On Mon, Jan 8, 2024 at 12:53 PM Maxim Mikityanskiy <maxtram95@xxxxxxxxx> wrote: > > From: Maxim Mikityanskiy <maxim@xxxxxxxxxxxxx> > > When the width of a fill is smaller than the width of the preceding > spill, the information about scalar boundaries can still be preserved, > as long as it's coerced to the right width (done by coerce_reg_to_size). > Even further, if the actual value fits into the fill width, the ID can > be preserved as well for further tracking of equal scalars. > > Implement the above improvements, which makes narrowing fills behave the > same as narrowing spills and MOVs between registers. > > Two tests are adjusted to accommodate for endianness differences and to > take into account that it's now allowed to do a narrowing fill from the > least significant bits. > > reg_bounds_sync is added to coerce_reg_to_size to correctly adjust > umin/umax boundaries after the var_off truncation, for example, a 64-bit > value 0xXXXXXXXX00000000, when read as a 32-bit, gets umin = 0, umax = > 0xFFFFFFFF, var_off = (0x0; 0xffffffff00000000), which needs to be > synced down to umax = 0, otherwise reg_bounds_sanity_check doesn't pass. > > Signed-off-by: Maxim Mikityanskiy <maxim@xxxxxxxxxxxxx> > --- > include/linux/bpf_verifier.h | 2 -- > include/linux/filter.h | 12 ++++++++ > kernel/bpf/verifier.c | 15 +++++++--- > .../selftests/bpf/progs/verifier_spill_fill.c | 28 +++++++++++++------ > 4 files changed, 42 insertions(+), 15 deletions(-) > > diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h > index e11baecbde68..95ea7657f07e 100644 > --- a/include/linux/bpf_verifier.h > +++ b/include/linux/bpf_verifier.h > @@ -239,8 +239,6 @@ enum bpf_stack_slot_type { > STACK_ITER, > }; > > -#define BPF_REG_SIZE 8 /* size of eBPF register in bytes */ > - > #define BPF_REGMASK_ARGS ((1 << BPF_REG_1) | (1 << BPF_REG_2) | \ > (1 << BPF_REG_3) | (1 << BPF_REG_4) | \ > (1 << BPF_REG_5)) > diff --git a/include/linux/filter.h b/include/linux/filter.h > index 68fb6c8142fe..be784be7ed4e 100644 > --- a/include/linux/filter.h > +++ b/include/linux/filter.h > @@ -39,6 +39,8 @@ struct sock_reuseport; > struct ctl_table; > struct ctl_table_header; > > +#define BPF_REG_SIZE 8 /* size of eBPF register in bytes */ > + > /* ArgX, context and stack frame pointer register positions. Note, > * Arg1, Arg2, Arg3, etc are used as argument mappings of function > * calls in BPF_CALL instruction. > @@ -881,6 +883,16 @@ bpf_ctx_narrow_access_offset(u32 off, u32 size, u32 size_default) > > #define bpf_classic_proglen(fprog) (fprog->len * sizeof(fprog->filter[0])) > > +static inline bool > +bpf_stack_narrow_access_ok(int off, int size, int spill_size) this is used by verifier.c, right? So why not add this to bpf_verifier.h? nit: given we have spill_size, should we s/size/fill_size/ for symmetry? > +{ > +#ifdef __BIG_ENDIAN > + off -= spill_size - size; > +#endif > + > + return !(off % BPF_REG_SIZE); > +} > + > static inline void bpf_prog_lock_ro(struct bpf_prog *fp) > { > #ifndef CONFIG_BPF_JIT_ALWAYS_ON [...]