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

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
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -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,
+3 −0
Original line number Diff line number Diff line
@@ -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);
+23 −7
Original line number Diff line number Diff line
@@ -33,10 +33,10 @@
#include <linux/uaccess.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 sockaddr __user **save_addr,
		      struct iovec **iov)
			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;
}

+21 −4
Original line number Diff line number Diff line
@@ -2226,10 +2226,10 @@ struct used_address {
	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 sockaddr __user **save_addr,
				 struct iovec **iov)
			    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,