[RHEL8,COMMIT] connector: avoid RCU read-side critical section in cn_init_ve()

Submitted by Konstantin Khorenko on April 8, 2019, 3:43 p.m.

Details

Message ID 201904081543.x38FhMoX019949@finist_el8beta.work.ct
State New
Series "connector: avoid RCU read-side critical section in cn_init_ve()"
Headers show

Commit Message

Konstantin Khorenko April 8, 2019, 3:43 p.m.
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 5bae346f86aa4b40d00394f5cdfeda9cf5204c60
Author: Konstantin Khorenko <khorenko@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@virtuozzo.com>
---
 drivers/connector/connector.c | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

Patch hide | download patch | download mbox

diff --git a/drivers/connector/connector.c b/drivers/connector/connector.c
index 3d07b8bccc88..2eb6cb9b6d11 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(ve->ve_ns)->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(ve->ve_ns)->net_ns;
 	remove_proc_entry("connector", net->proc_net);
-	ve_net_unlock(ve);
 
 	cn_queue_free_dev(dev->cbdev);
 	netlink_kernel_release(dev->nls);