aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2015-05-16 16:40:22 -0400
committerDavid S. Miller <davem@davemloft.net>2015-05-16 16:40:22 -0400
commit1d6057019ee1b0de90697ff10bf84b7028e8bba4 (patch)
treee4ecabf883d7fa5c8f30d9f9294c50ee1def75de
parent7e14069651591c81046ffaec13c3dac8cb70f5fb (diff)
parent960bd2c26421d321e890f1936938196ead41976f (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf
Pablo Neira Ayuso says: ==================== The following patchset contains Netfilter fixes for your net tree, they are: 1) Fix a leak in IPVS, the sysctl table is not released accordingly when destroying a netns, patch from Tommi Rantala. 2) Fix a build error when TPROXY and socket are built-in but IPv6 defrag is compiled as module, from Florian Westphal. 3) Fix TCP tracket wrt. RFC5961 challenge ACK when in LAST_ACK state, patch from Jesper Dangaard Brouer. 4) Fix a bogus WARN_ON() in nf_tables when deleting a set element that stores a map, from Mirek Kratochvil. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/uapi/linux/netfilter/nf_conntrack_tcp.h3
-rw-r--r--net/netfilter/Kconfig2
-rw-r--r--net/netfilter/ipvs/ip_vs_ctl.c3
-rw-r--r--net/netfilter/nf_conntrack_proto_tcp.c35
-rw-r--r--net/netfilter/nf_tables_api.c4
5 files changed, 42 insertions, 5 deletions
diff --git a/include/uapi/linux/netfilter/nf_conntrack_tcp.h b/include/uapi/linux/netfilter/nf_conntrack_tcp.h
index 9993a421201c..ef9f80f0f529 100644
--- a/include/uapi/linux/netfilter/nf_conntrack_tcp.h
+++ b/include/uapi/linux/netfilter/nf_conntrack_tcp.h
@@ -42,6 +42,9 @@ enum tcp_conntrack {
42/* The field td_maxack has been set */ 42/* The field td_maxack has been set */
43#define IP_CT_TCP_FLAG_MAXACK_SET 0x20 43#define IP_CT_TCP_FLAG_MAXACK_SET 0x20
44 44
45/* Marks possibility for expected RFC5961 challenge ACK */
46#define IP_CT_EXP_CHALLENGE_ACK 0x40
47
45struct nf_ct_tcp_flags { 48struct nf_ct_tcp_flags {
46 __u8 flags; 49 __u8 flags;
47 __u8 mask; 50 __u8 mask;
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index f70e34a68f70..a0f3e6a3c7d1 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -863,6 +863,7 @@ config NETFILTER_XT_TARGET_TPROXY
863 depends on NETFILTER_XTABLES 863 depends on NETFILTER_XTABLES
864 depends on NETFILTER_ADVANCED 864 depends on NETFILTER_ADVANCED
865 depends on (IPV6 || IPV6=n) 865 depends on (IPV6 || IPV6=n)
866 depends on (IP6_NF_IPTABLES || IP6_NF_IPTABLES=n)
866 depends on IP_NF_MANGLE 867 depends on IP_NF_MANGLE
867 select NF_DEFRAG_IPV4 868 select NF_DEFRAG_IPV4
868 select NF_DEFRAG_IPV6 if IP6_NF_IPTABLES 869 select NF_DEFRAG_IPV6 if IP6_NF_IPTABLES
@@ -1356,6 +1357,7 @@ config NETFILTER_XT_MATCH_SOCKET
1356 depends on NETFILTER_ADVANCED 1357 depends on NETFILTER_ADVANCED
1357 depends on !NF_CONNTRACK || NF_CONNTRACK 1358 depends on !NF_CONNTRACK || NF_CONNTRACK
1358 depends on (IPV6 || IPV6=n) 1359 depends on (IPV6 || IPV6=n)
1360 depends on (IP6_NF_IPTABLES || IP6_NF_IPTABLES=n)
1359 select NF_DEFRAG_IPV4 1361 select NF_DEFRAG_IPV4
1360 select NF_DEFRAG_IPV6 if IP6_NF_IPTABLES 1362 select NF_DEFRAG_IPV6 if IP6_NF_IPTABLES
1361 help 1363 help
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
index 49532672f66d..285eae3a1454 100644
--- a/net/netfilter/ipvs/ip_vs_ctl.c
+++ b/net/netfilter/ipvs/ip_vs_ctl.c
@@ -3823,6 +3823,9 @@ static void __net_exit ip_vs_control_net_cleanup_sysctl(struct net *net)
3823 cancel_work_sync(&ipvs->defense_work.work); 3823 cancel_work_sync(&ipvs->defense_work.work);
3824 unregister_net_sysctl_table(ipvs->sysctl_hdr); 3824 unregister_net_sysctl_table(ipvs->sysctl_hdr);
3825 ip_vs_stop_estimator(net, &ipvs->tot_stats); 3825 ip_vs_stop_estimator(net, &ipvs->tot_stats);
3826
3827 if (!net_eq(net, &init_net))
3828 kfree(ipvs->sysctl_tbl);
3826} 3829}
3827 3830
3828#else 3831#else
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c
index 5caa0c41bf26..70383de72054 100644
--- a/net/netfilter/nf_conntrack_proto_tcp.c
+++ b/net/netfilter/nf_conntrack_proto_tcp.c
@@ -202,7 +202,7 @@ static const u8 tcp_conntracks[2][6][TCP_CONNTRACK_MAX] = {
202 * sES -> sES :-) 202 * sES -> sES :-)
203 * sFW -> sCW Normal close request answered by ACK. 203 * sFW -> sCW Normal close request answered by ACK.
204 * sCW -> sCW 204 * sCW -> sCW
205 * sLA -> sTW Last ACK detected. 205 * sLA -> sTW Last ACK detected (RFC5961 challenged)
206 * sTW -> sTW Retransmitted last ACK. Remain in the same state. 206 * sTW -> sTW Retransmitted last ACK. Remain in the same state.
207 * sCL -> sCL 207 * sCL -> sCL
208 */ 208 */
@@ -261,7 +261,7 @@ static const u8 tcp_conntracks[2][6][TCP_CONNTRACK_MAX] = {
261 * sES -> sES :-) 261 * sES -> sES :-)
262 * sFW -> sCW Normal close request answered by ACK. 262 * sFW -> sCW Normal close request answered by ACK.
263 * sCW -> sCW 263 * sCW -> sCW
264 * sLA -> sTW Last ACK detected. 264 * sLA -> sTW Last ACK detected (RFC5961 challenged)
265 * sTW -> sTW Retransmitted last ACK. 265 * sTW -> sTW Retransmitted last ACK.
266 * sCL -> sCL 266 * sCL -> sCL
267 */ 267 */
@@ -906,6 +906,7 @@ static int tcp_packet(struct nf_conn *ct,
906 1 : ct->proto.tcp.last_win; 906 1 : ct->proto.tcp.last_win;
907 ct->proto.tcp.seen[ct->proto.tcp.last_dir].td_scale = 907 ct->proto.tcp.seen[ct->proto.tcp.last_dir].td_scale =
908 ct->proto.tcp.last_wscale; 908 ct->proto.tcp.last_wscale;
909 ct->proto.tcp.last_flags &= ~IP_CT_EXP_CHALLENGE_ACK;
909 ct->proto.tcp.seen[ct->proto.tcp.last_dir].flags = 910 ct->proto.tcp.seen[ct->proto.tcp.last_dir].flags =
910 ct->proto.tcp.last_flags; 911 ct->proto.tcp.last_flags;
911 memset(&ct->proto.tcp.seen[dir], 0, 912 memset(&ct->proto.tcp.seen[dir], 0,
@@ -923,7 +924,9 @@ static int tcp_packet(struct nf_conn *ct,
923 * may be in sync but we are not. In that case, we annotate 924 * may be in sync but we are not. In that case, we annotate
924 * the TCP options and let the packet go through. If it is a 925 * the TCP options and let the packet go through. If it is a
925 * valid SYN packet, the server will reply with a SYN/ACK, and 926 * valid SYN packet, the server will reply with a SYN/ACK, and
926 * then we'll get in sync. Otherwise, the server ignores it. */ 927 * then we'll get in sync. Otherwise, the server potentially
928 * responds with a challenge ACK if implementing RFC5961.
929 */
927 if (index == TCP_SYN_SET && dir == IP_CT_DIR_ORIGINAL) { 930 if (index == TCP_SYN_SET && dir == IP_CT_DIR_ORIGINAL) {
928 struct ip_ct_tcp_state seen = {}; 931 struct ip_ct_tcp_state seen = {};
929 932
@@ -939,6 +942,13 @@ static int tcp_packet(struct nf_conn *ct,
939 ct->proto.tcp.last_flags |= 942 ct->proto.tcp.last_flags |=
940 IP_CT_TCP_FLAG_SACK_PERM; 943 IP_CT_TCP_FLAG_SACK_PERM;
941 } 944 }
945 /* Mark the potential for RFC5961 challenge ACK,
946 * this pose a special problem for LAST_ACK state
947 * as ACK is intrepretated as ACKing last FIN.
948 */
949 if (old_state == TCP_CONNTRACK_LAST_ACK)
950 ct->proto.tcp.last_flags |=
951 IP_CT_EXP_CHALLENGE_ACK;
942 } 952 }
943 spin_unlock_bh(&ct->lock); 953 spin_unlock_bh(&ct->lock);
944 if (LOG_INVALID(net, IPPROTO_TCP)) 954 if (LOG_INVALID(net, IPPROTO_TCP))
@@ -970,6 +980,25 @@ static int tcp_packet(struct nf_conn *ct,
970 nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, 980 nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL,
971 "nf_ct_tcp: invalid state "); 981 "nf_ct_tcp: invalid state ");
972 return -NF_ACCEPT; 982 return -NF_ACCEPT;
983 case TCP_CONNTRACK_TIME_WAIT:
984 /* RFC5961 compliance cause stack to send "challenge-ACK"
985 * e.g. in response to spurious SYNs. Conntrack MUST
986 * not believe this ACK is acking last FIN.
987 */
988 if (old_state == TCP_CONNTRACK_LAST_ACK &&
989 index == TCP_ACK_SET &&
990 ct->proto.tcp.last_dir != dir &&
991 ct->proto.tcp.last_index == TCP_SYN_SET &&
992 (ct->proto.tcp.last_flags & IP_CT_EXP_CHALLENGE_ACK)) {
993 /* Detected RFC5961 challenge ACK */
994 ct->proto.tcp.last_flags &= ~IP_CT_EXP_CHALLENGE_ACK;
995 spin_unlock_bh(&ct->lock);
996 if (LOG_INVALID(net, IPPROTO_TCP))
997 nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL,
998 "nf_ct_tcp: challenge-ACK ignored ");
999 return NF_ACCEPT; /* Don't change state */
1000 }
1001 break;
973 case TCP_CONNTRACK_CLOSE: 1002 case TCP_CONNTRACK_CLOSE:
974 if (index == TCP_RST_SET 1003 if (index == TCP_RST_SET
975 && (ct->proto.tcp.seen[!dir].flags & IP_CT_TCP_FLAG_MAXACK_SET) 1004 && (ct->proto.tcp.seen[!dir].flags & IP_CT_TCP_FLAG_MAXACK_SET)
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index ad9d11fb29fd..34ded09317e7 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -4472,9 +4472,9 @@ EXPORT_SYMBOL_GPL(nft_data_init);
4472 */ 4472 */
4473void nft_data_uninit(const struct nft_data *data, enum nft_data_types type) 4473void nft_data_uninit(const struct nft_data *data, enum nft_data_types type)
4474{ 4474{
4475 switch (type) { 4475 if (type < NFT_DATA_VERDICT)
4476 case NFT_DATA_VALUE:
4477 return; 4476 return;
4477 switch (type) {
4478 case NFT_DATA_VERDICT: 4478 case NFT_DATA_VERDICT:
4479 return nft_verdict_uninit(data); 4479 return nft_verdict_uninit(data);
4480 default: 4480 default: