@@ -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+
244268func 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 ,
0 commit comments