Patch "bpf: Repeat check_max_stack_depth for async callbacks" has been added to the 6.4-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: Repeat check_max_stack_depth for async callbacks

to the 6.4-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-repeat-check_max_stack_depth-for-async-callbacks.patch
and it can be found in the queue-6.4 subdirectory.

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



commit 618abe8dabe1ad1d0d66135467202aca5f3881c9
Author: Kumar Kartikeya Dwivedi <memxor@xxxxxxxxx>
Date:   Mon Jul 17 21:45:29 2023 +0530

    bpf: Repeat check_max_stack_depth for async callbacks
    
    [ Upstream commit b5e9ad522c4ccd32d322877515cff8d47ed731b9 ]
    
    While the check_max_stack_depth function explores call chains emanating
    from the main prog, which is typically enough to cover all possible call
    chains, it doesn't explore those rooted at async callbacks unless the
    async callback will have been directly called, since unlike non-async
    callbacks it skips their instruction exploration as they don't
    contribute to stack depth.
    
    It could be the case that the async callback leads to a callchain which
    exceeds the stack depth, but this is never reachable while only
    exploring the entry point from main subprog. Hence, repeat the check for
    the main subprog *and* all async callbacks marked by the symbolic
    execution pass of the verifier, as execution of the program may begin at
    any of them.
    
    Consider functions with following stack depths:
    main: 256
    async: 256
    foo: 256
    
    main:
        rX = async
        bpf_timer_set_callback(...)
    
    async:
        foo()
    
    Here, async is not descended as it does not contribute to stack depth of
    main (since it is referenced using bpf_pseudo_func and not
    bpf_pseudo_call). However, when async is invoked asynchronously, it will
    end up breaching the MAX_BPF_STACK limit by calling foo.
    
    Hence, in addition to main, we also need to explore call chains
    beginning at all async callback subprogs in a program.
    
    Fixes: 7ddc80a476c2 ("bpf: Teach stack depth check about async callbacks.")
    Signed-off-by: Kumar Kartikeya Dwivedi <memxor@xxxxxxxxx>
    Link: https://lore.kernel.org/r/20230717161530.1238-3-memxor@xxxxxxxxx
    Signed-off-by: Alexei Starovoitov <ast@xxxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index e95bfe45fd890..4fbfe1d086467 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -5381,16 +5381,17 @@ static int update_stack_depth(struct bpf_verifier_env *env,
  * Since recursion is prevented by check_cfg() this algorithm
  * only needs a local stack of MAX_CALL_FRAMES to remember callsites
  */
-static int check_max_stack_depth(struct bpf_verifier_env *env)
+static int check_max_stack_depth_subprog(struct bpf_verifier_env *env, int idx)
 {
-	int depth = 0, frame = 0, idx = 0, i = 0, subprog_end;
 	struct bpf_subprog_info *subprog = env->subprog_info;
 	struct bpf_insn *insn = env->prog->insnsi;
+	int depth = 0, frame = 0, i, subprog_end;
 	bool tail_call_reachable = false;
 	int ret_insn[MAX_CALL_FRAMES];
 	int ret_prog[MAX_CALL_FRAMES];
 	int j;
 
+	i = subprog[idx].start;
 process_func:
 	/* protect against potential stack overflow that might happen when
 	 * bpf2bpf calls get combined with tailcalls. Limit the caller's stack
@@ -5491,6 +5492,22 @@ static int check_max_stack_depth(struct bpf_verifier_env *env)
 	goto continue_func;
 }
 
+static int check_max_stack_depth(struct bpf_verifier_env *env)
+{
+	struct bpf_subprog_info *si = env->subprog_info;
+	int ret;
+
+	for (int i = 0; i < env->subprog_cnt; i++) {
+		if (!i || si[i].is_async_cb) {
+			ret = check_max_stack_depth_subprog(env, i);
+			if (ret < 0)
+				return ret;
+		}
+		continue;
+	}
+	return 0;
+}
+
 #ifndef CONFIG_BPF_JIT_ALWAYS_ON
 static int get_callee_stack_depth(struct bpf_verifier_env *env,
 				  const struct bpf_insn *insn, int idx)



[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