This issue is most likely caused by the BPF verifier changes from
ubuntu-genial commit 68dd63b26223880d1b431b6bf54e45d93d04361a.

The BPF uses a map and bpf_map_update_elem crashes because the map
pointer is invalid.

The map pointer is invalid because the BPF instruction to load the
pointer into the BPF register R1 was broken. It's opcode 0x18 /
BPF_LD_IMM64. The lower part of the 64bit value is correctly loaded
(from the IMM value in that instruction). The following instruction
should be opcode 0 and IMM should be the higher 32 bits of the value.
But at the time the instruction is processed opcode is 0xBF and IMM=0.

- BPF_LD_IMM64 instruction: 0x18 0x01 0x00 0x00 0x00 0x1b 0xbf 0x38
- following instruction: 0xbf 0x00 0x00 0x00 0x00 0x00 0x00 0x00
- BPF_LD_IMM64 instruction: 0x18 0x01 0x00 0x00 0x00 0x1b 0xbf 0x38
- following instruction: 0x00 0x00 0x00 0x00 <higher 32 bits of map pointer>

In kernel/bpf/verifier.c the function replace_map_fd_with_map_ptr() prepares 
the IMM values of the instruction pair correctly.
But after setting up the map pointer the verifier continues. In do_check() the 
instructions that are part of accessed code are marked as "seen". After 
do_check() the function sanitize_dead_code() is run to turn "unseen" BPF 
instructions into NOPs. That's what happens with the 2nd half of the 
BPF_LD_IMM64! The part that carries the higher 32 bits of the value was not 
marked as "seen" and is consequently patched into a NOP which resets the higher 
32 bits of the map pointer to 0.

The change to sanitize the dead code was introduced in commit
68dd63b26223880d1b431b6bf54e45d93d04361a "bpf: fix branch pruning

The fix would be to add a line
env->insn_aux_data[insn_idx].seen = true;
in kernel/bpf/verifier.c (see below or in attached patch)

diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 8a40719c6ae5..5cc8b3f406e5 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -2005,6 +2005,7 @@ process_bpf_exit:
                                        return err;

+                               env->insn_aux_data[insn_idx].seen = true;
                        } else {
                                verbose("invalid BPF_LD mode\n");
                                return -EINVAL;

** Patch added: "Patch for BPF verifier"

You received this bug notification because you are a member of Ubuntu
Bugs, which is subscribed to Ubuntu.

  kernel panic in bpf_map_update_elem (with bcc tool ext4slower)

To manage notifications about this bug go to:

ubuntu-bugs mailing list

Reply via email to