3.0-stable review patch.  If anyone has any objections, please let us know.

------------------


From: "David S. Miller" <da...@davemloft.net>

[ Upstream commit 415b3334a21aa67806c52d1acf4e72e14f7f402f ]

icmp_route_lookup() uses the wrong flow parameters if the reverse
session route lookup isn't used.

So do not commit to the re-decoded flow until we actually make a
final decision to use a real route saved in 'rt2'.

Reported-by: Florian Westphal <f...@strlen.de>
Signed-off-by: David S. Miller <da...@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gre...@suse.de>
---
 net/ipv4/icmp.c |   14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -380,6 +380,7 @@ static struct rtable *icmp_route_lookup(
                                        struct icmp_bxm *param)
 {
        struct rtable *rt, *rt2;
+       struct flowi4 fl4_dec;
        int err;
 
        memset(fl4, 0, sizeof(*fl4));
@@ -408,19 +409,19 @@ static struct rtable *icmp_route_lookup(
        } else
                return rt;
 
-       err = xfrm_decode_session_reverse(skb_in, flowi4_to_flowi(fl4), 
AF_INET);
+       err = xfrm_decode_session_reverse(skb_in, flowi4_to_flowi(&fl4_dec), 
AF_INET);
        if (err)
                goto relookup_failed;
 
-       if (inet_addr_type(net, fl4->saddr) == RTN_LOCAL) {
-               rt2 = __ip_route_output_key(net, fl4);
+       if (inet_addr_type(net, fl4_dec.saddr) == RTN_LOCAL) {
+               rt2 = __ip_route_output_key(net, &fl4_dec);
                if (IS_ERR(rt2))
                        err = PTR_ERR(rt2);
        } else {
                struct flowi4 fl4_2 = {};
                unsigned long orefdst;
 
-               fl4_2.daddr = fl4->saddr;
+               fl4_2.daddr = fl4_dec.saddr;
                rt2 = ip_route_output_key(net, &fl4_2);
                if (IS_ERR(rt2)) {
                        err = PTR_ERR(rt2);
@@ -428,7 +429,7 @@ static struct rtable *icmp_route_lookup(
                }
                /* Ugh! */
                orefdst = skb_in->_skb_refdst; /* save old refdst */
-               err = ip_route_input(skb_in, fl4->daddr, fl4->saddr,
+               err = ip_route_input(skb_in, fl4_dec.daddr, fl4_dec.saddr,
                                     RT_TOS(tos), rt2->dst.dev);
 
                dst_release(&rt2->dst);
@@ -440,10 +441,11 @@ static struct rtable *icmp_route_lookup(
                goto relookup_failed;
 
        rt2 = (struct rtable *) xfrm_lookup(net, &rt2->dst,
-                                           flowi4_to_flowi(fl4), NULL,
+                                           flowi4_to_flowi(&fl4_dec), NULL,
                                            XFRM_LOOKUP_ICMP);
        if (!IS_ERR(rt2)) {
                dst_release(&rt->dst);
+               memcpy(fl4, &fl4_dec, sizeof(*fl4));
                rt = rt2;
        } else if (PTR_ERR(rt2) == -EPERM) {
                if (rt)


_______________________________________________
stable mailing list
stable@linux.kernel.org
http://linux.kernel.org/mailman/listinfo/stable

Reply via email to