aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2017-06-27 18:24:21 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2017-07-04 13:14:34 -0400
commit5da028a8af38eced330332d5ae51c212e9e86242 (patch)
treedd6e88a9e04a3e47c3ff112997909a9646a0ee9f
parentffb07550c76f70b8fa5e57352e7e299f4811f0a0 (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.c31
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