bpf-helper.h 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. /*
  3. * Example wrapper around BPF macros.
  4. *
  5. * Copyright (c) 2012 The Chromium OS Authors <chromium-os-dev@chromium.org>
  6. * Author: Will Drewry <wad@chromium.org>
  7. *
  8. * The code may be used by anyone for any purpose,
  9. * and can serve as a starting point for developing
  10. * applications using prctl(PR_SET_SECCOMP, 2, ...).
  11. *
  12. * No guarantees are provided with respect to the correctness
  13. * or functionality of this code.
  14. */
  15. #ifndef __BPF_HELPER_H__
  16. #define __BPF_HELPER_H__
  17. #include <asm/bitsperlong.h> /* for __BITS_PER_LONG */
  18. #include <endian.h>
  19. #include <linux/filter.h>
  20. #include <linux/seccomp.h> /* for seccomp_data */
  21. #include <linux/types.h>
  22. #include <linux/unistd.h>
  23. #include <stddef.h>
  24. #define BPF_LABELS_MAX 256
  25. struct bpf_labels {
  26. int count;
  27. struct __bpf_label {
  28. const char *label;
  29. __u32 location;
  30. } labels[BPF_LABELS_MAX];
  31. };
  32. int bpf_resolve_jumps(struct bpf_labels *labels,
  33. struct sock_filter *filter, size_t count);
  34. __u32 seccomp_bpf_label(struct bpf_labels *labels, const char *label);
  35. void seccomp_bpf_print(struct sock_filter *filter, size_t count);
  36. #define JUMP_JT 0xff
  37. #define JUMP_JF 0xff
  38. #define LABEL_JT 0xfe
  39. #define LABEL_JF 0xfe
  40. #define ALLOW \
  41. BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW)
  42. #define DENY \
  43. BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL)
  44. #define JUMP(labels, label) \
  45. BPF_JUMP(BPF_JMP+BPF_JA, FIND_LABEL((labels), (label)), \
  46. JUMP_JT, JUMP_JF)
  47. #define LABEL(labels, label) \
  48. BPF_JUMP(BPF_JMP+BPF_JA, FIND_LABEL((labels), (label)), \
  49. LABEL_JT, LABEL_JF)
  50. #define SYSCALL(nr, jt) \
  51. BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (nr), 0, 1), \
  52. jt
  53. /* Lame, but just an example */
  54. #define FIND_LABEL(labels, label) seccomp_bpf_label((labels), #label)
  55. #define EXPAND(...) __VA_ARGS__
  56. /* Ensure that we load the logically correct offset. */
  57. #if __BYTE_ORDER == __LITTLE_ENDIAN
  58. #define LO_ARG(idx) offsetof(struct seccomp_data, args[(idx)])
  59. #elif __BYTE_ORDER == __BIG_ENDIAN
  60. #define LO_ARG(idx) offsetof(struct seccomp_data, args[(idx)]) + sizeof(__u32)
  61. #else
  62. #error "Unknown endianness"
  63. #endif
  64. /* Map all width-sensitive operations */
  65. #if __BITS_PER_LONG == 32
  66. #define JEQ(x, jt) JEQ32(x, EXPAND(jt))
  67. #define JNE(x, jt) JNE32(x, EXPAND(jt))
  68. #define JGT(x, jt) JGT32(x, EXPAND(jt))
  69. #define JLT(x, jt) JLT32(x, EXPAND(jt))
  70. #define JGE(x, jt) JGE32(x, EXPAND(jt))
  71. #define JLE(x, jt) JLE32(x, EXPAND(jt))
  72. #define JA(x, jt) JA32(x, EXPAND(jt))
  73. #define ARG(i) ARG_32(i)
  74. #elif __BITS_PER_LONG == 64
  75. /* Ensure that we load the logically correct offset. */
  76. #if __BYTE_ORDER == __LITTLE_ENDIAN
  77. #define ENDIAN(_lo, _hi) _lo, _hi
  78. #define HI_ARG(idx) offsetof(struct seccomp_data, args[(idx)]) + sizeof(__u32)
  79. #elif __BYTE_ORDER == __BIG_ENDIAN
  80. #define ENDIAN(_lo, _hi) _hi, _lo
  81. #define HI_ARG(idx) offsetof(struct seccomp_data, args[(idx)])
  82. #endif
  83. union arg64 {
  84. struct {
  85. __u32 ENDIAN(lo32, hi32);
  86. };
  87. __u64 u64;
  88. };
  89. #define JEQ(x, jt) \
  90. JEQ64(((union arg64){.u64 = (x)}).lo32, \
  91. ((union arg64){.u64 = (x)}).hi32, \
  92. EXPAND(jt))
  93. #define JGT(x, jt) \
  94. JGT64(((union arg64){.u64 = (x)}).lo32, \
  95. ((union arg64){.u64 = (x)}).hi32, \
  96. EXPAND(jt))
  97. #define JGE(x, jt) \
  98. JGE64(((union arg64){.u64 = (x)}).lo32, \
  99. ((union arg64){.u64 = (x)}).hi32, \
  100. EXPAND(jt))
  101. #define JNE(x, jt) \
  102. JNE64(((union arg64){.u64 = (x)}).lo32, \
  103. ((union arg64){.u64 = (x)}).hi32, \
  104. EXPAND(jt))
  105. #define JLT(x, jt) \
  106. JLT64(((union arg64){.u64 = (x)}).lo32, \
  107. ((union arg64){.u64 = (x)}).hi32, \
  108. EXPAND(jt))
  109. #define JLE(x, jt) \
  110. JLE64(((union arg64){.u64 = (x)}).lo32, \
  111. ((union arg64){.u64 = (x)}).hi32, \
  112. EXPAND(jt))
  113. #define JA(x, jt) \
  114. JA64(((union arg64){.u64 = (x)}).lo32, \
  115. ((union arg64){.u64 = (x)}).hi32, \
  116. EXPAND(jt))
  117. #define ARG(i) ARG_64(i)
  118. #else
  119. #error __BITS_PER_LONG value unusable.
  120. #endif
  121. /* Loads the arg into A */
  122. #define ARG_32(idx) \
  123. BPF_STMT(BPF_LD+BPF_W+BPF_ABS, LO_ARG(idx))
  124. /* Loads lo into M[0] and hi into M[1] and A */
  125. #define ARG_64(idx) \
  126. BPF_STMT(BPF_LD+BPF_W+BPF_ABS, LO_ARG(idx)), \
  127. BPF_STMT(BPF_ST, 0), /* lo -> M[0] */ \
  128. BPF_STMT(BPF_LD+BPF_W+BPF_ABS, HI_ARG(idx)), \
  129. BPF_STMT(BPF_ST, 1) /* hi -> M[1] */
  130. #define JEQ32(value, jt) \
  131. BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (value), 0, 1), \
  132. jt
  133. #define JNE32(value, jt) \
  134. BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (value), 1, 0), \
  135. jt
  136. #define JA32(value, jt) \
  137. BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, (value), 0, 1), \
  138. jt
  139. #define JGE32(value, jt) \
  140. BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (value), 0, 1), \
  141. jt
  142. #define JGT32(value, jt) \
  143. BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (value), 0, 1), \
  144. jt
  145. #define JLE32(value, jt) \
  146. BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (value), 1, 0), \
  147. jt
  148. #define JLT32(value, jt) \
  149. BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (value), 1, 0), \
  150. jt
  151. /*
  152. * All the JXX64 checks assume lo is saved in M[0] and hi is saved in both
  153. * A and M[1]. This invariant is kept by restoring A if necessary.
  154. */
  155. #define JEQ64(lo, hi, jt) \
  156. /* if (hi != arg.hi) goto NOMATCH; */ \
  157. BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 5), \
  158. BPF_STMT(BPF_LD+BPF_MEM, 0), /* swap in lo */ \
  159. /* if (lo != arg.lo) goto NOMATCH; */ \
  160. BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (lo), 0, 2), \
  161. BPF_STMT(BPF_LD+BPF_MEM, 1), \
  162. jt, \
  163. BPF_STMT(BPF_LD+BPF_MEM, 1)
  164. #define JNE64(lo, hi, jt) \
  165. /* if (hi != arg.hi) goto MATCH; */ \
  166. BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 3), \
  167. BPF_STMT(BPF_LD+BPF_MEM, 0), \
  168. /* if (lo != arg.lo) goto MATCH; */ \
  169. BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (lo), 2, 0), \
  170. BPF_STMT(BPF_LD+BPF_MEM, 1), \
  171. jt, \
  172. BPF_STMT(BPF_LD+BPF_MEM, 1)
  173. #define JA64(lo, hi, jt) \
  174. /* if (hi & arg.hi) goto MATCH; */ \
  175. BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, (hi), 3, 0), \
  176. BPF_STMT(BPF_LD+BPF_MEM, 0), \
  177. /* if (lo & arg.lo) goto MATCH; */ \
  178. BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, (lo), 0, 2), \
  179. BPF_STMT(BPF_LD+BPF_MEM, 1), \
  180. jt, \
  181. BPF_STMT(BPF_LD+BPF_MEM, 1)
  182. #define JGE64(lo, hi, jt) \
  183. /* if (hi > arg.hi) goto MATCH; */ \
  184. BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (hi), 4, 0), \
  185. /* if (hi != arg.hi) goto NOMATCH; */ \
  186. BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 5), \
  187. BPF_STMT(BPF_LD+BPF_MEM, 0), \
  188. /* if (lo >= arg.lo) goto MATCH; */ \
  189. BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (lo), 0, 2), \
  190. BPF_STMT(BPF_LD+BPF_MEM, 1), \
  191. jt, \
  192. BPF_STMT(BPF_LD+BPF_MEM, 1)
  193. #define JGT64(lo, hi, jt) \
  194. /* if (hi > arg.hi) goto MATCH; */ \
  195. BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (hi), 4, 0), \
  196. /* if (hi != arg.hi) goto NOMATCH; */ \
  197. BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 5), \
  198. BPF_STMT(BPF_LD+BPF_MEM, 0), \
  199. /* if (lo > arg.lo) goto MATCH; */ \
  200. BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (lo), 0, 2), \
  201. BPF_STMT(BPF_LD+BPF_MEM, 1), \
  202. jt, \
  203. BPF_STMT(BPF_LD+BPF_MEM, 1)
  204. #define JLE64(lo, hi, jt) \
  205. /* if (hi < arg.hi) goto MATCH; */ \
  206. BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (hi), 0, 4), \
  207. /* if (hi != arg.hi) goto NOMATCH; */ \
  208. BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 5), \
  209. BPF_STMT(BPF_LD+BPF_MEM, 0), \
  210. /* if (lo <= arg.lo) goto MATCH; */ \
  211. BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (lo), 2, 0), \
  212. BPF_STMT(BPF_LD+BPF_MEM, 1), \
  213. jt, \
  214. BPF_STMT(BPF_LD+BPF_MEM, 1)
  215. #define JLT64(lo, hi, jt) \
  216. /* if (hi < arg.hi) goto MATCH; */ \
  217. BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (hi), 0, 4), \
  218. /* if (hi != arg.hi) goto NOMATCH; */ \
  219. BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 5), \
  220. BPF_STMT(BPF_LD+BPF_MEM, 0), \
  221. /* if (lo < arg.lo) goto MATCH; */ \
  222. BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (lo), 2, 0), \
  223. BPF_STMT(BPF_LD+BPF_MEM, 1), \
  224. jt, \
  225. BPF_STMT(BPF_LD+BPF_MEM, 1)
  226. #define LOAD_SYSCALL_NR \
  227. BPF_STMT(BPF_LD+BPF_W+BPF_ABS, \
  228. offsetof(struct seccomp_data, nr))
  229. #endif /* __BPF_HELPER_H__ */