[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