]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
netfilter: require Ethernet MAC header before using eth_hdr()
authorZhengchuan Liang <zcliangcn@gmail.com>
Sat, 4 Apr 2026 09:39:48 +0000 (17:39 +0800)
committerFlorian Westphal <fw@strlen.de>
Fri, 10 Apr 2026 10:16:27 +0000 (12:16 +0200)
`ip6t_eui64`, `xt_mac`, the `bitmap:ip,mac`, `hash:ip,mac`, and
`hash:mac` ipset types, and `nf_log_syslog` access `eth_hdr(skb)`
after either assuming that the skb is associated with an Ethernet
device or checking only that the `ETH_HLEN` bytes at
`skb_mac_header(skb)` lie between `skb->head` and `skb->data`.

Make these paths first verify that the skb is associated with an
Ethernet device, that the MAC header was set, and that it spans at
least a full Ethernet header before accessing `eth_hdr(skb)`.

Suggested-by: Florian Westphal <fw@strlen.de>
Tested-by: Ren Wei <enjou1224z@gmail.com>
Signed-off-by: Zhengchuan Liang <zcliangcn@gmail.com>
Signed-off-by: Ren Wei <n05ec@lzu.edu.cn>
Signed-off-by: Florian Westphal <fw@strlen.de>
net/ipv6/netfilter/ip6t_eui64.c
net/netfilter/ipset/ip_set_bitmap_ipmac.c
net/netfilter/ipset/ip_set_hash_ipmac.c
net/netfilter/ipset/ip_set_hash_mac.c
net/netfilter/nf_log_syslog.c
net/netfilter/xt_mac.c

index da69a27e8332c13e0a54014f6913a7c617cc09fa..bbb684f9964c03d53239bedc412a03f45efac5c3 100644 (file)
@@ -7,6 +7,7 @@
 #include <linux/module.h>
 #include <linux/skbuff.h>
 #include <linux/ipv6.h>
+#include <linux/if_arp.h>
 #include <linux/if_ether.h>
 
 #include <linux/netfilter/x_tables.h>
