1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 /* A pointer that can point to either kernel or userspace memory. */ 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 return copy_from_sockptr_offset(dst, (sockptr_t) src, offset, size); 53 } 54 55 static inline int copy_from_bpfptr(void *dst, bpfptr_t src, size_t size) 56 { 57 return copy_from_bpfptr_offset(dst, src, 0, size); 58 } 59 60 static inline int copy_to_bpfptr_offset(bpfptr_t dst, size_t offset, 61 const void *src, size_t size) 62 { 63 return copy_to_sockptr_offset((sockptr_t) dst, offset, src, size); 64 } 65 66 static inline void *kvmemdup_bpfptr(bpfptr_t src, size_t len) 67 { 68 void *p = kvmalloc(len, GFP_USER | __GFP_NOWARN); 69 70 if (!p) 71 return ERR_PTR(-ENOMEM); 72 if (copy_from_bpfptr(p, src, len)) { 73 kvfree(p); 74 return ERR_PTR(-EFAULT); 75 } 76 return p; 77 } 78 79 static inline long strncpy_from_bpfptr(char *dst, bpfptr_t src, size_t count) 80 { 81 return strncpy_from_sockptr(dst, (sockptr_t) src, count); 82 } 83 84 #endif /* _LINUX_BPFPTR_H */ 85