BPF List
 help / color / mirror / Atom feed
* [PATCH bpf v1 0/2] bpf: Fix precision tracking for BPF_ALU | BPF_TO_BE | BPF_END
@ 2023-11-02  5:39 Shung-Hsi Yu
  2023-11-02  5:39 ` [PATCH bpf v1 1/2] " Shung-Hsi Yu
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Shung-Hsi Yu @ 2023-11-02  5:39 UTC (permalink / raw)
  To: bpf
  Cc: Shung-Hsi Yu, Daniel Borkmann, Alexei Starovoitov,
	Toke Høiland-Jørgensen, John Fastabend, Andrii Nakryiko,
	Martin KaFai Lau, Song Liu, Yonghong Song, KP Singh,
	Stanislav Fomichev, Hao Luo, Jiri Olsa, Eduard Zingerman

Changes since v1:
- add test for negation and bswap (Alexei, Eduard)
- add test for BPF_TO_LE as well to cover all types of BPF_END opcode
- remove vals map and trigger backtracking with jump instead, based of
  Eduard's code
- v1 at https://lore.kernel.org/bpf/20231030132145.20867-1-shung-hsi.yu@suse.com

This patchset fixes and adds selftest for the issue reported by Mohamed
Mahmoud and Toke Høiland-Jørgensen where the kernel can run into a
verifier bug during backtracking of BPF_ALU | BPF_TO_BE | BPF_END
instruction[0]. As seen in the verifier log below, r0 was incorrectly
marked as precise even tough its value was not being used.

Patch 1 fixes the issue based on Andrii's analysis, and patch 2 adds a
selftest for such case using inline assembly. Please see individual
patch for detail.

    ...
	mark_precise: frame2: regs=r2 stack= before 1891: (77) r2 >>= 56
	mark_precise: frame2: regs=r2 stack= before 1890: (dc) r2 = be64 r2
	mark_precise: frame2: regs=r0,r2 stack= before 1889: (73) *(u8 *)(r1 +47) = r3
	...
	mark_precise: frame2: regs=r0 stack= before 212: (85) call pc+1617
	BUG regs 1
	processed 5112 insns (limit 1000000) max_states_per_insn 4 total_states 92 peak_states 90 mark_read 20

0: https://lore.kernel.org/r/87jzrrwptf.fsf@toke.dk


Shung-Hsi Yu (2):
  bpf: Fix precision tracking for BPF_ALU | BPF_TO_BE | BPF_END
  selftests/bpf: precision tracking test for BPF_NEG and BPF_END

 kernel/bpf/verifier.c                         |  7 +-
 .../selftests/bpf/prog_tests/verifier.c       |  2 +
 .../selftests/bpf/progs/verifier_precision.c  | 93 +++++++++++++++++++
 3 files changed, 101 insertions(+), 1 deletion(-)
 create mode 100644 tools/testing/selftests/bpf/progs/verifier_precision.c


base-commit: c17cda15cc86e65e9725641daddcd7a63cc9ad01
-- 
2.42.0


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH bpf v1 1/2] bpf: Fix precision tracking for BPF_ALU | BPF_TO_BE | BPF_END
  2023-11-02  5:39 [PATCH bpf v1 0/2] bpf: Fix precision tracking for BPF_ALU | BPF_TO_BE | BPF_END Shung-Hsi Yu
@ 2023-11-02  5:39 ` Shung-Hsi Yu
  2023-11-02  5:39 ` [PATCH bpf v1 2/2] selftests/bpf: precision tracking test for BPF_NEG and BPF_END Shung-Hsi Yu
  2023-11-02  6:10 ` [PATCH bpf v1 0/2] bpf: Fix precision tracking for BPF_ALU | BPF_TO_BE | BPF_END patchwork-bot+netdevbpf
  2 siblings, 0 replies; 4+ messages in thread
From: Shung-Hsi Yu @ 2023-11-02  5:39 UTC (permalink / raw)
  To: bpf
  Cc: Shung-Hsi Yu, Daniel Borkmann, Alexei Starovoitov,
	Toke Høiland-Jørgensen, John Fastabend, Andrii Nakryiko,
	Martin KaFai Lau, Song Liu, Yonghong Song, KP Singh,
	Stanislav Fomichev, Hao Luo, Jiri Olsa, Eduard Zingerman, stable,
	Mohamed Mahmoud, Tao Lyu

