[PATCH net] net: kcm: Hold RCU read lock while running BPF parser

Junseo Lim <[email protected]>
Newsgroups org.kernel.vger.netdev,org.kernel.vger.bpf
Message-ID <[email protected]>
kcm_parse_func_strparser() calls bpf_prog_run_pin_on_cpu() which
prevents CPU migration, but does not establish an RCU read-side
critical section. Consequently, BPF map operations can trigger
WARN_ON_ONCE(!bpf_rcu_lock_held()) when called from the KCM strparser
program.

Hold the RCU read lock while running the program.

Fixes: 9b73896a81dc ("kcm: Use stream parser")
Reported-by: Sechang Lim <[email protected]>
Signed-off-by: Junseo Lim <[email protected]>
---
This issue was found by a custom fuzzer developed by
Sechang Lim <[email protected]>.

The report could not be reproduced locally.  However, the trace shows
the BPF parser being invoked from strp_work without an RCU read-side
critical section.

Below is an excerpt of the warning:

    WARNING: kernel/bpf/hashtab.c:1547 at htab_lru_map_delete_elem+0x604/0x700, CPU#0: kworker/u4:2/28
    CPU: 0 UID: 0 PID: 28 Comm: kworker/u4:2 Not tainted 7.2.0-rc4-dirty #3 PREEMPT(full)
    Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.16.3-0-ga6ed6b701f0a-prebuilt.qemu.org 04/01/2014
    Workqueue: kstrp strp_work
    RIP: 0010:htab_lru_map_delete_elem+0x604/0x700
    Code: 8f d9 03 48 3b 44 24 30 0f 85 b0 00 00 00 4c 89 e0 48 83 c4 38 5b 41 5c 41 5d 41 5e 41 5f 5d c3 cc cc cc cc cc e8 ec a0 dd ff <0f> 0b e9 35 fa ff ff 44 89 f9 80 e1 07 80 c1 03 38 c1 0f 8c 54 fa
    RSP: 0018:ffffc900001cf678 EFLAGS: 00010293
    RAX: ffffffff8e8910f4 RBX: ffff888102bf8800 RCX: ffff888100ce8000
    RDX: 0000000000000000 RSI: ffffffff91df4082 RDI: ffffffff91597ac0
    RBP: ffffc900001cf7f8 R08: 0000000000000000 R09: 0000000000000000
    R10: ffff888106cf6180 R11: ffffffffc020540c R12: ffffc900001cf778
    R13: 1ffff1102019d07f R14: ffff888106cf6140 R15: ffffc90020a65000
    FS:  0000000000000000(0000) GS:0000000000000000(0000) knlGS:0000000000000000
    CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
    CR2: 0000001b34521ff8 CR3: 0000000021a28001 CR4: 0000000000370ef0
    Call Trace:
     <TASK>
     bpf_prog_5dda175565b852e0+0x140/0x153
     ? __copy_skb_header+0xba/0x480
     ? __asan_memcpy+0x40/0x70
     ? __skb_clone+0x61/0x8f0
     bpf_prog_run_pin_on_cpu+0xf4/0x330
     kcm_parse_func_strparser+0x60/0xb0
     __strp_recv+0x5d5/0x1880
     __tcp_read_sock+0x181/0x8c0
     ? __pfx_strp_recv+0x10/0x10
     ? __pfx_tcp_read_sock+0x10/0x10
     strp_work+0x20f/0x3c0
     ? __pfx_strp_work+0x10/0x10
     ? lock_acquire+0xf5/0x250
     ? process_scheduled_works+0x9ce/0x13c0
     process_scheduled_works+0xa3f/0x13c0
     ? __pfx_process_scheduled_works+0x10/0x10
     ? assign_work+0x366/0x530
     worker_thread+0x93c/0xe70
     kthread+0x34b/0x460
     ? __pfx_worker_thread+0x10/0x10
     ? __pfx_kthread+0x10/0x10
     ret_from_fork+0x348/0x700
     ? __pfx_ret_from_fork+0x10/0x10
     ? native_load_tls+0xd/0x40
     ? __switch_to+0x916/0xc30
     ? __pfx_kthread+0x10/0x10
     ret_from_fork_asm+0x19/0x30
     </TASK>

 
 net/kcm/kcmsock.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/net/kcm/kcmsock.c b/net/kcm/kcmsock.c
index d469abcd989b..71af69d442f2 100644
--- a/net/kcm/kcmsock.c
+++ b/net/kcm/kcmsock.c
@@ -5,6 +5,7 @@
  * Copyright (c) 2016 Tom Herbert <[email protected]>
  */
 
+#include <linux/rcupdate.h>
 #include <linux/bpf.h>
 #include <linux/errno.h>
 #include <linux/errqueue.h>
@@ -391,7 +392,9 @@ static int kcm_parse_func_strparser(struct strparser *strp, struct sk_buff *skb)
 	struct bpf_prog *prog = psock->bpf_prog;
 	int res;
 
+	rcu_read_lock();
 	res = bpf_prog_run_pin_on_cpu(prog, skb);
+	rcu_read_unlock();
 	return res;
 }
 
-- 
2.55.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.