BPF_PROG_QUERY writes back the 'query.revision' field unconditionally to
userspace. If userspace passes a smaller 'bpf_attr' structure (e.g. 40
bytes, which was the layout before the addition of 'query.revision'),
the kernel performs an out-of-bounds write.

Fix this by returning -EFAULT in bpf_prog_query() if the user-provided
attribute size is smaller than the offset of the 'query.revision' field.

Fixes: 120933984460 ("bpf: Implement mprog API on top of existing cgroup progs")
Cc: Maciej Żenczykowski <[email protected]>
Cc: Lorenzo Colitti <[email protected]>
Signed-off-by: Yuyang Huang <[email protected]>
---
 kernel/bpf/syscall.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index a3c0214ca934..c9a5415ad437 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -4654,8 +4654,10 @@ static int bpf_prog_detach(const union bpf_attr *attr)
 #define BPF_PROG_QUERY_LAST_FIELD query.revision
 
 static int bpf_prog_query(const union bpf_attr *attr,
-                         union bpf_attr __user *uattr)
+                         union bpf_attr __user *uattr, u32 uattr_size)
 {
+       if (uattr_size < offsetofend(union bpf_attr, query.revision))
+               return -EFAULT;
        if (!bpf_net_capable())
                return -EPERM;
        if (CHECK_ATTR(BPF_PROG_QUERY))
@@ -6260,7 +6262,7 @@ static int __sys_bpf(enum bpf_cmd cmd, bpfptr_t uattr, 
unsigned int size)
                err = bpf_prog_detach(&attr);
                break;
        case BPF_PROG_QUERY:
-               err = bpf_prog_query(&attr, uattr.user);
+               err = bpf_prog_query(&attr, uattr.user, size);
                break;
        case BPF_PROG_TEST_RUN:
                err = bpf_prog_test_run(&attr, uattr.user);
-- 
2.54.0.823.g6e5bcc1fc9-goog


Reply via email to