bpfptr.h 2.0 KB

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