summaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2020-05-11 13:59:13 +0200
committerDavid S. Miller <davem@davemloft.net>2020-05-11 16:59:16 -0700
commit1f466e1f15cf1dac7c86798d694649fc42cd868a (patch)
tree1f8ca24224e9aa0dbaf924bec224deb08d1ab505 /include
parent2618d530dd8b7ac0fdcb83f4c95b88f7b0d37ce6 (diff)
downloadlinux-1f466e1f15cf1dac7c86798d694649fc42cd868a.tar.bz2
net: cleanly handle kernel vs user buffers for ->msg_control
The msg_control field in struct msghdr can either contain a user pointer when used with the recvmsg system call, or a kernel pointer when used with sendmsg. To complicate things further kernel_recvmsg can stuff a kernel pointer in and then use set_fs to make the uaccess helpers accept it. Replace it with a union of a kernel pointer msg_control field, and a user pointer msg_control_user one, and allow kernel_recvmsg operate on a proper kernel pointer using a bitfield to override the normal choice of a user pointer for recvmsg. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include')
-rw-r--r--include/linux/socket.h12
1 files changed, 11 insertions, 1 deletions
diff --git a/include/linux/socket.h b/include/linux/socket.h
index 4cc64d611cf4..04d2bc97f497 100644
--- a/include/linux/socket.h
+++ b/include/linux/socket.h
@@ -50,7 +50,17 @@ struct msghdr {
void *msg_name; /* ptr to socket address structure */
int msg_namelen; /* size of socket address structure */
struct iov_iter msg_iter; /* data */
- void *msg_control; /* ancillary data */
+
+ /*
+ * Ancillary data. msg_control_user is the user buffer used for the
+ * recv* side when msg_control_is_user is set, msg_control is the kernel
+ * buffer used for all other cases.
+ */
+ union {
+ void *msg_control;
+ void __user *msg_control_user;
+ };
+ bool msg_control_is_user : 1;
__kernel_size_t msg_controllen; /* ancillary data buffer length */
unsigned int msg_flags; /* flags on received message */
struct kiocb *msg_iocb; /* ptr to iocb for async requests */