Blob Blame History Raw
From d18e2e7b13ce623da968e896c04813f9d3b8efbf Mon Sep 17 00:00:00 2001
From: Pablo Neira Ayuso <pablo@netfilter.org>
Date: Tue, 8 Mar 2022 23:05:39 +0100
Subject: [PATCH] nfct: remove lazy binding

Since cd5135377ac4 ("conntrackd: cthelper: Set up userspace helpers when
daemon starts"), userspace conntrack helpers do not depend on a previous
invocation of nfct to set up the userspace helpers.

Move helper definitions to nfct-extensions/helper.c since existing
deployments might still invoke nfct, even if not required anymore.

This patch was motivated by the removal of the lazy binding.

Phil Sutter says:

"For security purposes, distributions might want to pass -Wl,-z,now
linker flags to all builds, thereby disabling lazy binding globally.

In the past, nfct relied upon lazy binding: It uses the helper objects'
parsing functions without but doesn't provide all symbols the objects
use."

Acked-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
(cherry picked from commit dc454a657f57a5cf143fddc5c1dd87a510c1790a)
(cherry picked from commit 4527e4fec140ff5480d4fbfb2916001d64a0f72a)
---
 configure.ac                 |   5 +-
 include/Makefile.am          |   2 +-
 include/helper.h             |   1 +
 include/helpers/Makefile.am  |   1 +
 include/helpers/ftp.h        |  14 +++
 include/helpers/rpc.h        |  15 +++
 include/helpers/sane.h       |  13 +++
 include/helpers/tns.h        |   9 ++
 src/Makefile.am              |   2 -
 src/helpers.c                |   3 +-
 src/helpers/Makefile.am      |   2 +-
 src/helpers/ftp.c            |  12 +--
 src/helpers/rpc.c            |  13 +--
 src/helpers/sane.c           |  10 +-
 src/helpers/tns.c            |   7 +-
 src/nfct-extensions/helper.c | 184 ++++++++++++++++++++++++++++++++++-
 16 files changed, 246 insertions(+), 47 deletions(-)
 create mode 100644 include/helpers/Makefile.am
 create mode 100644 include/helpers/ftp.h
 create mode 100644 include/helpers/rpc.h
 create mode 100644 include/helpers/sane.h
 create mode 100644 include/helpers/tns.h

diff --git a/configure.ac b/configure.ac
index 5388054e64a58..1e444508fdc3c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -78,15 +78,12 @@ AC_CHECK_HEADERS([linux/capability.h],, [AC_MSG_ERROR([Cannot find linux/capabib
 AC_CHECK_HEADERS(arpa/inet.h)
 AC_CHECK_FUNCS(inet_pton)
 
-# Let nfct use dlopen() on helper libraries without resolving all symbols.
-AX_CHECK_LINK_FLAG([-Wl,-z,lazy], [AC_SUBST([LAZY_LDFLAGS], [-Wl,-z,lazy])])
-
 if test ! -z "$libdir"; then
 	MODULE_DIR="\\\"$libdir/conntrack-tools/\\\""
 	CFLAGS="$CFLAGS -DCONNTRACKD_LIB_DIR=$MODULE_DIR"
 fi
 
-AC_CONFIG_FILES([Makefile src/Makefile include/Makefile include/linux/Makefile include/linux/netfilter/Makefile extensions/Makefile src/helpers/Makefile])
+AC_CONFIG_FILES([Makefile src/Makefile include/Makefile include/helpers/Makefile include/linux/Makefile include/linux/netfilter/Makefile extensions/Makefile src/helpers/Makefile])
 AC_OUTPUT
 
 echo "
diff --git a/include/Makefile.am b/include/Makefile.am
index 352054e9135bd..4741b50228eb9 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -1,4 +1,4 @@
-SUBDIRS = linux
+SUBDIRS = linux helpers
 
 noinst_HEADERS = alarm.h jhash.h cache.h linux_list.h linux_rbtree.h \
 		 sync.h conntrackd.h local.h udp.h tcp.h \
diff --git a/include/helper.h b/include/helper.h
index d15c1c62c0534..7353dfa9b2073 100644
--- a/include/helper.h
+++ b/include/helper.h
@@ -56,6 +56,7 @@ extern int in4_pton(const char *src, int srclen, uint8_t *dst, int delim, const
 extern int in6_pton(const char *src, int srclen, uint8_t *dst, int delim, const char **end);
 
 extern void helper_register(struct ctd_helper *helper);
+struct ctd_helper *__helper_find(const char *helper_name, uint8_t l4proto);
 struct ctd_helper *helper_find(const char *libdir_path, const char *name, uint8_t l4proto, int flags);
 
 #define min_t(type, x, y) ({			\
diff --git a/include/helpers/Makefile.am b/include/helpers/Makefile.am
new file mode 100644
index 0000000000000..99a4257d2d061
--- /dev/null
+++ b/include/helpers/Makefile.am
@@ -0,0 +1 @@
+noinst_HEADERS = ftp.h  rpc.h  sane.h  tns.h
diff --git a/include/helpers/ftp.h b/include/helpers/ftp.h
new file mode 100644
index 0000000000000..50e2d0c97946d
--- /dev/null
+++ b/include/helpers/ftp.h
@@ -0,0 +1,14 @@
+#ifndef _CTD_FTP_H
+#define _CTD_FTP_H
+
+#define NUM_SEQ_TO_REMEMBER 2
+
+/* This structure exists only once per master */
+struct ftp_info {
+	/* Valid seq positions for cmd matching after newline */
+	uint32_t seq_aft_nl[MYCT_DIR_MAX][NUM_SEQ_TO_REMEMBER];
+	/* 0 means seq_match_aft_nl not set */
+	int seq_aft_nl_num[MYCT_DIR_MAX];
+};
+
+#endif
diff --git a/include/helpers/rpc.h b/include/helpers/rpc.h
new file mode 100644
index 0000000000000..b0b8d176fb542
--- /dev/null
+++ b/include/helpers/rpc.h
@@ -0,0 +1,15 @@
+#ifndef _CTD_RPC_H
+#define _CTD_RPC_H
+
+struct rpc_info {
+	/* XID */
+	uint32_t xid;
+	/* program */
+	uint32_t pm_prog;
+	/* program version */
+	uint32_t pm_vers;
+	/* transport protocol: TCP|UDP */
+	uint32_t pm_prot;
+};
+
+#endif
diff --git a/include/helpers/sane.h b/include/helpers/sane.h
new file mode 100644
index 0000000000000..1e70ff636d60d
--- /dev/null
+++ b/include/helpers/sane.h
@@ -0,0 +1,13 @@
+#ifndef _CTD_SANE_H
+#define _CTD_SANE_H
+
+enum sane_state {
+	SANE_STATE_NORMAL,
+	SANE_STATE_START_REQUESTED,
+};
+
+struct nf_ct_sane_master {
+	enum sane_state state;
+};
+
+#endif
diff --git a/include/helpers/tns.h b/include/helpers/tns.h
new file mode 100644
index 0000000000000..60dcf253657fc
--- /dev/null
+++ b/include/helpers/tns.h
@@ -0,0 +1,9 @@
+#ifndef _CTD_TNS_H
+#define _CTD_TNS_H
+
+struct tns_info {
+	/* Scan next DATA|REDIRECT packet */
+	bool parse;
+};
+
+#endif
diff --git a/src/Makefile.am b/src/Makefile.am
index a5b918d951327..9e47d2278a0d5 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -35,8 +35,6 @@ if HAVE_CTHELPER
 nfct_LDADD += ${LIBNETFILTER_CTHELPER_LIBS}
 endif
 
-nfct_LDFLAGS = -export-dynamic ${LAZY_LDFLAGS}
-
 conntrackd_SOURCES = alarm.c main.c run.c hash.c queue.c queue_tx.c rbtree.c \
 		    local.c log.c mcast.c udp.c netlink.c vector.c \
 		    filter.c fds.c event.c process.c origin.c date.c \
diff --git a/src/helpers.c b/src/helpers.c
index 3e4e6c8553b8a..8ca78dc113fb7 100644
--- a/src/helpers.c
+++ b/src/helpers.c
@@ -26,8 +26,7 @@ void helper_register(struct ctd_helper *helper)
 	list_add(&helper->head, &helper_list);
 }
 
-static struct ctd_helper *
-__helper_find(const char *helper_name, uint8_t l4proto)
+struct ctd_helper *__helper_find(const char *helper_name, uint8_t l4proto)
 {
 	struct ctd_helper *cur, *helper = NULL;
 
diff --git a/src/helpers/Makefile.am b/src/helpers/Makefile.am
index d851d313e6fea..8f9c4ec556b66 100644
--- a/src/helpers/Makefile.am
+++ b/src/helpers/Makefile.am
@@ -10,7 +10,7 @@ pkglib_LTLIBRARIES = ct_helper_amanda.la \
 		     ct_helper_sane.la	\
 		     ct_helper_ssdp.la
 
-HELPER_LDFLAGS = -avoid-version -module $(LIBNETFILTER_CONNTRACK_LIBS) $(LAZY_LDFLAGS)
+HELPER_LDFLAGS = -avoid-version -module $(LIBNETFILTER_CONNTRACK_LIBS)
 HELPER_CFLAGS = $(AM_CFLAGS) $(LIBNETFILTER_CONNTRACK_CFLAGS)
 
 ct_helper_amanda_la_SOURCES = amanda.c
diff --git a/src/helpers/ftp.c b/src/helpers/ftp.c
index c3aa28485b0f3..bd3f11788cc24 100644
--- a/src/helpers/ftp.c
+++ b/src/helpers/ftp.c
@@ -35,17 +35,9 @@
 #include <libnetfilter_queue/pktbuff.h>
 #include <linux/netfilter.h>
 
-static bool loose; /* XXX: export this as config option. */
-
-#define NUM_SEQ_TO_REMEMBER 2
+#include "helpers/ftp.h"
 
-/* This structure exists only once per master */
-struct ftp_info {
-	/* Valid seq positions for cmd matching after newline */
-	uint32_t seq_aft_nl[MYCT_DIR_MAX][NUM_SEQ_TO_REMEMBER];
-	/* 0 means seq_match_aft_nl not set */
-	int seq_aft_nl_num[MYCT_DIR_MAX];
-};
+static bool loose; /* XXX: export this as config option. */
 
 enum nf_ct_ftp_type {
 	/* PORT command from client */
diff --git a/src/helpers/rpc.c b/src/helpers/rpc.c
index bd24dd3269c8e..83adf658521d4 100644
--- a/src/helpers/rpc.c
+++ b/src/helpers/rpc.c
@@ -40,21 +40,12 @@
 #include <libnetfilter_queue/pktbuff.h>
 #include <linux/netfilter.h>
 
+#include "helpers/rpc.h"
+
 /* RFC 1050: RPC: Remote Procedure Call Protocol Specification Version 2 */
 /* RFC 1014: XDR: External Data Representation Standard */
 #define SUPPORTED_RPC_VERSION	2
 
-struct rpc_info {
-	/* XID */
-	uint32_t xid;
-	/* program */
-	uint32_t pm_prog;
-	/* program version */
-	uint32_t pm_vers;
-	/* transport protocol: TCP|UDP */
-	uint32_t pm_prot;
-};
-
 /* So, this packet has hit the connection tracking matching code.
    Mangle it, and change the expectation to match the new version. */
 static unsigned int
diff --git a/src/helpers/sane.c b/src/helpers/sane.c
index c30f4ba18533e..5e02e4fc2c1c3 100644
--- a/src/helpers/sane.c
+++ b/src/helpers/sane.c
@@ -38,11 +38,7 @@
 #include <libnetfilter_queue/libnetfilter_queue_tcp.h>
 #include <libnetfilter_queue/pktbuff.h>
 #include <linux/netfilter.h>
-
-enum sane_state {
-	SANE_STATE_NORMAL,
-	SANE_STATE_START_REQUESTED,
-};
+#include "helpers/sane.h"
 
 struct sane_request {
 	uint32_t RPC_code;
@@ -60,10 +56,6 @@ struct sane_reply_net_start {
 	/* other fields aren't interesting for conntrack */
 };
 
-struct nf_ct_sane_master {
-	enum sane_state state;
-};
-
 static int
 sane_helper_cb(struct pkt_buff *pkt, uint32_t protoff,
 		 struct myct *myct, uint32_t ctinfo)
diff --git a/src/helpers/tns.c b/src/helpers/tns.c
index 2b4fed420afb0..d9c7ae693f3a7 100644
--- a/src/helpers/tns.c
+++ b/src/helpers/tns.c
@@ -28,6 +28,8 @@
 #include <libnetfilter_queue/pktbuff.h>
 #include <linux/netfilter.h>
 
+#include "helpers/tns.h"
+
 /* TNS SQL*Net Version 2 */
 enum tns_types {
        TNS_TYPE_CONNECT        = 1,
@@ -57,11 +59,6 @@ struct tns_redirect {
        uint16_t data_len;
 };
 
-struct tns_info {
-       /* Scan next DATA|REDIRECT packet */
-       bool parse;
-};
-
 static int try_number(const char *data, size_t dlen, uint32_t array[],
 		      int array_size, char sep, char term)
 {
diff --git a/src/nfct-extensions/helper.c b/src/nfct-extensions/helper.c
index 0569827612f06..fdeb94c5e5172 100644
--- a/src/nfct-extensions/helper.c
+++ b/src/nfct-extensions/helper.c
@@ -180,7 +180,7 @@ static int nfct_cmd_helper_add(struct mnl_socket *nl, int argc, char *argv[])
 		return -1;
 	}
 
-	helper = helper_find(CONNTRACKD_LIB_DIR, argv[3], l4proto, RTLD_LAZY);
+	helper = __helper_find(argv[3], l4proto);
 	if (helper == NULL) {
 		nfct_perror("that helper is not supported");
 		return -1;
@@ -430,7 +430,7 @@ nfct_cmd_helper_disable(struct mnl_socket *nl, int argc, char *argv[])
 		return -1;
 	}
 
-	helper = helper_find(CONNTRACKD_LIB_DIR, argv[3], l4proto, RTLD_LAZY);
+	helper = __helper_find(argv[3], l4proto);
 	if (helper == NULL) {
 		nfct_perror("that helper is not supported");
 		return -1;
@@ -468,7 +468,187 @@ static struct nfct_extension helper = {
 	.parse_params	= nfct_helper_parse_params,
 };
 
+/*
+ * supported helpers: to set up helpers via nfct, the following definitions are
+ * provided for backward compatibility reasons since conntrackd does not depend
+ * on nfct anymore to set up the userspace helpers.
+ */
+
+static struct ctd_helper amanda_helper = {
+	.name		= "amanda",
+	.l4proto	= IPPROTO_UDP,
+	.policy		= {
+		[0] = {
+			.name			= "amanda",
+			.expect_max		= 3,
+			.expect_timeout		= 180,
+		},
+	},
+};
+
+static struct ctd_helper dhcpv6_helper = {
+	.name		= "dhcpv6",
+	.l4proto	= IPPROTO_UDP,
+	.policy		= {
+		[0] = {
+			.name			= "dhcpv6",
+			.expect_max		= 1,
+			.expect_timeout		= 300,
+		},
+	},
+};
+
+#include "helpers/ftp.h"
+
+static struct ctd_helper ftp_helper = {
+	.name		= "ftp",
+	.l4proto	= IPPROTO_TCP,
+	.priv_data_len	= sizeof(struct ftp_info),
+	.policy		= {
+		[0] = {
+			.name			= "ftp",
+			.expect_max		= 1,
+			.expect_timeout		= 300,
+		},
+	},
+};
+
+static struct ctd_helper mdns_helper = {
+	.name		= "mdns",
+	.l4proto	= IPPROTO_UDP,
+	.priv_data_len	= 0,
+	.policy		= {
+		[0] = {
+			.name		= "mdns",
+			.expect_max	= 8,
+			.expect_timeout = 30,
+		},
+	},
+};
+
+#include "helpers/rpc.h"
+
+static struct ctd_helper rpc_helper_tcp = {
+	.name		= "rpc",
+	.l4proto	= IPPROTO_TCP,
+	.priv_data_len	= sizeof(struct rpc_info),
+	.policy		= {
+		{
+			.name			= "rpc",
+			.expect_max		= 1,
+			.expect_timeout		= 300,
+		},
+	},
+};
+
+static struct ctd_helper rpc_helper_udp = {
+	.name		= "rpc",
+	.l4proto	= IPPROTO_UDP,
+	.priv_data_len	= sizeof(struct rpc_info),
+	.policy		= {
+		{
+			.name			= "rpc",
+			.expect_max		= 1,
+			.expect_timeout		= 300,
+		},
+	},
+};
+
+#include "helpers/sane.h"
+
+static struct ctd_helper sane_helper = {
+	.name		= "sane",
+	.l4proto	= IPPROTO_TCP,
+	.priv_data_len	= sizeof(struct nf_ct_sane_master),
+	.policy		= {
+		[0] = {
+			.name			= "sane",
+			.expect_max		= 1,
+			.expect_timeout		= 5 * 60,
+		},
+	},
+};
+
+static struct ctd_helper slp_helper = {
+	.name		= "slp",
+	.l4proto	= IPPROTO_UDP,
+	.priv_data_len	= 0,
+	.policy		= {
+		[0] = {
+			.name		= "slp",
+			.expect_max	= 8,
+			.expect_timeout = 16, /* default CONFIG_MC_MAX + 1 */
+		},
+	},
+};
+
+static struct ctd_helper ssdp_helper_udp = {
+	.name		= "ssdp",
+	.l4proto	= IPPROTO_UDP,
+	.priv_data_len	= 0,
+	.policy		= {
+		[0] = {
+			.name		= "ssdp",
+			.expect_max	= 8,
+			.expect_timeout = 5 * 60,
+		},
+	},
+};
+
+static struct ctd_helper ssdp_helper_tcp = {
+	.name		= "ssdp",
+	.l4proto	= IPPROTO_TCP,
+	.priv_data_len	= 0,
+	.policy		= {
+		[0] = {
+			.name		= "ssdp",
+			.expect_max	= 8,
+			.expect_timeout = 5 * 60,
+		},
+	},
+};
+
+static struct ctd_helper tftp_helper = {
+	.name		= "tftp",
+	.l4proto	= IPPROTO_UDP,
+	.policy		= {
+		[0] = {
+			.name			= "tftp",
+			.expect_max		= 1,
+			.expect_timeout		= 5 * 60,
+		},
+	},
+};
+
+#include "helpers/tns.h"
+
+static struct ctd_helper tns_helper = {
+	.name		= "tns",
+	.l4proto	= IPPROTO_TCP,
+	.priv_data_len	= sizeof(struct tns_info),
+	.policy		= {
+		[0] = {
+			.name		= "tns",
+			.expect_max	= 1,
+			.expect_timeout = 300,
+		},
+	},
+};
+
 static void __init helper_init(void)
 {
+	helper_register(&amanda_helper);
+	helper_register(&dhcpv6_helper);
+	helper_register(&ftp_helper);
+	helper_register(&mdns_helper);
+	helper_register(&rpc_helper_tcp);
+	helper_register(&rpc_helper_udp);
+	helper_register(&sane_helper);
+	helper_register(&slp_helper);
+	helper_register(&ssdp_helper_udp);
+	helper_register(&ssdp_helper_tcp);
+	helper_register(&tftp_helper);
+	helper_register(&tns_helper);
+
 	nfct_extension_register(&helper);
 }
-- 
2.34.1