bpf: Handle bpf_mprog_query with NULL entry
authorDaniel Borkmann <daniel@iogearbox.net>
Fri, 6 Oct 2023 22:06:50 +0000 (00:06 +0200)
committerMartin KaFai Lau <martin.lau@kernel.org>
Sat, 7 Oct 2023 00:11:20 +0000 (17:11 -0700)
Improve consistency for bpf_mprog_query() API and let the latter also handle
a NULL entry as can be the case for tcx. Instead of returning -ENOENT, we
copy a count of 0 and revision of 1 to user space, so that this can be fed
into a subsequent bpf_mprog_attach() call as expected_revision. A BPF self-
test as part of this series has been added to assert this case.

Suggested-by: Lorenz Bauer <lmb@isovalent.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Link: https://lore.kernel.org/r/20231006220655.1653-2-daniel@iogearbox.net
Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
kernel/bpf/mprog.c
kernel/bpf/tcx.c

index 007d98c..1394168 100644 (file)
@@ -401,14 +401,16 @@ int bpf_mprog_query(const union bpf_attr *attr, union bpf_attr __user *uattr,
        struct bpf_mprog_cp *cp;
        struct bpf_prog *prog;
        const u32 flags = 0;
+       u32 id, count = 0;
+       u64 revision = 1;
        int i, ret = 0;
-       u32 id, count;
-       u64 revision;
 
        if (attr->query.query_flags || attr->query.attach_flags)
                return -EINVAL;
-       revision = bpf_mprog_revision(entry);
-       count = bpf_mprog_total(entry);
+       if (entry) {
+               revision = bpf_mprog_revision(entry);
+               count = bpf_mprog_total(entry);
+       }
        if (copy_to_user(&uattr->query.attach_flags, &flags, sizeof(flags)))
                return -EFAULT;
        if (copy_to_user(&uattr->query.revision, &revision, sizeof(revision)))
index 13f0b5d..1338a13 100644 (file)
@@ -123,7 +123,6 @@ int tcx_prog_query(const union bpf_attr *attr, union bpf_attr __user *uattr)
 {
        bool ingress = attr->query.attach_type == BPF_TCX_INGRESS;
        struct net *net = current->nsproxy->net_ns;
-       struct bpf_mprog_entry *entry;
        struct net_device *dev;
        int ret;
 
@@ -133,12 +132,7 @@ int tcx_prog_query(const union bpf_attr *attr, union bpf_attr __user *uattr)
                ret = -ENODEV;
                goto out;
        }
-       entry = tcx_entry_fetch(dev, ingress);
-       if (!entry) {
-               ret = -ENOENT;
-               goto out;
-       }
-       ret = bpf_mprog_query(attr, uattr, entry);
+       ret = bpf_mprog_query(attr, uattr, tcx_entry_fetch(dev, ingress));
 out:
        rtnl_unlock();
        return ret;