[Devel] [PATCH RHEL7 COMMIT] ms/netfilter: nfnetlink_{log, queue}: Register pernet in first place

Konstantin Khorenko khorenko at virtuozzo.com
Fri Apr 8 00:24:48 PDT 2016


The commit is pushed to "branch-rh7-3.10.0-327.10.1.vz7.12.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-327.10.1.vz7.12.5
------>
commit f13e8480bfcfc7c590bc20dec5e5a80e6e3fa41f
Author: Francesco Ruggeri <fruggeri at aristanetworks.com>
Date:   Fri Apr 8 11:24:47 2016 +0400

    ms/netfilter: nfnetlink_{log,queue}: Register pernet in first place
    
    nfnetlink_{log,queue}_init() register the netlink callback nf*_rcv_nl_event
    before registering the pernet_subsys, but the callback relies on data
    structures allocated by pernet init functions.
    
    When nfnetlink_{log,queue} is loaded, if a netlink message is received after
    the netlink callback is registered but before the pernet_subsys is registered,
    the kernel will panic in the sequence
    
    nfulnl_rcv_nl_event
      nfnl_log_pernet
        net_generic
          BUG_ON(id == 0)  where id is nfnl_log_net_id.
    
    The panic can be easily reproduced in 4.0.3 by:
    
    while true ;do modprobe nfnetlink_log ; rmmod nfnetlink_log ; done &
    while true ;do ip netns add dummy ; ip netns del dummy ; done &
    
    This patch moves register_pernet_subsys to earlier in nfnetlink_log_init.
    
    Notice that the BUG_ON hit in 4.0.3 was recently removed in 2591ffd308
    ["netns: remove BUG_ONs from net_generic()"].
    
    Signed-off-by: Francesco Ruggeri <fruggeri at arista.com>
    Signed-off-by: Pablo Neira Ayuso <pablo at netfilter.org>
    
    https://jira.sw.ru/browse/PSBM-45783
    
    (cherry picked from commit 3bfe049807c240344b407e3cfb74544927359817
    ("netfilter: nfnetlink_{log,queue}: Register pernet in first place"))
    Signed-off-by: Andrey Ryabinin <aryabinin at virtuozzo.com>
---
 net/netfilter/nfnetlink_log.c        | 20 ++++++++++----------
 net/netfilter/nfnetlink_queue_core.c | 18 +++++++++---------
 2 files changed, 19 insertions(+), 19 deletions(-)

diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
index 096d94c..3360d00 100644
--- a/net/netfilter/nfnetlink_log.c
+++ b/net/netfilter/nfnetlink_log.c
@@ -1062,7 +1062,13 @@ static struct pernet_operations nfnl_log_net_ops = {
 
 static int __init nfnetlink_log_init(void)
 {
-	int status = -ENOMEM;
+	int status;
+
+	status = register_pernet_subsys(&nfnl_log_net_ops);
+	if (status < 0) {
+		pr_err("log: failed to register pernet ops\n");
+		goto out;
+	}
 
 	netlink_register_notifier(&nfulnl_rtnl_notifier);
 	status = nfnetlink_subsys_register(&nfulnl_subsys);
@@ -1076,29 +1082,23 @@ static int __init nfnetlink_log_init(void)
 		pr_err("log: failed to register logger\n");
 		goto cleanup_subsys;
 	}
-
-	status = register_pernet_subsys(&nfnl_log_net_ops);
-	if (status < 0) {
-		pr_err("log: failed to register pernet ops\n");
-		goto cleanup_logger;
-	}
 	return status;
 
-cleanup_logger:
-	nf_log_unregister(&nfulnl_logger);
 cleanup_subsys:
 	nfnetlink_subsys_unregister(&nfulnl_subsys);
 cleanup_netlink_notifier:
 	netlink_unregister_notifier(&nfulnl_rtnl_notifier);
+	unregister_pernet_subsys(&nfnl_log_net_ops);
+out:
 	return status;
 }
 
 static void __exit nfnetlink_log_fini(void)
 {
-	unregister_pernet_subsys(&nfnl_log_net_ops);
 	nf_log_unregister(&nfulnl_logger);
 	nfnetlink_subsys_unregister(&nfulnl_subsys);
 	netlink_unregister_notifier(&nfulnl_rtnl_notifier);
+	unregister_pernet_subsys(&nfnl_log_net_ops);
 }
 
 MODULE_DESCRIPTION("netfilter userspace logging");
diff --git a/net/netfilter/nfnetlink_queue_core.c b/net/netfilter/nfnetlink_queue_core.c
index b5cda59..d940d18 100644
--- a/net/netfilter/nfnetlink_queue_core.c
+++ b/net/netfilter/nfnetlink_queue_core.c
@@ -1270,7 +1270,13 @@ static struct pernet_operations nfnl_queue_net_ops = {
 
 static int __init nfnetlink_queue_init(void)
 {
-	int status = -ENOMEM;
+	int status;
+
+	status = register_pernet_subsys(&nfnl_queue_net_ops);
+	if (status < 0) {
+		pr_err("nf_queue: failed to register pernet ops\n");
+		goto out;
+	}
 
 	netlink_register_notifier(&nfqnl_rtnl_notifier);
 	status = nfnetlink_subsys_register(&nfqnl_subsys);
@@ -1279,19 +1285,13 @@ static int __init nfnetlink_queue_init(void)
 		goto cleanup_netlink_notifier;
 	}
 
-	status = register_pernet_subsys(&nfnl_queue_net_ops);
-	if (status < 0) {
-		pr_err("nf_queue: failed to register pernet ops\n");
-		goto cleanup_subsys;
-	}
 	register_netdevice_notifier(&nfqnl_dev_notifier);
 	nf_register_queue_handler(&nfqh);
 	return status;
 
-cleanup_subsys:
-	nfnetlink_subsys_unregister(&nfqnl_subsys);
 cleanup_netlink_notifier:
 	netlink_unregister_notifier(&nfqnl_rtnl_notifier);
+out:
 	return status;
 }
 
@@ -1299,9 +1299,9 @@ static void __exit nfnetlink_queue_fini(void)
 {
 	nf_unregister_queue_handler();
 	unregister_netdevice_notifier(&nfqnl_dev_notifier);
-	unregister_pernet_subsys(&nfnl_queue_net_ops);
 	nfnetlink_subsys_unregister(&nfqnl_subsys);
 	netlink_unregister_notifier(&nfqnl_rtnl_notifier);
+	unregister_pernet_subsys(&nfnl_queue_net_ops);
 
 	rcu_barrier(); /* Wait for completion of call_rcu()'s */
 }


More information about the Devel mailing list