aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTeddy Engel <engel.teddy@gmail.com>2026-06-01 16:42:56 +0000
committerPouria Mousavizadeh Tehrani <pouria@FreeBSD.org>2026-06-02 09:14:26 +0000
commitea4888e63f6ac89c38982ffee693f89a5927e9c9 (patch)
tree7d2cfb2237e42f55f49430279094f65130b29ef9
parent1cef7e9eb0822c606fc34f975efd14b6daeff756 (diff)
nat64lsn: Fix type confusion panic when using wrong NAT64 instance type
When an ipfw rule references a NAT64 instance by name using 'nat64lsn', the kernel looks up the instance in the shared srvstate[] array without verifying the instance type. If the named instance is actually a nat64clat or nat64stl instance (created with 'nat64clat' or 'nat64stl'), the code incorrectly casts the instance to nat64lsn_instance and dereferences the ->cfg pointer, which causes a kernel panic. The root cause is that all NAT64 instance types share the same srvstate[] array but have different struct layouts. For nat64lsn_instance, the field after 'no' is a pointer to nat64lsn_cfg. For nat64clat_cfg, the same offset contains an embedded nat64_config struct. Fix by adding a type check after NAT64_LOOKUP() to verify that the instance's etlv matches IPFW_TLV_NAT64LSN_NAME before proceeding. If the type doesn't match, return IP_FW_DENY to reject the packet safely rather than crashing. Signed-off-by: Teddy Engel <engel.teddy@gmail.com> PR: 292023 Reported by: pouria Reviewed by: ae Pull-Request: https://github.com/freebsd/freebsd-src/pull/2249
-rw-r--r--sys/netpfil/ipfw/nat64/nat64lsn.c3
1 files changed, 2 insertions, 1 deletions
diff --git a/sys/netpfil/ipfw/nat64/nat64lsn.c b/sys/netpfil/ipfw/nat64/nat64lsn.c
index 1bac425afc30..9d2ee5e650df 100644
--- a/sys/netpfil/ipfw/nat64/nat64lsn.c
+++ b/sys/netpfil/ipfw/nat64/nat64lsn.c
@@ -1731,7 +1731,8 @@ ipfw_nat64lsn(struct ip_fw_chain *ch, struct ip_fw_args *args,
if (cmd->opcode != O_EXTERNAL_ACTION ||
insntod(cmd, kidx)->kidx != V_nat64lsn_eid ||
icmd->opcode != O_EXTERNAL_INSTANCE ||
- (i = NAT64_LOOKUP(ch, icmd)) == NULL)
+ (i = NAT64_LOOKUP(ch, icmd)) == NULL ||
+ i->no.etlv != IPFW_TLV_NAT64LSN_NAME)
return (IP_FW_DENY);
*done = 1; /* terminate the search */