diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2017-06-27 19:32:04 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2017-07-04 13:14:33 -0400 |
commit | ffb07550c76f70b8fa5e57352e7e299f4811f0a0 (patch) | |
tree | 7e3eff67e3fb93e41021d8533f3b3b435c2eeb4e /net/socket.c | |
parent | 0d0606060baefdb13d3d80dba1b4c816b0676e16 (diff) |
copy_msghdr_from_user(): get rid of field-by-field copyin
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'net/socket.c')
-rw-r--r-- | net/socket.c | 31 |
1 files changed, 14 insertions, 17 deletions
diff --git a/net/socket.c b/net/socket.c index c2564eb25c6b..af33d929135a 100644 --- a/net/socket.c +++ b/net/socket.c | |||
@@ -1870,22 +1870,18 @@ static int copy_msghdr_from_user(struct msghdr *kmsg, | |||
1870 | struct sockaddr __user **save_addr, | 1870 | struct sockaddr __user **save_addr, |
1871 | struct iovec **iov) | 1871 | struct iovec **iov) |
1872 | { | 1872 | { |
1873 | struct sockaddr __user *uaddr; | 1873 | struct user_msghdr msg; |
1874 | struct iovec __user *uiov; | ||
1875 | size_t nr_segs; | ||
1876 | ssize_t err; | 1874 | ssize_t err; |
1877 | 1875 | ||
1878 | if (!access_ok(VERIFY_READ, umsg, sizeof(*umsg)) || | 1876 | if (copy_from_user(&msg, umsg, sizeof(*umsg))) |
1879 | __get_user(uaddr, &umsg->msg_name) || | ||
1880 | __get_user(kmsg->msg_namelen, &umsg->msg_namelen) || | ||
1881 | __get_user(uiov, &umsg->msg_iov) || | ||
1882 | __get_user(nr_segs, &umsg->msg_iovlen) || | ||
1883 | __get_user(kmsg->msg_control, &umsg->msg_control) || | ||
1884 | __get_user(kmsg->msg_controllen, &umsg->msg_controllen) || | ||
1885 | __get_user(kmsg->msg_flags, &umsg->msg_flags)) | ||
1886 | return -EFAULT; | 1877 | return -EFAULT; |
1887 | 1878 | ||
1888 | if (!uaddr) | 1879 | kmsg->msg_control = msg.msg_control; |
1880 | kmsg->msg_controllen = msg.msg_controllen; | ||
1881 | kmsg->msg_flags = msg.msg_flags; | ||
1882 | |||
1883 | kmsg->msg_namelen = msg.msg_namelen; | ||
1884 | if (!msg.msg_name) | ||
1889 | kmsg->msg_namelen = 0; | 1885 | kmsg->msg_namelen = 0; |
1890 | 1886 | ||
1891 | if (kmsg->msg_namelen < 0) | 1887 | if (kmsg->msg_namelen < 0) |
@@ -1895,11 +1891,11 @@ static int copy_msghdr_from_user(struct msghdr *kmsg, | |||
1895 | kmsg->msg_namelen = sizeof(struct sockaddr_storage); | 1891 | kmsg->msg_namelen = sizeof(struct sockaddr_storage); |
1896 | 1892 | ||
1897 | if (save_addr) | 1893 | if (save_addr) |
1898 | *save_addr = uaddr; | 1894 | *save_addr = msg.msg_name; |
1899 | 1895 | ||
1900 | if (uaddr && kmsg->msg_namelen) { | 1896 | if (msg.msg_name && kmsg->msg_namelen) { |
1901 | if (!save_addr) { | 1897 | if (!save_addr) { |
1902 | err = move_addr_to_kernel(uaddr, kmsg->msg_namelen, | 1898 | err = move_addr_to_kernel(msg.msg_name, kmsg->msg_namelen, |
1903 | kmsg->msg_name); | 1899 | kmsg->msg_name); |
1904 | if (err < 0) | 1900 | if (err < 0) |
1905 | return err; | 1901 | return err; |
@@ -1909,12 +1905,13 @@ static int copy_msghdr_from_user(struct msghdr *kmsg, | |||
1909 | kmsg->msg_namelen = 0; | 1905 | kmsg->msg_namelen = 0; |
1910 | } | 1906 | } |
1911 | 1907 | ||
1912 | if (nr_segs > UIO_MAXIOV) | 1908 | if (msg.msg_iovlen > UIO_MAXIOV) |
1913 | return -EMSGSIZE; | 1909 | return -EMSGSIZE; |
1914 | 1910 | ||
1915 | kmsg->msg_iocb = NULL; | 1911 | kmsg->msg_iocb = NULL; |
1916 | 1912 | ||
1917 | return import_iovec(save_addr ? READ : WRITE, uiov, nr_segs, | 1913 | return import_iovec(save_addr ? READ : WRITE, |
1914 | msg.msg_iov, msg.msg_iovlen, | ||
1918 | UIO_FASTIOV, iov, &kmsg->msg_iter); | 1915 | UIO_FASTIOV, iov, &kmsg->msg_iter); |
1919 | } | 1916 | } |
1920 | 1917 | ||