Skip to content

Commit c11d2e7

Browse files
committed
Merge branch 'msg_control-split'
Kevin Brodsky says: ==================== net: Finish up ->msg_control{,_user} split Commit 1f466e1 ("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: David S. Miller <[email protected]>
2 parents eaaa4e9 + b6d85cf commit c11d2e7

File tree

4 files changed

+16
-11
lines changed

4 files changed

+16
-11
lines changed

net/compat.c

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ int get_compat_msghdr(struct msghdr *kmsg,
113113

114114
#define CMSG_COMPAT_FIRSTHDR(msg) \
115115
(((msg)->msg_controllen) >= sizeof(struct compat_cmsghdr) ? \
116-
(struct compat_cmsghdr __user *)((msg)->msg_control) : \
116+
(struct compat_cmsghdr __user *)((msg)->msg_control_user) : \
117117
(struct compat_cmsghdr __user *)NULL)
118118

119119
#define CMSG_COMPAT_OK(ucmlen, ucmsg, mhdr) \
@@ -126,7 +126,7 @@ static inline struct compat_cmsghdr __user *cmsg_compat_nxthdr(struct msghdr *ms
126126
struct compat_cmsghdr __user *cmsg, int cmsg_len)
127127
{
128128
char __user *ptr = (char __user *)cmsg + CMSG_COMPAT_ALIGN(cmsg_len);
129-
if ((unsigned long)(ptr + 1 - (char __user *)msg->msg_control) >
129+
if ((unsigned long)(ptr + 1 - (char __user *)msg->msg_control_user) >
130130
msg->msg_controllen)
131131
return NULL;
132132
return (struct compat_cmsghdr __user *)ptr;
@@ -211,6 +211,7 @@ int cmsghdr_from_user_compat_to_kern(struct msghdr *kmsg, struct sock *sk,
211211
goto Einval;
212212

213213
/* Ok, looks like we made it. Hook it up and return success. */
214+
kmsg->msg_control_is_user = false;
214215
kmsg->msg_control = kcmsg_base;
215216
kmsg->msg_controllen = kcmlen;
216217
return 0;
@@ -225,7 +226,7 @@ int cmsghdr_from_user_compat_to_kern(struct msghdr *kmsg, struct sock *sk,
225226

226227
int put_cmsg_compat(struct msghdr *kmsg, int level, int type, int len, void *data)
227228
{
228-
struct compat_cmsghdr __user *cm = (struct compat_cmsghdr __user *) kmsg->msg_control;
229+
struct compat_cmsghdr __user *cm = (struct compat_cmsghdr __user *) kmsg->msg_control_user;
229230
struct compat_cmsghdr cmhdr;
230231
struct old_timeval32 ctv;
231232
struct old_timespec32 cts[3];
@@ -274,7 +275,7 @@ int put_cmsg_compat(struct msghdr *kmsg, int level, int type, int len, void *dat
274275
cmlen = CMSG_COMPAT_SPACE(len);
275276
if (kmsg->msg_controllen < cmlen)
276277
cmlen = kmsg->msg_controllen;
277-
kmsg->msg_control += cmlen;
278+
kmsg->msg_control_user += cmlen;
278279
kmsg->msg_controllen -= cmlen;
279280
return 0;
280281
}
@@ -289,7 +290,7 @@ static int scm_max_fds_compat(struct msghdr *msg)
289290
void scm_detach_fds_compat(struct msghdr *msg, struct scm_cookie *scm)
290291
{
291292
struct compat_cmsghdr __user *cm =
292-
(struct compat_cmsghdr __user *)msg->msg_control;
293+
(struct compat_cmsghdr __user *)msg->msg_control_user;
293294
unsigned int o_flags = (msg->msg_flags & MSG_CMSG_CLOEXEC) ? O_CLOEXEC : 0;
294295
int fdmax = min_t(int, scm_max_fds_compat(msg), scm->fp->count);
295296
int __user *cmsg_data = CMSG_COMPAT_DATA(cm);
@@ -313,7 +314,7 @@ void scm_detach_fds_compat(struct msghdr *msg, struct scm_cookie *scm)
313314
cmlen = CMSG_COMPAT_SPACE(i * sizeof(int));
314315
if (msg->msg_controllen < cmlen)
315316
cmlen = msg->msg_controllen;
316-
msg->msg_control += cmlen;
317+
msg->msg_control_user += cmlen;
317318
msg->msg_controllen -= cmlen;
318319
}
319320
}

net/core/scm.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,10 @@ int put_cmsg(struct msghdr * msg, int level, int type, int len, void *data)
250250
}
251251

252252
cmlen = min(CMSG_SPACE(len), msg->msg_controllen);
253-
msg->msg_control += cmlen;
253+
if (msg->msg_control_is_user)
254+
msg->msg_control_user += cmlen;
255+
else
256+
msg->msg_control += cmlen;
254257
msg->msg_controllen -= cmlen;
255258
return 0;
256259

@@ -299,7 +302,7 @@ static int scm_max_fds(struct msghdr *msg)
299302
void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm)
300303
{
301304
struct cmsghdr __user *cm =
302-
(__force struct cmsghdr __user *)msg->msg_control;
305+
(__force struct cmsghdr __user *)msg->msg_control_user;
303306
unsigned int o_flags = (msg->msg_flags & MSG_CMSG_CLOEXEC) ? O_CLOEXEC : 0;
304307
int fdmax = min_t(int, scm_max_fds(msg), scm->fp->count);
305308
int __user *cmsg_data = CMSG_USER_DATA(cm);
@@ -332,7 +335,7 @@ void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm)
332335
cmlen = CMSG_SPACE(i * sizeof(int));
333336
if (msg->msg_controllen < cmlen)
334337
cmlen = msg->msg_controllen;
335-
msg->msg_control += cmlen;
338+
msg->msg_control_user += cmlen;
336339
msg->msg_controllen -= cmlen;
337340
}
338341
}

net/ipv4/tcp.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2165,7 +2165,7 @@ static void tcp_zc_finalize_rx_tstamp(struct sock *sk,
21652165
struct msghdr cmsg_dummy;
21662166

21672167
msg_control_addr = (unsigned long)zc->msg_control;
2168-
cmsg_dummy.msg_control = (void *)msg_control_addr;
2168+
cmsg_dummy.msg_control_user = (void __user *)msg_control_addr;
21692169
cmsg_dummy.msg_controllen =
21702170
(__kernel_size_t)zc->msg_controllen;
21712171
cmsg_dummy.msg_flags = in_compat_syscall()
@@ -2176,7 +2176,7 @@ static void tcp_zc_finalize_rx_tstamp(struct sock *sk,
21762176
zc->msg_controllen == cmsg_dummy.msg_controllen) {
21772177
tcp_recv_timestamp(&cmsg_dummy, sk, tss);
21782178
zc->msg_control = (__u64)
2179-
((uintptr_t)cmsg_dummy.msg_control);
2179+
((uintptr_t)cmsg_dummy.msg_control_user);
21802180
zc->msg_controllen =
21812181
(__u64)cmsg_dummy.msg_controllen;
21822182
zc->msg_flags = (__u32)cmsg_dummy.msg_flags;

net/ipv6/ipv6_sockglue.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -716,6 +716,7 @@ int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
716716
goto done;
717717

718718
msg.msg_controllen = optlen;
719+
msg.msg_control_is_user = false;
719720
msg.msg_control = (void *)(opt+1);
720721
ipc6.opt = opt;
721722

0 commit comments

Comments
 (0)