diff options
author | Hannes Frederic Sowa <hannes@stressinduktion.org> | 2014-01-09 04:01:17 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-01-13 14:22:55 -0500 |
commit | 8ed1dc44d3e9e8387a104b1ae8f92e9a3fbf1b1e (patch) | |
tree | 4a8093c0dfa1507ce234754a54db8a95399955a4 /net/ipv4/icmp.c | |
parent | 0954cf9c6141d597929a292b93a2dca2c1f29159 (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.c | 28 |
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 | ||
671 | static 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; |