Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

bpf: Right align verifier states in verifier logs.

Make the verifier logs more readable, print the verifier states
on the corresponding instruction line. If the previous line was
not a bpf instruction, then print the verifier states on its own
line.

Before:

Validating test_pkt_access_subprog3() func#3...
86: R1=invP(id=0) R2=ctx(id=0,off=0,imm=0) R10=fp0
; int test_pkt_access_subprog3(int val, struct __sk_buff *skb)
86: (bf) r6 = r2
87: R2=ctx(id=0,off=0,imm=0) R6_w=ctx(id=0,off=0,imm=0)
87: (bc) w7 = w1
88: R1=invP(id=0) R7_w=invP(id=0,umax_value=4294967295,var_off=(0x0; 0xffffffff))
; return get_skb_len(skb) * get_skb_ifindex(val, skb, get_constant(123));
88: (bf) r1 = r6
89: R1_w=ctx(id=0,off=0,imm=0) R6_w=ctx(id=0,off=0,imm=0)
89: (85) call pc+9
Func#4 is global and valid. Skipping.
90: R0_w=invP(id=0)
90: (bc) w8 = w0
91: R0_w=invP(id=0) R8_w=invP(id=0,umax_value=4294967295,var_off=(0x0; 0xffffffff))
; return get_skb_len(skb) * get_skb_ifindex(val, skb, get_constant(123));
91: (b7) r1 = 123
92: R1_w=invP123
92: (85) call pc+65
Func#5 is global and valid. Skipping.
93: R0=invP(id=0)

After:

86: R1=invP(id=0) R2=ctx(id=0,off=0,imm=0) R10=fp0
; int test_pkt_access_subprog3(int val, struct __sk_buff *skb)
86: (bf) r6 = r2 ; R2=ctx(id=0,off=0,imm=0) R6_w=ctx(id=0,off=0,imm=0)
87: (bc) w7 = w1 ; R1=invP(id=0) R7_w=invP(id=0,umax_value=4294967295,var_off=(0x0; 0xffffffff))
; return get_skb_len(skb) * get_skb_ifindex(val, skb, get_constant(123));
88: (bf) r1 = r6 ; R1_w=ctx(id=0,off=0,imm=0) R6_w=ctx(id=0,off=0,imm=0)
89: (85) call pc+9
Func#4 is global and valid. Skipping.
90: R0_w=invP(id=0)
90: (bc) w8 = w0 ; R0_w=invP(id=0) R8_w=invP(id=0,umax_value=4294967295,var_off=(0x0; 0xffffffff))
; return get_skb_len(skb) * get_skb_ifindex(val, skb, get_constant(123));
91: (b7) r1 = 123 ; R1_w=invP123
92: (85) call pc+65
Func#5 is global and valid. Skipping.
93: R0=invP(id=0)

Signed-off-by: Christy Lee <christylee@fb.com>
Acked-by: Andrii Nakryiko <andrii@kernel.org>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

authored by

Christy Lee and committed by
Alexei Starovoitov
2e576648 0f55f9ed

