bpf, cgroup: Reject prog_attach_flags array when effective query
authorPu Lehui <pulehui@huawei.com>
Wed, 21 Sep 2022 10:46:02 +0000 (10:46 +0000)
committerMartin KaFai Lau <martin.lau@kernel.org>
Wed, 21 Sep 2022 17:57:12 +0000 (10:57 -0700)
Attach flags is only valid for attached progs of this layer cgroup,
but not for effective progs. For querying with EFFECTIVE flags,
exporting attach flags does not make sense. So when effective query,
we reject prog_attach_flags array and don't need to populate it.
Also we limit attach_flags to output 0 during effective query.

Fixes: b79c9fc9551b ("bpf: implement BPF_PROG_QUERY for BPF_LSM_CGROUP")
Signed-off-by: Pu Lehui <pulehui@huawei.com>
Link: https://lore.kernel.org/r/20220921104604.2340580-2-pulehui@huaweicloud.com
Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
include/uapi/linux/bpf.h
kernel/bpf/cgroup.c
tools/include/uapi/linux/bpf.h

index 59a217ca2dfd3e6f3ad53a3c0eb448af6664afda..4eff7fc7ae586b3dcad1f7b3f109dc1f04fc1b97 100644 (file)
@@ -1233,7 +1233,7 @@ enum {
 
 /* Query effective (directly attached + inherited from ancestor cgroups)
  * programs that will be executed for events within a cgroup.
- * attach_flags with this flag are returned only for directly attached programs.
+ * attach_flags with this flag are always returned 0.
  */
 #define BPF_F_QUERY_EFFECTIVE  (1U << 0)
 
@@ -1432,7 +1432,10 @@ union bpf_attr {
                __u32           attach_flags;
                __aligned_u64   prog_ids;
                __u32           prog_cnt;
-               __aligned_u64   prog_attach_flags; /* output: per-program attach_flags */
+               /* output: per-program attach_flags.
+                * not allowed to be set during effective query.
+                */
+               __aligned_u64   prog_attach_flags;
        } query;
 
        struct { /* anonymous struct used by BPF_RAW_TRACEPOINT_OPEN command */
index 4a400cd6373167d99ba2ce9c27101b9e95282c7f..22888aaa68b666a053ef77918c5627402f7d9f18 100644 (file)
@@ -1020,6 +1020,7 @@ static int __cgroup_bpf_query(struct cgroup *cgrp, const union bpf_attr *attr,
                              union bpf_attr __user *uattr)
 {
        __u32 __user *prog_attach_flags = u64_to_user_ptr(attr->query.prog_attach_flags);
+       bool effective_query = attr->query.query_flags & BPF_F_QUERY_EFFECTIVE;
        __u32 __user *prog_ids = u64_to_user_ptr(attr->query.prog_ids);
        enum bpf_attach_type type = attr->query.attach_type;
        enum cgroup_bpf_attach_type from_atype, to_atype;
@@ -1029,8 +1030,12 @@ static int __cgroup_bpf_query(struct cgroup *cgrp, const union bpf_attr *attr,
        int total_cnt = 0;
        u32 flags;
 
+       if (effective_query && prog_attach_flags)
+               return -EINVAL;
+
        if (type == BPF_LSM_CGROUP) {
-               if (attr->query.prog_cnt && prog_ids && !prog_attach_flags)
+               if (!effective_query && attr->query.prog_cnt &&
+                   prog_ids && !prog_attach_flags)
                        return -EINVAL;
 
                from_atype = CGROUP_LSM_START;
@@ -1045,7 +1050,7 @@ static int __cgroup_bpf_query(struct cgroup *cgrp, const union bpf_attr *attr,
        }
 
        for (atype = from_atype; atype <= to_atype; atype++) {
-               if (attr->query.query_flags & BPF_F_QUERY_EFFECTIVE) {
+               if (effective_query) {
                        effective = rcu_dereference_protected(cgrp->bpf.effective[atype],
                                                              lockdep_is_held(&cgroup_mutex));
                        total_cnt += bpf_prog_array_length(effective);
@@ -1054,6 +1059,8 @@ static int __cgroup_bpf_query(struct cgroup *cgrp, const union bpf_attr *attr,
                }
        }
 
+       /* always output uattr->query.attach_flags as 0 during effective query */
+       flags = effective_query ? 0 : flags;
        if (copy_to_user(&uattr->query.attach_flags, &flags, sizeof(flags)))
                return -EFAULT;
        if (copy_to_user(&uattr->query.prog_cnt, &total_cnt, sizeof(total_cnt)))
@@ -1068,7 +1075,7 @@ static int __cgroup_bpf_query(struct cgroup *cgrp, const union bpf_attr *attr,
        }
 
        for (atype = from_atype; atype <= to_atype && total_cnt; atype++) {
-               if (attr->query.query_flags & BPF_F_QUERY_EFFECTIVE) {
+               if (effective_query) {
                        effective = rcu_dereference_protected(cgrp->bpf.effective[atype],
                                                              lockdep_is_held(&cgroup_mutex));
                        cnt = min_t(int, bpf_prog_array_length(effective), total_cnt);
@@ -1090,15 +1097,16 @@ static int __cgroup_bpf_query(struct cgroup *cgrp, const union bpf_attr *attr,
                                if (++i == cnt)
                                        break;
                        }
-               }
 
-               if (prog_attach_flags) {
-                       flags = cgrp->bpf.flags[atype];
+                       if (prog_attach_flags) {
+                               flags = cgrp->bpf.flags[atype];
 
-                       for (i = 0; i < cnt; i++)
-                               if (copy_to_user(prog_attach_flags + i, &flags, sizeof(flags)))
-                                       return -EFAULT;
-                       prog_attach_flags += cnt;
+                               for (i = 0; i < cnt; i++)
+                                       if (copy_to_user(prog_attach_flags + i,
+                                                        &flags, sizeof(flags)))
+                                               return -EFAULT;
+                               prog_attach_flags += cnt;
+                       }
                }
 
                prog_ids += cnt;
index 59a217ca2dfd3e6f3ad53a3c0eb448af6664afda..4eff7fc7ae586b3dcad1f7b3f109dc1f04fc1b97 100644 (file)
@@ -1233,7 +1233,7 @@ enum {
 
 /* Query effective (directly attached + inherited from ancestor cgroups)
  * programs that will be executed for events within a cgroup.
- * attach_flags with this flag are returned only for directly attached programs.
+ * attach_flags with this flag are always returned 0.
  */
 #define BPF_F_QUERY_EFFECTIVE  (1U << 0)
 
@@ -1432,7 +1432,10 @@ union bpf_attr {
                __u32           attach_flags;
                __aligned_u64   prog_ids;
                __u32           prog_cnt;
-               __aligned_u64   prog_attach_flags; /* output: per-program attach_flags */
+               /* output: per-program attach_flags.
+                * not allowed to be set during effective query.
+                */
+               __aligned_u64   prog_attach_flags;
        } query;
 
        struct { /* anonymous struct used by BPF_RAW_TRACEPOINT_OPEN command */