Merge pull request #451 from cyphar/fix-infinite-recursion

cgroups: fs: fix cgroup.Parent path sanitisation
This commit is contained in:
Alexander Morozov 2016-01-11 08:52:26 -08:00
commit c0cad6aa5e
2 changed files with 32 additions and 0 deletions

View File

@ -241,12 +241,39 @@ func getCgroupPath(c *configs.Cgroup) (string, error) {
return d.path("devices")
}
// pathClean makes a path safe for use with filepath.Join. This is done by not
// only cleaning the path, but also (if the path is relative) adding a leading
// '/' and cleaning it (then removing the leading '/'). This ensures that a
// path resulting from prepending another path will always resolve to lexically
// be a subdirectory of the prefixed path. This is all done lexically, so paths
// that include symlinks won't be safe as a result of using pathClean.
func pathClean(path string) string {
// Ensure that all paths are cleaned (especially problematic ones like
// "/../../../../../" which can cause lots of issues).
path = filepath.Clean(path)
// If the path isn't absolute, we need to do more processing to fix paths
// such as "../../../../<etc>/some/path". We also shouldn't convert absolute
// paths to relative ones.
if !filepath.IsAbs(path) {
path = filepath.Clean(string(os.PathSeparator) + path)
// This can't fail, as (by definition) all paths are relative to root.
path, _ = filepath.Rel(string(os.PathSeparator), path)
}
// Clean the path again for good measure.
return filepath.Clean(path)
}
func getCgroupData(c *configs.Cgroup, pid int) (*cgroupData, error) {
root, err := getCgroupRoot()
if err != nil {
return nil, err
}
// Clean the parent slice path.
c.Parent = pathClean(c.Parent)
return &cgroupData{
root: root,
parent: c.Parent,

View File

@ -4,6 +4,7 @@ package fs
import (
"bytes"
"fmt"
"io/ioutil"
"os"
"path/filepath"
@ -95,6 +96,10 @@ func (s *CpusetGroup) ensureParent(current, root string) error {
if filepath.Clean(parent) == root {
return nil
}
// Avoid infinite recursion.
if parent == current {
return fmt.Errorf("cpuset: cgroup parent path outside cgroup root")
}
if err := s.ensureParent(parent, root); err != nil {
return err
}