Skip to content

Commit c0cad6a

Browse files
committed
Merge pull request #451 from cyphar/fix-infinite-recursion
cgroups: fs: fix cgroup.Parent path sanitisation
2 parents d431081 + bf899fe commit c0cad6a

File tree

2 files changed

+32
-0
lines changed

2 files changed

+32
-0
lines changed

libcontainer/cgroups/fs/apply_raw.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,12 +241,39 @@ func getCgroupPath(c *configs.Cgroup) (string, error) {
241241
return d.path("devices")
242242
}
243243

244+
// pathClean makes a path safe for use with filepath.Join. This is done by not
245+
// only cleaning the path, but also (if the path is relative) adding a leading
246+
// '/' and cleaning it (then removing the leading '/'). This ensures that a
247+
// path resulting from prepending another path will always resolve to lexically
248+
// be a subdirectory of the prefixed path. This is all done lexically, so paths
249+
// that include symlinks won't be safe as a result of using pathClean.
250+
func pathClean(path string) string {
251+
// Ensure that all paths are cleaned (especially problematic ones like
252+
// "/../../../../../" which can cause lots of issues).
253+
path = filepath.Clean(path)
254+
255+
// If the path isn't absolute, we need to do more processing to fix paths
256+
// such as "../../../../<etc>/some/path". We also shouldn't convert absolute
257+
// paths to relative ones.
258+
if !filepath.IsAbs(path) {
259+
path = filepath.Clean(string(os.PathSeparator) + path)
260+
// This can't fail, as (by definition) all paths are relative to root.
261+
path, _ = filepath.Rel(string(os.PathSeparator), path)
262+
}
263+
264+
// Clean the path again for good measure.
265+
return filepath.Clean(path)
266+
}
267+
244268
func getCgroupData(c *configs.Cgroup, pid int) (*cgroupData, error) {
245269
root, err := getCgroupRoot()
246270
if err != nil {
247271
return nil, err
248272
}
249273

274+
// Clean the parent slice path.
275+
c.Parent = pathClean(c.Parent)
276+
250277
return &cgroupData{
251278
root: root,
252279
parent: c.Parent,

libcontainer/cgroups/fs/cpuset.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ package fs
44

55
import (
66
"bytes"
7+
"fmt"
78
"io/ioutil"
89
"os"
910
"path/filepath"
@@ -95,6 +96,10 @@ func (s *CpusetGroup) ensureParent(current, root string) error {
9596
if filepath.Clean(parent) == root {
9697
return nil
9798
}
99+
// Avoid infinite recursion.
100+
if parent == current {
101+
return fmt.Errorf("cpuset: cgroup parent path outside cgroup root")
102+
}
98103
if err := s.ensureParent(parent, root); err != nil {
99104
return err
100105
}

0 commit comments

Comments
 (0)