bpfptr.h (1891B)
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 9typedef sockptr_t bpfptr_t; 10 11static inline bool bpfptr_is_kernel(bpfptr_t bpfptr) 12{ 13 return bpfptr.is_kernel; 14} 15 16static inline bpfptr_t KERNEL_BPFPTR(void *p) 17{ 18 return (bpfptr_t) { .kernel = p, .is_kernel = true }; 19} 20 21static inline bpfptr_t USER_BPFPTR(void __user *p) 22{ 23 return (bpfptr_t) { .user = p }; 24} 25 26static 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 34static 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 41static 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 49static 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 55static 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 60static 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 66static 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 79static 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 */