Skip to content

Commit a31edb2

Browse files
Christoph Hellwigdavem330
authored andcommitted
net: improve the user pointer check in init_user_sockptr
Make sure not just the pointer itself but the whole range lies in the user address space. For that pass the length and then use the access_ok helper to do the check. Fixes: 6d04fe1 ("net: optimize the sockptr_t for unified kernel/user address spaces") Reported-by: David Laight <[email protected]> Signed-off-by: Christoph Hellwig <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent d3c4815 commit a31edb2

File tree

3 files changed

+8
-14
lines changed

3 files changed

+8
-14
lines changed

include/linux/sockptr.h

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,6 @@ static inline sockptr_t KERNEL_SOCKPTR(void *p)
2727
{
2828
return (sockptr_t) { .kernel = p };
2929
}
30-
31-
static inline int __must_check init_user_sockptr(sockptr_t *sp, void __user *p)
32-
{
33-
if ((unsigned long)p >= TASK_SIZE)
34-
return -EFAULT;
35-
sp->user = p;
36-
return 0;
37-
}
3830
#else /* CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE */
3931
typedef struct {
4032
union {
@@ -53,14 +45,16 @@ static inline sockptr_t KERNEL_SOCKPTR(void *p)
5345
{
5446
return (sockptr_t) { .kernel = p, .is_kernel = true };
5547
}
48+
#endif /* CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE */
5649

57-
static inline int __must_check init_user_sockptr(sockptr_t *sp, void __user *p)
50+
static inline int __must_check init_user_sockptr(sockptr_t *sp, void __user *p,
51+
size_t size)
5852
{
59-
sp->user = p;
60-
sp->is_kernel = false;
53+
if (!access_ok(p, size))
54+
return -EFAULT;
55+
*sp = (sockptr_t) { .user = p };
6156
return 0;
6257
}
63-
#endif /* CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE */
6458

6559
static inline bool sockptr_is_null(sockptr_t sockptr)
6660
{

net/ipv4/bpfilter/sockopt.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ int bpfilter_ip_get_sockopt(struct sock *sk, int optname,
6565

6666
if (get_user(len, optlen))
6767
return -EFAULT;
68-
err = init_user_sockptr(&optval, user_optval);
68+
err = init_user_sockptr(&optval, user_optval, len);
6969
if (err)
7070
return err;
7171
return bpfilter_mbox_request(sk, optname, optval, len, false);

net/socket.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2105,7 +2105,7 @@ int __sys_setsockopt(int fd, int level, int optname, char __user *user_optval,
21052105
if (optlen < 0)
21062106
return -EINVAL;
21072107

2108-
err = init_user_sockptr(&optval, user_optval);
2108+
err = init_user_sockptr(&optval, user_optval, optlen);
21092109
if (err)
21102110
return err;
21112111

0 commit comments

Comments
 (0)