From 53f40118e2a86c14d1018fa7f2721a036bfe19ee Mon Sep 17 00:00:00 2001 From: Nadav Strahilevitz Date: Thu, 8 Dec 2022 11:08:17 +0000 Subject: [PATCH] derive: fix cgroupv1 hid false derives In cgroupv1 systems, cgroup_mkdir events come from many different hierarchies, some existing outside of cpuset, where we query for the container cgroups. Because these cgroup_mkdir events would go through a derive process anyway, for each controller in the system there would be a failed derive searching through the entire cpuset controller with no results. This fix adds a check in v1 systems to see if the hierarchy id is the default one, otherwise derivation is skipped. --- pkg/cgroup/cgroup.go | 9 +++++++++ pkg/containers/containers.go | 4 ++++ pkg/events/derive/container_create.go | 19 +++++++++++++++++++ pkg/events/derive/container_remove.go | 4 ++++ 4 files changed, 36 insertions(+) diff --git a/pkg/cgroup/cgroup.go b/pkg/cgroup/cgroup.go index 7260fb581085..b8e56740d74d 100644 --- a/pkg/cgroup/cgroup.go +++ b/pkg/cgroup/cgroup.go @@ -164,6 +164,7 @@ type Cgroup interface { destroy() error GetMountPoint() string getDefaultHierarchyID() int + GetVersion() CgroupVersion } func NewCgroup(ver CgroupVersion) (Cgroup, error) { @@ -227,6 +228,10 @@ func (c *CgroupV1) getDefaultHierarchyID() int { return c.hid } +func (c *CgroupV1) GetVersion() CgroupVersion { + return CgroupVersion1 +} + // cgroupv2 type CgroupV2 struct { @@ -274,6 +279,10 @@ func (c *CgroupV2) getDefaultHierarchyID() int { return c.hid } +func (c *CgroupV2) GetVersion() CgroupVersion { + return CgroupVersion2 +} + // // General // diff --git a/pkg/containers/containers.go b/pkg/containers/containers.go index f557139a51b5..cbf9d84c20e7 100644 --- a/pkg/containers/containers.go +++ b/pkg/containers/containers.go @@ -86,6 +86,10 @@ func (c *Containers) GetDefaultCgroupHierarchyID() int { return c.cgroups.GetDefaultCgroupHierarchyID() } +func (c *Containers) GetCgroupVersion() cgroup.CgroupVersion { + return c.cgroups.GetDefaultCgroup().GetVersion() +} + // Populate populates Containers struct by reading mounted proc and cgroups fs. func (c *Containers) Populate() error { return c.populate() diff --git a/pkg/events/derive/container_create.go b/pkg/events/derive/container_create.go index 7b01aa387a1b..5dddede087d6 100644 --- a/pkg/events/derive/container_create.go +++ b/pkg/events/derive/container_create.go @@ -1,6 +1,7 @@ package derive import ( + "github.com/aquasecurity/tracee/pkg/cgroup" "github.com/aquasecurity/tracee/pkg/containers" "github.com/aquasecurity/tracee/pkg/events" "github.com/aquasecurity/tracee/pkg/events/parse" @@ -15,6 +16,10 @@ func ContainerCreate(containers *containers.Containers) deriveFunction { func deriveContainerCreateArgs(containers *containers.Containers) func(event trace.Event) ([]interface{}, error) { return func(event trace.Event) ([]interface{}, error) { + // if cgroup_id is from non default hid (v1 case), the cgroup info query will fail, so we skip + if check, err := isCgroupEventInHid(&event, containers); !check { + return nil, err + } cgroupId, err := parse.ArgUint64Val(&event, "cgroup_id") if err != nil { return nil, err @@ -35,3 +40,17 @@ func deriveContainerCreateArgs(containers *containers.Containers) func(event tra return nil, nil } } + +// isCgroupEventInHid checks if cgroup event is relevant for deriving container event in it's hierarchy id. +// in tracee we only care about containers inside the cpuset controller, as such other hierarchy ids will lead +// to a failed query. +func isCgroupEventInHid(event *trace.Event, containers *containers.Containers) (bool, error) { + if containers.GetCgroupVersion() == cgroup.CgroupVersion2 { + return true, nil + } + hierarchyID, err := parse.ArgUint32Val(event, "hierarchy_id") + if err != nil { + return false, err + } + return containers.GetDefaultCgroupHierarchyID() == int(hierarchyID), nil +} diff --git a/pkg/events/derive/container_remove.go b/pkg/events/derive/container_remove.go index 3bc1425ce180..c9610fabfede 100644 --- a/pkg/events/derive/container_remove.go +++ b/pkg/events/derive/container_remove.go @@ -15,6 +15,10 @@ func ContainerRemove(containers *containers.Containers) deriveFunction { func deriveContainerRemoveArgs(containers *containers.Containers) deriveArgsFunction { return func(event trace.Event) ([]interface{}, error) { + // if cgroup_id is from non default hid (v1 case), the cgroup info query will fail, so we skip + if check, err := isCgroupEventInHid(&event, containers); !check { + return nil, err + } cgroupId, err := parse.ArgUint64Val(&event, "cgroup_id") if err != nil { return nil, err