[PATCH] netfilter: bpf: Don't hold rcu_read_lock during enable/disable
From: Daniel Xu
Date: Wed Jul 12 2023 - 21:17:35 EST
->enable()/->disable() takes a mutex which can sleep. You can't sleep
during RCU read side critical section.
Our refcnt on the module will protect us from ->enable()/->disable()
from going away while we call it.
Signed-off-by: Daniel Xu <dxu@xxxxxxxxx>
---
net/netfilter/nf_bpf_link.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/net/netfilter/nf_bpf_link.c b/net/netfilter/nf_bpf_link.c
index 77ffbf26ba3d..79704cc596aa 100644
--- a/net/netfilter/nf_bpf_link.c
+++ b/net/netfilter/nf_bpf_link.c
@@ -60,9 +60,12 @@ static int bpf_nf_enable_defrag(struct bpf_nf_link *link)
goto out_v4;
}
+ rcu_read_unlock();
err = v4_hook->enable(link->net);
if (err)
module_put(v4_hook->owner);
+
+ return err;
out_v4:
rcu_read_unlock();
return err;
@@ -92,9 +95,12 @@ static int bpf_nf_enable_defrag(struct bpf_nf_link *link)
goto out_v6;
}
+ rcu_read_unlock();
err = v6_hook->enable(link->net);
if (err)
module_put(v6_hook->owner);
+
+ return err;
out_v6:
rcu_read_unlock();
return err;
@@ -114,11 +120,11 @@ static void bpf_nf_disable_defrag(struct bpf_nf_link *link)
case NFPROTO_IPV4:
rcu_read_lock();
v4_hook = rcu_dereference(nf_defrag_v4_hook);
+ rcu_read_unlock();
if (v4_hook) {
v4_hook->disable(link->net);
module_put(v4_hook->owner);
}
- rcu_read_unlock();
break;
#endif
@@ -126,11 +132,11 @@ static void bpf_nf_disable_defrag(struct bpf_nf_link *link)
case NFPROTO_IPV6:
rcu_read_lock();
v6_hook = rcu_dereference(nf_defrag_v6_hook);
+ rcu_read_unlock();
if (v6_hook) {
v6_hook->disable(link->net);
module_put(v6_hook->owner);
}
- rcu_read_unlock();
break;
}
--
2.41.0
```
I'll send out a v5 tomorrow morning unless you feel like applying the
series + this patch today.
>
> Please make sure you have all kernel debug flags on in your testing.
>
Ack. Will make sure lockdep is on.
Thanks,
Daniel