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>
This commit is contained in:

committed by
David S. Miller

parent
2618d530dd
commit
1f466e1f15
@@ -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 */
|
||||
|
Reference in New Issue
Block a user