| .. | .. |
|---|
| 2146 | 2146 | goto exit; |
|---|
| 2147 | 2147 | } |
|---|
| 2148 | 2148 | |
|---|
| 2149 | | - if ((psta->flags & WLAN_STA_AMSDU_DISABLE) && pattrib->amsdu) { |
|---|
| 2150 | | - #ifdef DBG_RX_DROP_FRAME |
|---|
| 2151 | | - RTW_INFO("DBG_RX_DROP_FRAME "FUNC_ADPT_FMT" amsdu not allowed"MAC_FMT"\n" |
|---|
| 2152 | | - , FUNC_ADPT_ARG(adapter), MAC_ARG(psta->cmn.mac_addr)); |
|---|
| 2153 | | - #endif |
|---|
| 2154 | | - ret = _FAIL; |
|---|
| 2155 | | - goto exit; |
|---|
| 2156 | | - |
|---|
| 2157 | | - } |
|---|
| 2158 | | - |
|---|
| 2159 | | - |
|---|
| 2160 | 2149 | precv_frame->u.hdr.psta = psta; |
|---|
| 2161 | 2150 | precv_frame->u.hdr.preorder_ctrl = NULL; |
|---|
| 2162 | 2151 | pattrib->ack_policy = 0; |
|---|
| .. | .. |
|---|
| 2204 | 2193 | #endif |
|---|
| 2205 | 2194 | ret = _FAIL; |
|---|
| 2206 | 2195 | goto exit; |
|---|
| 2207 | | - } |
|---|
| 2208 | | - } |
|---|
| 2209 | | - |
|---|
| 2210 | | - if (pattrib->privacy) { |
|---|
| 2211 | | -#ifdef CONFIG_TDLS |
|---|
| 2212 | | - if ((psta->tdls_sta_state & TDLS_LINKED_STATE) && (psta->dot118021XPrivacy == _AES_)) |
|---|
| 2213 | | - pattrib->encrypt = psta->dot118021XPrivacy; |
|---|
| 2214 | | - else |
|---|
| 2215 | | -#endif /* CONFIG_TDLS */ |
|---|
| 2216 | | - GET_ENCRY_ALGO(psecuritypriv, psta, pattrib->encrypt, IS_MCAST(pattrib->ra)); |
|---|
| 2217 | | - |
|---|
| 2218 | | - |
|---|
| 2219 | | - SET_ICE_IV_LEN(pattrib->iv_len, pattrib->icv_len, pattrib->encrypt); |
|---|
| 2220 | | - } else { |
|---|
| 2221 | | - pattrib->encrypt = 0; |
|---|
| 2222 | | - pattrib->iv_len = pattrib->icv_len = 0; |
|---|
| 2223 | | - } |
|---|
| 2224 | | - |
|---|
| 2225 | | - /* drop unprotected frame in protected network. */ |
|---|
| 2226 | | - if (psecuritypriv->dot11PrivacyAlgrthm != _NO_PRIVACY_ ) { |
|---|
| 2227 | | - if (IS_MCAST(pattrib->ra)) { |
|---|
| 2228 | | - if (!pattrib->privacy) { |
|---|
| 2229 | | - #ifdef DBG_RX_DROP_FRAME |
|---|
| 2230 | | - RTW_INFO("DBG_RX_DROP_FRAME "FUNC_ADPT_FMT"recv plaintext bmc packet for sta="MAC_FMT"\n" |
|---|
| 2231 | | - , FUNC_ADPT_ARG(adapter), MAC_ARG(psta->cmn.mac_addr)); |
|---|
| 2232 | | - #endif |
|---|
| 2233 | | - ret = _FAIL; |
|---|
| 2234 | | - goto exit; |
|---|
| 2235 | | - } |
|---|
| 2236 | | - } else { |
|---|
| 2237 | | - /* unicast */ |
|---|
| 2238 | | - u16 ether_type; |
|---|
| 2239 | | - u8* ether_ptr = NULL; |
|---|
| 2240 | | - u16 eapol_type = 0x888e; |
|---|
| 2241 | | - ether_ptr = ptr + pattrib->hdrlen + pattrib->iv_len + RATTRIB_GET_MCTRL_LEN(pattrib) + LLC_HEADER_SIZE; |
|---|
| 2242 | | - _rtw_memcpy(ðer_type, ether_ptr, 2); |
|---|
| 2243 | | - ether_type = ntohs((unsigned short)ether_type); |
|---|
| 2244 | | - |
|---|
| 2245 | | - if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) { |
|---|
| 2246 | | - /* CVE-2020-26140, CVE-2020-26143, CVE-2020-26147, let eapol packet go through*/ |
|---|
| 2247 | | - if (!pattrib->privacy && ether_type != eapol_type ) { |
|---|
| 2248 | | - #ifdef DBG_RX_DROP_FRAME |
|---|
| 2249 | | - RTW_INFO("DBG_RX_DROP_FRAME "FUNC_ADPT_FMT"recv plaintext unicast packet for sta="MAC_FMT"\n" |
|---|
| 2250 | | - , FUNC_ADPT_ARG(adapter), MAC_ARG(psta->cmn.mac_addr)); |
|---|
| 2251 | | - #endif |
|---|
| 2252 | | - ret = _FAIL; |
|---|
| 2253 | | - goto exit; |
|---|
| 2254 | | - } |
|---|
| 2255 | | - /* CVE-2020-26144, pevernt plaintext A-MSDU */ |
|---|
| 2256 | | - /* This can prevent plantext A-MSDU cloacked as an EAPOL frame */ |
|---|
| 2257 | | - if (!pattrib->privacy && pattrib->amsdu) { |
|---|
| 2258 | | - #ifdef DBG_RX_DROP_FRAME |
|---|
| 2259 | | - RTW_INFO("DBG_RX_DROP_FRAME "FUNC_ADPT_FMT"recv plaintext A-MSDU for sta="MAC_FMT"\n" |
|---|
| 2260 | | - , FUNC_ADPT_ARG(adapter), MAC_ARG(psta->cmn.mac_addr)); |
|---|
| 2261 | | - #endif |
|---|
| 2262 | | - ret = _FAIL; |
|---|
| 2263 | | - goto exit; |
|---|
| 2264 | | - } |
|---|
| 2265 | | - /* CVE-2020-26139, Drop any forwarding eapol packet until 4-way has done. */ |
|---|
| 2266 | | - if ((ether_type == eapol_type) |
|---|
| 2267 | | - && (MLME_IS_AP(adapter) || MLME_IS_MESH(adapter)) |
|---|
| 2268 | | - && (psta->dot118021XPrivacy == _NO_PRIVACY_) |
|---|
| 2269 | | - && (!_rtw_memcmp( adapter_mac_addr(adapter), pattrib->dst, ETH_ALEN))) { |
|---|
| 2270 | | - #ifdef DBG_RX_DROP_FRAME |
|---|
| 2271 | | - RTW_INFO("DBG_RX_DROP_FRAME "FUNC_ADPT_FMT" recv eapol packet forwarding(dst:"MAC_FMT") before 4-way finish.\n" |
|---|
| 2272 | | - , FUNC_ADPT_ARG(adapter), MAC_ARG(pattrib->dst)); |
|---|
| 2273 | | - #endif |
|---|
| 2274 | | - ret = _FAIL; |
|---|
| 2275 | | - goto exit; |
|---|
| 2276 | | - } |
|---|
| 2277 | | - } else { |
|---|
| 2278 | | - /* CVE-2020-26140, CVE-2020-26143, CVE-2020-26147 */ |
|---|
| 2279 | | - if (!pattrib->privacy) { |
|---|
| 2280 | | - #ifdef DBG_RX_DROP_FRAME |
|---|
| 2281 | | - RTW_INFO("DBG_RX_DROP_FRAME "FUNC_ADPT_FMT"recv plaintext packet for sta="MAC_FMT"\n" |
|---|
| 2282 | | - , FUNC_ADPT_ARG(adapter), MAC_ARG(psta->cmn.mac_addr)); |
|---|
| 2283 | | - #endif |
|---|
| 2284 | | - ret = _FAIL; |
|---|
| 2285 | | - goto exit; |
|---|
| 2286 | | - } |
|---|
| 2287 | | - } |
|---|
| 2288 | 2196 | } |
|---|
| 2289 | 2197 | } |
|---|
| 2290 | 2198 | |
|---|
| .. | .. |
|---|
| 2640 | 2548 | union recv_frame *prframe, *pnextrframe; |
|---|
| 2641 | 2549 | _queue *pfree_recv_queue; |
|---|
| 2642 | 2550 | |
|---|
| 2643 | | - u8 *pdata = NULL; |
|---|
| 2644 | | - u64 tmp_iv_hdr = 0; |
|---|
| 2645 | | - u64 pkt_pn = 0, cur_pn = 0; |
|---|
| 2646 | | - struct rx_pkt_attrib *pattrib = NULL; |
|---|
| 2647 | 2551 | |
|---|
| 2648 | 2552 | curfragnum = 0; |
|---|
| 2649 | 2553 | pfree_recv_queue = &adapter->recvpriv.free_recv_queue; |
|---|
| .. | .. |
|---|
| 2651 | 2555 | phead = get_list_head(defrag_q); |
|---|
| 2652 | 2556 | plist = get_next(phead); |
|---|
| 2653 | 2557 | prframe = LIST_CONTAINOR(plist, union recv_frame, u); |
|---|
| 2654 | | - /* CVE-2020-26146 */ |
|---|
| 2655 | | - pattrib = &prframe->u.hdr.attrib; |
|---|
| 2656 | | - if (pattrib->encrypt == _AES_ || pattrib->encrypt == _CCMP_256_ |
|---|
| 2657 | | - || pattrib->encrypt == _GCMP_ || pattrib->encrypt == _GCMP_256_ ) { |
|---|
| 2658 | | - pdata = prframe->u.hdr.rx_data; |
|---|
| 2659 | | - tmp_iv_hdr = le64_to_cpu(*(u64*)(pdata + pattrib->hdrlen)); |
|---|
| 2660 | | - /* get the first frame's PN. */ |
|---|
| 2661 | | - cur_pn = CCMPH_2_PN(tmp_iv_hdr); |
|---|
| 2662 | | - } |
|---|
| 2663 | 2558 | pfhdr = &prframe->u.hdr; |
|---|
| 2664 | 2559 | rtw_list_delete(&(prframe->u.list)); |
|---|
| 2665 | 2560 | |
|---|
| .. | .. |
|---|
| 2689 | 2584 | while (rtw_end_of_queue_search(phead, plist) == _FALSE) { |
|---|
| 2690 | 2585 | pnextrframe = LIST_CONTAINOR(plist, union recv_frame , u); |
|---|
| 2691 | 2586 | pnfhdr = &pnextrframe->u.hdr; |
|---|
| 2692 | | - /* CVE-2020-26146, check whether the PN is consecutive. */ |
|---|
| 2693 | | - pattrib = &pnextrframe->u.hdr.attrib; |
|---|
| 2694 | | - if (pattrib->encrypt == _AES_ || pattrib->encrypt == _CCMP_256_ |
|---|
| 2695 | | - || pattrib->encrypt == _GCMP_ || pattrib->encrypt == _GCMP_256_ ) { |
|---|
| 2696 | | - pdata = pnextrframe->u.hdr.rx_data; |
|---|
| 2697 | | - tmp_iv_hdr = le64_to_cpu(*(u64*)(pdata + pattrib->hdrlen)); |
|---|
| 2698 | | - pkt_pn = CCMPH_2_PN(tmp_iv_hdr); |
|---|
| 2699 | | - if (pkt_pn != cur_pn + 1) { |
|---|
| 2700 | | - RTW_INFO("%s non-consective PN! old:%llu, new:%llu\n", |
|---|
| 2701 | | - __func__, cur_pn, pkt_pn); |
|---|
| 2702 | | - /* PN must be consecutive */ |
|---|
| 2703 | | - /* release the defrag_q & prframe */ |
|---|
| 2704 | | - rtw_free_recvframe(prframe, pfree_recv_queue); |
|---|
| 2705 | | - rtw_free_recvframe_queue(defrag_q, pfree_recv_queue); |
|---|
| 2706 | | - return NULL; |
|---|
| 2707 | | - } else { |
|---|
| 2708 | | - cur_pn = pkt_pn; |
|---|
| 2709 | | - } |
|---|
| 2710 | | - } |
|---|
| 2711 | | - |
|---|
| 2712 | | - /* CVE-2020-24587, The keytrack of the fragment is supposed to be the same with other's */ |
|---|
| 2713 | | - if (pfhdr->keytrack != pnfhdr->keytrack) { |
|---|
| 2714 | | - RTW_INFO("Inconsistent key track, drop fragmented frame!\n"); |
|---|
| 2715 | | - rtw_free_recvframe(prframe, pfree_recv_queue); |
|---|
| 2716 | | - rtw_free_recvframe_queue(defrag_q, pfree_recv_queue); |
|---|
| 2717 | | - return NULL; |
|---|
| 2718 | | - } |
|---|
| 2719 | 2587 | |
|---|
| 2720 | 2588 | |
|---|
| 2721 | 2589 | /* check the fragment sequence (2nd ~n fragment frame) */ |
|---|
| .. | .. |
|---|
| 2728 | 2596 | return NULL; |
|---|
| 2729 | 2597 | } |
|---|
| 2730 | 2598 | |
|---|
| 2599 | + curfragnum++; |
|---|
| 2600 | + |
|---|
| 2731 | 2601 | /* copy the 2nd~n fragment frame's payload to the first fragment */ |
|---|
| 2732 | 2602 | /* get the 2nd~last fragment frame's payload */ |
|---|
| 2733 | 2603 | |
|---|
| 2734 | 2604 | wlanhdr_offset = pnfhdr->attrib.hdrlen + pnfhdr->attrib.iv_len; |
|---|
| 2735 | 2605 | |
|---|
| 2736 | 2606 | recvframe_pull(pnextrframe, wlanhdr_offset); |
|---|
| 2737 | | - |
|---|
| 2738 | | - if ((pfhdr->rx_end - pfhdr->rx_tail) < pnfhdr->len) { |
|---|
| 2739 | | - RTW_INFO("Not enough buffer space, drop fragmented frame!\n"); |
|---|
| 2740 | | - rtw_free_recvframe(prframe, pfree_recv_queue); |
|---|
| 2741 | | - rtw_free_recvframe_queue(defrag_q, pfree_recv_queue); |
|---|
| 2742 | | - return NULL; |
|---|
| 2743 | | - } |
|---|
| 2744 | | - |
|---|
| 2745 | | - curfragnum++; |
|---|
| 2746 | 2607 | |
|---|
| 2747 | 2608 | /* append to first fragment frame's tail (if privacy frame, pull the ICV) */ |
|---|
| 2748 | 2609 | recvframe_pull_tail(prframe, pfhdr->attrib.icv_len); |
|---|
| .. | .. |
|---|
| 2804 | 2665 | |
|---|
| 2805 | 2666 | if ((ismfrag == 0) && (fragnum == 0)) { |
|---|
| 2806 | 2667 | prtnframe = precv_frame;/* isn't a fragment frame */ |
|---|
| 2807 | | - } else { |
|---|
| 2808 | | - /* CVE-2020-26145, group addressed frame cannot use fragmentation!! */ |
|---|
| 2809 | | - if (IS_MCAST(pfhdr->attrib.ra)) { |
|---|
| 2810 | | - RTW_INFO("DROP group addressed fragment!\n"); |
|---|
| 2811 | | - rtw_free_recvframe(precv_frame, pfree_recv_queue); |
|---|
| 2812 | | - return NULL; |
|---|
| 2813 | | - } |
|---|
| 2814 | | - /* CVE-2020-24587 */ |
|---|
| 2815 | | - if ((psta) && (pdefrag_q)) |
|---|
| 2816 | | - precv_frame->u.hdr.keytrack = ATOMIC_READ(&psta->keytrack); |
|---|
| 2817 | | - |
|---|
| 2818 | 2668 | } |
|---|
| 2819 | 2669 | |
|---|
| 2820 | 2670 | if (ismfrag == 1) { |
|---|
| .. | .. |
|---|
| 3052 | 2902 | } |
|---|
| 3053 | 2903 | #endif /* defined(CONFIG_AP_MODE) || defined(CONFIG_RTW_MESH) */ |
|---|
| 3054 | 2904 | |
|---|
| 3055 | | -/* |
|---|
| 3056 | | - * From WFA suggestion: * |
|---|
| 3057 | | - * If first subframe meets one of the following condition, * |
|---|
| 3058 | | - * the whole received AMSDU should drop. * |
|---|
| 3059 | | - * 1. subframe's DA is not the same as RA in From DS case. * |
|---|
| 3060 | | - * 2. subframe's SA is not the same as TA in To DS case. * |
|---|
| 3061 | | - * 3. subframe's DA is AA:AA:03:00:00:00 * |
|---|
| 3062 | | - */ |
|---|
| 3063 | | -static u8 validate_amsdu_content(_adapter *padapter, union recv_frame *prframe, |
|---|
| 3064 | | - const u8 *da, const u8 *sa) |
|---|
| 3065 | | -{ |
|---|
| 3066 | | - struct rx_pkt_attrib *pattrib = &prframe->u.hdr.attrib; |
|---|
| 3067 | | - u8 ret = _SUCCESS; |
|---|
| 3068 | | - |
|---|
| 3069 | | - /* Use the recommendation method form Wi-Fi alliance to check subframe */ |
|---|
| 3070 | | - /* in protected network */ |
|---|
| 3071 | | - if (padapter->registrypriv.amsdu_mode == RTW_AMSDU_MODE_NON_SPP && |
|---|
| 3072 | | - padapter->securitypriv.dot11PrivacyAlgrthm != _NO_PRIVACY_) { |
|---|
| 3073 | | - |
|---|
| 3074 | | - /* 1.check From DS */ |
|---|
| 3075 | | - if (pattrib->to_fr_ds == 2) { |
|---|
| 3076 | | - if (_rtw_memcmp(da, pattrib->ra, ETH_ALEN) == _FALSE) |
|---|
| 3077 | | - ret = _FAIL; |
|---|
| 3078 | | - } |
|---|
| 3079 | | - |
|---|
| 3080 | | - /* 2.check To DS */ |
|---|
| 3081 | | - if (pattrib->to_fr_ds == 1) { |
|---|
| 3082 | | - if (_rtw_memcmp(sa, pattrib->ta, ETH_ALEN) == _FALSE) |
|---|
| 3083 | | - ret = _FAIL; |
|---|
| 3084 | | - } |
|---|
| 3085 | | - |
|---|
| 3086 | | - /* 3.Check whether DA is AA:AA:03:00:00:00 */ |
|---|
| 3087 | | - if (_rtw_memcmp(da, rtw_rfc1042_header, ETH_ALEN) == _TRUE) |
|---|
| 3088 | | - ret = _FAIL; |
|---|
| 3089 | | - |
|---|
| 3090 | | - } |
|---|
| 3091 | | - |
|---|
| 3092 | | - return ret; |
|---|
| 3093 | | - |
|---|
| 3094 | | -} |
|---|
| 3095 | | - |
|---|
| 3096 | 2905 | int amsdu_to_msdu(_adapter *padapter, union recv_frame *prframe) |
|---|
| 3097 | 2906 | { |
|---|
| 3098 | 2907 | struct rx_pkt_attrib *rattrib = &prframe->u.hdr.attrib; |
|---|
| .. | .. |
|---|
| 3146 | 2955 | |
|---|
| 3147 | 2956 | v_ret = rtw_mesh_rx_data_validate_mctrl(padapter, prframe |
|---|
| 3148 | 2957 | , mctrl, mda, msa, &mctrl_len, &da, &sa); |
|---|
| 3149 | | - |
|---|
| 3150 | | - if (validate_amsdu_content(padapter, prframe, da, sa) == _FAIL) { |
|---|
| 3151 | | - RTW_INFO("%s check subframe content fail!\n", __func__); |
|---|
| 3152 | | - break; |
|---|
| 3153 | | - } |
|---|
| 3154 | | - |
|---|
| 3155 | 2958 | if (v_ret != _SUCCESS) |
|---|
| 3156 | 2959 | goto move_to_next; |
|---|
| 3157 | 2960 | |
|---|
| .. | .. |
|---|
| 3165 | 2968 | { |
|---|
| 3166 | 2969 | da = pdata; |
|---|
| 3167 | 2970 | sa = pdata + ETH_ALEN; |
|---|
| 3168 | | - |
|---|
| 3169 | | - if (validate_amsdu_content(padapter, prframe, da, sa) == _FAIL) { |
|---|
| 3170 | | - RTW_INFO("%s check subframe content fail!\n", __func__); |
|---|
| 3171 | | - break; |
|---|
| 3172 | | - } |
|---|
| 3173 | | - |
|---|
| 3174 | 2971 | llc_hdl = rtw_recv_llc_parse(pdata + ETH_HLEN, nSubframe_Length); |
|---|
| 3175 | 2972 | #ifdef CONFIG_AP_MODE |
|---|
| 3176 | 2973 | if (MLME_IS_AP(padapter)) { |
|---|
| .. | .. |
|---|
| 4867 | 4664 | s32 err = _SUCCESS; |
|---|
| 4868 | 4665 | #ifdef RTW_RECV_THREAD_HIGH_PRIORITY |
|---|
| 4869 | 4666 | #ifdef PLATFORM_LINUX |
|---|
| 4870 | | -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0)) |
|---|
| 4871 | | - sched_set_fifo_low(current); |
|---|
| 4872 | | -#else |
|---|
| 4873 | 4667 | struct sched_param param = { .sched_priority = 1 }; |
|---|
| 4874 | | - |
|---|
| 4668 | + |
|---|
| 4875 | 4669 | sched_setscheduler(current, SCHED_FIFO, ¶m); |
|---|
| 4876 | | -#endif |
|---|
| 4877 | 4670 | #endif /* PLATFORM_LINUX */ |
|---|
| 4878 | 4671 | #endif /*RTW_RECV_THREAD_HIGH_PRIORITY*/ |
|---|
| 4879 | 4672 | thread_enter("RTW_RECV_THREAD"); |
|---|