aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/include/linux/sockptr.h
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2020-07-28 18:38:36 +0200
committerDavid S. Miller <davem@davemloft.net>2020-07-28 13:43:40 -0700
commita31edb2059ed4e498f9aa8230c734b59d0ad797a (patch)
tree050f16554295c22db098bb4e81021e21d2718c5f /include/linux/sockptr.h
parentnet: remove sockptr_advance (diff)
downloadwireguard-linux-a31edb2059ed4e498f9aa8230c734b59d0ad797a.tar.xz
wireguard-linux-a31edb2059ed4e498f9aa8230c734b59d0ad797a.zip
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: 6d04fe15f78a ("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>
Diffstat (limited to 'include/linux/sockptr.h')
-rw-r--r--include/linux/sockptr.h18
1 files changed, 6 insertions, 12 deletions
diff --git a/include/linux/sockptr.h b/include/linux/sockptr.h
index 9e6c81d474cb..96840def9d69 100644
--- a/include/linux/sockptr.h
+++ b/include/linux/sockptr.h
@@ -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 {
@@ -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)
{