]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
netfilter: load nf_log_syslog on enabling nf_conntrack_log_invalid
authorLance Yang <lance.yang@linux.dev>
Mon, 26 May 2025 08:59:02 +0000 (16:59 +0800)
committerPablo Neira Ayuso <pablo@netfilter.org>
Fri, 25 Jul 2025 16:35:41 +0000 (18:35 +0200)
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>
include/net/netfilter/nf_log.h
net/netfilter/nf_conntrack_standalone.c
net/netfilter/nf_log.c

index e55eedc84ed7229af95b2b7903446666148cf244..00506792a06d9860611dd4288b972da3ff1d5391 100644 (file)
@@ -59,6 +59,9 @@ extern int sysctl_nf_log_all_netns;
 int nf_log_register(u_int8_t pf, struct nf_logger *logger);
 void nf_log_unregister(struct nf_logger *logger);
 
+/* Check if any logger is registered for a given protocol family. */
+bool nf_log_is_registered(u_int8_t pf);
+
 int nf_log_set(struct net *net, u_int8_t pf, const struct nf_logger *logger);
 void nf_log_unset(struct net *net, const struct nf_logger *logger);
 
index 829f60496008c8c235b26462091b31de15af3acf..9b8b10a852339ff17045436408368e01375b4ab4 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/sysctl.h>
 #endif
 
+#include <net/netfilter/nf_log.h>
 #include <net/netfilter/nf_conntrack.h>
 #include <net/netfilter/nf_conntrack_core.h>
 #include <net/netfilter/nf_conntrack_l4proto.h>
@@ -555,6 +556,29 @@ nf_conntrack_hash_sysctl(const struct ctl_table *table, int write,
        return ret;
 }
 
+static int
+nf_conntrack_log_invalid_sysctl(const struct ctl_table *table, int write,
+                               void *buffer, size_t *lenp, loff_t *ppos)
+{
+       int ret, i;
+
+       ret = proc_dou8vec_minmax(table, write, buffer, lenp, ppos);
+       if (ret < 0 || !write)
+               return ret;
+
+       if (*(u8 *)table->data == 0)
+               return ret;
+
+       /* Load nf_log_syslog only if no logger is currently registered */
+       for (i = 0; i < NFPROTO_NUMPROTO; i++) {
+               if (nf_log_is_registered(i))
+                       return ret;
+       }
+       request_module("%s", "nf_log_syslog");
+
+       return ret;
+}
+
 static struct ctl_table_header *nf_ct_netfilter_header;
 
 enum nf_ct_sysctl_index {
@@ -651,7 +675,7 @@ static struct ctl_table nf_ct_sysctl_table[] = {
                .data           = &init_net.ct.sysctl_log_invalid,
                .maxlen         = sizeof(u8),
                .mode           = 0644,
-               .proc_handler   = proc_dou8vec_minmax,
+               .proc_handler   = nf_conntrack_log_invalid_sysctl,
        },
        [NF_SYSCTL_CT_EXPECT_MAX] = {
                .procname       = "nf_conntrack_expect_max",
index 6dd0de33eebd8a65c8b3512743352a8692d727d7..74cef8bf554c55b52426ccbef0a8f0d22fae0b9d 100644 (file)
@@ -125,6 +125,32 @@ void nf_log_unregister(struct nf_logger *logger)
 }
 EXPORT_SYMBOL(nf_log_unregister);
 
+/**
+ * nf_log_is_registered - Check if any logger is registered for a given
+ * protocol family.
+ *
+ * @pf: Protocol family
+ *
+ * Returns: true if at least one logger is active for @pf, false otherwise.
+ */
+bool nf_log_is_registered(u_int8_t pf)
+{
+       int i;
+
+       if (pf >= NFPROTO_NUMPROTO) {
+               WARN_ON_ONCE(1);
+               return false;
+       }
+
+       for (i = 0; i < NF_LOG_TYPE_MAX; i++) {
+               if (rcu_access_pointer(loggers[pf][i]))
+                       return true;
+       }
+
+       return false;
+}
+EXPORT_SYMBOL(nf_log_is_registered);
+
 int nf_log_bind_pf(struct net *net, u_int8_t pf,
                   const struct nf_logger *logger)
 {