test_verifier.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678
  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. "stack out of bounds",
  210. .insns = {
  211. BPF_ST_MEM(BPF_DW, BPF_REG_10, 8, 0),
  212. BPF_EXIT_INSN(),
  213. },
  214. .errstr = "invalid stack",
  215. .result = REJECT,
  216. },
  217. {
  218. "invalid call insn1",
  219. .insns = {
  220. BPF_RAW_INSN(BPF_JMP | BPF_CALL | BPF_X, 0, 0, 0, 0),
  221. BPF_EXIT_INSN(),
  222. },
  223. .errstr = "BPF_CALL uses reserved",
  224. .result = REJECT,
  225. },
  226. {
  227. "invalid call insn2",
  228. .insns = {
  229. BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 1, 0),
  230. BPF_EXIT_INSN(),
  231. },
  232. .errstr = "BPF_CALL uses reserved",
  233. .result = REJECT,
  234. },
  235. {
  236. "invalid function call",
  237. .insns = {
  238. BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, 1234567),
  239. BPF_EXIT_INSN(),
  240. },
  241. .errstr = "invalid func 1234567",
  242. .result = REJECT,
  243. },
  244. {
  245. "uninitialized stack1",
  246. .insns = {
  247. BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
  248. BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
  249. BPF_LD_MAP_FD(BPF_REG_1, 0),
  250. BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_unspec),
  251. BPF_EXIT_INSN(),
  252. },
  253. .fixup = {2},
  254. .errstr = "invalid indirect read from stack",
  255. .result = REJECT,
  256. },
  257. {
  258. "uninitialized stack2",
  259. .insns = {
  260. BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
  261. BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_2, -8),
  262. BPF_EXIT_INSN(),
  263. },
  264. .errstr = "invalid read from stack",
  265. .result = REJECT,
  266. },
  267. {
  268. "check valid spill/fill",
  269. .insns = {
  270. /* spill R1(ctx) into stack */
  271. BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_1, -8),
  272. /* fill it back into R2 */
  273. BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_10, -8),
  274. /* should be able to access R0 = *(R2 + 8) */
  275. BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_2, 8),
  276. BPF_EXIT_INSN(),
  277. },
  278. .result = ACCEPT,
  279. },
  280. {
  281. "check corrupted spill/fill",
  282. .insns = {
  283. /* spill R1(ctx) into stack */
  284. BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_1, -8),
  285. /* mess up with R1 pointer on stack */
  286. BPF_ST_MEM(BPF_B, BPF_REG_10, -7, 0x23),
  287. /* fill back into R0 should fail */
  288. BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_10, -8),
  289. BPF_EXIT_INSN(),
  290. },
  291. .errstr = "corrupted spill",
  292. .result = REJECT,
  293. },
  294. {
  295. "invalid src register in STX",
  296. .insns = {
  297. BPF_STX_MEM(BPF_B, BPF_REG_10, -1, -1),
  298. BPF_EXIT_INSN(),
  299. },
  300. .errstr = "R15 is invalid",
  301. .result = REJECT,
  302. },
  303. {
  304. "invalid dst register in STX",
  305. .insns = {
  306. BPF_STX_MEM(BPF_B, 14, BPF_REG_10, -1),
  307. BPF_EXIT_INSN(),
  308. },
  309. .errstr = "R14 is invalid",
  310. .result = REJECT,
  311. },
  312. {
  313. "invalid dst register in ST",
  314. .insns = {
  315. BPF_ST_MEM(BPF_B, 14, -1, -1),
  316. BPF_EXIT_INSN(),
  317. },
  318. .errstr = "R14 is invalid",
  319. .result = REJECT,
  320. },
  321. {
  322. "invalid src register in LDX",
  323. .insns = {
  324. BPF_LDX_MEM(BPF_B, BPF_REG_0, 12, 0),
  325. BPF_EXIT_INSN(),
  326. },
  327. .errstr = "R12 is invalid",
  328. .result = REJECT,
  329. },
  330. {
  331. "invalid dst register in LDX",
  332. .insns = {
  333. BPF_LDX_MEM(BPF_B, 11, BPF_REG_1, 0),
  334. BPF_EXIT_INSN(),
  335. },
  336. .errstr = "R11 is invalid",
  337. .result = REJECT,
  338. },
  339. {
  340. "junk insn",
  341. .insns = {
  342. BPF_RAW_INSN(0, 0, 0, 0, 0),
  343. BPF_EXIT_INSN(),
  344. },
  345. .errstr = "invalid BPF_LD_IMM",
  346. .result = REJECT,
  347. },
  348. {
  349. "junk insn2",
  350. .insns = {
  351. BPF_RAW_INSN(1, 0, 0, 0, 0),
  352. BPF_EXIT_INSN(),
  353. },
  354. .errstr = "BPF_LDX uses reserved fields",
  355. .result = REJECT,
  356. },
  357. {
  358. "junk insn3",
  359. .insns = {
  360. BPF_RAW_INSN(-1, 0, 0, 0, 0),
  361. BPF_EXIT_INSN(),
  362. },
  363. .errstr = "invalid BPF_ALU opcode f0",
  364. .result = REJECT,
  365. },
  366. {
  367. "junk insn4",
  368. .insns = {
  369. BPF_RAW_INSN(-1, -1, -1, -1, -1),
  370. BPF_EXIT_INSN(),
  371. },
  372. .errstr = "invalid BPF_ALU opcode f0",
  373. .result = REJECT,
  374. },
  375. {
  376. "junk insn5",
  377. .insns = {
  378. BPF_RAW_INSN(0x7f, -1, -1, -1, -1),
  379. BPF_EXIT_INSN(),
  380. },
  381. .errstr = "BPF_ALU uses reserved fields",
  382. .result = REJECT,
  383. },
  384. {
  385. "misaligned read from stack",
  386. .insns = {
  387. BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
  388. BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_2, -4),
  389. BPF_EXIT_INSN(),
  390. },
  391. .errstr = "misaligned access",
  392. .result = REJECT,
  393. },
  394. {
  395. "invalid map_fd for function call",
  396. .insns = {
  397. BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
  398. BPF_ALU64_REG(BPF_MOV, BPF_REG_2, BPF_REG_10),
  399. BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
  400. BPF_LD_MAP_FD(BPF_REG_1, 0),
  401. BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_unspec),
  402. BPF_EXIT_INSN(),
  403. },
  404. .errstr = "fd 0 is not pointing to valid bpf_map",
  405. .result = REJECT,
  406. },
  407. {
  408. "don't check return value before access",
  409. .insns = {
  410. BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
  411. BPF_MOV64_REG(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_unspec),
  415. BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 0),
  416. BPF_EXIT_INSN(),
  417. },
  418. .fixup = {3},
  419. .errstr = "R0 invalid mem access 'map_value_or_null'",
  420. .result = REJECT,
  421. },
  422. {
  423. "access memory with incorrect alignment",
  424. .insns = {
  425. BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
  426. BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
  427. BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
  428. BPF_LD_MAP_FD(BPF_REG_1, 0),
  429. BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_unspec),
  430. BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1),
  431. BPF_ST_MEM(BPF_DW, BPF_REG_0, 4, 0),
  432. BPF_EXIT_INSN(),
  433. },
  434. .fixup = {3},
  435. .errstr = "misaligned access",
  436. .result = REJECT,
  437. },
  438. {
  439. "sometimes access memory with incorrect alignment",
  440. .insns = {
  441. BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
  442. BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
  443. BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
  444. BPF_LD_MAP_FD(BPF_REG_1, 0),
  445. BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_unspec),
  446. BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2),
  447. BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 0),
  448. BPF_EXIT_INSN(),
  449. BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 1),
  450. BPF_EXIT_INSN(),
  451. },
  452. .fixup = {3},
  453. .errstr = "R0 invalid mem access",
  454. .result = REJECT,
  455. },
  456. {
  457. "jump test 1",
  458. .insns = {
  459. BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
  460. BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, -8),
  461. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 1),
  462. BPF_ST_MEM(BPF_DW, BPF_REG_2, -8, 0),
  463. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 1, 1),
  464. BPF_ST_MEM(BPF_DW, BPF_REG_2, -16, 1),
  465. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 2, 1),
  466. BPF_ST_MEM(BPF_DW, BPF_REG_2, -8, 2),
  467. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 3, 1),
  468. BPF_ST_MEM(BPF_DW, BPF_REG_2, -16, 3),
  469. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 4, 1),
  470. BPF_ST_MEM(BPF_DW, BPF_REG_2, -8, 4),
  471. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 5, 1),
  472. BPF_ST_MEM(BPF_DW, BPF_REG_2, -32, 5),
  473. BPF_MOV64_IMM(BPF_REG_0, 0),
  474. BPF_EXIT_INSN(),
  475. },
  476. .result = ACCEPT,
  477. },
  478. {
  479. "jump test 2",
  480. .insns = {
  481. BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
  482. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 2),
  483. BPF_ST_MEM(BPF_DW, BPF_REG_2, -8, 0),
  484. BPF_JMP_IMM(BPF_JA, 0, 0, 14),
  485. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 1, 2),
  486. BPF_ST_MEM(BPF_DW, BPF_REG_2, -16, 0),
  487. BPF_JMP_IMM(BPF_JA, 0, 0, 11),
  488. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 2, 2),
  489. BPF_ST_MEM(BPF_DW, BPF_REG_2, -32, 0),
  490. BPF_JMP_IMM(BPF_JA, 0, 0, 8),
  491. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 3, 2),
  492. BPF_ST_MEM(BPF_DW, BPF_REG_2, -40, 0),
  493. BPF_JMP_IMM(BPF_JA, 0, 0, 5),
  494. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 4, 2),
  495. BPF_ST_MEM(BPF_DW, BPF_REG_2, -48, 0),
  496. BPF_JMP_IMM(BPF_JA, 0, 0, 2),
  497. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 5, 1),
  498. BPF_ST_MEM(BPF_DW, BPF_REG_2, -56, 0),
  499. BPF_MOV64_IMM(BPF_REG_0, 0),
  500. BPF_EXIT_INSN(),
  501. },
  502. .result = ACCEPT,
  503. },
  504. {
  505. "jump test 3",
  506. .insns = {
  507. BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
  508. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 3),
  509. BPF_ST_MEM(BPF_DW, BPF_REG_2, -8, 0),
  510. BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
  511. BPF_JMP_IMM(BPF_JA, 0, 0, 19),
  512. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 1, 3),
  513. BPF_ST_MEM(BPF_DW, BPF_REG_2, -16, 0),
  514. BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -16),
  515. BPF_JMP_IMM(BPF_JA, 0, 0, 15),
  516. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 2, 3),
  517. BPF_ST_MEM(BPF_DW, BPF_REG_2, -32, 0),
  518. BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -32),
  519. BPF_JMP_IMM(BPF_JA, 0, 0, 11),
  520. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 3, 3),
  521. BPF_ST_MEM(BPF_DW, BPF_REG_2, -40, 0),
  522. BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -40),
  523. BPF_JMP_IMM(BPF_JA, 0, 0, 7),
  524. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 4, 3),
  525. BPF_ST_MEM(BPF_DW, BPF_REG_2, -48, 0),
  526. BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -48),
  527. BPF_JMP_IMM(BPF_JA, 0, 0, 3),
  528. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 5, 0),
  529. BPF_ST_MEM(BPF_DW, BPF_REG_2, -56, 0),
  530. BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -56),
  531. BPF_LD_MAP_FD(BPF_REG_1, 0),
  532. BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_unspec),
  533. BPF_EXIT_INSN(),
  534. },
  535. .fixup = {24},
  536. .result = ACCEPT,
  537. },
  538. {
  539. "jump test 4",
  540. .insns = {
  541. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1),
  542. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2),
  543. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3),
  544. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4),
  545. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1),
  546. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2),
  547. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3),
  548. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4),
  549. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1),
  550. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2),
  551. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3),
  552. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4),
  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, 0),
  578. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 0),
  579. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 0),
  580. BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 0),
  581. BPF_MOV64_IMM(BPF_REG_0, 0),
  582. BPF_EXIT_INSN(),
  583. },
  584. .result = ACCEPT,
  585. },
  586. };
  587. static int probe_filter_length(struct bpf_insn *fp)
  588. {
  589. int len = 0;
  590. for (len = MAX_INSNS - 1; len > 0; --len)
  591. if (fp[len].code != 0 || fp[len].imm != 0)
  592. break;
  593. return len + 1;
  594. }
  595. static int create_map(void)
  596. {
  597. long long key, value = 0;
  598. int map_fd;
  599. map_fd = bpf_create_map(BPF_MAP_TYPE_UNSPEC, sizeof(key), sizeof(value), 1024);
  600. if (map_fd < 0) {
  601. printf("failed to create map '%s'\n", strerror(errno));
  602. }
  603. return map_fd;
  604. }
  605. static int test(void)
  606. {
  607. int prog_fd, i;
  608. for (i = 0; i < ARRAY_SIZE(tests); i++) {
  609. struct bpf_insn *prog = tests[i].insns;
  610. int prog_len = probe_filter_length(prog);
  611. int *fixup = tests[i].fixup;
  612. int map_fd = -1;
  613. if (*fixup) {
  614. map_fd = create_map();
  615. do {
  616. prog[*fixup].imm = map_fd;
  617. fixup++;
  618. } while (*fixup);
  619. }
  620. printf("#%d %s ", i, tests[i].descr);
  621. prog_fd = bpf_prog_load(BPF_PROG_TYPE_UNSPEC, prog,
  622. prog_len * sizeof(struct bpf_insn),
  623. "GPL");
  624. if (tests[i].result == ACCEPT) {
  625. if (prog_fd < 0) {
  626. printf("FAIL\nfailed to load prog '%s'\n",
  627. strerror(errno));
  628. printf("%s", bpf_log_buf);
  629. goto fail;
  630. }
  631. } else {
  632. if (prog_fd >= 0) {
  633. printf("FAIL\nunexpected success to load\n");
  634. printf("%s", bpf_log_buf);
  635. goto fail;
  636. }
  637. if (strstr(bpf_log_buf, tests[i].errstr) == 0) {
  638. printf("FAIL\nunexpected error message: %s",
  639. bpf_log_buf);
  640. goto fail;
  641. }
  642. }
  643. printf("OK\n");
  644. fail:
  645. if (map_fd >= 0)
  646. close(map_fd);
  647. close(prog_fd);
  648. }
  649. return 0;
  650. }
  651. int main(void)
  652. {
  653. return test();
  654. }