Commit 0a384abf authored by Jens Axboe's avatar Jens Axboe

net: abstract out normal and compat msghdr import

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: default avatarDavid Miller <davem@davemloft.net>
Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent 4d954c25
...@@ -391,6 +391,10 @@ extern int recvmsg_copy_msghdr(struct msghdr *msg, ...@@ -391,6 +391,10 @@ extern int recvmsg_copy_msghdr(struct msghdr *msg,
struct user_msghdr __user *umsg, unsigned flags, struct user_msghdr __user *umsg, unsigned flags,
struct sockaddr __user **uaddr, struct sockaddr __user **uaddr,
struct iovec **iov); 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 */ /* helpers which do the actual work for syscalls */
extern int __sys_recvfrom(int fd, void __user *ubuf, size_t size, extern int __sys_recvfrom(int fd, void __user *ubuf, size_t size,
......
...@@ -38,6 +38,9 @@ struct compat_cmsghdr { ...@@ -38,6 +38,9 @@ struct compat_cmsghdr {
#define compat_mmsghdr mmsghdr #define compat_mmsghdr mmsghdr
#endif /* defined(CONFIG_COMPAT) */ #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 *, int get_compat_msghdr(struct msghdr *, struct compat_msghdr __user *,
struct sockaddr __user **, struct iovec **); struct sockaddr __user **, struct iovec **);
struct sock_fprog __user *get_compat_bpf_fprog(char __user *optval); struct sock_fprog __user *get_compat_bpf_fprog(char __user *optval);
......
...@@ -33,10 +33,10 @@ ...@@ -33,10 +33,10 @@
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <net/compat.h> #include <net/compat.h>
int get_compat_msghdr(struct msghdr *kmsg, int __get_compat_msghdr(struct msghdr *kmsg,
struct compat_msghdr __user *umsg, struct compat_msghdr __user *umsg,
struct sockaddr __user **save_addr, struct sockaddr __user **save_addr,
struct iovec **iov) compat_uptr_t *ptr, compat_size_t *len)
{ {
struct compat_msghdr msg; struct compat_msghdr msg;
ssize_t err; ssize_t err;
...@@ -79,10 +79,26 @@ int get_compat_msghdr(struct msghdr *kmsg, ...@@ -79,10 +79,26 @@ int get_compat_msghdr(struct msghdr *kmsg,
return -EMSGSIZE; return -EMSGSIZE;
kmsg->msg_iocb = NULL; 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, err = compat_import_iovec(save_addr ? READ : WRITE, compat_ptr(ptr),
compat_ptr(msg.msg_iov), msg.msg_iovlen, len, UIO_FASTIOV, iov, &kmsg->msg_iter);
UIO_FASTIOV, iov, &kmsg->msg_iter);
return err < 0 ? err : 0; return err < 0 ? err : 0;
} }
......
...@@ -2226,10 +2226,10 @@ struct used_address { ...@@ -2226,10 +2226,10 @@ struct used_address {
unsigned int name_len; unsigned int name_len;
}; };
static int copy_msghdr_from_user(struct msghdr *kmsg, int __copy_msghdr_from_user(struct msghdr *kmsg,
struct user_msghdr __user *umsg, struct user_msghdr __user *umsg,
struct sockaddr __user **save_addr, struct sockaddr __user **save_addr,
struct iovec **iov) struct iovec __user **uiov, size_t *nsegs)
{ {
struct user_msghdr msg; struct user_msghdr msg;
ssize_t err; ssize_t err;
...@@ -2271,6 +2271,23 @@ static int copy_msghdr_from_user(struct msghdr *kmsg, ...@@ -2271,6 +2271,23 @@ static int copy_msghdr_from_user(struct msghdr *kmsg,
return -EMSGSIZE; return -EMSGSIZE;
kmsg->msg_iocb = NULL; 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, err = import_iovec(save_addr ? READ : WRITE,
msg.msg_iov, msg.msg_iovlen, msg.msg_iov, msg.msg_iovlen,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment