ebpf.rs 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491
  1. // Copyright 2016 6WIND S.A. <quentin.monnet@6wind.com>
  2. //
  3. // Licensed under the Apache License, Version 2.0 <http://www.apache.org/licenses/LICENSE-2.0> or
  4. // the MIT license <http://opensource.org/licenses/MIT>, at your option. This file may not be
  5. // copied, modified, or distributed except according to those terms.
  6. //! This module contains all the definitions related to eBPF.
  7. //!
  8. //! The number of bytes in an instruction, the maximum number of instructions in a program, and
  9. //! also all operation codes are defined here as constants.
  10. //!
  11. //! The structure for an instruction used by this crate, as well as the function to extract it from
  12. //! a program, is also defined in the module.
  13. //!
  14. //! To learn more about these instructions, see the Linux kernel documentation:
  15. //! <https://www.kernel.org/doc/Documentation/networking/filter.txt>, or for a shorter version of
  16. //! the list of the operation codes: <https://github.com/iovisor/bpf-docs/blob/master/eBPF.md>
  17. /// Maximum number of instructions in an eBPF program.
  18. pub const PROG_MAX_INSNS: usize = 4096;
  19. /// Size of an eBPF instructions, in bytes.
  20. pub const INSN_SIZE: usize = 8;
  21. /// Maximum size of an eBPF program, in bytes.
  22. pub const PROG_MAX_SIZE: usize = PROG_MAX_INSNS * INSN_SIZE;
  23. /// Stack for the eBPF stack, in bytes.
  24. pub const STACK_SIZE: usize = 512;
  25. // eBPF op codes.
  26. // See also https://www.kernel.org/doc/Documentation/networking/filter.txt
  27. // Three least significant bits are operation class:
  28. /// BPF operation class: load from immediate.
  29. pub const BPF_LD : u8 = 0x00;
  30. /// BPF operation class: load from register.
  31. pub const BPF_LDX : u8 = 0x01;
  32. /// BPF operation class: store immediate.
  33. pub const BPF_ST : u8 = 0x02;
  34. /// BPF operation class: store value from register.
  35. pub const BPF_STX : u8 = 0x03;
  36. /// BPF operation class: 32 bits arithmetic operation.
  37. pub const BPF_ALU : u8 = 0x04;
  38. /// BPF operation class: jump.
  39. pub const BPF_JMP : u8 = 0x05;
  40. // [ class 6 unused, reserved for future use ]
  41. /// BPF operation class: 64 bits arithmetic operation.
  42. pub const BPF_ALU64 : u8 = 0x07;
  43. // For load and store instructions:
  44. // +------------+--------+------------+
  45. // | 3 bits | 2 bits | 3 bits |
  46. // | mode | size | insn class |
  47. // +------------+--------+------------+
  48. // (MSB) (LSB)
  49. // Size modifiers:
  50. /// BPF size modifier: word (4 bytes).
  51. pub const BPF_W : u8 = 0x00;
  52. /// BPF size modifier: half-word (2 bytes).
  53. pub const BPF_H : u8 = 0x08;
  54. /// BPF size modifier: byte (1 byte).
  55. pub const BPF_B : u8 = 0x10;
  56. /// BPF size modifier: double word (8 bytes).
  57. pub const BPF_DW : u8 = 0x18;
  58. // Mode modifiers:
  59. /// BPF mode modifier: immediate value.
  60. pub const BPF_IMM : u8 = 0x00;
  61. /// BPF mode modifier: absolute load.
  62. pub const BPF_ABS : u8 = 0x20;
  63. /// BPF mode modifier: indirect load.
  64. pub const BPF_IND : u8 = 0x40;
  65. /// BPF mode modifier: load from / store to memory.
  66. pub const BPF_MEM : u8 = 0x60;
  67. // [ 0x80 reserved ]
  68. // [ 0xa0 reserved ]
  69. /// BPF mode modifier: exclusive add.
  70. pub const BPF_XADD : u8 = 0xc0;
  71. // For arithmetic (BPF_ALU/BPF_ALU64) and jump (BPF_JMP) instructions:
  72. // +----------------+--------+--------+
  73. // | 4 bits |1 b.| 3 bits |
  74. // | operation code | src| insn class |
  75. // +----------------+----+------------+
  76. // (MSB) (LSB)
  77. // Source modifiers:
  78. /// BPF source operand modifier: 32-bit immediate value.
  79. pub const BPF_K : u8 = 0x00;
  80. /// BPF source operand modifier: `src` register.
  81. pub const BPF_X : u8 = 0x08;
  82. // Operation codes -- BPF_ALU or BPF_ALU64 classes:
  83. /// BPF ALU/ALU64 operation code: addition.
  84. pub const BPF_ADD : u8 = 0x00;
  85. /// BPF ALU/ALU64 operation code: subtraction.
  86. pub const BPF_SUB : u8 = 0x10;
  87. /// BPF ALU/ALU64 operation code: multiplication.
  88. pub const BPF_MUL : u8 = 0x20;
  89. /// BPF ALU/ALU64 operation code: division.
  90. pub const BPF_DIV : u8 = 0x30;
  91. /// BPF ALU/ALU64 operation code: or.
  92. pub const BPF_OR : u8 = 0x40;
  93. /// BPF ALU/ALU64 operation code: and.
  94. pub const BPF_AND : u8 = 0x50;
  95. /// BPF ALU/ALU64 operation code: left shift.
  96. pub const BPF_LSH : u8 = 0x60;
  97. /// BPF ALU/ALU64 operation code: right shift.
  98. pub const BPF_RSH : u8 = 0x70;
  99. /// BPF ALU/ALU64 operation code: negation.
  100. pub const BPF_NEG : u8 = 0x80;
  101. /// BPF ALU/ALU64 operation code: modulus.
  102. pub const BPF_MOD : u8 = 0x90;
  103. /// BPF ALU/ALU64 operation code: exclusive or.
  104. pub const BPF_XOR : u8 = 0xa0;
  105. /// BPF ALU/ALU64 operation code: move.
  106. pub const BPF_MOV : u8 = 0xb0;
  107. /// BPF ALU/ALU64 operation code: sign extending right shift.
  108. pub const BPF_ARSH : u8 = 0xc0;
  109. /// BPF ALU/ALU64 operation code: endianness conversion.
  110. pub const BPF_END : u8 = 0xd0;
  111. // Operation codes -- BPF_JMP class:
  112. /// BPF JMP operation code: jump.
  113. pub const BPF_JA : u8 = 0x00;
  114. /// BPF JMP operation code: jump if equal.
  115. pub const BPF_JEQ : u8 = 0x10;
  116. /// BPF JMP operation code: jump if greater than.
  117. pub const BPF_JGT : u8 = 0x20;
  118. /// BPF JMP operation code: jump if greater or equal.
  119. pub const BPF_JGE : u8 = 0x30;
  120. /// BPF JMP operation code: jump if `src` & `reg`.
  121. pub const BPF_JSET : u8 = 0x40;
  122. /// BPF JMP operation code: jump if not equal.
  123. pub const BPF_JNE : u8 = 0x50;
  124. /// BPF JMP operation code: jump if greater than (signed).
  125. pub const BPF_JSGT : u8 = 0x60;
  126. /// BPF JMP operation code: jump if greater or equal (signed).
  127. pub const BPF_JSGE : u8 = 0x70;
  128. /// BPF JMP operation code: helper function call.
  129. pub const BPF_CALL : u8 = 0x80;
  130. /// BPF JMP operation code: return from program.
  131. pub const BPF_EXIT : u8 = 0x90;
  132. // Op codes
  133. // (Following operation names are not “official”, but may be proper to rbpf; Linux kernel only
  134. // combines above flags and does not attribute a name per operation.)
  135. /// BPF opcode: `ldabsb src, dst, imm`.
  136. pub const LD_ABS_B : u8 = BPF_LD | BPF_ABS | BPF_B;
  137. /// BPF opcode: `ldabsh src, dst, imm`.
  138. pub const LD_ABS_H : u8 = BPF_LD | BPF_ABS | BPF_H;
  139. /// BPF opcode: `ldabsw src, dst, imm`.
  140. pub const LD_ABS_W : u8 = BPF_LD | BPF_ABS | BPF_W;
  141. /// BPF opcode: `ldabsdw src, dst, imm`.
  142. pub const LD_ABS_DW : u8 = BPF_LD | BPF_ABS | BPF_DW;
  143. /// BPF opcode: `ldindb src, dst, imm`.
  144. pub const LD_IND_B : u8 = BPF_LD | BPF_IND | BPF_B;
  145. /// BPF opcode: `ldindh src, dst, imm`.
  146. pub const LD_IND_H : u8 = BPF_LD | BPF_IND | BPF_H;
  147. /// BPF opcode: `ldindw src, dst, imm`.
  148. pub const LD_IND_W : u8 = BPF_LD | BPF_IND | BPF_W;
  149. /// BPF opcode: `ldinddw src, dst, imm`.
  150. pub const LD_IND_DW : u8 = BPF_LD | BPF_IND | BPF_DW;
  151. /// BPF opcode: `lddw dst, imm` /// `dst = imm`.
  152. pub const LD_DW_IMM : u8 = BPF_LD | BPF_IMM | BPF_DW;
  153. /// BPF opcode: `ldxb dst, [src + off]` /// `dst = (src + off) as u8`.
  154. pub const LD_B_REG : u8 = BPF_LDX | BPF_MEM | BPF_B;
  155. /// BPF opcode: `ldxh dst, [src + off]` /// `dst = (src + off) as u16`.
  156. pub const LD_H_REG : u8 = BPF_LDX | BPF_MEM | BPF_H;
  157. /// BPF opcode: `ldxw dst, [src + off]` /// `dst = (src + off) as u32`.
  158. pub const LD_W_REG : u8 = BPF_LDX | BPF_MEM | BPF_W;
  159. /// BPF opcode: `ldxdw dst, [src + off]` /// `dst = (src + off) as u64`.
  160. pub const LD_DW_REG : u8 = BPF_LDX | BPF_MEM | BPF_DW;
  161. /// BPF opcode: `stb [dst + off], imm` /// `(dst + offset) as u8 = imm`.
  162. pub const ST_B_IMM : u8 = BPF_ST | BPF_MEM | BPF_B;
  163. /// BPF opcode: `sth [dst + off], imm` /// `(dst + offset) as u16 = imm`.
  164. pub const ST_H_IMM : u8 = BPF_ST | BPF_MEM | BPF_H;
  165. /// BPF opcode: `stw [dst + off], imm` /// `(dst + offset) as u32 = imm`.
  166. pub const ST_W_IMM : u8 = BPF_ST | BPF_MEM | BPF_W;
  167. /// BPF opcode: `stdw [dst + off], imm` /// `(dst + offset) as u64 = imm`.
  168. pub const ST_DW_IMM : u8 = BPF_ST | BPF_MEM | BPF_DW;
  169. /// BPF opcode: `stxb [dst + off], src` /// `(dst + offset) as u8 = src`.
  170. pub const ST_B_REG : u8 = BPF_STX | BPF_MEM | BPF_B;
  171. /// BPF opcode: `stxh [dst + off], src` /// `(dst + offset) as u16 = src`.
  172. pub const ST_H_REG : u8 = BPF_STX | BPF_MEM | BPF_H;
  173. /// BPF opcode: `stxw [dst + off], src` /// `(dst + offset) as u32 = src`.
  174. pub const ST_W_REG : u8 = BPF_STX | BPF_MEM | BPF_W;
  175. /// BPF opcode: `stxdw [dst + off], src` /// `(dst + offset) as u64 = src`.
  176. pub const ST_DW_REG : u8 = BPF_STX | BPF_MEM | BPF_DW;
  177. /// BPF opcode: `stxxaddw [dst + off], src`.
  178. pub const ST_W_XADD : u8 = BPF_STX | BPF_XADD | BPF_W;
  179. /// BPF opcode: `stxxadddw [dst + off], src`.
  180. pub const ST_DW_XADD : u8 = BPF_STX | BPF_XADD | BPF_DW;
  181. /// BPF opcode: `add32 dst, imm` /// `dst += imm`.
  182. pub const ADD32_IMM : u8 = BPF_ALU | BPF_K | BPF_ADD;
  183. /// BPF opcode: `add32 dst, src` /// `dst += src`.
  184. pub const ADD32_REG : u8 = BPF_ALU | BPF_X | BPF_ADD;
  185. /// BPF opcode: `sub32 dst, imm` /// `dst -= imm`.
  186. pub const SUB32_IMM : u8 = BPF_ALU | BPF_K | BPF_SUB;
  187. /// BPF opcode: `sub32 dst, src` /// `dst -= src`.
  188. pub const SUB32_REG : u8 = BPF_ALU | BPF_X | BPF_SUB;
  189. /// BPF opcode: `mul32 dst, imm` /// `dst *= imm`.
  190. pub const MUL32_IMM : u8 = BPF_ALU | BPF_K | BPF_MUL;
  191. /// BPF opcode: `mul32 dst, src` /// `dst *= src`.
  192. pub const MUL32_REG : u8 = BPF_ALU | BPF_X | BPF_MUL;
  193. /// BPF opcode: `div32 dst, imm` /// `dst /= imm`.
  194. pub const DIV32_IMM : u8 = BPF_ALU | BPF_K | BPF_DIV;
  195. /// BPF opcode: `div32 dst, src` /// `dst /= src`.
  196. pub const DIV32_REG : u8 = BPF_ALU | BPF_X | BPF_DIV;
  197. /// BPF opcode: `or32 dst, imm` /// `dst |= imm`.
  198. pub const OR32_IMM : u8 = BPF_ALU | BPF_K | BPF_OR;
  199. /// BPF opcode: `or32 dst, src` /// `dst |= src`.
  200. pub const OR32_REG : u8 = BPF_ALU | BPF_X | BPF_OR;
  201. /// BPF opcode: `and32 dst, imm` /// `dst &= imm`.
  202. pub const AND32_IMM : u8 = BPF_ALU | BPF_K | BPF_AND;
  203. /// BPF opcode: `and32 dst, src` /// `dst &= src`.
  204. pub const AND32_REG : u8 = BPF_ALU | BPF_X | BPF_AND;
  205. /// BPF opcode: `lsh32 dst, imm` /// `dst <<= imm`.
  206. pub const LSH32_IMM : u8 = BPF_ALU | BPF_K | BPF_LSH;
  207. /// BPF opcode: `lsh32 dst, src` /// `dst <<= src`.
  208. pub const LSH32_REG : u8 = BPF_ALU | BPF_X | BPF_LSH;
  209. /// BPF opcode: `rsh32 dst, imm` /// `dst >>= imm`.
  210. pub const RSH32_IMM : u8 = BPF_ALU | BPF_K | BPF_RSH;
  211. /// BPF opcode: `rsh32 dst, src` /// `dst >>= src`.
  212. pub const RSH32_REG : u8 = BPF_ALU | BPF_X | BPF_RSH;
  213. /// BPF opcode: `neg32 dst` /// `dst = -dst`.
  214. pub const NEG32 : u8 = BPF_ALU | BPF_NEG;
  215. /// BPF opcode: `mod32 dst, imm` /// `dst %= imm`.
  216. pub const MOD32_IMM : u8 = BPF_ALU | BPF_K | BPF_MOD;
  217. /// BPF opcode: `mod32 dst, src` /// `dst %= src`.
  218. pub const MOD32_REG : u8 = BPF_ALU | BPF_X | BPF_MOD;
  219. /// BPF opcode: `xor32 dst, imm` /// `dst ^= imm`.
  220. pub const XOR32_IMM : u8 = BPF_ALU | BPF_K | BPF_XOR;
  221. /// BPF opcode: `xor32 dst, src` /// `dst ^= src`.
  222. pub const XOR32_REG : u8 = BPF_ALU | BPF_X | BPF_XOR;
  223. /// BPF opcode: `mov32 dst, imm` /// `dst = imm`.
  224. pub const MOV32_IMM : u8 = BPF_ALU | BPF_K | BPF_MOV;
  225. /// BPF opcode: `mov32 dst, src` /// `dst = src`.
  226. pub const MOV32_REG : u8 = BPF_ALU | BPF_X | BPF_MOV;
  227. /// BPF opcode: `arsh32 dst, imm` /// `dst >>= imm (arithmetic)`.
  228. ///
  229. /// <https://en.wikipedia.org/wiki/Arithmetic_shift>
  230. pub const ARSH32_IMM : u8 = BPF_ALU | BPF_K | BPF_ARSH;
  231. /// BPF opcode: `arsh32 dst, src` /// `dst >>= src (arithmetic)`.
  232. ///
  233. /// <https://en.wikipedia.org/wiki/Arithmetic_shift>
  234. pub const ARSH32_REG : u8 = BPF_ALU | BPF_X | BPF_ARSH;
  235. /// BPF opcode: `le dst` /// `dst = htole<imm>(dst), with imm in {16, 32, 64}`.
  236. pub const LE : u8 = BPF_ALU | BPF_K | BPF_END;
  237. /// BPF opcode: `be dst` /// `dst = htobe<imm>(dst), with imm in {16, 32, 64}`.
  238. pub const BE : u8 = BPF_ALU | BPF_X | BPF_END;
  239. /// BPF opcode: `add64 dst, imm` /// `dst += imm`.
  240. pub const ADD64_IMM : u8 = BPF_ALU64 | BPF_K | BPF_ADD;
  241. /// BPF opcode: `add64 dst, src` /// `dst += src`.
  242. pub const ADD64_REG : u8 = BPF_ALU64 | BPF_X | BPF_ADD;
  243. /// BPF opcode: `sub64 dst, imm` /// `dst -= imm`.
  244. pub const SUB64_IMM : u8 = BPF_ALU64 | BPF_K | BPF_SUB;
  245. /// BPF opcode: `sub64 dst, src` /// `dst -= src`.
  246. pub const SUB64_REG : u8 = BPF_ALU64 | BPF_X | BPF_SUB;
  247. /// BPF opcode: `div64 dst, imm` /// `dst /= imm`.
  248. pub const MUL64_IMM : u8 = BPF_ALU64 | BPF_K | BPF_MUL;
  249. /// BPF opcode: `div64 dst, src` /// `dst /= src`.
  250. pub const MUL64_REG : u8 = BPF_ALU64 | BPF_X | BPF_MUL;
  251. /// BPF opcode: `div64 dst, imm` /// `dst /= imm`.
  252. pub const DIV64_IMM : u8 = BPF_ALU64 | BPF_K | BPF_DIV;
  253. /// BPF opcode: `div64 dst, src` /// `dst /= src`.
  254. pub const DIV64_REG : u8 = BPF_ALU64 | BPF_X | BPF_DIV;
  255. /// BPF opcode: `or64 dst, imm` /// `dst |= imm`.
  256. pub const OR64_IMM : u8 = BPF_ALU64 | BPF_K | BPF_OR;
  257. /// BPF opcode: `or64 dst, src` /// `dst |= src`.
  258. pub const OR64_REG : u8 = BPF_ALU64 | BPF_X | BPF_OR;
  259. /// BPF opcode: `and64 dst, imm` /// `dst &= imm`.
  260. pub const AND64_IMM : u8 = BPF_ALU64 | BPF_K | BPF_AND;
  261. /// BPF opcode: `and64 dst, src` /// `dst &= src`.
  262. pub const AND64_REG : u8 = BPF_ALU64 | BPF_X | BPF_AND;
  263. /// BPF opcode: `lsh64 dst, imm` /// `dst <<= imm`.
  264. pub const LSH64_IMM : u8 = BPF_ALU64 | BPF_K | BPF_LSH;
  265. /// BPF opcode: `lsh64 dst, src` /// `dst <<= src`.
  266. pub const LSH64_REG : u8 = BPF_ALU64 | BPF_X | BPF_LSH;
  267. /// BPF opcode: `rsh64 dst, imm` /// `dst >>= imm`.
  268. pub const RSH64_IMM : u8 = BPF_ALU64 | BPF_K | BPF_RSH;
  269. /// BPF opcode: `rsh64 dst, src` /// `dst >>= src`.
  270. pub const RSH64_REG : u8 = BPF_ALU64 | BPF_X | BPF_RSH;
  271. /// BPF opcode: `neg64 dst, imm` /// `dst = -dst`.
  272. pub const NEG64 : u8 = BPF_ALU64 | BPF_NEG;
  273. /// BPF opcode: `mod64 dst, imm` /// `dst %= imm`.
  274. pub const MOD64_IMM : u8 = BPF_ALU64 | BPF_K | BPF_MOD;
  275. /// BPF opcode: `mod64 dst, src` /// `dst %= src`.
  276. pub const MOD64_REG : u8 = BPF_ALU64 | BPF_X | BPF_MOD;
  277. /// BPF opcode: `xor64 dst, imm` /// `dst ^= imm`.
  278. pub const XOR64_IMM : u8 = BPF_ALU64 | BPF_K | BPF_XOR;
  279. /// BPF opcode: `xor64 dst, src` /// `dst ^= src`.
  280. pub const XOR64_REG : u8 = BPF_ALU64 | BPF_X | BPF_XOR;
  281. /// BPF opcode: `mov64 dst, imm` /// `dst = imm`.
  282. pub const MOV64_IMM : u8 = BPF_ALU64 | BPF_K | BPF_MOV;
  283. /// BPF opcode: `mov64 dst, src` /// `dst = src`.
  284. pub const MOV64_REG : u8 = BPF_ALU64 | BPF_X | BPF_MOV;
  285. /// BPF opcode: `arsh64 dst, imm` /// `dst >>= imm (arithmetic)`.
  286. ///
  287. /// <https://en.wikipedia.org/wiki/Arithmetic_shift>
  288. pub const ARSH64_IMM : u8 = BPF_ALU64 | BPF_K | BPF_ARSH;
  289. /// BPF opcode: `arsh64 dst, src` /// `dst >>= src (arithmetic)`.
  290. ///
  291. /// <https://en.wikipedia.org/wiki/Arithmetic_shift>
  292. pub const ARSH64_REG : u8 = BPF_ALU64 | BPF_X | BPF_ARSH;
  293. /// BPF opcode: `ja +off` /// `PC += off`.
  294. pub const JA : u8 = BPF_JMP | BPF_JA;
  295. /// BPF opcode: `jeq dst, imm, +off` /// `PC += off if dst == imm`.
  296. pub const JEQ_IMM : u8 = BPF_JMP | BPF_K | BPF_JEQ;
  297. /// BPF opcode: `jeq dst, src, +off` /// `PC += off if dst == src`.
  298. pub const JEQ_REG : u8 = BPF_JMP | BPF_X | BPF_JEQ;
  299. /// BPF opcode: `jgt dst, imm, +off` /// `PC += off if dst > imm`.
  300. pub const JGT_IMM : u8 = BPF_JMP | BPF_K | BPF_JGT;
  301. /// BPF opcode: `jgt dst, src, +off` /// `PC += off if dst > src`.
  302. pub const JGT_REG : u8 = BPF_JMP | BPF_X | BPF_JGT;
  303. /// BPF opcode: `jge dst, imm, +off` /// `PC += off if dst >= imm`.
  304. pub const JGE_IMM : u8 = BPF_JMP | BPF_K | BPF_JGE;
  305. /// BPF opcode: `jge dst, src, +off` /// `PC += off if dst >= src`.
  306. pub const JGE_REG : u8 = BPF_JMP | BPF_X | BPF_JGE;
  307. /// BPF opcode: `jset dst, imm, +off` /// `PC += off if dst & imm`.
  308. pub const JSET_IMM : u8 = BPF_JMP | BPF_K | BPF_JSET;
  309. /// BPF opcode: `jset dst, src, +off` /// `PC += off if dst & src`.
  310. pub const JSET_REG : u8 = BPF_JMP | BPF_X | BPF_JSET;
  311. /// BPF opcode: `jne dst, imm, +off` /// `PC += off if dst != imm`.
  312. pub const JNE_IMM : u8 = BPF_JMP | BPF_K | BPF_JNE;
  313. /// BPF opcode: `jne dst, src, +off` /// `PC += off if dst != src`.
  314. pub const JNE_REG : u8 = BPF_JMP | BPF_X | BPF_JNE;
  315. /// BPF opcode: `jsgt dst, imm, +off` /// `PC += off if dst > imm (signed)`.
  316. pub const JSGT_IMM : u8 = BPF_JMP | BPF_K | BPF_JSGT;
  317. /// BPF opcode: `jsgt dst, src, +off` /// `PC += off if dst > src (signed)`.
  318. pub const JSGT_REG : u8 = BPF_JMP | BPF_X | BPF_JSGT;
  319. /// BPF opcode: `jsge dst, imm, +off` /// `PC += off if dst >= imm (signed)`.
  320. pub const JSGE_IMM : u8 = BPF_JMP | BPF_K | BPF_JSGE;
  321. /// BPF opcode: `jsge dst, src, +off` /// `PC += off if dst >= src (signed)`.
  322. pub const JSGE_REG : u8 = BPF_JMP | BPF_X | BPF_JSGE;
  323. /// BPF opcode: `call imm` /// helper function call to helper with key `imm`.
  324. pub const CALL : u8 = BPF_JMP | BPF_CALL;
  325. /// BPF opcode: tail call.
  326. pub const TAIL_CALL : u8 = BPF_JMP | BPF_X | BPF_CALL;
  327. /// BPF opcode: `exit` /// `return r0`.
  328. pub const EXIT : u8 = BPF_JMP | BPF_EXIT;
  329. // Used in JIT
  330. /// Mask to extract the operation class from an operation code.
  331. pub const BPF_CLS_MASK : u8 = 0x07;
  332. /// Mask to extract the arithmetic operation code from an instruction operation code.
  333. pub const BPF_ALU_OP_MASK : u8 = 0xf0;
  334. /// Prototype of an eBPF helper function.
  335. pub type Helper = fn (u64, u64, u64, u64, u64) -> u64;
  336. /// An eBPF instruction.
  337. ///
  338. /// See <https://www.kernel.org/doc/Documentation/networking/filter.txt> for the Linux kernel
  339. /// documentation about eBPF, or <https://github.com/iovisor/bpf-docs/blob/master/eBPF.md> for a
  340. /// more concise version.
  341. #[derive(Debug, PartialEq)]
  342. pub struct Insn {
  343. /// Operation code.
  344. pub opc: u8,
  345. /// Destination register operand.
  346. pub dst: u8,
  347. /// Source register operand.
  348. pub src: u8,
  349. /// Offset operand.
  350. pub off: i16,
  351. /// Immediate value operand.
  352. pub imm: i32,
  353. }
  354. /// Get the instruction at `idx` of an eBPF program. `idx` is the index (number) of the
  355. /// instruction (not a byte offset). The first instruction has index 0.
  356. ///
  357. /// # Panics
  358. ///
  359. /// Panics if it is not possible to get the instruction (if idx is too high, or last instruction is
  360. /// incomplete).
  361. ///
  362. /// # Examples
  363. ///
  364. /// ```
  365. /// use rbpf::ebpf;
  366. ///
  367. /// let prog = &[
  368. /// 0xb7, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  369. /// 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  370. /// ];
  371. /// let insn = ebpf::get_insn(prog, 1);
  372. /// assert_eq!(insn.opc, 0x95);
  373. /// ```
  374. ///
  375. /// The example below will panic, since the last instruction is not complete and cannot be loaded.
  376. ///
  377. /// ```rust,should_panic
  378. /// use rbpf::ebpf;
  379. ///
  380. /// let prog = &[
  381. /// 0xb7, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  382. /// 0x95, 0x00, 0x00, 0x00, 0x00, 0x00 // two bytes missing
  383. /// ];
  384. /// let insn = ebpf::get_insn(prog, 1);
  385. /// ```
  386. pub fn get_insn(prog: &[u8], idx: usize) -> Insn {
  387. // This guard should not be needed in most cases, since the verifier already checks the program
  388. // size, and indexes should be fine in the interpreter/JIT. But this function is publicly
  389. // available and user can call it with any `idx`, so we have to check anyway.
  390. if (idx + 1) * INSN_SIZE > prog.len() {
  391. panic!("Error: cannot reach instruction at index {:?} in program containing {:?} bytes",
  392. idx, prog.len());
  393. }
  394. Insn {
  395. opc: prog[INSN_SIZE * idx],
  396. dst: prog[INSN_SIZE * idx + 1] & 0x0f,
  397. src: (prog[INSN_SIZE * idx + 1] & 0xf0) >> 4,
  398. off: unsafe {
  399. let x = prog.as_ptr().offset((INSN_SIZE * idx + 2) as isize) as *const i16; *x
  400. },
  401. imm: unsafe {
  402. let x = prog.as_ptr().offset((INSN_SIZE * idx + 4) as isize) as *const i32; *x
  403. },
  404. }
  405. }
  406. /// Return a vector of `struct Insn` built from a program.
  407. ///
  408. /// This is provided as a convenience for users wishing to manipulate a vector of instructions, for
  409. /// example for dumping the program instruction after instruction with a custom format.
  410. ///
  411. /// Note that the two parts of `LD_DW_IMM` instructions (spanning on 64 bits) are considered as two
  412. /// distinct instructions.
  413. ///
  414. /// # Examples
  415. ///
  416. /// ```
  417. /// use rbpf::ebpf;
  418. ///
  419. /// let prog = &[
  420. /// 0x18, 0x00, 0x00, 0x00, 0x88, 0x77, 0x66, 0x55,
  421. /// 0x00, 0x00, 0x00, 0x00, 0x44, 0x33, 0x22, 0x11,
  422. /// 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  423. /// ];
  424. ///
  425. /// let v = ebpf::to_insn_vec(prog);
  426. /// assert_eq!(v, vec![
  427. /// ebpf::Insn {
  428. /// opc: 0x18,
  429. /// dst: 0,
  430. /// src: 0,
  431. /// off: 0,
  432. /// imm: 0x55667788
  433. /// },
  434. /// ebpf::Insn {
  435. /// opc: 0,
  436. /// dst: 0,
  437. /// src: 0,
  438. /// off: 0,
  439. /// imm: 0x11223344
  440. /// },
  441. /// ebpf::Insn {
  442. /// opc: 0x95,
  443. /// dst: 0,
  444. /// src: 0,
  445. /// off: 0,
  446. /// imm: 0
  447. /// },
  448. /// ]);
  449. /// ```
  450. pub fn to_insn_vec(prog: &[u8]) -> Vec<Insn> {
  451. if prog.len() % INSN_SIZE != 0 {
  452. panic!("Error: eBPF program length must be a multiple of {:?} octets",
  453. INSN_SIZE);
  454. }
  455. let mut res = vec![];
  456. let mut insn_ptr:usize = 0;
  457. while insn_ptr * INSN_SIZE < prog.len() {
  458. let insn = get_insn(prog, insn_ptr);
  459. res.push(insn);
  460. insn_ptr += 1;
  461. };
  462. res
  463. }