bpf: respect size hint to BPF_PROG_TEST_RUN if present
authorLorenz Bauer <lmb@cloudflare.com>
Mon, 3 Dec 2018 11:31:23 +0000 (11:31 +0000)
committerAlexei Starovoitov <ast@kernel.org>
Tue, 4 Dec 2018 16:18:13 +0000 (08:18 -0800)
Use data_size_out as a size hint when copying test output to user space.
ENOSPC is returned if the output buffer is too small.
Callers which so far did not set data_size_out are not affected.

Signed-off-by: Lorenz Bauer <lmb@cloudflare.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
include/uapi/linux/bpf.h
net/bpf/test_run.c

index 572eb2d..c8e1eee 100644 (file)
@@ -374,8 +374,11 @@ union bpf_attr {
        struct { /* anonymous struct used by BPF_PROG_TEST_RUN command */
                __u32           prog_fd;
                __u32           retval;
-               __u32           data_size_in;
-               __u32           data_size_out;
+               __u32           data_size_in;   /* input: len of data_in */
+               __u32           data_size_out;  /* input/output: len of data_out
+                                                *   returns ENOSPC if data_out
+                                                *   is too small.
+                                                */
                __aligned_u64   data_in;
                __aligned_u64   data_out;
                __u32           repeat;
index c89c22c..7663e6a 100644 (file)
@@ -74,8 +74,18 @@ static int bpf_test_finish(const union bpf_attr *kattr,
 {
        void __user *data_out = u64_to_user_ptr(kattr->test.data_out);
        int err = -EFAULT;
+       u32 copy_size = size;
+
+       /* Clamp copy if the user has provided a size hint, but copy the full
+        * buffer if not to retain old behaviour.
+        */
+       if (kattr->test.data_size_out &&
+           copy_size > kattr->test.data_size_out) {
+               copy_size = kattr->test.data_size_out;
+               err = -ENOSPC;
+       }
 
-       if (data_out && copy_to_user(data_out, data, size))
+       if (data_out && copy_to_user(data_out, data, copy_size))
                goto out;
        if (copy_to_user(&uattr->test.data_size_out, &size, sizeof(size)))
                goto out;
@@ -83,7 +93,8 @@ static int bpf_test_finish(const union bpf_attr *kattr,
                goto out;
        if (copy_to_user(&uattr->test.duration, &duration, sizeof(duration)))
                goto out;
-       err = 0;
+       if (err != -ENOSPC)
+               err = 0;
 out:
        return err;
 }