[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