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.

Merge branch 'BPF verifier precision tracking improvements'

Andrii Nakryiko says:

====================

This patch set fixes and improves BPF verifier's precision tracking logic for
SCALAR registers.

Patches #1 and #2 are bug fixes discovered while working on these changes.

Patch #3 enables precision tracking for BPF programs that contain subprograms.
This was disabled before and prevent any modern BPF programs that use
subprograms from enjoying the benefits of SCALAR (im)precise logic.

Patch #4 is few lines of code changes and many lines of explaining why those
changes are correct. We establish why ignoring precise markings in current
state is OK.

Patch #5 build on explanation in patch #4 and pushes it to the limit by
forcefully forgetting inherited precise markins. Patch #4 by itself doesn't
prevent current state from having precise=true SCALARs, so patch #5 is
necessary to prevent such stray precise=true registers from creeping in.

Patch #6 adjusts test_align selftests to work around BPF verifier log's
limitations when it comes to interactions between state output and precision
backtracking output.

Overall, the goal of this patch set is to make BPF verifier's state tracking
a bit more efficient by trying to preserve as much generality in checkpointed
states as possible.

v1->v2:
- adjusted patch #1 commit message to make it clear we are fixing forward
step, not precision backtracking (Alexei);
- moved last_idx/first_idx verbose logging up to make it clear when global
func reaches the first empty state (Alexei).
====================

Signed-off-by: Alexei Starovoitov <ast@kernel.org>

