Skip to content

Commit c39ef21

Browse files
kevin-brodsky-armdavem330
authored andcommitted
net: Ensure ->msg_control_user is used for user buffers
Since commit 1f466e1 ("net: cleanly handle kernel vs user buffers for ->msg_control"), pointers to user buffers should be stored in struct msghdr::msg_control_user, instead of the msg_control field. Most users of msg_control have already been converted (where user buffers are involved), but not all of them. This patch attempts to address the remaining cases. An exception is made for null checks, as it should be safe to use msg_control unconditionally for that purpose. Cc: Christoph Hellwig <hch@lst.de> Cc: Eric Dumazet <edumazet@google.com> Cc: "David S. Miller" <davem@davemloft.net> Cc: Jakub Kicinski <kuba@kernel.org> Signed-off-by: Kevin Brodsky <kevin.brodsky@arm.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent eaaa4e9 commit c39ef21

File tree

3 files changed

+14
-11
lines changed

3 files changed

+14
-11
lines changed

net/compat.c

Lines changed: 6 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;
@@ -225,7 +225,7 @@ int cmsghdr_from_user_compat_to_kern(struct msghdr *kmsg, struct sock *sk,
225225

226226
int put_cmsg_compat(struct msghdr *kmsg, int level, int type, int len, void *data)
227227
{
228-
struct compat_cmsghdr __user *cm = (struct compat_cmsghdr __user *) kmsg->msg_control;
228+
struct compat_cmsghdr __user *cm = (struct compat_cmsghdr __user *) kmsg->msg_control_user;
229229
struct compat_cmsghdr cmhdr;
230230
struct old_timeval32 ctv;
231231
struct old_timespec32 cts[3];
@@ -274,7 +274,7 @@ int put_cmsg_compat(struct msghdr *kmsg, int level, int type, int len, void *dat
274274
cmlen = CMSG_COMPAT_SPACE(len);
275275
if (kmsg->msg_controllen < cmlen)
276276
cmlen = kmsg->msg_controllen;
277-
kmsg->msg_control += cmlen;
277+
kmsg->msg_control_user += cmlen;
278278
kmsg->msg_controllen -= cmlen;
279279
return 0;
280280
}
@@ -289,7 +289,7 @@ static int scm_max_fds_compat(struct msghdr *msg)
289289
void scm_detach_fds_compat(struct msghdr *msg, struct scm_cookie *scm)
290290
{
291291
struct compat_cmsghdr __user *cm =
292-
(struct compat_cmsghdr __user *)msg->msg_control;
292+
(struct compat_cmsghdr __user *)msg->msg_control_user;
293293
unsigned int o_flags = (msg->msg_flags & MSG_CMSG_CLOEXEC) ? O_CLOEXEC : 0;
294294
int fdmax = min_t(int, scm_max_fds_compat(msg), scm->fp->count);
295295
int __user *cmsg_data = CMSG_COMPAT_DATA(cm);
@@ -313,7 +313,7 @@ void scm_detach_fds_compat(struct msghdr *msg, struct scm_cookie *scm)
313313
cmlen = CMSG_COMPAT_SPACE(i * sizeof(int));
314314
if (msg->msg_controllen < cmlen)
315315
cmlen = msg->msg_controllen;
316-
msg->msg_control += cmlen;
316+
msg->msg_control_user += cmlen;
317317
msg->msg_controllen -= cmlen;
318318
}
319319
}

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;

0 commit comments

Comments
 (0)