Commit 4a8765d9 authored by Luis Gerhorst's avatar Luis Gerhorst Committed by Alexei Starovoitov
Browse files

selftests/bpf: Add test for Spectre v1 mitigation



This is based on the gadget from the description of commit 9183671a
("bpf: Fix leakage under speculation on mispredicted branches").

Signed-off-by: default avatarLuis Gerhorst <luis.gerhorst@fau.de>
Acked-by: default avatarKumar Kartikeya Dwivedi <memxor@gmail.com>
Link: https://lore.kernel.org/r/20250603212814.338867-1-luis.gerhorst@fau.de
Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parent d6f1c85f
Loading
Loading
Loading
Loading
+57 −0
Original line number Diff line number Diff line
@@ -744,4 +744,61 @@ l0_%=: r0 = 0; \
"	::: __clobber_all);
}

SEC("socket")
__description("unpriv: Spectre v1 path-based type confusion of scalar as stack-ptr")
__success __success_unpriv __retval(0)
#ifdef SPEC_V1
__xlated_unpriv("if r0 != 0x1 goto pc+2")
/* This nospec prevents the exploit because it forces the mispredicted (not
 * taken) `if r0 != 0x0 goto l0_%=` to resolve before using r6 as a pointer.
 * This causes the CPU to realize that `r6 = r9` should have never executed. It
 * ensures that r6 always contains a readable stack slot ptr when the insn after
 * the nospec executes.
 */
__xlated_unpriv("nospec")
__xlated_unpriv("r9 = *(u8 *)(r6 +0)")
#endif
__naked void unpriv_spec_v1_type_confusion(void)
{
	asm volatile ("					\
	r1 = 0;						\
	*(u64*)(r10 - 8) = r1;				\
	r2 = r10;					\
	r2 += -8;					\
	r1 = %[map_hash_8b] ll;				\
	call %[bpf_map_lookup_elem];			\
	if r0 == 0 goto l2_%=;				\
	/* r0: pointer to a map array entry */		\
	r2 = r10;					\
	r2 += -8;					\
	r1 = %[map_hash_8b] ll;				\
	/* r1, r2: prepared call args */		\
	r6 = r10;					\
	r6 += -8;					\
	/* r6: pointer to readable stack slot */	\
	r9 = 0xffffc900;				\
	r9 <<= 32;					\
	/* r9: scalar controlled by attacker */		\
	r0 = *(u64 *)(r0 + 0); /* cache miss */		\
	if r0 != 0x0 goto l0_%=;			\
	r6 = r9;					\
l0_%=:	if r0 != 0x1 goto l1_%=;			\
	r9 = *(u8 *)(r6 + 0);				\
l1_%=:  /* leak r9 */					\
	r9 &= 1;					\
	r9 <<= 9;					\
	*(u64*)(r10 - 8) = r9;				\
	call %[bpf_map_lookup_elem];			\
	if r0 == 0 goto l2_%=;				\
	/* leak secret into is_cached(map[0|512]): */	\
	r0 = *(u64 *)(r0 + 0);				\
l2_%=:							\
	r0 = 0;						\
	exit;						\
"	:
	: __imm(bpf_map_lookup_elem),
	  __imm_addr(map_hash_8b)
	: __clobber_all);
}

char _license[] SEC("license") = "GPL";