Skip to content

Commit

Permalink
net: improve the user pointer check in init_user_sockptr
Browse files Browse the repository at this point in the history
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 <David.Laight@ACULAB.COM>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Christoph Hellwig authored and davem330 committed Jul 28, 2020
1 parent d3c4815 commit a31edb2
Show file tree
Hide file tree
Showing 3 changed files with 8 additions and 14 deletions.
18 changes: 6 additions & 12 deletions include/linux/sockptr.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,6 @@ static inline sockptr_t KERNEL_SOCKPTR(void *p)
{
return (sockptr_t) { .kernel = p };
}

static inline int __must_check init_user_sockptr(sockptr_t *sp, void __user *p)
{
if ((unsigned long)p >= TASK_SIZE)
return -EFAULT;
sp->user = p;
return 0;
}
#else /* CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE */
typedef struct {
union {
Expand All @@ -53,14 +45,16 @@ static inline sockptr_t KERNEL_SOCKPTR(void *p)
{
return (sockptr_t) { .kernel = p, .is_kernel = true };
}
#endif /* CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE */

static inline int __must_check init_user_sockptr(sockptr_t *sp, void __user *p)
static inline int __must_check init_user_sockptr(sockptr_t *sp, void __user *p,
size_t size)
{
sp->user = p;
sp->is_kernel = false;
if (!access_ok(p, size))
return -EFAULT;
*sp = (sockptr_t) { .user = p };
return 0;
}
#endif /* CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE */

static inline bool sockptr_is_null(sockptr_t sockptr)
{
Expand Down
2 changes: 1 addition & 1 deletion net/ipv4/bpfilter/sockopt.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ int bpfilter_ip_get_sockopt(struct sock *sk, int optname,

if (get_user(len, optlen))
return -EFAULT;
err = init_user_sockptr(&optval, user_optval);
err = init_user_sockptr(&optval, user_optval, len);
if (err)
return err;
return bpfilter_mbox_request(sk, optname, optval, len, false);
Expand Down
2 changes: 1 addition & 1 deletion net/socket.c
Original file line number Diff line number Diff line change
Expand Up @@ -2105,7 +2105,7 @@ int __sys_setsockopt(int fd, int level, int optname, char __user *user_optval,
if (optlen < 0)
return -EINVAL;

err = init_user_sockptr(&optval, user_optval);
err = init_user_sockptr(&optval, user_optval, optlen);
if (err)
return err;

Expand Down

0 comments on commit a31edb2

Please sign in to comment.