nftables/0019-table-Embed-creating-nft-version-into-userdata.patch

233 lines
7.0 KiB
Diff

From 50afb84d7064806ad7acc8364455062fc0751528 Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
Date: Tue, 9 Sep 2025 16:49:27 +0200
Subject: [PATCH] table: Embed creating nft version into userdata
JIRA: https://issues.redhat.com/browse/RHEL-108851
Upstream Status: nftables commit 64c07e38f0494093a399a68a31056f5866c4d705
Conflicts: Context change due to missing --with-unitdir option.
commit 64c07e38f0494093a399a68a31056f5866c4d705
Author: Phil Sutter <phil@nwl.cc>
Date: Mon May 12 22:59:26 2025 +0200
table: Embed creating nft version into userdata
Upon listing a table which was created by a newer version of nftables,
warn about the potentially incomplete content.
Suggested-by: Florian Westphal <fw@strlen.de>
Cc: Dan Winship <danwinship@redhat.com>
Signed-off-by: Phil Sutter <phil@nwl.cc>
Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Phil Sutter <psutter@redhat.com>
---
Makefile.am | 3 +++
configure.ac | 24 ++++++++++++++++++++++++
include/rule.h | 1 +
src/mnl.c | 21 +++++++++++++++------
src/netlink.c | 33 +++++++++++++++++++++++++++++++++
src/rule.c | 4 ++++
6 files changed, 80 insertions(+), 6 deletions(-)
diff --git a/Makefile.am b/Makefile.am
index ba09e7f..c2a6908 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -33,6 +33,7 @@ sbin_PROGRAMS =
check_PROGRAMS =
dist_man_MANS =
CLEANFILES =
+DISTCLEANFILES =
###############################################################################
@@ -105,6 +106,8 @@ noinst_HEADERS = \
\
$(NULL)
+DISTCLEANFILES += nftversion.h
+
###############################################################################
AM_CPPFLAGS = \
diff --git a/configure.ac b/configure.ac
index 816e920..bac8319 100644
--- a/configure.ac
+++ b/configure.ac
@@ -114,6 +114,30 @@ AC_CHECK_DECLS([getprotobyname_r, getprotobynumber_r, getservbyport_r], [], [],
#include <netdb.h>
]])
+AC_ARG_WITH([stable-release], [AS_HELP_STRING([--with-stable-release],
+ [Stable release number])],
+ [], [with_stable_release=0])
+AC_CONFIG_COMMANDS([stable_release],
+ [STABLE_RELEASE=$stable_release],
+ [stable_release=$with_stable_release])
+AC_CONFIG_COMMANDS([nftversion.h], [
+(
+ echo "static char nftversion[[]] = {"
+ echo " ${VERSION}," | tr '.' ','
+ echo " ${STABLE_RELEASE}"
+ echo "};"
+ echo "static char nftbuildstamp[[]] = {"
+ for ((i = 56; i >= 0; i-= 8)); do
+ echo " ((uint64_t)MAKE_STAMP >> $i) & 0xff,"
+ done
+ echo "};"
+) >nftversion.h
+])
+# Current date should be fetched exactly once per build,
+# so have 'make' call date and pass the value to every 'gcc' call
+AC_SUBST([MAKE_STAMP], ["\$(shell date +%s)"])
+CFLAGS="${CFLAGS} -DMAKE_STAMP=\${MAKE_STAMP}"
+
AC_CONFIG_FILES([ \
Makefile \
libnftables.pc \
diff --git a/include/rule.h b/include/rule.h
index 238be23..1b52972 100644
--- a/include/rule.h
+++ b/include/rule.h
@@ -170,6 +170,7 @@ struct table {
uint32_t owner;
const char *comment;
bool has_xt_stmts;
+ bool is_from_future;
};
extern struct table *table_alloc(void);
diff --git a/src/mnl.c b/src/mnl.c
index 12a6345..e748ab6 100644
--- a/src/mnl.c
+++ b/src/mnl.c
@@ -10,6 +10,7 @@
#include <nft.h>
#include <iface.h>
+#include <nftversion.h>
#include <libmnl/libmnl.h>
#include <libnftnl/common.h>
@@ -1054,24 +1055,32 @@ int mnl_nft_table_add(struct netlink_ctx *ctx, struct cmd *cmd,
if (nlt == NULL)
memory_allocation_error();
+ udbuf = nftnl_udata_buf_alloc(NFT_USERDATA_MAXLEN);
+ if (!udbuf)
+ memory_allocation_error();
+
nftnl_table_set_u32(nlt, NFTNL_TABLE_FAMILY, cmd->handle.family);
if (cmd->table) {
nftnl_table_set_u32(nlt, NFTNL_TABLE_FLAGS, cmd->table->flags);
if (cmd->table->comment) {
- udbuf = nftnl_udata_buf_alloc(NFT_USERDATA_MAXLEN);
- if (!udbuf)
- memory_allocation_error();
if (!nftnl_udata_put_strz(udbuf, NFTNL_UDATA_TABLE_COMMENT, cmd->table->comment))
memory_allocation_error();
- nftnl_table_set_data(nlt, NFTNL_TABLE_USERDATA, nftnl_udata_buf_data(udbuf),
- nftnl_udata_buf_len(udbuf));
- nftnl_udata_buf_free(udbuf);
}
} else {
nftnl_table_set_u32(nlt, NFTNL_TABLE_FLAGS, 0);
}
+ if (!nftnl_udata_put(udbuf, NFTNL_UDATA_TABLE_NFTVER,
+ sizeof(nftversion), nftversion) ||
+ !nftnl_udata_put(udbuf, NFTNL_UDATA_TABLE_NFTBLD,
+ sizeof(nftbuildstamp), nftbuildstamp))
+ memory_allocation_error();
+ nftnl_table_set_data(nlt, NFTNL_TABLE_USERDATA,
+ nftnl_udata_buf_data(udbuf),
+ nftnl_udata_buf_len(udbuf));
+ nftnl_udata_buf_free(udbuf);
+
nlh = nftnl_nlmsg_build_hdr(nftnl_batch_buffer(ctx->batch),
NFT_MSG_NEWTABLE,
cmd->handle.family,
diff --git a/src/netlink.c b/src/netlink.c
index 2ced863..7f9730d 100644
--- a/src/netlink.c
+++ b/src/netlink.c
@@ -10,6 +10,7 @@
*/
#include <nft.h>
+#include <nftversion.h>
#include <errno.h>
#include <libmnl/libmnl.h>
@@ -728,6 +729,14 @@ static int table_parse_udata_cb(const struct nftnl_udata *attr, void *data)
if (value[len - 1] != '\0')
return -1;
break;
+ case NFTNL_UDATA_TABLE_NFTVER:
+ if (len != sizeof(nftversion))
+ return -1;
+ break;
+ case NFTNL_UDATA_TABLE_NFTBLD:
+ if (len != sizeof(nftbuildstamp))
+ return -1;
+ break;
default:
return 0;
}
@@ -735,6 +744,29 @@ static int table_parse_udata_cb(const struct nftnl_udata *attr, void *data)
return 0;
}
+static int version_cmp(const struct nftnl_udata **ud)
+{
+ const char *udbuf;
+ size_t i;
+
+ /* netlink attribute lengths checked by table_parse_udata_cb() */
+ if (ud[NFTNL_UDATA_TABLE_NFTVER]) {
+ udbuf = nftnl_udata_get(ud[NFTNL_UDATA_TABLE_NFTVER]);
+ for (i = 0; i < sizeof(nftversion); i++) {
+ if (nftversion[i] != udbuf[i])
+ return nftversion[i] - udbuf[i];
+ }
+ }
+ if (ud[NFTNL_UDATA_TABLE_NFTBLD]) {
+ udbuf = nftnl_udata_get(ud[NFTNL_UDATA_TABLE_NFTBLD]);
+ for (i = 0; i < sizeof(nftbuildstamp); i++) {
+ if (nftbuildstamp[i] != udbuf[i])
+ return nftbuildstamp[i] - udbuf[i];
+ }
+ }
+ return 0;
+}
+
struct table *netlink_delinearize_table(struct netlink_ctx *ctx,
const struct nftnl_table *nlt)
{
@@ -759,6 +791,7 @@ struct table *netlink_delinearize_table(struct netlink_ctx *ctx,
}
if (ud[NFTNL_UDATA_TABLE_COMMENT])
table->comment = xstrdup(nftnl_udata_get(ud[NFTNL_UDATA_TABLE_COMMENT]));
+ table->is_from_future = version_cmp(ud) < 0;
}
return table;
diff --git a/src/rule.c b/src/rule.c
index 151ed53..e4d6f53 100644
--- a/src/rule.c
+++ b/src/rule.c
@@ -1274,6 +1274,10 @@ static void table_print(const struct table *table, struct output_ctx *octx)
fprintf(octx->error_fp,
"# Warning: table %s %s is managed by iptables-nft, do not touch!\n",
family, table->handle.table.name);
+ if (table->is_from_future)
+ fprintf(octx->error_fp,
+ "# Warning: table %s %s was created by a newer version of nftables? Content may be incomplete!\n",
+ family, table->handle.table.name);
nft_print(octx, "table %s %s {", family, table->handle.table.name);
if (nft_output_handle(octx) || table->flags & TABLE_F_OWNER)