Skip to content

Commit 4b2aa74

Browse files
committed
Fix eBPF compare-and-exchange instruction
Linux kernel's documentation tells in https://www.kernel.org/doc/html/v6.0/bpf/instruction-set.html#atomic-operations > The BPF_CMPXCHG operation atomically compares the value addressed by > dst_reg + off with R0. If they match, the value addressed by > dst_reg + off is replaced with src_reg. In either case, the value that > was at dst_reg + off before the operation is zero-extended and loaded > back to R0. If the values don't match, *(dst_reg + off) is not supposed to be modified. Moreover, register R0 is always modified and the 32-bit instruction truncates its value (with a zero-extension). This is also clear in the implementation of BPF_CMPXCHG in https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/kernel/bpf/core.c?h=v6.18#n2186 case BPF_CMPXCHG: if (BPF_SIZE(insn->code) == BPF_W) BPF_R0 = (u32) atomic_cmpxchg( (atomic_t *)(unsigned long) (DST + insn->off), (u32) BPF_R0, (u32) SRC); else if (BPF_SIZE(insn->code) == BPF_DW) BPF_R0 = (u64) atomic64_cmpxchg( (atomic64_t *)(unsigned long) (DST + insn->off), (u64) BPF_R0, (u64) SRC); Fix the semantic of the compare-and-exchange instruction accordingly.
1 parent fbd2641 commit 4b2aa74

File tree

1 file changed

+6
-6
lines changed
  • Ghidra/Processors/eBPF/data/languages

1 file changed

+6
-6
lines changed

Ghidra/Processors/eBPF/data/languages/eBPF.sinc

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -369,18 +369,18 @@ DST4: dst is dst { local tmp:4 = dst:4; export tmp; }
369369

370370
:ACMP32 [dst + off], src is imm=0xf1 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x0 & op_insn_class=0x3 {
371371
local tmp:4 = *:4 (dst + off);
372-
if (R0:4 == tmp) goto <equal>;
373-
R0 = zext(tmp);
374-
<equal>
372+
if (R0:4 != tmp) goto <notEqual>;
375373
*:4 (dst + off) = src:4;
374+
<notEqual>
375+
R0 = zext(tmp);
376376
}
377377

378378
:ACMP [dst + off], src is imm=0xf1 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x3 & op_insn_class=0x3 {
379379
local tmp:8 = *:8 (dst + off);
380-
if (R0 == tmp) goto <equal>;
381-
R0 = tmp;
382-
<equal>
380+
if (R0 != tmp) goto <notEqual>;
383381
*:8 (dst + off) = src;
382+
<notEqual>
383+
R0 = tmp;
384384
}
385385

386386
#Jump instructions (BPF_JMP, BPF_JMP32)

0 commit comments

Comments
 (0)