@@ -21,8 +22,10 @@ eui64_mt6(const struct sk_buff *skb, struct xt_action_param *par)
 {
        unsigned char eui64[8];
 
-       if (!(skb_mac_header(skb) >= skb->head &&
-             skb_mac_header(skb) + ETH_HLEN <= skb->data)) {
+       if (!skb->dev || skb->dev->type != ARPHRD_ETHER)
+               return false;
+
+       if (!skb_mac_header_was_set(skb) || skb_mac_header_len(skb) < ETH_HLEN) {
                par->hotdrop = true;
                return false;
        }
index 2c625e0f49ec020581206445b3365663d9c19746..752f59ef8744296090c3680175a321826391be56 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/errno.h>
+#include <linux/if_arp.h>
 #include <linux/if_ether.h>
 #include <linux/netlink.h>
 #include <linux/jiffies.h>
@@ -220,8 +221,8 @@ bitmap_ipmac_kadt(struct ip_set *set, const struct sk_buff *skb,
                return -IPSET_ERR_BITMAP_RANGE;
 
        /* Backward compatibility: we don't check the second flag */
-       if (skb_mac_header(skb) < skb->head ||
-           (skb_mac_header(skb) + ETH_HLEN) > skb->data)
+       if (!skb->dev || skb->dev->type != ARPHRD_ETHER ||
+           !skb_mac_header_was_set(skb) || skb_mac_header_len(skb) < ETH_HLEN)
                return -EINVAL;
 
        e.id = ip_to_id(map, ip);
index 467c59a83c0abc5e6740dc617a1d906fdae3eb41..b9a2681e248881690141af4ceaee94dfa4f8e5ab 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/skbuff.h>
 #include <linux/errno.h>
 #include <linux/random.h>
+#include <linux/if_arp.h>
 #include <linux/if_ether.h>
 #include <net/ip.h>
 #include <net/ipv6.h>
@@ -89,8 +90,8 @@ hash_ipmac4_kadt(struct ip_set *set, const struct sk_buff *skb,
        struct hash_ipmac4_elem e = { .ip = 0, { .foo[0] = 0, .foo[1] = 0 } };
        struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
 
-       if (skb_mac_header(skb) < skb->head ||
-           (skb_mac_header(skb) + ETH_HLEN) > skb->data)
+       if (!skb->dev || skb->dev->type != ARPHRD_ETHER ||
+           !skb_mac_header_was_set(skb) || skb_mac_header_len(skb) < ETH_HLEN)
                return -EINVAL;
 
        if (opt->flags & IPSET_DIM_TWO_SRC)
@@ -205,8 +206,8 @@ hash_ipmac6_kadt(struct ip_set *set, const struct sk_buff *skb,
        };
        struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
 
-       if (skb_mac_header(skb) < skb->head ||
-           (skb_mac_header(skb) + ETH_HLEN) > skb->data)
+       if (!skb->dev || skb->dev->type != ARPHRD_ETHER ||
+           !skb_mac_header_was_set(skb) || skb_mac_header_len(skb) < ETH_HLEN)
                return -EINVAL;
 
        if (opt->flags & IPSET_DIM_TWO_SRC)
index 718814730acf6bcdbc6c66f0af5a47569ea1b4ef..41a122591fe24dc964c2dae0b291e5a47df2371b 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/errno.h>
+#include <linux/if_arp.h>
 #include <linux/if_ether.h>
 #include <net/netlink.h>
 
@@ -77,8 +78,8 @@ hash_mac4_kadt(struct ip_set *set, const struct sk_buff *skb,
        struct hash_mac4_elem e = { { .foo[0] = 0, .foo[1] = 0 } };
        struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
 
-       if (skb_mac_header(skb) < skb->head ||
-           (skb_mac_header(skb) + ETH_HLEN) > skb->data)
+       if (!skb->dev || skb->dev->type != ARPHRD_ETHER ||
+           !skb_mac_header_was_set(skb) || skb_mac_header_len(skb) < ETH_HLEN)
                return -EINVAL;
 
        if (opt->flags & IPSET_DIM_ONE_SRC)
index 0507d67cad27530dd814aabaf806fdcd3583fe01..7a8952b049d10c26431dc04d5ebfab3f83f29ac9 100644 (file)
@@ -78,7 +78,10 @@ dump_arp_packet(struct nf_log_buf *m,
        else
                logflags = NF_LOG_DEFAULT_MASK;
 
-       if (logflags & NF_LOG_MACDECODE) {
+       if ((logflags & NF_LOG_MACDECODE) &&
+           skb->dev && skb->dev->type == ARPHRD_ETHER &&
+           skb_mac_header_was_set(skb) &&
+           skb_mac_header_len(skb) >= ETH_HLEN) {
                nf_log_buf_add(m, "MACSRC=%pM MACDST=%pM ",
                               eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest);
                nf_log_dump_vlan(m, skb);
@@ -797,6 +800,9 @@ static void dump_mac_header(struct nf_log_buf *m,
 
        switch (dev->type) {
        case ARPHRD_ETHER:
+               if (!skb_mac_header_was_set(skb) || skb_mac_header_len(skb) < ETH_HLEN)
+                       return;
+
                nf_log_buf_add(m, "MACSRC=%pM MACDST=%pM ",
                               eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest);
                nf_log_dump_vlan(m, skb);
index 81649da57ba5d38d704d69264a78b36e166d1a7e..4798cd2ca26ed5890dd7ca8afb4957307a183f4b 100644 (file)
@@ -29,9 +29,7 @@ static bool mac_mt(const struct sk_buff *skb, struct xt_action_param *par)
 
        if (skb->dev == NULL || skb->dev->type != ARPHRD_ETHER)
                return false;
-       if (skb_mac_header(skb) < skb->head)
-               return false;
-       if (skb_mac_header(skb) + ETH_HLEN > skb->data)
+       if (!skb_mac_header_was_set(skb) || skb_mac_header_len(skb) < ETH_HLEN)
                return false;
        ret  = ether_addr_equal(eth_hdr(skb)->h_source, info->srcaddr);
        ret ^= info->invert;