aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/networking/ip-sysctl.txt13
-rw-r--r--include/net/protocol.h7
-rw-r--r--net/dccp/ipv4.c1
-rw-r--r--net/ipv4/af_inet.c1
-rw-r--r--net/ipv4/icmp.c28
-rw-r--r--net/sctp/protocol.c1
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
32min_pmtu - INTEGER 43min_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
994static const struct proto_ops inet_dccp_ops = { 995static 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
1550static const struct net_protocol udp_protocol = { 1551static 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
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;
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. */