aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/icmp.c
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2008-04-03 15:52:19 -0400
committerDavid S. Miller <davem@davemloft.net>2008-04-03 15:52:19 -0400
commitaf2681828af5f2b42e12e8b16ba0cf113cf486c8 (patch)
treeed25908930ea98782ec7a13fd985c9825317a8b2 /net/ipv4/icmp.c
parent9597362d354f8655ece324b01d0c640a0e99c077 (diff)
[ICMP]: Ensure that ICMP relookup maintains status quo
The ICMP relookup path is only meant to modify behaviour when appropriate IPsec policies are in place and marked as requiring relookups. It is certainly not meant to modify behaviour when IPsec policies don't exist at all. However, due to an oversight on the error paths existing behaviour may in fact change should one of the relookup steps fail. This patch corrects this by redirecting all errors on relookup failures to the previous code path. That is, if the initial xfrm_lookup let the packet pass, we will stand by that decision should the relookup fail due to an error. This should be safe from a security point-of-view because compliant systems must install a default deny policy so the packet would'nt have passed in that case. Many thanks to Julian Anastasov for pointing out this error. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/icmp.c')
-rw-r--r--net/ipv4/icmp.c24
1 files changed, 13 insertions, 11 deletions
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index a944e8053e28..40508babad8c 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -591,7 +591,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
591 } 591 }
592 592
593 if (xfrm_decode_session_reverse(skb_in, &fl, AF_INET)) 593 if (xfrm_decode_session_reverse(skb_in, &fl, AF_INET))
594 goto ende; 594 goto relookup_failed;
595 595
596 if (inet_addr_type(net, fl.fl4_src) == RTN_LOCAL) 596 if (inet_addr_type(net, fl.fl4_src) == RTN_LOCAL)
597 err = __ip_route_output_key(net, &rt2, &fl); 597 err = __ip_route_output_key(net, &rt2, &fl);
@@ -601,7 +601,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
601 601
602 fl2.fl4_dst = fl.fl4_src; 602 fl2.fl4_dst = fl.fl4_src;
603 if (ip_route_output_key(net, &rt2, &fl2)) 603 if (ip_route_output_key(net, &rt2, &fl2))
604 goto ende; 604 goto relookup_failed;
605 605
606 /* Ugh! */ 606 /* Ugh! */
607 odst = skb_in->dst; 607 odst = skb_in->dst;
@@ -614,21 +614,23 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
614 } 614 }
615 615
616 if (err) 616 if (err)
617 goto ende; 617 goto relookup_failed;
618 618
619 err = xfrm_lookup((struct dst_entry **)&rt2, &fl, NULL, 619 err = xfrm_lookup((struct dst_entry **)&rt2, &fl, NULL,
620 XFRM_LOOKUP_ICMP); 620 XFRM_LOOKUP_ICMP);
621 if (err == -ENOENT) { 621 switch (err) {
622 case 0:
623 dst_release(&rt->u.dst);
624 rt = rt2;
625 break;
626 case -EPERM:
627 goto ende;
628 default:
629relookup_failed:
622 if (!rt) 630 if (!rt)
623 goto out_unlock; 631 goto out_unlock;
624 goto route_done; 632 break;
625 } 633 }
626
627 dst_release(&rt->u.dst);
628 rt = rt2;
629
630 if (err)
631 goto out_unlock;
632 } 634 }
633 635
634route_done: 636route_done: