diff options
-rw-r--r-- | Documentation/networking/ip-sysctl.txt | 13 | ||||
-rw-r--r-- | include/net/protocol.h | 7 | ||||
-rw-r--r-- | net/dccp/ipv4.c | 1 | ||||
-rw-r--r-- | net/ipv4/af_inet.c | 1 | ||||
-rw-r--r-- | net/ipv4/icmp.c | 28 | ||||
-rw-r--r-- | net/sctp/protocol.c | 1 |
6 files changed, 45 insertions, 6 deletions
diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt index 0d71fa962d8a..c97932c88ea3 100644 --- a/Documentation/networking/ip-sysctl.txt +++ b/Documentation/networking/ip-sysctl.txt | |||
@@ -26,7 +26,18 @@ ip_no_pmtu_disc - INTEGER | |||
26 | discarded. Outgoing frames are handled the same as in mode 1, | 26 | discarded. Outgoing frames are handled the same as in mode 1, |
27 | implicitly setting IP_PMTUDISC_DONT on every created socket. | 27 | implicitly setting IP_PMTUDISC_DONT on every created socket. |
28 | 28 | ||
29 | Possible values: 0-2 | 29 | Mode 3 is a hardend pmtu discover mode. The kernel will only |
30 | accept fragmentation-needed errors if the underlying protocol | ||
31 | can verify them besides a plain socket lookup. Current | ||
32 | protocols for which pmtu events will be honored are TCP, SCTP | ||
33 | and DCCP as they verify e.g. the sequence number or the | ||
34 | association. This mode should not be enabled globally but is | ||
35 | only intended to secure e.g. name servers in namespaces where | ||
36 | TCP path mtu must still work but path MTU information of other | ||
37 | protocols should be discarded. If enabled globally this mode | ||
38 | could break other protocols. | ||
39 | |||
40 | Possible values: 0-3 | ||
30 | Default: FALSE | 41 | Default: FALSE |
31 | 42 | ||
32 | min_pmtu - INTEGER | 43 | min_pmtu - INTEGER |
diff --git a/include/net/protocol.h b/include/net/protocol.h index fbf7676c9a02..0e5f8665d7fb 100644 --- a/include/net/protocol.h +++ b/include/net/protocol.h | |||
@@ -43,7 +43,12 @@ struct net_protocol { | |||
43 | int (*handler)(struct sk_buff *skb); | 43 | int (*handler)(struct sk_buff *skb); |
44 | void (*err_handler)(struct sk_buff *skb, u32 info); | 44 | void (*err_handler)(struct sk_buff *skb, u32 info); |
45 | unsigned int no_policy:1, | 45 | unsigned int no_policy:1, |
46 | netns_ok:1; | 46 | netns_ok:1, |
47 | /* does the protocol do more stringent | ||
48 | * icmp tag validation than simple | ||
49 | * socket lookup? | ||
50 | */ | ||
51 | icmp_strict_tag_validation:1; | ||
47 | }; | 52 | }; |
48 | 53 | ||
49 | #if IS_ENABLED(CONFIG_IPV6) | 54 | #if IS_ENABLED(CONFIG_IPV6) |
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index 88299c29101d..22b5d818b200 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c | |||
@@ -989,6 +989,7 @@ static const struct net_protocol dccp_v4_protocol = { | |||
989 | .err_handler = dccp_v4_err, | 989 | .err_handler = dccp_v4_err, |
990 | .no_policy = 1, | 990 | .no_policy = 1, |
991 | .netns_ok = 1, | 991 | .netns_ok = 1, |
992 | .icmp_strict_tag_validation = 1, | ||
992 | }; | 993 | }; |
993 | 994 | ||
994 | static const struct proto_ops inet_dccp_ops = { | 995 | static const struct proto_ops inet_dccp_ops = { |
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 6268a4751e64..ecd2c3f245ce 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c | |||
@@ -1545,6 +1545,7 @@ static const struct net_protocol tcp_protocol = { | |||
1545 | .err_handler = tcp_v4_err, | 1545 | .err_handler = tcp_v4_err, |
1546 | .no_policy = 1, | 1546 | .no_policy = 1, |
1547 | .netns_ok = 1, | 1547 | .netns_ok = 1, |
1548 | .icmp_strict_tag_validation = 1, | ||
1548 | }; | 1549 | }; |
1549 | 1550 | ||
1550 | static const struct net_protocol udp_protocol = { | 1551 | static const struct net_protocol udp_protocol = { |
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; |
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 34b7726bcd7f..7c161084f241 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c | |||
@@ -1030,6 +1030,7 @@ static const struct net_protocol sctp_protocol = { | |||
1030 | .err_handler = sctp_v4_err, | 1030 | .err_handler = sctp_v4_err, |
1031 | .no_policy = 1, | 1031 | .no_policy = 1, |
1032 | .netns_ok = 1, | 1032 | .netns_ok = 1, |
1033 | .icmp_strict_tag_validation = 1, | ||
1033 | }; | 1034 | }; |
1034 | 1035 | ||
1035 | /* IPv4 address related functions. */ | 1036 | /* IPv4 address related functions. */ |