bpf-helper.h 7.1 KB

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