diff options
author | David S. Miller <davem@davemloft.net> | 2020-07-28 13:43:40 -0700 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2020-07-28 13:43:40 -0700 |
commit | 0003041e7a0bf24594e5d66fe217bbbefdac44ab (patch) | |
tree | 050f16554295c22db098bb4e81021e21d2718c5f /include/linux/sockptr.h | |
parent | Merge branch 'mlxsw-Add-support-for-QSFP-DD-transceiver-type' (diff) | |
parent | net: improve the user pointer check in init_user_sockptr (diff) | |
download | wireguard-linux-0003041e7a0bf24594e5d66fe217bbbefdac44ab.tar.xz wireguard-linux-0003041e7a0bf24594e5d66fe217bbbefdac44ab.zip |
Merge branch 'sockptr_t-fixes-v2'
Christoph Hellwig says:
====================
sockptr_t fixes v2
a bunch of fixes for the sockptr_t conversion
Changes since v1:
- fix a user pointer dereference braino in bpfilter
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include/linux/sockptr.h')
-rw-r--r-- | include/linux/sockptr.h | 49 |
1 files changed, 22 insertions, 27 deletions
diff --git a/include/linux/sockptr.h b/include/linux/sockptr.h index 7d5cdb2b30b5..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,33 +45,44 @@ 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) { - return !sockptr.user && !sockptr.kernel; + if (sockptr_is_kernel(sockptr)) + return !sockptr.kernel; + return !sockptr.user; } -static inline int copy_from_sockptr(void *dst, sockptr_t src, size_t size) +static inline int copy_from_sockptr_offset(void *dst, sockptr_t src, + size_t offset, size_t size) { if (!sockptr_is_kernel(src)) - return copy_from_user(dst, src.user, size); - memcpy(dst, src.kernel, size); + return copy_from_user(dst, src.user + offset, size); + memcpy(dst, src.kernel + offset, size); return 0; } -static inline int copy_to_sockptr(sockptr_t dst, const void *src, size_t size) +static inline int copy_from_sockptr(void *dst, sockptr_t src, size_t size) +{ + return copy_from_sockptr_offset(dst, src, 0, size); +} + +static inline int copy_to_sockptr_offset(sockptr_t dst, size_t offset, + const void *src, size_t size) { if (!sockptr_is_kernel(dst)) - return copy_to_user(dst.user, src, size); - memcpy(dst.kernel, src, size); + return copy_to_user(dst.user + offset, src, size); + memcpy(dst.kernel + offset, src, size); return 0; } @@ -110,14 +113,6 @@ static inline void *memdup_sockptr_nul(sockptr_t src, size_t len) return p; } -static inline void sockptr_advance(sockptr_t sockptr, size_t len) -{ - if (sockptr_is_kernel(sockptr)) - sockptr.kernel += len; - else - sockptr.user += len; -} - static inline long strncpy_from_sockptr(char *dst, sockptr_t src, size_t count) { if (sockptr_is_kernel(src)) { |