test_verifier.c 18 KB

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