
hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/ica1gk -------------------------------- As multiple numbers and levels of sub namespaces could be created in a namespace, the kernel doesn't know exactly which one corresponds to the container. So we heuristically take the level-1 pid namespaces as the component of containers, and create a kfunc and a helper to retrieve the child reaper (i.e. pid 1 task of the pid namespace, almost equal to the init process of the container) of the level-1 ancestor pid namespace of the current task. The exception is for tasks in the root pid namespace (level 0), where the root pid namespace will be returned. Signed-off-by: GONG Ruiqi <gongruiqi1@huawei.com> --- include/linux/pid_namespace.h | 4 ++++ kernel/bpf/helpers.c | 29 +++++++++++++++++++++++++++++ kernel/pid.c | 25 +++++++++++++++++++++++++ 3 files changed, 58 insertions(+) diff --git a/include/linux/pid_namespace.h b/include/linux/pid_namespace.h index 7ab8c213f13b..28161eefca5d 100644 --- a/include/linux/pid_namespace.h +++ b/include/linux/pid_namespace.h @@ -130,4 +130,8 @@ static inline bool task_is_in_init_pid_ns(struct task_struct *tsk) return task_active_pid_ns(tsk) == &init_pid_ns; } +#ifdef CONFIG_BPF_RVI +extern struct task_struct *get_current_level1_reaper(void); +#endif + #endif /* _LINUX_PID_NS_H */ diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c index f5226ddf87b6..140097c8198e 100644 --- a/kernel/bpf/helpers.c +++ b/kernel/bpf/helpers.c @@ -2362,6 +2362,32 @@ __bpf_kfunc struct task_struct *bpf_task_from_pid(s32 pid) return p; } +#ifdef CONFIG_BPF_RVI +/** + * bpf_current_level1_reaper - Find the reaper task in the level-1 parent of + * current pid namespace. If a task is returned, it must either be stored in + * a map, or released with bpf_task_release(). + */ +__bpf_kfunc struct task_struct *bpf_current_level1_reaper(void) +{ + struct task_struct *p; + struct pid_namespace *ns; + + ns = task_active_pid_ns(current); + while (ns->level > 1) { // not !=, as ns could be init_pid_ns + ns = ns->parent; + } + + read_lock(&tasklist_lock); + p = ns->child_reaper; + if (p) + p = bpf_task_acquire(p); + read_unlock(&tasklist_lock); + + return p; +} +#endif + /** * bpf_dynptr_slice() - Obtain a read-only pointer to the dynptr data. * @ptr: The dynptr whose data slice to retrieve @@ -2604,6 +2630,9 @@ BTF_ID_FLAGS(func, bpf_cgroup_from_id, KF_ACQUIRE | KF_RET_NULL) BTF_ID_FLAGS(func, bpf_task_under_cgroup, KF_RCU) #endif BTF_ID_FLAGS(func, bpf_task_from_pid, KF_ACQUIRE | KF_RET_NULL) +#ifdef CONFIG_BPF_RVI +BTF_ID_FLAGS(func, bpf_current_level1_reaper, KF_ACQUIRE | KF_RET_NULL) +#endif BTF_SET8_END(generic_btf_ids) static const struct btf_kfunc_id_set generic_kfunc_set = { diff --git a/kernel/pid.c b/kernel/pid.c index db99713600fc..8000cf327985 100644 --- a/kernel/pid.c +++ b/kernel/pid.c @@ -797,3 +797,28 @@ SYSCALL_DEFINE3(pidfd_getfd, int, pidfd, int, fd, fdput(f); return ret; } + +#ifdef CONFIG_BPF_RVI +/* + * We assume that containers should start at root ns, which means that + * containers themselves are level-1 ns. + */ +struct task_struct *get_current_level1_reaper(void) +{ + struct task_struct *reaper; + struct pid_namespace *ns; + + ns = task_active_pid_ns(current); + while (ns->level > 1) { // not !=, as ns could be init_pid_ns + ns = ns->parent; + } + + read_lock(&tasklist_lock); + reaper = ns->child_reaper; + if (reaper) + get_task_struct(reaper); + read_unlock(&tasklist_lock); + + return reaper; +} +#endif /* CONFIG_BPF_RVI */ -- 2.25.1