+257 -59
+233 -45
kernel/bpf/verifier.c
··· 504 504 return func_id == BPF_FUNC_dynptr_data; 505 505 } 506 506 507 + static bool is_callback_calling_function(enum bpf_func_id func_id) 508 + { 509 + return func_id == BPF_FUNC_for_each_map_elem || 510 + func_id == BPF_FUNC_timer_set_callback || 511 + func_id == BPF_FUNC_find_vma || 512 + func_id == BPF_FUNC_loop || 513 + func_id == BPF_FUNC_user_ringbuf_drain; 514 + } 515 + 507 516 static bool helper_multiple_ref_obj_use(enum bpf_func_id func_id, 508 517 const struct bpf_map *map) 509 518 { ··· 1686 1677 reg->type = SCALAR_VALUE; 1687 1678 reg->var_off = tnum_unknown; 1688 1679 reg->frameno = 0; 1689 - reg->precise = env->subprog_cnt > 1 || !env->bpf_capable; 1680 + reg->precise = !env->bpf_capable; 1690 1681 __mark_reg_unbounded(reg); 1691 1682 } 1692 1683 ··· 2655 2646 if (opcode == BPF_CALL) { 2656 2647 if (insn->src_reg == BPF_PSEUDO_CALL) 2657 2648 return -ENOTSUPP; 2649 + /* BPF helpers that invoke callback subprogs are 2650 + * equivalent to BPF_PSEUDO_CALL above 2651 + */ 2652 + if (insn->src_reg == 0 && is_callback_calling_function(insn->imm)) 2653 + return -ENOTSUPP; 2658 2654 /* regular helper call sets R0 */ 2659 2655 *reg_mask &= ~1; 2660 2656 if (*reg_mask & 0x3f) { ··· 2749 2735 2750 2736 /* big hammer: mark all scalars precise in this path. 2751 2737 * pop_stack may still get !precise scalars. 2738 + * We also skip current state and go straight to first parent state, 2739 + * because precision markings in current non-checkpointed state are 2740 + * not needed. See why in the comment in __mark_chain_precision below. 2752 2741 */ 2753 - for (; st; st = st->parent) 2742 + for (st = st->parent; st; st = st->parent) { 2754 2743 for (i = 0; i <= st->curframe; i++) { 2755 2744 func = st->frame[i]; 2756 2745 for (j = 0; j < BPF_REG_FP; j++) { ··· 2771 2754 reg->precise = true; 2772 2755 } 2773 2756 } 2757 + } 2774 2758 } 2775 2759 2776 - static int __mark_chain_precision(struct bpf_verifier_env *env, int regno, 2760 + static void mark_all_scalars_imprecise(struct bpf_verifier_env *env, struct bpf_verifier_state *st) 2761 + { 2762 + struct bpf_func_state *func; 2763 + struct bpf_reg_state *reg; 2764 + int i, j; 2765 + 2766 + for (i = 0; i <= st->curframe; i++) { 2767 + func = st->frame[i]; 2768 + for (j = 0; j < BPF_REG_FP; j++) { 2769 + reg = &func->regs[j]; 2770 + if (reg->type != SCALAR_VALUE) 2771 + continue; 2772 + reg->precise = false; 2773 + } 2774 + for (j = 0; j < func->allocated_stack / BPF_REG_SIZE; j++) { 2775 + if (!is_spilled_reg(&func->stack[j])) 2776 + continue; 2777 + reg = &func->stack[j].spilled_ptr; 2778 + if (reg->type != SCALAR_VALUE) 2779 + continue; 2780 + reg->precise = false; 2781 + } 2782 + } 2783 + } 2784 + 2785 + /* 2786 + * __mark_chain_precision() backtracks BPF program instruction sequence and 2787 + * chain of verifier states making sure that register *regno* (if regno >= 0) 2788 + * and/or stack slot *spi* (if spi >= 0) are marked as precisely tracked 2789 + * SCALARS, as well as any other registers and slots that contribute to 2790 + * a tracked state of given registers/stack slots, depending on specific BPF 2791 + * assembly instructions (see backtrack_insns() for exact instruction handling 2792 + * logic). This backtracking relies on recorded jmp_history and is able to 2793 + * traverse entire chain of parent states. This process ends only when all the 2794 + * necessary registers/slots and their transitive dependencies are marked as 2795 + * precise. 2796 + * 2797 + * One important and subtle aspect is that precise marks *do not matter* in 2798 + * the currently verified state (current state). It is important to understand 2799 + * why this is the case. 2800 + * 2801 + * First, note that current state is the state that is not yet "checkpointed", 2802 + * i.e., it is not yet put into env->explored_states, and it has no children 2803 + * states as well. It's ephemeral, and can end up either a) being discarded if 2804 + * compatible explored state is found at some point or BPF_EXIT instruction is 2805 + * reached or b) checkpointed and put into env->explored_states, branching out 2806 + * into one or more children states. 2807 + * 2808 + * In the former case, precise markings in current state are completely 2809 + * ignored by state comparison code (see regsafe() for details). Only 2810 + * checkpointed ("old") state precise markings are important, and if old 2811 + * state's register/slot is precise, regsafe() assumes current state's 2812 + * register/slot as precise and checks value ranges exactly and precisely. If 2813 + * states turn out to be compatible, current state's necessary precise 2814 + * markings and any required parent states' precise markings are enforced 2815 + * after the fact with propagate_precision() logic, after the fact. But it's 2816 + * important to realize that in this case, even after marking current state 2817 + * registers/slots as precise, we immediately discard current state. So what 2818 + * actually matters is any of the precise markings propagated into current 2819 + * state's parent states, which are always checkpointed (due to b) case above). 2820 + * As such, for scenario a) it doesn't matter if current state has precise 2821 + * markings set or not. 2822 + * 2823 + * Now, for the scenario b), checkpointing and forking into child(ren) 2824 + * state(s). Note that before current state gets to checkpointing step, any 2825 + * processed instruction always assumes precise SCALAR register/slot 2826 + * knowledge: if precise value or range is useful to prune jump branch, BPF 2827 + * verifier takes this opportunity enthusiastically. Similarly, when 2828 + * register's value is used to calculate offset or memory address, exact 2829 + * knowledge of SCALAR range is assumed, checked, and enforced. So, similar to 2830 + * what we mentioned above about state comparison ignoring precise markings 2831 + * during state comparison, BPF verifier ignores and also assumes precise 2832 + * markings *at will* during instruction verification process. But as verifier 2833 + * assumes precision, it also propagates any precision dependencies across 2834 + * parent states, which are not yet finalized, so can be further restricted 2835 + * based on new knowledge gained from restrictions enforced by their children 2836 + * states. This is so that once those parent states are finalized, i.e., when 2837 + * they have no more active children state, state comparison logic in 2838 + * is_state_visited() would enforce strict and precise SCALAR ranges, if 2839 + * required for correctness. 2840 + * 2841 + * To build a bit more intuition, note also that once a state is checkpointed, 2842 + * the path we took to get to that state is not important. This is crucial 2843 + * property for state pruning. When state is checkpointed and finalized at 2844 + * some instruction index, it can be correctly and safely used to "short 2845 + * circuit" any *compatible* state that reaches exactly the same instruction 2846 + * index. I.e., if we jumped to that instruction from a completely different 2847 + * code path than original finalized state was derived from, it doesn't 2848 + * matter, current state can be discarded because from that instruction 2849 + * forward having a compatible state will ensure we will safely reach the 2850 + * exit. States describe preconditions for further exploration, but completely 2851 + * forget the history of how we got here. 2852 + * 2853 + * This also means that even if we needed precise SCALAR range to get to 2854 + * finalized state, but from that point forward *that same* SCALAR register is 2855 + * never used in a precise context (i.e., it's precise value is not needed for 2856 + * correctness), it's correct and safe to mark such register as "imprecise" 2857 + * (i.e., precise marking set to false). This is what we rely on when we do 2858 + * not set precise marking in current state. If no child state requires 2859 + * precision for any given SCALAR register, it's safe to dictate that it can 2860 + * be imprecise. If any child state does require this register to be precise, 2861 + * we'll mark it precise later retroactively during precise markings 2862 + * propagation from child state to parent states. 2863 + * 2864 + * Skipping precise marking setting in current state is a mild version of 2865 + * relying on the above observation. But we can utilize this property even 2866 + * more aggressively by proactively forgetting any precise marking in the 2867 + * current state (which we inherited from the parent state), right before we 2868 + * checkpoint it and branch off into new child state. This is done by 2869 + * mark_all_scalars_imprecise() to hopefully get more permissive and generic 2870 + * finalized states which help in short circuiting more future states. 2871 + */ 2872 + static int __mark_chain_precision(struct bpf_verifier_env *env, int frame, int regno, 2777 2873 int spi) 2778 2874 { 2779 2875 struct bpf_verifier_state *st = env->cur_state; ··· 2903 2773 if (!env->bpf_capable) 2904 2774 return 0; 2905 2775 2906 - func = st->frame[st->curframe]; 2776 + /* Do sanity checks against current state of register and/or stack 2777 + * slot, but don't set precise flag in current state, as precision 2778 + * tracking in the current state is unnecessary. 2779 + */ 2780 + func = st->frame[frame]; 2907 2781 if (regno >= 0) { 2908 2782 reg = &func->regs[regno]; 2909 2783 if (reg->type != SCALAR_VALUE) { 2910 2784 WARN_ONCE(1, "backtracing misuse"); 2911 2785 return -EFAULT; 2912 2786 } 2913 - if (!reg->precise) 2914 - new_marks = true; 2915 - else 2916 - reg_mask = 0; 2917 - reg->precise = true; 2787 + new_marks = true; 2918 2788 } 2919 2789 2920 2790 while (spi >= 0) { ··· 2927 2797 stack_mask = 0; 2928 2798 break; 2929 2799 } 2930 - if (!reg->precise) 2931 - new_marks = true; 2932 - else 2933 - stack_mask = 0; 2934 - reg->precise = true; 2800 + new_marks = true; 2935 2801 break; 2936 2802 } 2937 2803 ··· 2935 2809 return 0; 2936 2810 if (!reg_mask && !stack_mask) 2937 2811 return 0; 2812 + 2938 2813 for (;;) { 2939 2814 DECLARE_BITMAP(mask, 64); 2940 2815 u32 history = st->jmp_history_cnt; 2941 2816 2942 2817 if (env->log.level & BPF_LOG_LEVEL2) 2943 2818 verbose(env, "last_idx %d first_idx %d\n", last_idx, first_idx); 2819 + 2820 + if (last_idx < 0) { 2821 + /* we are at the entry into subprog, which 2822 + * is expected for global funcs, but only if 2823 + * requested precise registers are R1-R5 2824 + * (which are global func's input arguments) 2825 + */ 2826 + if (st->curframe == 0 && 2827 + st->frame[0]->subprogno > 0 && 2828 + st->frame[0]->callsite == BPF_MAIN_FUNC && 2829 + stack_mask == 0 && (reg_mask & ~0x3e) == 0) { 2830 + bitmap_from_u64(mask, reg_mask); 2831 + for_each_set_bit(i, mask, 32) { 2832 + reg = &st->frame[0]->regs[i]; 2833 + if (reg->type != SCALAR_VALUE) { 2834 + reg_mask &= ~(1u << i); 2835 + continue; 2836 + } 2837 + reg->precise = true; 2838 + } 2839 + return 0; 2840 + } 2841 + 2842 + verbose(env, "BUG backtracing func entry subprog %d reg_mask %x stack_mask %llx\n", 2843 + st->frame[0]->subprogno, reg_mask, stack_mask); 2844 + WARN_ONCE(1, "verifier backtracking bug"); 2845 + return -EFAULT; 2846 + } 2847 + 2944 2848 for (i = last_idx;;) { 2945 2849 if (skip_first) { 2946 2850 err = 0; ··· 3010 2854 break; 3011 2855 3012 2856 new_marks = false; 3013 - func = st->frame[st->curframe]; 2857 + func = st->frame[frame]; 3014 2858 bitmap_from_u64(mask, reg_mask); 3015 2859 for_each_set_bit(i, mask, 32) { 3016 2860 reg = &func->regs[i]; ··· 3076 2920 3077 2921 int mark_chain_precision(struct bpf_verifier_env *env, int regno) 3078 2922 { 3079 - return __mark_chain_precision(env, regno, -1); 2923 + return __mark_chain_precision(env, env->cur_state->curframe, regno, -1); 3080 2924 } 3081 2925 3082 - static int mark_chain_precision_stack(struct bpf_verifier_env *env, int spi) 2926 + static int mark_chain_precision_frame(struct bpf_verifier_env *env, int frame, int regno) 3083 2927 { 3084 - return __mark_chain_precision(env, -1, spi); 2928 + return __mark_chain_precision(env, frame, regno, -1); 2929 + } 2930 + 2931 + static int mark_chain_precision_stack_frame(struct bpf_verifier_env *env, int frame, int spi) 2932 + { 2933 + return __mark_chain_precision(env, frame, -1, spi); 3085 2934 } 3086 2935 3087 2936 static bool is_spillable_regtype(enum bpf_reg_type type) ··· 6758 6597 struct bpf_func_state *callee, 6759 6598 int insn_idx); 6760 6599 6600 + static int set_callee_state(struct bpf_verifier_env *env, 6601 + struct bpf_func_state *caller, 6602 + struct bpf_func_state *callee, int insn_idx); 6603 + 6761 6604 static int __check_func_call(struct bpf_verifier_env *env, struct bpf_insn *insn, 6762 6605 int *insn_idx, int subprog, 6763 6606 set_callee_state_fn set_callee_state_cb) ··· 6810 6645 /* continue with next insn after call */ 6811 6646 return 0; 6812 6647 } 6648 + } 6649 + 6650 + /* set_callee_state is used for direct subprog calls, but we are 6651 + * interested in validating only BPF helpers that can call subprogs as 6652 + * callbacks 6653 + */ 6654 + if (set_callee_state_cb != set_callee_state && !is_callback_calling_function(insn->imm)) { 6655 + verbose(env, "verifier bug: helper %s#%d is not marked as callback-calling\n", 6656 + func_id_name(insn->imm), insn->imm); 6657 + return -EFAULT; 6813 6658 } 6814 6659 6815 6660 if (insn->code == (BPF_JMP | BPF_CALL) && ··· 9328 9153 return err; 9329 9154 return adjust_ptr_min_max_vals(env, insn, 9330 9155 dst_reg, src_reg); 9156 + } else if (dst_reg->precise) { 9157 + /* if dst_reg is precise, src_reg should be precise as well */ 9158 + err = mark_chain_precision(env, insn->src_reg); 9159 + if (err) 9160 + return err; 9331 9161 } 9332 9162 } else { 9333 9163 /* Pretend the src is a reg with a known value, since we only ··· 11646 11466 if (env->explore_alu_limits) 11647 11467 return false; 11648 11468 if (rcur->type == SCALAR_VALUE) { 11649 - if (!rold->precise && !rcur->precise) 11469 + if (!rold->precise) 11650 11470 return true; 11651 11471 /* new val must satisfy old val knowledge */ 11652 11472 return range_within(rold, rcur) && ··· 11969 11789 { 11970 11790 struct bpf_reg_state *state_reg; 11971 11791 struct bpf_func_state *state; 11972 - int i, err = 0; 11792 + int i, err = 0, fr; 11973 11793 11974 - state = old->frame[old->curframe]; 11975 - state_reg = state->regs; 11976 - for (i = 0; i < BPF_REG_FP; i++, state_reg++) { 11977 - if (state_reg->type != SCALAR_VALUE || 11978 - !state_reg->precise) 11979 - continue; 11980 - if (env->log.level & BPF_LOG_LEVEL2) 11981 - verbose(env, "propagating r%d\n", i); 11982 - err = mark_chain_precision(env, i); 11983 - if (err < 0) 11984 - return err; 11985 - } 11794 + for (fr = old->curframe; fr >= 0; fr--) { 11795 + state = old->frame[fr]; 11796 + state_reg = state->regs; 11797 + for (i = 0; i < BPF_REG_FP; i++, state_reg++) { 11798 + if (state_reg->type != SCALAR_VALUE || 11799 + !state_reg->precise) 11800 + continue; 11801 + if (env->log.level & BPF_LOG_LEVEL2) 11802 + verbose(env, "frame %d: propagating r%d\n", i, fr); 11803 + err = mark_chain_precision_frame(env, fr, i); 11804 + if (err < 0) 11805 + return err; 11806 + } 11986 11807 11987 - for (i = 0; i < state->allocated_stack / BPF_REG_SIZE; i++) { 11988 - if (!is_spilled_reg(&state->stack[i])) 11989 - continue; 11990 - state_reg = &state->stack[i].spilled_ptr; 11991 - if (state_reg->type != SCALAR_VALUE || 11992 - !state_reg->precise) 11993 - continue; 11994 - if (env->log.level & BPF_LOG_LEVEL2) 11995 - verbose(env, "propagating fp%d\n", 11996 - (-i - 1) * BPF_REG_SIZE); 11997 - err = mark_chain_precision_stack(env, i); 11998 - if (err < 0) 11999 - return err; 11808 + for (i = 0; i < state->allocated_stack / BPF_REG_SIZE; i++) { 11809 + if (!is_spilled_reg(&state->stack[i])) 11810 + continue; 11811 + state_reg = &state->stack[i].spilled_ptr; 11812 + if (state_reg->type != SCALAR_VALUE || 11813 + !state_reg->precise) 11814 + continue; 11815 + if (env->log.level & BPF_LOG_LEVEL2) 11816 + verbose(env, "frame %d: propagating fp%d\n", 11817 + (-i - 1) * BPF_REG_SIZE, fr); 11818 + err = mark_chain_precision_stack_frame(env, fr, i); 11819 + if (err < 0) 11820 + return err; 11821 + } 12000 11822 } 12001 11823 return 0; 12002 11824 } ··· 12192 12010 env->peak_states++; 12193 12011 env->prev_jmps_processed = env->jmps_processed; 12194 12012 env->prev_insn_processed = env->insn_processed; 12013 + 12014 + /* forget precise markings we inherited, see __mark_chain_precision */ 12015 + if (env->bpf_capable) 12016 + mark_all_scalars_imprecise(env, cur); 12195 12017 12196 12018 /* add new state to the head of linked list */ 12197 12019 new = &new_sl->state; ··· 14745 14559 BPF_MAIN_FUNC /* callsite */, 14746 14560 0 /* frameno */, 14747 14561 subprog); 14562 + state->first_insn_idx = env->subprog_info[subprog].start; 14563 + state->last_insn_idx = -1; 14748 14564 14749 14565 regs = state->frame[state->curframe]->regs; 14750 14566 if (subprog || env->prog->type == BPF_PROG_TYPE_EXT) {
+24 -14
tools/testing/selftests/bpf/prog_tests/align.c
··· 2 2 #include <test_progs.h> 3 3 4 4 #define MAX_INSNS 512 5 - #define MAX_MATCHES 16 5 + #define MAX_MATCHES 24 6 6 7 7 struct bpf_reg_match { 8 8 unsigned int line; ··· 267 267 */ 268 268 BPF_MOV64_REG(BPF_REG_5, BPF_REG_2), 269 269 BPF_ALU64_REG(BPF_ADD, BPF_REG_5, BPF_REG_6), 270 + BPF_MOV64_REG(BPF_REG_4, BPF_REG_5), 270 271 BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, 14), 271 272 BPF_MOV64_REG(BPF_REG_4, BPF_REG_5), 272 273 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 4), ··· 281 280 BPF_MOV64_REG(BPF_REG_5, BPF_REG_2), 282 281 BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, 14), 283 282 BPF_ALU64_REG(BPF_ADD, BPF_REG_5, BPF_REG_6), 283 + BPF_MOV64_REG(BPF_REG_4, BPF_REG_5), 284 284 BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, 4), 285 285 BPF_ALU64_REG(BPF_ADD, BPF_REG_5, BPF_REG_6), 286 286 BPF_MOV64_REG(BPF_REG_4, BPF_REG_5), ··· 313 311 {15, "R4=pkt(id=1,off=18,r=18,umax=1020,var_off=(0x0; 0x3fc))"}, 314 312 {15, "R5=pkt(id=1,off=14,r=18,umax=1020,var_off=(0x0; 0x3fc))"}, 315 313 /* Variable offset is added to R5 packet pointer, 316 - * resulting in auxiliary alignment of 4. 314 + * resulting in auxiliary alignment of 4. To avoid BPF 315 + * verifier's precision backtracking logging 316 + * interfering we also have a no-op R4 = R5 317 + * instruction to validate R5 state. We also check 318 + * that R4 is what it should be in such case. 317 319 */ 318 - {17, "R5_w=pkt(id=2,off=0,r=0,umax=1020,var_off=(0x0; 0x3fc))"}, 320 + {18, "R4_w=pkt(id=2,off=0,r=0,umax=1020,var_off=(0x0; 0x3fc))"}, 321 + {18, "R5_w=pkt(id=2,off=0,r=0,umax=1020,var_off=(0x0; 0x3fc))"}, 319 322 /* Constant offset is added to R5, resulting in 320 323 * reg->off of 14. 321 324 */ 322 - {18, "R5_w=pkt(id=2,off=14,r=0,umax=1020,var_off=(0x0; 0x3fc))"}, 325 + {19, "R5_w=pkt(id=2,off=14,r=0,umax=1020,var_off=(0x0; 0x3fc))"}, 323 326 /* At the time the word size load is performed from R5, 324 327 * its total fixed offset is NET_IP_ALIGN + reg->off 325 328 * (14) which is 16. Then the variable offset is 4-byte 326 329 * aligned, so the total offset is 4-byte aligned and 327 330 * meets the load's requirements. 328 331 */ 329 - {23, "R4=pkt(id=2,off=18,r=18,umax=1020,var_off=(0x0; 0x3fc))"}, 330 - {23, "R5=pkt(id=2,off=14,r=18,umax=1020,var_off=(0x0; 0x3fc))"}, 332 + {24, "R4=pkt(id=2,off=18,r=18,umax=1020,var_off=(0x0; 0x3fc))"}, 333 + {24, "R5=pkt(id=2,off=14,r=18,umax=1020,var_off=(0x0; 0x3fc))"}, 331 334 /* Constant offset is added to R5 packet pointer, 332 335 * resulting in reg->off value of 14. 333 336 */ 334 - {25, "R5_w=pkt(off=14,r=8"}, 337 + {26, "R5_w=pkt(off=14,r=8"}, 335 338 /* Variable offset is added to R5, resulting in a 336 - * variable offset of (4n). 339 + * variable offset of (4n). See comment for insn #18 340 + * for R4 = R5 trick. 337 341 */ 338 - {26, "R5_w=pkt(id=3,off=14,r=0,umax=1020,var_off=(0x0; 0x3fc))"}, 342 + {28, "R4_w=pkt(id=3,off=14,r=0,umax=1020,var_off=(0x0; 0x3fc))"}, 343 + {28, "R5_w=pkt(id=3,off=14,r=0,umax=1020,var_off=(0x0; 0x3fc))"}, 339 344 /* Constant is added to R5 again, setting reg->off to 18. */ 340 - {27, "R5_w=pkt(id=3,off=18,r=0,umax=1020,var_off=(0x0; 0x3fc))"}, 345 + {29, "R5_w=pkt(id=3,off=18,r=0,umax=1020,var_off=(0x0; 0x3fc))"}, 341 346 /* And once more we add a variable; resulting var_off 342 347 * is still (4n), fixed offset is not changed. 343 348 * Also, we create a new reg->id. 344 349 */ 345 - {28, "R5_w=pkt(id=4,off=18,r=0,umax=2040,var_off=(0x0; 0x7fc)"}, 350 + {31, "R4_w=pkt(id=4,off=18,r=0,umax=2040,var_off=(0x0; 0x7fc)"}, 351 + {31, "R5_w=pkt(id=4,off=18,r=0,umax=2040,var_off=(0x0; 0x7fc)"}, 346 352 /* At the time the word size load is performed from R5, 347 353 * its total fixed offset is NET_IP_ALIGN + reg->off (18) 348 354 * which is 20. Then the variable offset is (4n), so 349 355 * the total offset is 4-byte aligned and meets the 350 356 * load's requirements. 351 357 */ 352 - {33, "R4=pkt(id=4,off=22,r=22,umax=2040,var_off=(0x0; 0x7fc)"}, 353 - {33, "R5=pkt(id=4,off=18,r=22,umax=2040,var_off=(0x0; 0x7fc)"}, 358 + {35, "R4=pkt(id=4,off=22,r=22,umax=2040,var_off=(0x0; 0x7fc)"}, 359 + {35, "R5=pkt(id=4,off=18,r=22,umax=2040,var_off=(0x0; 0x7fc)"}, 354 360 }, 355 361 }, 356 362 { ··· 691 681 if (!test__start_subtest(test->descr)) 692 682 continue; 693 683 694 - CHECK_FAIL(do_test_single(test)); 684 + ASSERT_OK(do_test_single(test), test->descr); 695 685 } 696 686 }