xfrm4: Reload skb header pointers after calling pskb_may_pull. [Linux 3.16.72]

This Linux kernel change "xfrm4: Reload skb header pointers after calling pskb_may_pull" is included in the Linux 3.16.72 release. This change is authored by Steffen Klassert <steffen.klassert [at] secunet.com> on Fri Oct 23 07:32:39 2015 +0200. The commit for this change in Linux stable tree is 8e9ba7f (patch) which is from upstream commit ea673a4. The same Linux upstream change may have been applied to various maintained Linux releases and you can find all Linux releases containing changes from upstream ea673a4.

xfrm4: Reload skb header pointers after calling pskb_may_pull.

commit ea673a4d3a337184f3c314dcc6300bf02f39e077 upstream.

A call to pskb_may_pull may change the pointers into the packet,
so reload the pointers after the call.

Signed-off-by: Steffen Klassert <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>

There are 33 lines of Linux source code added/deleted in this change. Code changes to Linux kernel are as follows.

 net/ipv4/xfrm4_policy.c | 33 ++++++++++++++++++++++++++-------
 1 file changed, 26 insertions(+), 7 deletions(-)

diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
index ff96243..08e45c3 100644
--- a/net/ipv4/xfrm4_policy.c
+++ b/net/ipv4/xfrm4_policy.c
@@ -123,7 +123,10 @@ static int xfrm4_fill_dst(struct xfrm_dst *xdst, struct net_device *dev,
        case IPPROTO_DCCP:
            if (xprth + 4 < skb->data ||
                pskb_may_pull(skb, xprth + 4 - skb->data)) {
-               __be16 *ports = (__be16 *)xprth;
+               __be16 *ports;
+
+               xprth = skb_network_header(skb) + iph->ihl * 4;
+               ports = (__be16 *)xprth;

                fl4->fl4_sport = ports[!!reverse];
                fl4->fl4_dport = ports[!reverse];
@@ -133,7 +136,10 @@ static int xfrm4_fill_dst(struct xfrm_dst *xdst, struct net_device *dev,
        case IPPROTO_ICMP:
            if (xprth + 2 < skb->data ||
                pskb_may_pull(skb, xprth + 2 - skb->data)) {
-               u8 *icmp = xprth;
+               u8 *icmp;
+
+               xprth = skb_network_header(skb) + iph->ihl * 4;
+               icmp = xprth;

                fl4->fl4_icmp_type = icmp[0];
                fl4->fl4_icmp_code = icmp[1];
@@ -143,7 +149,10 @@ static int xfrm4_fill_dst(struct xfrm_dst *xdst, struct net_device *dev,
        case IPPROTO_ESP:
            if (xprth + 4 < skb->data ||
                pskb_may_pull(skb, xprth + 4 - skb->data)) {
-               __be32 *ehdr = (__be32 *)xprth;
+               __be32 *ehdr;
+
+               xprth = skb_network_header(skb) + iph->ihl * 4;
+               ehdr = (__be32 *)xprth;

                fl4->fl4_ipsec_spi = ehdr[0];
            }
@@ -152,7 +161,10 @@ static int xfrm4_fill_dst(struct xfrm_dst *xdst, struct net_device *dev,
        case IPPROTO_AH:
            if (xprth + 8 < skb->data ||
                pskb_may_pull(skb, xprth + 8 - skb->data)) {
-               __be32 *ah_hdr = (__be32 *)xprth;
+               __be32 *ah_hdr;
+
+               xprth = skb_network_header(skb) + iph->ihl * 4;
+               ah_hdr = (__be32 *)xprth;

                fl4->fl4_ipsec_spi = ah_hdr[1];
            }
@@ -161,7 +173,10 @@ static int xfrm4_fill_dst(struct xfrm_dst *xdst, struct net_device *dev,
        case IPPROTO_COMP:
            if (xprth + 4 < skb->data ||
                pskb_may_pull(skb, xprth + 4 - skb->data)) {
-               __be16 *ipcomp_hdr = (__be16 *)xprth;
+               __be16 *ipcomp_hdr;
+
+               xprth = skb_network_header(skb) + iph->ihl * 4;
+               ipcomp_hdr = (__be16 *)xprth;

                fl4->fl4_ipsec_spi = htonl(ntohs(ipcomp_hdr[1]));
            }
@@ -170,8 +185,12 @@ static int xfrm4_fill_dst(struct xfrm_dst *xdst, struct net_device *dev,
        case IPPROTO_GRE:
            if (xprth + 12 < skb->data ||
                pskb_may_pull(skb, xprth + 12 - skb->data)) {
-               __be16 *greflags = (__be16 *)xprth;
-               __be32 *gre_hdr = (__be32 *)xprth;
+               __be16 *greflags;
+               __be32 *gre_hdr;
+
+               xprth = skb_network_header(skb) + iph->ihl * 4;
+               greflags = (__be16 *)xprth;
+               gre_hdr = (__be32 *)xprth;

                if (greflags[0] & GRE_KEY) {
                    if (greflags[0] & GRE_CSUM)

Leave a Reply

Your email address will not be published. Required fields are marked *