From 4f69f1c3a569e8ed650dd9746f8128b47109adaf Mon Sep 17 00:00:00 2001 From: Djalal Harouni Date: Wed, 14 Dec 2022 16:43:39 +0100 Subject: [PATCH] bpf:cgroups: set ->flags error when reading cgroup info fails Set appropriate EVENT_ERROR_CGROUP_* flags when reading cgroup info from BPF side fails. It allows to easily identify from user space the offending bpf code. Signed-off-by: Djalal Harouni (cherry picked from commit 82b216ce9f83cc00ff4f29eade51bdbfdda08d42) --- bpf/lib/bpf_cgroup.h | 38 ++++++++++++++++++--------------- bpf/process/bpf_process_event.h | 9 +++----- 2 files changed, 24 insertions(+), 23 deletions(-) diff --git a/bpf/lib/bpf_cgroup.h b/bpf/lib/bpf_cgroup.h index b0ee4edcc1e..0db508622f6 100644 --- a/bpf/lib/bpf_cgroup.h +++ b/bpf/lib/bpf_cgroup.h @@ -238,9 +238,12 @@ get_cgroup_id(const struct cgroup *cgrp) * @task: must be current task. * @subsys_idx: index of the desired cgroup_subsys_state part of css_set. * Passing a zero as a subsys_idx is fine assuming you want that. + * @error_flags: error flags that will be ORed to indicate errors on + * failures. * * Returns the cgroup of the css part of css_set of current task and is - * indexed at subsys_idx on success, NULL on failures. + * indexed at subsys_idx on success. NULL on failures, and the error_flags + * will be ORed to indicate the corresponding error. * * To get cgroup and kernfs node information we want to operate on the right * cgroup hierarchy which is setup by user space. However due to the @@ -254,15 +257,17 @@ get_cgroup_id(const struct cgroup *cgrp) * counting first comment line. */ static inline __attribute__((always_inline)) struct cgroup * -get_task_cgroup(struct task_struct *task, __u32 subsys_idx) +get_task_cgroup(struct task_struct *task, __u32 subsys_idx, __u32 *error_flags) { struct cgroup_subsys_state *subsys; struct css_set *cgroups; struct cgroup *cgrp = NULL; probe_read(&cgroups, sizeof(cgroups), _(&task->cgroups)); - if (unlikely(!cgroups)) + if (unlikely(!cgroups)) { + *error_flags |= EVENT_ERROR_CGROUPS; return cgrp; + } /* We are interested only in the cpuset, memory or pids controllers * which are indexed at 0, 4 and 11 respectively assuming all controllers @@ -280,8 +285,10 @@ get_task_cgroup(struct task_struct *task, __u32 subsys_idx) * especially if they happen to be before the desired subsys_idx, * we fail. */ - if (unlikely(subsys_idx > pids_cgrp_id)) + if (unlikely(subsys_idx > pids_cgrp_id)) { + *error_flags |= EVENT_ERROR_CGROUP_SUBSYS; return cgrp; + } /* Read css from the passed subsys index to ensure that we operate * on the desired controller. This allows user space to be flexible @@ -290,34 +297,34 @@ get_task_cgroup(struct task_struct *task, __u32 subsys_idx) * in a significant way. */ probe_read(&subsys, sizeof(subsys), _(&cgroups->subsys[subsys_idx])); - if (unlikely(!subsys)) + if (unlikely(!subsys)) { + *error_flags |= EVENT_ERROR_CGROUP_SUBSYS; return cgrp; + } probe_read(&cgrp, sizeof(cgrp), _(&subsys->cgroup)); + if (!cgrp) + *error_flags |= EVENT_ERROR_CGROUP_SUBSYSCGRP; + return cgrp; } /** * tg_get_current_cgroup_id() Returns the accurate cgroup id of current task. - * @task: current task. + * @cgrp: cgroup target of current task. * @cgrpfs_ver: Cgroupfs Magic number either Cgroupv1 or Cgroupv2 - * @subsys_idx: index of the desired cgroup_subsys_state part of css_set. - * Passing zero as a subsys_idx is fine assuming that is what you want. * * It handles both cgroupv2 and cgroupv1. * If @cgrpfs_ver is default cgroupv2 hierarchy, then it uses the bpf * helper bpf_get_current_cgroup_id() to retrieve the cgroup id. Otherwise - * it falls back on the cgroup id of the desired css that is indexed by - * @subsys_idx. + * it falls back on using the passed @cgrp * * Returns the cgroup id of current task on success, zero on failures. */ static inline __attribute__((always_inline)) __u64 -tg_get_current_cgroup_id(struct task_struct *task, __u64 cgrpfs_ver, - __u32 subsys_idx) +tg_get_current_cgroup_id(struct cgroup *cgrp, __u64 cgrpfs_ver) { __u64 id = 0; - struct cgroup *cgrp; /* * Try the bpf helper on the default hierarchy if available @@ -328,10 +335,7 @@ tg_get_current_cgroup_id(struct task_struct *task, __u64 cgrpfs_ver, cgrpfs_ver == CGROUP2_SUPER_MAGIC) { id = get_current_cgroup_id(); } else { - /* Fallback to read cgroup ID from cgroup of the desired css */ - cgrp = get_task_cgroup(task, subsys_idx); - if (cgrp) - id = get_cgroup_id(cgrp); + id = get_cgroup_id(cgrp); } return id; diff --git a/bpf/process/bpf_process_event.h b/bpf/process/bpf_process_event.h index 76e58daa68c..ec81b4b37cf 100644 --- a/bpf/process/bpf_process_event.h +++ b/bpf/process/bpf_process_event.h @@ -532,15 +532,12 @@ __event_get_cgroup_info(struct msg_execve_event *msg, cgrpfs_magic = conf->cgrp_fs_magic; } - cgrp = get_task_cgroup(task, subsys_idx); - if (!cgrp) { - process->flags |= EVENT_ERROR_CGROUP_SUBSYSCGRP; + cgrp = get_task_cgroup(task, subsys_idx, &process->flags); + if (!cgrp) return; - } /* Collect event cgroup ID */ - msg->kube.cgrpid = - tg_get_current_cgroup_id(task, cgrpfs_magic, subsys_idx); + msg->kube.cgrpid = tg_get_current_cgroup_id(cgrp, cgrpfs_magic); if (!msg->kube.cgrpid) { process->flags |= EVENT_ERROR_CGROUP_ID; /* Continue and gather remaining info */