Berkeley Packet Filter (BPF) assembler. https://godoc.org/maze.io/x/bpf
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

vm_jump_test.go 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710
  1. // Copyright (c) 2019 Wijnand Modderman-Lenstra. All rights reserved.
  2. // Copyright (c) 2016 The Go Authors. All rights reserved.
  3. // Use of this source code is governed by a BSD-style
  4. // license that can be found in the LICENSE file.
  5. package bpf_test
  6. import (
  7. "testing"
  8. "golang.org/x/net/bpf"
  9. )
  10. func TestVMJumpOne(t *testing.T) {
  11. vm, err := testVM(t, []bpf.Instruction{
  12. bpf.LoadAbsolute{
  13. Off: 8,
  14. Size: 1,
  15. },
  16. bpf.Jump{
  17. Skip: 1,
  18. },
  19. bpf.RetConstant{
  20. Val: 0,
  21. },
  22. bpf.RetConstant{
  23. Val: 9,
  24. },
  25. })
  26. if err != nil {
  27. t.Fatalf("failed to load BPF program: %v", err)
  28. }
  29. out, err := vm.Run([]byte{
  30. 0xff, 0xff, 0xff, 0xff,
  31. 0xff, 0xff, 0xff, 0xff,
  32. 1,
  33. })
  34. if err != nil {
  35. t.Fatalf("unexpected error while running program: %v", err)
  36. }
  37. if want, got := uint32(1), out; want != got {
  38. t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
  39. want, got)
  40. }
  41. }
  42. func TestVMJumpOutOfProgram(t *testing.T) {
  43. _, err := testVM(t, []bpf.Instruction{
  44. bpf.Jump{
  45. Skip: 1,
  46. },
  47. bpf.RetA{},
  48. })
  49. if errStr(err) != "bpf: cannot jump 1 instructions; jumping past program bounds" {
  50. t.Fatalf("unexpected error: %v", err)
  51. }
  52. }
  53. func TestVMJumpIfTrueOutOfProgram(t *testing.T) {
  54. _, err := testVM(t, []bpf.Instruction{
  55. bpf.JumpIf{
  56. Cond: bpf.JumpEqual,
  57. SkipTrue: 2,
  58. },
  59. bpf.RetA{},
  60. })
  61. if errStr(err) != "bpf: cannot jump 2 instructions in true case; jumping past program bounds" {
  62. t.Fatalf("unexpected error: %v", err)
  63. }
  64. }
  65. func TestVMJumpIfFalseOutOfProgram(t *testing.T) {
  66. _, err := testVM(t, []bpf.Instruction{
  67. bpf.JumpIf{
  68. Cond: bpf.JumpEqual,
  69. SkipFalse: 3,
  70. },
  71. bpf.RetA{},
  72. })
  73. if errStr(err) != "bpf: cannot jump 3 instructions in false case; jumping past program bounds" {
  74. t.Fatalf("unexpected error: %v", err)
  75. }
  76. }
  77. func TestVMJumpIfXTrueOutOfProgram(t *testing.T) {
  78. _, err := testVM(t, []bpf.Instruction{
  79. bpf.JumpIfX{
  80. Cond: bpf.JumpEqual,
  81. SkipTrue: 2,
  82. },
  83. bpf.RetA{},
  84. })
  85. if errStr(err) != "bpf: cannot jump 2 instructions in true case; jumping past program bounds" {
  86. t.Fatalf("unexpected error: %v", err)
  87. }
  88. }
  89. func TestVMJumpIfXFalseOutOfProgram(t *testing.T) {
  90. _, err := testVM(t, []bpf.Instruction{
  91. bpf.JumpIfX{
  92. Cond: bpf.JumpEqual,
  93. SkipFalse: 3,
  94. },
  95. bpf.RetA{},
  96. })
  97. if errStr(err) != "bpf: cannot jump 3 instructions in false case; jumping past program bounds" {
  98. t.Fatalf("unexpected error: %v", err)
  99. }
  100. }
  101. func TestVMJumpIfEqual(t *testing.T) {
  102. vm, err := testVM(t, []bpf.Instruction{
  103. bpf.LoadAbsolute{
  104. Off: 8,
  105. Size: 1,
  106. },
  107. bpf.JumpIf{
  108. Cond: bpf.JumpEqual,
  109. Val: 1,
  110. SkipTrue: 1,
  111. },
  112. bpf.RetConstant{
  113. Val: 0,
  114. },
  115. bpf.RetConstant{
  116. Val: 9,
  117. },
  118. })
  119. if err != nil {
  120. t.Fatalf("failed to load BPF program: %v", err)
  121. }
  122. out, err := vm.Run([]byte{
  123. 0xff, 0xff, 0xff, 0xff,
  124. 0xff, 0xff, 0xff, 0xff,
  125. 1,
  126. })
  127. if err != nil {
  128. t.Fatalf("unexpected error while running program: %v", err)
  129. }
  130. if want, got := uint32(1), out; want != got {
  131. t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
  132. want, got)
  133. }
  134. }
  135. func TestVMJumpIfNotEqual(t *testing.T) {
  136. vm, err := testVM(t, []bpf.Instruction{
  137. bpf.LoadAbsolute{
  138. Off: 8,
  139. Size: 1,
  140. },
  141. bpf.JumpIf{
  142. Cond: bpf.JumpNotEqual,
  143. Val: 1,
  144. SkipFalse: 1,
  145. },
  146. bpf.RetConstant{
  147. Val: 0,
  148. },
  149. bpf.RetConstant{
  150. Val: 9,
  151. },
  152. })
  153. if err != nil {
  154. t.Fatalf("failed to load BPF program: %v", err)
  155. }
  156. out, err := vm.Run([]byte{
  157. 0xff, 0xff, 0xff, 0xff,
  158. 0xff, 0xff, 0xff, 0xff,
  159. 1,
  160. })
  161. if err != nil {
  162. t.Fatalf("unexpected error while running program: %v", err)
  163. }
  164. if want, got := uint32(1), out; want != got {
  165. t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
  166. want, got)
  167. }
  168. }
  169. func TestVMJumpIfGreaterThan(t *testing.T) {
  170. vm, err := testVM(t, []bpf.Instruction{
  171. bpf.LoadAbsolute{
  172. Off: 8,
  173. Size: 4,
  174. },
  175. bpf.JumpIf{
  176. Cond: bpf.JumpGreaterThan,
  177. Val: 0x00010202,
  178. SkipTrue: 1,
  179. },
  180. bpf.RetConstant{
  181. Val: 0,
  182. },
  183. bpf.RetConstant{
  184. Val: 12,
  185. },
  186. })
  187. if err != nil {
  188. t.Fatalf("failed to load BPF program: %v", err)
  189. }
  190. out, err := vm.Run([]byte{
  191. 0xff, 0xff, 0xff, 0xff,
  192. 0xff, 0xff, 0xff, 0xff,
  193. 0, 1, 2, 3,
  194. })
  195. if err != nil {
  196. t.Fatalf("unexpected error while running program: %v", err)
  197. }
  198. if want, got := uint32(4), out; want != got {
  199. t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
  200. want, got)
  201. }
  202. }
  203. func TestVMJumpIfLessThan(t *testing.T) {
  204. vm, err := testVM(t, []bpf.Instruction{
  205. bpf.LoadAbsolute{
  206. Off: 8,
  207. Size: 4,
  208. },
  209. bpf.JumpIf{
  210. Cond: bpf.JumpLessThan,
  211. Val: 0xff010203,
  212. SkipTrue: 1,
  213. },
  214. bpf.RetConstant{
  215. Val: 0,
  216. },
  217. bpf.RetConstant{
  218. Val: 12,
  219. },
  220. })
  221. if err != nil {
  222. t.Fatalf("failed to load BPF program: %v", err)
  223. }
  224. out, err := vm.Run([]byte{
  225. 0xff, 0xff, 0xff, 0xff,
  226. 0xff, 0xff, 0xff, 0xff,
  227. 0, 1, 2, 3,
  228. })
  229. if err != nil {
  230. t.Fatalf("unexpected error while running program: %v", err)
  231. }
  232. if want, got := uint32(4), out; want != got {
  233. t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
  234. want, got)
  235. }
  236. }
  237. func TestVMJumpIfGreaterOrEqual(t *testing.T) {
  238. vm, err := testVM(t, []bpf.Instruction{
  239. bpf.LoadAbsolute{
  240. Off: 8,
  241. Size: 4,
  242. },
  243. bpf.JumpIf{
  244. Cond: bpf.JumpGreaterOrEqual,
  245. Val: 0x00010203,
  246. SkipTrue: 1,
  247. },
  248. bpf.RetConstant{
  249. Val: 0,
  250. },
  251. bpf.RetConstant{
  252. Val: 12,
  253. },
  254. })
  255. if err != nil {
  256. t.Fatalf("failed to load BPF program: %v", err)
  257. }
  258. out, err := vm.Run([]byte{
  259. 0xff, 0xff, 0xff, 0xff,
  260. 0xff, 0xff, 0xff, 0xff,
  261. 0, 1, 2, 3,
  262. })
  263. if err != nil {
  264. t.Fatalf("unexpected error while running program: %v", err)
  265. }
  266. if want, got := uint32(4), out; want != got {
  267. t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
  268. want, got)
  269. }
  270. }
  271. func TestVMJumpIfLessOrEqual(t *testing.T) {
  272. vm, err := testVM(t, []bpf.Instruction{
  273. bpf.LoadAbsolute{
  274. Off: 8,
  275. Size: 4,
  276. },
  277. bpf.JumpIf{
  278. Cond: bpf.JumpLessOrEqual,
  279. Val: 0xff010203,
  280. SkipTrue: 1,
  281. },
  282. bpf.RetConstant{
  283. Val: 0,
  284. },
  285. bpf.RetConstant{
  286. Val: 12,
  287. },
  288. })
  289. if err != nil {
  290. t.Fatalf("failed to load BPF program: %v", err)
  291. }
  292. out, err := vm.Run([]byte{
  293. 0xff, 0xff, 0xff, 0xff,
  294. 0xff, 0xff, 0xff, 0xff,
  295. 0, 1, 2, 3,
  296. })
  297. if err != nil {
  298. t.Fatalf("unexpected error while running program: %v", err)
  299. }
  300. if want, got := uint32(4), out; want != got {
  301. t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
  302. want, got)
  303. }
  304. }
  305. func TestVMJumpIfBitsSet(t *testing.T) {
  306. vm, err := testVM(t, []bpf.Instruction{
  307. bpf.LoadAbsolute{
  308. Off: 8,
  309. Size: 2,
  310. },
  311. bpf.JumpIf{
  312. Cond: bpf.JumpBitsSet,
  313. Val: 0x1122,
  314. SkipTrue: 1,
  315. },
  316. bpf.RetConstant{
  317. Val: 0,
  318. },
  319. bpf.RetConstant{
  320. Val: 10,
  321. },
  322. })
  323. if err != nil {
  324. t.Fatalf("failed to load BPF program: %v", err)
  325. }
  326. out, err := vm.Run([]byte{
  327. 0xff, 0xff, 0xff, 0xff,
  328. 0xff, 0xff, 0xff, 0xff,
  329. 0x01, 0x02,
  330. })
  331. if err != nil {
  332. t.Fatalf("unexpected error while running program: %v", err)
  333. }
  334. if want, got := uint32(2), out; want != got {
  335. t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
  336. want, got)
  337. }
  338. }
  339. func TestVMJumpIfBitsNotSet(t *testing.T) {
  340. vm, err := testVM(t, []bpf.Instruction{
  341. bpf.LoadAbsolute{
  342. Off: 8,
  343. Size: 2,
  344. },
  345. bpf.JumpIf{
  346. Cond: bpf.JumpBitsNotSet,
  347. Val: 0x1221,
  348. SkipTrue: 1,
  349. },
  350. bpf.RetConstant{
  351. Val: 0,
  352. },
  353. bpf.RetConstant{
  354. Val: 10,
  355. },
  356. })
  357. if err != nil {
  358. t.Fatalf("failed to load BPF program: %v", err)
  359. }
  360. out, err := vm.Run([]byte{
  361. 0xff, 0xff, 0xff, 0xff,
  362. 0xff, 0xff, 0xff, 0xff,
  363. 0x01, 0x02,
  364. })
  365. if err != nil {
  366. t.Fatalf("unexpected error while running program: %v", err)
  367. }
  368. if want, got := uint32(2), out; want != got {
  369. t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
  370. want, got)
  371. }
  372. }
  373. func TestVMJumpIfXEqual(t *testing.T) {
  374. vm, err := testVM(t, []bpf.Instruction{
  375. bpf.LoadAbsolute{
  376. Off: 8,
  377. Size: 1,
  378. },
  379. bpf.LoadConstant{
  380. Dst: bpf.RegX,
  381. Val: 1,
  382. },
  383. bpf.JumpIfX{
  384. Cond: bpf.JumpEqual,
  385. SkipTrue: 1,
  386. },
  387. bpf.RetConstant{
  388. Val: 0,
  389. },
  390. bpf.RetConstant{
  391. Val: 9,
  392. },
  393. })
  394. if err != nil {
  395. t.Fatalf("failed to load BPF program: %v", err)
  396. }
  397. out, err := vm.Run([]byte{
  398. 0xff, 0xff, 0xff, 0xff,
  399. 0xff, 0xff, 0xff, 0xff,
  400. 1,
  401. })
  402. if err != nil {
  403. t.Fatalf("unexpected error while running program: %v", err)
  404. }
  405. if want, got := uint32(1), out; want != got {
  406. t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
  407. want, got)
  408. }
  409. }
  410. func TestVMJumpIfXNotEqual(t *testing.T) {
  411. vm, err := testVM(t, []bpf.Instruction{
  412. bpf.LoadAbsolute{
  413. Off: 8,
  414. Size: 1,
  415. },
  416. bpf.LoadConstant{
  417. Dst: bpf.RegX,
  418. Val: 1,
  419. },
  420. bpf.JumpIfX{
  421. Cond: bpf.JumpNotEqual,
  422. SkipFalse: 1,
  423. },
  424. bpf.RetConstant{
  425. Val: 0,
  426. },
  427. bpf.RetConstant{
  428. Val: 9,
  429. },
  430. })
  431. if err != nil {
  432. t.Fatalf("failed to load BPF program: %v", err)
  433. }
  434. out, err := vm.Run([]byte{
  435. 0xff, 0xff, 0xff, 0xff,
  436. 0xff, 0xff, 0xff, 0xff,
  437. 1,
  438. })
  439. if err != nil {
  440. t.Fatalf("unexpected error while running program: %v", err)
  441. }
  442. if want, got := uint32(1), out; want != got {
  443. t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
  444. want, got)
  445. }
  446. }
  447. func TestVMJumpIfXGreaterThan(t *testing.T) {
  448. vm, err := testVM(t, []bpf.Instruction{
  449. bpf.LoadAbsolute{
  450. Off: 8,
  451. Size: 4,
  452. },
  453. bpf.LoadConstant{
  454. Dst: bpf.RegX,
  455. Val: 0x00010202,
  456. },
  457. bpf.JumpIfX{
  458. Cond: bpf.JumpGreaterThan,
  459. SkipTrue: 1,
  460. },
  461. bpf.RetConstant{
  462. Val: 0,
  463. },
  464. bpf.RetConstant{
  465. Val: 12,
  466. },
  467. })
  468. if err != nil {
  469. t.Fatalf("failed to load BPF program: %v", err)
  470. }
  471. out, err := vm.Run([]byte{
  472. 0xff, 0xff, 0xff, 0xff,
  473. 0xff, 0xff, 0xff, 0xff,
  474. 0, 1, 2, 3,
  475. })
  476. if err != nil {
  477. t.Fatalf("unexpected error while running program: %v", err)
  478. }
  479. if want, got := uint32(4), out; want != got {
  480. t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
  481. want, got)
  482. }
  483. }
  484. func TestVMJumpIfXLessThan(t *testing.T) {
  485. vm, err := testVM(t, []bpf.Instruction{
  486. bpf.LoadAbsolute{
  487. Off: 8,
  488. Size: 4,
  489. },
  490. bpf.LoadConstant{
  491. Dst: bpf.RegX,
  492. Val: 0xff010203,
  493. },
  494. bpf.JumpIfX{
  495. Cond: bpf.JumpLessThan,
  496. SkipTrue: 1,
  497. },
  498. bpf.RetConstant{
  499. Val: 0,
  500. },
  501. bpf.RetConstant{
  502. Val: 12,
  503. },
  504. })
  505. if err != nil {
  506. t.Fatalf("failed to load BPF program: %v", err)
  507. }
  508. out, err := vm.Run([]byte{
  509. 0xff, 0xff, 0xff, 0xff,
  510. 0xff, 0xff, 0xff, 0xff,
  511. 0, 1, 2, 3,
  512. })
  513. if err != nil {
  514. t.Fatalf("unexpected error while running program: %v", err)
  515. }
  516. if want, got := uint32(4), out; want != got {
  517. t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
  518. want, got)
  519. }
  520. }
  521. func TestVMJumpIfXGreaterOrEqual(t *testing.T) {
  522. vm, err := testVM(t, []bpf.Instruction{
  523. bpf.LoadAbsolute{
  524. Off: 8,
  525. Size: 4,
  526. },
  527. bpf.LoadConstant{
  528. Dst: bpf.RegX,
  529. Val: 0x00010203,
  530. },
  531. bpf.JumpIfX{
  532. Cond: bpf.JumpGreaterOrEqual,
  533. SkipTrue: 1,
  534. },
  535. bpf.RetConstant{
  536. Val: 0,
  537. },
  538. bpf.RetConstant{
  539. Val: 12,
  540. },
  541. })
  542. if err != nil {
  543. t.Fatalf("failed to load BPF program: %v", err)
  544. }
  545. out, err := vm.Run([]byte{
  546. 0xff, 0xff, 0xff, 0xff,
  547. 0xff, 0xff, 0xff, 0xff,
  548. 0, 1, 2, 3,
  549. })
  550. if err != nil {
  551. t.Fatalf("unexpected error while running program: %v", err)
  552. }
  553. if want, got := uint32(4), out; want != got {
  554. t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
  555. want, got)
  556. }
  557. }
  558. func TestVMJumpIfXLessOrEqual(t *testing.T) {
  559. vm, err := testVM(t, []bpf.Instruction{
  560. bpf.LoadAbsolute{
  561. Off: 8,
  562. Size: 4,
  563. },
  564. bpf.LoadConstant{
  565. Dst: bpf.RegX,
  566. Val: 0xff010203,
  567. },
  568. bpf.JumpIfX{
  569. Cond: bpf.JumpLessOrEqual,
  570. SkipTrue: 1,
  571. },
  572. bpf.RetConstant{
  573. Val: 0,
  574. },
  575. bpf.RetConstant{
  576. Val: 12,
  577. },
  578. })
  579. if err != nil {
  580. t.Fatalf("failed to load BPF program: %v", err)
  581. }
  582. out, err := vm.Run([]byte{
  583. 0xff, 0xff, 0xff, 0xff,
  584. 0xff, 0xff, 0xff, 0xff,
  585. 0, 1, 2, 3,
  586. })
  587. if err != nil {
  588. t.Fatalf("unexpected error while running program: %v", err)
  589. }
  590. if want, got := uint32(4), out; want != got {
  591. t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
  592. want, got)
  593. }
  594. }
  595. func TestVMJumpIfXBitsSet(t *testing.T) {
  596. vm, err := testVM(t, []bpf.Instruction{
  597. bpf.LoadAbsolute{
  598. Off: 8,
  599. Size: 2,
  600. },
  601. bpf.LoadConstant{
  602. Dst: bpf.RegX,
  603. Val: 0x1122,
  604. },
  605. bpf.JumpIfX{
  606. Cond: bpf.JumpBitsSet,
  607. SkipTrue: 1,
  608. },
  609. bpf.RetConstant{
  610. Val: 0,
  611. },
  612. bpf.RetConstant{
  613. Val: 10,
  614. },
  615. })
  616. if err != nil {
  617. t.Fatalf("failed to load BPF program: %v", err)
  618. }
  619. out, err := vm.Run([]byte{
  620. 0xff, 0xff, 0xff, 0xff,
  621. 0xff, 0xff, 0xff, 0xff,
  622. 0x01, 0x02,
  623. })
  624. if err != nil {
  625. t.Fatalf("unexpected error while running program: %v", err)
  626. }
  627. if want, got := uint32(2), out; want != got {
  628. t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
  629. want, got)
  630. }
  631. }
  632. func TestVMJumpIfXBitsNotSet(t *testing.T) {
  633. vm, err := testVM(t, []bpf.Instruction{
  634. bpf.LoadAbsolute{
  635. Off: 8,
  636. Size: 2,
  637. },
  638. bpf.LoadConstant{
  639. Dst: bpf.RegX,
  640. Val: 0x1221,
  641. },
  642. bpf.JumpIfX{
  643. Cond: bpf.JumpBitsNotSet,
  644. SkipTrue: 1,
  645. },
  646. bpf.RetConstant{
  647. Val: 0,
  648. },
  649. bpf.RetConstant{
  650. Val: 10,
  651. },
  652. })
  653. if err != nil {
  654. t.Fatalf("failed to load BPF program: %v", err)
  655. }
  656. out, err := vm.Run([]byte{
  657. 0xff, 0xff, 0xff, 0xff,
  658. 0xff, 0xff, 0xff, 0xff,
  659. 0x01, 0x02,
  660. })
  661. if err != nil {
  662. t.Fatalf("unexpected error while running program: %v", err)
  663. }
  664. if want, got := uint32(2), out; want != got {
  665. t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
  666. want, got)
  667. }
  668. }