mirror of
https://github.com/torvalds/linux.git
synced 2026-04-18 06:44:00 -04:00
netfilter: require Ethernet MAC header before using eth_hdr()
`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>
This commit is contained in:
committed by
Florian Westphal
parent
1dfd95bdf4
commit
62443dc211
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user