linux/kernel/bpf
Brendan Jackman 39491867ac bpf: Explicitly zero-extend R0 after 32-bit cmpxchg
As pointed out by Ilya and explained in the new comment, there's a
discrepancy between x86 and BPF CMPXCHG semantics: BPF always loads
the value from memory into r0, while x86 only does so when r0 and the
value in memory are different. The same issue affects s390.

At first this might sound like pure semantics, but it makes a real
difference when the comparison is 32-bit, since the load will
zero-extend r0/rax.

The fix is to explicitly zero-extend rax after doing such a
CMPXCHG. Since this problem affects multiple archs, this is done in
the verifier by patching in a BPF_ZEXT_REG instruction after every
32-bit cmpxchg. Any archs that don't need such manual zero-extension
can do a look-ahead with insn_is_zext to skip the unnecessary mov.

Note this still goes on top of Ilya's patch:

https://lore.kernel.org/bpf/20210301154019.129110-1-iii@linux.ibm.com/T/#u

Differences v5->v6[1]:
 - Moved is_cmpxchg_insn and ensured it can be safely re-used. Also renamed it
   and removed 'inline' to match the style of the is_*_function helpers.
 - Fixed up comments in verifier test (thanks for the careful review, Martin!)

Differences v4->v5[1]:
 - Moved the logic entirely into opt_subreg_zext_lo32_rnd_hi32, thanks to Martin
   for suggesting this.

Differences v3->v4[1]:
 - Moved the optimization against pointless zext into the correct place:
   opt_subreg_zext_lo32_rnd_hi32 is called _after_ fixup_bpf_calls.

Differences v2->v3[1]:
 - Moved patching into fixup_bpf_calls (patch incoming to rename this function)
 - Added extra commentary on bpf_jit_needs_zext
 - Added check to avoid adding a pointless zext(r0) if there's already one there.

Difference v1->v2[1]: Now solved centrally in the verifier instead of
  specifically for the x86 JIT. Thanks to Ilya and Daniel for the suggestions!

[1] v5: https://lore.kernel.org/bpf/CA+i-1C3ytZz6FjcPmUg5s4L51pMQDxWcZNvM86w4RHZ_o2khwg@mail.gmail.com/T/#t
    v4: https://lore.kernel.org/bpf/CA+i-1C3ytZz6FjcPmUg5s4L51pMQDxWcZNvM86w4RHZ_o2khwg@mail.gmail.com/T/#t
    v3: https://lore.kernel.org/bpf/08669818-c99d-0d30-e1db-53160c063611@iogearbox.net/T/#t
    v2: https://lore.kernel.org/bpf/08669818-c99d-0d30-e1db-53160c063611@iogearbox.net/T/#t
    v1: https://lore.kernel.org/bpf/d7ebaefb-bfd6-a441-3ff2-2fdfe699b1d2@iogearbox.net/T/#t

