VYPR
Unrated severityNVD Advisory· Published May 27, 2026· Updated May 27, 2026

CVE-2026-45844

CVE-2026-45844

Description

In the Linux kernel, the following vulnerability has been resolved:

netfilter: arp_tables: fix IEEE1394 ARP payload parsing

Weiming Shi says:

"arp_packet_match() unconditionally parses the ARP payload assuming two hardware addresses are present (source and target). However, IPv4-over-IEEE1394 ARP (RFC 2734) omits the target hardware address field, and arp_hdr_len() already accounts for this by returning a shorter length for ARPHRD_IEEE1394 devices.

As a result, on IEEE1394 interfaces arp_packet_match() advances past a nonexistent target hardware address and reads the wrong bytes for both the target device address comparison and the target IP address. This causes arptables rules to match against garbage data, leading to incorrect filtering decisions: packets that should be accepted may be dropped and vice versa.

The ARP stack in net/ipv4/arp.c (arp_create and arp_process) already handles this correctly by skipping the target hardware address for ARPHRD_IEEE1394. Apply the same pattern to arp_packet_match()."

Mangle the original patch to always return 0 (no match) in case user matches on the target hardware address which is never present in IEEE1394.

Note that this returns 0 (no match) for either normal and inverse match because matching in the target hardware address in ARPHRD_IEEE1394 has never been supported by arptables. This is intentional, matching on the target hardware address should never evaluate true for ARPHRD_IEEE1394.

Moreover, adjust arpt_mangle to drop the packet too as AI suggests:

In arpt_mangle, the logic assumes a standard ARP layout. Because IEEE1394 (FireWire) omits the target hardware address, the linear pointer arithmetic miscalculates the offset for the target IP address. This causes mangling operations to write to the wrong location, leading to packet corruption. To ensure safety, this patch drops packets (NF_DROP) when mangling is requested for these fields on IEEE1394 devices, as the current implementation cannot correctly map the FireWire ARP payload.

This omits both mangling target hardware and IP address. Even if IP address mangling should be possible in IEEE1394, this would require to adjust arpt_mangle offset calculation, which has never been supported.

Based on patch from Weiming Shi <bestswngs@gmail.com>.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

arp_packet_match() and arpt_mangle in Linux netfilter mishandle IEEE1394 ARP payloads, causing incorrect filtering and potential packet corruption.

Vulnerability

In the Linux kernel, arp_packet_match() in net/ipv4/netfilter/arp_tables.c unconditionally parses the ARP payload assuming two hardware addresses (source and target). However, IPv4-over-IEEE1394 ARP (RFC 2734) omits the target hardware address field. The function arp_hdr_len() correctly returns a shorter length for ARPHRD_IEEE1394 devices, but arp_packet_match() advances past a nonexistent target hardware address and reads garbage for the target device address and target IP address. Additionally, arpt_mangle miscalculates offsets for the target IP address on IEEE1394 devices due to the missing target hardware address. This affects all kernel versions prior to the fix.

Exploitation

An attacker with network access to a system using an IEEE1394 (FireWire) interface and arptables rules can send specially crafted ARP packets conforming to RFC 2734. The attacker does not need authentication; the vulnerability is triggered by the kernel's processing of ARP packets on such interfaces. The attacker can cause incorrect matching by arp_packet_match(), leading to packets being incorrectly dropped or accepted, and in the case of arpt_mangle, packet corruption.

Impact

Successful exploitation can lead to incorrect packet filtering decisions: packets that should be accepted may be dropped, or vice versa. In the mangling path, packets may be corrupted due to writes to wrong memory locations. This can result in denial of service, network misrouting, or potentially information disclosure. The privilege level required is none beyond network access; the impact is on the network filtering behavior of the system.

Mitigation

The fix is included in the following stable kernel commits: [1], [2], [3]. These patches ensure that arp_packet_match() returns 0 (no match) when the rule matches on the target hardware address for IEEE1394 interfaces, and arpt_mangle drops packets (NF_DROP) when mangling is requested for fields that rely on the missing target hardware address. Users should apply the latest kernel updates from their distribution. No workarounds are currently available.

AI Insight generated on May 27, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected products

2

Patches

10
03ea11dbefaa

