Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'misc.compat' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs

Pull network field-by-field copy-in updates from Al Viro:
"This part of the misc compat queue was held back for review from
networking folks and since davem has jus ACKed those..."

* 'misc.compat' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
get_compat_bpf_fprog(): don't copyin field-by-field
get_compat_msghdr(): get rid of field-by-field copyin
copy_msghdr_from_user(): get rid of field-by-field copyin

+36 -42
+22 -25
net/compat.c
··· 37 37 struct sockaddr __user **save_addr, 38 38 struct iovec **iov) 39 39 { 40 - compat_uptr_t uaddr, uiov, tmp3; 41 - compat_size_t nr_segs; 40 + struct compat_msghdr msg; 42 41 ssize_t err; 43 42 44 - if (!access_ok(VERIFY_READ, 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)) 43 + if (copy_from_user(&msg, umsg, sizeof(*umsg))) 52 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 50 kmsg->msg_namelen = 0; 56 51 57 52 if (kmsg->msg_namelen < 0) ··· 54 59 55 60 if (kmsg->msg_namelen > sizeof(struct sockaddr_storage)) 56 61 kmsg->msg_namelen = sizeof(struct sockaddr_storage); 57 - kmsg->msg_control = compat_ptr(tmp3); 62 + 63 + kmsg->msg_control = compat_ptr(msg.msg_control); 64 + kmsg->msg_controllen = msg.msg_controllen; 58 65 59 66 if (save_addr) 60 - *save_addr = compat_ptr(uaddr); 67 + *save_addr = compat_ptr(msg.msg_name); 61 68 62 - if (uaddr && kmsg->msg_namelen) { 69 + if (msg.msg_name && kmsg->msg_namelen) { 63 70 if (!save_addr) { 64 - err = move_addr_to_kernel(compat_ptr(uaddr), 71 + err = move_addr_to_kernel(compat_ptr(msg.msg_name), 65 72 kmsg->msg_namelen, 66 73 kmsg->msg_name); 67 74 if (err < 0) ··· 74 77 kmsg->msg_namelen = 0; 75 78 } 76 79 77 - if (nr_segs > UIO_MAXIOV) 80 + if (msg.msg_iovlen > UIO_MAXIOV) 78 81 return -EMSGSIZE; 79 82 80 83 kmsg->msg_iocb = NULL; 81 84 82 85 return compat_import_iovec(save_addr ? READ : WRITE, 83 - compat_ptr(uiov), nr_segs, 86 + compat_ptr(msg.msg_iov), msg.msg_iovlen, 84 87 UIO_FASTIOV, iov, &kmsg->msg_iter); 85 88 } 86 89 ··· 313 316 { 314 317 struct compat_sock_fprog __user *fprog32 = (struct compat_sock_fprog __user *)optval; 315 318 struct sock_fprog __user *kfprog = compat_alloc_user_space(sizeof(struct sock_fprog)); 316 - compat_uptr_t ptr; 317 - u16 len; 319 + struct compat_sock_fprog f32; 320 + struct sock_fprog f; 318 321 319 - if (!access_ok(VERIFY_READ, fprog32, sizeof(*fprog32)) || 320 - !access_ok(VERIFY_WRITE, kfprog, sizeof(struct sock_fprog)) || 321 - __get_user(len, &fprog32->len) || 322 - __get_user(ptr, &fprog32->filter) || 323 - __put_user(len, &kfprog->len) || 324 - __put_user(compat_ptr(ptr), &kfprog->filter)) 322 + if (copy_from_user(&f32, fprog32, sizeof(*fprog32))) 323 + return NULL; 324 + memset(&f, 0, sizeof(f)); 325 + f.len = f32.len; 326 + f.filter = compat_ptr(f32.filter); 327 + if (copy_to_user(kfprog, &f, sizeof(struct sock_fprog))) 325 328 return NULL; 326 329 327 330 return kfprog;
+14 -17
net/socket.c
··· 1910 1910 struct sockaddr __user **save_addr, 1911 1911 struct iovec **iov) 1912 1912 { 1913 - struct sockaddr __user *uaddr; 1914 - struct iovec __user *uiov; 1915 - size_t nr_segs; 1913 + struct user_msghdr msg; 1916 1914 ssize_t err; 1917 1915 1918 - if (!access_ok(VERIFY_READ, umsg, sizeof(*umsg)) || 1919 - __get_user(uaddr, &umsg->msg_name) || 1920 - __get_user(kmsg->msg_namelen, &umsg->msg_namelen) || 1921 - __get_user(uiov, &umsg->msg_iov) || 1922 - __get_user(nr_segs, &umsg->msg_iovlen) || 1923 - __get_user(kmsg->msg_control, &umsg->msg_control) || 1924 - __get_user(kmsg->msg_controllen, &umsg->msg_controllen) || 1925 - __get_user(kmsg->msg_flags, &umsg->msg_flags)) 1916 + if (copy_from_user(&msg, umsg, sizeof(*umsg))) 1926 1917 return -EFAULT; 1927 1918 1928 - if (!uaddr) 1919 + kmsg->msg_control = msg.msg_control; 1920 + kmsg->msg_controllen = msg.msg_controllen; 1921 + kmsg->msg_flags = msg.msg_flags; 1922 + 1923 + kmsg->msg_namelen = msg.msg_namelen; 1924 + if (!msg.msg_name) 1929 1925 kmsg->msg_namelen = 0; 1930 1926 1931 1927 if (kmsg->msg_namelen < 0) ··· 1931 1935 kmsg->msg_namelen = sizeof(struct sockaddr_storage); 1932 1936 1933 1937 if (save_addr) 1934 - *save_addr = uaddr; 1938 + *save_addr = msg.msg_name; 1935 1939 1936 - if (uaddr && kmsg->msg_namelen) { 1940 + if (msg.msg_name && kmsg->msg_namelen) { 1937 1941 if (!save_addr) { 1938 - err = move_addr_to_kernel(uaddr, kmsg->msg_namelen, 1942 + err = move_addr_to_kernel(msg.msg_name, kmsg->msg_namelen, 1939 1943 kmsg->msg_name); 1940 1944 if (err < 0) 1941 1945 return err; ··· 1945 1949 kmsg->msg_namelen = 0; 1946 1950 } 1947 1951 1948 - if (nr_segs > UIO_MAXIOV) 1952 + if (msg.msg_iovlen > UIO_MAXIOV) 1949 1953 return -EMSGSIZE; 1950 1954 1951 1955 kmsg->msg_iocb = NULL; 1952 1956 1953 - return import_iovec(save_addr ? READ : WRITE, uiov, nr_segs, 1957 + return import_iovec(save_addr ? READ : WRITE, 1958 + msg.msg_iov, msg.msg_iovlen, 1954 1959 UIO_FASTIOV, iov, &kmsg->msg_iter); 1955 1960 } 1956 1961