net: abstract out normal and compat msghdr import
authorJens Axboe <axboe@kernel.dk>
Thu, 27 Feb 2020 15:11:20 +0000 (08:11 -0700)
committerJens Axboe <axboe@kernel.dk>
Tue, 10 Mar 2020 15:12:49 +0000 (09:12 -0600)
This splits it into two parts, one that imports the message, and one
that imports the iovec. This allows a caller to only do the first part,
and import the iovec manually afterwards.

No functional changes in this patch.

Acked-by: David Miller <davem@davemloft.net>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
include/linux/socket.h
include/net/compat.h
net/compat.c
net/socket.c

index 2d23134031016e6efefc93c6270c0efa7c4d60f2..fc59ac825561209c53cfce1ac3bace1a87216ee7 100644 (file)
@@ -391,6 +391,10 @@ extern int recvmsg_copy_msghdr(struct msghdr *msg,
                               struct user_msghdr __user *umsg, unsigned flags,
                               struct sockaddr __user **uaddr,
                               struct iovec **iov);
+extern int __copy_msghdr_from_user(struct msghdr *kmsg,
+                                  struct user_msghdr __user *umsg,
+                                  struct sockaddr __user **save_addr,
+                                  struct iovec __user **uiov, size_t *nsegs);
 
 /* helpers which do the actual work for syscalls */
 extern int __sys_recvfrom(int fd, void __user *ubuf, size_t size,
index f277653c7e1739fb4209b1244ea8499ca50508b3..e341260642feedd7cc77f22a4a5c7915e7d07d31 100644 (file)
@@ -38,6 +38,9 @@ struct compat_cmsghdr {
 #define compat_mmsghdr mmsghdr
 #endif /* defined(CONFIG_COMPAT) */
 
+int __get_compat_msghdr(struct msghdr *kmsg, struct compat_msghdr __user *umsg,
+                       struct sockaddr __user **save_addr, compat_uptr_t *ptr,
+                       compat_size_t *len);
 int get_compat_msghdr(struct msghdr *, struct compat_msghdr __user *,
                      struct sockaddr __user **, struct iovec **);
 struct sock_fprog __user *get_compat_bpf_fprog(char __user *optval);
index 47d99c784947c910bbe1b85d9539b3a07b023246..4bed96e84d9a6a41f165c748444bf6dff89ad01d 100644 (file)
 #include <linux/uaccess.h>
 #include <net/compat.h>
 
-int get_compat_msghdr(struct msghdr *kmsg,
-                     struct compat_msghdr __user *umsg,
-                     struct sockaddr __user **save_addr,
-                     struct iovec **iov)
+int __get_compat_msghdr(struct msghdr *kmsg,
+                       struct compat_msghdr __user *umsg,
+                       struct sockaddr __user **save_addr,
+                       compat_uptr_t *ptr, compat_size_t *len)
 {
        struct compat_msghdr msg;
        ssize_t err;
@@ -79,10 +79,26 @@ int get_compat_msghdr(struct msghdr *kmsg,
                return -EMSGSIZE;
 
        kmsg->msg_iocb = NULL;
+       *ptr = msg.msg_iov;
+       *len = msg.msg_iovlen;
+       return 0;
+}
+
+int get_compat_msghdr(struct msghdr *kmsg,
+                     struct compat_msghdr __user *umsg,
+                     struct sockaddr __user **save_addr,
+                     struct iovec **iov)
+{
+       compat_uptr_t ptr;
+       compat_size_t len;
+       ssize_t err;
+
+       err = __get_compat_msghdr(kmsg, umsg, save_addr, &ptr, &len);
+       if (err)
+               return err;
 
-       err = compat_import_iovec(save_addr ? READ : WRITE,
-                                  compat_ptr(msg.msg_iov), msg.msg_iovlen,
-                                  UIO_FASTIOV, iov, &kmsg->msg_iter);
+       err = compat_import_iovec(save_addr ? READ : WRITE, compat_ptr(ptr),
+                                  len, UIO_FASTIOV, iov, &kmsg->msg_iter);
        return err < 0 ? err : 0;
 }
 
index b79a05de7c6e9091df65f4aa4816af329cf2c0c8..70ede74ab24b01ffba2dea0f3b4953eaded6a4b3 100644 (file)
@@ -2226,10 +2226,10 @@ struct used_address {
        unsigned int name_len;
 };
 
-static int copy_msghdr_from_user(struct msghdr *kmsg,
-                                struct user_msghdr __user *umsg,
-                                struct sockaddr __user **save_addr,
-                                struct iovec **iov)
+int __copy_msghdr_from_user(struct msghdr *kmsg,
+                           struct user_msghdr __user *umsg,
+                           struct sockaddr __user **save_addr,
+                           struct iovec __user **uiov, size_t *nsegs)
 {
        struct user_msghdr msg;
        ssize_t err;
@@ -2271,6 +2271,23 @@ static int copy_msghdr_from_user(struct msghdr *kmsg,
                return -EMSGSIZE;
 
        kmsg->msg_iocb = NULL;
+       *uiov = msg.msg_iov;
+       *nsegs = msg.msg_iovlen;
+       return 0;
+}
+
+static int copy_msghdr_from_user(struct msghdr *kmsg,
+                                struct user_msghdr __user *umsg,
+                                struct sockaddr __user **save_addr,
+                                struct iovec **iov)
+{
+       struct user_msghdr msg;
+       ssize_t err;
+
+       err = __copy_msghdr_from_user(kmsg, umsg, save_addr, &msg.msg_iov,
+                                       &msg.msg_iovlen);
+       if (err)
+               return err;
 
        err = import_iovec(save_addr ? READ : WRITE,
                            msg.msg_iov, msg.msg_iovlen,