diff options
| author | Teddy Engel <engel.teddy@gmail.com> | 2026-06-01 16:42:56 +0000 |
|---|---|---|
| committer | Pouria Mousavizadeh Tehrani <pouria@FreeBSD.org> | 2026-06-02 09:14:26 +0000 |
| commit | ea4888e63f6ac89c38982ffee693f89a5927e9c9 (patch) | |
| tree | 7d2cfb2237e42f55f49430279094f65130b29ef9 | |
| parent | 1cef7e9eb0822c606fc34f975efd14b6daeff756 (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.c | 3 |
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 */ |
