Commit c11d2e71 authored by David S. Miller's avatar David S. Miller

Merge branch 'msg_control-split'

Kevin Brodsky says:

====================
net: Finish up ->msg_control{,_user} split

Commit 1f466e1f ("net: cleanly handle kernel vs user buffers for
->msg_control") introduced the msg_control_user and
msg_control_is_user fields in struct msghdr, to ensure that user
pointers are represented as such. It also took care of converting most
users of struct msghdr::msg_control where user pointers are involved. It
did however miss a number of cases, and some code using msg_control
inappropriately has also appeared in the meantime.

This series is attempting to complete the split, by eliminating the
remaining cases where msg_control is used when in fact a user
pointer is stored in the union (patch 1).

It also addresses a couple of issues with msg_control_is_user: one where
it is not updated as it should (patch 2), and one where it is not
initialised (patch 3).

v1..v2:
* Split out the msg_control_is_user fixes into separate patches.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents eaaa4e92 b6d85cf5
...@@ -113,7 +113,7 @@ int get_compat_msghdr(struct msghdr *kmsg, ...@@ -113,7 +113,7 @@ int get_compat_msghdr(struct msghdr *kmsg,
#define CMSG_COMPAT_FIRSTHDR(msg) \ #define CMSG_COMPAT_FIRSTHDR(msg) \
(((msg)->msg_controllen) >= sizeof(struct compat_cmsghdr) ? \ (((msg)->msg_controllen) >= sizeof(struct compat_cmsghdr) ? \
(struct compat_cmsghdr __user *)((msg)->msg_control) : \ (struct compat_cmsghdr __user *)((msg)->msg_control_user) : \
(struct compat_cmsghdr __user *)NULL) (struct compat_cmsghdr __user *)NULL)
#define CMSG_COMPAT_OK(ucmlen, ucmsg, mhdr) \ #define CMSG_COMPAT_OK(ucmlen, ucmsg, mhdr) \
...@@ -126,7 +126,7 @@ static inline struct compat_cmsghdr __user *cmsg_compat_nxthdr(struct msghdr *ms ...@@ -126,7 +126,7 @@ static inline struct compat_cmsghdr __user *cmsg_compat_nxthdr(struct msghdr *ms
struct compat_cmsghdr __user *cmsg, int cmsg_len) struct compat_cmsghdr __user *cmsg, int cmsg_len)
{ {
char __user *ptr = (char __user *)cmsg + CMSG_COMPAT_ALIGN(cmsg_len); char __user *ptr = (char __user *)cmsg + CMSG_COMPAT_ALIGN(cmsg_len);
if ((unsigned long)(ptr + 1 - (char __user *)msg->msg_control) > if ((unsigned long)(ptr + 1 - (char __user *)msg->msg_control_user) >
msg->msg_controllen) msg->msg_controllen)
return NULL; return NULL;
return (struct compat_cmsghdr __user *)ptr; return (struct compat_cmsghdr __user *)ptr;
...@@ -211,6 +211,7 @@ int cmsghdr_from_user_compat_to_kern(struct msghdr *kmsg, struct sock *sk, ...@@ -211,6 +211,7 @@ int cmsghdr_from_user_compat_to_kern(struct msghdr *kmsg, struct sock *sk,
goto Einval; goto Einval;
/* Ok, looks like we made it. Hook it up and return success. */ /* Ok, looks like we made it. Hook it up and return success. */
kmsg->msg_control_is_user = false;
kmsg->msg_control = kcmsg_base; kmsg->msg_control = kcmsg_base;
kmsg->msg_controllen = kcmlen; kmsg->msg_controllen = kcmlen;
return 0; return 0;
...@@ -225,7 +226,7 @@ int cmsghdr_from_user_compat_to_kern(struct msghdr *kmsg, struct sock *sk, ...@@ -225,7 +226,7 @@ int cmsghdr_from_user_compat_to_kern(struct msghdr *kmsg, struct sock *sk,
int put_cmsg_compat(struct msghdr *kmsg, int level, int type, int len, void *data) int put_cmsg_compat(struct msghdr *kmsg, int level, int type, int len, void *data)
{ {
struct compat_cmsghdr __user *cm = (struct compat_cmsghdr __user *) kmsg->msg_control; struct compat_cmsghdr __user *cm = (struct compat_cmsghdr __user *) kmsg->msg_control_user;
struct compat_cmsghdr cmhdr; struct compat_cmsghdr cmhdr;
struct old_timeval32 ctv; struct old_timeval32 ctv;
struct old_timespec32 cts[3]; struct old_timespec32 cts[3];
...@@ -274,7 +275,7 @@ int put_cmsg_compat(struct msghdr *kmsg, int level, int type, int len, void *dat ...@@ -274,7 +275,7 @@ int put_cmsg_compat(struct msghdr *kmsg, int level, int type, int len, void *dat
cmlen = CMSG_COMPAT_SPACE(len); cmlen = CMSG_COMPAT_SPACE(len);
if (kmsg->msg_controllen < cmlen) if (kmsg->msg_controllen < cmlen)
cmlen = kmsg->msg_controllen; cmlen = kmsg->msg_controllen;
kmsg->msg_control += cmlen; kmsg->msg_control_user += cmlen;
kmsg->msg_controllen -= cmlen; kmsg->msg_controllen -= cmlen;
return 0; return 0;
} }
...@@ -289,7 +290,7 @@ static int scm_max_fds_compat(struct msghdr *msg) ...@@ -289,7 +290,7 @@ static int scm_max_fds_compat(struct msghdr *msg)
void scm_detach_fds_compat(struct msghdr *msg, struct scm_cookie *scm) void scm_detach_fds_compat(struct msghdr *msg, struct scm_cookie *scm)
{ {
struct compat_cmsghdr __user *cm = struct compat_cmsghdr __user *cm =
(struct compat_cmsghdr __user *)msg->msg_control; (struct compat_cmsghdr __user *)msg->msg_control_user;
unsigned int o_flags = (msg->msg_flags & MSG_CMSG_CLOEXEC) ? O_CLOEXEC : 0; unsigned int o_flags = (msg->msg_flags & MSG_CMSG_CLOEXEC) ? O_CLOEXEC : 0;
int fdmax = min_t(int, scm_max_fds_compat(msg), scm->fp->count); int fdmax = min_t(int, scm_max_fds_compat(msg), scm->fp->count);
int __user *cmsg_data = CMSG_COMPAT_DATA(cm); int __user *cmsg_data = CMSG_COMPAT_DATA(cm);
...@@ -313,7 +314,7 @@ void scm_detach_fds_compat(struct msghdr *msg, struct scm_cookie *scm) ...@@ -313,7 +314,7 @@ void scm_detach_fds_compat(struct msghdr *msg, struct scm_cookie *scm)
cmlen = CMSG_COMPAT_SPACE(i * sizeof(int)); cmlen = CMSG_COMPAT_SPACE(i * sizeof(int));
if (msg->msg_controllen < cmlen) if (msg->msg_controllen < cmlen)
cmlen = msg->msg_controllen; cmlen = msg->msg_controllen;
msg->msg_control += cmlen; msg->msg_control_user += cmlen;
msg->msg_controllen -= cmlen; msg->msg_controllen -= cmlen;
} }
} }
......
...@@ -250,7 +250,10 @@ int put_cmsg(struct msghdr * msg, int level, int type, int len, void *data) ...@@ -250,7 +250,10 @@ int put_cmsg(struct msghdr * msg, int level, int type, int len, void *data)
} }
cmlen = min(CMSG_SPACE(len), msg->msg_controllen); cmlen = min(CMSG_SPACE(len), msg->msg_controllen);
msg->msg_control += cmlen; if (msg->msg_control_is_user)
msg->msg_control_user += cmlen;
else
msg->msg_control += cmlen;
msg->msg_controllen -= cmlen; msg->msg_controllen -= cmlen;
return 0; return 0;
...@@ -299,7 +302,7 @@ static int scm_max_fds(struct msghdr *msg) ...@@ -299,7 +302,7 @@ static int scm_max_fds(struct msghdr *msg)
void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm) void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm)
{ {
struct cmsghdr __user *cm = struct cmsghdr __user *cm =
(__force struct cmsghdr __user *)msg->msg_control; (__force struct cmsghdr __user *)msg->msg_control_user;
unsigned int o_flags = (msg->msg_flags & MSG_CMSG_CLOEXEC) ? O_CLOEXEC : 0; unsigned int o_flags = (msg->msg_flags & MSG_CMSG_CLOEXEC) ? O_CLOEXEC : 0;
int fdmax = min_t(int, scm_max_fds(msg), scm->fp->count); int fdmax = min_t(int, scm_max_fds(msg), scm->fp->count);
int __user *cmsg_data = CMSG_USER_DATA(cm); int __user *cmsg_data = CMSG_USER_DATA(cm);
...@@ -332,7 +335,7 @@ void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm) ...@@ -332,7 +335,7 @@ void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm)
cmlen = CMSG_SPACE(i * sizeof(int)); cmlen = CMSG_SPACE(i * sizeof(int));
if (msg->msg_controllen < cmlen) if (msg->msg_controllen < cmlen)
cmlen = msg->msg_controllen; cmlen = msg->msg_controllen;
msg->msg_control += cmlen; msg->msg_control_user += cmlen;
msg->msg_controllen -= cmlen; msg->msg_controllen -= cmlen;
} }
} }
......
...@@ -2165,7 +2165,7 @@ static void tcp_zc_finalize_rx_tstamp(struct sock *sk, ...@@ -2165,7 +2165,7 @@ static void tcp_zc_finalize_rx_tstamp(struct sock *sk,
struct msghdr cmsg_dummy; struct msghdr cmsg_dummy;
msg_control_addr = (unsigned long)zc->msg_control; msg_control_addr = (unsigned long)zc->msg_control;
cmsg_dummy.msg_control = (void *)msg_control_addr; cmsg_dummy.msg_control_user = (void __user *)msg_control_addr;
cmsg_dummy.msg_controllen = cmsg_dummy.msg_controllen =
(__kernel_size_t)zc->msg_controllen; (__kernel_size_t)zc->msg_controllen;
cmsg_dummy.msg_flags = in_compat_syscall() cmsg_dummy.msg_flags = in_compat_syscall()
...@@ -2176,7 +2176,7 @@ static void tcp_zc_finalize_rx_tstamp(struct sock *sk, ...@@ -2176,7 +2176,7 @@ static void tcp_zc_finalize_rx_tstamp(struct sock *sk,
zc->msg_controllen == cmsg_dummy.msg_controllen) { zc->msg_controllen == cmsg_dummy.msg_controllen) {
tcp_recv_timestamp(&cmsg_dummy, sk, tss); tcp_recv_timestamp(&cmsg_dummy, sk, tss);
zc->msg_control = (__u64) zc->msg_control = (__u64)
((uintptr_t)cmsg_dummy.msg_control); ((uintptr_t)cmsg_dummy.msg_control_user);
zc->msg_controllen = zc->msg_controllen =
(__u64)cmsg_dummy.msg_controllen; (__u64)cmsg_dummy.msg_controllen;
zc->msg_flags = (__u32)cmsg_dummy.msg_flags; zc->msg_flags = (__u32)cmsg_dummy.msg_flags;
......
...@@ -716,6 +716,7 @@ int do_ipv6_setsockopt(struct sock *sk, int level, int optname, ...@@ -716,6 +716,7 @@ int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
goto done; goto done;
msg.msg_controllen = optlen; msg.msg_controllen = optlen;
msg.msg_control_is_user = false;
msg.msg_control = (void *)(opt+1); msg.msg_control = (void *)(opt+1);
ipc6.opt = opt; ipc6.opt = opt;
......
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