BPF_END and BPF_NEG has a different specification for the source bit in
the opcode compared to other ALU/ALU64 instructions, and is either
reserved or use to specify the byte swap endianness. In both cases the
source bit does not encode source operand location, and src_reg is a
reserved field.

backtrack_insn() currently does not differentiate BPF_END and BPF_NEG
from other ALU/ALU64 instructions, which leads to r0 being incorrectly
marked as precise when processing BPF_ALU | BPF_TO_BE | BPF_END
instructions. This commit teaches backtrack_insn() to correctly mark
precision for such case.

While precise tracking of BPF_NEG and other BPF_END instructions are
correct and does not need fixing, this commit opt to process all BPF_NEG
and BPF_END instructions within the same if-clause to better align with
current convention used in the verifier (e.g. check_alu_op).

Fixes: b5dc0163d8fd ("bpf: precise scalar_value tracking")
Cc: stable@vger.kernel.org
Reported-by: Mohamed Mahmoud <mmahmoud@redhat.com>
Closes: https://lore.kernel.org/r/87jzrrwptf.fsf@toke.dk
Tested-by: Toke Høiland-Jørgensen <toke@redhat.com>
Tested-by: Tao Lyu <tao.lyu@epfl.ch>
Acked-by: Eduard Zingerman <eddyz87@gmail.com>
Signed-off-by: Shung-Hsi Yu <shung-hsi.yu@suse.com>
---
 kernel/bpf/verifier.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 873ade146f3d..ba9aee3a4269 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -3426,7 +3426,12 @@ static int backtrack_insn(struct bpf_verifier_env *env, int idx, int subseq_idx,
 	if (class == BPF_ALU || class == BPF_ALU64) {
 		if (!bt_is_reg_set(bt, dreg))
 			return 0;
-		if (opcode == BPF_MOV) {
+		if (opcode == BPF_END || opcode == BPF_NEG) {
+			/* sreg is reserved and unused
+			 * dreg still need precision before this insn
+			 */
+			return 0;
+		} else if (opcode == BPF_MOV) {
 			if (BPF_SRC(insn->code) == BPF_X) {
 				/* dreg = sreg or dreg = (s8, s16, s32)sreg
 				 * dreg needs precision after this insn
-- 
2.42.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH bpf v1 2/2] selftests/bpf: precision tracking test for BPF_NEG and BPF_END
  2023-11-02  5:39 [PATCH bpf v1 0/2] bpf: Fix precision tracking for BPF_ALU | BPF_TO_BE | BPF_END Shung-Hsi Yu
  2023-11-02  5:39 ` [PATCH bpf v1 1/2] " Shung-Hsi Yu
@ 2023-11-02  5:39 ` Shung-Hsi Yu
  2023-11-02  6:10 ` [PATCH bpf v1 0/2] bpf: Fix precision tracking for BPF_ALU | BPF_TO_BE | BPF_END patchwork-bot+netdevbpf
  2 siblings, 0 replies; 4+ messages in thread
From: Shung-Hsi Yu @ 2023-11-02  5:39 UTC (permalink / raw)
  To: bpf
  Cc: Shung-Hsi Yu, Daniel Borkmann, Alexei Starovoitov,
	Toke Høiland-Jørgensen, John Fastabend, Andrii Nakryiko,
	Martin KaFai Lau, Song Liu, Yonghong Song, KP Singh,
	Stanislav Fomichev, Hao Luo, Jiri Olsa, Eduard Zingerman,
	Mykola Lysenko, Shuah Khan, Paul Walmsley, Palmer Dabbelt,
	Albert Ou

As seen from previous commit that fix backtracking for BPF_ALU | BPF_TO_BE
| BPF_END, both BPF_NEG and BPF_END require special handling. Add tests
written with inline assembly to check that the verifier does not incorrecly
use the src_reg field of BPF_NEG and BPF_END (including bswap added in v4).

Suggested-by: Eduard Zingerman <eddyz87@gmail.com>
Signed-off-by: Shung-Hsi Yu <shung-hsi.yu@suse.com>
---
 .../selftests/bpf/prog_tests/verifier.c       |  2 +
 .../selftests/bpf/progs/verifier_precision.c  | 93 +++++++++++++++++++
 2 files changed, 95 insertions(+)
 create mode 100644 tools/testing/selftests/bpf/progs/verifier_precision.c

diff --git a/tools/testing/selftests/bpf/prog_tests/verifier.c b/tools/testing/selftests/bpf/prog_tests/verifier.c
index e3e68c97b40c..e5c61aa6604a 100644
--- a/tools/testing/selftests/bpf/prog_tests/verifier.c
+++ b/tools/testing/selftests/bpf/prog_tests/verifier.c
@@ -46,6 +46,7 @@
 #include "verifier_movsx.skel.h"
 #include "verifier_netfilter_ctx.skel.h"
 #include "verifier_netfilter_retcode.skel.h"
+#include "verifier_precision.skel.h"
 #include "verifier_prevent_map_lookup.skel.h"
 #include "verifier_raw_stack.skel.h"
 #include "verifier_raw_tp_writable.skel.h"
@@ -153,6 +154,7 @@ void test_verifier_meta_access(void)          { RUN(verifier_meta_access); }
 void test_verifier_movsx(void)                 { RUN(verifier_movsx); }
 void test_verifier_netfilter_ctx(void)        { RUN(verifier_netfilter_ctx); }
 void test_verifier_netfilter_retcode(void)    { RUN(verifier_netfilter_retcode); }
+void test_verifier_precision(void)            { RUN(verifier_precision); }
 void test_verifier_prevent_map_lookup(void)   { RUN(verifier_prevent_map_lookup); }
 void test_verifier_raw_stack(void)            { RUN(verifier_raw_stack); }
 void test_verifier_raw_tp_writable(void)      { RUN(verifier_raw_tp_writable); }
diff --git a/tools/testing/selftests/bpf/progs/verifier_precision.c b/tools/testing/selftests/bpf/progs/verifier_precision.c
new file mode 100644
index 000000000000..193c0f8272d0
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/verifier_precision.c
@@ -0,0 +1,93 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (C) 2023 SUSE LLC */
+#include <linux/bpf.h>
+#include <bpf/bpf_helpers.h>
+#include "bpf_misc.h"
+
+SEC("?raw_tp")
+__success __log_level(2)
+__msg("mark_precise: frame0: regs=r2 stack= before 3: (bf) r1 = r10")
+__msg("mark_precise: frame0: regs=r2 stack= before 2: (55) if r2 != 0xfffffff8 goto pc+2")
+__msg("mark_precise: frame0: regs=r2 stack= before 1: (87) r2 = -r2")
+__msg("mark_precise: frame0: regs=r2 stack= before 0: (b7) r2 = 8")
+__naked int bpf_neg(void)
+{
+	asm volatile (
+		"r2 = 8;"
+		"r2 = -r2;"
+		"if r2 != -8 goto 1f;"
+		"r1 = r10;"
+		"r1 += r2;"
+	"1:"
+		"r0 = 0;"
+		"exit;"
+		::: __clobber_all);
+}
+
+SEC("?raw_tp")
+__success __log_level(2)
+__msg("mark_precise: frame0: regs=r2 stack= before 3: (bf) r1 = r10")
+__msg("mark_precise: frame0: regs=r2 stack= before 2: (55) if r2 != 0x0 goto pc+2")
+__msg("mark_precise: frame0: regs=r2 stack= before 1: (d4) r2 = le16 r2")
+__msg("mark_precise: frame0: regs=r2 stack= before 0: (b7) r2 = 0")
+__naked int bpf_end_to_le(void)
+{
+	asm volatile (
+		"r2 = 0;"
+		"r2 = le16 r2;"
+		"if r2 != 0 goto 1f;"
+		"r1 = r10;"
+		"r1 += r2;"
+	"1:"
+		"r0 = 0;"
+		"exit;"
+		::: __clobber_all);
+}
+
+
+SEC("?raw_tp")
+__success __log_level(2)
+__msg("mark_precise: frame0: regs=r2 stack= before 3: (bf) r1 = r10")
+__msg("mark_precise: frame0: regs=r2 stack= before 2: (55) if r2 != 0x0 goto pc+2")
+__msg("mark_precise: frame0: regs=r2 stack= before 1: (dc) r2 = be16 r2")
+__msg("mark_precise: frame0: regs=r2 stack= before 0: (b7) r2 = 0")
+__naked int bpf_end_to_be(void)
+{
+	asm volatile (
+		"r2 = 0;"
+		"r2 = be16 r2;"
+		"if r2 != 0 goto 1f;"
+		"r1 = r10;"
+		"r1 += r2;"
+	"1:"
+		"r0 = 0;"
+		"exit;"
+		::: __clobber_all);
+}
+
+#if (defined(__TARGET_ARCH_arm64) || defined(__TARGET_ARCH_x86) || \
+	(defined(__TARGET_ARCH_riscv) && __riscv_xlen == 64) || \
+	defined(__TARGET_ARCH_arm) || defined(__TARGET_ARCH_s390)) && \
+	__clang_major__ >= 18
+
+SEC("?raw_tp")
+__success __log_level(2)
+__msg("mark_precise: frame0: regs=r2 stack= before 3: (bf) r1 = r10")
+__msg("mark_precise: frame0: regs=r2 stack= before 2: (55) if r2 != 0x0 goto pc+2")
+__msg("mark_precise: frame0: regs=r2 stack= before 1: (d7) r2 = bswap16 r2")
+__msg("mark_precise: frame0: regs=r2 stack= before 0: (b7) r2 = 0")
+__naked int bpf_end_bswap(void)
+{
+	asm volatile (
+		"r2 = 0;"
+		"r2 = bswap16 r2;"
+		"if r2 != 0 goto 1f;"
+		"r1 = r10;"
+		"r1 += r2;"
+	"1:"
+		"r0 = 0;"
+		"exit;"
+		::: __clobber_all);
+}
+
+#endif /* v4 instruction */
-- 
2.42.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH bpf v1 0/2] bpf: Fix precision tracking for BPF_ALU | BPF_TO_BE | BPF_END
  2023-11-02  5:39 [PATCH bpf v1 0/2] bpf: Fix precision tracking for BPF_ALU | BPF_TO_BE | BPF_END Shung-Hsi Yu
  2023-11-02  5:39 ` [PATCH bpf v1 1/2] " Shung-Hsi Yu
  2023-11-02  5:39 ` [PATCH bpf v1 2/2] selftests/bpf: precision tracking test for BPF_NEG and BPF_END Shung-Hsi Yu
@ 2023-11-02  6:10 ` patchwork-bot+netdevbpf
  2 siblings, 0 replies; 4+ messages in thread
From: patchwork-bot+netdevbpf @ 2023-11-02  6:10 UTC (permalink / raw)
  To: Shung-Hsi Yu
  Cc: bpf, daniel, ast, toke, john.fastabend, andrii, martin.lau, song,
	yonghong.song, kpsingh, sdf, haoluo, jolsa, eddyz87

Hello:

This series was applied to bpf/bpf.git (master)
by Alexei Starovoitov <ast@kernel.org>:

On Thu,  2 Nov 2023 13:39:02 +0800 you wrote:
> Changes since v1:
> - add test for negation and bswap (Alexei, Eduard)
> - add test for BPF_TO_LE as well to cover all types of BPF_END opcode
> - remove vals map and trigger backtracking with jump instead, based of
>   Eduard's code
> - v1 at https://lore.kernel.org/bpf/20231030132145.20867-1-shung-hsi.yu@suse.com
> 
> [...]

Here is the summary with links:
  - [bpf,v1,1/2] bpf: Fix precision tracking for BPF_ALU | BPF_TO_BE | BPF_END
    https://git.kernel.org/bpf/bpf/c/291d044fd51f
  - [bpf,v1,2/2] selftests/bpf: precision tracking test for BPF_NEG and BPF_END
    https://git.kernel.org/bpf/bpf/c/3c41971550f5

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2023-11-02  6:10 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-11-02  5:39 [PATCH bpf v1 0/2] bpf: Fix precision tracking for BPF_ALU | BPF_TO_BE | BPF_END Shung-Hsi Yu
2023-11-02  5:39 ` [PATCH bpf v1 1/2] " Shung-Hsi Yu
2023-11-02  5:39 ` [PATCH bpf v1 2/2] selftests/bpf: precision tracking test for BPF_NEG and BPF_END Shung-Hsi Yu
2023-11-02  6:10 ` [PATCH bpf v1 0/2] bpf: Fix precision tracking for BPF_ALU | BPF_TO_BE | BPF_END patchwork-bot+netdevbpf

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox