aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/icmp.c
diff options
context:
space:
mode:
authorHannes Frederic Sowa <hannes@stressinduktion.org>2014-01-09 04:01:17 -0500
committerDavid S. Miller <davem@davemloft.net>2014-01-13 14:22:55 -0500
commit8ed1dc44d3e9e8387a104b1ae8f92e9a3fbf1b1e (patch)
tree4a8093c0dfa1507ce234754a54db8a95399955a4 /net/ipv4/icmp.c
parent0954cf9c6141d597929a292b93a2dca2c1f29159 (diff)
ipv4: introduce hardened ip_no_pmtu_disc mode
This new ip_no_pmtu_disc mode only allowes fragmentation-needed errors to be honored by protocols which do more stringent validation on the ICMP's packet payload. This knob is useful for people who e.g. want to run an unmodified DNS server in a namespace where they need to use pmtu for TCP connections (as they are used for zone transfers or fallback for requests) but don't want to use possibly spoofed UDP pmtu information. Currently the whitelisted protocols are TCP, SCTP and DCCP as they check if the returned packet is in the window or if the association is valid. Cc: Eric Dumazet <eric.dumazet@gmail.com> Cc: David Miller <davem@davemloft.net> Cc: John Heffner <johnwheffner@gmail.com> Suggested-by: Florian Weimer <fweimer@redhat.com> Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/icmp.c')
-rw-r--r--net/ipv4/icmp.c28
1 files changed, 24 insertions, 4 deletions
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index fb3c5637199d..0134663fdbce 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -668,6 +668,16 @@ static void icmp_socket_deliver(struct sk_buff *skb, u32 info)
668 rcu_read_unlock(); 668 rcu_read_unlock();
669} 669}
670 670
671static bool icmp_tag_validation(int proto)
672{
673 bool ok;
674
675 rcu_read_lock();
676 ok = rcu_dereference(inet_protos[proto])->icmp_strict_tag_validation;
677 rcu_read_unlock();
678 return ok;
679}
680
671/* 681/*
672 * Handle ICMP_DEST_UNREACH, ICMP_TIME_EXCEED, ICMP_QUENCH, and 682 * Handle ICMP_DEST_UNREACH, ICMP_TIME_EXCEED, ICMP_QUENCH, and
673 * ICMP_PARAMETERPROB. 683 * ICMP_PARAMETERPROB.
@@ -705,12 +715,22 @@ static void icmp_unreach(struct sk_buff *skb)
705 case ICMP_PORT_UNREACH: 715 case ICMP_PORT_UNREACH:
706 break; 716 break;
707 case ICMP_FRAG_NEEDED: 717 case ICMP_FRAG_NEEDED:
708 if (net->ipv4.sysctl_ip_no_pmtu_disc == 2) { 718 /* for documentation of the ip_no_pmtu_disc
709 goto out; 719 * values please see
710 } else if (net->ipv4.sysctl_ip_no_pmtu_disc) { 720 * Documentation/networking/ip-sysctl.txt
721 */
722 switch (net->ipv4.sysctl_ip_no_pmtu_disc) {
723 default:
711 LIMIT_NETDEBUG(KERN_INFO pr_fmt("%pI4: fragmentation needed and DF set\n"), 724 LIMIT_NETDEBUG(KERN_INFO pr_fmt("%pI4: fragmentation needed and DF set\n"),
712 &iph->daddr); 725 &iph->daddr);
713 } else { 726 break;
727 case 2:
728 goto out;
729 case 3:
730 if (!icmp_tag_validation(iph->protocol))
731 goto out;
732 /* fall through */
733 case 0:
714 info = ntohs(icmph->un.frag.mtu); 734 info = ntohs(icmph->un.frag.mtu);
715 if (!info) 735 if (!info)
716 goto out; 736 goto out;