Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

netfilter: load nf_log_syslog on enabling nf_conntrack_log_invalid

When no logger is registered, nf_conntrack_log_invalid fails to log invalid
packets, leaving users unaware of actual invalid traffic. Improve this by
loading nf_log_syslog, similar to how 'iptables -I FORWARD 1 -m conntrack
--ctstate INVALID -j LOG' triggers it.

Suggested-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Zi Li <zi.li@linux.dev>
Signed-off-by: Lance Yang <lance.yang@linux.dev>
Acked-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>

authored by

Lance Yang and committed by
Pablo Neira Ayuso
e89a6804 aa584016

+54 -1
+3
include/net/netfilter/nf_log.h
··· 59 59 int nf_log_register(u_int8_t pf, struct nf_logger *logger); 60 60 void nf_log_unregister(struct nf_logger *logger); 61 61 62 + /* Check if any logger is registered for a given protocol family. */ 63 + bool nf_log_is_registered(u_int8_t pf); 64 + 62 65 int nf_log_set(struct net *net, u_int8_t pf, const struct nf_logger *logger); 63 66 void nf_log_unset(struct net *net, const struct nf_logger *logger); 64 67
+25 -1
net/netfilter/nf_conntrack_standalone.c
··· 14 14 #include <linux/sysctl.h> 15 15 #endif 16 16 17 + #include <net/netfilter/nf_log.h> 17 18 #include <net/netfilter/nf_conntrack.h> 18 19 #include <net/netfilter/nf_conntrack_core.h> 19 20 #include <net/netfilter/nf_conntrack_l4proto.h> ··· 556 555 return ret; 557 556 } 558 557 558 + static int 559 + nf_conntrack_log_invalid_sysctl(const struct ctl_table *table, int write, 560 + void *buffer, size_t *lenp, loff_t *ppos) 561 + { 562 + int ret, i; 563 + 564 + ret = proc_dou8vec_minmax(table, write, buffer, lenp, ppos); 565 + if (ret < 0 || !write) 566 + return ret; 567 + 568 + if (*(u8 *)table->data == 0) 569 + return ret; 570 + 571 + /* Load nf_log_syslog only if no logger is currently registered */ 572 + for (i = 0; i < NFPROTO_NUMPROTO; i++) { 573 + if (nf_log_is_registered(i)) 574 + return ret; 575 + } 576 + request_module("%s", "nf_log_syslog"); 577 + 578 + return ret; 579 + } 580 + 559 581 static struct ctl_table_header *nf_ct_netfilter_header; 560 582 561 583 enum nf_ct_sysctl_index { ··· 675 651 .data = &init_net.ct.sysctl_log_invalid, 676 652 .maxlen = sizeof(u8), 677 653 .mode = 0644, 678 - .proc_handler = proc_dou8vec_minmax, 654 + .proc_handler = nf_conntrack_log_invalid_sysctl, 679 655 }, 680 656 [NF_SYSCTL_CT_EXPECT_MAX] = { 681 657 .procname = "nf_conntrack_expect_max",
+26
net/netfilter/nf_log.c
··· 125 125 } 126 126 EXPORT_SYMBOL(nf_log_unregister); 127 127 128 + /** 129 + * nf_log_is_registered - Check if any logger is registered for a given 130 + * protocol family. 131 + * 132 + * @pf: Protocol family 133 + * 134 + * Returns: true if at least one logger is active for @pf, false otherwise. 135 + */ 136 + bool nf_log_is_registered(u_int8_t pf) 137 + { 138 + int i; 139 + 140 + if (pf >= NFPROTO_NUMPROTO) { 141 + WARN_ON_ONCE(1); 142 + return false; 143 + } 144 + 145 + for (i = 0; i < NF_LOG_TYPE_MAX; i++) { 146 + if (rcu_access_pointer(loggers[pf][i])) 147 + return true; 148 + } 149 + 150 + return false; 151 + } 152 + EXPORT_SYMBOL(nf_log_is_registered); 153 + 128 154 int nf_log_bind_pf(struct net *net, u_int8_t pf, 129 155 const struct nf_logger *logger) 130 156 {