diff --git a/sandbox/cgroup/scanning.go b/sandbox/cgroup/scanning.go index 75a2867797..0c6597eb7b 100644 --- a/sandbox/cgroup/scanning.go +++ b/sandbox/cgroup/scanning.go @@ -88,6 +88,24 @@ func PidsOfSnap(snapInstanceName string) (map[string][]int, error) { // pidsByTag maps security tag to a list of pids. pidsByTag := make(map[string][]int) + ver, err := Version() + if err != nil { + return nil, err + } + + var cgroupPathToScan string + if ver == V2 { + // In v2 mode scan all of /sys/fs/cgroup as there is no specialization + // anymore (each directory represents a hierarchy with equal + // capabilities and old split into controllers is gone). + cgroupPathToScan = filepath.Join(rootPath, cgroupMountPoint) + } else { + // In v1 mode scan just /sys/fs/cgroup/systemd as that is sufficient + // for finding snap-specific cgroup names. Systemd uses this for + // tracking and scopes and services are represented there. + cgroupPathToScan = filepath.Join(rootPath, cgroupMountPoint, "systemd") + } + // Walk the cgroup tree and look for "cgroup.procs" files. Having found one // we try to derive the snap security tag from it. If successful and the // tag matches the snap we are interested in, we harvest the snapshot of @@ -100,6 +118,14 @@ func PidsOfSnap(snapInstanceName string) (map[string][]int, error) { // that error quickly. return err } + + // ignore snaps inside containers + for _, slice := range []string{"lxc.payload", "machine.slice", "docker"} { + if strings.HasPrefix(path, filepath.Join(cgroupPathToScan, slice)) { + return filepath.SkipDir + } + } + if fileInfo.IsDir() { // We don't care about directories. return nil @@ -133,22 +159,6 @@ func PidsOfSnap(snapInstanceName string) (map[string][]int, error) { return filepath.SkipDir } - var cgroupPathToScan string - ver, err := Version() - if err != nil { - return nil, err - } - if ver == V2 { - // In v2 mode scan all of /sys/fs/cgroup as there is no specialization - // anymore (each directory represents a hierarchy with equal - // capabilities and old split into controllers is gone). - cgroupPathToScan = filepath.Join(rootPath, cgroupMountPoint) - } else { - // In v1 mode scan just /sys/fs/cgroup/systemd as that is sufficient - // for finding snap-specific cgroup names. Systemd uses this for - // tracking and scopes and services are represented there. - cgroupPathToScan = filepath.Join(rootPath, cgroupMountPoint, "systemd") - } // NOTE: Walk is internally performed in lexical order so the output is // deterministic and we don't need to sort the returned aggregated PIDs. if err := filepath.Walk(cgroupPathToScan, walkFunc); err != nil { diff --git a/sandbox/cgroup/scanning_test.go b/sandbox/cgroup/scanning_test.go index ebd3d4ccff..4fe1c3f2a9 100644 --- a/sandbox/cgroup/scanning_test.go +++ b/sandbox/cgroup/scanning_test.go @@ -224,3 +224,22 @@ func (s *scanningSuite) TestPidsOfSnapUnrelated(c *C) { }, comment) } } + +func (s *scanningSuite) TestContainerPidsAreIgnored(c *C) { + for _, ver := range []int{cgroup.V2, cgroup.V1} { + comment := Commentf("cgroup version %v", ver) + restore := cgroup.MockVersion(ver, nil) + defer restore() + + s.writePids(c, "user.slice/user-1000.slice/user@1000.service/snap.foo.bar.scope", []int{1}) + s.writePids(c, "system.slice/snap.foo.bar.service", []int{2}) + s.writePids(c, "lxc.payload.my-container/system.slice/snap.foo.bar.service", []int{3}) + s.writePids(c, "machine.slice/snap.foo.bar.service", []int{4}) + s.writePids(c, "docker/snap.foo.bar.service", []int{5}) + + pids, err := cgroup.PidsOfSnap("foo") + c.Assert(err, IsNil, comment) + c.Check(pids, HasLen, 1, comment) + c.Check(pids["snap.foo.bar"], testutil.DeepUnsortedMatches, []int{1, 2}, comment) + } +}