summaryrefslogtreecommitdiffstats
path: root/debian/patches-rt/0059-bpf-Remove-in_atomic-from-bpf_link_put.patch
diff options
context:
space:
mode:
Diffstat (limited to 'debian/patches-rt/0059-bpf-Remove-in_atomic-from-bpf_link_put.patch')
-rw-r--r--debian/patches-rt/0059-bpf-Remove-in_atomic-from-bpf_link_put.patch120
1 files changed, 120 insertions, 0 deletions
diff --git a/debian/patches-rt/0059-bpf-Remove-in_atomic-from-bpf_link_put.patch b/debian/patches-rt/0059-bpf-Remove-in_atomic-from-bpf_link_put.patch
new file mode 100644
index 000000000..8abf764af
--- /dev/null
+++ b/debian/patches-rt/0059-bpf-Remove-in_atomic-from-bpf_link_put.patch
@@ -0,0 +1,120 @@
+From 05999b640eb04be872e5491a040701fcddc73349 Mon Sep 17 00:00:00 2001
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Wed, 14 Jun 2023 10:34:30 +0200
+Subject: [PATCH 59/62] bpf: Remove in_atomic() from bpf_link_put().
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.1/older/patches-6.1.69-rt21.tar.xz
+
+bpf_free_inode() is invoked as a RCU callback. Usually RCU callbacks are
+invoked within softirq context. By setting rcutree.use_softirq=0 boot
+option the RCU callbacks will be invoked in a per-CPU kthread with
+bottom halves disabled which implies a RCU read section.
+
+On PREEMPT_RT the context remains fully preemptible. The RCU read
+section however does not allow schedule() invocation. The latter happens
+in mutex_lock() performed by bpf_trampoline_unlink_prog() originated
+from bpf_link_put().
+
+It was pointed out that the bpf_link_put() invocation should not be
+delayed if originated from close(). It was also pointed out that other
+invocations from within a syscall should also avoid the workqueue.
+Everyone else should use workqueue by default to remain safe in the
+future (while auditing the code, every caller was preemptible except for
+the RCU case).
+
+Let bpf_link_put() use the worker unconditionally. Add
+bpf_link_put_direct() which will directly free the resources and is used
+by close() and from within __sys_bpf().
+
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
+Link: https://lore.kernel.org/bpf/20230614083430.oENawF8f@linutronix.de
+(cherry picked from commit ab5d47bd41b1db82c295b0e751e2b822b43a4b5a)
+Signed-off-by: Clark Williams <clark.williams@gmail.com>
+---
+ kernel/bpf/syscall.c | 29 ++++++++++++++++-------------
+ 1 file changed, 16 insertions(+), 13 deletions(-)
+
+diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
+index c0915e2424f1..f8ba6e0a5c08 100644
+--- a/kernel/bpf/syscall.c
++++ b/kernel/bpf/syscall.c
+@@ -2732,28 +2732,31 @@ static void bpf_link_put_deferred(struct work_struct *work)
+ bpf_link_free(link);
+ }
+
+-/* bpf_link_put can be called from atomic context, but ensures that resources
+- * are freed from process context
++/* bpf_link_put might be called from atomic context. It needs to be called
++ * from sleepable context in order to acquire sleeping locks during the process.
+ */
+ void bpf_link_put(struct bpf_link *link)
+ {
+ if (!atomic64_dec_and_test(&link->refcnt))
+ return;
+
+- if (in_atomic()) {
+- INIT_WORK(&link->work, bpf_link_put_deferred);
+- schedule_work(&link->work);
+- } else {
+- bpf_link_free(link);
+- }
++ INIT_WORK(&link->work, bpf_link_put_deferred);
++ schedule_work(&link->work);
+ }
+ EXPORT_SYMBOL(bpf_link_put);
+
++static void bpf_link_put_direct(struct bpf_link *link)
++{
++ if (!atomic64_dec_and_test(&link->refcnt))
++ return;
++ bpf_link_free(link);
++}
++
+ static int bpf_link_release(struct inode *inode, struct file *filp)
+ {
+ struct bpf_link *link = filp->private_data;
+
+- bpf_link_put(link);
++ bpf_link_put_direct(link);
+ return 0;
+ }
+
+@@ -4674,7 +4677,7 @@ static int link_update(union bpf_attr *attr)
+ if (ret)
+ bpf_prog_put(new_prog);
+ out_put_link:
+- bpf_link_put(link);
++ bpf_link_put_direct(link);
+ return ret;
+ }
+
+@@ -4697,7 +4700,7 @@ static int link_detach(union bpf_attr *attr)
+ else
+ ret = -EOPNOTSUPP;
+
+- bpf_link_put(link);
++ bpf_link_put_direct(link);
+ return ret;
+ }
+
+@@ -4767,7 +4770,7 @@ static int bpf_link_get_fd_by_id(const union bpf_attr *attr)
+
+ fd = bpf_link_new_fd(link);
+ if (fd < 0)
+- bpf_link_put(link);
++ bpf_link_put_direct(link);
+
+ return fd;
+ }
+@@ -4844,7 +4847,7 @@ static int bpf_iter_create(union bpf_attr *attr)
+ return PTR_ERR(link);
+
+ err = bpf_iter_new_fd(link);
+- bpf_link_put(link);
++ bpf_link_put_direct(link);
+
+ return err;
+ }
+--
+2.43.0
+