From 33766368f6532313571534f9112b1796d6651bbe Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 30 Sep 2012 19:47:40 +0300 Subject: mac80211: Fix FC masking in BIP AAD generation The bits used in the mask were off-by-one and ended up masking PwrMgt, MoreData, Protected fields instead of Retry, PwrMgt, MoreData. Fix this and to mask the correct fields. While doing so, convert the code to mask the full FC using IEEE80211_FCTL_* defines similarly to how CCMP AAD is built. Since BIP is used only with broadcast/multicast management frames, the Retry field is always 0 in these frames. The Protected field is also zero to maintain backwards compatibility. As such, the incorrect mask here does not really cause any problems for valid frames. In theory, an invalid BIP frame with Retry or Protected field set to 1 could be rejected because of BIP validation. However, no such frame should show up with standard compliant implementations, so this does not cause problems in normal BIP use. Signed-off-by: Jouni Malinen Signed-off-by: Johannes Berg --- net/mac80211/wpa.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'net') diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index bdb53aba888e..e58bf3fe3ed9 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c @@ -545,14 +545,19 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx) static void bip_aad(struct sk_buff *skb, u8 *aad) { + __le16 mask_fc; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; + /* BIP AAD: FC(masked) || A1 || A2 || A3 */ /* FC type/subtype */ - aad[0] = skb->data[0]; /* Mask FC Retry, PwrMgt, MoreData flags to zero */ - aad[1] = skb->data[1] & ~(BIT(4) | BIT(5) | BIT(6)); + mask_fc = hdr->frame_control; + mask_fc &= ~cpu_to_le16(IEEE80211_FCTL_RETRY | IEEE80211_FCTL_PM | + IEEE80211_FCTL_MOREDATA); + put_unaligned(mask_fc, (__le16 *) &aad[0]); /* A1 || A2 || A3 */ - memcpy(aad + 2, skb->data + 4, 3 * ETH_ALEN); + memcpy(aad + 2, &hdr->addr1, 3 * ETH_ALEN); } -- cgit v1.2.3 From b61a602ee6730150f4d0df730d9312ac4d820ceb Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 9 Oct 2012 13:04:34 +0900 Subject: ipvs: initialize returned data in do_ip_vs_get_ctl As reported by a gcc warning, the do_ip_vs_get_ctl does not initalize all the members of the ip_vs_timeout_user structure it returns if at least one of the TCP or UDP protocols is disabled for ipvs. This makes sure that the data is always initialized, before it is returned as a response to IPVS_CMD_GET_CONFIG or printed as a debug message in IPVS_CMD_SET_CONFIG. Without this patch, building ARM ixp4xx_defconfig results in: net/netfilter/ipvs/ip_vs_ctl.c: In function 'ip_vs_genl_set_cmd': net/netfilter/ipvs/ip_vs_ctl.c:2238:47: warning: 't.udp_timeout' may be used uninitialized in this function [-Wuninitialized] net/netfilter/ipvs/ip_vs_ctl.c:3322:28: note: 't.udp_timeout' was declared here net/netfilter/ipvs/ip_vs_ctl.c:2238:47: warning: 't.tcp_fin_timeout' may be used uninitialized in this function [-Wuninitialized] net/netfilter/ipvs/ip_vs_ctl.c:3322:28: note: 't.tcp_fin_timeout' was declared here net/netfilter/ipvs/ip_vs_ctl.c:2238:47: warning: 't.tcp_timeout' may be used uninitialized in this function [-Wuninitialized] net/netfilter/ipvs/ip_vs_ctl.c:3322:28: note: 't.tcp_timeout' was declared here Signed-off-by: Arnd Bergmann Acked-by: Julian Anastasov Signed-off-by: Simon Horman --- net/netfilter/ipvs/ip_vs_ctl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'net') diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index 7e7198b51c06..c4ee43710aab 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c @@ -2589,6 +2589,8 @@ __ip_vs_get_timeouts(struct net *net, struct ip_vs_timeout_user *u) struct ip_vs_proto_data *pd; #endif + memset(u, 0, sizeof (*u)); + #ifdef CONFIG_IP_VS_PROTO_TCP pd = ip_vs_proto_data_get(net, IPPROTO_TCP); u->tcp_timeout = pd->timeout_table[IP_VS_TCP_S_ESTABLISHED] / HZ; @@ -2766,7 +2768,6 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) { struct ip_vs_timeout_user t; - memset(&t, 0, sizeof(t)); __ip_vs_get_timeouts(net, &t); if (copy_to_user(user, &t, sizeof(t)) != 0) ret = -EFAULT; -- cgit v1.2.3 From 065a13e2cc665f6547dc7e8a9d6b6565badf940a Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Thu, 11 Oct 2012 16:26:06 +0200 Subject: Bluetooth: SMP: Fix setting unknown auth_req bits When sending a pairing request or response we should not just blindly copy the value that the remote device sent. Instead we should at least make sure to mask out any unknown bits. This is particularly critical from the upcoming LE Secure Connections feature perspective as incorrectly indicating support for it (by copying the remote value) would cause a failure to pair with devices that support it. Signed-off-by: Johan Hedberg Cc: stable@kernel.org Acked-by: Marcel Holtmann Signed-off-by: Gustavo Padovan --- net/bluetooth/smp.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index 8c225ef349cd..2ac8d50861e0 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c @@ -32,6 +32,8 @@ #define SMP_TIMEOUT msecs_to_jiffies(30000) +#define AUTH_REQ_MASK 0x07 + static inline void swap128(u8 src[16], u8 dst[16]) { int i; @@ -230,7 +232,7 @@ static void build_pairing_cmd(struct l2cap_conn *conn, req->max_key_size = SMP_MAX_ENC_KEY_SIZE; req->init_key_dist = 0; req->resp_key_dist = dist_keys; - req->auth_req = authreq; + req->auth_req = (authreq & AUTH_REQ_MASK); return; } @@ -239,7 +241,7 @@ static void build_pairing_cmd(struct l2cap_conn *conn, rsp->max_key_size = SMP_MAX_ENC_KEY_SIZE; rsp->init_key_dist = 0; rsp->resp_key_dist = req->resp_key_dist & dist_keys; - rsp->auth_req = authreq; + rsp->auth_req = (authreq & AUTH_REQ_MASK); } static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size) -- cgit v1.2.3 From 0153d5a810ab335aae86acfe69722a7efc1db536 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Thu, 11 Oct 2012 10:49:12 +0200 Subject: netfilter: xt_CT: fix timeout setting with IPv6 This patch fixes ip6tables and the CT target if it is used to set some custom conntrack timeout policy for IPv6. Use xt_ct_find_proto which already handles the ip6tables case for us. Signed-off-by: Pablo Neira Ayuso --- net/netfilter/xt_CT.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'net') diff --git a/net/netfilter/xt_CT.c b/net/netfilter/xt_CT.c index 16c712563860..ae7f5daeee43 100644 --- a/net/netfilter/xt_CT.c +++ b/net/netfilter/xt_CT.c @@ -180,9 +180,9 @@ xt_ct_set_timeout(struct nf_conn *ct, const struct xt_tgchk_param *par, typeof(nf_ct_timeout_find_get_hook) timeout_find_get; struct ctnl_timeout *timeout; struct nf_conn_timeout *timeout_ext; - const struct ipt_entry *e = par->entryinfo; struct nf_conntrack_l4proto *l4proto; int ret = 0; + u8 proto; rcu_read_lock(); timeout_find_get = rcu_dereference(nf_ct_timeout_find_get_hook); @@ -192,9 +192,11 @@ xt_ct_set_timeout(struct nf_conn *ct, const struct xt_tgchk_param *par, goto out; } - if (e->ip.invflags & IPT_INV_PROTO) { + proto = xt_ct_find_proto(par); + if (!proto) { ret = -EINVAL; - pr_info("You cannot use inversion on L4 protocol\n"); + pr_info("You must specify a L4 protocol, and not use " + "inversions on it.\n"); goto out; } @@ -214,7 +216,7 @@ xt_ct_set_timeout(struct nf_conn *ct, const struct xt_tgchk_param *par, /* Make sure the timeout policy matches any existing protocol tracker, * otherwise default to generic. */ - l4proto = __nf_ct_l4proto_find(par->family, e->ip.proto); + l4proto = __nf_ct_l4proto_find(par->family, proto); if (timeout->l4proto->l4proto != l4proto->l4proto) { ret = -EINVAL; pr_info("Timeout policy `%s' can only be used by L4 protocol " -- cgit v1.2.3 From 939ccba437da1726a5c8a5b702a47d473da927ae Mon Sep 17 00:00:00 2001 From: Elison Niven Date: Mon, 15 Oct 2012 00:44:48 +0000 Subject: netfilter: xt_nat: fix incorrect hooks for SNAT and DNAT targets In (c7232c9 netfilter: add protocol independent NAT core), the hooks were accidentally modified: SNAT hooks are POST_ROUTING and LOCAL_IN (before it was LOCAL_OUT). DNAT hooks are PRE_ROUTING and LOCAL_OUT (before it was LOCAL_IN). Signed-off-by: Elison Niven Signed-off-by: Sanket Shah Signed-off-by: Pablo Neira Ayuso --- net/netfilter/xt_nat.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'net') diff --git a/net/netfilter/xt_nat.c b/net/netfilter/xt_nat.c index 81aafa8e4fef..bea7464cc43f 100644 --- a/net/netfilter/xt_nat.c +++ b/net/netfilter/xt_nat.c @@ -111,7 +111,7 @@ static struct xt_target xt_nat_target_reg[] __read_mostly = { .family = NFPROTO_IPV4, .table = "nat", .hooks = (1 << NF_INET_POST_ROUTING) | - (1 << NF_INET_LOCAL_OUT), + (1 << NF_INET_LOCAL_IN), .me = THIS_MODULE, }, { @@ -123,7 +123,7 @@ static struct xt_target xt_nat_target_reg[] __read_mostly = { .family = NFPROTO_IPV4, .table = "nat", .hooks = (1 << NF_INET_PRE_ROUTING) | - (1 << NF_INET_LOCAL_IN), + (1 << NF_INET_LOCAL_OUT), .me = THIS_MODULE, }, { @@ -133,7 +133,7 @@ static struct xt_target xt_nat_target_reg[] __read_mostly = { .targetsize = sizeof(struct nf_nat_range), .table = "nat", .hooks = (1 << NF_INET_POST_ROUTING) | - (1 << NF_INET_LOCAL_OUT), + (1 << NF_INET_LOCAL_IN), .me = THIS_MODULE, }, { @@ -143,7 +143,7 @@ static struct xt_target xt_nat_target_reg[] __read_mostly = { .targetsize = sizeof(struct nf_nat_range), .table = "nat", .hooks = (1 << NF_INET_PRE_ROUTING) | - (1 << NF_INET_LOCAL_IN), + (1 << NF_INET_LOCAL_OUT), .me = THIS_MODULE, }, }; -- cgit v1.2.3 From 6863255bd0e48bc41ae5a066d5c771801e92735a Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Mon, 15 Oct 2012 14:52:41 +0200 Subject: cfg80211/mac80211: avoid state mishmash on deauth Avoid situation when we are on associate state in mac80211 and on disassociate state in cfg80211. This can results on crash during modules unload (like showed on this thread: http://marc.info/?t=134373976300001&r=1&w=2) and possibly other problems. Reported-by: Pedro Francisco Cc: stable@vger.kernel.org Signed-off-by: Stanislaw Gruszka Signed-off-by: Johannes Berg --- include/net/cfg80211.h | 1 + net/mac80211/mlme.c | 5 +++-- net/wireless/mlme.c | 12 +++--------- 3 files changed, 7 insertions(+), 11 deletions(-) (limited to 'net') diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 1b4989082244..f8cd4cf3fad8 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1218,6 +1218,7 @@ struct cfg80211_deauth_request { const u8 *ie; size_t ie_len; u16 reason_code; + bool local_state_change; }; /** diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index e714ed8bb198..e510a33fec76 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -3549,6 +3549,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, { struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN]; + bool tx = !req->local_state_change; mutex_lock(&ifmgd->mtx); @@ -3565,12 +3566,12 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, if (ifmgd->associated && ether_addr_equal(ifmgd->associated->bssid, req->bssid)) { ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, - req->reason_code, true, frame_buf); + req->reason_code, tx, frame_buf); } else { drv_mgd_prepare_tx(sdata->local, sdata); ieee80211_send_deauth_disassoc(sdata, req->bssid, IEEE80211_STYPE_DEAUTH, - req->reason_code, true, + req->reason_code, tx, frame_buf); } diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index 8016fee0752b..904a7f368325 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c @@ -457,20 +457,14 @@ int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, .reason_code = reason, .ie = ie, .ie_len = ie_len, + .local_state_change = local_state_change, }; ASSERT_WDEV_LOCK(wdev); - if (local_state_change) { - if (wdev->current_bss && - ether_addr_equal(wdev->current_bss->pub.bssid, bssid)) { - cfg80211_unhold_bss(wdev->current_bss); - cfg80211_put_bss(&wdev->current_bss->pub); - wdev->current_bss = NULL; - } - + if (local_state_change && (!wdev->current_bss || + !ether_addr_equal(wdev->current_bss->pub.bssid, bssid))) return 0; - } return rdev->ops->deauth(&rdev->wiphy, dev, &req); } -- cgit v1.2.3 From 4045f72bcf3c293c7c5932ef001742d8bb5ded76 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Tue, 2 Oct 2012 21:34:23 +0200 Subject: mac80211: check if key has TKIP type before updating IV This patch fix corruption which can manifest itself by following crash when switching on rfkill switch with rt2x00 driver: https://bugzilla.redhat.com/attachment.cgi?id=615362 Pointer key->u.ccmp.tfm of group key get corrupted in: ieee80211_rx_h_michael_mic_verify(): /* update IV in key information to be able to detect replays */ rx->key->u.tkip.rx[rx->security_idx].iv32 = rx->tkip_iv32; rx->key->u.tkip.rx[rx->security_idx].iv16 = rx->tkip_iv16; because rt2x00 always set RX_FLAG_MMIC_STRIPPED, even if key is not TKIP. We already check type of the key in different path in ieee80211_rx_h_michael_mic_verify() function, so adding additional check here is reasonable. Cc: stable@vger.kernel.org # 3.0+ Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- net/mac80211/wpa.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'net') diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index bdb53aba888e..e72562a18bad 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c @@ -106,7 +106,8 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx) if (status->flag & RX_FLAG_MMIC_ERROR) goto mic_fail; - if (!(status->flag & RX_FLAG_IV_STRIPPED) && rx->key) + if (!(status->flag & RX_FLAG_IV_STRIPPED) && rx->key && + rx->key->conf.cipher == WLAN_CIPHER_SUITE_TKIP) goto update_iv; return RX_CONTINUE; -- cgit v1.2.3 From d4fa14cd62bd078c8e3ef39283b9f237e5b2ff0f Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 10 Oct 2012 22:40:23 +0200 Subject: mac80211: use ieee80211_free_txskb in a few more places Free tx status skbs when draining power save buffers, pending frames, or when tearing down a vif. Fixes remaining conditions that can lead to hostapd/wpa_supplicant hangs when running out of socket write memory. Signed-off-by: Felix Fietkau Cc: stable@vger.kernel.org Signed-off-by: John W. Linville --- net/mac80211/iface.c | 2 +- net/mac80211/sta_info.c | 4 ++-- net/mac80211/util.c | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'net') diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 6f8a73c64fb3..7de7717ad67d 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -853,7 +853,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); if (info->control.vif == &sdata->vif) { __skb_unlink(skb, &local->pending[i]); - dev_kfree_skb_irq(skb); + ieee80211_free_txskb(&local->hw, skb); } } } diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 797dd36a220d..0a4e4c04db89 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -650,7 +650,7 @@ static bool sta_info_cleanup_expire_buffered_ac(struct ieee80211_local *local, */ if (!skb) break; - dev_kfree_skb(skb); + ieee80211_free_txskb(&local->hw, skb); } /* @@ -679,7 +679,7 @@ static bool sta_info_cleanup_expire_buffered_ac(struct ieee80211_local *local, local->total_ps_buffered--; ps_dbg(sta->sdata, "Buffered frame expired (STA %pM)\n", sta->sta.addr); - dev_kfree_skb(skb); + ieee80211_free_txskb(&local->hw, skb); } /* diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 22ca35054dd0..94e586873979 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -406,7 +406,7 @@ void ieee80211_add_pending_skb(struct ieee80211_local *local, int queue = info->hw_queue; if (WARN_ON(!info->control.vif)) { - kfree_skb(skb); + ieee80211_free_txskb(&local->hw, skb); return; } @@ -431,7 +431,7 @@ void ieee80211_add_pending_skbs_fn(struct ieee80211_local *local, struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); if (WARN_ON(!info->control.vif)) { - kfree_skb(skb); + ieee80211_free_txskb(&local->hw, skb); continue; } -- cgit v1.2.3 From 2ad5b9e4bd314fc685086b99e90e5de3bc59e26b Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 16 Oct 2012 22:33:29 +0000 Subject: netfilter: xt_TEE: don't use destination address found in header Torsten Luettgert bisected TEE regression starting with commit f8126f1d5136be1 (ipv4: Adjust semantics of rt->rt_gateway.) The problem is that it tries to ARP-lookup the original destination address of the forwarded packet, not the address of the gateway. Fix this using FLOWI_FLAG_KNOWN_NH Julian added in commit c92b96553a80c1 (ipv4: Add FLOWI_FLAG_KNOWN_NH), so that known nexthop (info->gw.ip) has preference on resolving. Reported-by: Torsten Luettgert Bisected-by: Torsten Luettgert Tested-by: Torsten Luettgert Cc: Julian Anastasov Signed-off-by: Eric Dumazet Signed-off-by: Pablo Neira Ayuso --- net/netfilter/xt_TEE.c | 1 + 1 file changed, 1 insertion(+) (limited to 'net') diff --git a/net/netfilter/xt_TEE.c b/net/netfilter/xt_TEE.c index ee2e5bc5a8c7..bd93e51d30ac 100644 --- a/net/netfilter/xt_TEE.c +++ b/net/netfilter/xt_TEE.c @@ -70,6 +70,7 @@ tee_tg_route4(struct sk_buff *skb, const struct xt_tee_tginfo *info) fl4.daddr = info->gw.ip; fl4.flowi4_tos = RT_TOS(iph->tos); fl4.flowi4_scope = RT_SCOPE_UNIVERSE; + fl4.flowi4_flags = FLOWI_FLAG_KNOWN_NH; rt = ip_route_output_key(net, &fl4); if (IS_ERR(rt)) return false; -- cgit v1.2.3 From 3a40414f826a8f1096d9b94c4a53ef91b25ba28d Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 1 Oct 2012 15:52:00 +0200 Subject: mac80211: connect with HT20 if HT40 is not permitted Some changes to fix issues with HT40 APs in Korea and follow-up changes to allow using HT40 even if the local regulatory database disallows it caused issues with iwlwifi (and could cause issues with other devices); iwlwifi firmware would assert if you tried to connect to an AP that has an invalid configuration (e.g. using HT40- on channel 140.) Fix this, while avoiding the "Korean AP" issue by disabling HT40 and advertising HT20 to the AP when connecting. Cc: stable@vger.kernel.org [3.6] Reported-by: Florian Reitmeir Tested-by: Florian Reitmeir Signed-off-by: Johannes Berg --- net/mac80211/mlme.c | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) (limited to 'net') diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index e510a33fec76..1b7eed252fe9 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -3099,22 +3099,32 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, ht_cfreq, ht_oper->primary_chan, cbss->channel->band); ht_oper = NULL; + } else { + channel_type = NL80211_CHAN_HT20; } } - if (ht_oper) { - channel_type = NL80211_CHAN_HT20; + if (ht_oper && sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) { + /* + * cfg80211 already verified that the channel itself can + * be used, but it didn't check that we can do the right + * HT type, so do that here as well. If HT40 isn't allowed + * on this channel, disable 40 MHz operation. + */ - if (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) { - switch (ht_oper->ht_param & - IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { - case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: + switch (ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { + case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: + if (cbss->channel->flags & IEEE80211_CHAN_NO_HT40PLUS) + ifmgd->flags |= IEEE80211_STA_DISABLE_40MHZ; + else channel_type = NL80211_CHAN_HT40PLUS; - break; - case IEEE80211_HT_PARAM_CHA_SEC_BELOW: + break; + case IEEE80211_HT_PARAM_CHA_SEC_BELOW: + if (cbss->channel->flags & IEEE80211_CHAN_NO_HT40MINUS) + ifmgd->flags |= IEEE80211_STA_DISABLE_40MHZ; + else channel_type = NL80211_CHAN_HT40MINUS; - break; - } + break; } } -- cgit v1.2.3 From 7f112af40fecf5399b61e69ffc6b55a9d82789f7 Mon Sep 17 00:00:00 2001 From: Linus Lüssing Date: Wed, 17 Oct 2012 14:53:04 +0200 Subject: batman-adv: Fix broadcast packet CRC calculation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit So far the crc16 checksum for a batman-adv broadcast data packet, received on a batman-adv hard interface, was calculated over zero bytes of its content leading to many incoming broadcast data packets wrongly being dropped (60-80% packet loss). This patch fixes this issue by calculating the crc16 over the actual, complete broadcast payload. The issue is a regression introduced by ("batman-adv: add broadcast duplicate check"). Signed-off-by: Linus Lüssing Acked-by: Simon Wunderlich Signed-off-by: Marek Lindner --- net/batman-adv/bridge_loop_avoidance.c | 8 ++++---- net/batman-adv/routing.c | 8 +++++++- 2 files changed, 11 insertions(+), 5 deletions(-) (limited to 'net') diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c index 0a9084ad19a6..eebab20c7478 100644 --- a/net/batman-adv/bridge_loop_avoidance.c +++ b/net/batman-adv/bridge_loop_avoidance.c @@ -1210,8 +1210,8 @@ int batadv_bla_init(struct batadv_priv *bat_priv) /** * batadv_bla_check_bcast_duplist * @bat_priv: the bat priv with all the soft interface information - * @bcast_packet: originator mac address - * @hdr_size: maximum length of the frame + * @bcast_packet: encapsulated broadcast frame plus batman header + * @bcast_packet_len: length of encapsulated broadcast frame plus batman header * * check if it is on our broadcast list. Another gateway might * have sent the same packet because it is connected to the same backbone, @@ -1224,14 +1224,14 @@ int batadv_bla_init(struct batadv_priv *bat_priv) */ int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv, struct batadv_bcast_packet *bcast_packet, - int hdr_size) + int bcast_packet_len) { int i, length, curr; uint8_t *content; uint16_t crc; struct batadv_bcast_duplist_entry *entry; - length = hdr_size - sizeof(*bcast_packet); + length = bcast_packet_len - sizeof(*bcast_packet); content = (uint8_t *)bcast_packet; content += sizeof(*bcast_packet); diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index 939fc01371df..376b4cc6ca82 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c @@ -1124,8 +1124,14 @@ int batadv_recv_bcast_packet(struct sk_buff *skb, spin_unlock_bh(&orig_node->bcast_seqno_lock); + /* keep skb linear for crc calculation */ + if (skb_linearize(skb) < 0) + goto out; + + bcast_packet = (struct batadv_bcast_packet *)skb->data; + /* check whether this has been sent by another originator before */ - if (batadv_bla_check_bcast_duplist(bat_priv, bcast_packet, hdr_size)) + if (batadv_bla_check_bcast_duplist(bat_priv, bcast_packet, skb->len)) goto out; /* rebroadcast packet */ -- cgit v1.2.3 From 7dac7b76b8db87fc79857a53a09730fb2148579b Mon Sep 17 00:00:00 2001 From: Linus Lüssing Date: Wed, 17 Oct 2012 14:53:05 +0200 Subject: batman-adv: Fix potential broadcast BLA-duplicate-check race condition MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Threads in the bottom half of batadv_bla_check_bcast_duplist() might otherwise for instance overwrite variables which other threads might be using/reading at the same time in the top half, potentially leading to messing up the bcast_duplist, possibly resulting in false bridge loop avoidance duplicate check decisions. Signed-off-by: Linus Lüssing Acked-by: Simon Wunderlich Signed-off-by: Marek Lindner --- net/batman-adv/bridge_loop_avoidance.c | 19 ++++++++++++++----- net/batman-adv/types.h | 2 ++ 2 files changed, 16 insertions(+), 5 deletions(-) (limited to 'net') diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c index eebab20c7478..fd8d5afec0dd 100644 --- a/net/batman-adv/bridge_loop_avoidance.c +++ b/net/batman-adv/bridge_loop_avoidance.c @@ -1167,6 +1167,8 @@ int batadv_bla_init(struct batadv_priv *bat_priv) uint16_t crc; unsigned long entrytime; + spin_lock_init(&bat_priv->bla.bcast_duplist_lock); + batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla hash registering\n"); /* setting claim destination address */ @@ -1226,7 +1228,7 @@ int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv, struct batadv_bcast_packet *bcast_packet, int bcast_packet_len) { - int i, length, curr; + int i, length, curr, ret = 0; uint8_t *content; uint16_t crc; struct batadv_bcast_duplist_entry *entry; @@ -1238,6 +1240,8 @@ int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv, /* calculate the crc ... */ crc = crc16(0, content, length); + spin_lock_bh(&bat_priv->bla.bcast_duplist_lock); + for (i = 0; i < BATADV_DUPLIST_SIZE; i++) { curr = (bat_priv->bla.bcast_duplist_curr + i); curr %= BATADV_DUPLIST_SIZE; @@ -1259,9 +1263,12 @@ int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv, /* this entry seems to match: same crc, not too old, * and from another gw. therefore return 1 to forbid it. */ - return 1; + ret = 1; + goto out; } - /* not found, add a new entry (overwrite the oldest entry) */ + /* not found, add a new entry (overwrite the oldest entry) + * and allow it, its the first occurence. + */ curr = (bat_priv->bla.bcast_duplist_curr + BATADV_DUPLIST_SIZE - 1); curr %= BATADV_DUPLIST_SIZE; entry = &bat_priv->bla.bcast_duplist[curr]; @@ -1270,8 +1277,10 @@ int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv, memcpy(entry->orig, bcast_packet->orig, ETH_ALEN); bat_priv->bla.bcast_duplist_curr = curr; - /* allow it, its the first occurence. */ - return 0; +out: + spin_unlock_bh(&bat_priv->bla.bcast_duplist_lock); + + return ret; } diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index 2ed82caacdca..ac1e07a80454 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h @@ -205,6 +205,8 @@ struct batadv_priv_bla { struct batadv_hashtable *backbone_hash; struct batadv_bcast_duplist_entry bcast_duplist[BATADV_DUPLIST_SIZE]; int bcast_duplist_curr; + /* protects bcast_duplist and bcast_duplist_curr */ + spinlock_t bcast_duplist_lock; struct batadv_bla_claim_dst claim_dest; struct delayed_work work; }; -- cgit v1.2.3 From 18c22a03a2187bcbda7d3a7fa1061584a6348e7b Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Wed, 17 Oct 2012 01:37:36 +0000 Subject: vlan: allow to change type when no vlan device is hooked on netdev vlan_info might be present but still no vlan devices might be there. That is in case of vlan0 automatically added. So in that case, allow to change netdev type. Reported-by: Jon Stanley Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- net/8021q/vlan.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'net') diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index 9096bcb08132..ee070722a3a3 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c @@ -463,7 +463,9 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, case NETDEV_PRE_TYPE_CHANGE: /* Forbid underlaying device to change its type. */ - return NOTIFY_BAD; + if (vlan_uses_dev(dev)) + return NOTIFY_BAD; + break; case NETDEV_NOTIFY_PEERS: case NETDEV_BONDING_FAILOVER: -- cgit v1.2.3 From 13d82bf50dce632355fcccafa4fe44a9b5e706d8 Mon Sep 17 00:00:00 2001 From: Steffen Klassert Date: Wed, 17 Oct 2012 21:17:44 +0000 Subject: ipv4: Fix flushing of cached routing informations Currently we can not flush cached pmtu/redirect informations via the ipv4_sysctl_rtcache_flush sysctl. We need to check the rt_genid of the old route and reset the nh exeption if the old route is expired when we bind a new route to a nh exeption. Signed-off-by: Steffen Klassert Acked-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv4/route.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'net') diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 432f4bb77238..a8c651216fa6 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -1163,8 +1163,12 @@ static bool rt_bind_exception(struct rtable *rt, struct fib_nh_exception *fnhe, spin_lock_bh(&fnhe_lock); if (daddr == fnhe->fnhe_daddr) { - struct rtable *orig; - + struct rtable *orig = rcu_dereference(fnhe->fnhe_rth); + if (orig && rt_is_expired(orig)) { + fnhe->fnhe_gw = 0; + fnhe->fnhe_pmtu = 0; + fnhe->fnhe_expires = 0; + } if (fnhe->fnhe_pmtu) { unsigned long expires = fnhe->fnhe_expires; unsigned long diff = expires - jiffies; @@ -1181,7 +1185,6 @@ static bool rt_bind_exception(struct rtable *rt, struct fib_nh_exception *fnhe, } else if (!rt->rt_gateway) rt->rt_gateway = daddr; - orig = rcu_dereference(fnhe->fnhe_rth); rcu_assign_pointer(fnhe->fnhe_rth, rt); if (orig) rt_free(orig); -- cgit v1.2.3 From 6d772ac5578f711d1ce7b03535d1c95bffb21dff Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 18 Oct 2012 03:21:55 +0000 Subject: netlink: use kfree_rcu() in netlink_release() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On some suspend/resume operations involving wimax device, we have noticed some intermittent memory corruptions in netlink code. Stéphane Marchesin tracked this corruption in netlink_update_listeners() and suggested a patch. It appears netlink_release() should use kfree_rcu() instead of kfree() for the listeners structure as it may be used by other cpus using RCU protection. netlink_release() must set to NULL the listeners pointer when it is about to be freed. Also have to protect netlink_update_listeners() and netlink_has_listeners() if listeners is NULL. Add a nl_deref_protected() lockdep helper to properly document which locks protects us. Reported-by: Jonathan Kliegman Signed-off-by: Eric Dumazet Cc: Stéphane Marchesin Cc: Sam Leffler Signed-off-by: David S. Miller --- net/netlink/af_netlink.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) (limited to 'net') diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 01e944a017a4..4da797fa5ec5 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -138,6 +138,8 @@ static int netlink_dump(struct sock *sk); static DEFINE_RWLOCK(nl_table_lock); static atomic_t nl_table_users = ATOMIC_INIT(0); +#define nl_deref_protected(X) rcu_dereference_protected(X, lockdep_is_held(&nl_table_lock)); + static ATOMIC_NOTIFIER_HEAD(netlink_chain); static inline u32 netlink_group_mask(u32 group) @@ -345,6 +347,11 @@ netlink_update_listeners(struct sock *sk) struct hlist_node *node; unsigned long mask; unsigned int i; + struct listeners *listeners; + + listeners = nl_deref_protected(tbl->listeners); + if (!listeners) + return; for (i = 0; i < NLGRPLONGS(tbl->groups); i++) { mask = 0; @@ -352,7 +359,7 @@ netlink_update_listeners(struct sock *sk) if (i < NLGRPLONGS(nlk_sk(sk)->ngroups)) mask |= nlk_sk(sk)->groups[i]; } - tbl->listeners->masks[i] = mask; + listeners->masks[i] = mask; } /* this function is only called with the netlink table "grabbed", which * makes sure updates are visible before bind or setsockopt return. */ @@ -536,7 +543,11 @@ static int netlink_release(struct socket *sock) if (netlink_is_kernel(sk)) { BUG_ON(nl_table[sk->sk_protocol].registered == 0); if (--nl_table[sk->sk_protocol].registered == 0) { - kfree(nl_table[sk->sk_protocol].listeners); + struct listeners *old; + + old = nl_deref_protected(nl_table[sk->sk_protocol].listeners); + RCU_INIT_POINTER(nl_table[sk->sk_protocol].listeners, NULL); + kfree_rcu(old, rcu); nl_table[sk->sk_protocol].module = NULL; nl_table[sk->sk_protocol].bind = NULL; nl_table[sk->sk_protocol].flags = 0; @@ -982,7 +993,7 @@ int netlink_has_listeners(struct sock *sk, unsigned int group) rcu_read_lock(); listeners = rcu_dereference(nl_table[sk->sk_protocol].listeners); - if (group - 1 < nl_table[sk->sk_protocol].groups) + if (listeners && group - 1 < nl_table[sk->sk_protocol].groups) res = test_bit(group - 1, listeners->masks); rcu_read_unlock(); @@ -1625,7 +1636,7 @@ int __netlink_change_ngroups(struct sock *sk, unsigned int groups) new = kzalloc(sizeof(*new) + NLGRPSZ(groups), GFP_ATOMIC); if (!new) return -ENOMEM; - old = rcu_dereference_protected(tbl->listeners, 1); + old = nl_deref_protected(tbl->listeners); memcpy(new->masks, old->masks, NLGRPSZ(tbl->groups)); rcu_assign_pointer(tbl->listeners, new); -- cgit v1.2.3 From a3374c42aa5f7237e87ff3b0622018636b0c847e Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 18 Oct 2012 09:14:12 +0000 Subject: tcp: fix FIONREAD/SIOCINQ tcp_ioctl() tries to take into account if tcp socket received a FIN to report correct number bytes in receive queue. But its flaky because if the application ate the last skb, we return 1 instead of 0. Correct way to detect that FIN was received is to test SOCK_DONE. Reported-by: Elliot Hughes Signed-off-by: Eric Dumazet Cc: Neal Cardwell Cc: Tom Herbert Signed-off-by: David S. Miller --- net/ipv4/tcp.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'net') diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index f32c02e2a543..b7c2f439b54f 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -549,14 +549,12 @@ int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg) !tp->urg_data || before(tp->urg_seq, tp->copied_seq) || !before(tp->urg_seq, tp->rcv_nxt)) { - struct sk_buff *skb; answ = tp->rcv_nxt - tp->copied_seq; - /* Subtract 1, if FIN is in queue. */ - skb = skb_peek_tail(&sk->sk_receive_queue); - if (answ && skb) - answ -= tcp_hdr(skb)->fin; + /* Subtract 1, if FIN was received */ + if (answ && sock_flag(sk, SOCK_DONE)) + answ--; } else answ = tp->urg_seq - tp->copied_seq; release_sock(sk); -- cgit v1.2.3 From 6f73601efb35c7003f5c58c2bc6fd08f3652169c Mon Sep 17 00:00:00 2001 From: Yuchung Cheng Date: Fri, 19 Oct 2012 15:14:44 +0000 Subject: tcp: add SYN/data info to TCP_INFO Add a bit TCPI_OPT_SYN_DATA (32) to the socket option TCP_INFO:tcpi_options. It's set if the data in SYN (sent or received) is acked by SYN-ACK. Server or client application can use this information to check Fast Open success rate. Signed-off-by: Yuchung Cheng Acked-by: Neal Cardwell Acked-by: Eric Dumazet Signed-off-by: David S. Miller --- include/linux/tcp.h | 3 ++- include/uapi/linux/tcp.h | 1 + net/ipv4/tcp.c | 2 ++ net/ipv4/tcp_input.c | 1 + net/ipv4/tcp_ipv4.c | 1 + net/ipv4/tcp_minisocks.c | 1 + 6 files changed, 8 insertions(+), 1 deletion(-) (limited to 'net') diff --git a/include/linux/tcp.h b/include/linux/tcp.h index 8a7fc4be2d75..60b7aac15e0e 100644 --- a/include/linux/tcp.h +++ b/include/linux/tcp.h @@ -191,7 +191,8 @@ struct tcp_sock { u8 do_early_retrans:1,/* Enable RFC5827 early-retransmit */ early_retrans_delayed:1, /* Delayed ER timer installed */ syn_data:1, /* SYN includes data */ - syn_fastopen:1; /* SYN includes Fast Open option */ + syn_fastopen:1, /* SYN includes Fast Open option */ + syn_data_acked:1;/* data in SYN is acked by SYN-ACK */ /* RTT measurement */ u32 srtt; /* smoothed round trip time << 3 */ diff --git a/include/uapi/linux/tcp.h b/include/uapi/linux/tcp.h index c4b89a5cb7df..e962faa5ab0d 100644 --- a/include/uapi/linux/tcp.h +++ b/include/uapi/linux/tcp.h @@ -130,6 +130,7 @@ enum { #define TCPI_OPT_WSCALE 4 #define TCPI_OPT_ECN 8 /* ECN was negociated at TCP session init */ #define TCPI_OPT_ECN_SEEN 16 /* we received at least one packet with ECT */ +#define TCPI_OPT_SYN_DATA 32 /* SYN-ACK acked data in SYN sent or rcvd */ enum tcp_ca_state { TCP_CA_Open = 0, diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index b7c2f439b54f..197c0008503c 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -2764,6 +2764,8 @@ void tcp_get_info(const struct sock *sk, struct tcp_info *info) info->tcpi_options |= TCPI_OPT_ECN; if (tp->ecn_flags & TCP_ECN_SEEN) info->tcpi_options |= TCPI_OPT_ECN_SEEN; + if (tp->syn_data_acked) + info->tcpi_options |= TCPI_OPT_SYN_DATA; info->tcpi_rto = jiffies_to_usecs(icsk->icsk_rto); info->tcpi_ato = jiffies_to_usecs(icsk->icsk_ack.ato); diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 432c36649db3..036f85738141 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -5646,6 +5646,7 @@ static bool tcp_rcv_fastopen_synack(struct sock *sk, struct sk_buff *synack, tcp_rearm_rto(sk); return true; } + tp->syn_data_acked = tp->syn_data; return false; } diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index ef998b008a57..0c4a64355603 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -1461,6 +1461,7 @@ static int tcp_v4_conn_req_fastopen(struct sock *sk, skb_set_owner_r(skb, child); __skb_queue_tail(&child->sk_receive_queue, skb); tp->rcv_nxt = TCP_SKB_CB(skb)->end_seq; + tp->syn_data_acked = 1; } sk->sk_data_ready(sk, 0); bh_unlock_sock(child); diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index 27536ba16c9d..a7302d974f32 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c @@ -510,6 +510,7 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req, newtp->rx_opt.mss_clamp = req->mss; TCP_ECN_openreq_child(newtp, req); newtp->fastopen_rsk = NULL; + newtp->syn_data_acked = 0; TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_PASSIVEOPENS); } -- cgit v1.2.3 From 3d861f661006606bf159fd6bd973e83dbf21d0f9 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 22 Oct 2012 09:03:40 +0000 Subject: net: fix secpath kmemleak Mike Kazantsev found 3.5 kernels and beyond were leaking memory, and tracked the faulty commit to a1c7fff7e18f59e ("net: netdev_alloc_skb() use build_skb()") While this commit seems fine, it uncovered a bug introduced in commit bad43ca8325 ("net: introduce skb_try_coalesce()), in function kfree_skb_partial()"): If head is stolen, we free the sk_buff, without removing references on secpath (skb->sp). So IPsec + IP defrag/reassembly (using skb coalescing), or TCP coalescing could leak secpath objects. Fix this bug by calling skb_release_head_state(skb) to properly release all possible references to linked objects. Reported-by: Mike Kazantsev Signed-off-by: Eric Dumazet Bisected-by: Mike Kazantsev Tested-by: Mike Kazantsev Signed-off-by: David S. Miller --- net/core/skbuff.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 6e04b1fa11f2..4007c1437fda 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -3379,10 +3379,12 @@ EXPORT_SYMBOL(__skb_warn_lro_forwarding); void kfree_skb_partial(struct sk_buff *skb, bool head_stolen) { - if (head_stolen) + if (head_stolen) { + skb_release_head_state(skb); kmem_cache_free(skbuff_head_cache, skb); - else + } else { __kfree_skb(skb); + } } EXPORT_SYMBOL(kfree_skb_partial); -- cgit v1.2.3 From 37561f68bd527ec39076e32effdc7b1dcdfb17ea Mon Sep 17 00:00:00 2001 From: Jerry Chu Date: Mon, 22 Oct 2012 11:26:36 +0000 Subject: tcp: Reject invalid ack_seq to Fast Open sockets A packet with an invalid ack_seq may cause a TCP Fast Open socket to switch to the unexpected TCP_CLOSING state, triggering a BUG_ON kernel panic. When a FIN packet with an invalid ack_seq# arrives at a socket in the TCP_FIN_WAIT1 state, rather than discarding the packet, the current code will accept the FIN, causing state transition to TCP_CLOSING. This may be a small deviation from RFC793, which seems to say that the packet should be dropped. Unfortunately I did not expect this case for Fast Open hence it will trigger a BUG_ON panic. It turns out there is really nothing bad about a TFO socket going into TCP_CLOSING state so I could just remove the BUG_ON statements. But after some thought I think it's better to treat this case like TCP_SYN_RECV and return a RST to the confused peer who caused the unacceptable ack_seq to be generated in the first place. Signed-off-by: H.K. Jerry Chu Cc: Neal Cardwell Cc: Yuchung Cheng Acked-by: Yuchung Cheng Acked-by: Eric Dumazet Acked-by: Neal Cardwell Signed-off-by: David S. Miller --- net/ipv4/tcp_input.c | 12 ++++++++++-- net/ipv4/tcp_timer.c | 4 ++-- 2 files changed, 12 insertions(+), 4 deletions(-) (limited to 'net') diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 036f85738141..1db663983587 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -5964,7 +5964,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, req = tp->fastopen_rsk; if (req != NULL) { - BUG_ON(sk->sk_state != TCP_SYN_RECV && + WARN_ON_ONCE(sk->sk_state != TCP_SYN_RECV && sk->sk_state != TCP_FIN_WAIT1); if (tcp_check_req(sk, skb, req, NULL, true) == NULL) @@ -6053,7 +6053,15 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, * ACK we have received, this would have acknowledged * our SYNACK so stop the SYNACK timer. */ - if (acceptable && req != NULL) { + if (req != NULL) { + /* Return RST if ack_seq is invalid. + * Note that RFC793 only says to generate a + * DUPACK for it but for TCP Fast Open it seems + * better to treat this case like TCP_SYN_RECV + * above. + */ + if (!acceptable) + return 1; /* We no longer need the request sock. */ reqsk_fastopen_remove(sk, req, false); tcp_rearm_rto(sk); diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c index fc04711e80c8..d47c1b4421a3 100644 --- a/net/ipv4/tcp_timer.c +++ b/net/ipv4/tcp_timer.c @@ -347,8 +347,8 @@ void tcp_retransmit_timer(struct sock *sk) return; } if (tp->fastopen_rsk) { - BUG_ON(sk->sk_state != TCP_SYN_RECV && - sk->sk_state != TCP_FIN_WAIT1); + WARN_ON_ONCE(sk->sk_state != TCP_SYN_RECV && + sk->sk_state != TCP_FIN_WAIT1); tcp_fastopen_synack_timer(sk); /* Before we receive ACK to our SYN-ACK don't retransmit * anything else (e.g., data or FIN segments). -- cgit v1.2.3 From 14edd87dc67311556f1254a8f29cf4dd6cb5b7d1 Mon Sep 17 00:00:00 2001 From: Li RongQing Date: Wed, 24 Oct 2012 14:01:18 +0800 Subject: ipv6: Set default hoplimit as zero. Commit a02e4b7dae4551(Demark default hoplimit as zero) only changes the hoplimit checking condition and default value in ip6_dst_hoplimit, not zeros all hoplimit default value. Keep the zeroing ip6_template_metrics[RTAX_HOPLIMIT - 1] to force it as const, cause as a37e6e344910(net: force dst_default_metrics to const section) Signed-off-by: Li RongQing Signed-off-by: David S. Miller --- net/ipv6/route.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 7c7e963260e1..b1e6cf0b95fd 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -219,7 +219,7 @@ static struct dst_ops ip6_dst_blackhole_ops = { }; static const u32 ip6_template_metrics[RTAX_MAX] = { - [RTAX_HOPLIMIT - 1] = 255, + [RTAX_HOPLIMIT - 1] = 0, }; static const struct rt6_info ip6_null_entry_template = { @@ -1232,7 +1232,7 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev, rt->rt6i_dst.addr = fl6->daddr; rt->rt6i_dst.plen = 128; rt->rt6i_idev = idev; - dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 255); + dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 0); spin_lock_bh(&icmp6_dst_lock); rt->dst.next = icmp6_dst_gc_list; -- cgit v1.2.3