staging: rtl8188eu: Revert 4 commits breaking ARP
commit66d32fdcbf
upstream. Commit2ba8444c97
("staging:r8188eu: move IV/ICV trimming into decrypt() and also place it after rtl88eu_mon_recv_hook()") breaks ARP. After this commit ssh-ing to a laptop with r8188eu wifi no longer works if the machine connecting has never communicated with the laptop before. This is 100% reproducable using "arp -d <ipv4> && ssh <ipv4>" to ssh to a laptop with r8188eu wifi. This commit reverts 4 commits in total: 1. Commit79650ffde3
("staging:r8188eu: trim IV/ICV fields in validate_recv_data_frame()") This commit depends on 2 of the other commits being reverted. 2. Commit02b19b4c49
("staging:r8188eu: inline unprotect_frame() in mon_recv_decrypted_recv()") The inline code is wrong the un-inlined version contains: if (skb->len < hdr_len + iv_len + icv_len) return; ... Where as the inline-ed code introduced by this commit does: if (skb->len < hdr_len + iv_len + icv_len) { ... Note the same check, but now to actually continue doing ... instead of to not do it, so this commit is no good. 3. Commitd86e16da6a
("staging:r8188eu: use different mon_recv_decrypted() inside rtl88eu_mon_recv_hook() and rtl88eu_mon_xmit_hook().") This commit introduced a 1:1 copy of a function so that one of the 2 copies can be modified in the 2 commits we're already reverting. 4. Commit2ba8444c97
("staging:r8188eu: move IV/ICV trimming into decrypt() and also place it after rtl88eu_mon_recv_hook()") This is the commit actually breaking ARP. Note this commit is a straight-forward squash of the revert of these 4 commits, without any changes. Cc: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
ccc04bde3a
commit
d3e36fd07b
@ -259,10 +259,12 @@ static int recvframe_chkmic(struct adapter *adapter,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* icv_len included the mic code */
|
/* icv_len included the mic code */
|
||||||
datalen = precvframe->pkt->len-prxattrib->hdrlen - 8;
|
datalen = precvframe->pkt->len-prxattrib->hdrlen -
|
||||||
|
prxattrib->iv_len-prxattrib->icv_len-8;
|
||||||
pframe = precvframe->pkt->data;
|
pframe = precvframe->pkt->data;
|
||||||
payload = pframe+prxattrib->hdrlen;
|
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],
|
rtw_seccalctkipmic(mickey, pframe, payload, datalen, &miccode[0],
|
||||||
(unsigned char)prxattrib->priority); /* care the length of the data */
|
(unsigned char)prxattrib->priority); /* care the length of the data */
|
||||||
|
|
||||||
@ -407,15 +409,9 @@ static struct recv_frame *decryptor(struct adapter *padapter,
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (res != _FAIL) {
|
|
||||||
memmove(precv_frame->pkt->data + precv_frame->attrib.iv_len, precv_frame->pkt->data, precv_frame->attrib.hdrlen);
|
|
||||||
skb_pull(precv_frame->pkt, precv_frame->attrib.iv_len);
|
|
||||||
skb_trim(precv_frame->pkt, precv_frame->pkt->len - precv_frame->attrib.icv_len);
|
|
||||||
}
|
|
||||||
} else if (prxattrib->bdecrypted == 1 && prxattrib->encrypt > 0 &&
|
} else if (prxattrib->bdecrypted == 1 && prxattrib->encrypt > 0 &&
|
||||||
(psecuritypriv->busetkipkey == 1 || prxattrib->encrypt != _TKIP_)) {
|
(psecuritypriv->busetkipkey == 1 || prxattrib->encrypt != _TKIP_))
|
||||||
psecuritypriv->hw_decrypted = true;
|
psecuritypriv->hw_decrypted = true;
|
||||||
}
|
|
||||||
|
|
||||||
if (res == _FAIL) {
|
if (res == _FAIL) {
|
||||||
rtw_free_recvframe(return_packet, &padapter->recvpriv.free_recv_queue);
|
rtw_free_recvframe(return_packet, &padapter->recvpriv.free_recv_queue);
|
||||||
@ -456,7 +452,7 @@ static struct recv_frame *portctrl(struct adapter *adapter,
|
|||||||
|
|
||||||
if (auth_alg == 2) {
|
if (auth_alg == 2) {
|
||||||
/* get ether_type */
|
/* get ether_type */
|
||||||
ptr = ptr + pfhdr->attrib.hdrlen + LLC_HEADER_SIZE;
|
ptr = ptr + pfhdr->attrib.hdrlen + LLC_HEADER_SIZE + pfhdr->attrib.iv_len;
|
||||||
memcpy(&be_tmp, ptr, 2);
|
memcpy(&be_tmp, ptr, 2);
|
||||||
ether_type = ntohs(be_tmp);
|
ether_type = ntohs(be_tmp);
|
||||||
|
|
||||||
@ -1138,8 +1134,6 @@ static int validate_recv_data_frame(struct adapter *adapter,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (pattrib->privacy) {
|
if (pattrib->privacy) {
|
||||||
struct sk_buff *skb = precv_frame->pkt;
|
|
||||||
|
|
||||||
RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("validate_recv_data_frame:pattrib->privacy=%x\n", pattrib->privacy));
|
RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("validate_recv_data_frame:pattrib->privacy=%x\n", pattrib->privacy));
|
||||||
RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("\n ^^^^^^^^^^^IS_MCAST(pattrib->ra(0x%02x))=%d^^^^^^^^^^^^^^^6\n", pattrib->ra[0], IS_MCAST(pattrib->ra)));
|
RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("\n ^^^^^^^^^^^IS_MCAST(pattrib->ra(0x%02x))=%d^^^^^^^^^^^^^^^6\n", pattrib->ra[0], IS_MCAST(pattrib->ra)));
|
||||||
|
|
||||||
@ -1148,13 +1142,6 @@ static int validate_recv_data_frame(struct adapter *adapter,
|
|||||||
RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("\n pattrib->encrypt=%d\n", pattrib->encrypt));
|
RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("\n pattrib->encrypt=%d\n", pattrib->encrypt));
|
||||||
|
|
||||||
SET_ICE_IV_LEN(pattrib->iv_len, pattrib->icv_len, pattrib->encrypt);
|
SET_ICE_IV_LEN(pattrib->iv_len, pattrib->icv_len, pattrib->encrypt);
|
||||||
|
|
||||||
if (pattrib->bdecrypted == 1 && pattrib->encrypt > 0) {
|
|
||||||
memmove(skb->data + pattrib->iv_len,
|
|
||||||
skb->data, pattrib->hdrlen);
|
|
||||||
skb_pull(skb, pattrib->iv_len);
|
|
||||||
skb_trim(skb, skb->len - pattrib->icv_len);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
pattrib->encrypt = 0;
|
pattrib->encrypt = 0;
|
||||||
pattrib->iv_len = 0;
|
pattrib->iv_len = 0;
|
||||||
@ -1274,7 +1261,6 @@ static int validate_recv_frame(struct adapter *adapter,
|
|||||||
* Hence forward the frame to the monitor anyway to preserve the order
|
* Hence forward the frame to the monitor anyway to preserve the order
|
||||||
* in which frames were received.
|
* in which frames were received.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
rtl88eu_mon_recv_hook(adapter->pmondev, precv_frame);
|
rtl88eu_mon_recv_hook(adapter->pmondev, precv_frame);
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
@ -1296,8 +1282,11 @@ static int wlanhdr_to_ethhdr(struct recv_frame *precvframe)
|
|||||||
u8 *ptr = precvframe->pkt->data;
|
u8 *ptr = precvframe->pkt->data;
|
||||||
struct rx_pkt_attrib *pattrib = &precvframe->attrib;
|
struct rx_pkt_attrib *pattrib = &precvframe->attrib;
|
||||||
|
|
||||||
psnap = (struct ieee80211_snap_hdr *)(ptr+pattrib->hdrlen);
|
if (pattrib->encrypt)
|
||||||
psnap_type = ptr+pattrib->hdrlen + SNAP_SIZE;
|
skb_trim(precvframe->pkt, precvframe->pkt->len - pattrib->icv_len);
|
||||||
|
|
||||||
|
psnap = (struct ieee80211_snap_hdr *)(ptr+pattrib->hdrlen + pattrib->iv_len);
|
||||||
|
psnap_type = ptr+pattrib->hdrlen + pattrib->iv_len+SNAP_SIZE;
|
||||||
/* convert hdr + possible LLC headers into Ethernet header */
|
/* convert hdr + possible LLC headers into Ethernet header */
|
||||||
if ((!memcmp(psnap, rtw_rfc1042_header, SNAP_SIZE) &&
|
if ((!memcmp(psnap, rtw_rfc1042_header, SNAP_SIZE) &&
|
||||||
(!memcmp(psnap_type, SNAP_ETH_TYPE_IPX, 2) == false) &&
|
(!memcmp(psnap_type, SNAP_ETH_TYPE_IPX, 2) == false) &&
|
||||||
@ -1310,9 +1299,12 @@ static int wlanhdr_to_ethhdr(struct recv_frame *precvframe)
|
|||||||
bsnaphdr = false;
|
bsnaphdr = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
rmv_len = pattrib->hdrlen + (bsnaphdr ? SNAP_SIZE : 0);
|
rmv_len = pattrib->hdrlen + pattrib->iv_len + (bsnaphdr ? SNAP_SIZE : 0);
|
||||||
len = precvframe->pkt->len - rmv_len;
|
len = precvframe->pkt->len - rmv_len;
|
||||||
|
|
||||||
|
RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
|
||||||
|
("\n===pattrib->hdrlen: %x, pattrib->iv_len:%x===\n\n", pattrib->hdrlen, pattrib->iv_len));
|
||||||
|
|
||||||
memcpy(&be_tmp, ptr+rmv_len, 2);
|
memcpy(&be_tmp, ptr+rmv_len, 2);
|
||||||
eth_type = ntohs(be_tmp); /* pattrib->ether_type */
|
eth_type = ntohs(be_tmp); /* pattrib->ether_type */
|
||||||
pattrib->eth_type = eth_type;
|
pattrib->eth_type = eth_type;
|
||||||
@ -1337,6 +1329,7 @@ static struct recv_frame *recvframe_defrag(struct adapter *adapter,
|
|||||||
struct __queue *defrag_q)
|
struct __queue *defrag_q)
|
||||||
{
|
{
|
||||||
struct list_head *plist, *phead;
|
struct list_head *plist, *phead;
|
||||||
|
u8 wlanhdr_offset;
|
||||||
u8 curfragnum;
|
u8 curfragnum;
|
||||||
struct recv_frame *pfhdr, *pnfhdr;
|
struct recv_frame *pfhdr, *pnfhdr;
|
||||||
struct recv_frame *prframe, *pnextrframe;
|
struct recv_frame *prframe, *pnextrframe;
|
||||||
@ -1385,7 +1378,12 @@ static struct recv_frame *recvframe_defrag(struct adapter *adapter,
|
|||||||
/* copy the 2nd~n fragment frame's payload to the first fragment */
|
/* copy the 2nd~n fragment frame's payload to the first fragment */
|
||||||
/* get the 2nd~last fragment frame's payload */
|
/* get the 2nd~last fragment frame's payload */
|
||||||
|
|
||||||
skb_pull(pnextrframe->pkt, pnfhdr->attrib.hdrlen);
|
wlanhdr_offset = pnfhdr->attrib.hdrlen + pnfhdr->attrib.iv_len;
|
||||||
|
|
||||||
|
skb_pull(pnextrframe->pkt, wlanhdr_offset);
|
||||||
|
|
||||||
|
/* append to first fragment frame's tail (if privacy frame, pull the ICV) */
|
||||||
|
skb_trim(prframe->pkt, prframe->pkt->len - pfhdr->attrib.icv_len);
|
||||||
|
|
||||||
/* memcpy */
|
/* memcpy */
|
||||||
memcpy(skb_tail_pointer(pfhdr->pkt), pnfhdr->pkt->data,
|
memcpy(skb_tail_pointer(pfhdr->pkt), pnfhdr->pkt->data,
|
||||||
@ -1393,7 +1391,7 @@ static struct recv_frame *recvframe_defrag(struct adapter *adapter,
|
|||||||
|
|
||||||
skb_put(prframe->pkt, pnfhdr->pkt->len);
|
skb_put(prframe->pkt, pnfhdr->pkt->len);
|
||||||
|
|
||||||
pfhdr->attrib.icv_len = 0;
|
pfhdr->attrib.icv_len = pnfhdr->attrib.icv_len;
|
||||||
plist = plist->next;
|
plist = plist->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1519,6 +1517,11 @@ static int amsdu_to_msdu(struct adapter *padapter, struct recv_frame *prframe)
|
|||||||
nr_subframes = 0;
|
nr_subframes = 0;
|
||||||
pattrib = &prframe->attrib;
|
pattrib = &prframe->attrib;
|
||||||
|
|
||||||
|
skb_pull(prframe->pkt, prframe->attrib.hdrlen);
|
||||||
|
|
||||||
|
if (prframe->attrib.iv_len > 0)
|
||||||
|
skb_pull(prframe->pkt, prframe->attrib.iv_len);
|
||||||
|
|
||||||
a_len = prframe->pkt->len;
|
a_len = prframe->pkt->len;
|
||||||
|
|
||||||
pdata = prframe->pkt->data;
|
pdata = prframe->pkt->data;
|
||||||
@ -1887,6 +1890,24 @@ static int process_recv_indicatepkts(struct adapter *padapter,
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int recv_func_prehandle(struct adapter *padapter,
|
||||||
|
struct recv_frame *rframe)
|
||||||
|
{
|
||||||
|
int ret = _SUCCESS;
|
||||||
|
struct __queue *pfree_recv_queue = &padapter->recvpriv.free_recv_queue;
|
||||||
|
|
||||||
|
/* check the frame crtl field and decache */
|
||||||
|
ret = validate_recv_frame(padapter, rframe);
|
||||||
|
if (ret != _SUCCESS) {
|
||||||
|
RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("recv_func: validate_recv_frame fail! drop pkt\n"));
|
||||||
|
rtw_free_recvframe(rframe, pfree_recv_queue);/* free this recv_frame */
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static int recv_func_posthandle(struct adapter *padapter,
|
static int recv_func_posthandle(struct adapter *padapter,
|
||||||
struct recv_frame *prframe)
|
struct recv_frame *prframe)
|
||||||
{
|
{
|
||||||
@ -1939,7 +1960,6 @@ static int recv_func(struct adapter *padapter, struct recv_frame *rframe)
|
|||||||
struct rx_pkt_attrib *prxattrib = &rframe->attrib;
|
struct rx_pkt_attrib *prxattrib = &rframe->attrib;
|
||||||
struct security_priv *psecuritypriv = &padapter->securitypriv;
|
struct security_priv *psecuritypriv = &padapter->securitypriv;
|
||||||
struct mlme_priv *mlmepriv = &padapter->mlmepriv;
|
struct mlme_priv *mlmepriv = &padapter->mlmepriv;
|
||||||
struct __queue *pfree_recv_queue = &padapter->recvpriv.free_recv_queue;
|
|
||||||
|
|
||||||
/* check if need to handle uc_swdec_pending_queue*/
|
/* check if need to handle uc_swdec_pending_queue*/
|
||||||
if (check_fwstate(mlmepriv, WIFI_STATION_STATE) && psecuritypriv->busetkipkey) {
|
if (check_fwstate(mlmepriv, WIFI_STATION_STATE) && psecuritypriv->busetkipkey) {
|
||||||
@ -1951,12 +1971,9 @@ static int recv_func(struct adapter *padapter, struct recv_frame *rframe)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check the frame crtl field and decache */
|
ret = recv_func_prehandle(padapter, rframe);
|
||||||
ret = validate_recv_frame(padapter, rframe);
|
|
||||||
if (ret != _SUCCESS) {
|
if (ret == _SUCCESS) {
|
||||||
RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("recv_func: validate_recv_frame fail! drop pkt\n"));
|
|
||||||
rtw_free_recvframe(rframe, pfree_recv_queue);/* free this recv_frame */
|
|
||||||
} else {
|
|
||||||
/* check if need to enqueue into uc_swdec_pending_queue*/
|
/* check if need to enqueue into uc_swdec_pending_queue*/
|
||||||
if (check_fwstate(mlmepriv, WIFI_STATION_STATE) &&
|
if (check_fwstate(mlmepriv, WIFI_STATION_STATE) &&
|
||||||
!IS_MCAST(prxattrib->ra) && prxattrib->encrypt > 0 &&
|
!IS_MCAST(prxattrib->ra) && prxattrib->encrypt > 0 &&
|
||||||
|
@ -66,34 +66,6 @@ static void mon_recv_decrypted(struct net_device *dev, const u8 *data,
|
|||||||
netif_rx(skb);
|
netif_rx(skb);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mon_recv_decrypted_recv(struct net_device *dev, const u8 *data,
|
|
||||||
int data_len)
|
|
||||||
{
|
|
||||||
struct sk_buff *skb;
|
|
||||||
struct ieee80211_hdr *hdr;
|
|
||||||
int hdr_len;
|
|
||||||
|
|
||||||
skb = netdev_alloc_skb(dev, data_len);
|
|
||||||
if (!skb)
|
|
||||||
return;
|
|
||||||
memcpy(skb_put(skb, data_len), data, data_len);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Frame data is not encrypted. Strip off protection so
|
|
||||||
* userspace doesn't think that it is.
|
|
||||||
*/
|
|
||||||
|
|
||||||
hdr = (struct ieee80211_hdr *)skb->data;
|
|
||||||
hdr_len = ieee80211_hdrlen(hdr->frame_control);
|
|
||||||
|
|
||||||
if (ieee80211_has_protected(hdr->frame_control))
|
|
||||||
hdr->frame_control &= ~cpu_to_le16(IEEE80211_FCTL_PROTECTED);
|
|
||||||
|
|
||||||
skb->ip_summed = CHECKSUM_UNNECESSARY;
|
|
||||||
skb->protocol = eth_type_trans(skb, dev);
|
|
||||||
netif_rx(skb);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void mon_recv_encrypted(struct net_device *dev, const u8 *data,
|
static void mon_recv_encrypted(struct net_device *dev, const u8 *data,
|
||||||
int data_len)
|
int data_len)
|
||||||
{
|
{
|
||||||
@ -110,6 +82,7 @@ static void mon_recv_encrypted(struct net_device *dev, const u8 *data,
|
|||||||
void rtl88eu_mon_recv_hook(struct net_device *dev, struct recv_frame *frame)
|
void rtl88eu_mon_recv_hook(struct net_device *dev, struct recv_frame *frame)
|
||||||
{
|
{
|
||||||
struct rx_pkt_attrib *attr;
|
struct rx_pkt_attrib *attr;
|
||||||
|
int iv_len, icv_len;
|
||||||
int data_len;
|
int data_len;
|
||||||
u8 *data;
|
u8 *data;
|
||||||
|
|
||||||
@ -122,8 +95,11 @@ void rtl88eu_mon_recv_hook(struct net_device *dev, struct recv_frame *frame)
|
|||||||
data = frame->pkt->data;
|
data = frame->pkt->data;
|
||||||
data_len = frame->pkt->len;
|
data_len = frame->pkt->len;
|
||||||
|
|
||||||
|
/* Broadcast and multicast frames don't have attr->{iv,icv}_len set */
|
||||||
|
SET_ICE_IV_LEN(iv_len, icv_len, attr->encrypt);
|
||||||
|
|
||||||
if (attr->bdecrypted)
|
if (attr->bdecrypted)
|
||||||
mon_recv_decrypted_recv(dev, data, data_len);
|
mon_recv_decrypted(dev, data, data_len, iv_len, icv_len);
|
||||||
else
|
else
|
||||||
mon_recv_encrypted(dev, data, data_len);
|
mon_recv_encrypted(dev, data, data_len);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user