Commit a31edb20 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by David S. Miller

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: 6d04fe15 ("net: optimize the sockptr_t for unified kernel/user address spaces")
Reported-by: default avatarDavid Laight <David.Laight@ACULAB.COM>
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent d3c48151
...@@ -27,14 +27,6 @@ static inline sockptr_t KERNEL_SOCKPTR(void *p) ...@@ -27,14 +27,6 @@ static inline sockptr_t KERNEL_SOCKPTR(void *p)
{ {
return (sockptr_t) { .kernel = 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 */ #else /* CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE */
typedef struct { typedef struct {
union { union {
...@@ -53,14 +45,16 @@ static inline sockptr_t KERNEL_SOCKPTR(void *p) ...@@ -53,14 +45,16 @@ static inline sockptr_t KERNEL_SOCKPTR(void *p)
{ {
return (sockptr_t) { .kernel = p, .is_kernel = true }; 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; if (!access_ok(p, size))
sp->is_kernel = false; return -EFAULT;
*sp = (sockptr_t) { .user = p };
return 0; return 0;
} }
#endif /* CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE */
static inline bool sockptr_is_null(sockptr_t sockptr) static inline bool sockptr_is_null(sockptr_t sockptr)
{ {
......
...@@ -65,7 +65,7 @@ int bpfilter_ip_get_sockopt(struct sock *sk, int optname, ...@@ -65,7 +65,7 @@ int bpfilter_ip_get_sockopt(struct sock *sk, int optname,
if (get_user(len, optlen)) if (get_user(len, optlen))
return -EFAULT; return -EFAULT;
err = init_user_sockptr(&optval, user_optval); err = init_user_sockptr(&optval, user_optval, len);
if (err) if (err)
return err; return err;
return bpfilter_mbox_request(sk, optname, optval, len, false); return bpfilter_mbox_request(sk, optname, optval, len, false);
......
...@@ -2105,7 +2105,7 @@ int __sys_setsockopt(int fd, int level, int optname, char __user *user_optval, ...@@ -2105,7 +2105,7 @@ int __sys_setsockopt(int fd, int level, int optname, char __user *user_optval,
if (optlen < 0) if (optlen < 0)
return -EINVAL; return -EINVAL;
err = init_user_sockptr(&optval, user_optval); err = init_user_sockptr(&optval, user_optval, optlen);
if (err) if (err)
return err; return err;
......
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