Patch "bpf: Detect IP == ksym.end as part of BPF program" has been added to the 6.1-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: Detect IP == ksym.end as part of BPF program

to the 6.1-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-detect-ip-ksym.end-as-part-of-bpf-program.patch
and it can be found in the queue-6.1 subdirectory.

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



commit 2dfab1827ec9717c6ba4407e6e96a3e6c8d2f1d9
Author: Kumar Kartikeya Dwivedi <memxor@xxxxxxxxx>
Date:   Wed Sep 13 01:32:08 2023 +0200

    bpf: Detect IP == ksym.end as part of BPF program
    
    [ Upstream commit 66d9111f3517f85ef2af0337ece02683ce0faf21 ]
    
    Now that bpf_throw kfunc is the first such call instruction that has
    noreturn semantics within the verifier, this also kicks in dead code
    elimination in unprecedented ways. For one, any instruction following
    a bpf_throw call will never be marked as seen. Moreover, if a callchain
    ends up throwing, any instructions after the call instruction to the
    eventually throwing subprog in callers will also never be marked as
    seen.
    
    The tempting way to fix this would be to emit extra 'int3' instructions
    which bump the jited_len of a program, and ensure that during runtime
    when a program throws, we can discover its boundaries even if the call
    instruction to bpf_throw (or to subprogs that always throw) is emitted
    as the final instruction in the program.
    
    An example of such a program would be this:
    
    do_something():
            ...
            r0 = 0
            exit
    
    foo():
            r1 = 0
            call bpf_throw
            r0 = 0
            exit
    
    bar(cond):
            if r1 != 0 goto pc+2
            call do_something
            exit
            call foo
            r0 = 0  // Never seen by verifier
            exit    //
    
    main(ctx):
            r1 = ...
            call bar
            r0 = 0
            exit
    
    Here, if we do end up throwing, the stacktrace would be the following:
    
    bpf_throw
    foo
    bar
    main
    
    In bar, the final instruction emitted will be the call to foo, as such,
    the return address will be the subsequent instruction (which the JIT
    emits as int3 on x86). This will end up lying outside the jited_len of
    the program, thus, when unwinding, we will fail to discover the return
    address as belonging to any program and end up in a panic due to the
    unreliable stack unwinding of BPF programs that we never expect.
    
    To remedy this case, make bpf_prog_ksym_find treat IP == ksym.end as
    part of the BPF program, so that is_bpf_text_address returns true when
    such a case occurs, and we are able to unwind reliably when the final
    instruction ends up being a call instruction.
    
    Signed-off-by: Kumar Kartikeya Dwivedi <memxor@xxxxxxxxx>
    Link: https://lore.kernel.org/r/20230912233214.1518551-12-memxor@xxxxxxxxx
    Signed-off-by: Alexei Starovoitov <ast@xxxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
index 64706723624b9..7225cb67c0d3a 100644
--- a/kernel/bpf/core.c
+++ b/kernel/bpf/core.c
@@ -608,7 +608,11 @@ static __always_inline int bpf_tree_comp(void *key, struct latch_tree_node *n)
 
 	if (val < ksym->start)
 		return -1;
-	if (val >= ksym->end)
+	/* Ensure that we detect return addresses as part of the program, when
+	 * the final instruction is a call for a program part of the stack
+	 * trace. Therefore, do val > ksym->end instead of val >= ksym->end.
+	 */
+	if (val > ksym->end)
 		return  1;
 
 	return 0;



[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