Re: [net-next v3] vxlan: fix ND proxy when skb doesn't have transport header offset

2017-04-01 Thread kbuild test robot
Hi Vincent,

[auto build test WARNING on net-next/master]

url:
https://github.com/0day-ci/linux/commits/Vincent-Bernat/vxlan-fix-ND-proxy-when-skb-doesn-t-have-transport-header-offset/20170401-182312
config: x86_64-randconfig-v0-04020359 (attached as .config)
compiler: gcc-4.4 (Debian 4.4.7-8) 4.4.7
reproduce:
# save the attached .config to linux build tree
make ARCH=x86_64 

All warnings (new ones prefixed by >>):

   drivers//net/vxlan.c: In function 'vxlan_xmit':
>> drivers//net/vxlan.c:2245: warning: unused variable '_hdr'
>> drivers//net/vxlan.c:2245: warning: unused variable 'hdr'

vim +/_hdr +2245 drivers//net/vxlan.c

  2229  skb_reset_mac_header(skb);
  2230  
  2231  if (vxlan->flags & VXLAN_F_COLLECT_METADATA) {
  2232  if (info && info->mode & IP_TUNNEL_INFO_BRIDGE &&
  2233  info->mode & IP_TUNNEL_INFO_TX) {
  2234  vni = tunnel_id_to_key32(info->key.tun_id);
  2235  } else {
  2236  if (info && info->mode & IP_TUNNEL_INFO_TX)
  2237  vxlan_xmit_one(skb, dev, vni, NULL, 
false);
  2238  else
  2239  kfree_skb(skb);
  2240  return NETDEV_TX_OK;
  2241  }
  2242  }
  2243  
  2244  if (vxlan->flags & VXLAN_F_PROXY) {
> 2245  struct ipv6hdr *hdr, _hdr;
  2246  eth = eth_hdr(skb);
  2247  if (ntohs(eth->h_proto) == ETH_P_ARP)
  2248  return arp_reduce(dev, skb, vni);
  2249  #if IS_ENABLED(CONFIG_IPV6)
  2250  else if (ntohs(eth->h_proto) == ETH_P_IPV6 &&
  2251   (hdr = skb_header_pointer(skb,
  2252 
skb_network_offset(skb),
  2253 sizeof(_hdr), 
&_hdr)) &&

---
0-DAY kernel test infrastructureOpen Source Technology Center
https://lists.01.org/pipermail/kbuild-all   Intel Corporation


.config.gz
Description: application/gzip


[net-next v3] vxlan: fix ND proxy when skb doesn't have transport header offset

2017-03-31 Thread Vincent Bernat
When an incoming frame is tagged or when GRO is disabled, the skb
handled to vxlan_xmit() doesn't contain a valid transport header
offset. This makes ND proxying fail.

We combine two changes: replace use of skb_transport_offset() and ensure
the necessary amount of skb is linear just before using it:

 - In vxlan_xmit(), when determining if we have an ICMPv6 neighbor
   discovery packet, just check if it is an ICMPv6 packet and rely on
   neigh_reduce() to do more checks if this is the case. The use of
   pskb_may_pull() is replaced by skb_header_pointer() for just the IPv6
   header.

 - In neigh_reduce(), add pskb_may_pull() for IPv6 header and neighbor
   discovery message since this was removed from vxlan_xmit(). Replace
   skb_transport_header() with ipv6_hdr() + 1.

 - In vxlan_na_create(), replace first skb_transport_offset() with
   ipv6_hdr() + 1 and second with skb_network_offset() + sizeof(struct
   ipv6hdr). Additionally, ensure we pskb_may_pull() the whole skb as we
   need it to iterate over the options.

Signed-off-by: Vincent Bernat 
---
 drivers/net/vxlan.c | 28 ++--
 1 file changed, 14 insertions(+), 14 deletions(-)

diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index 1e54fb5c883a..54dda367de2b 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -1515,7 +1515,7 @@ static struct sk_buff *vxlan_na_create(struct sk_buff 
*request,
int ns_olen;
int i, len;
 
-   if (dev == NULL)
+   if (dev == NULL || !pskb_may_pull(request, request->len))
return NULL;
 
len = LL_RESERVED_SPACE(dev) + sizeof(struct ipv6hdr) +
@@ -1530,10 +1530,11 @@ static struct sk_buff *vxlan_na_create(struct sk_buff 
*request,
skb_push(reply, sizeof(struct ethhdr));
skb_reset_mac_header(reply);
 
-   ns = (struct nd_msg *)skb_transport_header(request);
+   ns = (struct nd_msg *)(ipv6_hdr(request) + 1);
 
daddr = eth_hdr(request)->h_source;
-   ns_olen = request->len - skb_transport_offset(request) - sizeof(*ns);
+   ns_olen = request->len - skb_network_offset(request) -
+   sizeof(struct ipv6hdr) - sizeof(*ns);
for (i = 0; i < ns_olen-1; i += (ns->opt[i+1]<<3)) {
if (ns->opt[i] == ND_OPT_SOURCE_LL_ADDR) {
daddr = ns->opt + i + sizeof(struct nd_opt_hdr);
@@ -1604,10 +1605,13 @@ static int neigh_reduce(struct net_device *dev, struct 
sk_buff *skb, __be32 vni)
if (!in6_dev)
goto out;
 
+   if (!pskb_may_pull(skb, sizeof(struct ipv6hdr) + sizeof(struct nd_msg)))
+   goto out;
+
iphdr = ipv6_hdr(skb);
daddr = >daddr;
 
-   msg = (struct nd_msg *)skb_transport_header(skb);
+   msg = (struct nd_msg *)(iphdr + 1);
if (msg->icmph.icmp6_code != 0 ||
msg->icmph.icmp6_type != NDISC_NEIGHBOUR_SOLICITATION)
goto out;
@@ -2238,21 +2242,17 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, 
struct net_device *dev)
}
 
if (vxlan->flags & VXLAN_F_PROXY) {
+   struct ipv6hdr *hdr, _hdr;
eth = eth_hdr(skb);
if (ntohs(eth->h_proto) == ETH_P_ARP)
return arp_reduce(dev, skb, vni);
 #if IS_ENABLED(CONFIG_IPV6)
else if (ntohs(eth->h_proto) == ETH_P_IPV6 &&
-pskb_may_pull(skb, sizeof(struct ipv6hdr)
-  + sizeof(struct nd_msg)) &&
-ipv6_hdr(skb)->nexthdr == IPPROTO_ICMPV6) {
-   struct nd_msg *msg;
-
-   msg = (struct nd_msg 
*)skb_transport_header(skb);
-   if (msg->icmph.icmp6_code == 0 &&
-   msg->icmph.icmp6_type == 
NDISC_NEIGHBOUR_SOLICITATION)
-   return neigh_reduce(dev, skb, vni);
-   }
+(hdr = skb_header_pointer(skb,
+  skb_network_offset(skb),
+  sizeof(_hdr), &_hdr)) &&
+hdr->nexthdr == IPPROTO_ICMPV6)
+   return neigh_reduce(dev, skb, vni);
 #endif
}
 
-- 
2.11.0