netfilter: arp_tables: fix IEEE1394 ARP payload parsing

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitPablo Neira AyusoApr 20, 2026Fixed in 6.12.91via kernel-cna
2 files changed · +23 4
  • net/ipv4/netfilter/arp_tables.c+15 3 modified
    diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
    index 1cdd9c28ab2da4..97ead883e4a13b 100644
    --- a/net/ipv4/netfilter/arp_tables.c
    +++ b/net/ipv4/netfilter/arp_tables.c
    @@ -110,13 +110,25 @@ static inline int arp_packet_match(const struct arphdr *arphdr,
     	arpptr += dev->addr_len;
     	memcpy(&src_ipaddr, arpptr, sizeof(u32));
     	arpptr += sizeof(u32);
    -	tgt_devaddr = arpptr;
    -	arpptr += dev->addr_len;
    +
    +	if (IS_ENABLED(CONFIG_FIREWIRE_NET) && dev->type == ARPHRD_IEEE1394) {
    +		if (unlikely(memchr_inv(arpinfo->tgt_devaddr.mask, 0,
    +					sizeof(arpinfo->tgt_devaddr.mask))))
    +			return 0;
    +
    +		tgt_devaddr = NULL;
    +	} else {
    +		tgt_devaddr = arpptr;
    +		arpptr += dev->addr_len;
    +	}
     	memcpy(&tgt_ipaddr, arpptr, sizeof(u32));
     
     	if (NF_INVF(arpinfo, ARPT_INV_SRCDEVADDR,
     		    arp_devaddr_compare(&arpinfo->src_devaddr, src_devaddr,
    -					dev->addr_len)) ||
    +					dev->addr_len)))
    +		return 0;
    +
    +	if (tgt_devaddr &&
     	    NF_INVF(arpinfo, ARPT_INV_TGTDEVADDR,
     		    arp_devaddr_compare(&arpinfo->tgt_devaddr, tgt_devaddr,
     					dev->addr_len)))
    
  • net/ipv4/netfilter/arpt_mangle.c+8 1 modified
    diff --git a/net/ipv4/netfilter/arpt_mangle.c b/net/ipv4/netfilter/arpt_mangle.c
    index a4e07e5e9c118d..f65dd339208e8a 100644
    --- a/net/ipv4/netfilter/arpt_mangle.c
    +++ b/net/ipv4/netfilter/arpt_mangle.c
    @@ -40,6 +40,10 @@ target(struct sk_buff *skb, const struct xt_action_param *par)
     	}
     	arpptr += pln;
     	if (mangle->flags & ARPT_MANGLE_TDEV) {
    +		if (unlikely(IS_ENABLED(CONFIG_FIREWIRE_NET) &&
    +			     skb->dev->type == ARPHRD_IEEE1394))
    +			return NF_DROP;
    +
     		if (ARPT_DEV_ADDR_LEN_MAX < hln ||
     		   (arpptr + hln > skb_tail_pointer(skb)))
     			return NF_DROP;
    @@ -47,6 +51,10 @@ target(struct sk_buff *skb, const struct xt_action_param *par)
     	}
     	arpptr += hln;
     	if (mangle->flags & ARPT_MANGLE_TIP) {
    +		if (unlikely(IS_ENABLED(CONFIG_FIREWIRE_NET) &&
    +			     skb->dev->type == ARPHRD_IEEE1394))
    +			return NF_DROP;
    +
     		if (ARPT_MANGLE_ADDR_LEN_MAX < pln ||
     		   (arpptr + pln > skb_tail_pointer(skb)))
     			return NF_DROP;
    -- 
    cgit 1.3-korg
    
    
    
1c55053f8ffd

netfilter: arp_tables: fix IEEE1394 ARP payload parsing

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitPablo Neira AyusoApr 20, 2026Fixed in 6.18.33via kernel-cna
2 files changed · +23 4
  • net/ipv4/netfilter/arp_tables.c+15 3 modified
    diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
    index 1cdd9c28ab2da4..97ead883e4a13b 100644
    --- a/net/ipv4/netfilter/arp_tables.c
    +++ b/net/ipv4/netfilter/arp_tables.c
    @@ -110,13 +110,25 @@ static inline int arp_packet_match(const struct arphdr *arphdr,
     	arpptr += dev->addr_len;
     	memcpy(&src_ipaddr, arpptr, sizeof(u32));
     	arpptr += sizeof(u32);
    -	tgt_devaddr = arpptr;
    -	arpptr += dev->addr_len;
    +
    +	if (IS_ENABLED(CONFIG_FIREWIRE_NET) && dev->type == ARPHRD_IEEE1394) {
    +		if (unlikely(memchr_inv(arpinfo->tgt_devaddr.mask, 0,
    +					sizeof(arpinfo->tgt_devaddr.mask))))
    +			return 0;
    +
    +		tgt_devaddr = NULL;
    +	} else {
    +		tgt_devaddr = arpptr;
    +		arpptr += dev->addr_len;
    +	}
     	memcpy(&tgt_ipaddr, arpptr, sizeof(u32));
     
     	if (NF_INVF(arpinfo, ARPT_INV_SRCDEVADDR,
     		    arp_devaddr_compare(&arpinfo->src_devaddr, src_devaddr,
    -					dev->addr_len)) ||
    +					dev->addr_len)))
    +		return 0;
    +
    +	if (tgt_devaddr &&
     	    NF_INVF(arpinfo, ARPT_INV_TGTDEVADDR,
     		    arp_devaddr_compare(&arpinfo->tgt_devaddr, tgt_devaddr,
     					dev->addr_len)))
    
  • net/ipv4/netfilter/arpt_mangle.c+8 1 modified
    diff --git a/net/ipv4/netfilter/arpt_mangle.c b/net/ipv4/netfilter/arpt_mangle.c
    index a4e07e5e9c118d..f65dd339208e8a 100644
    --- a/net/ipv4/netfilter/arpt_mangle.c
    +++ b/net/ipv4/netfilter/arpt_mangle.c
    @@ -40,6 +40,10 @@ target(struct sk_buff *skb, const struct xt_action_param *par)
     	}
     	arpptr += pln;
     	if (mangle->flags & ARPT_MANGLE_TDEV) {
    +		if (unlikely(IS_ENABLED(CONFIG_FIREWIRE_NET) &&
    +			     skb->dev->type == ARPHRD_IEEE1394))
    +			return NF_DROP;
    +
     		if (ARPT_DEV_ADDR_LEN_MAX < hln ||
     		   (arpptr + hln > skb_tail_pointer(skb)))
     			return NF_DROP;
    @@ -47,6 +51,10 @@ target(struct sk_buff *skb, const struct xt_action_param *par)
     	}
     	arpptr += hln;
     	if (mangle->flags & ARPT_MANGLE_TIP) {
    +		if (unlikely(IS_ENABLED(CONFIG_FIREWIRE_NET) &&
    +			     skb->dev->type == ARPHRD_IEEE1394))
    +			return NF_DROP;
    +
     		if (ARPT_MANGLE_ADDR_LEN_MAX < pln ||
     		   (arpptr + pln > skb_tail_pointer(skb)))
     			return NF_DROP;
    -- 
    cgit 1.3-korg
    
    
    
ac698d81fd66

netfilter: arp_tables: fix IEEE1394 ARP payload parsing

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitPablo Neira AyusoApr 20, 2026Fixed in 7.0.10via kernel-cna
2 files changed · +23 4
  • net/ipv4/netfilter/arp_tables.c+15 3 modified
    diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
    index 1cdd9c28ab2da4..97ead883e4a13b 100644
    --- a/net/ipv4/netfilter/arp_tables.c
    +++ b/net/ipv4/netfilter/arp_tables.c
    @@ -110,13 +110,25 @@ static inline int arp_packet_match(const struct arphdr *arphdr,
     	arpptr += dev->addr_len;
     	memcpy(&src_ipaddr, arpptr, sizeof(u32));
     	arpptr += sizeof(u32);
    -	tgt_devaddr = arpptr;
    -	arpptr += dev->addr_len;
    +
    +	if (IS_ENABLED(CONFIG_FIREWIRE_NET) && dev->type == ARPHRD_IEEE1394) {
    +		if (unlikely(memchr_inv(arpinfo->tgt_devaddr.mask, 0,
    +					sizeof(arpinfo->tgt_devaddr.mask))))
    +			return 0;
    +
    +		tgt_devaddr = NULL;
    +	} else {
    +		tgt_devaddr = arpptr;
    +		arpptr += dev->addr_len;
    +	}
     	memcpy(&tgt_ipaddr, arpptr, sizeof(u32));
     
     	if (NF_INVF(arpinfo, ARPT_INV_SRCDEVADDR,
     		    arp_devaddr_compare(&arpinfo->src_devaddr, src_devaddr,
    -					dev->addr_len)) ||
    +					dev->addr_len)))
    +		return 0;
    +
    +	if (tgt_devaddr &&
     	    NF_INVF(arpinfo, ARPT_INV_TGTDEVADDR,
     		    arp_devaddr_compare(&arpinfo->tgt_devaddr, tgt_devaddr,
     					dev->addr_len)))
    
  • net/ipv4/netfilter/arpt_mangle.c+8 1 modified
    diff --git a/net/ipv4/netfilter/arpt_mangle.c b/net/ipv4/netfilter/arpt_mangle.c
    index a4e07e5e9c118d..f65dd339208e8a 100644
    --- a/net/ipv4/netfilter/arpt_mangle.c
    +++ b/net/ipv4/netfilter/arpt_mangle.c
    @@ -40,6 +40,10 @@ target(struct sk_buff *skb, const struct xt_action_param *par)
     	}
     	arpptr += pln;
     	if (mangle->flags & ARPT_MANGLE_TDEV) {
    +		if (unlikely(IS_ENABLED(CONFIG_FIREWIRE_NET) &&
    +			     skb->dev->type == ARPHRD_IEEE1394))
    +			return NF_DROP;
    +
     		if (ARPT_DEV_ADDR_LEN_MAX < hln ||
     		   (arpptr + hln > skb_tail_pointer(skb)))
     			return NF_DROP;
    @@ -47,6 +51,10 @@ target(struct sk_buff *skb, const struct xt_action_param *par)
     	}
     	arpptr += hln;
     	if (mangle->flags & ARPT_MANGLE_TIP) {
    +		if (unlikely(IS_ENABLED(CONFIG_FIREWIRE_NET) &&
    +			     skb->dev->type == ARPHRD_IEEE1394))
    +			return NF_DROP;
    +
     		if (ARPT_MANGLE_ADDR_LEN_MAX < pln ||
     		   (arpptr + pln > skb_tail_pointer(skb)))
     			return NF_DROP;
    -- 
    cgit 1.3-korg
    
    
    
1e8e3f449b1e

netfilter: arp_tables: fix IEEE1394 ARP payload parsing

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitPablo Neira AyusoApr 20, 2026Fixed in 7.1-rc2via kernel-cna
2 files changed · +23 4
  • net/ipv4/netfilter/arp_tables.c+15 3 modified
    diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
    index 1cdd9c28ab2da4..97ead883e4a13b 100644
    --- a/net/ipv4/netfilter/arp_tables.c
    +++ b/net/ipv4/netfilter/arp_tables.c
    @@ -110,13 +110,25 @@ static inline int arp_packet_match(const struct arphdr *arphdr,
     	arpptr += dev->addr_len;
     	memcpy(&src_ipaddr, arpptr, sizeof(u32));
     	arpptr += sizeof(u32);
    -	tgt_devaddr = arpptr;
    -	arpptr += dev->addr_len;
    +
    +	if (IS_ENABLED(CONFIG_FIREWIRE_NET) && dev->type == ARPHRD_IEEE1394) {
    +		if (unlikely(memchr_inv(arpinfo->tgt_devaddr.mask, 0,
    +					sizeof(arpinfo->tgt_devaddr.mask))))
    +			return 0;
    +
    +		tgt_devaddr = NULL;
    +	} else {
    +		tgt_devaddr = arpptr;
    +		arpptr += dev->addr_len;
    +	}
     	memcpy(&tgt_ipaddr, arpptr, sizeof(u32));
     
     	if (NF_INVF(arpinfo, ARPT_INV_SRCDEVADDR,
     		    arp_devaddr_compare(&arpinfo->src_devaddr, src_devaddr,
    -					dev->addr_len)) ||
    +					dev->addr_len)))
    +		return 0;
    +
    +	if (tgt_devaddr &&
     	    NF_INVF(arpinfo, ARPT_INV_TGTDEVADDR,
     		    arp_devaddr_compare(&arpinfo->tgt_devaddr, tgt_devaddr,
     					dev->addr_len)))
    
  • net/ipv4/netfilter/arpt_mangle.c+8 1 modified
    diff --git a/net/ipv4/netfilter/arpt_mangle.c b/net/ipv4/netfilter/arpt_mangle.c
    index a4e07e5e9c118d..f65dd339208e8a 100644
    --- a/net/ipv4/netfilter/arpt_mangle.c
    +++ b/net/ipv4/netfilter/arpt_mangle.c
    @@ -40,6 +40,10 @@ target(struct sk_buff *skb, const struct xt_action_param *par)
     	}
     	arpptr += pln;
     	if (mangle->flags & ARPT_MANGLE_TDEV) {
    +		if (unlikely(IS_ENABLED(CONFIG_FIREWIRE_NET) &&
    +			     skb->dev->type == ARPHRD_IEEE1394))
    +			return NF_DROP;
    +
     		if (ARPT_DEV_ADDR_LEN_MAX < hln ||
     		   (arpptr + hln > skb_tail_pointer(skb)))
     			return NF_DROP;
    @@ -47,6 +51,10 @@ target(struct sk_buff *skb, const struct xt_action_param *par)
     	}
     	arpptr += hln;
     	if (mangle->flags & ARPT_MANGLE_TIP) {
    +		if (unlikely(IS_ENABLED(CONFIG_FIREWIRE_NET) &&
    +			     skb->dev->type == ARPHRD_IEEE1394))
    +			return NF_DROP;
    +
     		if (ARPT_MANGLE_ADDR_LEN_MAX < pln ||
     		   (arpptr + pln > skb_tail_pointer(skb)))
     			return NF_DROP;
    -- 
    cgit 1.3-korg
    
    
    
ad9973df8e0e

netfilter: arp_tables: fix IEEE1394 ARP payload parsing

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitPablo Neira AyusoApr 20, 2026Fixed in 6.6.141via kernel-cna
2 files changed · +23 4
  • net/ipv4/netfilter/arp_tables.c+15 3 modified
    diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
    index 14365b20f1c5c0..564054123772a1 100644
    --- a/net/ipv4/netfilter/arp_tables.c
    +++ b/net/ipv4/netfilter/arp_tables.c
    @@ -110,13 +110,25 @@ static inline int arp_packet_match(const struct arphdr *arphdr,
     	arpptr += dev->addr_len;
     	memcpy(&src_ipaddr, arpptr, sizeof(u32));
     	arpptr += sizeof(u32);
    -	tgt_devaddr = arpptr;
    -	arpptr += dev->addr_len;
    +
    +	if (IS_ENABLED(CONFIG_FIREWIRE_NET) && dev->type == ARPHRD_IEEE1394) {
    +		if (unlikely(memchr_inv(arpinfo->tgt_devaddr.mask, 0,
    +					sizeof(arpinfo->tgt_devaddr.mask))))
    +			return 0;
    +
    +		tgt_devaddr = NULL;
    +	} else {
    +		tgt_devaddr = arpptr;
    +		arpptr += dev->addr_len;
    +	}
     	memcpy(&tgt_ipaddr, arpptr, sizeof(u32));
     
     	if (NF_INVF(arpinfo, ARPT_INV_SRCDEVADDR,
     		    arp_devaddr_compare(&arpinfo->src_devaddr, src_devaddr,
    -					dev->addr_len)) ||
    +					dev->addr_len)))
    +		return 0;
    +
    +	if (tgt_devaddr &&
     	    NF_INVF(arpinfo, ARPT_INV_TGTDEVADDR,
     		    arp_devaddr_compare(&arpinfo->tgt_devaddr, tgt_devaddr,
     					dev->addr_len)))
    
  • net/ipv4/netfilter/arpt_mangle.c+8 1 modified
    diff --git a/net/ipv4/netfilter/arpt_mangle.c b/net/ipv4/netfilter/arpt_mangle.c
    index a4e07e5e9c118d..f65dd339208e8a 100644
    --- a/net/ipv4/netfilter/arpt_mangle.c
    +++ b/net/ipv4/netfilter/arpt_mangle.c
    @@ -40,6 +40,10 @@ target(struct sk_buff *skb, const struct xt_action_param *par)
     	}
     	arpptr += pln;
     	if (mangle->flags & ARPT_MANGLE_TDEV) {
    +		if (unlikely(IS_ENABLED(CONFIG_FIREWIRE_NET) &&
    +			     skb->dev->type == ARPHRD_IEEE1394))
    +			return NF_DROP;
    +
     		if (ARPT_DEV_ADDR_LEN_MAX < hln ||
     		   (arpptr + hln > skb_tail_pointer(skb)))
     			return NF_DROP;
    @@ -47,6 +51,10 @@ target(struct sk_buff *skb, const struct xt_action_param *par)
     	}
     	arpptr += hln;
     	if (mangle->flags & ARPT_MANGLE_TIP) {
    +		if (unlikely(IS_ENABLED(CONFIG_FIREWIRE_NET) &&
    +			     skb->dev->type == ARPHRD_IEEE1394))
    +			return NF_DROP;
    +
     		if (ARPT_MANGLE_ADDR_LEN_MAX < pln ||
     		   (arpptr + pln > skb_tail_pointer(skb)))
     			return NF_DROP;
    -- 
    cgit 1.3-korg
    
    
    
1e8e3f449b1e

netfilter: arp_tables: fix IEEE1394 ARP payload parsing

2 files changed · +23 4
  • net/ipv4/netfilter/arp_tables.c+15 3 modified
    diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
    index 1cdd9c28ab2da4..97ead883e4a13b 100644
    --- a/net/ipv4/netfilter/arp_tables.c
    +++ b/net/ipv4/netfilter/arp_tables.c
    @@ -110,13 +110,25 @@ static inline int arp_packet_match(const struct arphdr *arphdr,
     	arpptr += dev->addr_len;
     	memcpy(&src_ipaddr, arpptr, sizeof(u32));
     	arpptr += sizeof(u32);
    -	tgt_devaddr = arpptr;
    -	arpptr += dev->addr_len;
    +
    +	if (IS_ENABLED(CONFIG_FIREWIRE_NET) && dev->type == ARPHRD_IEEE1394) {
    +		if (unlikely(memchr_inv(arpinfo->tgt_devaddr.mask, 0,
    +					sizeof(arpinfo->tgt_devaddr.mask))))
    +			return 0;
    +
    +		tgt_devaddr = NULL;
    +	} else {
    +		tgt_devaddr = arpptr;
    +		arpptr += dev->addr_len;
    +	}
     	memcpy(&tgt_ipaddr, arpptr, sizeof(u32));
     
     	if (NF_INVF(arpinfo, ARPT_INV_SRCDEVADDR,
     		    arp_devaddr_compare(&arpinfo->src_devaddr, src_devaddr,
    -					dev->addr_len)) ||
    +					dev->addr_len)))
    +		return 0;
    +
    +	if (tgt_devaddr &&
     	    NF_INVF(arpinfo, ARPT_INV_TGTDEVADDR,
     		    arp_devaddr_compare(&arpinfo->tgt_devaddr, tgt_devaddr,
     					dev->addr_len)))
    
  • net/ipv4/netfilter/arpt_mangle.c+8 1 modified
    diff --git a/net/ipv4/netfilter/arpt_mangle.c b/net/ipv4/netfilter/arpt_mangle.c
    index a4e07e5e9c118d..f65dd339208e8a 100644
    --- a/net/ipv4/netfilter/arpt_mangle.c
    +++ b/net/ipv4/netfilter/arpt_mangle.c
    @@ -40,6 +40,10 @@ target(struct sk_buff *skb, const struct xt_action_param *par)
     	}
     	arpptr += pln;
     	if (mangle->flags & ARPT_MANGLE_TDEV) {
    +		if (unlikely(IS_ENABLED(CONFIG_FIREWIRE_NET) &&
    +			     skb->dev->type == ARPHRD_IEEE1394))
    +			return NF_DROP;
    +
     		if (ARPT_DEV_ADDR_LEN_MAX < hln ||
     		   (arpptr + hln > skb_tail_pointer(skb)))
     			return NF_DROP;
    @@ -47,6 +51,10 @@ target(struct sk_buff *skb, const struct xt_action_param *par)
     	}
     	arpptr += hln;
     	if (mangle->flags & ARPT_MANGLE_TIP) {
    +		if (unlikely(IS_ENABLED(CONFIG_FIREWIRE_NET) &&
    +			     skb->dev->type == ARPHRD_IEEE1394))
    +			return NF_DROP;
    +
     		if (ARPT_MANGLE_ADDR_LEN_MAX < pln ||
     		   (arpptr + pln > skb_tail_pointer(skb)))
     			return NF_DROP;
    -- 
    cgit 1.3-korg
    
    
    
1c55053f8ffd

netfilter: arp_tables: fix IEEE1394 ARP payload parsing

2 files changed · +23 4
  • net/ipv4/netfilter/arp_tables.c+15 3 modified
    diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
    index 1cdd9c28ab2da4..97ead883e4a13b 100644
    --- a/net/ipv4/netfilter/arp_tables.c
    +++ b/net/ipv4/netfilter/arp_tables.c
    @@ -110,13 +110,25 @@ static inline int arp_packet_match(const struct arphdr *arphdr,
     	arpptr += dev->addr_len;
     	memcpy(&src_ipaddr, arpptr, sizeof(u32));
     	arpptr += sizeof(u32);
    -	tgt_devaddr = arpptr;
    -	arpptr += dev->addr_len;
    +
    +	if (IS_ENABLED(CONFIG_FIREWIRE_NET) && dev->type == ARPHRD_IEEE1394) {
    +		if (unlikely(memchr_inv(arpinfo->tgt_devaddr.mask, 0,
    +					sizeof(arpinfo->tgt_devaddr.mask))))
    +			return 0;
    +
    +		tgt_devaddr = NULL;
    +	} else {
    +		tgt_devaddr = arpptr;
    +		arpptr += dev->addr_len;
    +	}
     	memcpy(&tgt_ipaddr, arpptr, sizeof(u32));
     
     	if (NF_INVF(arpinfo, ARPT_INV_SRCDEVADDR,
     		    arp_devaddr_compare(&arpinfo->src_devaddr, src_devaddr,
    -					dev->addr_len)) ||
    +					dev->addr_len)))
    +		return 0;
    +
    +	if (tgt_devaddr &&
     	    NF_INVF(arpinfo, ARPT_INV_TGTDEVADDR,
     		    arp_devaddr_compare(&arpinfo->tgt_devaddr, tgt_devaddr,
     					dev->addr_len)))
    
  • net/ipv4/netfilter/arpt_mangle.c+8 1 modified
    diff --git a/net/ipv4/netfilter/arpt_mangle.c b/net/ipv4/netfilter/arpt_mangle.c
    index a4e07e5e9c118d..f65dd339208e8a 100644
    --- a/net/ipv4/netfilter/arpt_mangle.c
    +++ b/net/ipv4/netfilter/arpt_mangle.c
    @@ -40,6 +40,10 @@ target(struct sk_buff *skb, const struct xt_action_param *par)
     	}
     	arpptr += pln;
     	if (mangle->flags & ARPT_MANGLE_TDEV) {
    +		if (unlikely(IS_ENABLED(CONFIG_FIREWIRE_NET) &&
    +			     skb->dev->type == ARPHRD_IEEE1394))
    +			return NF_DROP;
    +
     		if (ARPT_DEV_ADDR_LEN_MAX < hln ||
     		   (arpptr + hln > skb_tail_pointer(skb)))
     			return NF_DROP;
    @@ -47,6 +51,10 @@ target(struct sk_buff *skb, const struct xt_action_param *par)
     	}
     	arpptr += hln;
     	if (mangle->flags & ARPT_MANGLE_TIP) {
    +		if (unlikely(IS_ENABLED(CONFIG_FIREWIRE_NET) &&
    +			     skb->dev->type == ARPHRD_IEEE1394))
    +			return NF_DROP;
    +
     		if (ARPT_MANGLE_ADDR_LEN_MAX < pln ||
     		   (arpptr + pln > skb_tail_pointer(skb)))
     			return NF_DROP;
    -- 
    cgit 1.3-korg
    
    
    
ac698d81fd66

netfilter: arp_tables: fix IEEE1394 ARP payload parsing

2 files changed · +23 4
  • net/ipv4/netfilter/arp_tables.c+15 3 modified
    diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
    index 1cdd9c28ab2da4..97ead883e4a13b 100644
    --- a/net/ipv4/netfilter/arp_tables.c
    +++ b/net/ipv4/netfilter/arp_tables.c
    @@ -110,13 +110,25 @@ static inline int arp_packet_match(const struct arphdr *arphdr,
     	arpptr += dev->addr_len;
     	memcpy(&src_ipaddr, arpptr, sizeof(u32));
     	arpptr += sizeof(u32);
    -	tgt_devaddr = arpptr;
    -	arpptr += dev->addr_len;
    +
    +	if (IS_ENABLED(CONFIG_FIREWIRE_NET) && dev->type == ARPHRD_IEEE1394) {
    +		if (unlikely(memchr_inv(arpinfo->tgt_devaddr.mask, 0,
    +					sizeof(arpinfo->tgt_devaddr.mask))))
    +			return 0;
    +
    +		tgt_devaddr = NULL;
    +	} else {
    +		tgt_devaddr = arpptr;
    +		arpptr += dev->addr_len;
    +	}
     	memcpy(&tgt_ipaddr, arpptr, sizeof(u32));
     
     	if (NF_INVF(arpinfo, ARPT_INV_SRCDEVADDR,
     		    arp_devaddr_compare(&arpinfo->src_devaddr, src_devaddr,
    -					dev->addr_len)) ||
    +					dev->addr_len)))
    +		return 0;
    +
    +	if (tgt_devaddr &&
     	    NF_INVF(arpinfo, ARPT_INV_TGTDEVADDR,
     		    arp_devaddr_compare(&arpinfo->tgt_devaddr, tgt_devaddr,
     					dev->addr_len)))
    
  • net/ipv4/netfilter/arpt_mangle.c+8 1 modified
    diff --git a/net/ipv4/netfilter/arpt_mangle.c b/net/ipv4/netfilter/arpt_mangle.c
    index a4e07e5e9c118d..f65dd339208e8a 100644
    --- a/net/ipv4/netfilter/arpt_mangle.c
    +++ b/net/ipv4/netfilter/arpt_mangle.c
    @@ -40,6 +40,10 @@ target(struct sk_buff *skb, const struct xt_action_param *par)
     	}
     	arpptr += pln;
     	if (mangle->flags & ARPT_MANGLE_TDEV) {
    +		if (unlikely(IS_ENABLED(CONFIG_FIREWIRE_NET) &&
    +			     skb->dev->type == ARPHRD_IEEE1394))
    +			return NF_DROP;
    +
     		if (ARPT_DEV_ADDR_LEN_MAX < hln ||
     		   (arpptr + hln > skb_tail_pointer(skb)))
     			return NF_DROP;
    @@ -47,6 +51,10 @@ target(struct sk_buff *skb, const struct xt_action_param *par)
     	}
     	arpptr += hln;
     	if (mangle->flags & ARPT_MANGLE_TIP) {
    +		if (unlikely(IS_ENABLED(CONFIG_FIREWIRE_NET) &&
    +			     skb->dev->type == ARPHRD_IEEE1394))
    +			return NF_DROP;
    +
     		if (ARPT_MANGLE_ADDR_LEN_MAX < pln ||
     		   (arpptr + pln > skb_tail_pointer(skb)))
     			return NF_DROP;
    -- 
    cgit 1.3-korg
    
    
    
ad9973df8e0e

netfilter: arp_tables: fix IEEE1394 ARP payload parsing

2 files changed · +23 4
  • net/ipv4/netfilter/arp_tables.c+15 3 modified
    diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
    index 14365b20f1c5c0..564054123772a1 100644
    --- a/net/ipv4/netfilter/arp_tables.c
    +++ b/net/ipv4/netfilter/arp_tables.c
    @@ -110,13 +110,25 @@ static inline int arp_packet_match(const struct arphdr *arphdr,
     	arpptr += dev->addr_len;
     	memcpy(&src_ipaddr, arpptr, sizeof(u32));
     	arpptr += sizeof(u32);
    -	tgt_devaddr = arpptr;
    -	arpptr += dev->addr_len;
    +
    +	if (IS_ENABLED(CONFIG_FIREWIRE_NET) && dev->type == ARPHRD_IEEE1394) {
    +		if (unlikely(memchr_inv(arpinfo->tgt_devaddr.mask, 0,
    +					sizeof(arpinfo->tgt_devaddr.mask))))
    +			return 0;
    +
    +		tgt_devaddr = NULL;
    +	} else {
    +		tgt_devaddr = arpptr;
    +		arpptr += dev->addr_len;
    +	}
     	memcpy(&tgt_ipaddr, arpptr, sizeof(u32));
     
     	if (NF_INVF(arpinfo, ARPT_INV_SRCDEVADDR,
     		    arp_devaddr_compare(&arpinfo->src_devaddr, src_devaddr,
    -					dev->addr_len)) ||
    +					dev->addr_len)))
    +		return 0;
    +
    +	if (tgt_devaddr &&
     	    NF_INVF(arpinfo, ARPT_INV_TGTDEVADDR,
     		    arp_devaddr_compare(&arpinfo->tgt_devaddr, tgt_devaddr,
     					dev->addr_len)))
    
  • net/ipv4/netfilter/arpt_mangle.c+8 1 modified
    diff --git a/net/ipv4/netfilter/arpt_mangle.c b/net/ipv4/netfilter/arpt_mangle.c
    index a4e07e5e9c118d..f65dd339208e8a 100644
    --- a/net/ipv4/netfilter/arpt_mangle.c
    +++ b/net/ipv4/netfilter/arpt_mangle.c
    @@ -40,6 +40,10 @@ target(struct sk_buff *skb, const struct xt_action_param *par)
     	}
     	arpptr += pln;
     	if (mangle->flags & ARPT_MANGLE_TDEV) {
    +		if (unlikely(IS_ENABLED(CONFIG_FIREWIRE_NET) &&
    +			     skb->dev->type == ARPHRD_IEEE1394))
    +			return NF_DROP;
    +
     		if (ARPT_DEV_ADDR_LEN_MAX < hln ||
     		   (arpptr + hln > skb_tail_pointer(skb)))
     			return NF_DROP;
    @@ -47,6 +51,10 @@ target(struct sk_buff *skb, const struct xt_action_param *par)
     	}
     	arpptr += hln;
     	if (mangle->flags & ARPT_MANGLE_TIP) {
    +		if (unlikely(IS_ENABLED(CONFIG_FIREWIRE_NET) &&
    +			     skb->dev->type == ARPHRD_IEEE1394))
    +			return NF_DROP;
    +
     		if (ARPT_MANGLE_ADDR_LEN_MAX < pln ||
     		   (arpptr + pln > skb_tail_pointer(skb)))
     			return NF_DROP;
    -- 
    cgit 1.3-korg
    
    
    
03ea11dbefaa

netfilter: arp_tables: fix IEEE1394 ARP payload parsing

2 files changed · +23 4
  • net/ipv4/netfilter/arp_tables.c+15 3 modified
    diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
    index 1cdd9c28ab2da4..97ead883e4a13b 100644
    --- a/net/ipv4/netfilter/arp_tables.c
    +++ b/net/ipv4/netfilter/arp_tables.c
    @@ -110,13 +110,25 @@ static inline int arp_packet_match(const struct arphdr *arphdr,
     	arpptr += dev->addr_len;
     	memcpy(&src_ipaddr, arpptr, sizeof(u32));
     	arpptr += sizeof(u32);
    -	tgt_devaddr = arpptr;
    -	arpptr += dev->addr_len;
    +
    +	if (IS_ENABLED(CONFIG_FIREWIRE_NET) && dev->type == ARPHRD_IEEE1394) {
    +		if (unlikely(memchr_inv(arpinfo->tgt_devaddr.mask, 0,
    +					sizeof(arpinfo->tgt_devaddr.mask))))
    +			return 0;
    +
    +		tgt_devaddr = NULL;
    +	} else {
    +		tgt_devaddr = arpptr;
    +		arpptr += dev->addr_len;
    +	}
     	memcpy(&tgt_ipaddr, arpptr, sizeof(u32));
     
     	if (NF_INVF(arpinfo, ARPT_INV_SRCDEVADDR,
     		    arp_devaddr_compare(&arpinfo->src_devaddr, src_devaddr,
    -					dev->addr_len)) ||
    +					dev->addr_len)))
    +		return 0;
    +
    +	if (tgt_devaddr &&
     	    NF_INVF(arpinfo, ARPT_INV_TGTDEVADDR,
     		    arp_devaddr_compare(&arpinfo->tgt_devaddr, tgt_devaddr,
     					dev->addr_len)))
    
  • net/ipv4/netfilter/arpt_mangle.c+8 1 modified
    diff --git a/net/ipv4/netfilter/arpt_mangle.c b/net/ipv4/netfilter/arpt_mangle.c
    index a4e07e5e9c118d..f65dd339208e8a 100644
    --- a/net/ipv4/netfilter/arpt_mangle.c
    +++ b/net/ipv4/netfilter/arpt_mangle.c
    @@ -40,6 +40,10 @@ target(struct sk_buff *skb, const struct xt_action_param *par)
     	}
     	arpptr += pln;
     	if (mangle->flags & ARPT_MANGLE_TDEV) {
    +		if (unlikely(IS_ENABLED(CONFIG_FIREWIRE_NET) &&
    +			     skb->dev->type == ARPHRD_IEEE1394))
    +			return NF_DROP;
    +
     		if (ARPT_DEV_ADDR_LEN_MAX < hln ||
     		   (arpptr + hln > skb_tail_pointer(skb)))
     			return NF_DROP;
    @@ -47,6 +51,10 @@ target(struct sk_buff *skb, const struct xt_action_param *par)
     	}
     	arpptr += hln;
     	if (mangle->flags & ARPT_MANGLE_TIP) {
    +		if (unlikely(IS_ENABLED(CONFIG_FIREWIRE_NET) &&
    +			     skb->dev->type == ARPHRD_IEEE1394))
    +			return NF_DROP;
    +
     		if (ARPT_MANGLE_ADDR_LEN_MAX < pln ||
     		   (arpptr + pln > skb_tail_pointer(skb)))
     			return NF_DROP;
    -- 
    cgit 1.3-korg
    
    
    

Vulnerability mechanics

Root cause

"Missing IEEE1394 ARP format detection in arp_packet_match() and arpt_mangle() causes out-of-bounds reads and incorrect pointer arithmetic when parsing ARP packets that omit the target hardware address field per RFC 2734."

Attack vector

An attacker on a network segment with an IEEE1394 (FireWire) interface can send specially crafted ARP packets that omit the target hardware address field, as permitted by RFC 2734. The `arp_packet_match()` function in arptables reads past the actual payload into garbage data when parsing the target hardware address and target IP address, causing filtering rules to match against incorrect bytes [patch_id=2654171]. This leads to incorrect filtering decisions — packets that should be accepted may be dropped and vice versa. Additionally, the `arpt_mangle` target miscalculates pointer offsets for the target IP address on IEEE1394 devices, causing packet corruption when mangling operations are applied [patch_id=2654171].

Affected code

The vulnerability resides in `net/ipv4/netfilter/arp_tables.c` in the `arp_packet_match()` function, and in `net/ipv4/netfilter/arpt_mangle.c` in the `target()` function. Both functions unconditionally assume a standard ARP layout with two hardware addresses (source and target), which is incorrect for IPv4-over-IEEE1394 (FireWire) ARP packets per RFC 2734 [patch_id=2654171].

What the fix does

The patch modifies `arp_packet_match()` in `arp_tables.c` to detect IEEE1394 devices (`dev->type == ARPHRD_IEEE1394`) and skip parsing the nonexistent target hardware address by setting `tgt_devaddr = NULL` [patch_id=2654171]. If a rule attempts to match on the target hardware address (non-zero mask), the function returns 0 (no match) for both normal and inverse matches, since that field is never present in IEEE1394 ARP. The target hardware address comparison is also guarded by a `if (tgt_devaddr &&)` check. In `arpt_mangle.c`, the patch adds early `NF_DROP` returns when mangling the target device address (`ARPT_MANGLE_TDEV`) or target IP address (`ARPT_MANGLE_TIP`) on IEEE1394 devices, preventing packet corruption from incorrect pointer arithmetic [patch_id=2654171].

Preconditions

  • configThe system must have a network interface of type ARPHRD_IEEE1394 (FireWire) and the CONFIG_FIREWIRE_NET kernel option enabled.
  • networkThe attacker must be able to send ARP packets on the same network segment as the target IEEE1394 interface.
  • configarptables rules must be loaded that match on the target hardware address or target IP address, or that use the arpt_mangle target on those fields.

Generated on May 27, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

5

News mentions

0

No linked articles in our index yet.