diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2017-06-27 18:34:53 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2017-07-04 13:14:34 -0400 |
commit | f8f8a727eab1c5b78c3703a461565b042979cc79 (patch) | |
tree | 1614a24192411d84b48c2f383fe3339666fc92a4 | |
parent | 5da028a8af38eced330332d5ae51c212e9e86242 (diff) |
get_compat_bpf_fprog(): don't copyin field-by-field
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r-- | net/compat.c | 18 |
1 files changed, 9 insertions, 9 deletions
diff --git a/net/compat.c b/net/compat.c index dba5e222a0e5..6ded6c821d7a 100644 --- a/net/compat.c +++ b/net/compat.c | |||
@@ -313,15 +313,15 @@ struct sock_fprog __user *get_compat_bpf_fprog(char __user *optval) | |||
313 | { | 313 | { |
314 | struct compat_sock_fprog __user *fprog32 = (struct compat_sock_fprog __user *)optval; | 314 | struct compat_sock_fprog __user *fprog32 = (struct compat_sock_fprog __user *)optval; |
315 | struct sock_fprog __user *kfprog = compat_alloc_user_space(sizeof(struct sock_fprog)); | 315 | struct sock_fprog __user *kfprog = compat_alloc_user_space(sizeof(struct sock_fprog)); |
316 | compat_uptr_t ptr; | 316 | struct compat_sock_fprog f32; |
317 | u16 len; | 317 | struct sock_fprog f; |
318 | 318 | ||
319 | if (!access_ok(VERIFY_READ, fprog32, sizeof(*fprog32)) || | 319 | if (copy_from_user(&f32, fprog32, sizeof(*fprog32))) |
320 | !access_ok(VERIFY_WRITE, kfprog, sizeof(struct sock_fprog)) || | 320 | return NULL; |
321 | __get_user(len, &fprog32->len) || | 321 | memset(&f, 0, sizeof(f)); |
322 | __get_user(ptr, &fprog32->filter) || | 322 | f.len = f32.len; |
323 | __put_user(len, &kfprog->len) || | 323 | f.filter = compat_ptr(f32.filter); |
324 | __put_user(compat_ptr(ptr), &kfprog->filter)) | 324 | if (copy_to_user(kfprog, &f, sizeof(struct sock_fprog))) |
325 | return NULL; | 325 | return NULL; |
326 | 326 | ||
327 | return kfprog; | 327 | return kfprog; |