Commit edfa9af0 authored by Daniel Borkmann's avatar Daniel Borkmann Committed by Martin KaFai Lau

bpf: Handle bpf_mprog_query with NULL entry

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: default avatarLorenz Bauer <lmb@isovalent.com>
Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
Link: https://lore.kernel.org/r/20231006220655.1653-2-daniel@iogearbox.netSigned-off-by: default avatarMartin KaFai Lau <martin.lau@kernel.org>
parent a4fe7838
...@@ -401,14 +401,16 @@ int bpf_mprog_query(const union bpf_attr *attr, union bpf_attr __user *uattr, ...@@ -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_mprog_cp *cp;
struct bpf_prog *prog; struct bpf_prog *prog;
const u32 flags = 0; const u32 flags = 0;
u32 id, count = 0;
u64 revision = 1;
int i, ret = 0; int i, ret = 0;
u32 id, count;
u64 revision;
if (attr->query.query_flags || attr->query.attach_flags) if (attr->query.query_flags || attr->query.attach_flags)
return -EINVAL; return -EINVAL;
revision = bpf_mprog_revision(entry); if (entry) {
count = bpf_mprog_total(entry); revision = bpf_mprog_revision(entry);
count = bpf_mprog_total(entry);
}
if (copy_to_user(&uattr->query.attach_flags, &flags, sizeof(flags))) if (copy_to_user(&uattr->query.attach_flags, &flags, sizeof(flags)))
return -EFAULT; return -EFAULT;
if (copy_to_user(&uattr->query.revision, &revision, sizeof(revision))) if (copy_to_user(&uattr->query.revision, &revision, sizeof(revision)))
......
...@@ -123,7 +123,6 @@ int tcx_prog_query(const union bpf_attr *attr, union bpf_attr __user *uattr) ...@@ -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; bool ingress = attr->query.attach_type == BPF_TCX_INGRESS;
struct net *net = current->nsproxy->net_ns; struct net *net = current->nsproxy->net_ns;
struct bpf_mprog_entry *entry;
struct net_device *dev; struct net_device *dev;
int ret; int ret;
...@@ -133,12 +132,7 @@ int tcx_prog_query(const union bpf_attr *attr, union bpf_attr __user *uattr) ...@@ -133,12 +132,7 @@ int tcx_prog_query(const union bpf_attr *attr, union bpf_attr __user *uattr)
ret = -ENODEV; ret = -ENODEV;
goto out; goto out;
} }
entry = tcx_entry_fetch(dev, ingress); ret = bpf_mprog_query(attr, uattr, tcx_entry_fetch(dev, ingress));
if (!entry) {
ret = -ENOENT;
goto out;
}
ret = bpf_mprog_query(attr, uattr, entry);
out: out:
rtnl_unlock(); rtnl_unlock();
return ret; return ret;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment