test_verifier.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734
  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_MOV64_REG(BPF_REG_0, BPF_REG_2),
  288. BPF_EXIT_INSN(),
  289. },
  290. .result = ACCEPT,
  291. },
  292. {
  293. "check corrupted spill/fill",
  294. .insns = {
  295. /* spill R1(ctx) into stack */
  296. BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_1, -8),
  297. /* mess up with R1 pointer on stack */
  298. BPF_ST_MEM(BPF_B, BPF_REG_10, -7, 0x23),
  299. /* fill back into R0 should fail */
  300. BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_10, -8),
  301. BPF_EXIT_INSN(),
  302. },
  303. .errstr = "corrupted spill",
  304. .result = REJECT,
  305. },
  306. {
  307. "invalid src register in STX",
  308. .insns = {
  309. BPF_STX_MEM(BPF_B, BPF_REG_10, -1, -1),
  310. BPF_EXIT_INSN(),
  311. },
  312. .errstr = "R15 is invalid",
  313. .result = REJECT,
  314. },
  315. {
  316. "invalid dst register in STX",
  317. .insns = {
  318. BPF_STX_MEM(BPF_B, 14, BPF_REG_10, -1),
  319. BPF_EXIT_INSN(),
  320. },
  321. .errstr = "R14 is invalid",
  322. .result = REJECT,
  323. },
  324. {
  325. "invalid dst register in ST",
  326. .insns = {
  327. BPF_ST_MEM(BPF_B, 14, -1, -1),
  328. BPF_EXIT_INSN(),
  329. },
  330. .errstr = "R14 is invalid",
  331. .result = REJECT,
  332. },
  333. {
  334. "invalid src register in LDX",
  335. .insns = {
  336. BPF_LDX_MEM(BPF_B, BPF_REG_0, 12, 0),
  337. BPF_EXIT_INSN(),
  338. },
  339. .errstr = "R12 is invalid",
  340. .result = REJECT,
  341. },
  342. {
  343. "invalid dst register in LDX",
  344. .insns = {
  345. BPF_LDX_MEM(BPF_B, 11, BPF_REG_1, 0),
  346. BPF_EXIT_INSN(),
  347. },
  348. .errstr = "R11 is invalid",
  349. .result = REJECT,
  350. },
  351. {
  352. "junk insn",
  353. .insns = {
  354. BPF_RAW_INSN(0, 0, 0, 0, 0),
  355. BPF_EXIT_INSN(),
  356. },
  357. .errstr = "invalid BPF_LD_IMM",
  358. .result = REJECT,
  359. },
  360. {
  361. "junk insn2",
  362. .insns = {
  363. BPF_RAW_INSN(1, 0, 0, 0, 0),
  364. BPF_EXIT_INSN(),
  365. },
  366. .errstr = "BPF_LDX uses reserved fields",
  367. .result = REJECT,
  368. },
  369. {
  370. "junk insn3",
  371. .insns = {
  372. BPF_RAW_INSN(-1, 0, 0, 0, 0),
  373. BPF_EXIT_INSN(),
  374. },
  375. .errstr = "invalid BPF_ALU opcode f0",
  376. .result = REJECT,
  377. },
  378. {
  379. "junk insn4",
  380. .insns = {
  381. BPF_RAW_INSN(-1, -1, -1, -1, -1),
  382. BPF_EXIT_INSN(),
  383. },
  384. .errstr = "invalid BPF_ALU opcode f0",
  385. .result = REJECT,
  386. },
  387. {
  388. "junk insn5",
  389. .insns = {
  390. BPF_RAW_INSN(0x7f, -1, -1, -1, -1),
  391. BPF_EXIT_INSN(),
  392. },
  393. .errstr = "BPF_ALU uses reserved fields",
  394. .result = REJECT,
  395. },
  396. {
  397. "misaligned read from stack",
  398. .insns = {
  399. BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
  400. BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_2, -4),
  401. BPF_EXIT_INSN(),
  402. },
  403. .errstr = "misaligned access",
  404. .result = REJECT,
  405. },
  406. {
  407. "invalid map_fd for function call",
  408. .insns = {
  409. BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
  410. BPF_ALU64_REG(BPF_MOV, BPF_REG_2, BPF_REG_10),
  411. BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
  412. BPF_LD_MAP_FD(BPF_REG_1, 0),
  413. BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_delete_elem),
  414. BPF_EXIT_INSN(),
  415. },
  416. .errstr = "fd 0 is not pointing to valid bpf_map",
  417. .result = REJECT,
  418. },
  419. {
  420. "don't check return value before access",
  421. .insns = {
  422. BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
  423. BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
  424. BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
  425. BPF_LD_MAP_FD(BPF_REG_1, 0),
  426. BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
  427. BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 0),
  428. BPF_EXIT_INSN(),
  429. },
  430. .fixup = {3},
  431. .errstr = "R0 invalid mem access 'map_value_or_null'",
  432. .result = REJECT,
  433. },
  434. {
  435. "access memory with incorrect alignment",
  436. .insns = {
  437. BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
  438. BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
  439. BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
  440. BPF_LD_MAP_FD(BPF_REG_1, 0),
  441. BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
  442. BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1),
  443. BPF_ST_MEM(BPF_DW, BPF_REG_0, 4, 0),
  444. BPF_EXIT_INSN(),
  445. },
  446. .fixup = {3},
  447. .errstr = "misaligned access",
  448. .result = REJECT,
  449. },
  450. {
  451. "sometimes access memory with incorrect alignment",
  452. .insns = {
  453. BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
  454. BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
  455. BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
  456. BPF_LD_MAP_FD(BPF_REG_1, 0),
  457. BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
  458. BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2),
  459. BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 0),
  460. BPF_EXIT_INSN(),
  461. BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 1),
  462. BPF_EXIT_INSN(),
  463. },
  464. .fixup = {3},
  465. .errstr = "R0 invalid mem access",
  466. .result = REJECT,
  467. },
  468. {
  469. "jump test 1",
  470. .insns = {
  471. BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
  472. BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, -8),
  473. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 1),
  474. BPF_ST_MEM(BPF_DW, BPF_REG_2, -8, 0),
  475. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 1, 1),
  476. BPF_ST_MEM(BPF_DW, BPF_REG_2, -16, 1),
  477. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 2, 1),
  478. BPF_ST_MEM(BPF_DW, BPF_REG_2, -8, 2),
  479. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 3, 1),
  480. BPF_ST_MEM(BPF_DW, BPF_REG_2, -16, 3),
  481. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 4, 1),
  482. BPF_ST_MEM(BPF_DW, BPF_REG_2, -8, 4),
  483. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 5, 1),
  484. BPF_ST_MEM(BPF_DW, BPF_REG_2, -32, 5),
  485. BPF_MOV64_IMM(BPF_REG_0, 0),
  486. BPF_EXIT_INSN(),
  487. },
  488. .result = ACCEPT,
  489. },
  490. {
  491. "jump test 2",
  492. .insns = {
  493. BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
  494. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 2),
  495. BPF_ST_MEM(BPF_DW, BPF_REG_2, -8, 0),
  496. BPF_JMP_IMM(BPF_JA, 0, 0, 14),
  497. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 1, 2),
  498. BPF_ST_MEM(BPF_DW, BPF_REG_2, -16, 0),
  499. BPF_JMP_IMM(BPF_JA, 0, 0, 11),
  500. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 2, 2),
  501. BPF_ST_MEM(BPF_DW, BPF_REG_2, -32, 0),
  502. BPF_JMP_IMM(BPF_JA, 0, 0, 8),
  503. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 3, 2),
  504. BPF_ST_MEM(BPF_DW, BPF_REG_2, -40, 0),
  505. BPF_JMP_IMM(BPF_JA, 0, 0, 5),
  506. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 4, 2),
  507. BPF_ST_MEM(BPF_DW, BPF_REG_2, -48, 0),
  508. BPF_JMP_IMM(BPF_JA, 0, 0, 2),
  509. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 5, 1),
  510. BPF_ST_MEM(BPF_DW, BPF_REG_2, -56, 0),
  511. BPF_MOV64_IMM(BPF_REG_0, 0),
  512. BPF_EXIT_INSN(),
  513. },
  514. .result = ACCEPT,
  515. },
  516. {
  517. "jump test 3",
  518. .insns = {
  519. BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
  520. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 3),
  521. BPF_ST_MEM(BPF_DW, BPF_REG_2, -8, 0),
  522. BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
  523. BPF_JMP_IMM(BPF_JA, 0, 0, 19),
  524. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 1, 3),
  525. BPF_ST_MEM(BPF_DW, BPF_REG_2, -16, 0),
  526. BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -16),
  527. BPF_JMP_IMM(BPF_JA, 0, 0, 15),
  528. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 2, 3),
  529. BPF_ST_MEM(BPF_DW, BPF_REG_2, -32, 0),
  530. BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -32),
  531. BPF_JMP_IMM(BPF_JA, 0, 0, 11),
  532. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 3, 3),
  533. BPF_ST_MEM(BPF_DW, BPF_REG_2, -40, 0),
  534. BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -40),
  535. BPF_JMP_IMM(BPF_JA, 0, 0, 7),
  536. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 4, 3),
  537. BPF_ST_MEM(BPF_DW, BPF_REG_2, -48, 0),
  538. BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -48),
  539. BPF_JMP_IMM(BPF_JA, 0, 0, 3),
  540. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 5, 0),
  541. BPF_ST_MEM(BPF_DW, BPF_REG_2, -56, 0),
  542. BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -56),
  543. BPF_LD_MAP_FD(BPF_REG_1, 0),
  544. BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_delete_elem),
  545. BPF_EXIT_INSN(),
  546. },
  547. .fixup = {24},
  548. .result = ACCEPT,
  549. },
  550. {
  551. "jump test 4",
  552. .insns = {
  553. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1),
  554. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2),
  555. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3),
  556. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4),
  557. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1),
  558. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2),
  559. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3),
  560. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4),
  561. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1),
  562. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2),
  563. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3),
  564. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4),
  565. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1),
  566. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2),
  567. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3),
  568. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4),
  569. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1),
  570. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2),
  571. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3),
  572. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4),
  573. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1),
  574. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2),
  575. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3),
  576. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4),
  577. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1),
  578. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2),
  579. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3),
  580. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4),
  581. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1),
  582. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2),
  583. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3),
  584. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4),
  585. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1),
  586. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2),
  587. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3),
  588. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4),
  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_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 0),
  593. BPF_MOV64_IMM(BPF_REG_0, 0),
  594. BPF_EXIT_INSN(),
  595. },
  596. .result = ACCEPT,
  597. },
  598. {
  599. "jump test 5",
  600. .insns = {
  601. BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
  602. BPF_MOV64_REG(BPF_REG_3, BPF_REG_2),
  603. BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 2),
  604. BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_3, -8),
  605. BPF_JMP_IMM(BPF_JA, 0, 0, 2),
  606. BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_2, -8),
  607. BPF_JMP_IMM(BPF_JA, 0, 0, 0),
  608. BPF_MOV64_IMM(BPF_REG_0, 0),
  609. BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 2),
  610. BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_3, -8),
  611. BPF_JMP_IMM(BPF_JA, 0, 0, 2),
  612. BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_2, -8),
  613. BPF_JMP_IMM(BPF_JA, 0, 0, 0),
  614. BPF_MOV64_IMM(BPF_REG_0, 0),
  615. BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 2),
  616. BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_3, -8),
  617. BPF_JMP_IMM(BPF_JA, 0, 0, 2),
  618. BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_2, -8),
  619. BPF_JMP_IMM(BPF_JA, 0, 0, 0),
  620. BPF_MOV64_IMM(BPF_REG_0, 0),
  621. BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 2),
  622. BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_3, -8),
  623. BPF_JMP_IMM(BPF_JA, 0, 0, 2),
  624. BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_2, -8),
  625. BPF_JMP_IMM(BPF_JA, 0, 0, 0),
  626. BPF_MOV64_IMM(BPF_REG_0, 0),
  627. BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 2),
  628. BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_3, -8),
  629. BPF_JMP_IMM(BPF_JA, 0, 0, 2),
  630. BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_2, -8),
  631. BPF_JMP_IMM(BPF_JA, 0, 0, 0),
  632. BPF_MOV64_IMM(BPF_REG_0, 0),
  633. BPF_EXIT_INSN(),
  634. },
  635. .result = ACCEPT,
  636. },
  637. };
  638. static int probe_filter_length(struct bpf_insn *fp)
  639. {
  640. int len = 0;
  641. for (len = MAX_INSNS - 1; len > 0; --len)
  642. if (fp[len].code != 0 || fp[len].imm != 0)
  643. break;
  644. return len + 1;
  645. }
  646. static int create_map(void)
  647. {
  648. long long key, value = 0;
  649. int map_fd;
  650. map_fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value), 1024);
  651. if (map_fd < 0) {
  652. printf("failed to create map '%s'\n", strerror(errno));
  653. }
  654. return map_fd;
  655. }
  656. static int test(void)
  657. {
  658. int prog_fd, i, pass_cnt = 0, err_cnt = 0;
  659. for (i = 0; i < ARRAY_SIZE(tests); i++) {
  660. struct bpf_insn *prog = tests[i].insns;
  661. int prog_len = probe_filter_length(prog);
  662. int *fixup = tests[i].fixup;
  663. int map_fd = -1;
  664. if (*fixup) {
  665. map_fd = create_map();
  666. do {
  667. prog[*fixup].imm = map_fd;
  668. fixup++;
  669. } while (*fixup);
  670. }
  671. printf("#%d %s ", i, tests[i].descr);
  672. prog_fd = bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER, prog,
  673. prog_len * sizeof(struct bpf_insn),
  674. "GPL");
  675. if (tests[i].result == ACCEPT) {
  676. if (prog_fd < 0) {
  677. printf("FAIL\nfailed to load prog '%s'\n",
  678. strerror(errno));
  679. printf("%s", bpf_log_buf);
  680. err_cnt++;
  681. goto fail;
  682. }
  683. } else {
  684. if (prog_fd >= 0) {
  685. printf("FAIL\nunexpected success to load\n");
  686. printf("%s", bpf_log_buf);
  687. err_cnt++;
  688. goto fail;
  689. }
  690. if (strstr(bpf_log_buf, tests[i].errstr) == 0) {
  691. printf("FAIL\nunexpected error message: %s",
  692. bpf_log_buf);
  693. err_cnt++;
  694. goto fail;
  695. }
  696. }
  697. pass_cnt++;
  698. printf("OK\n");
  699. fail:
  700. if (map_fd >= 0)
  701. close(map_fd);
  702. close(prog_fd);
  703. }
  704. printf("Summary: %d PASSED, %d FAILED\n", pass_cnt, err_cnt);
  705. return 0;
  706. }
  707. int main(void)
  708. {
  709. return test();
  710. }