From 1b86121806d2a0bb8bfd44a982828af00ac45bfd Mon Sep 17 00:00:00 2001 From: Mathy Vanhoef Date: Fri, 26 Jun 2020 09:27:51 +0400 Subject: [PATCH 1/2] rtl8812a: do not overwrite sequence number of injected frames The sequence number of inject frames was being overwritten. This prevents certain older attacks against WEP fragmentation older TKIP attacks. Fix this by tracking if a frames was injected in monitor mode, and if so, do not overwrite its sequence number. The patch also adds a module parameter to revert this behaviour if needed. By setting rtw_monitor_overwrite_seqnum to 1, sequence numbers will again be set by the driver/device. This may by useful if user-space relied on the driver/device to set sequence numbers. This patch was tested using an Alfa AWUS036ACH. --- core/rtw_xmit.c | 1 + hal/rtl8812a/usb/rtl8812au_xmit.c | 11 +++++++++-- include/drv_types.h | 1 + include/rtw_xmit.h | 1 + os_dep/linux/os_intfs.c | 5 +++++ 5 files changed, 17 insertions(+), 2 deletions(-) diff --git a/core/rtw_xmit.c b/core/rtw_xmit.c index d3a36a2..07d1a28 100644 --- a/core/rtw_xmit.c +++ b/core/rtw_xmit.c @@ -4460,6 +4460,7 @@ s32 rtw_monitor_xmit_entry(struct sk_buff *skb, struct net_device *ndev) /* Check DATA/MGNT frames */ pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; pattrib = &pmgntframe->attrib; + pattrib->injected = _TRUE; if (pregpriv->monitor_disable_1m) { diff --git a/hal/rtl8812a/usb/rtl8812au_xmit.c b/hal/rtl8812a/usb/rtl8812au_xmit.c index 13f4c60..8da4f79 100644 --- a/hal/rtl8812a/usb/rtl8812au_xmit.c +++ b/hal/rtl8812a/usb/rtl8812au_xmit.c @@ -60,6 +60,7 @@ static s32 update_txdesc(struct xmit_frame *pxmitframe, u8 *pmem, s32 sz , u8 ba #endif/*CONFIG_80211N_HT*/ u8 vht_max_ampdu_size = 0; struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter); + struct registry_priv *pregpriv = &(padapter->registrypriv); #ifndef CONFIG_USE_USB_BUFFER_ALLOC_TX if (padapter->registrypriv.mp_mode == 0) { @@ -115,10 +116,16 @@ static s32 update_txdesc(struct xmit_frame *pxmitframe, u8 *pmem, s32 sz , u8 ba /* offset 12 */ - if (!pattrib->qos_en) { + if (pattrib->injected == _TRUE && !pregpriv->monitor_overwrite_seqnum) { + /* Prevent sequence number from being overwritten */ + SET_TX_DESC_HWSEQ_EN_8812(ptxdesc, 0); /* Hw do not set sequence number */ + SET_TX_DESC_SEQ_8812(ptxdesc, pattrib->seqnum); /* Copy inject sequence number to TxDesc */ + } + else if (!pattrib->qos_en) { SET_TX_DESC_HWSEQ_EN_8812(ptxdesc, 1); /* Hw set sequence number */ - } else + } else { SET_TX_DESC_SEQ_8812(ptxdesc, pattrib->seqnum); + } if ((pxmitframe->frame_tag & 0x0f) == DATA_FRAMETAG) { /* RTW_INFO("pxmitframe->frame_tag == DATA_FRAMETAG\n"); */ diff --git a/include/drv_types.h b/include/drv_types.h index 157c0ed..083fe72 100644 --- a/include/drv_types.h +++ b/include/drv_types.h @@ -458,6 +458,7 @@ struct registry_priv { u8 tdmadig_dynamic; #endif/*CONFIG_TDMADIG*/ + u8 monitor_overwrite_seqnum; u8 monitor_disable_1m; }; diff --git a/include/rtw_xmit.h b/include/rtw_xmit.h index 7df0ccd..c1cd928 100644 --- a/include/rtw_xmit.h +++ b/include/rtw_xmit.h @@ -465,6 +465,7 @@ struct pkt_attrib { #endif /* CONFIG_WMMPS_STA */ struct sta_info *psta; + u8 injected; u8 rtsen; u8 cts2self; diff --git a/os_dep/linux/os_intfs.c b/os_dep/linux/os_intfs.c index a3e4e81..00b8e79 100644 --- a/os_dep/linux/os_intfs.c +++ b/os_dep/linux/os_intfs.c @@ -72,6 +72,10 @@ int rtw_scan_mode = 1;/* active, passive */ int rtw_lps_chk_by_tp = 0; #endif /* CONFIG_POWER_SAVING */ +int rtw_monitor_overwrite_seqnum = 0; +module_param(rtw_monitor_overwrite_seqnum, int, 0644); +MODULE_PARM_DESC(rtw_monitor_overwrite_seqnum, "Overwrite the sequence number of injected frames"); + int rtw_monitor_disable_1m = 0; module_param(rtw_monitor_disable_1m, int, 0644); MODULE_PARM_DESC(rtw_monitor_disable_1m, "Disable default 1Mbps rate for monitor injected frames"); @@ -1223,6 +1227,7 @@ uint loadparam(_adapter *padapter) registry_par->fw_tbtt_rpt = rtw_tbtt_rpt; #endif + registry_par->monitor_overwrite_seqnum = (u8)rtw_monitor_overwrite_seqnum; registry_par->monitor_disable_1m = (u8)rtw_monitor_disable_1m; return status; From 849bbf0698dd8e1ad362899f5ec8da4882c94a9f Mon Sep 17 00:00:00 2001 From: Mathy Vanhoef Date: Fri, 26 Jun 2020 16:23:46 +0400 Subject: [PATCH 2/2] rtl8812a: add module parameter to retransmit injected frames The reliability of some attacks is increased by letting the device retransmit injected frames. Since it may not always be desired to retransmit injected frames, add a module parameter to enable it manually. This was tested with an Alfa AWUS036ACH. Even when using a spoofed sender MAC address, the retransmission behaviour is as expected. That is, when an ACK frame towards the spoofed MAC address is received, the retransmission will stop. --- core/rtw_xmit.c | 6 +++++- include/drv_types.h | 1 + os_dep/linux/os_intfs.c | 5 +++++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/core/rtw_xmit.c b/core/rtw_xmit.c index 07d1a28..eb6cbe2 100644 --- a/core/rtw_xmit.c +++ b/core/rtw_xmit.c @@ -4485,7 +4485,11 @@ s32 rtw_monitor_xmit_entry(struct sk_buff *skb, struct net_device *ndev) pattrib->stbc = 0; } - pattrib->retry_ctrl = _FALSE; + + if (pregpriv->monitor_retransmit) + pattrib->retry_ctrl = _TRUE; + else + pattrib->retry_ctrl = _FALSE; pattrib->pktlen = len; pmlmeext->mgnt_seq = GetSequence(pwlanhdr); pattrib->seqnum = pmlmeext->mgnt_seq; diff --git a/include/drv_types.h b/include/drv_types.h index 083fe72..dcfa74c 100644 --- a/include/drv_types.h +++ b/include/drv_types.h @@ -459,6 +459,7 @@ struct registry_priv { #endif/*CONFIG_TDMADIG*/ u8 monitor_overwrite_seqnum; + u8 monitor_retransmit; u8 monitor_disable_1m; }; diff --git a/os_dep/linux/os_intfs.c b/os_dep/linux/os_intfs.c index 00b8e79..aea29b5 100644 --- a/os_dep/linux/os_intfs.c +++ b/os_dep/linux/os_intfs.c @@ -76,6 +76,10 @@ int rtw_monitor_overwrite_seqnum = 0; module_param(rtw_monitor_overwrite_seqnum, int, 0644); MODULE_PARM_DESC(rtw_monitor_overwrite_seqnum, "Overwrite the sequence number of injected frames"); +int rtw_monitor_retransmit = 0; +module_param(rtw_monitor_retransmit, int, 0644); +MODULE_PARM_DESC(rtw_monitor_retransmit, "Retransmit injected frames"); + int rtw_monitor_disable_1m = 0; module_param(rtw_monitor_disable_1m, int, 0644); MODULE_PARM_DESC(rtw_monitor_disable_1m, "Disable default 1Mbps rate for monitor injected frames"); @@ -1228,6 +1232,7 @@ uint loadparam(_adapter *padapter) #endif registry_par->monitor_overwrite_seqnum = (u8)rtw_monitor_overwrite_seqnum; + registry_par->monitor_retransmit = (u8)rtw_monitor_retransmit; registry_par->monitor_disable_1m = (u8)rtw_monitor_disable_1m; return status;