diff options
author | Lorenz Bauer <lmb@cloudflare.com> | 2018-12-03 11:31:23 +0000 |
---|---|---|
committer | Alexei Starovoitov <ast@kernel.org> | 2018-12-04 08:18:13 -0800 |
commit | b5a36b1e1b138285ea0df34bf96c759e1e30fafd (patch) | |
tree | 979d2a28beaa2dcb3bba77964e7e44630694e8eb | |
parent | d59dd69d5576d699d7d3f5da0b4738c3a36d0133 (diff) | |
download | linux-stable-b5a36b1e1b138285ea0df34bf96c759e1e30fafd.tar.gz linux-stable-b5a36b1e1b138285ea0df34bf96c759e1e30fafd.tar.bz2 linux-stable-b5a36b1e1b138285ea0df34bf96c759e1e30fafd.zip |
bpf: respect size hint to BPF_PROG_TEST_RUN if present
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>
-rw-r--r-- | include/uapi/linux/bpf.h | 7 | ||||
-rw-r--r-- | net/bpf/test_run.c | 15 |
2 files changed, 18 insertions, 4 deletions
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index 572eb2d42768..c8e1eeee2c5f 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -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; diff --git a/net/bpf/test_run.c b/net/bpf/test_run.c index c89c22c49015..7663e6a57280 100644 --- a/net/bpf/test_run.c +++ b/net/bpf/test_run.c @@ -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; } |