Reported-by: Ilya Leoshkevich <iii@linux.ibm.com>
Fixes: 5ffa25502b ("bpf: Add instructions for atomic_[cmp]xchg")
Signed-off-by: Brendan Jackman <jackmanb@google.com>
Acked-by: Martin KaFai Lau <kafai@fb.com>
Acked-by: Ilya Leoshkevich <iii@linux.ibm.com>
Tested-by: Ilya Leoshkevich <iii@linux.ibm.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
2021-03-04 19:06:03 -08:00
..
preload Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net 2021-02-02 14:21:31 -08:00
arraymap.c bpf: Eliminate rlimit-based memory accounting for arraymap maps 2020-12-02 18:32:46 -08:00
bpf_inode_storage.c bpf, inode_storage: Put file handler if no storage was found 2021-01-22 23:19:24 +01:00
bpf_iter.c bpf: Fix an unitialized value in bpf_iter 2021-02-12 13:33:50 -08:00
bpf_local_storage.c bpf: Eliminate rlimit-based memory accounting for bpf local storage maps 2020-12-02 18:32:47 -08:00
bpf_lru_list.c bpf_lru_list: Read double-checked variable once without lock 2021-02-10 15:54:26 -08:00
bpf_lru_list.h bpf: Fix a typo "inacitve" -> "inactive" 2020-04-06 21:54:10 +02:00
bpf_lsm.c bpf: Drop disabled LSM hooks from the sleepable set 2021-01-26 17:08:50 +01:00
bpf_struct_ops_types.h
bpf_struct_ops.c bpf: Eliminate rlimit-based memory accounting for bpf_struct_ops maps 2020-12-02 18:32:46 -08:00
bpf_task_storage.c bpf: Local storage helpers should check nullness of owner ptr passed 2021-01-12 16:07:56 +01:00
btf.c bpf: Drop imprecise log message 2021-02-24 16:43:39 +01:00
cgroup.c Merge git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next 2021-02-16 13:14:06 -08:00
core.c bpf: Explicitly zero-extend R0 after 32-bit cmpxchg 2021-03-04 19:06:03 -08:00
cpumap.c net, xdp: Introduce __xdp_build_skb_from_frame utility routine 2021-01-20 14:10:35 -08:00
devmap.c bpf, devmap: Use GFP_KERNEL for xdp bulk queue allocation 2021-02-13 00:11:26 +01:00
disasm.c bpf: Change 'BPF_ADD' to 'BPF_AND' in print_bpf_insn() 2021-01-27 22:23:46 +01:00
disasm.h
dispatcher.c bpf: Remove bpf_image tree 2020-03-13 12:49:52 -07:00
hashtab.c bpf: Allows per-cpu maps and map-in-map in sleepable programs 2021-02-11 16:19:26 +01:00
helpers.c bpf: Simplify cases in bpf_base_func_proto 2021-01-29 02:20:28 +01:00
inode.c fs: make helpers idmap mount aware 2021-01-24 14:27:20 +01:00
local_storage.c bpf: Eliminate rlimit-based memory accounting for cgroup storage maps 2020-12-02 18:32:46 -08:00
lpm_trie.c bpf: Eliminate rlimit-based memory accounting for lpm_trie maps 2020-12-02 18:32:46 -08:00
Makefile Merge git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next 2020-11-14 09:13:41 -08:00
map_in_map.c bpf: Relax max_entries check for most of the inner map types 2020-08-28 15:41:30 +02:00
map_in_map.h bpf: Add map_meta_equal map ops 2020-08-28 15:41:30 +02:00
map_iter.c bpf: Implement link_query callbacks in map element iterators 2020-08-21 14:01:39 -07:00
net_namespace.c bpf: Add support for forced LINK_DETACH command 2020-08-01 20:38:28 -07:00
offload.c bpf, offload: Replace bitwise AND by logical AND in bpf_prog_offload_info_fill 2020-02-17 16:53:49 +01:00
percpu_freelist.c bpf: Use raw_spin_trylock() for pcpu_freelist_push/pop in NMI 2020-10-06 00:04:11 +02:00
percpu_freelist.h bpf: Use raw_spin_trylock() for pcpu_freelist_push/pop in NMI 2020-10-06 00:04:11 +02:00
prog_iter.c bpf: Refactor bpf_iter_reg to have separate seq_info member 2020-07-25 20:16:32 -07:00
queue_stack_maps.c bpf: Eliminate rlimit-based memory accounting for queue_stack_maps maps 2020-12-02 18:32:46 -08:00
reuseport_array.c bpf: Eliminate rlimit-based memory accounting for reuseport_array maps 2020-12-02 18:32:47 -08:00
ringbuf.c bpf: Eliminate rlimit-based memory accounting for bpf ringbuffer 2020-12-02 18:32:47 -08:00
stackmap.c Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net 2021-02-10 13:30:12 -08:00
syscall.c bpf: Count the number of times recursion was prevented 2021-02-11 16:19:20 +01:00
sysfs_btf.c bpf: Load and verify kernel module BTFs 2020-11-10 15:25:53 -08:00
task_iter.c bpf: Introduce task_vma bpf_iter 2021-02-12 12:56:53 -08:00
tnum.c bpf: Verifier, do explicit ALU32 bounds tracking 2020-03-30 14:59:53 -07:00
trampoline.c bpf: Count the number of times recursion was prevented 2021-02-11 16:19:20 +01:00
verifier.c bpf: Explicitly zero-extend R0 after 32-bit cmpxchg 2021-03-04 19:06:03 -08:00