Skip to content

Commit 9a76be5

Browse files
Hou Taovijay-suman
authored andcommitted
bpf: Check rcu_read_lock_trace_held() before calling bpf map helpers
commit 169410e upstream. These three bpf_map_{lookup,update,delete}_elem() helpers are also available for sleepable bpf program, so add the corresponding lock assertion for sleepable bpf program, otherwise the following warning will be reported when a sleepable bpf program manipulates bpf map under interpreter mode (aka bpf_jit_enable=0): WARNING: CPU: 3 PID: 4985 at kernel/bpf/helpers.c:40 ...... CPU: 3 PID: 4985 Comm: test_progs Not tainted 6.6.0+ #2 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996) ...... RIP: 0010:bpf_map_lookup_elem+0x54/0x60 ...... Call Trace: <TASK> ? __warn+0xa5/0x240 ? bpf_map_lookup_elem+0x54/0x60 ? report_bug+0x1ba/0x1f0 ? handle_bug+0x40/0x80 ? exc_invalid_op+0x18/0x50 ? asm_exc_invalid_op+0x1b/0x20 ? __pfx_bpf_map_lookup_elem+0x10/0x10 ? rcu_lockdep_current_cpu_online+0x65/0xb0 ? rcu_is_watching+0x23/0x50 ? bpf_map_lookup_elem+0x54/0x60 ? __pfx_bpf_map_lookup_elem+0x10/0x10 ___bpf_prog_run+0x513/0x3b70 __bpf_prog_run32+0x9d/0xd0 ? __bpf_prog_enter_sleepable_recur+0xad/0x120 ? __bpf_prog_enter_sleepable_recur+0x3e/0x120 bpf_trampoline_6442580665+0x4d/0x1000 __x64_sys_getpgid+0x5/0x30 ? do_syscall_64+0x36/0xb0 entry_SYSCALL_64_after_hwframe+0x6e/0x76 </TASK> Signed-off-by: Hou Tao <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Alexei Starovoitov <[email protected]> Signed-off-by: Cliff Liu <[email protected]> Signed-off-by: He Zhe <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]> (cherry picked from commit 3516f93cc63d956e1b290ae4b7bf2586074535a0) Signed-off-by: Vijayendra Suman <[email protected]>
1 parent 7f2d42d commit 9a76be5

File tree

1 file changed

+9
-5
lines changed

1 file changed

+9
-5
lines changed

kernel/bpf/helpers.c

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include <linux/bpf.h>
55
#include <linux/btf.h>
66
#include <linux/rcupdate.h>
7+
#include <linux/rcupdate_trace.h>
78
#include <linux/random.h>
89
#include <linux/smp.h>
910
#include <linux/topology.h>
@@ -25,12 +26,13 @@
2526
*
2627
* Different map implementations will rely on rcu in map methods
2728
* lookup/update/delete, therefore eBPF programs must run under rcu lock
28-
* if program is allowed to access maps, so check rcu_read_lock_held in
29-
* all three functions.
29+
* if program is allowed to access maps, so check rcu_read_lock_held() or
30+
* rcu_read_lock_trace_held() in all three functions.
3031
*/
3132
BPF_CALL_2(bpf_map_lookup_elem, struct bpf_map *, map, void *, key)
3233
{
33-
WARN_ON_ONCE(!rcu_read_lock_held() && !rcu_read_lock_bh_held());
34+
WARN_ON_ONCE(!rcu_read_lock_held() && !rcu_read_lock_trace_held() &&
35+
!rcu_read_lock_bh_held());
3436
return (unsigned long) map->ops->map_lookup_elem(map, key);
3537
}
3638

@@ -46,7 +48,8 @@ const struct bpf_func_proto bpf_map_lookup_elem_proto = {
4648
BPF_CALL_4(bpf_map_update_elem, struct bpf_map *, map, void *, key,
4749
void *, value, u64, flags)
4850
{
49-
WARN_ON_ONCE(!rcu_read_lock_held() && !rcu_read_lock_bh_held());
51+
WARN_ON_ONCE(!rcu_read_lock_held() && !rcu_read_lock_trace_held() &&
52+
!rcu_read_lock_bh_held());
5053
return map->ops->map_update_elem(map, key, value, flags);
5154
}
5255

@@ -63,7 +66,8 @@ const struct bpf_func_proto bpf_map_update_elem_proto = {
6366

6467
BPF_CALL_2(bpf_map_delete_elem, struct bpf_map *, map, void *, key)
6568
{
66-
WARN_ON_ONCE(!rcu_read_lock_held() && !rcu_read_lock_bh_held());
69+
WARN_ON_ONCE(!rcu_read_lock_held() && !rcu_read_lock_trace_held() &&
70+
!rcu_read_lock_bh_held());
6771
return map->ops->map_delete_elem(map, key);
6872
}
6973

0 commit comments

Comments
 (0)