mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-07-16 14:30:06 -04:00
Merge tag 'staging-7.2-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging
Pull staging driver fixes from Greg KH: "Here are some staging driver fixes for 7.2-rc3 for some reported bugs in the vme_user and rtl8723bs drivers. These include: - many rtl8723bs OOB fixes for when connecting to "bad" wifi hosts - vme_user bugfixes to correctly validate some user-provided data All of these have been in linux-next for a while with no reported issues" * tag 'staging-7.2-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging: staging: rtl8723bs: fix OOB reads in rtw_get_sec_ie(), rtw_get_wapi_ie(), and rtw_get_wps_attr() staging: rtl8723bs: fix OOB reads in is_ap_in_tkip() IE loop staging: rtl8723bs: fix OOB read in OnAssocRsp() IE loop staging: rtl8723bs: fix OOB write in HT_caps_handler() staging: rtl8723bs: fix heap buffer overflow in rtw_cfg80211_set_wpa_ie() staging: rtl8723bs: fix OOB reads in IE loops in issue_assocreq() and join_cmd_hdl() staging: rtl8723bs: fix OOB read in update_beacon_info() IE loop staging: rtl8723bs: fix WEP length underflow and OOB read in OnAuth() staging: vme_user: fix location monitor leak in tsi148 bridge staging: vme_user: fix location monitor leak in fake bridge staging: vme_user: bound slave read/write to the kern_buf size staging: rtl8723bs: don't drop short TX frames in _rtw_pktfile_read()
This commit is contained in:
@@ -583,9 +583,14 @@ int rtw_get_wapi_ie(u8 *in_ie, uint in_len, u8 *wapi_ie, u16 *wapi_len)
|
||||
cnt = (_TIMESTAMP_ + _BEACON_ITERVAL_ + _CAPABILITY_);
|
||||
|
||||
while (cnt < in_len) {
|
||||
if (cnt + 2 > in_len)
|
||||
break;
|
||||
if (cnt + 2 + in_ie[cnt + 1] > in_len)
|
||||
break;
|
||||
authmode = in_ie[cnt];
|
||||
|
||||
if (authmode == WLAN_EID_BSS_AC_ACCESS_DELAY &&
|
||||
in_ie[cnt + 1] >= 8 &&
|
||||
(!memcmp(&in_ie[cnt + 6], wapi_oui1, 4) ||
|
||||
!memcmp(&in_ie[cnt + 6], wapi_oui2, 4))) {
|
||||
if (wapi_ie)
|
||||
@@ -615,9 +620,14 @@ void rtw_get_sec_ie(u8 *in_ie, uint in_len, u8 *rsn_ie, u16 *rsn_len, u8 *wpa_ie
|
||||
cnt = (_TIMESTAMP_ + _BEACON_ITERVAL_ + _CAPABILITY_);
|
||||
|
||||
while (cnt < in_len) {
|
||||
if (cnt + 2 > in_len)
|
||||
break;
|
||||
if (cnt + 2 + in_ie[cnt + 1] > in_len)
|
||||
break;
|
||||
authmode = in_ie[cnt];
|
||||
|
||||
if ((authmode == WLAN_EID_VENDOR_SPECIFIC) &&
|
||||
in_ie[cnt + 1] >= 4 &&
|
||||
(!memcmp(&in_ie[cnt + 2], &wpa_oui[0], 4))) {
|
||||
if (wpa_ie)
|
||||
memcpy(wpa_ie, &in_ie[cnt], in_ie[cnt + 1] + 2);
|
||||
@@ -698,6 +708,9 @@ u8 *rtw_get_wps_attr(u8 *wps_ie, uint wps_ielen, u16 target_attr_id, u8 *buf_att
|
||||
if (len_attr)
|
||||
*len_attr = 0;
|
||||
|
||||
if (wps_ielen < 6)
|
||||
return attr_ptr;
|
||||
|
||||
if ((wps_ie[0] != WLAN_EID_VENDOR_SPECIFIC) ||
|
||||
(memcmp(wps_ie + 2, wps_oui, 4))) {
|
||||
return attr_ptr;
|
||||
@@ -708,6 +721,8 @@ u8 *rtw_get_wps_attr(u8 *wps_ie, uint wps_ielen, u16 target_attr_id, u8 *buf_att
|
||||
|
||||
while (attr_ptr - wps_ie < wps_ielen) {
|
||||
/* 4 = 2(Attribute ID) + 2(Length) */
|
||||
if (attr_ptr + 4 > wps_ie + wps_ielen)
|
||||
break;
|
||||
u16 attr_id = get_unaligned_be16(attr_ptr);
|
||||
u16 attr_data_len = get_unaligned_be16(attr_ptr + 2);
|
||||
u16 attr_len = attr_data_len + 4;
|
||||
|
||||
@@ -677,6 +677,9 @@ unsigned int OnAuth(struct adapter *padapter, union recv_frame *precv_frame)
|
||||
if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
|
||||
return _FAIL;
|
||||
|
||||
if (len < WLAN_HDR_A3_LEN)
|
||||
return _FAIL;
|
||||
|
||||
sa = GetAddr2Ptr(pframe);
|
||||
|
||||
auth_mode = psecuritypriv->dot11AuthAlgrthm;
|
||||
@@ -688,6 +691,9 @@ unsigned int OnAuth(struct adapter *padapter, union recv_frame *precv_frame)
|
||||
prxattrib->hdrlen = WLAN_HDR_A3_LEN;
|
||||
prxattrib->encrypt = _WEP40_;
|
||||
|
||||
if (len < WLAN_HDR_A3_LEN + 8)
|
||||
return _FAIL;
|
||||
|
||||
iv = pframe+prxattrib->hdrlen;
|
||||
prxattrib->key_index = ((iv[3]>>6)&0x3);
|
||||
|
||||
@@ -787,7 +793,7 @@ unsigned int OnAuth(struct adapter *padapter, union recv_frame *precv_frame)
|
||||
p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + 4 + _AUTH_IE_OFFSET_, WLAN_EID_CHALLENGE, (int *)&ie_len,
|
||||
len - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_ - 4);
|
||||
|
||||
if (!p || ie_len <= 0) {
|
||||
if (!p || ie_len != 128) {
|
||||
status = WLAN_STATUS_CHALLENGE_FAIL;
|
||||
goto auth_fail;
|
||||
}
|
||||
@@ -1365,7 +1371,11 @@ unsigned int OnAssocRsp(struct adapter *padapter, union recv_frame *precv_frame)
|
||||
/* to handle HT, WMM, rate adaptive, update MAC reg */
|
||||
/* for not to handle the synchronous IO in the tasklet */
|
||||
for (i = (6 + WLAN_HDR_A3_LEN); i < pkt_len;) {
|
||||
if (i + sizeof(*pIE) > pkt_len)
|
||||
break;
|
||||
pIE = (struct ndis_80211_var_ie *)(pframe + i);
|
||||
if (i + sizeof(*pIE) + pIE->length > pkt_len)
|
||||
break;
|
||||
|
||||
switch (pIE->element_id) {
|
||||
case WLAN_EID_VENDOR_SPECIFIC:
|
||||
@@ -2855,7 +2865,11 @@ void issue_assocreq(struct adapter *padapter)
|
||||
|
||||
/* vendor specific IE, such as WPA, WMM, WPS */
|
||||
for (i = sizeof(struct ndis_802_11_fix_ie); i < pmlmeinfo->network.ie_length;) {
|
||||
if (i + sizeof(*pIE) > pmlmeinfo->network.ie_length)
|
||||
break;
|
||||
pIE = (struct ndis_80211_var_ie *)(pmlmeinfo->network.ies + i);
|
||||
if (i + sizeof(*pIE) + pIE->length > pmlmeinfo->network.ie_length)
|
||||
break;
|
||||
|
||||
switch (pIE->element_id) {
|
||||
case WLAN_EID_VENDOR_SPECIFIC:
|
||||
@@ -5183,7 +5197,11 @@ u8 join_cmd_hdl(struct adapter *padapter, u8 *pbuf)
|
||||
|
||||
/* sizeof(struct ndis_802_11_fix_ie) */
|
||||
for (i = _FIXED_IE_LENGTH_; i < pnetwork->ie_length;) {
|
||||
if (i + sizeof(*pIE) > pnetwork->ie_length)
|
||||
break;
|
||||
pIE = (struct ndis_80211_var_ie *)(pnetwork->ies + i);
|
||||
if (i + sizeof(*pIE) + pIE->length > pnetwork->ie_length)
|
||||
break;
|
||||
|
||||
switch (pIE->element_id) {
|
||||
case WLAN_EID_VENDOR_SPECIFIC:/* Get WMM IE. */
|
||||
|
||||
@@ -909,7 +909,8 @@ void HT_caps_handler(struct adapter *padapter, struct ndis_80211_var_ie *pIE)
|
||||
|
||||
pmlmeinfo->HT_caps_enable = 1;
|
||||
|
||||
for (i = 0; i < (pIE->length); i++) {
|
||||
for (i = 0; i < umin(pIE->length,
|
||||
sizeof(pmlmeinfo->HT_caps.u.HT_cap)); i++) {
|
||||
if (i != 2) {
|
||||
/* Commented by Albert 2010/07/12 */
|
||||
/* Got the endian issue here. */
|
||||
@@ -1262,7 +1263,11 @@ void update_beacon_info(struct adapter *padapter, u8 *pframe, uint pkt_len, stru
|
||||
len = pkt_len - (_BEACON_IE_OFFSET_ + WLAN_HDR_A3_LEN);
|
||||
|
||||
for (i = 0; i < len;) {
|
||||
if (i + sizeof(*pIE) > len)
|
||||
break;
|
||||
pIE = (struct ndis_80211_var_ie *)(pframe + (_BEACON_IE_OFFSET_ + WLAN_HDR_A3_LEN) + i);
|
||||
if (i + sizeof(*pIE) + pIE->length > len)
|
||||
break;
|
||||
|
||||
switch (pIE->element_id) {
|
||||
case WLAN_EID_VENDOR_SPECIFIC:
|
||||
@@ -1287,7 +1292,7 @@ void update_beacon_info(struct adapter *padapter, u8 *pframe, uint pkt_len, stru
|
||||
break;
|
||||
}
|
||||
|
||||
i += (pIE->length + 2);
|
||||
i += sizeof(*pIE) + pIE->length;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1303,15 +1308,23 @@ unsigned int is_ap_in_tkip(struct adapter *padapter)
|
||||
for (i = sizeof(struct ndis_802_11_fix_ie); i < pmlmeinfo->network.ie_length;) {
|
||||
pIE = (struct ndis_80211_var_ie *)(pmlmeinfo->network.ies + i);
|
||||
|
||||
if (i + sizeof(*pIE) > pmlmeinfo->network.ie_length)
|
||||
break;
|
||||
if (i + sizeof(*pIE) + pIE->length > pmlmeinfo->network.ie_length)
|
||||
break;
|
||||
|
||||
switch (pIE->element_id) {
|
||||
case WLAN_EID_VENDOR_SPECIFIC:
|
||||
if ((!memcmp(pIE->data, RTW_WPA_OUI, 4)) && (!memcmp((pIE->data + 12), WPA_TKIP_CIPHER, 4)))
|
||||
if (pIE->length >= 16 &&
|
||||
!memcmp(pIE->data, RTW_WPA_OUI, 4) &&
|
||||
!memcmp((pIE->data + 12), WPA_TKIP_CIPHER, 4))
|
||||
return true;
|
||||
|
||||
break;
|
||||
|
||||
case WLAN_EID_RSN:
|
||||
if (!memcmp((pIE->data + 8), RSN_TKIP_CIPHER, 4))
|
||||
if (pIE->length >= 12 &&
|
||||
!memcmp((pIE->data + 8), RSN_TKIP_CIPHER, 4))
|
||||
return true;
|
||||
break;
|
||||
|
||||
@@ -1319,7 +1332,7 @@ unsigned int is_ap_in_tkip(struct adapter *padapter)
|
||||
break;
|
||||
}
|
||||
|
||||
i += (pIE->length + 2);
|
||||
i += sizeof(*pIE) + pIE->length;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
@@ -1446,6 +1446,10 @@ static int rtw_cfg80211_set_wpa_ie(struct adapter *padapter, u8 *pie, size_t iel
|
||||
|
||||
pwpa = rtw_get_wpa_ie(buf, &wpa_ielen, ielen);
|
||||
if (pwpa && wpa_ielen > 0) {
|
||||
if (wpa_ielen + 2 > sizeof(padapter->securitypriv.supplicant_ie)) {
|
||||
ret = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
if (rtw_parse_wpa_ie(pwpa, wpa_ielen + 2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
|
||||
padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
|
||||
padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPAPSK;
|
||||
@@ -1455,6 +1459,10 @@ static int rtw_cfg80211_set_wpa_ie(struct adapter *padapter, u8 *pie, size_t iel
|
||||
|
||||
pwpa2 = rtw_get_wpa2_ie(buf, &wpa2_ielen, ielen);
|
||||
if (pwpa2 && wpa2_ielen > 0) {
|
||||
if (wpa2_ielen + 2 > sizeof(padapter->securitypriv.supplicant_ie)) {
|
||||
ret = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
if (rtw_parse_wpa2_ie(pwpa2, wpa2_ielen + 2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
|
||||
padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
|
||||
padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPA2PSK;
|
||||
|
||||
@@ -24,9 +24,11 @@ void _rtw_open_pktfile(struct sk_buff *pktptr, struct pkt_file *pfile)
|
||||
int _rtw_pktfile_read(struct pkt_file *pfile, u8 *rmem, unsigned int rlen)
|
||||
{
|
||||
int ret;
|
||||
unsigned int remain = rtw_remainder_len(pfile);
|
||||
|
||||
if (rtw_remainder_len(pfile) < rlen)
|
||||
return -EINVAL;
|
||||
/* clamp to bytes remaining; the coalesce loop relies on short reads */
|
||||
if (rlen > remain)
|
||||
rlen = remain;
|
||||
|
||||
if (rmem) {
|
||||
ret = skb_copy_bits(pfile->pkt, pfile->buf_len - pfile->pkt_len, rmem, rlen);
|
||||
|
||||
@@ -1239,6 +1239,7 @@ static void __exit fake_exit(void)
|
||||
{
|
||||
struct list_head *pos = NULL;
|
||||
struct list_head *tmplist;
|
||||
struct vme_lm_resource *lm;
|
||||
struct vme_master_resource *master_image;
|
||||
struct vme_slave_resource *slave_image;
|
||||
int i;
|
||||
@@ -1268,6 +1269,13 @@ static void __exit fake_exit(void)
|
||||
vme_unregister_bridge(fake_bridge);
|
||||
|
||||
fake_crcsr_exit(fake_bridge);
|
||||
/* resources are stored in link list */
|
||||
list_for_each_safe(pos, tmplist, &fake_bridge->lm_resources) {
|
||||
lm = list_entry(pos, struct vme_lm_resource, list);
|
||||
list_del(pos);
|
||||
kfree(lm);
|
||||
}
|
||||
|
||||
/* resources are stored in link list */
|
||||
list_for_each_safe(pos, tmplist, &fake_bridge->slave_resources) {
|
||||
slave_image = list_entry(pos, struct vme_slave_resource, list);
|
||||
|
||||
@@ -2534,6 +2534,7 @@ static void tsi148_remove(struct pci_dev *pdev)
|
||||
{
|
||||
struct list_head *pos = NULL;
|
||||
struct list_head *tmplist;
|
||||
struct vme_lm_resource *lm;
|
||||
struct vme_master_resource *master_image;
|
||||
struct vme_slave_resource *slave_image;
|
||||
struct vme_dma_resource *dma_ctrlr;
|
||||
@@ -2590,6 +2591,13 @@ static void tsi148_remove(struct pci_dev *pdev)
|
||||
|
||||
tsi148_crcsr_exit(tsi148_bridge, pdev);
|
||||
|
||||
/* resources are stored in link list */
|
||||
list_for_each_safe(pos, tmplist, &tsi148_bridge->lm_resources) {
|
||||
lm = list_entry(pos, struct vme_lm_resource, list);
|
||||
list_del(pos);
|
||||
kfree(lm);
|
||||
}
|
||||
|
||||
/* resources are stored in link list */
|
||||
list_for_each_safe(pos, tmplist, &tsi148_bridge->dma_resources) {
|
||||
dma_ctrlr = list_entry(pos, struct vme_dma_resource, list);
|
||||
|
||||
@@ -156,6 +156,17 @@ static ssize_t buffer_to_user(unsigned int minor, char __user *buf,
|
||||
{
|
||||
void *image_ptr;
|
||||
|
||||
/*
|
||||
* The slave window (image_size) can exceed the fixed kern_buf
|
||||
* (size_buf == PCI_BUF_SIZE), so bound the copy to kern_buf.
|
||||
* *ppos is >= 0 here (checked by the caller), so the
|
||||
* subtraction below cannot wrap.
|
||||
*/
|
||||
if (*ppos >= image[minor].size_buf)
|
||||
return 0;
|
||||
if (count > image[minor].size_buf - *ppos)
|
||||
count = image[minor].size_buf - *ppos;
|
||||
|
||||
image_ptr = image[minor].kern_buf + *ppos;
|
||||
if (copy_to_user(buf, image_ptr, (unsigned long)count))
|
||||
return -EFAULT;
|
||||
@@ -168,6 +179,17 @@ static ssize_t buffer_from_user(unsigned int minor, const char __user *buf,
|
||||
{
|
||||
void *image_ptr;
|
||||
|
||||
/*
|
||||
* The slave window (image_size) can exceed the fixed kern_buf
|
||||
* (size_buf == PCI_BUF_SIZE), so bound the copy to kern_buf.
|
||||
* *ppos is >= 0 here (checked by the caller), so the
|
||||
* subtraction below cannot wrap.
|
||||
*/
|
||||
if (*ppos >= image[minor].size_buf)
|
||||
return 0;
|
||||
if (count > image[minor].size_buf - *ppos)
|
||||
count = image[minor].size_buf - *ppos;
|
||||
|
||||
image_ptr = image[minor].kern_buf + *ppos;
|
||||
if (copy_from_user(image_ptr, buf, (unsigned long)count))
|
||||
return -EFAULT;
|
||||
|
||||
Reference in New Issue
Block a user