From 69a1d98c831ec64cbfd381f5dcb6697e1445d239 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 14 Jul 2018 20:31:26 +0200 Subject: [PATCH 1/3] Revert "staging:r8188eu: Use lib80211 to support TKIP" Commit b83b8b1881c4 ("staging:r8188eu: Use lib80211 to support TKIP") is causing 2 problems for me: 1) One boot the wifi on a laptop with a r8188eu wifi device would not connect and dmesg contained an oops about scheduling while atomic pointing to the tkip code. This went away after reverting the commit. 2) I reverted the revert to try and get the oops from 1. again to be able to add it to this commit message. But now the system did connect to the wifi only to print a whole bunch of oopses, followed by a hardfreeze a few seconds later. Subsequent reboots also all lead to scenario 2. Until I reverted the commit again. Revert the commit fixes both issues making the laptop usable again. Fixes: b83b8b1881c4 ("staging:r8188eu: Use lib80211 to support TKIP") Cc: stable@vger.kernel.org Signed-off-by: Hans de Goede Acked-by: Ivan Safonov Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/Kconfig | 1 - drivers/staging/rtl8188eu/core/rtw_recv.c | 171 ++++++++++++------ drivers/staging/rtl8188eu/core/rtw_security.c | 98 +++++----- 3 files changed, 168 insertions(+), 102 deletions(-) diff --git a/drivers/staging/rtl8188eu/Kconfig b/drivers/staging/rtl8188eu/Kconfig index 673fdce25530..ff7832798a77 100644 --- a/drivers/staging/rtl8188eu/Kconfig +++ b/drivers/staging/rtl8188eu/Kconfig @@ -7,7 +7,6 @@ config R8188EU select LIB80211 select LIB80211_CRYPT_WEP select LIB80211_CRYPT_CCMP - select LIB80211_CRYPT_TKIP ---help--- This option adds the Realtek RTL8188EU USB device such as TP-Link TL-WN725N. If built as a module, it will be called r8188eu. diff --git a/drivers/staging/rtl8188eu/core/rtw_recv.c b/drivers/staging/rtl8188eu/core/rtw_recv.c index 05936a45eb93..c6857a5be12a 100644 --- a/drivers/staging/rtl8188eu/core/rtw_recv.c +++ b/drivers/staging/rtl8188eu/core/rtw_recv.c @@ -23,7 +23,6 @@ #include #include #include -#include #define ETHERNET_HEADER_SIZE 14 /* Ethernet Header Length */ #define LLC_HEADER_SIZE 6 /* LLC Header Length */ @@ -221,20 +220,31 @@ u32 rtw_free_uc_swdec_pending_queue(struct adapter *adapter) static int recvframe_chkmic(struct adapter *adapter, struct recv_frame *precvframe) { - int res = _SUCCESS; - struct rx_pkt_attrib *prxattrib = &precvframe->attrib; - struct sta_info *stainfo = rtw_get_stainfo(&adapter->stapriv, prxattrib->ta); + int i, res = _SUCCESS; + u32 datalen; + u8 miccode[8]; + u8 bmic_err = false, brpt_micerror = true; + u8 *pframe, *payload, *pframemic; + u8 *mickey; + struct sta_info *stainfo; + struct rx_pkt_attrib *prxattrib = &precvframe->attrib; + struct security_priv *psecuritypriv = &adapter->securitypriv; + + struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv; + struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + + stainfo = rtw_get_stainfo(&adapter->stapriv, &prxattrib->ta[0]); if (prxattrib->encrypt == _TKIP_) { - if (stainfo) { - int key_idx; - const int iv_len = 8, icv_len = 4, key_length = 32; - struct sk_buff *skb = precvframe->pkt; - u8 key[32], iv[8], icv[4], *pframe = skb->data; - void *crypto_private = NULL; - struct lib80211_crypto_ops *crypto_ops = try_then_request_module(lib80211_get_crypto_ops("TKIP"), "lib80211_crypt_tkip"); - struct security_priv *psecuritypriv = &adapter->securitypriv; + RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, + ("\n %s: prxattrib->encrypt==_TKIP_\n", __func__)); + RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, + ("\n %s: da=0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x\n", + __func__, prxattrib->ra[0], prxattrib->ra[1], prxattrib->ra[2], + prxattrib->ra[3], prxattrib->ra[4], prxattrib->ra[5])); + /* calculate mic code */ + if (stainfo) { if (IS_MCAST(prxattrib->ra)) { if (!psecuritypriv) { res = _FAIL; @@ -243,58 +253,115 @@ static int recvframe_chkmic(struct adapter *adapter, DBG_88E("\n %s: didn't install group key!!!!!!!!!!\n", __func__); goto exit; } - key_idx = prxattrib->key_index; - memcpy(key, psecuritypriv->dot118021XGrpKey[key_idx].skey, 16); - memcpy(key + 16, psecuritypriv->dot118021XGrprxmickey[key_idx].skey, 16); + mickey = &psecuritypriv->dot118021XGrprxmickey[prxattrib->key_index].skey[0]; + + RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, + ("\n %s: bcmc key\n", __func__)); } else { - key_idx = 0; - memcpy(key, stainfo->dot118021x_UncstKey.skey, 16); - memcpy(key + 16, stainfo->dot11tkiprxmickey.skey, 16); + mickey = &stainfo->dot11tkiprxmickey.skey[0]; + RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, + ("\n %s: unicast key\n", __func__)); } - if (!crypto_ops) { + /* icv_len included the mic code */ + datalen = precvframe->pkt->len-prxattrib->hdrlen - + prxattrib->iv_len-prxattrib->icv_len-8; + pframe = precvframe->pkt->data; + payload = pframe+prxattrib->hdrlen+prxattrib->iv_len; + + RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("\n prxattrib->iv_len=%d prxattrib->icv_len=%d\n", prxattrib->iv_len, prxattrib->icv_len)); + rtw_seccalctkipmic(mickey, pframe, payload, datalen, &miccode[0], + (unsigned char)prxattrib->priority); /* care the length of the data */ + + pframemic = payload+datalen; + + bmic_err = false; + + for (i = 0; i < 8; i++) { + if (miccode[i] != *(pframemic+i)) { + RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, + ("%s: miccode[%d](%02x)!=*(pframemic+%d)(%02x) ", + __func__, i, miccode[i], i, *(pframemic + i))); + bmic_err = true; + } + } + + if (bmic_err) { + RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, + ("\n *(pframemic-8)-*(pframemic-1)=0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x\n", + *(pframemic-8), *(pframemic-7), *(pframemic-6), + *(pframemic-5), *(pframemic-4), *(pframemic-3), + *(pframemic-2), *(pframemic-1))); + RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, + ("\n *(pframemic-16)-*(pframemic-9)=0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x\n", + *(pframemic-16), *(pframemic-15), *(pframemic-14), + *(pframemic-13), *(pframemic-12), *(pframemic-11), + *(pframemic-10), *(pframemic-9))); + { + uint i; + + RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, + ("\n ======demp packet (len=%d)======\n", + precvframe->pkt->len)); + for (i = 0; i < precvframe->pkt->len; i += 8) { + RT_TRACE(_module_rtl871x_recv_c_, + _drv_err_, + ("0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x", + *(precvframe->pkt->data+i), + *(precvframe->pkt->data+i+1), + *(precvframe->pkt->data+i+2), + *(precvframe->pkt->data+i+3), + *(precvframe->pkt->data+i+4), + *(precvframe->pkt->data+i+5), + *(precvframe->pkt->data+i+6), + *(precvframe->pkt->data+i+7))); + } + RT_TRACE(_module_rtl871x_recv_c_, + _drv_err_, + ("\n ====== demp packet end [len=%d]======\n", + precvframe->pkt->len)); + RT_TRACE(_module_rtl871x_recv_c_, + _drv_err_, + ("\n hrdlen=%d,\n", + prxattrib->hdrlen)); + } + + RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, + ("ra=0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x psecuritypriv->binstallGrpkey=%d ", + prxattrib->ra[0], prxattrib->ra[1], prxattrib->ra[2], + prxattrib->ra[3], prxattrib->ra[4], prxattrib->ra[5], psecuritypriv->binstallGrpkey)); + + /* double check key_index for some timing issue , */ + /* cannot compare with psecuritypriv->dot118021XGrpKeyid also cause timing issue */ + if ((IS_MCAST(prxattrib->ra) == true) && (prxattrib->key_index != pmlmeinfo->key_index)) + brpt_micerror = false; + + if ((prxattrib->bdecrypted) && (brpt_micerror)) { + rtw_handle_tkip_mic_err(adapter, (u8)IS_MCAST(prxattrib->ra)); + RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, (" mic error :prxattrib->bdecrypted=%d ", prxattrib->bdecrypted)); + DBG_88E(" mic error :prxattrib->bdecrypted=%d\n", prxattrib->bdecrypted); + } else { + RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, (" mic error :prxattrib->bdecrypted=%d ", prxattrib->bdecrypted)); + DBG_88E(" mic error :prxattrib->bdecrypted=%d\n", prxattrib->bdecrypted); + } res = _FAIL; - goto exit_lib80211_tkip; + } else { + /* mic checked ok */ + if ((!psecuritypriv->bcheck_grpkey) && (IS_MCAST(prxattrib->ra))) { + psecuritypriv->bcheck_grpkey = true; + RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("psecuritypriv->bcheck_grpkey = true")); + } } - - memcpy(iv, pframe + prxattrib->hdrlen, iv_len); - memcpy(icv, pframe + skb->len - icv_len, icv_len); - memmove(pframe + iv_len, pframe, prxattrib->hdrlen); - - skb_pull(skb, iv_len); - skb_trim(skb, skb->len - icv_len); - - crypto_private = crypto_ops->init(key_idx); - if (!crypto_private) { - res = _FAIL; - goto exit_lib80211_tkip; - } - if (crypto_ops->set_key(key, key_length, NULL, crypto_private) < 0) { - res = _FAIL; - goto exit_lib80211_tkip; - } - if (crypto_ops->decrypt_msdu(skb, key_idx, prxattrib->hdrlen, crypto_private)) { - res = _FAIL; - goto exit_lib80211_tkip; - } - - memmove(pframe, pframe + iv_len, prxattrib->hdrlen); - skb_push(skb, iv_len); - skb_put(skb, icv_len); - - memcpy(pframe + prxattrib->hdrlen, iv, iv_len); - memcpy(pframe + skb->len - icv_len, icv, icv_len); - -exit_lib80211_tkip: - if (crypto_ops && crypto_private) - crypto_ops->deinit(crypto_private); } else { RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("%s: rtw_get_stainfo==NULL!!!\n", __func__)); } + + skb_trim(precvframe->pkt, precvframe->pkt->len - 8); } exit: + return res; } diff --git a/drivers/staging/rtl8188eu/core/rtw_security.c b/drivers/staging/rtl8188eu/core/rtw_security.c index bfe0b217e679..67a2490f055e 100644 --- a/drivers/staging/rtl8188eu/core/rtw_security.c +++ b/drivers/staging/rtl8188eu/core/rtw_security.c @@ -650,71 +650,71 @@ u32 rtw_tkip_encrypt(struct adapter *padapter, u8 *pxmitframe) return res; } +/* The hlen isn't include the IV */ u32 rtw_tkip_decrypt(struct adapter *padapter, u8 *precvframe) -{ - struct rx_pkt_attrib *prxattrib = &((struct recv_frame *)precvframe)->attrib; - u32 res = _SUCCESS; +{ /* exclude ICV */ + u16 pnl; + u32 pnh; + u8 rc4key[16]; + u8 ttkey[16]; + u8 crc[4]; + struct arc4context mycontext; + int length; + + u8 *pframe, *payload, *iv, *prwskey; + union pn48 dot11txpn; + struct sta_info *stainfo; + struct rx_pkt_attrib *prxattrib = &((struct recv_frame *)precvframe)->attrib; + struct security_priv *psecuritypriv = &padapter->securitypriv; + u32 res = _SUCCESS; + + + pframe = (unsigned char *)((struct recv_frame *)precvframe)->pkt->data; /* 4 start to decrypt recvframe */ if (prxattrib->encrypt == _TKIP_) { - struct sta_info *stainfo = rtw_get_stainfo(&padapter->stapriv, prxattrib->ta); - + stainfo = rtw_get_stainfo(&padapter->stapriv, &prxattrib->ta[0]); if (stainfo) { - int key_idx; - const int iv_len = 8, icv_len = 4, key_length = 32; - void *crypto_private = NULL; - struct sk_buff *skb = ((struct recv_frame *)precvframe)->pkt; - u8 key[32], iv[8], icv[4], *pframe = skb->data; - struct lib80211_crypto_ops *crypto_ops = try_then_request_module(lib80211_get_crypto_ops("TKIP"), "lib80211_crypt_tkip"); - struct security_priv *psecuritypriv = &padapter->securitypriv; - if (IS_MCAST(prxattrib->ra)) { if (!psecuritypriv->binstallGrpkey) { res = _FAIL; DBG_88E("%s:rx bc/mc packets, but didn't install group key!!!!!!!!!!\n", __func__); goto exit; } - key_idx = prxattrib->key_index; - memcpy(key, psecuritypriv->dot118021XGrpKey[key_idx].skey, 16); - memcpy(key + 16, psecuritypriv->dot118021XGrprxmickey[key_idx].skey, 16); + prwskey = psecuritypriv->dot118021XGrpKey[prxattrib->key_index].skey; } else { - key_idx = 0; - memcpy(key, stainfo->dot118021x_UncstKey.skey, 16); - memcpy(key + 16, stainfo->dot11tkiprxmickey.skey, 16); + RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("%s: stainfo!= NULL!!!\n", __func__)); + prwskey = &stainfo->dot118021x_UncstKey.skey[0]; } - if (!crypto_ops) { + iv = pframe+prxattrib->hdrlen; + payload = pframe+prxattrib->iv_len+prxattrib->hdrlen; + length = ((struct recv_frame *)precvframe)->pkt->len-prxattrib->hdrlen-prxattrib->iv_len; + + GET_TKIP_PN(iv, dot11txpn); + + pnl = (u16)(dot11txpn.val); + pnh = (u32)(dot11txpn.val>>16); + + phase1((u16 *)&ttkey[0], prwskey, &prxattrib->ta[0], pnh); + phase2(&rc4key[0], prwskey, (unsigned short *)&ttkey[0], pnl); + + /* 4 decrypt payload include icv */ + + arcfour_init(&mycontext, rc4key, 16); + arcfour_encrypt(&mycontext, payload, payload, length); + + *((__le32 *)crc) = getcrc32(payload, length-4); + + if (crc[3] != payload[length-1] || + crc[2] != payload[length-2] || + crc[1] != payload[length-3] || + crc[0] != payload[length-4]) { + RT_TRACE(_module_rtl871x_security_c_, _drv_err_, + ("rtw_wep_decrypt:icv error crc (%4ph)!=payload (%4ph)\n", + &crc, &payload[length-4])); res = _FAIL; - goto exit_lib80211_tkip; } - - memcpy(iv, pframe + prxattrib->hdrlen, iv_len); - memcpy(icv, pframe + skb->len - icv_len, icv_len); - - crypto_private = crypto_ops->init(key_idx); - if (!crypto_private) { - res = _FAIL; - goto exit_lib80211_tkip; - } - if (crypto_ops->set_key(key, key_length, NULL, crypto_private) < 0) { - res = _FAIL; - goto exit_lib80211_tkip; - } - if (crypto_ops->decrypt_mpdu(skb, prxattrib->hdrlen, crypto_private)) { - res = _FAIL; - goto exit_lib80211_tkip; - } - - memmove(pframe, pframe + iv_len, prxattrib->hdrlen); - skb_push(skb, iv_len); - skb_put(skb, icv_len); - - memcpy(pframe + prxattrib->hdrlen, iv, iv_len); - memcpy(pframe + skb->len - icv_len, icv, icv_len); - -exit_lib80211_tkip: - if (crypto_ops && crypto_private) - crypto_ops->deinit(crypto_private); } else { RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("rtw_tkip_decrypt: stainfo==NULL!!!\n")); res = _FAIL; From eb37430d402de7d1cb2f37a5fdc80620dd98dc1d Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos Date: Fri, 13 Jul 2018 09:36:59 +0200 Subject: [PATCH 2/3] staging: ks7010: call 'hostif_mib_set_request_int' instead of 'hostif_mib_set_request_bool' 'hostif_mib_set_request_bool' function receives a bool as value and send the received value with MIB_VALUE_TYPE_BOOL type. There is one case where the value passed is not a boolean one but 'MCAST_FILTER_PROMISC' which is '2'. Call hostif_mib_set_request_int instead for related multicast enumeration. This changes original code behaviour but seems to be the right way to do this. Fixes: 8ce76bff0e6a ("staging: ks7010: add new helpers to achieve mib set request and simplify code") Reported-by: Dan Carpenter Signed-off-by: Sergio Paracuellos Reviewed-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ks7010/ks_hostif.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/staging/ks7010/ks_hostif.c b/drivers/staging/ks7010/ks_hostif.c index 0ecffab52ec2..abdaf7cf8162 100644 --- a/drivers/staging/ks7010/ks_hostif.c +++ b/drivers/staging/ks7010/ks_hostif.c @@ -1842,15 +1842,15 @@ void hostif_sme_multicast_set(struct ks_wlan_private *priv) memset(set_address, 0, NIC_MAX_MCAST_LIST * ETH_ALEN); if (dev->flags & IFF_PROMISC) { - hostif_mib_set_request_bool(priv, LOCAL_MULTICAST_FILTER, - MCAST_FILTER_PROMISC); + hostif_mib_set_request_int(priv, LOCAL_MULTICAST_FILTER, + MCAST_FILTER_PROMISC); goto spin_unlock; } if ((netdev_mc_count(dev) > NIC_MAX_MCAST_LIST) || (dev->flags & IFF_ALLMULTI)) { - hostif_mib_set_request_bool(priv, LOCAL_MULTICAST_FILTER, - MCAST_FILTER_MCASTALL); + hostif_mib_set_request_int(priv, LOCAL_MULTICAST_FILTER, + MCAST_FILTER_MCASTALL); goto spin_unlock; } @@ -1866,8 +1866,8 @@ void hostif_sme_multicast_set(struct ks_wlan_private *priv) ETH_ALEN * mc_count); } else { priv->sme_i.sme_flag |= SME_MULTICAST; - hostif_mib_set_request_bool(priv, LOCAL_MULTICAST_FILTER, - MCAST_FILTER_MCAST); + hostif_mib_set_request_int(priv, LOCAL_MULTICAST_FILTER, + MCAST_FILTER_MCAST); } spin_unlock: From b96fba8d5855c3617adbfb43ca4723a808cac954 Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Fri, 13 Jul 2018 00:29:36 +0200 Subject: [PATCH 3/3] staging: speakup: fix wraparound in uaccess length check If softsynthx_read() is called with `count < 3`, `count - 3` wraps, causing the loop to copy as much data as available to the provided buffer. If softsynthx_read() is invoked through sys_splice(), this causes an unbounded kernel write; but even when userspace just reads from it normally, a small size could cause userspace crashes. Fixes: 425e586cf95b ("speakup: add unicode variant of /dev/softsynth") Cc: stable@vger.kernel.org Signed-off-by: Samuel Thibault Signed-off-by: Jann Horn Signed-off-by: Greg Kroah-Hartman --- drivers/staging/speakup/speakup_soft.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/staging/speakup/speakup_soft.c b/drivers/staging/speakup/speakup_soft.c index a61bc41b82d7..947c79532e10 100644 --- a/drivers/staging/speakup/speakup_soft.c +++ b/drivers/staging/speakup/speakup_soft.c @@ -198,11 +198,15 @@ static ssize_t softsynthx_read(struct file *fp, char __user *buf, size_t count, int chars_sent = 0; char __user *cp; char *init; + size_t bytes_per_ch = unicode ? 3 : 1; u16 ch; int empty; unsigned long flags; DEFINE_WAIT(wait); + if (count < bytes_per_ch) + return -EINVAL; + spin_lock_irqsave(&speakup_info.spinlock, flags); while (1) { prepare_to_wait(&speakup_event, &wait, TASK_INTERRUPTIBLE); @@ -228,7 +232,7 @@ static ssize_t softsynthx_read(struct file *fp, char __user *buf, size_t count, init = get_initstring(); /* Keep 3 bytes available for a 16bit UTF-8-encoded character */ - while (chars_sent <= count - 3) { + while (chars_sent <= count - bytes_per_ch) { if (speakup_info.flushing) { speakup_info.flushing = 0; ch = '\x18';