From 66c4d646bfcb2247cff5687f73e7e7d5c4d29c84 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Tue, 19 Mar 2024 08:29:21 +0000 Subject: [PATCH 1/5] rt2800: do not nullify initialization vector data mainline inclusion from mainline-v5.3-rc1 commit 710e6cc1595e25378c4b9977f7a8b4ad4a72a109 category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/I96GO9 CVE: CVE-2023-52595 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=710e6cc1595e -------------------------------- If we restart hw we should keep existing IV (initialization vector) otherwise HW encryption will be broken after restart. Also fix some coding style issues on the way. Signed-off-by: Stanislaw Gruszka Signed-off-by: Kalle Valo Signed-off-by: Pu Lehui --- drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c index a567bc273ffc..e499789674ca 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c @@ -1440,14 +1440,15 @@ static void rt2800_config_wcid_attr_cipher(struct rt2x00_dev *rt2x00dev, offset = MAC_IVEIV_ENTRY(key->hw_key_idx); - memset(&iveiv_entry, 0, sizeof(iveiv_entry)); + rt2800_register_multiread(rt2x00dev, offset, + &iveiv_entry, sizeof(iveiv_entry)); if ((crypto->cipher == CIPHER_TKIP) || (crypto->cipher == CIPHER_TKIP_NO_MIC) || (crypto->cipher == CIPHER_AES)) iveiv_entry.iv[3] |= 0x20; iveiv_entry.iv[3] |= key->keyidx << 6; rt2800_register_multiwrite(rt2x00dev, offset, - &iveiv_entry, sizeof(iveiv_entry)); + &iveiv_entry, sizeof(iveiv_entry)); } int rt2800_config_shared_key(struct rt2x00_dev *rt2x00dev, @@ -5546,13 +5547,11 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) * ASIC will keep garbage value after boot, clear encryption keys. */ for (i = 0; i < 4; i++) - rt2800_register_write(rt2x00dev, - SHARED_KEY_MODE_ENTRY(i), 0); + rt2800_register_write(rt2x00dev, SHARED_KEY_MODE_ENTRY(i), 0); for (i = 0; i < 256; i++) { rt2800_config_wcid(rt2x00dev, NULL, i); rt2800_delete_wcid_attr(rt2x00dev, i); - rt2800_register_write(rt2x00dev, MAC_IVEIV_ENTRY(i), 0); } /* -- Gitee From ae3741cabe42716537fe487ff9b4c98d9f3fc1a5 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Tue, 19 Mar 2024 08:29:22 +0000 Subject: [PATCH 2/5] rt2800: add pre_reset_hw callback mainline inclusion from mainline-v5.3-rc1 commit 09db3b000619b38d504e1fff66efed33dfacb6c0 category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/I96GO9 CVE: CVE-2023-52595 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=09db3b000619 -------------------------------- Add routine to cleanup interfaces data before hw reset as ieee80211_restart_hw() will do setup interfaces again. Signed-off-by: Stanislaw Gruszka Signed-off-by: Kalle Valo Signed-off-by: Pu Lehui --- .../net/wireless/ralink/rt2x00/rt2800lib.c | 19 +++++++++++++++++++ .../net/wireless/ralink/rt2x00/rt2800lib.h | 1 + .../net/wireless/ralink/rt2x00/rt2800pci.c | 1 + .../net/wireless/ralink/rt2x00/rt2800soc.c | 1 + .../net/wireless/ralink/rt2x00/rt2800usb.c | 1 + drivers/net/wireless/ralink/rt2x00/rt2x00.h | 1 + 6 files changed, 24 insertions(+) diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c index e499789674ca..35d656c756b4 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c @@ -1637,6 +1637,25 @@ int rt2800_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, } EXPORT_SYMBOL_GPL(rt2800_sta_remove); +void rt2800_pre_reset_hw(struct rt2x00_dev *rt2x00dev) +{ + struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; + struct data_queue *queue = rt2x00dev->bcn; + struct queue_entry *entry; + int i, wcid; + + for (wcid = WCID_START; wcid < WCID_END; wcid++) { + drv_data->wcid_to_sta[wcid - WCID_START] = NULL; + __clear_bit(wcid - WCID_START, drv_data->sta_ids); + } + + for (i = 0; i < queue->limit; i++) { + entry = &queue->entries[i]; + clear_bit(ENTRY_BCN_ASSIGNED, &entry->flags); + } +} +EXPORT_SYMBOL_GPL(rt2800_pre_reset_hw); + void rt2800_config_filter(struct rt2x00_dev *rt2x00dev, const unsigned int filter_flags) { diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h index 51d9c2a932cc..18c90253cfb1 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h +++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h @@ -254,5 +254,6 @@ void rt2800_disable_wpdma(struct rt2x00_dev *rt2x00dev); void rt2800_get_txwi_rxwi_size(struct rt2x00_dev *rt2x00dev, unsigned short *txwi_size, unsigned short *rxwi_size); +void rt2800_pre_reset_hw(struct rt2x00_dev *rt2x00dev); #endif /* RT2800LIB_H */ diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800pci.c b/drivers/net/wireless/ralink/rt2x00/rt2800pci.c index 71b1affc3885..cf730a47fb15 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2800pci.c @@ -377,6 +377,7 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = { .config_erp = rt2800_config_erp, .config_ant = rt2800_config_ant, .config = rt2800_config, + .pre_reset_hw = rt2800_pre_reset_hw, }; static const struct rt2x00_ops rt2800pci_ops = { diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800soc.c b/drivers/net/wireless/ralink/rt2x00/rt2800soc.c index a502816214ab..752604027108 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2800soc.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2800soc.c @@ -216,6 +216,7 @@ static const struct rt2x00lib_ops rt2800soc_rt2x00_ops = { .config_erp = rt2800_config_erp, .config_ant = rt2800_config_ant, .config = rt2800_config, + .pre_reset_hw = rt2800_pre_reset_hw, }; static const struct rt2x00_ops rt2800soc_ops = { diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800usb.c b/drivers/net/wireless/ralink/rt2x00/rt2800usb.c index 98a7313fea4a..6e31f243aab1 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2800usb.c @@ -858,6 +858,7 @@ static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = { .config_erp = rt2800_config_erp, .config_ant = rt2800_config_ant, .config = rt2800_config, + .pre_reset_hw = rt2800_pre_reset_hw, }; static void rt2800usb_queue_init(struct data_queue *queue) diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00.h b/drivers/net/wireless/ralink/rt2x00/rt2x00.h index 1d21424eae8a..4b3cb2add7fa 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h @@ -626,6 +626,7 @@ struct rt2x00lib_ops { void (*config) (struct rt2x00_dev *rt2x00dev, struct rt2x00lib_conf *libconf, const unsigned int changed_flags); + void (*pre_reset_hw) (struct rt2x00_dev *rt2x00dev); int (*sta_add) (struct rt2x00_dev *rt2x00dev, struct ieee80211_vif *vif, struct ieee80211_sta *sta); -- Gitee From 097f8ac92f9dd475b755049743c5cc19c31a9a76 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Tue, 19 Mar 2024 08:29:23 +0000 Subject: [PATCH 3/5] rt2x00: clear IV's on start to fix AP mode regression mainline inclusion from mainline-v5.3-rc7 commit 95844124385eae4bd9ca5f9514a0fc33d561ac3c category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/I96GO9 CVE: CVE-2023-52595 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=95844124385e -------------------------------- To do not brake HW restart we should keep initialization vectors data. I assumed that on start the data is already initialized to zeros, but that not true on some scenarios and we should clear it. So add additional flag to check if we are under HW restart and clear IV's data if we are not. Patch fixes AP mode regression. Reported-and-tested-by: Emil Karlson Fixes: 710e6cc1595e ("rt2800: do not nullify initialization vector data") Signed-off-by: Stanislaw Gruszka Signed-off-by: Kalle Valo Conflicts: drivers/net/wireless/ralink/rt2x00/rt2x00dev.c Signed-off-by: Pu Lehui --- .../net/wireless/ralink/rt2x00/rt2800lib.c | 9 ++++++++ drivers/net/wireless/ralink/rt2x00/rt2x00.h | 1 + .../net/wireless/ralink/rt2x00/rt2x00dev.c | 23 +++++++++++++------ 3 files changed, 26 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c index 35d656c756b4..d6dca6f98ca5 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c @@ -5573,6 +5573,15 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) rt2800_delete_wcid_attr(rt2x00dev, i); } + /* + * Clear encryption initialization vectors on start, but keep them + * for watchdog reset. Otherwise we will have wrong IVs and not be + * able to keep connections after reset. + */ + if (!test_bit(DEVICE_STATE_RESET, &rt2x00dev->flags)) + for (i = 0; i < 256; i++) + rt2800_register_write(rt2x00dev, MAC_IVEIV_ENTRY(i), 0); + /* * Clear all beacons */ diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00.h b/drivers/net/wireless/ralink/rt2x00/rt2x00.h index 4b3cb2add7fa..d4dfc9c147ea 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h @@ -666,6 +666,7 @@ enum rt2x00_state_flags { DEVICE_STATE_STARTED, DEVICE_STATE_ENABLED_RADIO, DEVICE_STATE_SCANNING, + DEVICE_STATE_RESET, /* * Driver configuration diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c index 357c0941aaad..2c613c69d2b0 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c @@ -1267,10 +1267,17 @@ static int rt2x00lib_initialize(struct rt2x00_dev *rt2x00dev) int rt2x00lib_start(struct rt2x00_dev *rt2x00dev) { - int retval; + int retval = 0; - if (test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags)) - return 0; + if (test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags)) { + /* + * This is special case for ieee80211_restart_hw(), otherwise + * mac80211 never call start() two times in row without stop(); + */ + set_bit(DEVICE_STATE_RESET, &rt2x00dev->flags); + rt2x00dev->ops->lib->pre_reset_hw(rt2x00dev); + rt2x00lib_stop(rt2x00dev); + } /* * If this is the first interface which is added, @@ -1278,14 +1285,14 @@ int rt2x00lib_start(struct rt2x00_dev *rt2x00dev) */ retval = rt2x00lib_load_firmware(rt2x00dev); if (retval) - return retval; + goto out; /* * Initialize the device. */ retval = rt2x00lib_initialize(rt2x00dev); if (retval) - return retval; + goto out; rt2x00dev->intf_ap_count = 0; rt2x00dev->intf_sta_count = 0; @@ -1294,11 +1301,13 @@ int rt2x00lib_start(struct rt2x00_dev *rt2x00dev) /* Enable the radio */ retval = rt2x00lib_enable_radio(rt2x00dev); if (retval) - return retval; + goto out; set_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags); - return 0; +out: + clear_bit(DEVICE_STATE_RESET, &rt2x00dev->flags); + return retval; } void rt2x00lib_stop(struct rt2x00_dev *rt2x00dev) -- Gitee From 821b13fdac14d51246dab2f9c31fcc307580f07d Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Tue, 19 Mar 2024 08:29:24 +0000 Subject: [PATCH 4/5] rt2x00: clear up IV's on key removal mainline inclusion from mainline-v5.3-rc8 commit 14d5e14c8a6c257eb322ddeb294ac4c243a7d2e1 category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/I96GO9 CVE: CVE-2023-52595 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=14d5e14c8a6c -------------------------------- After looking at code I realized that my previous fix 95844124385e ("rt2x00: clear IV's on start to fix AP mode regression") was incomplete. We can still have wrong IV's after re-keyring. To fix that, clear up IV's also on key removal. Fixes: 710e6cc1595e ("rt2800: do not nullify initialization vector data") Signed-off-by: Stanislaw Gruszka tested-by: Emil Karlson Signed-off-by: Kalle Valo Signed-off-by: Pu Lehui --- .../net/wireless/ralink/rt2x00/rt2800lib.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c index d6dca6f98ca5..5c86b657aa9a 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c @@ -1440,13 +1440,18 @@ static void rt2800_config_wcid_attr_cipher(struct rt2x00_dev *rt2x00dev, offset = MAC_IVEIV_ENTRY(key->hw_key_idx); - rt2800_register_multiread(rt2x00dev, offset, - &iveiv_entry, sizeof(iveiv_entry)); - if ((crypto->cipher == CIPHER_TKIP) || - (crypto->cipher == CIPHER_TKIP_NO_MIC) || - (crypto->cipher == CIPHER_AES)) - iveiv_entry.iv[3] |= 0x20; - iveiv_entry.iv[3] |= key->keyidx << 6; + if (crypto->cmd == SET_KEY) { + rt2800_register_multiread(rt2x00dev, offset, + &iveiv_entry, sizeof(iveiv_entry)); + if ((crypto->cipher == CIPHER_TKIP) || + (crypto->cipher == CIPHER_TKIP_NO_MIC) || + (crypto->cipher == CIPHER_AES)) + iveiv_entry.iv[3] |= 0x20; + iveiv_entry.iv[3] |= key->keyidx << 6; + } else { + memset(&iveiv_entry, 0, sizeof(iveiv_entry)); + } + rt2800_register_multiwrite(rt2x00dev, offset, &iveiv_entry, sizeof(iveiv_entry)); } -- Gitee From 72b62a7e1430f097940732400975bdabe5404edf Mon Sep 17 00:00:00 2001 From: Shiji Yang Date: Tue, 19 Mar 2024 08:29:25 +0000 Subject: [PATCH 5/5] wifi: rt2x00: restart beacon queue when hardware reset mainline inclusion from mainline-v6.8-rc1 commit a11d965a218f0cd95b13fe44d0bcd8a20ce134a8 category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/I96GO9 CVE: CVE-2023-52595 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=a11d965a218f -------------------------------- When a hardware reset is triggered, all registers are reset, so all queues are forced to stop in hardware interface. However, mac80211 will not automatically stop the queue. If we don't manually stop the beacon queue, the queue will be deadlocked and unable to start again. This patch fixes the issue where Apple devices cannot connect to the AP after calling ieee80211_restart_hw(). Signed-off-by: Shiji Yang Acked-by: Stanislaw Gruszka Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/TYAP286MB031530EB6D98DCE4DF20766CBCA4A@TYAP286MB0315.JPNP286.PROD.OUTLOOK.COM Signed-off-by: Pu Lehui --- drivers/net/wireless/ralink/rt2x00/rt2x00dev.c | 3 +++ drivers/net/wireless/ralink/rt2x00/rt2x00mac.c | 11 +++++++++++ 2 files changed, 14 insertions(+) diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c index 2c613c69d2b0..5ebbd9b5607a 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c @@ -112,6 +112,7 @@ void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev) rt2x00link_stop_tuner(rt2x00dev); rt2x00queue_stop_queues(rt2x00dev); rt2x00queue_flush_queues(rt2x00dev, true); + rt2x00queue_stop_queue(rt2x00dev->bcn); /* * Disable radio. @@ -1297,6 +1298,7 @@ int rt2x00lib_start(struct rt2x00_dev *rt2x00dev) rt2x00dev->intf_ap_count = 0; rt2x00dev->intf_sta_count = 0; rt2x00dev->intf_associated = 0; + rt2x00dev->intf_beaconing = 0; /* Enable the radio */ retval = rt2x00lib_enable_radio(rt2x00dev); @@ -1324,6 +1326,7 @@ void rt2x00lib_stop(struct rt2x00_dev *rt2x00dev) rt2x00dev->intf_ap_count = 0; rt2x00dev->intf_sta_count = 0; rt2x00dev->intf_associated = 0; + rt2x00dev->intf_beaconing = 0; } static inline void rt2x00lib_set_if_combinations(struct rt2x00_dev *rt2x00dev) diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00mac.c b/drivers/net/wireless/ralink/rt2x00/rt2x00mac.c index da526684596f..99c02fd077d2 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00mac.c @@ -589,6 +589,17 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, */ if (changes & BSS_CHANGED_BEACON_ENABLED) { mutex_lock(&intf->beacon_skb_mutex); + + /* + * Clear the 'enable_beacon' flag and clear beacon because + * the beacon queue has been stopped after hardware reset. + */ + if (test_bit(DEVICE_STATE_RESET, &rt2x00dev->flags) && + intf->enable_beacon) { + intf->enable_beacon = false; + rt2x00queue_clear_beacon(rt2x00dev, vif); + } + if (!bss_conf->enable_beacon && intf->enable_beacon) { rt2x00dev->intf_beaconing--; intf->enable_beacon = false; -- Gitee