Message ID | 39e23fdcc196851e3039ac7217c4a8447bb6bcef.1524585579.git.joseph.salisbury@canonical.com |
---|---|
State | New |
Headers | show |
Series | netfilter: allow logging from non-init namespaces | expand |
On 04/27/18 21:11, Joseph Salisbury wrote: > From: Michal Kubeček <mkubecek@suse.cz> > > BugLink: http://bugs.launchpad.net/bugs/1766573 > > 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> > (cherry picked from commit 2851940ffee313e0ff12540a8e11a8c54dea9c65) > Signed-off-by: Joseph Salisbury <joseph.salisbury@canonical.com> Acked-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com> > --- > Documentation/networking/netfilter-sysctl.txt | 10 ++++++++++ > include/net/netfilter/nf_log.h | 3 +++ > net/bridge/netfilter/ebt_log.c | 2 +- > net/ipv4/netfilter/nf_log_arp.c | 2 +- > net/ipv4/netfilter/nf_log_ipv4.c | 2 +- > net/ipv6/netfilter/nf_log_ipv6.c | 2 +- > net/netfilter/nf_log.c | 24 ++++++++++++++++++++++++ > 7 files changed, 41 insertions(+), 4 deletions(-) > create mode 100644 Documentation/networking/netfilter-sysctl.txt > > diff --git a/Documentation/networking/netfilter-sysctl.txt b/Documentation/networking/netfilter-sysctl.txt > new file mode 100644 > index 0000000..55791e5 > --- /dev/null > +++ b/Documentation/networking/netfilter-sysctl.txt > @@ -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. > diff --git a/include/net/netfilter/nf_log.h b/include/net/netfilter/nf_log.h > index 57639fc..8c4b018 100644 > --- a/include/net/netfilter/nf_log.h > +++ b/include/net/netfilter/nf_log.h > @@ -49,6 +49,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); > diff --git a/net/bridge/netfilter/ebt_log.c b/net/bridge/netfilter/ebt_log.c > index 0ad639a..0a2d0e3 100644 > --- a/net/bridge/netfilter/ebt_log.c > +++ b/net/bridge/netfilter/ebt_log.c > @@ -80,7 +80,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); > diff --git a/net/ipv4/netfilter/nf_log_arp.c b/net/ipv4/netfilter/nf_log_arp.c > index e7ad950..39e1348 100644 > --- a/net/ipv4/netfilter/nf_log_arp.c > +++ b/net/ipv4/netfilter/nf_log_arp.c > @@ -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(); > diff --git a/net/ipv4/netfilter/nf_log_ipv4.c b/net/ipv4/netfilter/nf_log_ipv4.c > index 076aadd..2b00831 100644 > --- a/net/ipv4/netfilter/nf_log_ipv4.c > +++ b/net/ipv4/netfilter/nf_log_ipv4.c > @@ -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(); > diff --git a/net/ipv6/netfilter/nf_log_ipv6.c b/net/ipv6/netfilter/nf_log_ipv6.c > index 8dd8696..0496048 100644 > --- a/net/ipv6/netfilter/nf_log_ipv6.c > +++ b/net/ipv6/netfilter/nf_log_ipv6.c > @@ -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(); > diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c > index 2c89f90..d84e11a 100644 > --- a/net/netfilter/nf_log.c > +++ b/net/netfilter/nf_log.c > @@ -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); > > @@ -392,6 +395,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) > @@ -460,6 +475,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++) > @@ -476,6 +495,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; > } > @@ -488,6 +510,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) >
On 27.04.2018 21:11, Joseph Salisbury wrote: > From: Michal Kubeček <mkubecek@suse.cz> > > BugLink: http://bugs.launchpad.net/bugs/1766573 > > 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> > (cherry picked from commit 2851940ffee313e0ff12540a8e11a8c54dea9c65) > Signed-off-by: Joseph Salisbury <joseph.salisbury@canonical.com> Acked-by: Stefan Bader <stefan.bader@canonical.com> > --- > Documentation/networking/netfilter-sysctl.txt | 10 ++++++++++ > include/net/netfilter/nf_log.h | 3 +++ > net/bridge/netfilter/ebt_log.c | 2 +- > net/ipv4/netfilter/nf_log_arp.c | 2 +- > net/ipv4/netfilter/nf_log_ipv4.c | 2 +- > net/ipv6/netfilter/nf_log_ipv6.c | 2 +- > net/netfilter/nf_log.c | 24 ++++++++++++++++++++++++ > 7 files changed, 41 insertions(+), 4 deletions(-) > create mode 100644 Documentation/networking/netfilter-sysctl.txt > > diff --git a/Documentation/networking/netfilter-sysctl.txt b/Documentation/networking/netfilter-sysctl.txt > new file mode 100644 > index 0000000..55791e5 > --- /dev/null > +++ b/Documentation/networking/netfilter-sysctl.txt > @@ -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. > diff --git a/include/net/netfilter/nf_log.h b/include/net/netfilter/nf_log.h > index 57639fc..8c4b018 100644 > --- a/include/net/netfilter/nf_log.h > +++ b/include/net/netfilter/nf_log.h > @@ -49,6 +49,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); > diff --git a/net/bridge/netfilter/ebt_log.c b/net/bridge/netfilter/ebt_log.c > index 0ad639a..0a2d0e3 100644 > --- a/net/bridge/netfilter/ebt_log.c > +++ b/net/bridge/netfilter/ebt_log.c > @@ -80,7 +80,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); > diff --git a/net/ipv4/netfilter/nf_log_arp.c b/net/ipv4/netfilter/nf_log_arp.c > index e7ad950..39e1348 100644 > --- a/net/ipv4/netfilter/nf_log_arp.c > +++ b/net/ipv4/netfilter/nf_log_arp.c > @@ -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(); > diff --git a/net/ipv4/netfilter/nf_log_ipv4.c b/net/ipv4/netfilter/nf_log_ipv4.c > index 076aadd..2b00831 100644 > --- a/net/ipv4/netfilter/nf_log_ipv4.c > +++ b/net/ipv4/netfilter/nf_log_ipv4.c > @@ -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(); > diff --git a/net/ipv6/netfilter/nf_log_ipv6.c b/net/ipv6/netfilter/nf_log_ipv6.c > index 8dd8696..0496048 100644 > --- a/net/ipv6/netfilter/nf_log_ipv6.c > +++ b/net/ipv6/netfilter/nf_log_ipv6.c > @@ -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(); > diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c > index 2c89f90..d84e11a 100644 > --- a/net/netfilter/nf_log.c > +++ b/net/netfilter/nf_log.c > @@ -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); > > @@ -392,6 +395,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) > @@ -460,6 +475,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++) > @@ -476,6 +495,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; > } > @@ -488,6 +510,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) >
diff --git a/Documentation/networking/netfilter-sysctl.txt b/Documentation/networking/netfilter-sysctl.txt new file mode 100644 index 0000000..55791e5 --- /dev/null +++ b/Documentation/networking/netfilter-sysctl.txt @@ -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. diff --git a/include/net/netfilter/nf_log.h b/include/net/netfilter/nf_log.h index 57639fc..8c4b018 100644 --- a/include/net/netfilter/nf_log.h +++ b/include/net/netfilter/nf_log.h @@ -49,6 +49,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); diff --git a/net/bridge/netfilter/ebt_log.c b/net/bridge/netfilter/ebt_log.c index 0ad639a..0a2d0e3 100644 --- a/net/bridge/netfilter/ebt_log.c +++ b/net/bridge/netfilter/ebt_log.c @@ -80,7 +80,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); diff --git a/net/ipv4/netfilter/nf_log_arp.c b/net/ipv4/netfilter/nf_log_arp.c index e7ad950..39e1348 100644 --- a/net/ipv4/netfilter/nf_log_arp.c +++ b/net/ipv4/netfilter/nf_log_arp.c @@ -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(); diff --git a/net/ipv4/netfilter/nf_log_ipv4.c b/net/ipv4/netfilter/nf_log_ipv4.c index 076aadd..2b00831 100644 --- a/net/ipv4/netfilter/nf_log_ipv4.c +++ b/net/ipv4/netfilter/nf_log_ipv4.c @@ -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(); diff --git a/net/ipv6/netfilter/nf_log_ipv6.c b/net/ipv6/netfilter/nf_log_ipv6.c index 8dd8696..0496048 100644 --- a/net/ipv6/netfilter/nf_log_ipv6.c +++ b/net/ipv6/netfilter/nf_log_ipv6.c @@ -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(); diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c index 2c89f90..d84e11a 100644 --- a/net/netfilter/nf_log.c +++ b/net/netfilter/nf_log.c @@ -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); @@ -392,6 +395,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) @@ -460,6 +475,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++) @@ -476,6 +495,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; } @@ -488,6 +510,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)