Skip to content

Commit 7ee017c

Browse files
authored
Merge pull request #4633 from kolyshkin/libct-cg-sep
libct/cg: eliminate remaining libct deps
2 parents 91e6621 + 4e0f7a2 commit 7ee017c

File tree

7 files changed

+158
-53
lines changed

7 files changed

+158
-53
lines changed

libcontainer/cgroups/devices/devicefilter_test.go

+82-5
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import (
55
"testing"
66

77
devices "github.com/opencontainers/runc/libcontainer/cgroups/devices/config"
8-
"github.com/opencontainers/runc/libcontainer/specconv"
98
)
109

1110
func hash(s, comm string) string {
@@ -53,6 +52,88 @@ block-0:
5352
}
5453

5554
func TestDeviceFilter_BuiltInAllowList(t *testing.T) {
55+
// This is a copy of all rules from
56+
// github.com/opencontainers/runc/libcontainer/specconv.AllowedDevices.
57+
devices := []*devices.Rule{
58+
{
59+
Type: devices.CharDevice,
60+
Major: devices.Wildcard,
61+
Minor: devices.Wildcard,
62+
Permissions: "m",
63+
Allow: true,
64+
},
65+
{
66+
Type: devices.BlockDevice,
67+
Major: devices.Wildcard,
68+
Minor: devices.Wildcard,
69+
Permissions: "m",
70+
Allow: true,
71+
},
72+
{
73+
Type: devices.CharDevice,
74+
Major: 1,
75+
Minor: 3,
76+
Permissions: "rwm",
77+
Allow: true,
78+
},
79+
{
80+
Type: devices.CharDevice,
81+
Major: 1,
82+
Minor: 8,
83+
Permissions: "rwm",
84+
Allow: true,
85+
},
86+
{
87+
Type: devices.CharDevice,
88+
Major: 1,
89+
Minor: 7,
90+
Permissions: "rwm",
91+
Allow: true,
92+
},
93+
{
94+
Type: devices.CharDevice,
95+
Major: 5,
96+
Minor: 0,
97+
Permissions: "rwm",
98+
Allow: true,
99+
},
100+
{
101+
Type: devices.CharDevice,
102+
Major: 1,
103+
Minor: 5,
104+
Permissions: "rwm",
105+
Allow: true,
106+
},
107+
{
108+
Type: devices.CharDevice,
109+
Major: 1,
110+
Minor: 9,
111+
Permissions: "rwm",
112+
Allow: true,
113+
},
114+
{
115+
Type: devices.CharDevice,
116+
Major: 136,
117+
Minor: devices.Wildcard,
118+
Permissions: "rwm",
119+
Allow: true,
120+
},
121+
{
122+
Type: devices.CharDevice,
123+
Major: 5,
124+
Minor: 2,
125+
Permissions: "rwm",
126+
Allow: true,
127+
},
128+
{
129+
Type: devices.CharDevice,
130+
Major: 10,
131+
Minor: 200,
132+
Permissions: "rwm",
133+
Allow: true,
134+
},
135+
}
136+
56137
expected := `
57138
// load parameters into registers
58139
0: LdXMemW dst: r2 src: r1 off: 0 imm: 0
@@ -136,10 +217,6 @@ block-11:
136217
62: MovImm32 dst: r0 imm: 0
137218
63: Exit
138219
`
139-
var devices []*devices.Rule
140-
for _, device := range specconv.AllowedDevices {
141-
devices = append(devices, &device.Rule)
142-
}
143220
testDeviceFilter(t, devices, expected)
144221
}
145222

libcontainer/cgroups/file.go

