| 1 |
|
| 2 |
|
| 3 | #ifndef _LINUX_BPFPTR_H
|
| 4 | #define _LINUX_BPFPTR_H
|
| 5 |
|
| 6 | #include <linux/mm.h>
|
| 7 | #include <linux/sockptr.h>
|
| 8 |
|
| 9 | typedef sockptr_t bpfptr_t;
|
| 10 |
|
| 11 | static inline bool bpfptr_is_kernel(bpfptr_t bpfptr)
|
| 12 | {
|
| 13 | return bpfptr.is_kernel;
|
| 14 | }
|
| 15 |
|
| 16 | static inline bpfptr_t KERNEL_BPFPTR(void *p)
|
| 17 | {
|
| 18 | return (bpfptr_t) { .kernel = p, .is_kernel = true };
|
| 19 | }
|
| 20 |
|
| 21 | static inline bpfptr_t USER_BPFPTR(void __user *p)
|
| 22 | {
|
| 23 | return (bpfptr_t) { .user = p };
|
| 24 | }
|
| 25 |
|
| 26 | static inline bpfptr_t make_bpfptr(u64 addr, bool is_kernel)
|
| 27 | {
|
| 28 | if (is_kernel)
|
| 29 | return KERNEL_BPFPTR((void*) (uintptr_t) addr);
|
| 30 | else
|
| 31 | return USER_BPFPTR(u64_to_user_ptr(addr));
|
| 32 | }
|
| 33 |
|
| 34 | static inline bool bpfptr_is_null(bpfptr_t bpfptr)
|
| 35 | {
|
| 36 | if (bpfptr_is_kernel(bpfptr))
|
| 37 | return !bpfptr.kernel;
|
| 38 | return !bpfptr.user;
|
| 39 | }
|
| 40 |
|
| 41 | static inline void bpfptr_add(bpfptr_t *bpfptr, size_t val)
|
| 42 | {
|
| 43 | if (bpfptr_is_kernel(*bpfptr))
|
| 44 | bpfptr->kernel += val;
|
| 45 | else
|
| 46 | bpfptr->user += val;
|
| 47 | }
|
| 48 |
|
| 49 | static inline int copy_from_bpfptr_offset(void *dst, bpfptr_t src,
|
| 50 | size_t offset, size_t size)
|
| 51 | {
|
| 52 | if (!bpfptr_is_kernel(src))
|
| 53 | return copy_from_user(dst, src.user + offset, size);
|
| 54 | return copy_from_kernel_nofault(dst, src.kernel + offset, size);
|
| 55 | }
|
| 56 |
|
| 57 | static inline int copy_from_bpfptr(void *dst, bpfptr_t src, size_t size)
|
| 58 | {
|
| 59 | return copy_from_bpfptr_offset(dst, src, 0, size);
|
| 60 | }
|
| 61 |
|
| 62 | static inline int copy_to_bpfptr_offset(bpfptr_t dst, size_t offset,
|
| 63 | const void *src, size_t size)
|
| 64 | {
|
| 65 | return copy_to_sockptr_offset((sockptr_t) dst, offset, src, size);
|
| 66 | }
|
| 67 |
|
| 68 | static inline void *kvmemdup_bpfptr_noprof(bpfptr_t src, size_t len)
|
| 69 | {
|
| 70 | void *p = kvmalloc_node_align_noprof(len, 1, GFP_USER | __GFP_NOWARN, NUMA_NO_NODE);
|
| 71 |
|
| 72 | if (!p)
|
| 73 | return ERR_PTR(-ENOMEM);
|
| 74 | if (copy_from_bpfptr(p, src, len)) {
|
| 75 | kvfree(p);
|
| 76 | return ERR_PTR(-EFAULT);
|
| 77 | }
|
| 78 | return p;
|
| 79 | }
|
| 80 | #define kvmemdup_bpfptr(...) alloc_hooks(kvmemdup_bpfptr_noprof(__VA_ARGS__))
|
| 81 |
|
| 82 | static inline long strncpy_from_bpfptr(char *dst, bpfptr_t src, size_t count)
|
| 83 | {
|
| 84 | if (bpfptr_is_kernel(src))
|
| 85 | return strncpy_from_kernel_nofault(dst, src.kernel, count);
|
| 86 | return strncpy_from_user(dst, src.user, count);
|
| 87 | }
|
| 88 |
|
| 89 | #endif
|