Patch "bpf: Simplify checking size of helper accesses" has been added to the 6.6-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    bpf: Simplify checking size of helper accesses

to the 6.6-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     bpf-simplify-checking-size-of-helper-accesses.patch
and it can be found in the queue-6.6 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit 4b174ee3c878d42aae8c6bea4555f54faad5981f
Author: Andrei Matei <andreimatei1@xxxxxxxxx>
Date:   Thu Dec 21 18:22:24 2023 -0500

    bpf: Simplify checking size of helper accesses
    
    [ Upstream commit 8a021e7fa10576eeb3938328f39bbf98fe7d4715 ]
    
    This patch simplifies the verification of size arguments associated to
    pointer arguments to helpers and kfuncs. Many helpers take a pointer
    argument followed by the size of the memory access performed to be
    performed through that pointer. Before this patch, the handling of the
    size argument in check_mem_size_reg() was confusing and wasteful: if the
    size register's lower bound was 0, then the verification was done twice:
    once considering the size of the access to be the lower-bound of the
    respective argument, and once considering the upper bound (even if the
    two are the same). The upper bound checking is a super-set of the
    lower-bound checking(*), except: the only point of the lower-bound check
    is to handle the case where zero-sized-accesses are explicitly not
    allowed and the lower-bound is zero. This static condition is now
    checked explicitly, replacing a much more complex, expensive and
    confusing verification call to check_helper_mem_access().
    
    Error messages change in this patch. Before, messages about illegal
    zero-size accesses depended on the type of the pointer and on other
    conditions, and sometimes the message was plain wrong: in some tests
    that changed you'll see that the old message was something like "R1 min
    value is outside of the allowed memory range", where R1 is the pointer
    register; the error was wrongly claiming that the pointer was bad
    instead of the size being bad. Other times the information that the size
    came for a register with a possible range of values was wrong, and the
    error presented the size as a fixed zero. Now the errors refer to the
    right register. However, the old error messages did contain useful
    information about the pointer register which is now lost; recovering
    this information was deemed not important enough.
    
    (*) Besides standing to reason that the checks for a bigger size access
    are a super-set of the checks for a smaller size access, I have also
    mechanically verified this by reading the code for all types of
    pointers. I could convince myself that it's true for all but
    PTR_TO_BTF_ID (check_ptr_to_btf_access). There, simply looking
    line-by-line does not immediately prove what we want. If anyone has any
    qualms, let me know.
    
    Signed-off-by: Andrei Matei <andreimatei1@xxxxxxxxx>
    Signed-off-by: Andrii Nakryiko <andrii@xxxxxxxxxx>
    Acked-by: Andrii Nakryiko <andrii@xxxxxxxxxx>
    Link: https://lore.kernel.org/bpf/20231221232225.568730-2-andreimatei1@xxxxxxxxx
    Stable-dep-of: 8ea607330a39 ("bpf: Fix overloading of MEM_UNINIT's meaning")
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 28b09ca5525f0..f24d570d67ca5 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -7324,12 +7324,10 @@ static int check_mem_size_reg(struct bpf_verifier_env *env,
 		return -EACCES;
 	}
 
-	if (reg->umin_value == 0) {
-		err = check_helper_mem_access(env, regno - 1, 0,
-					      zero_size_allowed,
-					      meta);
-		if (err)
-			return err;
+	if (reg->umin_value == 0 && !zero_size_allowed) {
+		verbose(env, "R%d invalid zero-sized read: u64=[%lld,%lld]\n",
+			regno, reg->umin_value, reg->umax_value);
+		return -EACCES;
 	}
 
 	if (reg->umax_value >= BPF_MAX_VAR_SIZ) {
diff --git a/tools/testing/selftests/bpf/progs/verifier_helper_value_access.c b/tools/testing/selftests/bpf/progs/verifier_helper_value_access.c
index 692216c0ad3d4..3e8340c2408f3 100644
--- a/tools/testing/selftests/bpf/progs/verifier_helper_value_access.c
+++ b/tools/testing/selftests/bpf/progs/verifier_helper_value_access.c
@@ -91,7 +91,7 @@ l0_%=:	exit;						\
 
 SEC("tracepoint")
 __description("helper access to map: empty range")
-__failure __msg("invalid access to map value, value_size=48 off=0 size=0")
+__failure __msg("R2 invalid zero-sized read")
 __naked void access_to_map_empty_range(void)
 {
 	asm volatile ("					\
@@ -221,7 +221,7 @@ l0_%=:	exit;						\
 
 SEC("tracepoint")
 __description("helper access to adjusted map (via const imm): empty range")
-__failure __msg("invalid access to map value, value_size=48 off=4 size=0")
+__failure __msg("R2 invalid zero-sized read")
 __naked void via_const_imm_empty_range(void)
 {
 	asm volatile ("					\
@@ -386,7 +386,7 @@ l0_%=:	exit;						\
 
 SEC("tracepoint")
 __description("helper access to adjusted map (via const reg): empty range")
-__failure __msg("R1 min value is outside of the allowed memory range")
+__failure __msg("R2 invalid zero-sized read")
 __naked void via_const_reg_empty_range(void)
 {
 	asm volatile ("					\
@@ -556,7 +556,7 @@ l0_%=:	exit;						\
 
 SEC("tracepoint")
 __description("helper access to adjusted map (via variable): empty range")
-__failure __msg("R1 min value is outside of the allowed memory range")
+__failure __msg("R2 invalid zero-sized read")
 __naked void map_via_variable_empty_range(void)
 {
 	asm volatile ("					\
diff --git a/tools/testing/selftests/bpf/progs/verifier_raw_stack.c b/tools/testing/selftests/bpf/progs/verifier_raw_stack.c
index f67390224a9cf..7cc83acac7271 100644
--- a/tools/testing/selftests/bpf/progs/verifier_raw_stack.c
+++ b/tools/testing/selftests/bpf/progs/verifier_raw_stack.c
@@ -64,7 +64,7 @@ __naked void load_bytes_negative_len_2(void)
 
 SEC("tc")
 __description("raw_stack: skb_load_bytes, zero len")
-__failure __msg("invalid zero-sized read")
+__failure __msg("R4 invalid zero-sized read: u64=[0,0]")
 __naked void skb_load_bytes_zero_len(void)
 {
 	asm volatile ("					\




[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux