llvm-project
34acb4f9 - [BPF] Check every locked atomic insn for a used result (#231550)

Commit
8 days ago
[BPF] Check every locked atomic insn for a used result (#231550) With `-mcpu=v3` and later, a monotonic (relaxed) `atomicrmw add`, `sub`, `and`, `or` or `xor` whose result is used is selected to the locked insn, which does not return the old value, so the program gets the operand register back instead. The verifier accepts the program and it silently computes the wrong value: `next()` below returns 1 on every call instead of the previous value of `counter`, so anything built on it, such as an id or sequence counter, breaks without any error at compile or load time. ```c long counter; long next(void) { return __atomic_fetch_add(&counter, 1, __ATOMIC_RELAXED); } ``` Before: ``` r0 = 1 r1 = counter ll lock *(u64 *)(r1 + 0) += r0 exit ``` After: ``` r0 = 1 r1 = counter ll r0 = atomic_fetch_add((u64 *)(r1 + 0), r0) exit ``` Commit 4c4fb6ada7a1 (#107343) intended the locked insn for monotonic ordering only when the result is unused, through the `binop_no_use`/`binop_has_use` fragments, but only used them for the 64-bit `and`, `or` and `xor`. Use them for the 32-bit `add`, `sub`, `and`, `or`, `xor` and the 64-bit `add` and `sub` as well. The locked insn is still selected when the result is unused, and the `BPFNoALU32` patterns are unchanged: without alu32 there is no fetching add insn, and `BPFMIChecking` reports an error when the result of the locked insn is used. `BPFMIChecking` only checked `XADDW` and `XADDD`, and only without jmp32, so it never ran for v3+ and did not catch this. A live result of a locked insn is a selection bug on every cpu, so check all of the locked insns regardless of the cpu version. `atomics_mem_order_v3.ll` was generated from the wrong output and asserts it in seven of its ten `*_ret` functions; regenerate it and also run it with `-mcpu=v4`. Add `atomics_relaxed_alu32.ll`, covering every op and width with the result used and unused for `-mcpu=v1/v2 -mattr=+alu32` and `-mcpu=v3/v4`, and a MIR test that the checker reports each locked insn.
Author
Parents
Loading