selftests/bpf: Verify copy_register_state() preserves parent/live fields
authorEduard Zingerman <eddyz87@gmail.com>
Fri, 6 Jan 2023 14:22:14 +0000 (16:22 +0200)
committerAlexei Starovoitov <ast@kernel.org>
Thu, 19 Jan 2023 23:19:23 +0000 (15:19 -0800)
A testcase to check that verifier.c:copy_register_state() preserves
register parentage chain and livness information.

Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
Link: https://lore.kernel.org/r/20230106142214.1040390-3-eddyz87@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
tools/testing/selftests/bpf/verifier/search_pruning.c

index 68b14fdfebdb1f3d2d08afd3ac655e67a712d32a..d63fd8991b03aa9e9f3f2ec1b3f03419f8a1686c 100644 (file)
        .result_unpriv = ACCEPT,
        .insn_processed = 15,
 },
+/* The test performs a conditional 64-bit write to a stack location
+ * fp[-8], this is followed by an unconditional 8-bit write to fp[-8],
+ * then data is read from fp[-8]. This sequence is unsafe.
+ *
+ * The test would be mistakenly marked as safe w/o dst register parent
+ * preservation in verifier.c:copy_register_state() function.
+ *
+ * Note the usage of BPF_F_TEST_STATE_FREQ to force creation of the
+ * checkpoint state after conditional 64-bit assignment.
+ */
+{
+       "write tracking and register parent chain bug",
+       .insns = {
+       /* r6 = ktime_get_ns() */
+       BPF_EMIT_CALL(BPF_FUNC_ktime_get_ns),
+       BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
+       /* r0 = ktime_get_ns() */
+       BPF_EMIT_CALL(BPF_FUNC_ktime_get_ns),
+       /* if r0 > r6 goto +1 */
+       BPF_JMP_REG(BPF_JGT, BPF_REG_0, BPF_REG_6, 1),
+       /* *(u64 *)(r10 - 8) = 0xdeadbeef */
+       BPF_ST_MEM(BPF_DW, BPF_REG_FP, -8, 0xdeadbeef),
+       /* r1 = 42 */
+       BPF_MOV64_IMM(BPF_REG_1, 42),
+       /* *(u8 *)(r10 - 8) = r1 */
+       BPF_STX_MEM(BPF_B, BPF_REG_FP, BPF_REG_1, -8),
+       /* r2 = *(u64 *)(r10 - 8) */
+       BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_FP, -8),
+       /* exit(0) */
+       BPF_MOV64_IMM(BPF_REG_0, 0),
+       BPF_EXIT_INSN(),
+       },
+       .flags = BPF_F_TEST_STATE_FREQ,
+       .errstr = "invalid read from stack off -8+1 size 8",
+       .result = REJECT,
+},