+7-7
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,11 @@ import (
55
"errors"
66
"fmt"
77
"os"
8-
"path"
8+
"path/filepath"
99
"strconv"
1010
"strings"
1111
"sync"
1212

13-
"github.com/opencontainers/runc/libcontainer/utils"
1413
"github.com/sirupsen/logrus"
1514
"golang.org/x/sys/unix"
1615
)
@@ -147,7 +146,10 @@ func openFile(dir, file string, flags int) (*os.File, error) {
147146
flags |= os.O_TRUNC | os.O_CREATE
148147
mode = 0o600
149148
}
150-
path := path.Join(dir, utils.CleanPath(file))
149+
// NOTE it is important to use filepath.Clean("/"+file) here
150+
// (see https://github.com/opencontainers/runc/issues/4103)!
151+
path := filepath.Join(dir, filepath.Clean("/"+file))
152+
151153
if prepareOpenat2() != nil {
152154
return openFallback(path, flags, mode)
153155
}
@@ -171,10 +173,8 @@ func openFile(dir, file string, flags int) (*os.File, error) {
171173
//
172174
// TODO: if such usage will ever be common, amend this
173175
// to reopen cgroupRootHandle and retry openat2.
174-
fdPath, closer := utils.ProcThreadSelf("fd/" + strconv.Itoa(int(cgroupRootHandle.Fd())))
175-
defer closer()
176-
fdDest, _ := os.Readlink(fdPath)
177-
if fdDest != cgroupfsDir {
176+
fdDest, fdErr := os.Readlink("/proc/thread-self/fd/" + strconv.Itoa(int(cgroupRootHandle.Fd())))
177+
if fdErr == nil && fdDest != cgroupfsDir {
178178
// Wrap the error so it is clear that cgroupRootHandle
179179
// is opened to an unexpected/wrong directory.
180180
err = fmt.Errorf("cgroupRootHandle %d unexpectedly opened to %s != %s: %w",

libcontainer/cgroups/fs/paths.go

+2-18
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import (
99
"golang.org/x/sys/unix"
1010

1111
"github.com/opencontainers/runc/libcontainer/cgroups"
12-
"github.com/opencontainers/runc/libcontainer/utils"
12+
"github.com/opencontainers/runc/libcontainer/cgroups/internal/path"
1313
)
1414

1515
// The absolute path to the root of the cgroup hierarchies.
@@ -26,7 +26,7 @@ func initPaths(cg *cgroups.Cgroup) (map[string]string, error) {
2626
return nil, err
2727
}
2828

29-
inner, err := innerPath(cg)
29+
inner, err := path.Inner(cg)
3030
if err != nil {
3131
return nil, err
3232
}
@@ -135,22 +135,6 @@ func rootPath() (string, error) {
135135
return cgroupRoot, nil
136136
}
137137

138-
func innerPath(c *cgroups.Cgroup) (string, error) {
139-
if (c.Name != "" || c.Parent != "") && c.Path != "" {
140-
return "", errors.New("cgroup: either Path or Name and Parent should be used")
141-
}
142-
143-
// XXX: Do not remove CleanPath. Path safety is important! -- cyphar
144-
innerPath := utils.CleanPath(c.Path)
145-
if innerPath == "" {
146-
cgParent := utils.CleanPath(c.Parent)
147-
cgName := utils.CleanPath(c.Name)
148-
innerPath = filepath.Join(cgParent, cgName)
149-
}
150-
151-
return innerPath, nil
152-
}
153-
154138
func subsysPath(root, inner, subsystem string) (string, error) {
155139
// If the cgroup name/path is absolute do not look relative to the cgroup of the init process.
156140
if filepath.IsAbs(inner) {

libcontainer/cgroups/fs/paths_test.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"testing"
77

88
"github.com/opencontainers/runc/libcontainer/cgroups"
9+
"github.com/opencontainers/runc/libcontainer/cgroups/internal/path"
910
)
1011

1112
func TestInvalidCgroupPath(t *testing.T) {
@@ -66,7 +67,7 @@ func TestInvalidCgroupPath(t *testing.T) {
6667
t.Run(tc.test, func(t *testing.T) {
6768
config := &cgroups.Cgroup{Path: tc.path, Name: tc.name, Parent: tc.parent}
6869

69-
inner, err := innerPath(config)
70+
inner, err := path.Inner(config)
7071
if err != nil {
7172
t.Fatalf("couldn't get cgroup data: %v", err)
7273
}

libcontainer/cgroups/fs2/defaultpath.go

+6-21
Original file line numberDiff line numberDiff line change
@@ -19,40 +19,25 @@ package fs2
1919
import (
2020
"bufio"
2121
"errors"
22-
"fmt"
2322
"io"
2423
"os"
2524
"path/filepath"
2625
"strings"
2726

2827
"github.com/opencontainers/runc/libcontainer/cgroups"
29-
"github.com/opencontainers/runc/libcontainer/utils"
28+
"github.com/opencontainers/runc/libcontainer/cgroups/internal/path"
3029
)
3130

3231
const UnifiedMountpoint = "/sys/fs/cgroup"
3332

3433
func defaultDirPath(c *cgroups.Cgroup) (string, error) {
35-
if (c.Name != "" || c.Parent != "") && c.Path != "" {
36-
return "", fmt.Errorf("cgroup: either Path or Name and Parent should be used, got %+v", c)
37-
}
38-
39-
return _defaultDirPath(UnifiedMountpoint, c.Path, c.Parent, c.Name)
40-
}
41-
42-
func _defaultDirPath(root, cgPath, cgParent, cgName string) (string, error) {
43-
if (cgName != "" || cgParent != "") && cgPath != "" {
44-
return "", errors.New("cgroup: either Path or Name and Parent should be used")
34+
innerPath, err := path.Inner(c)
35+
if err != nil {
36+
return "", err
4537
}
4638

47-
// XXX: Do not remove CleanPath. Path safety is important! -- cyphar
48-
innerPath := utils.CleanPath(cgPath)
49-
if innerPath == "" {
50-
cgParent := utils.CleanPath(cgParent)
51-
cgName := utils.CleanPath(cgName)
52-
innerPath = filepath.Join(cgParent, cgName)
53-
}
5439
if filepath.IsAbs(innerPath) {
55-
return filepath.Join(root, innerPath), nil
40+
return filepath.Join(UnifiedMountpoint, innerPath), nil
5641
}
5742

5843
// we don't need to use /proc/thread-self here because runc always runs
@@ -67,7 +52,7 @@ func _defaultDirPath(root, cgPath, cgParent, cgName string) (string, error) {
6752
// A parent cgroup (with no tasks in it) is what we need.
6853
ownCgroup = filepath.Dir(ownCgroup)
6954

70-
return filepath.Join(root, ownCgroup, innerPath), nil
55+
return filepath.Join(UnifiedMountpoint, ownCgroup, innerPath), nil
7156
}
7257

7358
// parseCgroupFile parses /proc/PID/cgroup file and return string

libcontainer/cgroups/fs2/defaultpath_test.go

+7-1
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,13 @@ func TestDefaultDirPath(t *testing.T) {
7676
},
7777
}
7878
for _, c := range cases {
79-
got, err := _defaultDirPath(UnifiedMountpoint, c.cgPath, c.cgParent, c.cgName)
79+
cg := &cgroups.Cgroup{
80+
Path: c.cgPath,
81+
Parent: c.cgParent,
82+
Name: c.cgName,
83+
}
84+
85+
got, err := defaultDirPath(cg)
8086
if err != nil {
8187
t.Fatal(err)
8288
}
+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package path
2+
3+
import (
4+
"errors"
5+
"os"
6+
"path/filepath"
7+
8+
"github.com/opencontainers/runc/libcontainer/cgroups"
9+
)
10+
11+
// Inner returns a path to cgroup relative to a cgroup mount point, based
12+
// on cgroup configuration, or an error, if cgroup configuration is invalid.
13+
// To be used only by fs cgroup managers (systemd has different path rules).
14+
func Inner(c *cgroups.Cgroup) (string, error) {
15+
if (c.Name != "" || c.Parent != "") && c.Path != "" {
16+
return "", errors.New("cgroup: either Path or Name and Parent should be used")
17+
}
18+
19+
// XXX: Do not remove cleanPath. Path safety is important! -- cyphar
20+
innerPath := cleanPath(c.Path)
21+
if innerPath == "" {
22+
cgParent := cleanPath(c.Parent)
23+
cgName := cleanPath(c.Name)
24+
innerPath = filepath.Join(cgParent, cgName)
25+
}
26+
27+
return innerPath, nil
28+
}
29+
30+
// cleanPath is a copy of github.com/opencontainers/runc/libcontainer/utils.CleanPath.
31+
func cleanPath(path string) string {
32+
// Deal with empty strings nicely.
33+
if path == "" {
34+
return ""
35+
}
36+
37+
// Ensure that all paths are cleaned (especially problematic ones like
38+
// "/../../../../../" which can cause lots of issues).
39+
40+
if filepath.IsAbs(path) {
41+
return filepath.Clean(path)
42+
}
43+
44+
// If the path isn't absolute, we need to do more processing to fix paths
45+
// such as "../../../../<etc>/some/path". We also shouldn't convert absolute
46+
// paths to relative ones.
47+
path = filepath.Clean(string(os.PathSeparator) + path)
48+
// This can't fail, as (by definition) all paths are relative to root.
49+
path, _ = filepath.Rel(string(os.PathSeparator), path)
50+
51+
return path
52+
}

0 commit comments

Comments
 (0)