+131 -98
+3
include/linux/bpf_verifier.h
··· 388 388 #define BPF_LOG_LEVEL (BPF_LOG_LEVEL1 | BPF_LOG_LEVEL2) 389 389 #define BPF_LOG_MASK (BPF_LOG_LEVEL | BPF_LOG_STATS) 390 390 #define BPF_LOG_KERNEL (BPF_LOG_MASK + 1) /* kernel internal flag */ 391 + #define BPF_LOG_MIN_ALIGNMENT 8U 392 + #define BPF_LOG_ALIGNMENT 40U 391 393 392 394 static inline bool bpf_verifier_log_needed(const struct bpf_verifier_log *log) 393 395 { ··· 483 481 u32 scratched_regs; 484 482 /* Same as scratched_regs but for stack slots */ 485 483 u64 scratched_stack_slots; 484 + u32 prev_log_len, prev_insn_print_len; 486 485 }; 487 486 488 487 __printf(2, 0) void bpf_verifier_vlog(struct bpf_verifier_log *log,
+36 -21
kernel/bpf/verifier.c
··· 797 797 mark_verifier_state_clean(env); 798 798 } 799 799 800 + static inline u32 vlog_alignment(u32 pos) 801 + { 802 + return round_up(max(pos + BPF_LOG_MIN_ALIGNMENT / 2, BPF_LOG_ALIGNMENT), 803 + BPF_LOG_MIN_ALIGNMENT) - pos - 1; 804 + } 805 + 806 + static void print_insn_state(struct bpf_verifier_env *env, 807 + const struct bpf_func_state *state) 808 + { 809 + if (env->prev_log_len && env->prev_log_len == env->log.len_used) { 810 + /* remove new line character */ 811 + bpf_vlog_reset(&env->log, env->prev_log_len - 1); 812 + verbose(env, "%*c;", vlog_alignment(env->prev_insn_print_len), ' '); 813 + } else { 814 + verbose(env, "%d:", env->insn_idx); 815 + } 816 + print_verifier_state(env, state, false); 817 + } 818 + 800 819 /* copy array src of length n * size bytes to dst. dst is reallocated if it's too 801 820 * small to hold src. This is different from krealloc since we don't want to preserve 802 821 * the contents of dst. ··· 2744 2725 reg->precise = true; 2745 2726 } 2746 2727 if (env->log.level & BPF_LOG_LEVEL) { 2747 - print_verifier_state(env, func, false); 2748 - verbose(env, "parent %s regs=%x stack=%llx marks\n", 2728 + verbose(env, "parent %s regs=%x stack=%llx marks:", 2749 2729 new_marks ? "didn't have" : "already had", 2750 2730 reg_mask, stack_mask); 2731 + print_verifier_state(env, func, true); 2751 2732 } 2752 2733 2753 2734 if (!reg_mask && !stack_mask) ··· 3442 3423 /* We may have adjusted the register pointing to memory region, so we 3443 3424 * need to try adding each of min_value and max_value to off 3444 3425 * to make sure our theoretical access will be safe. 3445 - */ 3446 - if (env->log.level & BPF_LOG_LEVEL) 3447 - print_verifier_state(env, state, false); 3448 - 3449 - /* The minimum value is only important with signed 3426 + * 3427 + * The minimum value is only important with signed 3450 3428 * comparisons where we can't assume the floor of a 3451 3429 * value is 0. If we are using signed variables for our 3452 3430 * index'es we need to make sure that whatever we use ··· 9454 9438 return -EACCES; 9455 9439 } 9456 9440 if (env->log.level & BPF_LOG_LEVEL) 9457 - print_verifier_state(env, this_branch->frame[this_branch->curframe], false); 9441 + print_insn_state(env, this_branch->frame[this_branch->curframe]); 9458 9442 return 0; 9459 9443 } 9460 9444 ··· 11322 11306 if (need_resched()) 11323 11307 cond_resched(); 11324 11308 11325 - if (env->log.level & BPF_LOG_LEVEL2 || 11326 - (env->log.level & BPF_LOG_LEVEL && do_print_state)) { 11327 - if (env->log.level & BPF_LOG_LEVEL2) { 11328 - if (verifier_state_scratched(env)) 11329 - verbose(env, "%d:", env->insn_idx); 11330 - } else { 11331 - verbose(env, "\nfrom %d to %d%s:", 11332 - env->prev_insn_idx, env->insn_idx, 11333 - env->cur_state->speculative ? 11334 - " (speculative execution)" : ""); 11335 - } 11336 - print_verifier_state(env, state->frame[state->curframe], 11337 - false); 11309 + if (env->log.level & BPF_LOG_LEVEL2 && do_print_state) { 11310 + verbose(env, "\nfrom %d to %d%s:", 11311 + env->prev_insn_idx, env->insn_idx, 11312 + env->cur_state->speculative ? 11313 + " (speculative execution)" : ""); 11314 + print_verifier_state(env, state->frame[state->curframe], true); 11338 11315 do_print_state = false; 11339 11316 } 11340 11317 ··· 11338 11329 .private_data = env, 11339 11330 }; 11340 11331 11332 + if (verifier_state_scratched(env)) 11333 + print_insn_state(env, state->frame[state->curframe]); 11334 + 11341 11335 verbose_linfo(env, env->insn_idx, "; "); 11336 + env->prev_log_len = env->log.len_used; 11342 11337 verbose(env, "%d: ", env->insn_idx); 11343 11338 print_bpf_insn(&cbs, insn, env->allow_ptr_leaks); 11339 + env->prev_insn_print_len = env->log.len_used - env->prev_log_len; 11340 + env->prev_log_len = env->log.len_used; 11344 11341 } 11345 11342 11346 11343 if (bpf_prog_is_dev_bound(env->prog->aux)) {
+92 -77
tools/testing/selftests/bpf/prog_tests/align.c
··· 41 41 .matches = { 42 42 {0, "R1=ctx(id=0,off=0,imm=0)"}, 43 43 {0, "R10=fp0"}, 44 - {1, "R3_w=inv2"}, 45 - {2, "R3_w=inv4"}, 46 - {3, "R3_w=inv8"}, 47 - {4, "R3_w=inv16"}, 48 - {5, "R3_w=inv32"}, 44 + {0, "R3_w=inv2"}, 45 + {1, "R3_w=inv4"}, 46 + {2, "R3_w=inv8"}, 47 + {3, "R3_w=inv16"}, 48 + {4, "R3_w=inv32"}, 49 49 }, 50 50 }, 51 51 { ··· 69 69 .matches = { 70 70 {0, "R1=ctx(id=0,off=0,imm=0)"}, 71 71 {0, "R10=fp0"}, 72 - {1, "R3_w=inv1"}, 73 - {2, "R3_w=inv2"}, 74 - {3, "R3_w=inv4"}, 75 - {4, "R3_w=inv8"}, 76 - {5, "R3_w=inv16"}, 77 - {6, "R3_w=inv1"}, 78 - {7, "R4_w=inv32"}, 79 - {8, "R4_w=inv16"}, 80 - {9, "R4_w=inv8"}, 81 - {10, "R4_w=inv4"}, 82 - {11, "R4_w=inv2"}, 72 + {0, "R3_w=inv1"}, 73 + {1, "R3_w=inv2"}, 74 + {2, "R3_w=inv4"}, 75 + {3, "R3_w=inv8"}, 76 + {4, "R3_w=inv16"}, 77 + {5, "R3_w=inv1"}, 78 + {6, "R4_w=inv32"}, 79 + {7, "R4_w=inv16"}, 80 + {8, "R4_w=inv8"}, 81 + {9, "R4_w=inv4"}, 82 + {10, "R4_w=inv2"}, 83 83 }, 84 84 }, 85 85 { ··· 98 98 .matches = { 99 99 {0, "R1=ctx(id=0,off=0,imm=0)"}, 100 100 {0, "R10=fp0"}, 101 - {1, "R3_w=inv4"}, 102 - {2, "R3_w=inv8"}, 103 - {3, "R3_w=inv10"}, 104 - {4, "R4_w=inv8"}, 105 - {5, "R4_w=inv12"}, 106 - {6, "R4_w=inv14"}, 101 + {0, "R3_w=inv4"}, 102 + {1, "R3_w=inv8"}, 103 + {2, "R3_w=inv10"}, 104 + {3, "R4_w=inv8"}, 105 + {4, "R4_w=inv12"}, 106 + {5, "R4_w=inv14"}, 107 107 }, 108 108 }, 109 109 { ··· 120 120 .matches = { 121 121 {0, "R1=ctx(id=0,off=0,imm=0)"}, 122 122 {0, "R10=fp0"}, 123 + {0, "R3_w=inv7"}, 123 124 {1, "R3_w=inv7"}, 124 - {2, "R3_w=inv7"}, 125 - {3, "R3_w=inv14"}, 126 - {4, "R3_w=inv56"}, 125 + {2, "R3_w=inv14"}, 126 + {3, "R3_w=inv56"}, 127 127 }, 128 128 }, 129 129 ··· 162 162 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 163 163 .matches = { 164 164 {6, "R0_w=pkt(id=0,off=8,r=8,imm=0)"}, 165 - {7, "R3_w=inv(id=0,umax_value=255,var_off=(0x0; 0xff))"}, 166 - {8, "R3_w=inv(id=0,umax_value=510,var_off=(0x0; 0x1fe))"}, 167 - {9, "R3_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"}, 168 - {10, "R3_w=inv(id=0,umax_value=2040,var_off=(0x0; 0x7f8))"}, 169 - {11, "R3_w=inv(id=0,umax_value=4080,var_off=(0x0; 0xff0))"}, 170 - {13, "R3_w=pkt_end(id=0,off=0,imm=0)"}, 171 - {18, "R4_w=inv(id=0,umax_value=255,var_off=(0x0; 0xff))"}, 172 - {19, "R4_w=inv(id=0,umax_value=8160,var_off=(0x0; 0x1fe0))"}, 173 - {20, "R4_w=inv(id=0,umax_value=4080,var_off=(0x0; 0xff0))"}, 174 - {21, "R4_w=inv(id=0,umax_value=2040,var_off=(0x0; 0x7f8))"}, 175 - {22, "R4_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"}, 176 - {23, "R4_w=inv(id=0,umax_value=510,var_off=(0x0; 0x1fe))"}, 165 + {6, "R3_w=inv(id=0,umax_value=255,var_off=(0x0; 0xff))"}, 166 + {7, "R3_w=inv(id=0,umax_value=510,var_off=(0x0; 0x1fe))"}, 167 + {8, "R3_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"}, 168 + {9, "R3_w=inv(id=0,umax_value=2040,var_off=(0x0; 0x7f8))"}, 169 + {10, "R3_w=inv(id=0,umax_value=4080,var_off=(0x0; 0xff0))"}, 170 + {12, "R3_w=pkt_end(id=0,off=0,imm=0)"}, 171 + {17, "R4_w=inv(id=0,umax_value=255,var_off=(0x0; 0xff))"}, 172 + {18, "R4_w=inv(id=0,umax_value=8160,var_off=(0x0; 0x1fe0))"}, 173 + {19, "R4_w=inv(id=0,umax_value=4080,var_off=(0x0; 0xff0))"}, 174 + {20, "R4_w=inv(id=0,umax_value=2040,var_off=(0x0; 0x7f8))"}, 175 + {21, "R4_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"}, 176 + {22, "R4_w=inv(id=0,umax_value=510,var_off=(0x0; 0x1fe))"}, 177 177 }, 178 178 }, 179 179 { ··· 194 194 }, 195 195 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 196 196 .matches = { 197 - {7, "R3_w=inv(id=0,umax_value=255,var_off=(0x0; 0xff))"}, 198 - {8, "R4_w=inv(id=1,umax_value=255,var_off=(0x0; 0xff))"}, 199 - {9, "R4_w=inv(id=0,umax_value=255,var_off=(0x0; 0xff))"}, 200 - {10, "R4_w=inv(id=1,umax_value=255,var_off=(0x0; 0xff))"}, 201 - {11, "R4_w=inv(id=0,umax_value=510,var_off=(0x0; 0x1fe))"}, 202 - {12, "R4_w=inv(id=1,umax_value=255,var_off=(0x0; 0xff))"}, 203 - {13, "R4_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"}, 204 - {14, "R4_w=inv(id=1,umax_value=255,var_off=(0x0; 0xff))"}, 205 - {15, "R4_w=inv(id=0,umax_value=2040,var_off=(0x0; 0x7f8))"}, 206 - {16, "R4_w=inv(id=0,umax_value=4080,var_off=(0x0; 0xff0))"}, 197 + {6, "R3_w=inv(id=0,umax_value=255,var_off=(0x0; 0xff))"}, 198 + {7, "R4_w=inv(id=1,umax_value=255,var_off=(0x0; 0xff))"}, 199 + {8, "R4_w=inv(id=0,umax_value=255,var_off=(0x0; 0xff))"}, 200 + {9, "R4_w=inv(id=1,umax_value=255,var_off=(0x0; 0xff))"}, 201 + {10, "R4_w=inv(id=0,umax_value=510,var_off=(0x0; 0x1fe))"}, 202 + {11, "R4_w=inv(id=1,umax_value=255,var_off=(0x0; 0xff))"}, 203 + {12, "R4_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"}, 204 + {13, "R4_w=inv(id=1,umax_value=255,var_off=(0x0; 0xff))"}, 205 + {14, "R4_w=inv(id=0,umax_value=2040,var_off=(0x0; 0x7f8))"}, 206 + {15, "R4_w=inv(id=0,umax_value=4080,var_off=(0x0; 0xff0))"}, 207 207 }, 208 208 }, 209 209 { ··· 234 234 }, 235 235 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 236 236 .matches = { 237 - {3, "R5_w=pkt(id=0,off=0,r=0,imm=0)"}, 238 - {5, "R5_w=pkt(id=0,off=14,r=0,imm=0)"}, 239 - {6, "R4_w=pkt(id=0,off=14,r=0,imm=0)"}, 237 + {2, "R5_w=pkt(id=0,off=0,r=0,imm=0)"}, 238 + {4, "R5_w=pkt(id=0,off=14,r=0,imm=0)"}, 239 + {5, "R4_w=pkt(id=0,off=14,r=0,imm=0)"}, 240 240 {9, "R2=pkt(id=0,off=0,r=18,imm=0)"}, 241 241 {10, "R5=pkt(id=0,off=14,r=18,imm=0)"}, 242 242 {10, "R4_w=inv(id=0,umax_value=255,var_off=(0x0; 0xff))"}, 243 + {13, "R4_w=inv(id=0,umax_value=65535,var_off=(0x0; 0xffff))"}, 243 244 {14, "R4_w=inv(id=0,umax_value=65535,var_off=(0x0; 0xffff))"}, 244 - {15, "R4_w=inv(id=0,umax_value=65535,var_off=(0x0; 0xffff))"}, 245 245 }, 246 246 }, 247 247 { ··· 297 297 * alignment of 4. 298 298 */ 299 299 {6, "R2_w=pkt(id=0,off=0,r=8,imm=0)"}, 300 - {8, "R6_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"}, 300 + {7, "R6_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"}, 301 301 /* Offset is added to packet pointer R5, resulting in 302 302 * known fixed offset, and variable offset from R6. 303 303 */ ··· 313 313 /* Variable offset is added to R5 packet pointer, 314 314 * resulting in auxiliary alignment of 4. 315 315 */ 316 - {18, "R5_w=pkt(id=2,off=0,r=0,umax_value=1020,var_off=(0x0; 0x3fc))"}, 316 + {17, "R5_w=pkt(id=2,off=0,r=0,umax_value=1020,var_off=(0x0; 0x3fc))"}, 317 317 /* Constant offset is added to R5, resulting in 318 318 * reg->off of 14. 319 319 */ 320 - {19, "R5_w=pkt(id=2,off=14,r=0,umax_value=1020,var_off=(0x0; 0x3fc))"}, 320 + {18, "R5_w=pkt(id=2,off=14,r=0,umax_value=1020,var_off=(0x0; 0x3fc))"}, 321 321 /* At the time the word size load is performed from R5, 322 322 * its total fixed offset is NET_IP_ALIGN + reg->off 323 323 * (14) which is 16. Then the variable offset is 4-byte ··· 329 329 /* Constant offset is added to R5 packet pointer, 330 330 * resulting in reg->off value of 14. 331 331 */ 332 - {26, "R5_w=pkt(id=0,off=14,r=8"}, 332 + {25, "R5_w=pkt(id=0,off=14,r=8"}, 333 333 /* Variable offset is added to R5, resulting in a 334 334 * variable offset of (4n). 335 335 */ 336 - {27, "R5_w=pkt(id=3,off=14,r=0,umax_value=1020,var_off=(0x0; 0x3fc))"}, 336 + {26, "R5_w=pkt(id=3,off=14,r=0,umax_value=1020,var_off=(0x0; 0x3fc))"}, 337 337 /* Constant is added to R5 again, setting reg->off to 18. */ 338 - {28, "R5_w=pkt(id=3,off=18,r=0,umax_value=1020,var_off=(0x0; 0x3fc))"}, 338 + {27, "R5_w=pkt(id=3,off=18,r=0,umax_value=1020,var_off=(0x0; 0x3fc))"}, 339 339 /* And once more we add a variable; resulting var_off 340 340 * is still (4n), fixed offset is not changed. 341 341 * Also, we create a new reg->id. 342 342 */ 343 - {29, "R5_w=pkt(id=4,off=18,r=0,umax_value=2040,var_off=(0x0; 0x7fc)"}, 343 + {28, "R5_w=pkt(id=4,off=18,r=0,umax_value=2040,var_off=(0x0; 0x7fc)"}, 344 344 /* At the time the word size load is performed from R5, 345 345 * its total fixed offset is NET_IP_ALIGN + reg->off (18) 346 346 * which is 20. Then the variable offset is (4n), so ··· 387 387 * alignment of 4. 388 388 */ 389 389 {6, "R2_w=pkt(id=0,off=0,r=8,imm=0)"}, 390 - {8, "R6_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"}, 390 + {7, "R6_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"}, 391 391 /* Adding 14 makes R6 be (4n+2) */ 392 - {9, "R6_w=inv(id=0,umin_value=14,umax_value=1034,var_off=(0x2; 0x7fc))"}, 392 + {8, "R6_w=inv(id=0,umin_value=14,umax_value=1034,var_off=(0x2; 0x7fc))"}, 393 393 /* Packet pointer has (4n+2) offset */ 394 394 {11, "R5_w=pkt(id=1,off=0,r=0,umin_value=14,umax_value=1034,var_off=(0x2; 0x7fc)"}, 395 - {13, "R4=pkt(id=1,off=4,r=0,umin_value=14,umax_value=1034,var_off=(0x2; 0x7fc)"}, 395 + {12, "R4=pkt(id=1,off=4,r=0,umin_value=14,umax_value=1034,var_off=(0x2; 0x7fc)"}, 396 396 /* At the time the word size load is performed from R5, 397 397 * its total fixed offset is NET_IP_ALIGN + reg->off (0) 398 398 * which is 2. Then the variable offset is (4n+2), so ··· 403 403 /* Newly read value in R6 was shifted left by 2, so has 404 404 * known alignment of 4. 405 405 */ 406 - {18, "R6_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"}, 406 + {17, "R6_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"}, 407 407 /* Added (4n) to packet pointer's (4n+2) var_off, giving 408 408 * another (4n+2). 409 409 */ 410 410 {19, "R5_w=pkt(id=2,off=0,r=0,umin_value=14,umax_value=2054,var_off=(0x2; 0xffc)"}, 411 - {21, "R4=pkt(id=2,off=4,r=0,umin_value=14,umax_value=2054,var_off=(0x2; 0xffc)"}, 411 + {20, "R4=pkt(id=2,off=4,r=0,umin_value=14,umax_value=2054,var_off=(0x2; 0xffc)"}, 412 412 /* At the time the word size load is performed from R5, 413 413 * its total fixed offset is NET_IP_ALIGN + reg->off (0) 414 414 * which is 2. Then the variable offset is (4n+2), so ··· 448 448 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 449 449 .result = REJECT, 450 450 .matches = { 451 - {4, "R5_w=pkt_end(id=0,off=0,imm=0)"}, 451 + {3, "R5_w=pkt_end(id=0,off=0,imm=0)"}, 452 452 /* (ptr - ptr) << 2 == unknown, (4n) */ 453 - {6, "R5_w=inv(id=0,smax_value=9223372036854775804,umax_value=18446744073709551612,var_off=(0x0; 0xfffffffffffffffc)"}, 453 + {5, "R5_w=inv(id=0,smax_value=9223372036854775804,umax_value=18446744073709551612,var_off=(0x0; 0xfffffffffffffffc)"}, 454 454 /* (4n) + 14 == (4n+2). We blow our bounds, because 455 455 * the add could overflow. 456 456 */ 457 - {7, "R5_w=inv(id=0,smin_value=-9223372036854775806,smax_value=9223372036854775806,umin_value=2,umax_value=18446744073709551614,var_off=(0x2; 0xfffffffffffffffc)"}, 457 + {6, "R5_w=inv(id=0,smin_value=-9223372036854775806,smax_value=9223372036854775806,umin_value=2,umax_value=18446744073709551614,var_off=(0x2; 0xfffffffffffffffc)"}, 458 458 /* Checked s>=0 */ 459 459 {9, "R5=inv(id=0,umin_value=2,umax_value=9223372036854775806,var_off=(0x2; 0x7ffffffffffffffc)"}, 460 460 /* packet pointer + nonnegative (4n+2) */ 461 - {12, "R6_w=pkt(id=1,off=0,r=0,umin_value=2,umax_value=9223372036854775806,var_off=(0x2; 0x7ffffffffffffffc)"}, 462 - {13, "R4_w=pkt(id=1,off=4,r=0,umin_value=2,umax_value=9223372036854775806,var_off=(0x2; 0x7ffffffffffffffc)"}, 461 + {11, "R6_w=pkt(id=1,off=0,r=0,umin_value=2,umax_value=9223372036854775806,var_off=(0x2; 0x7ffffffffffffffc)"}, 462 + {12, "R4_w=pkt(id=1,off=4,r=0,umin_value=2,umax_value=9223372036854775806,var_off=(0x2; 0x7ffffffffffffffc)"}, 463 463 /* NET_IP_ALIGN + (4n+2) == (4n), alignment is fine. 464 464 * We checked the bounds, but it might have been able 465 465 * to overflow if the packet pointer started in the ··· 502 502 /* Calculated offset in R6 has unknown value, but known 503 503 * alignment of 4. 504 504 */ 505 - {7, "R2_w=pkt(id=0,off=0,r=8,imm=0)"}, 506 - {9, "R6_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"}, 505 + {6, "R2_w=pkt(id=0,off=0,r=8,imm=0)"}, 506 + {8, "R6_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"}, 507 507 /* Adding 14 makes R6 be (4n+2) */ 508 - {10, "R6_w=inv(id=0,umin_value=14,umax_value=1034,var_off=(0x2; 0x7fc))"}, 508 + {9, "R6_w=inv(id=0,umin_value=14,umax_value=1034,var_off=(0x2; 0x7fc))"}, 509 509 /* New unknown value in R7 is (4n) */ 510 - {11, "R7_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"}, 510 + {10, "R7_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"}, 511 511 /* Subtracting it from R6 blows our unsigned bounds */ 512 - {12, "R6=inv(id=0,smin_value=-1006,smax_value=1034,umin_value=2,umax_value=18446744073709551614,var_off=(0x2; 0xfffffffffffffffc)"}, 512 + {11, "R6=inv(id=0,smin_value=-1006,smax_value=1034,umin_value=2,umax_value=18446744073709551614,var_off=(0x2; 0xfffffffffffffffc)"}, 513 513 /* Checked s>= 0 */ 514 514 {14, "R6=inv(id=0,umin_value=2,umax_value=1034,var_off=(0x2; 0x7fc))"}, 515 515 /* At the time the word size load is performed from R5, ··· 556 556 /* Calculated offset in R6 has unknown value, but known 557 557 * alignment of 4. 558 558 */ 559 - {7, "R2_w=pkt(id=0,off=0,r=8,imm=0)"}, 560 - {10, "R6_w=inv(id=0,umax_value=60,var_off=(0x0; 0x3c))"}, 559 + {6, "R2_w=pkt(id=0,off=0,r=8,imm=0)"}, 560 + {9, "R6_w=inv(id=0,umax_value=60,var_off=(0x0; 0x3c))"}, 561 561 /* Adding 14 makes R6 be (4n+2) */ 562 - {11, "R6_w=inv(id=0,umin_value=14,umax_value=74,var_off=(0x2; 0x7c))"}, 562 + {10, "R6_w=inv(id=0,umin_value=14,umax_value=74,var_off=(0x2; 0x7c))"}, 563 563 /* Subtracting from packet pointer overflows ubounds */ 564 564 {13, "R5_w=pkt(id=2,off=0,r=8,umin_value=18446744073709551542,umax_value=18446744073709551602,var_off=(0xffffffffffffff82; 0x7c)"}, 565 565 /* New unknown value in R7 is (4n), >= 76 */ 566 - {15, "R7_w=inv(id=0,umin_value=76,umax_value=1096,var_off=(0x0; 0x7fc))"}, 566 + {14, "R7_w=inv(id=0,umin_value=76,umax_value=1096,var_off=(0x0; 0x7fc))"}, 567 567 /* Adding it to packet pointer gives nice bounds again */ 568 568 {16, "R5_w=pkt(id=3,off=0,r=0,umin_value=2,umax_value=1082,var_off=(0x2; 0xfffffffc)"}, 569 569 /* At the time the word size load is performed from R5, ··· 625 625 line_ptr = strtok(bpf_vlog_copy, "\n"); 626 626 for (i = 0; i < MAX_MATCHES; i++) { 627 627 struct bpf_reg_match m = test->matches[i]; 628 + int tmp; 628 629 629 630 if (!m.match) 630 631 break; 631 632 while (line_ptr) { 632 633 cur_line = -1; 633 634 sscanf(line_ptr, "%u: ", &cur_line); 635 + if (cur_line == -1) 636 + sscanf(line_ptr, "from %u to %u: ", &tmp, &cur_line); 634 637 if (cur_line == m.line) 635 638 break; 636 639 line_ptr = strtok(NULL, "\n"); ··· 645 642 printf("%s", bpf_vlog); 646 643 break; 647 644 } 645 + /* Check the next line as well in case the previous line 646 + * did not have a corresponding bpf insn. Example: 647 + * func#0 @0 648 + * 0: R1=ctx(id=0,off=0,imm=0) R10=fp0 649 + * 0: (b7) r3 = 2 ; R3_w=inv2 650 + */ 648 651 if (!strstr(line_ptr, m.match)) { 652 + cur_line = -1; 653 + line_ptr = strtok(NULL, "\n"); 654 + sscanf(line_ptr, "%u: ", &cur_line); 655 + } 656 + if (cur_line != m.line || !line_ptr || 657 + !strstr(line_ptr, m.match)) { 649 658 printf("Failed to find match %u: %s\n", 650 659 m.line, m.match); 651 660 ret = 1;