[Devel] [PATCH RHEL8 COMMIT] connector: avoid RCU read-side critical section in cn_init_ve()
Konstantin Khorenko
khorenko at virtuozzo.com
Mon Apr 8 19:05:50 MSK 2019
The commit is pushed to "branch-rh8-4.18.0-32.vz8.1.x" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh8-4.18.0-32.el8
------>
commit 6afaf250252ad08f1ae2a3c670cbb2f07ed28628
Author: Konstantin Khorenko <khorenko at virtuozzo.com>
Date: Mon Apr 8 15:04:12 2019 +0300
connector: avoid RCU read-side critical section in cn_init_ve()
First, netlink_kernel_create() cannot be called under rcu_read_lock()
(inside ve_net_lock()) because it sleeps.
Second, cn_init_ve() is a hook called on VE creation, VE creation is
done in a single thread, all hooks are called under a lock =>
ve cannot be destroyed during start hook execution => rcu_read_lock() is
not needed at all here.
Fixes: e7b9a7d5ce79 ("connector: per-ve init and fini helpers
introduced")
https://jira.sw.ru/browse/PSBM-93640
Signed-off-by: Konstantin Khorenko <khorenko at virtuozzo.com>
---
drivers/connector/connector.c | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)
diff --git a/drivers/connector/connector.c b/drivers/connector/connector.c
index 3d07b8bccc88..22d6d24e3a39 100644
--- a/drivers/connector/connector.c
+++ b/drivers/connector/connector.c
@@ -305,7 +305,11 @@ static int cn_init_ve(void *data)
dev = &ve->cn->cdev;
- net = ve_net_lock(ve);
+ /*
+ * This is a hook, hooks are called under a single lock, so ve_ns will
+ * not disappear, so rcu_read_lock()/unlock is not needed here.
+ */
+ net = rcu_dereference_check(ve->ve_ns, 1)->net_ns;
err = -EIO;
dev->nls = netlink_kernel_create(net, NETLINK_CONNECTOR, &cfg);
@@ -331,7 +335,6 @@ static int cn_init_ve(void *data)
goto remove_proc;
net_unlock:
- ve_net_unlock(ve);
return err;
remove_proc:
@@ -356,9 +359,13 @@ static void cn_fini_ve(void *data)
cn_proc_fini_ve(ve);
- net = ve_net_lock(ve);
+ /*
+ * This is a hook called on ve stop, ve->ve_ns will be destroyed
+ * later in the same thread, parallel ve stop is impossible,
+ * so rcu_read_lock()/unlock is not needed here.
+ */
+ net = rcu_dereference_check(ve->ve_ns, 1)->net_ns;
remove_proc_entry("connector", net->proc_net);
- ve_net_unlock(ve);
cn_queue_free_dev(dev->cbdev);
netlink_kernel_release(dev->nls);
More information about the Devel
mailing list