test_verifier.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835
  1. /*
  2. * Testsuite for eBPF verifier
  3. *
  4. * Copyright (c) 2014 PLUMgrid, http://plumgrid.com
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of version 2 of the GNU General Public
  8. * License as published by the Free Software Foundation.
  9. */
  10. #include <stdio.h>
  11. #include <unistd.h>
  12. #include <linux/bpf.h>
  13. #include <errno.h>
  14. #include <linux/unistd.h>
  15. #include <string.h>
  16. #include <linux/filter.h>
  17. #include <stddef.h>
  18. #include "libbpf.h"
  19. #define MAX_INSNS 512
  20. #define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))
  21. struct bpf_test {
  22. const char *descr;
  23. struct bpf_insn insns[MAX_INSNS];
  24. int fixup[32];
  25. const char *errstr;
  26. enum {
  27. ACCEPT,
  28. REJECT
  29. } result;
  30. };
  31. static struct bpf_test tests[] = {
  32. {
  33. "add+sub+mul",
  34. .insns = {
  35. BPF_MOV64_IMM(BPF_REG_1, 1),
  36. BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 2),
  37. BPF_MOV64_IMM(BPF_REG_2, 3),
  38. BPF_ALU64_REG(BPF_SUB, BPF_REG_1, BPF_REG_2),
  39. BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -1),
  40. BPF_ALU64_IMM(BPF_MUL, BPF_REG_1, 3),
  41. BPF_MOV64_REG(BPF_REG_0, BPF_REG_1),
  42. BPF_EXIT_INSN(),
  43. },
  44. .result = ACCEPT,
  45. },
  46. {
  47. "unreachable",
  48. .insns = {
  49. BPF_EXIT_INSN(),
  50. BPF_EXIT_INSN(),
  51. },
  52. .errstr = "unreachable",
  53. .result = REJECT,
  54. },
  55. {
  56. "unreachable2",
  57. .insns = {
  58. BPF_JMP_IMM(BPF_JA, 0, 0, 1),
  59. BPF_JMP_IMM(BPF_JA, 0, 0, 0),
  60. BPF_EXIT_INSN(),
  61. },
  62. .errstr = "unreachable",
  63. .result = REJECT,
  64. },
  65. {
  66. "out of range jump",
  67. .insns = {
  68. BPF_JMP_IMM(BPF_JA, 0, 0, 1),
  69. BPF_EXIT_INSN(),
  70. },
  71. .errstr = "jump out of range",
  72. .result = REJECT,
  73. },
  74. {
  75. "out of range jump2",
  76. .insns = {
  77. BPF_JMP_IMM(BPF_JA, 0, 0, -2),
  78. BPF_EXIT_INSN(),
  79. },
  80. .errstr = "jump out of range",
  81. .result = REJECT,
  82. },
  83. {
  84. "test1 ld_imm64",
  85. .insns = {
  86. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 1),
  87. BPF_LD_IMM64(BPF_REG_0, 0),
  88. BPF_LD_IMM64(BPF_REG_0, 0),
  89. BPF_LD_IMM64(BPF_REG_0, 1),
  90. BPF_LD_IMM64(BPF_REG_0, 1),
  91. BPF_MOV64_IMM(BPF_REG_0, 2),
  92. BPF_EXIT_INSN(),
  93. },
  94. .errstr = "invalid BPF_LD_IMM insn",
  95. .result = REJECT,
  96. },
  97. {
  98. "test2 ld_imm64",
  99. .insns = {
  100. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 1),
  101. BPF_LD_IMM64(BPF_REG_0, 0),
  102. BPF_LD_IMM64(BPF_REG_0, 0),
  103. BPF_LD_IMM64(BPF_REG_0, 1),
  104. BPF_LD_IMM64(BPF_REG_0, 1),
  105. BPF_EXIT_INSN(),
  106. },
  107. .errstr = "invalid BPF_LD_IMM insn",
  108. .result = REJECT,
  109. },
  110. {
  111. "test3 ld_imm64",
  112. .insns = {
  113. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 1),
  114. BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, 0, 0, 0, 0),
  115. BPF_LD_IMM64(BPF_REG_0, 0),
  116. BPF_LD_IMM64(BPF_REG_0, 0),
  117. BPF_LD_IMM64(BPF_REG_0, 1),
  118. BPF_LD_IMM64(BPF_REG_0, 1),
  119. BPF_EXIT_INSN(),
  120. },
  121. .errstr = "invalid bpf_ld_imm64 insn",
  122. .result = REJECT,
  123. },
  124. {
  125. "test4 ld_imm64",
  126. .insns = {
  127. BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, 0, 0, 0, 0),
  128. BPF_EXIT_INSN(),
  129. },
  130. .errstr = "invalid bpf_ld_imm64 insn",
  131. .result = REJECT,
  132. },
  133. {
  134. "test5 ld_imm64",
  135. .insns = {
  136. BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, 0, 0, 0, 0),
  137. },
  138. .errstr = "invalid bpf_ld_imm64 insn",
  139. .result = REJECT,
  140. },
  141. {
  142. "no bpf_exit",
  143. .insns = {
  144. BPF_ALU64_REG(BPF_MOV, BPF_REG_0, BPF_REG_2),
  145. },
  146. .errstr = "jump out of range",
  147. .result = REJECT,
  148. },
  149. {
  150. "loop (back-edge)",
  151. .insns = {
  152. BPF_JMP_IMM(BPF_JA, 0, 0, -1),
  153. BPF_EXIT_INSN(),
  154. },
  155. .errstr = "back-edge",
  156. .result = REJECT,
  157. },
  158. {
  159. "loop2 (back-edge)",
  160. .insns = {
  161. BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
  162. BPF_MOV64_REG(BPF_REG_2, BPF_REG_0),
  163. BPF_MOV64_REG(BPF_REG_3, BPF_REG_0),
  164. BPF_JMP_IMM(BPF_JA, 0, 0, -4),
  165. BPF_EXIT_INSN(),
  166. },
  167. .errstr = "back-edge",
  168. .result = REJECT,
  169. },
  170. {
  171. "conditional loop",
  172. .insns = {
  173. BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
  174. BPF_MOV64_REG(BPF_REG_2, BPF_REG_0),
  175. BPF_MOV64_REG(BPF_REG_3, BPF_REG_0),
  176. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, -3),
  177. BPF_EXIT_INSN(),
  178. },
  179. .errstr = "back-edge",
  180. .result = REJECT,
  181. },
  182. {
  183. "read uninitialized register",
  184. .insns = {
  185. BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
  186. BPF_EXIT_INSN(),
  187. },
  188. .errstr = "R2 !read_ok",
  189. .result = REJECT,
  190. },
  191. {
  192. "read invalid register",
  193. .insns = {
  194. BPF_MOV64_REG(BPF_REG_0, -1),
  195. BPF_EXIT_INSN(),
  196. },
  197. .errstr = "R15 is invalid",
  198. .result = REJECT,
  199. },
  200. {
  201. "program doesn't init R0 before exit",
  202. .insns = {
  203. BPF_ALU64_REG(BPF_MOV, BPF_REG_2, BPF_REG_1),
  204. BPF_EXIT_INSN(),
  205. },
  206. .errstr = "R0 !read_ok",
  207. .result = REJECT,
  208. },
  209. {
  210. "program doesn't init R0 before exit in all branches",
  211. .insns = {
  212. BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 2),
  213. BPF_MOV64_IMM(BPF_REG_0, 1),
  214. BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 2),
  215. BPF_EXIT_INSN(),
  216. },
  217. .errstr = "R0 !read_ok",
  218. .result = REJECT,
  219. },
  220. {
  221. "stack out of bounds",
  222. .insns = {
  223. BPF_ST_MEM(BPF_DW, BPF_REG_10, 8, 0),
  224. BPF_EXIT_INSN(),
  225. },
  226. .errstr = "invalid stack",
  227. .result = REJECT,
  228. },
  229. {
  230. "invalid call insn1",
  231. .insns = {
  232. BPF_RAW_INSN(BPF_JMP | BPF_CALL | BPF_X, 0, 0, 0, 0),
  233. BPF_EXIT_INSN(),
  234. },
  235. .errstr = "BPF_CALL uses reserved",
  236. .result = REJECT,
  237. },
  238. {
  239. "invalid call insn2",
  240. .insns = {
  241. BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 1, 0),
  242. BPF_EXIT_INSN(),
  243. },
  244. .errstr = "BPF_CALL uses reserved",
  245. .result = REJECT,
  246. },
  247. {
  248. "invalid function call",
  249. .insns = {
  250. BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, 1234567),
  251. BPF_EXIT_INSN(),
  252. },
  253. .errstr = "invalid func 1234567",
  254. .result = REJECT,
  255. },
  256. {
  257. "uninitialized stack1",
  258. .insns = {
  259. BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
  260. BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
  261. BPF_LD_MAP_FD(BPF_REG_1, 0),
  262. BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
  263. BPF_EXIT_INSN(),
  264. },
  265. .fixup = {2},
  266. .errstr = "invalid indirect read from stack",
  267. .result = REJECT,
  268. },
  269. {
  270. "uninitialized stack2",
  271. .insns = {
  272. BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
  273. BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_2, -8),
  274. BPF_EXIT_INSN(),
  275. },
  276. .errstr = "invalid read from stack",
  277. .result = REJECT,
  278. },
  279. {
  280. "check valid spill/fill",
  281. .insns = {
  282. /* spill R1(ctx) into stack */
  283. BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_1, -8),
  284. /* fill it back into R2 */
  285. BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_10, -8),
  286. /* should be able to access R0 = *(R2 + 8) */
  287. /* BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_2, 8), */
  288. BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
  289. BPF_EXIT_INSN(),
  290. },
  291. .result = ACCEPT,
  292. },
  293. {
  294. "check corrupted spill/fill",
  295. .insns = {
  296. /* spill R1(ctx) into stack */
  297. BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_1, -8),
  298. /* mess up with R1 pointer on stack */
  299. BPF_ST_MEM(BPF_B, BPF_REG_10, -7, 0x23),
  300. /* fill back into R0 should fail */
  301. BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_10, -8),
  302. BPF_EXIT_INSN(),
  303. },
  304. .errstr = "corrupted spill",
  305. .result = REJECT,
  306. },
  307. {
  308. "invalid src register in STX",
  309. .insns = {
  310. BPF_STX_MEM(BPF_B, BPF_REG_10, -1, -1),
  311. BPF_EXIT_INSN(),
  312. },
  313. .errstr = "R15 is invalid",
  314. .result = REJECT,
  315. },
  316. {
  317. "invalid dst register in STX",
  318. .insns = {
  319. BPF_STX_MEM(BPF_B, 14, BPF_REG_10, -1),
  320. BPF_EXIT_INSN(),
  321. },
  322. .errstr = "R14 is invalid",
  323. .result = REJECT,
  324. },
  325. {
  326. "invalid dst register in ST",
  327. .insns = {
  328. BPF_ST_MEM(BPF_B, 14, -1, -1),
  329. BPF_EXIT_INSN(),
  330. },
  331. .errstr = "R14 is invalid",
  332. .result = REJECT,
  333. },
  334. {
  335. "invalid src register in LDX",
  336. .insns = {
  337. BPF_LDX_MEM(BPF_B, BPF_REG_0, 12, 0),
  338. BPF_EXIT_INSN(),
  339. },
  340. .errstr = "R12 is invalid",
  341. .result = REJECT,
  342. },
  343. {
  344. "invalid dst register in LDX",
  345. .insns = {
  346. BPF_LDX_MEM(BPF_B, 11, BPF_REG_1, 0),
  347. BPF_EXIT_INSN(),
  348. },
  349. .errstr = "R11 is invalid",
  350. .result = REJECT,
  351. },
  352. {
  353. "junk insn",
  354. .insns = {
  355. BPF_RAW_INSN(0, 0, 0, 0, 0),
  356. BPF_EXIT_INSN(),
  357. },
  358. .errstr = "invalid BPF_LD_IMM",
  359. .result = REJECT,
  360. },
  361. {
  362. "junk insn2",
  363. .insns = {
  364. BPF_RAW_INSN(1, 0, 0, 0, 0),
  365. BPF_EXIT_INSN(),
  366. },
  367. .errstr = "BPF_LDX uses reserved fields",
  368. .result = REJECT,
  369. },
  370. {
  371. "junk insn3",
  372. .insns = {
  373. BPF_RAW_INSN(-1, 0, 0, 0, 0),
  374. BPF_EXIT_INSN(),
  375. },
  376. .errstr = "invalid BPF_ALU opcode f0",
  377. .result = REJECT,
  378. },
  379. {
  380. "junk insn4",
  381. .insns = {
  382. BPF_RAW_INSN(-1, -1, -1, -1, -1),
  383. BPF_EXIT_INSN(),
  384. },
  385. .errstr = "invalid BPF_ALU opcode f0",
  386. .result = REJECT,
  387. },
  388. {
  389. "junk insn5",
  390. .insns = {
  391. BPF_RAW_INSN(0x7f, -1, -1, -1, -1),
  392. BPF_EXIT_INSN(),
  393. },
  394. .errstr = "BPF_ALU uses reserved fields",
  395. .result = REJECT,
  396. },
  397. {
  398. "misaligned read from stack",
  399. .insns = {
  400. BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
  401. BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_2, -4),
  402. BPF_EXIT_INSN(),
  403. },
  404. .errstr = "misaligned access",
  405. .result = REJECT,
  406. },
  407. {
  408. "invalid map_fd for function call",
  409. .insns = {
  410. BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
  411. BPF_ALU64_REG(BPF_MOV, BPF_REG_2, BPF_REG_10),
  412. BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
  413. BPF_LD_MAP_FD(BPF_REG_1, 0),
  414. BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_delete_elem),
  415. BPF_EXIT_INSN(),
  416. },
  417. .errstr = "fd 0 is not pointing to valid bpf_map",
  418. .result = REJECT,
  419. },
  420. {
  421. "don't check return value before access",
  422. .insns = {
  423. BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
  424. BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
  425. BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
  426. BPF_LD_MAP_FD(BPF_REG_1, 0),
  427. BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
  428. BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 0),
  429. BPF_EXIT_INSN(),
  430. },
  431. .fixup = {3},
  432. .errstr = "R0 invalid mem access 'map_value_or_null'",
  433. .result = REJECT,
  434. },
  435. {
  436. "access memory with incorrect alignment",
  437. .insns = {
  438. BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
  439. BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
  440. BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
  441. BPF_LD_MAP_FD(BPF_REG_1, 0),
  442. BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
  443. BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1),
  444. BPF_ST_MEM(BPF_DW, BPF_REG_0, 4, 0),
  445. BPF_EXIT_INSN(),
  446. },
  447. .fixup = {3},
  448. .errstr = "misaligned access",
  449. .result = REJECT,
  450. },
  451. {
  452. "sometimes access memory with incorrect alignment",
  453. .insns = {
  454. BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
  455. BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
  456. BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
  457. BPF_LD_MAP_FD(BPF_REG_1, 0),
  458. BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
  459. BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2),
  460. BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 0),
  461. BPF_EXIT_INSN(),
  462. BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 1),
  463. BPF_EXIT_INSN(),
  464. },
  465. .fixup = {3},
  466. .errstr = "R0 invalid mem access",
  467. .result = REJECT,
  468. },
  469. {
  470. "jump test 1",
  471. .insns = {
  472. BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
  473. BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, -8),
  474. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 1),
  475. BPF_ST_MEM(BPF_DW, BPF_REG_2, -8, 0),
  476. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 1, 1),
  477. BPF_ST_MEM(BPF_DW, BPF_REG_2, -16, 1),
  478. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 2, 1),
  479. BPF_ST_MEM(BPF_DW, BPF_REG_2, -8, 2),
  480. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 3, 1),
  481. BPF_ST_MEM(BPF_DW, BPF_REG_2, -16, 3),
  482. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 4, 1),
  483. BPF_ST_MEM(BPF_DW, BPF_REG_2, -8, 4),
  484. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 5, 1),
  485. BPF_ST_MEM(BPF_DW, BPF_REG_2, -32, 5),
  486. BPF_MOV64_IMM(BPF_REG_0, 0),
  487. BPF_EXIT_INSN(),
  488. },
  489. .result = ACCEPT,
  490. },
  491. {
  492. "jump test 2",
  493. .insns = {
  494. BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
  495. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 2),
  496. BPF_ST_MEM(BPF_DW, BPF_REG_2, -8, 0),
  497. BPF_JMP_IMM(BPF_JA, 0, 0, 14),
  498. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 1, 2),
  499. BPF_ST_MEM(BPF_DW, BPF_REG_2, -16, 0),
  500. BPF_JMP_IMM(BPF_JA, 0, 0, 11),
  501. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 2, 2),
  502. BPF_ST_MEM(BPF_DW, BPF_REG_2, -32, 0),
  503. BPF_JMP_IMM(BPF_JA, 0, 0, 8),
  504. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 3, 2),
  505. BPF_ST_MEM(BPF_DW, BPF_REG_2, -40, 0),
  506. BPF_JMP_IMM(BPF_JA, 0, 0, 5),
  507. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 4, 2),
  508. BPF_ST_MEM(BPF_DW, BPF_REG_2, -48, 0),
  509. BPF_JMP_IMM(BPF_JA, 0, 0, 2),
  510. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 5, 1),
  511. BPF_ST_MEM(BPF_DW, BPF_REG_2, -56, 0),
  512. BPF_MOV64_IMM(BPF_REG_0, 0),
  513. BPF_EXIT_INSN(),
  514. },
  515. .result = ACCEPT,
  516. },
  517. {
  518. "jump test 3",
  519. .insns = {
  520. BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
  521. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 3),
  522. BPF_ST_MEM(BPF_DW, BPF_REG_2, -8, 0),
  523. BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
  524. BPF_JMP_IMM(BPF_JA, 0, 0, 19),
  525. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 1, 3),
  526. BPF_ST_MEM(BPF_DW, BPF_REG_2, -16, 0),
  527. BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -16),
  528. BPF_JMP_IMM(BPF_JA, 0, 0, 15),
  529. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 2, 3),
  530. BPF_ST_MEM(BPF_DW, BPF_REG_2, -32, 0),
  531. BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -32),
  532. BPF_JMP_IMM(BPF_JA, 0, 0, 11),
  533. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 3, 3),
  534. BPF_ST_MEM(BPF_DW, BPF_REG_2, -40, 0),
  535. BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -40),
  536. BPF_JMP_IMM(BPF_JA, 0, 0, 7),
  537. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 4, 3),
  538. BPF_ST_MEM(BPF_DW, BPF_REG_2, -48, 0),
  539. BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -48),
  540. BPF_JMP_IMM(BPF_JA, 0, 0, 3),
  541. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 5, 0),
  542. BPF_ST_MEM(BPF_DW, BPF_REG_2, -56, 0),
  543. BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -56),
  544. BPF_LD_MAP_FD(BPF_REG_1, 0),
  545. BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_delete_elem),
  546. BPF_EXIT_INSN(),
  547. },
  548. .fixup = {24},
  549. .result = ACCEPT,
  550. },
  551. {
  552. "jump test 4",
  553. .insns = {
  554. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1),
  555. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2),
  556. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3),
  557. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4),
  558. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1),
  559. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2),
  560. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3),
  561. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4),
  562. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1),
  563. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2),
  564. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3),
  565. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4),
  566. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1),
  567. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2),
  568. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3),
  569. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4),
  570. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1),
  571. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2),
  572. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3),
  573. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4),
  574. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1),
  575. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2),
  576. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3),
  577. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4),
  578. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1),
  579. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2),
  580. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3),
  581. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4),
  582. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1),
  583. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2),
  584. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3),
  585. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4),
  586. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1),
  587. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2),
  588. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3),
  589. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4),
  590. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 0),
  591. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 0),
  592. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 0),
  593. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 0),
  594. BPF_MOV64_IMM(BPF_REG_0, 0),
  595. BPF_EXIT_INSN(),
  596. },
  597. .result = ACCEPT,
  598. },
  599. {
  600. "jump test 5",
  601. .insns = {
  602. BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
  603. BPF_MOV64_REG(BPF_REG_3, BPF_REG_2),
  604. BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 2),
  605. BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_3, -8),
  606. BPF_JMP_IMM(BPF_JA, 0, 0, 2),
  607. BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_2, -8),
  608. BPF_JMP_IMM(BPF_JA, 0, 0, 0),
  609. BPF_MOV64_IMM(BPF_REG_0, 0),
  610. BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 2),
  611. BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_3, -8),
  612. BPF_JMP_IMM(BPF_JA, 0, 0, 2),
  613. BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_2, -8),
  614. BPF_JMP_IMM(BPF_JA, 0, 0, 0),
  615. BPF_MOV64_IMM(BPF_REG_0, 0),
  616. BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 2),
  617. BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_3, -8),
  618. BPF_JMP_IMM(BPF_JA, 0, 0, 2),
  619. BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_2, -8),
  620. BPF_JMP_IMM(BPF_JA, 0, 0, 0),
  621. BPF_MOV64_IMM(BPF_REG_0, 0),
  622. BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 2),
  623. BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_3, -8),
  624. BPF_JMP_IMM(BPF_JA, 0, 0, 2),
  625. BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_2, -8),
  626. BPF_JMP_IMM(BPF_JA, 0, 0, 0),
  627. BPF_MOV64_IMM(BPF_REG_0, 0),
  628. BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 2),
  629. BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_3, -8),
  630. BPF_JMP_IMM(BPF_JA, 0, 0, 2),
  631. BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_2, -8),
  632. BPF_JMP_IMM(BPF_JA, 0, 0, 0),
  633. BPF_MOV64_IMM(BPF_REG_0, 0),
  634. BPF_EXIT_INSN(),
  635. },
  636. .result = ACCEPT,
  637. },
  638. {
  639. "access skb fields ok",
  640. .insns = {
  641. BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
  642. offsetof(struct __sk_buff, len)),
  643. BPF_JMP_IMM(BPF_JGE, BPF_REG_0, 0, 1),
  644. BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
  645. offsetof(struct __sk_buff, mark)),
  646. BPF_JMP_IMM(BPF_JGE, BPF_REG_0, 0, 1),
  647. BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
  648. offsetof(struct __sk_buff, pkt_type)),
  649. BPF_JMP_IMM(BPF_JGE, BPF_REG_0, 0, 1),
  650. BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
  651. offsetof(struct __sk_buff, queue_mapping)),
  652. BPF_JMP_IMM(BPF_JGE, BPF_REG_0, 0, 0),
  653. BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
  654. offsetof(struct __sk_buff, protocol)),
  655. BPF_JMP_IMM(BPF_JGE, BPF_REG_0, 0, 0),
  656. BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
  657. offsetof(struct __sk_buff, vlan_present)),
  658. BPF_JMP_IMM(BPF_JGE, BPF_REG_0, 0, 0),
  659. BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
  660. offsetof(struct __sk_buff, vlan_tci)),
  661. BPF_JMP_IMM(BPF_JGE, BPF_REG_0, 0, 0),
  662. BPF_EXIT_INSN(),
  663. },
  664. .result = ACCEPT,
  665. },
  666. {
  667. "access skb fields bad1",
  668. .insns = {
  669. BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1, -4),
  670. BPF_EXIT_INSN(),
  671. },
  672. .errstr = "invalid bpf_context access",
  673. .result = REJECT,
  674. },
  675. {
  676. "access skb fields bad2",
  677. .insns = {
  678. BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 9),
  679. BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
  680. BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
  681. BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
  682. BPF_LD_MAP_FD(BPF_REG_1, 0),
  683. BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
  684. BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
  685. BPF_EXIT_INSN(),
  686. BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
  687. BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
  688. offsetof(struct __sk_buff, pkt_type)),
  689. BPF_EXIT_INSN(),
  690. },
  691. .fixup = {4},
  692. .errstr = "different pointers",
  693. .result = REJECT,
  694. },
  695. {
  696. "access skb fields bad3",
  697. .insns = {
  698. BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 2),
  699. BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
  700. offsetof(struct __sk_buff, pkt_type)),
  701. BPF_EXIT_INSN(),
  702. BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
  703. BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
  704. BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
  705. BPF_LD_MAP_FD(BPF_REG_1, 0),
  706. BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
  707. BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
  708. BPF_EXIT_INSN(),
  709. BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
  710. BPF_JMP_IMM(BPF_JA, 0, 0, -12),
  711. },
  712. .fixup = {6},
  713. .errstr = "different pointers",
  714. .result = REJECT,
  715. },
  716. {
  717. "access skb fields bad4",
  718. .insns = {
  719. BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 3),
  720. BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_1,
  721. offsetof(struct __sk_buff, len)),
  722. BPF_MOV64_IMM(BPF_REG_0, 0),
  723. BPF_EXIT_INSN(),
  724. BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
  725. BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
  726. BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
  727. BPF_LD_MAP_FD(BPF_REG_1, 0),
  728. BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
  729. BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
  730. BPF_EXIT_INSN(),
  731. BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
  732. BPF_JMP_IMM(BPF_JA, 0, 0, -13),
  733. },
  734. .fixup = {7},
  735. .errstr = "different pointers",
  736. .result = REJECT,
  737. },
  738. };
  739. static int probe_filter_length(struct bpf_insn *fp)
  740. {
  741. int len = 0;
  742. for (len = MAX_INSNS - 1; len > 0; --len)
  743. if (fp[len].code != 0 || fp[len].imm != 0)
  744. break;
  745. return len + 1;
  746. }
  747. static int create_map(void)
  748. {
  749. long long key, value = 0;
  750. int map_fd;
  751. map_fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value), 1024);
  752. if (map_fd < 0) {
  753. printf("failed to create map '%s'\n", strerror(errno));
  754. }
  755. return map_fd;
  756. }
  757. static int test(void)
  758. {
  759. int prog_fd, i, pass_cnt = 0, err_cnt = 0;
  760. for (i = 0; i < ARRAY_SIZE(tests); i++) {
  761. struct bpf_insn *prog = tests[i].insns;
  762. int prog_len = probe_filter_length(prog);
  763. int *fixup = tests[i].fixup;
  764. int map_fd = -1;
  765. if (*fixup) {
  766. map_fd = create_map();
  767. do {
  768. prog[*fixup].imm = map_fd;
  769. fixup++;
  770. } while (*fixup);
  771. }
  772. printf("#%d %s ", i, tests[i].descr);
  773. prog_fd = bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER, prog,
  774. prog_len * sizeof(struct bpf_insn),
  775. "GPL", 0);
  776. if (tests[i].result == ACCEPT) {
  777. if (prog_fd < 0) {
  778. printf("FAIL\nfailed to load prog '%s'\n",
  779. strerror(errno));
  780. printf("%s", bpf_log_buf);
  781. err_cnt++;
  782. goto fail;
  783. }
  784. } else {
  785. if (prog_fd >= 0) {
  786. printf("FAIL\nunexpected success to load\n");
  787. printf("%s", bpf_log_buf);
  788. err_cnt++;
  789. goto fail;
  790. }
  791. if (strstr(bpf_log_buf, tests[i].errstr) == 0) {
  792. printf("FAIL\nunexpected error message: %s",
  793. bpf_log_buf);
  794. err_cnt++;
  795. goto fail;
  796. }
  797. }
  798. pass_cnt++;
  799. printf("OK\n");
  800. fail:
  801. if (map_fd >= 0)
  802. close(map_fd);
  803. close(prog_fd);
  804. }
  805. printf("Summary: %d PASSED, %d FAILED\n", pass_cnt, err_cnt);
  806. return 0;
  807. }
  808. int main(void)
  809. {
  810. return test();
  811. }