Skip to content

Commit 9ed3380

Browse files
committed
Merge branch 'ipvlan-Fix-insufficient-skb-linear-check'
Gao Feng says: ==================== ipvlan: Fix insufficient skb linear check The current ipvlan codes use pskb_may_pull to get the skb linear header in func ipvlan_get_L3_hdr, but the size isn't enough for arp and ipv6 icmp. So it may access the unexpected momory in ipvlan_addr_lookup. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
2 parents f9094b7 + 747a713 commit 9ed3380

File tree

1 file changed

+27
-9
lines changed

1 file changed

+27
-9
lines changed

drivers/net/ipvlan/ipvlan_core.c

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -116,15 +116,15 @@ bool ipvlan_addr_busy(struct ipvl_port *port, void *iaddr, bool is_v6)
116116
return false;
117117
}
118118

119-
static void *ipvlan_get_L3_hdr(struct sk_buff *skb, int *type)
119+
static void *ipvlan_get_L3_hdr(struct ipvl_port *port, struct sk_buff *skb, int *type)
120120
{
121121
void *lyr3h = NULL;
122122

123123
switch (skb->protocol) {
124124
case htons(ETH_P_ARP): {
125125
struct arphdr *arph;
126126

127-
if (unlikely(!pskb_may_pull(skb, sizeof(*arph))))
127+
if (unlikely(!pskb_may_pull(skb, arp_hdr_len(port->dev))))
128128
return NULL;
129129

130130
arph = arp_hdr(skb);
@@ -165,8 +165,26 @@ static void *ipvlan_get_L3_hdr(struct sk_buff *skb, int *type)
165165
/* Only Neighbour Solicitation pkts need different treatment */
166166
if (ipv6_addr_any(&ip6h->saddr) &&
167167
ip6h->nexthdr == NEXTHDR_ICMP) {
168+
struct icmp6hdr *icmph;
169+
170+
if (unlikely(!pskb_may_pull(skb, sizeof(*ip6h) + sizeof(*icmph))))
171+
return NULL;
172+
173+
ip6h = ipv6_hdr(skb);
174+
icmph = (struct icmp6hdr *)(ip6h + 1);
175+
176+
if (icmph->icmp6_type == NDISC_NEIGHBOUR_SOLICITATION) {
177+
/* Need to access the ipv6 address in body */
178+
if (unlikely(!pskb_may_pull(skb, sizeof(*ip6h) + sizeof(*icmph)
179+
+ sizeof(struct in6_addr))))
180+
return NULL;
181+
182+
ip6h = ipv6_hdr(skb);
183+
icmph = (struct icmp6hdr *)(ip6h + 1);
184+
}
185+
168186
*type = IPVL_ICMPV6;
169-
lyr3h = ip6h + 1;
187+
lyr3h = icmph;
170188
}
171189
break;
172190
}
@@ -510,7 +528,7 @@ static int ipvlan_xmit_mode_l3(struct sk_buff *skb, struct net_device *dev)
510528
struct ipvl_addr *addr;
511529
int addr_type;
512530

513-
lyr3h = ipvlan_get_L3_hdr(skb, &addr_type);
531+
lyr3h = ipvlan_get_L3_hdr(ipvlan->port, skb, &addr_type);
514532
if (!lyr3h)
515533
goto out;
516534

@@ -539,7 +557,7 @@ static int ipvlan_xmit_mode_l2(struct sk_buff *skb, struct net_device *dev)
539557

540558
if (!ipvlan_is_vepa(ipvlan->port) &&
541559
ether_addr_equal(eth->h_dest, eth->h_source)) {
542-
lyr3h = ipvlan_get_L3_hdr(skb, &addr_type);
560+
lyr3h = ipvlan_get_L3_hdr(ipvlan->port, skb, &addr_type);
543561
if (lyr3h) {
544562
addr = ipvlan_addr_lookup(ipvlan->port, lyr3h, addr_type, true);
545563
if (addr) {
@@ -606,7 +624,7 @@ static bool ipvlan_external_frame(struct sk_buff *skb, struct ipvl_port *port)
606624
int addr_type;
607625

608626
if (ether_addr_equal(eth->h_source, skb->dev->dev_addr)) {
609-
lyr3h = ipvlan_get_L3_hdr(skb, &addr_type);
627+
lyr3h = ipvlan_get_L3_hdr(port, skb, &addr_type);
610628
if (!lyr3h)
611629
return true;
612630

@@ -627,7 +645,7 @@ static rx_handler_result_t ipvlan_handle_mode_l3(struct sk_buff **pskb,
627645
struct sk_buff *skb = *pskb;
628646
rx_handler_result_t ret = RX_HANDLER_PASS;
629647

630-
lyr3h = ipvlan_get_L3_hdr(skb, &addr_type);
648+
lyr3h = ipvlan_get_L3_hdr(port, skb, &addr_type);
631649
if (!lyr3h)
632650
goto out;
633651

@@ -666,7 +684,7 @@ static rx_handler_result_t ipvlan_handle_mode_l2(struct sk_buff **pskb,
666684
} else {
667685
struct ipvl_addr *addr;
668686

669-
lyr3h = ipvlan_get_L3_hdr(skb, &addr_type);
687+
lyr3h = ipvlan_get_L3_hdr(port, skb, &addr_type);
670688
if (!lyr3h)
671689
return ret;
672690

@@ -717,7 +735,7 @@ static struct ipvl_addr *ipvlan_skb_to_addr(struct sk_buff *skb,
717735
if (!port || port->mode != IPVLAN_MODE_L3S)
718736
goto out;
719737

720-
lyr3h = ipvlan_get_L3_hdr(skb, &addr_type);
738+
lyr3h = ipvlan_get_L3_hdr(port, skb, &addr_type);
721739
if (!lyr3h)
722740
goto out;
723741

0 commit comments

Comments
 (0)