diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2017-06-27 18:24:21 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2017-07-04 13:14:34 -0400 |
commit | 5da028a8af38eced330332d5ae51c212e9e86242 (patch) | |
tree | dd6e88a9e04a3e47c3ff112997909a9646a0ee9f | |
parent | ffb07550c76f70b8fa5e57352e7e299f4811f0a0 (diff) |
get_compat_msghdr(): get rid of field-by-field copyin
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r-- | net/compat.c | 31 |
1 files changed, 14 insertions, 17 deletions
diff --git a/net/compat.c b/net/compat.c index aba929e5250f..dba5e222a0e5 100644 --- a/net/compat.c +++ b/net/compat.c | |||
@@ -37,21 +37,16 @@ int get_compat_msghdr(struct msghdr *kmsg, | |||
37 | struct sockaddr __user **save_addr, | 37 | struct sockaddr __user **save_addr, |
38 | struct iovec **iov) | 38 | struct iovec **iov) |
39 | { | 39 | { |
40 | compat_uptr_t uaddr, uiov, tmp3; | 40 | struct compat_msghdr msg; |
41 | compat_size_t nr_segs; | ||
42 | ssize_t err; | 41 | ssize_t err; |
43 | 42 | ||
44 | if (!access_ok(VERIFY_READ, umsg, sizeof(*umsg)) || | 43 | if (copy_from_user(&msg, umsg, sizeof(*umsg))) |
45 | __get_user(uaddr, &umsg->msg_name) || | ||
46 | __get_user(kmsg->msg_namelen, &umsg->msg_namelen) || | ||
47 | __get_user(uiov, &umsg->msg_iov) || | ||
48 | __get_user(nr_segs, &umsg->msg_iovlen) || | ||
49 | __get_user(tmp3, &umsg->msg_control) || | ||
50 | __get_user(kmsg->msg_controllen, &umsg->msg_controllen) || | ||
51 | __get_user(kmsg->msg_flags, &umsg->msg_flags)) | ||
52 | return -EFAULT; | 44 | return -EFAULT; |
53 | 45 | ||
54 | if (!uaddr) | 46 | kmsg->msg_flags = msg.msg_flags; |
47 | kmsg->msg_namelen = msg.msg_namelen; | ||
48 | |||
49 | if (!msg.msg_name) | ||
55 | kmsg->msg_namelen = 0; | 50 | kmsg->msg_namelen = 0; |
56 | 51 | ||
57 | if (kmsg->msg_namelen < 0) | 52 | if (kmsg->msg_namelen < 0) |
@@ -59,14 +54,16 @@ int get_compat_msghdr(struct msghdr *kmsg, | |||
59 | 54 | ||
60 | if (kmsg->msg_namelen > sizeof(struct sockaddr_storage)) | 55 | if (kmsg->msg_namelen > sizeof(struct sockaddr_storage)) |
61 | kmsg->msg_namelen = sizeof(struct sockaddr_storage); | 56 | kmsg->msg_namelen = sizeof(struct sockaddr_storage); |
62 | kmsg->msg_control = compat_ptr(tmp3); | 57 | |
58 | kmsg->msg_control = compat_ptr(msg.msg_control); | ||
59 | kmsg->msg_controllen = msg.msg_controllen; | ||
63 | 60 | ||
64 | if (save_addr) | 61 | if (save_addr) |
65 | *save_addr = compat_ptr(uaddr); | 62 | *save_addr = compat_ptr(msg.msg_name); |
66 | 63 | ||
67 | if (uaddr && kmsg->msg_namelen) { | 64 | if (msg.msg_name && kmsg->msg_namelen) { |
68 | if (!save_addr) { | 65 | if (!save_addr) { |
69 | err = move_addr_to_kernel(compat_ptr(uaddr), | 66 | err = move_addr_to_kernel(compat_ptr(msg.msg_name), |
70 | kmsg->msg_namelen, | 67 | kmsg->msg_namelen, |
71 | kmsg->msg_name); | 68 | kmsg->msg_name); |
72 | if (err < 0) | 69 | if (err < 0) |
@@ -77,13 +74,13 @@ int get_compat_msghdr(struct msghdr *kmsg, | |||
77 | kmsg->msg_namelen = 0; | 74 | kmsg->msg_namelen = 0; |
78 | } | 75 | } |
79 | 76 | ||
80 | if (nr_segs > UIO_MAXIOV) | 77 | if (msg.msg_iovlen > UIO_MAXIOV) |
81 | return -EMSGSIZE; | 78 | return -EMSGSIZE; |
82 | 79 | ||
83 | kmsg->msg_iocb = NULL; | 80 | kmsg->msg_iocb = NULL; |
84 | 81 | ||
85 | return compat_import_iovec(save_addr ? READ : WRITE, | 82 | return compat_import_iovec(save_addr ? READ : WRITE, |
86 | compat_ptr(uiov), nr_segs, | 83 | compat_ptr(msg.msg_iov), msg.msg_iovlen, |
87 | UIO_FASTIOV, iov, &kmsg->msg_iter); | 84 | UIO_FASTIOV, iov, &kmsg->msg_iter); |
88 | } | 85 | } |
89 | 86 | ||