Commit 8ac2bde2 authored by Marcelo Leitner's avatar Marcelo Leitner Committed by Pablo Neira Ayuso

netfilter: log: protect nf_log_register against double registering

Currently, despite the comment right before the function,
nf_log_register allows registering two loggers on with the same type and
end up overwriting the previous register.

Not a real issue today as current tree doesn't have two loggers for the
same type but it's better to get this protected.

Also make sure that all of its callers do error checking.
Signed-off-by: default avatarMarcelo Ricardo Leitner <mleitner@redhat.com>
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent 0c26ed1c
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
* it under the terms of the GNU General Public License version 2 as * it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation. * published by the Free Software Foundation.
*/ */
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h> #include <linux/module.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
...@@ -130,8 +131,17 @@ static int __init nf_log_arp_init(void) ...@@ -130,8 +131,17 @@ static int __init nf_log_arp_init(void)
if (ret < 0) if (ret < 0)
return ret; return ret;
nf_log_register(NFPROTO_ARP, &nf_arp_logger); ret = nf_log_register(NFPROTO_ARP, &nf_arp_logger);
if (ret < 0) {
pr_err("failed to register logger\n");
goto err1;
}
return 0; return 0;
err1:
unregister_pernet_subsys(&nf_log_arp_net_ops);
return ret;
} }
static void __exit nf_log_arp_exit(void) static void __exit nf_log_arp_exit(void)
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
* it under the terms of the GNU General Public License version 2 as * it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation. * published by the Free Software Foundation.
*/ */
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h> #include <linux/module.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
...@@ -366,8 +367,17 @@ static int __init nf_log_ipv4_init(void) ...@@ -366,8 +367,17 @@ static int __init nf_log_ipv4_init(void)
if (ret < 0) if (ret < 0)
return ret; return ret;
nf_log_register(NFPROTO_IPV4, &nf_ip_logger); ret = nf_log_register(NFPROTO_IPV4, &nf_ip_logger);
if (ret < 0) {
pr_err("failed to register logger\n");
goto err1;
}
return 0; return 0;
err1:
unregister_pernet_subsys(&nf_log_ipv4_net_ops);
return ret;
} }
static void __exit nf_log_ipv4_exit(void) static void __exit nf_log_ipv4_exit(void)
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
* it under the terms of the GNU General Public License version 2 as * it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation. * published by the Free Software Foundation.
*/ */
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h> #include <linux/module.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
...@@ -398,8 +399,17 @@ static int __init nf_log_ipv6_init(void) ...@@ -398,8 +399,17 @@ static int __init nf_log_ipv6_init(void)
if (ret < 0) if (ret < 0)
return ret; return ret;
nf_log_register(NFPROTO_IPV6, &nf_ip6_logger); ret = nf_log_register(NFPROTO_IPV6, &nf_ip6_logger);
if (ret < 0) {
pr_err("failed to register logger\n");
goto err1;
}
return 0; return 0;
err1:
unregister_pernet_subsys(&nf_log_ipv6_net_ops);
return ret;
} }
static void __exit nf_log_ipv6_exit(void) static void __exit nf_log_ipv6_exit(void)
......
...@@ -75,6 +75,7 @@ EXPORT_SYMBOL(nf_log_unset); ...@@ -75,6 +75,7 @@ EXPORT_SYMBOL(nf_log_unset);
int nf_log_register(u_int8_t pf, struct nf_logger *logger) int nf_log_register(u_int8_t pf, struct nf_logger *logger)
{ {
int i; int i;
int ret = 0;
if (pf >= ARRAY_SIZE(init_net.nf.nf_loggers)) if (pf >= ARRAY_SIZE(init_net.nf.nf_loggers))
return -EINVAL; return -EINVAL;
...@@ -82,16 +83,25 @@ int nf_log_register(u_int8_t pf, struct nf_logger *logger) ...@@ -82,16 +83,25 @@ int nf_log_register(u_int8_t pf, struct nf_logger *logger)
mutex_lock(&nf_log_mutex); mutex_lock(&nf_log_mutex);
if (pf == NFPROTO_UNSPEC) { if (pf == NFPROTO_UNSPEC) {
for (i = NFPROTO_UNSPEC; i < NFPROTO_NUMPROTO; i++) {
if (rcu_access_pointer(loggers[i][logger->type])) {
ret = -EEXIST;
goto unlock;
}
}
for (i = NFPROTO_UNSPEC; i < NFPROTO_NUMPROTO; i++) for (i = NFPROTO_UNSPEC; i < NFPROTO_NUMPROTO; i++)
rcu_assign_pointer(loggers[i][logger->type], logger); rcu_assign_pointer(loggers[i][logger->type], logger);
} else { } else {
/* register at end of list to honor first register win */ if (rcu_access_pointer(loggers[pf][logger->type])) {
ret = -EEXIST;
goto unlock;
}
rcu_assign_pointer(loggers[pf][logger->type], logger); rcu_assign_pointer(loggers[pf][logger->type], logger);
} }
unlock:
mutex_unlock(&nf_log_mutex); mutex_unlock(&nf_log_mutex);
return ret;
return 0;
} }
EXPORT_SYMBOL(nf_log_register); EXPORT_SYMBOL(nf_log_register);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment