netfilter: allow logging from non-init namespaces
authorMichal Kubeček <mkubecek@suse.cz>
Tue, 31 Jan 2017 09:30:06 +0000 (10:30 +0100)
committerPablo Neira Ayuso <pablo@netfilter.org>
Thu, 2 Feb 2017 13:31:58 +0000 (14:31 +0100)
Commit 69b34fb996b2 ("netfilter: xt_LOG: add net namespace support for
xt_LOG") disabled logging packets using the LOG target from non-init
namespaces. The motivation was to prevent containers from flooding
kernel log of the host. The plan was to keep it that way until syslog
namespace implementation allows containers to log in a safe way.

However, the work on syslog namespace seems to have hit a dead end
somewhere in 2013 and there are users who want to use xt_LOG in all
network namespaces. This patch allows to do so by setting

  /proc/sys/net/netfilter/nf_log_all_netns

to a nonzero value. This sysctl is only accessible from init_net so that
one cannot switch the behaviour from inside a container.

Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Documentation/networking/netfilter-sysctl.txt [new file with mode: 0644]
include/net/netfilter/nf_log.h
net/bridge/netfilter/ebt_log.c
net/ipv4/netfilter/nf_log_arp.c
net/ipv4/netfilter/nf_log_ipv4.c
net/ipv6/netfilter/nf_log_ipv6.c
net/netfilter/nf_log.c

diff --git a/Documentation/networking/netfilter-sysctl.txt b/Documentation/networking/netfilter-sysctl.txt
new file mode 100644 (file)
index 0000000..55791e5
--- /dev/null
@@ -0,0 +1,10 @@
+/proc/sys/net/netfilter/* Variables:
+
+nf_log_all_netns - BOOLEAN
+       0 - disabled (default)
+       not 0 - enabled
+
+       By default, only init_net namespace can log packets into kernel log
+       with LOG target; this aims to prevent containers from flooding host
+       kernel log. If enabled, this target also works in other network
+       namespaces. This variable is only accessible from init_net.
index 450f87f95415824586a1dae0bbfdcef467e6dc7a..42e0696f38d80f0b8b03bc18cf7413aa1893a6de 100644 (file)
@@ -51,6 +51,9 @@ struct nf_logger {
        struct module           *me;
 };
 
+/* sysctl_nf_log_all_netns - allow LOG target in all network namespaces */
+extern int sysctl_nf_log_all_netns;
+
 /* Function to register/unregister log function. */
 int nf_log_register(u_int8_t pf, struct nf_logger *logger);
 void nf_log_unregister(struct nf_logger *logger);
index e88bd4827ac1add767973298760895d851aa4b10..98b9c8e8615ebc6e2ddefd1885a01af3ef58781b 100644 (file)
@@ -78,7 +78,7 @@ ebt_log_packet(struct net *net, u_int8_t pf, unsigned int hooknum,
        unsigned int bitmask;
 
        /* FIXME: Disabled from containers until syslog ns is supported */
-       if (!net_eq(net, &init_net))
+       if (!net_eq(net, &init_net) && !sysctl_nf_log_all_netns)
                return;
 
        spin_lock_bh(&ebt_log_lock);
index b24795e2ee6d486c871149811b7916145345f6ea..f6f713376e6e429610b070ba65f685cbfd6ae6ae 100644 (file)
@@ -87,7 +87,7 @@ static void nf_log_arp_packet(struct net *net, u_int8_t pf,
        struct nf_log_buf *m;
 
        /* FIXME: Disabled from containers until syslog ns is supported */
-       if (!net_eq(net, &init_net))
+       if (!net_eq(net, &init_net) && !sysctl_nf_log_all_netns)
                return;
 
        m = nf_log_buf_open();
index 856648966f4c209b5d01b608afb1b25a069b8b54..c83a9963269bf689d7c4285c89ef1a4228bc739b 100644 (file)
@@ -319,7 +319,7 @@ static void nf_log_ip_packet(struct net *net, u_int8_t pf,
        struct nf_log_buf *m;
 
        /* FIXME: Disabled from containers until syslog ns is supported */
-       if (!net_eq(net, &init_net))
+       if (!net_eq(net, &init_net) && !sysctl_nf_log_all_netns)
                return;
 
        m = nf_log_buf_open();
index 57d86066a13bc567d0526da14b13173657acac9c..055c51b80f5dd1fa37873a665bbe3810d3f17c3e 100644 (file)
@@ -351,7 +351,7 @@ static void nf_log_ip6_packet(struct net *net, u_int8_t pf,
        struct nf_log_buf *m;
 
        /* FIXME: Disabled from containers until syslog ns is supported */
-       if (!net_eq(net, &init_net))
+       if (!net_eq(net, &init_net) && !sysctl_nf_log_all_netns)
                return;
 
        m = nf_log_buf_open();
index 3dca90dc24ad392a6be6076e4ddbc345a1959ac0..0a034f52b9122cf5004d52e420a138fa5dba1177 100644 (file)
@@ -16,6 +16,9 @@
 #define NF_LOG_PREFIXLEN               128
 #define NFLOGGER_NAME_LEN              64
 
+int sysctl_nf_log_all_netns __read_mostly;
+EXPORT_SYMBOL(sysctl_nf_log_all_netns);
+
 static struct nf_logger __rcu *loggers[NFPROTO_NUMPROTO][NF_LOG_TYPE_MAX] __read_mostly;
 static DEFINE_MUTEX(nf_log_mutex);
 
@@ -414,6 +417,18 @@ static const struct file_operations nflog_file_ops = {
 #ifdef CONFIG_SYSCTL
 static char nf_log_sysctl_fnames[NFPROTO_NUMPROTO-NFPROTO_UNSPEC][3];
 static struct ctl_table nf_log_sysctl_table[NFPROTO_NUMPROTO+1];
+static struct ctl_table_header *nf_log_sysctl_fhdr;
+
+static struct ctl_table nf_log_sysctl_ftable[] = {
+       {
+               .procname       = "nf_log_all_netns",
+               .data           = &sysctl_nf_log_all_netns,
+               .maxlen         = sizeof(sysctl_nf_log_all_netns),
+               .mode           = 0644,
+               .proc_handler   = proc_dointvec,
+       },
+       { }
+};
 
 static int nf_log_proc_dostring(struct ctl_table *table, int write,
                         void __user *buffer, size_t *lenp, loff_t *ppos)
@@ -483,6 +498,10 @@ static int netfilter_log_sysctl_init(struct net *net)
                        nf_log_sysctl_table[i].extra1 =
                                (void *)(unsigned long) i;
                }
+               nf_log_sysctl_fhdr = register_net_sysctl(net, "net/netfilter",
+                                                        nf_log_sysctl_ftable);
+               if (!nf_log_sysctl_fhdr)
+                       goto err_freg;
        }
 
        for (i = NFPROTO_UNSPEC; i < NFPROTO_NUMPROTO; i++)
@@ -499,6 +518,9 @@ static int netfilter_log_sysctl_init(struct net *net)
 err_reg:
        if (!net_eq(net, &init_net))
                kfree(table);
+       else
+               unregister_net_sysctl_table(nf_log_sysctl_fhdr);
+err_freg:
 err_alloc:
        return -ENOMEM;
 }
@@ -511,6 +533,8 @@ static void netfilter_log_sysctl_exit(struct net *net)
        unregister_net_sysctl_table(net->nf.nf_log_dir_header);
        if (!net_eq(net, &init_net))
                kfree(table);
+       else
+               unregister_net_sysctl_table(nf_log_sysctl_fhdr);
 }
 #else
 static int netfilter_log_sysctl_init(struct net *net)