[Devel,RHEL7,COMMIT] venet: ipX_forward headroom check

Submitted by Konstantin Khorenko on July 17, 2017, 2:56 p.m.

Details

Message ID 201707171456.v6HEuDIk013964@finist_cl7.x64_64.work.ct
State New
Series "venet: ipX_forward headroom check"
Headers show

Commit Message

Konstantin Khorenko July 17, 2017, 2:56 p.m.
The commit is pushed to "branch-rh7-3.10.0-514.26.1.vz7.33.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-514.26.1.vz7.33.8
------>
commit 9a05b36b74f00f920b750511e6fbf87a3d6e9324
Author: Vasily Averin <vvs@virtuozzo.com>
Date:   Mon Jul 17 18:56:13 2017 +0400

    venet: ipX_forward headroom check
    
    skb from virtual (NETIF_F_VENET) devices do not call skb_cow() in ip[6]_forward.
    As result such skb can lack space for eth header, it can trigger skb_under_panic
    and crash the host.
    
    https://jira.sw.ru/browse/PSBM-68362
    
    Signed-off-by:	Vasily Averin <vvs@virtuozzo.com>
---
 net/ipv4/ip_forward.c | 10 ++++++----
 net/ipv6/ip6_output.c |  8 +++++---
 2 files changed, 11 insertions(+), 7 deletions(-)

Patch hide | download patch | download mbox

diff --git a/net/ipv4/ip_forward.c b/net/ipv4/ip_forward.c
index 17bbdd8..556792c 100644
--- a/net/ipv4/ip_forward.c
+++ b/net/ipv4/ip_forward.c
@@ -75,6 +75,7 @@  int ip_forward(struct sk_buff *skb)
 	struct iphdr *iph;	/* Our header */
 	struct rtable *rt;	/* Route we use */
 	struct ip_options *opt	= &(IPCB(skb)->opt);
+	unsigned int hroom;
 
 	if (skb_warn_if_lro(skb))
 		goto drop;
@@ -125,16 +126,17 @@  int ip_forward(struct sk_buff *skb)
 	 * in pkts path with mandatory ttl decr, that is
 	 * sufficient to prevent routing loops.
 	 */
-	iph = ip_hdr(skb);
+	hroom = LL_RESERVED_SPACE(rt->dst.dev)+rt->dst.header_len;
 	if (
-#ifdef CONFIG_IP_ROUTE_NAT			
+#ifdef CONFIG_IP_ROUTE_NAT
 	    (rt->rt_flags & RTCF_NAT) == 0 &&	  /* no NAT mangling expected */
 #endif						  /* and */
-	    (skb->dev->features & NETIF_F_VENET)) /* src is VENET device */
+	    (skb->dev->features & NETIF_F_VENET) && /* src is VENET device and */
+	    (skb_headroom(skb) >= hroom))	 /* skb has enough headroom */
 		goto no_ttl_decr;
 
 	/* We are about to mangle packet. Copy it! */
-	if (skb_cow(skb, LL_RESERVED_SPACE(rt->dst.dev)+rt->dst.header_len))
+	if (skb_cow(skb, hroom))
 		goto drop;
 	iph = ip_hdr(skb);
 
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 11e64fb..d569fa5 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -346,6 +346,7 @@  int ip6_forward(struct sk_buff *skb)
 	struct ipv6hdr *hdr = ipv6_hdr(skb);
 	struct inet6_skb_parm *opt = IP6CB(skb);
 	struct net *net = dev_net(dst->dev);
+	unsigned int hroom;
 	u32 mtu;
 
 	if (net->ipv6.devconf_all->forwarding == 0)
@@ -487,11 +488,12 @@  int ip6_forward(struct sk_buff *skb)
 	 * in pkts path with mandatory ttl decr, that is
 	 * sufficient to prevent routing loops.
 	 */
-	hdr = ipv6_hdr(skb);
-	if (skb->dev->features & NETIF_F_VENET) /* src is VENET device */
+	hroom = dst->dev->hard_header_len;
+	if ((skb->dev->features & NETIF_F_VENET) && /* src is VENET device */
+	    (skb_headroom(skb) >= hroom))  /* and skb has enough headroom */
 		goto no_ttl_decr;
 
