Skip to content

Commit 759377d

Browse files
author
Alexei Starovoitov
committed
Merge branch 'bpf-verifier-improvement-in-32bit-shift-sign-extension-pattern'
Cupertino Miranda says: ==================== bpf: verifier improvement in 32bit shift sign extension pattern Changed from v2: - Removed newline nit. - Corrected mistake in the test functions definitions. Changed from v1: - Split initial patch in 2 patches. The verifier changes and seftests. - Improve comment near the verifier change. - Improved code for the added selftests. Signed-off-by: Cupertino Miranda <[email protected]> Signed-off-by: Andrew Pinski <[email protected]> Acked-by: Eduard Zingerman <[email protected]> Cc: Alexei Starovoitov <[email protected]> Cc: David Faust <[email protected]> Cc: Jose Marchesi <[email protected]> Cc: Elena Zannoni <[email protected]> ==================== Link: https://patch.msgid.link/[email protected] Signed-off-by: Alexei Starovoitov <[email protected]>
2 parents c93c124 + a5b4867 commit 759377d

File tree

2 files changed

+75
-11
lines changed

2 files changed

+75
-11
lines changed

kernel/bpf/verifier.c

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15300,21 +15300,17 @@ static void __scalar64_min_max_lsh(struct bpf_reg_state *dst_reg,
1530015300
u64 umin_val, u64 umax_val)
1530115301
{
1530215302
/* Special case <<32 because it is a common compiler pattern to sign
15303-
* extend subreg by doing <<32 s>>32. In this case if 32bit bounds are
15304-
* positive we know this shift will also be positive so we can track
15305-
* bounds correctly. Otherwise we lose all sign bit information except
15306-
* what we can pick up from var_off. Perhaps we can generalize this
15307-
* later to shifts of any length.
15303+
* extend subreg by doing <<32 s>>32. smin/smax assignments are correct
15304+
* because s32 bounds don't flip sign when shifting to the left by
15305+
* 32bits.
1530815306
*/
15309-
if (umin_val == 32 && umax_val == 32 && dst_reg->s32_max_value >= 0)
15307+
if (umin_val == 32 && umax_val == 32) {
1531015308
dst_reg->smax_value = (s64)dst_reg->s32_max_value << 32;
15311-
else
15312-
dst_reg->smax_value = S64_MAX;
15313-
15314-
if (umin_val == 32 && umax_val == 32 && dst_reg->s32_min_value >= 0)
1531515309
dst_reg->smin_value = (s64)dst_reg->s32_min_value << 32;
15316-
else
15310+
} else {
15311+
dst_reg->smax_value = S64_MAX;
1531715312
dst_reg->smin_value = S64_MIN;
15313+
}
1531815314

1531915315
/* If we might shift our top bit out, then we know nothing */
1532015316
if (dst_reg->umax_value > 1ULL << (63 - umax_val)) {

tools/testing/selftests/bpf/progs/verifier_subreg.c

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -531,6 +531,74 @@ __naked void arsh32_imm_zero_extend_check(void)
531531
: __clobber_all);
532532
}
533533

534+
SEC("socket")
535+
__description("arsh32 imm sign positive extend check")
536+
__success __retval(0)
537+
__log_level(2)
538+
__msg("2: (57) r6 &= 4095 ; R6=scalar(smin=smin32=0,smax=umax=smax32=umax32=4095,var_off=(0x0; 0xfff))")
539+
__msg("3: (67) r6 <<= 32 ; R6=scalar(smin=smin32=0,smax=umax=0xfff00000000,smax32=umax32=0,var_off=(0x0; 0xfff00000000))")
540+
__msg("4: (c7) r6 s>>= 32 ; R6=scalar(smin=smin32=0,smax=umax=smax32=umax32=4095,var_off=(0x0; 0xfff))")
541+
__naked void arsh32_imm_sign_extend_positive_check(void)
542+
{
543+
asm volatile (" \
544+
call %[bpf_get_prandom_u32]; \
545+
r6 = r0; \
546+
r6 &= 4095; \
547+
r6 <<= 32; \
548+
r6 s>>= 32; \
549+
r0 = 0; \
550+
exit; \
551+
" :
552+
: __imm(bpf_get_prandom_u32)
553+
: __clobber_all);
554+
}
555+
556+
SEC("socket")
557+
__description("arsh32 imm sign negative extend check")
558+
__success __retval(0)
559+
__log_level(2)
560+
__msg("3: (17) r6 -= 4095 ; R6=scalar(smin=smin32=-4095,smax=smax32=0)")
561+
__msg("4: (67) r6 <<= 32 ; R6=scalar(smin=0xfffff00100000000,smax=smax32=umax32=0,umax=0xffffffff00000000,smin32=0,var_off=(0x0; 0xffffffff00000000))")
562+
__msg("5: (c7) r6 s>>= 32 ; R6=scalar(smin=smin32=-4095,smax=smax32=0)")
563+
__naked void arsh32_imm_sign_extend_negative_check(void)
564+
{
565+
asm volatile (" \
566+
call %[bpf_get_prandom_u32]; \
567+
r6 = r0; \
568+
r6 &= 4095; \
569+
r6 -= 4095; \
570+
r6 <<= 32; \
571+
r6 s>>= 32; \
572+
r0 = 0; \
573+
exit; \
574+
" :
575+
: __imm(bpf_get_prandom_u32)
576+
: __clobber_all);
577+
}
578+
579+
SEC("socket")
580+
__description("arsh32 imm sign extend check")
581+
__success __retval(0)
582+
__log_level(2)
583+
__msg("3: (17) r6 -= 2047 ; R6=scalar(smin=smin32=-2047,smax=smax32=2048)")
584+
__msg("4: (67) r6 <<= 32 ; R6=scalar(smin=0xfffff80100000000,smax=0x80000000000,umax=0xffffffff00000000,smin32=0,smax32=umax32=0,var_off=(0x0; 0xffffffff00000000))")
585+
__msg("5: (c7) r6 s>>= 32 ; R6=scalar(smin=smin32=-2047,smax=smax32=2048)")
586+
__naked void arsh32_imm_sign_extend_check(void)
587+
{
588+
asm volatile (" \
589+
call %[bpf_get_prandom_u32]; \
590+
r6 = r0; \
591+
r6 &= 4095; \
592+
r6 -= 2047; \
593+
r6 <<= 32; \
594+
r6 s>>= 32; \
595+
r0 = 0; \
596+
exit; \
597+
" :
598+
: __imm(bpf_get_prandom_u32)
599+
: __clobber_all);
600+
}
601+
534602
SEC("socket")
535603
__description("end16 (to_le) reg zero extend check")
536604
__success __success_unpriv __retval(0)

0 commit comments

Comments
 (0)