forked from mirrors/linux
		
	bpf/tests: Fix error in tail call limit tests
This patch fixes an error in the tail call limit test that caused the
test to fail on for x86-64 JIT. Previously, the register R0 was used to
report the total number of tail calls made. However, after a tail call
fall-through, the value of the R0 register is undefined. Now, all tail
call error path tests instead use context state to store the count.
Fixes: 874be05f52 ("bpf, tests: Add tail call test suite")
Reported-by: Paul Chaignon <paul@cilium.io>
Reported-by: Tiezhu Yang <yangtiezhu@loongson.cn>
Signed-off-by: Johan Almbladh <johan.almbladh@anyfinetworks.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Tested-by: Tiezhu Yang <yangtiezhu@loongson.cn>
Link: https://lore.kernel.org/bpf/20210914091842.4186267-14-johan.almbladh@anyfinetworks.com
			
			
This commit is contained in:
		
							parent
							
								
									f536a7c806
								
							
						
					
					
						commit
						18935a72eb
					
				
					 1 changed files with 27 additions and 10 deletions
				
			
		|  | @ -12180,10 +12180,15 @@ static __init int test_bpf(void) | |||
| struct tail_call_test { | ||||
| 	const char *descr; | ||||
| 	struct bpf_insn insns[MAX_INSNS]; | ||||
| 	int flags; | ||||
| 	int result; | ||||
| 	int stack_depth; | ||||
| }; | ||||
| 
 | ||||
| /* Flags that can be passed to tail call test cases */ | ||||
| #define FLAG_NEED_STATE		BIT(0) | ||||
| #define FLAG_RESULT_IN_STATE	BIT(1) | ||||
| 
 | ||||
| /*
 | ||||
|  * Magic marker used in test snippets for tail calls below. | ||||
|  * BPF_LD/MOV to R2 and R2 with this immediate value is replaced | ||||
|  | @ -12253,32 +12258,38 @@ static struct tail_call_test tail_call_tests[] = { | |||
| 	{ | ||||
| 		"Tail call error path, max count reached", | ||||
| 		.insns = { | ||||
| 			BPF_ALU64_IMM(BPF_ADD, R1, 1), | ||||
| 			BPF_ALU64_REG(BPF_MOV, R0, R1), | ||||
| 			BPF_LDX_MEM(BPF_W, R2, R1, 0), | ||||
| 			BPF_ALU64_IMM(BPF_ADD, R2, 1), | ||||
| 			BPF_STX_MEM(BPF_W, R1, R2, 0), | ||||
| 			TAIL_CALL(0), | ||||
| 			BPF_EXIT_INSN(), | ||||
| 		}, | ||||
| 		.result = MAX_TAIL_CALL_CNT + 1, | ||||
| 		.flags = FLAG_NEED_STATE | FLAG_RESULT_IN_STATE, | ||||
| 		.result = (MAX_TAIL_CALL_CNT + 1 + 1) * MAX_TESTRUNS, | ||||
| 	}, | ||||
| 	{ | ||||
| 		"Tail call error path, NULL target", | ||||
| 		.insns = { | ||||
| 			BPF_ALU64_IMM(BPF_MOV, R0, -1), | ||||
| 			BPF_LDX_MEM(BPF_W, R2, R1, 0), | ||||
| 			BPF_ALU64_IMM(BPF_ADD, R2, 1), | ||||
| 			BPF_STX_MEM(BPF_W, R1, R2, 0), | ||||
| 			TAIL_CALL(TAIL_CALL_NULL), | ||||
| 			BPF_ALU64_IMM(BPF_MOV, R0, 1), | ||||
| 			BPF_EXIT_INSN(), | ||||
| 		}, | ||||
| 		.result = 1, | ||||
| 		.flags = FLAG_NEED_STATE | FLAG_RESULT_IN_STATE, | ||||
| 		.result = MAX_TESTRUNS, | ||||
| 	}, | ||||
| 	{ | ||||
| 		"Tail call error path, index out of range", | ||||
| 		.insns = { | ||||
| 			BPF_ALU64_IMM(BPF_MOV, R0, -1), | ||||
| 			BPF_LDX_MEM(BPF_W, R2, R1, 0), | ||||
| 			BPF_ALU64_IMM(BPF_ADD, R2, 1), | ||||
| 			BPF_STX_MEM(BPF_W, R1, R2, 0), | ||||
| 			TAIL_CALL(TAIL_CALL_INVALID), | ||||
| 			BPF_ALU64_IMM(BPF_MOV, R0, 1), | ||||
| 			BPF_EXIT_INSN(), | ||||
| 		}, | ||||
| 		.result = 1, | ||||
| 		.flags = FLAG_NEED_STATE | FLAG_RESULT_IN_STATE, | ||||
| 		.result = MAX_TESTRUNS, | ||||
| 	}, | ||||
| }; | ||||
| 
 | ||||
|  | @ -12384,6 +12395,8 @@ static __init int test_tail_calls(struct bpf_array *progs) | |||
| 	for (i = 0; i < ARRAY_SIZE(tail_call_tests); i++) { | ||||
| 		struct tail_call_test *test = &tail_call_tests[i]; | ||||
| 		struct bpf_prog *fp = progs->ptrs[i]; | ||||
| 		int *data = NULL; | ||||
| 		int state = 0; | ||||
| 		u64 duration; | ||||
| 		int ret; | ||||
| 
 | ||||
|  | @ -12400,7 +12413,11 @@ static __init int test_tail_calls(struct bpf_array *progs) | |||
| 		if (fp->jited) | ||||
| 			jit_cnt++; | ||||
| 
 | ||||
| 		ret = __run_one(fp, NULL, MAX_TESTRUNS, &duration); | ||||
| 		if (test->flags & FLAG_NEED_STATE) | ||||
| 			data = &state; | ||||
| 		ret = __run_one(fp, data, MAX_TESTRUNS, &duration); | ||||
| 		if (test->flags & FLAG_RESULT_IN_STATE) | ||||
| 			ret = state; | ||||
| 		if (ret == test->result) { | ||||
| 			pr_cont("%lld PASS", duration); | ||||
| 			pass_cnt++; | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Johan Almbladh
						Johan Almbladh