-	if (skb_cow(skb, dst->dev->hard_header_len)) {
+	if (skb_cow(skb, hroom)) {
 		IP6_INC_STATS(net, ip6_dst_idev(dst), IPSTATS_MIB_OUTDISCARDS);
 		goto drop;
 	}

Comments

Konstantin Khorenko July 17, 2017, 2:57 p.m.
Please consider to prepare a ReadyKernel patch for it.

https://readykernel.com/

--
Best regards,

Konstantin Khorenko,
Virtuozzo Linux Kernel Team

On 07/17/2017 05:56 PM, Konstantin Khorenko wrote:
> The commit is pushed to "branch-rh7-3.10.0-514.26.1.vz7.33.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
> after rh7-3.10.0-514.26.1.vz7.33.8
> ------>
> commit 9a05b36b74f00f920b750511e6fbf87a3d6e9324
> Author: Vasily Averin <vvs@virtuozzo.com>
> Date:   Mon Jul 17 18:56:13 2017 +0400
>
>     venet: ipX_forward headroom check
>
>     skb from virtual (NETIF_F_VENET) devices do not call skb_cow() in ip[6]_forward.
>     As result such skb can lack space for eth header, it can trigger skb_under_panic
>     and crash the host.
>
>     https://jira.sw.ru/browse/PSBM-68362
>
>     Signed-off-by:	Vasily Averin <vvs@virtuozzo.com>
> ---
>  net/ipv4/ip_forward.c | 10 ++++++----
>  net/ipv6/ip6_output.c |  8 +++++---
>  2 files changed, 11 insertions(+), 7 deletions(-)
>
> diff --git a/net/ipv4/ip_forward.c b/net/ipv4/ip_forward.c
> index 17bbdd8..556792c 100644
> --- a/net/ipv4/ip_forward.c
> +++ b/net/ipv4/ip_forward.c
> @@ -75,6 +75,7 @@ int ip_forward(struct sk_buff *skb)
>  	struct iphdr *iph;	/* Our header */
>  	struct rtable *rt;	/* Route we use */
>  	struct ip_options *opt	= &(IPCB(skb)->opt);
> +	unsigned int hroom;
>
>  	if (skb_warn_if_lro(skb))
>  		goto drop;
> @@ -125,16 +126,17 @@ int ip_forward(struct sk_buff *skb)
>  	 * in pkts path with mandatory ttl decr, that is
>  	 * sufficient to prevent routing loops.
>  	 */
> -	iph = ip_hdr(skb);
> +	hroom = LL_RESERVED_SPACE(rt->dst.dev)+rt->dst.header_len;
>  	if (
> -#ifdef CONFIG_IP_ROUTE_NAT			
> +#ifdef CONFIG_IP_ROUTE_NAT
>  	    (rt->rt_flags & RTCF_NAT) == 0 &&	  /* no NAT mangling expected */
>  #endif						  /* and */
> -	    (skb->dev->features & NETIF_F_VENET)) /* src is VENET device */
> +	    (skb->dev->features & NETIF_F_VENET) && /* src is VENET device and */
> +	    (skb_headroom(skb) >= hroom))	 /* skb has enough headroom */
>  		goto no_ttl_decr;
>
>  	/* We are about to mangle packet. Copy it! */
> -	if (skb_cow(skb, LL_RESERVED_SPACE(rt->dst.dev)+rt->dst.header_len))
> +	if (skb_cow(skb, hroom))
>  		goto drop;
>  	iph = ip_hdr(skb);
>
> diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
> index 11e64fb..d569fa5 100644
> --- a/net/ipv6/ip6_output.c
> +++ b/net/ipv6/ip6_output.c
> @@ -346,6 +346,7 @@ int ip6_forward(struct sk_buff *skb)
>  	struct ipv6hdr *hdr = ipv6_hdr(skb);
>  	struct inet6_skb_parm *opt = IP6CB(skb);
>  	struct net *net = dev_net(dst->dev);
> +	unsigned int hroom;
>  	u32 mtu;
>
>  	if (net->ipv6.devconf_all->forwarding == 0)
> @@ -487,11 +488,12 @@ int ip6_forward(struct sk_buff *skb)
>  	 * in pkts path with mandatory ttl decr, that is
>  	 * sufficient to prevent routing loops.
>  	 */
> -	hdr = ipv6_hdr(skb);
> -	if (skb->dev->features & NETIF_F_VENET) /* src is VENET device */
> +	hroom = dst->dev->hard_header_len;
> +	if ((skb->dev->features & NETIF_F_VENET) && /* src is VENET device */
> +	    (skb_headroom(skb) >= hroom))  /* and skb has enough headroom */
>  		goto no_ttl_decr;
>
> -	if (skb_cow(skb, dst->dev->hard_header_len)) {
> +	if (skb_cow(skb, hroom)) {
>  		IP6_INC_STATS(net, ip6_dst_idev(dst), IPSTATS_MIB_OUTDISCARDS);
>  		goto drop;
>  	}
> .
>