Commit 415b3334a21aa67806c52d1acf4e72e14f7f402f

Authored by David S. Miller
1 parent ace62dd1a8

icmp: Fix regression in nexthop resolution during replies.

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 <fw@strlen.de>
Signed-off-by: David S. Miller <davem@davemloft.net>

Showing 1 changed file with 8 additions and 6 deletions Side-by-side Diff

... ... @@ -380,6 +380,7 @@
380 380 struct icmp_bxm *param)
381 381 {
382 382 struct rtable *rt, *rt2;
  383 + struct flowi4 fl4_dec;
383 384 int err;
384 385  
385 386 memset(fl4, 0, sizeof(*fl4));
386 387  
387 388  
... ... @@ -408,19 +409,19 @@
408 409 } else
409 410 return rt;
410 411  
411   - err = xfrm_decode_session_reverse(skb_in, flowi4_to_flowi(fl4), AF_INET);
  412 + err = xfrm_decode_session_reverse(skb_in, flowi4_to_flowi(&fl4_dec), AF_INET);
412 413 if (err)
413 414 goto relookup_failed;
414 415  
415   - if (inet_addr_type(net, fl4->saddr) == RTN_LOCAL) {
416   - rt2 = __ip_route_output_key(net, fl4);
  416 + if (inet_addr_type(net, fl4_dec.saddr) == RTN_LOCAL) {
  417 + rt2 = __ip_route_output_key(net, &fl4_dec);
417 418 if (IS_ERR(rt2))
418 419 err = PTR_ERR(rt2);
419 420 } else {
420 421 struct flowi4 fl4_2 = {};
421 422 unsigned long orefdst;
422 423  
423   - fl4_2.daddr = fl4->saddr;
  424 + fl4_2.daddr = fl4_dec.saddr;
424 425 rt2 = ip_route_output_key(net, &fl4_2);
425 426 if (IS_ERR(rt2)) {
426 427 err = PTR_ERR(rt2);
... ... @@ -428,7 +429,7 @@
428 429 }
429 430 /* Ugh! */
430 431 orefdst = skb_in->_skb_refdst; /* save old refdst */
431   - err = ip_route_input(skb_in, fl4->daddr, fl4->saddr,
  432 + err = ip_route_input(skb_in, fl4_dec.daddr, fl4_dec.saddr,
432 433 RT_TOS(tos), rt2->dst.dev);
433 434  
434 435 dst_release(&rt2->dst);
435 436  
... ... @@ -440,10 +441,11 @@
440 441 goto relookup_failed;
441 442  
442 443 rt2 = (struct rtable *) xfrm_lookup(net, &rt2->dst,
443   - flowi4_to_flowi(fl4), NULL,
  444 + flowi4_to_flowi(&fl4_dec), NULL,
444 445 XFRM_LOOKUP_ICMP);
445 446 if (!IS_ERR(rt2)) {
446 447 dst_release(&rt->dst);
  448 + memcpy(fl4, &fl4_dec, sizeof(*fl4));
447 449 rt = rt2;
448 450 } else if (PTR_ERR(rt2) == -EPERM) {
449 451 if (rt)