From a556d5e591aa0d9c155b20cdb0f74ced355deabc Mon Sep 17 00:00:00 2001 From: Mathy Vanhoef Date: Mon, 7 Jun 2021 22:38:53 +0800 Subject: [PATCH 1/2] mac80211: assure all fragments are encrypted commit:ddb64a7489623aeaadf212e0dec27e6078027991 CVE:CVE-2020-26147 Signed-off-by:Ywenrui commit 965a7d72e798eb7af0aa67210e37cf7ecd1c9cad upstream. Do not mix plaintext and encrypted fragments in protected Wi-Fi networks. This fixes CVE-2020-26147. Previously, an attacker was able to first forward a legitimate encrypted fragment towards a victim, followed by a plaintext fragment. The encrypted and plaintext fragment would then be reassembled. For further details see Section 6.3 and Appendix D in the paper "Fragment and Forge: Breaking Wi-Fi Through Frame Aggregation and Fragmentation". Because of this change there are now two equivalent conditions in the code to determine if a received fragment requires sequential PNs, so we also move this test to a separate function to make the code easier to maintain. Cc: stable@vger.kernel.org Signed-off-by: Mathy Vanhoef Link: https://lore.kernel.org/r/20210511200110.30c4394bb835.I5acfdb552cc1d20c339c262315950b3eac491397@changeid Signed-off-by: Johannes Berg Signed-off-by: Greg Kroah-Hartman Signed-off-by: Yang Yingliang Signed-off-by: Ywenrui --- net/mac80211/rx.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 5e56719f999c..1907085b1272 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -2078,6 +2078,16 @@ ieee80211_reassemble_find(struct ieee80211_sub_if_data *sdata, return NULL; } +static bool requires_sequential_pn(struct ieee80211_rx_data *rx, __le16 fc) +{ + return rx->key && + (rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP || + rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP_256 || + rx->key->conf.cipher == WLAN_CIPHER_SUITE_GCMP || + rx->key->conf.cipher == WLAN_CIPHER_SUITE_GCMP_256) && + ieee80211_has_protected(fc); +} + static ieee80211_rx_result debug_noinline ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) { @@ -2122,12 +2132,7 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) /* This is the first fragment of a new frame. */ entry = ieee80211_reassemble_add(rx->sdata, frag, seq, rx->seqno_idx, &(rx->skb)); - if (rx->key && - (rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP || - rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP_256 || - rx->key->conf.cipher == WLAN_CIPHER_SUITE_GCMP || - rx->key->conf.cipher == WLAN_CIPHER_SUITE_GCMP_256) && - ieee80211_has_protected(fc)) { + if (requires_sequential_pn(rx, fc)) { int queue = rx->security_idx; /* Store CCMP/GCMP PN so that we can verify that the @@ -2169,11 +2174,7 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) u8 pn[IEEE80211_CCMP_PN_LEN], *rpn; int queue; - if (!rx->key || - (rx->key->conf.cipher != WLAN_CIPHER_SUITE_CCMP && - rx->key->conf.cipher != WLAN_CIPHER_SUITE_CCMP_256 && - rx->key->conf.cipher != WLAN_CIPHER_SUITE_GCMP && - rx->key->conf.cipher != WLAN_CIPHER_SUITE_GCMP_256)) + if (!requires_sequential_pn(rx, fc)) return RX_DROP_UNUSABLE; memcpy(pn, entry->last_pn, IEEE80211_CCMP_PN_LEN); for (i = IEEE80211_CCMP_PN_LEN - 1; i >= 0; i--) { -- Gitee From 55c743c40e4e5ef3fb20d5d6b51f6f90baad0ff8 Mon Sep 17 00:00:00 2001 From: yu kuai Date: Thu, 20 Feb 2020 15:19:36 +0800 Subject: [PATCH 2/2] block: rename 'q->debugfs_dir' and 'q->blk_trace->dir' in blk_unregister_queue() commit:7532f5ad14e4a0c7798752091f0f26e444d44c0c CVE:CVE-2019-19770 Signed-off-by:Ywenrui hulk inclusion category: bugfix bugzilla: 30213 CVE: CVE-2019-19770 --------------------------- syzbot is reporting use after free bug in debugfs_remove[1]. This is because in request_queue, 'q->debugfs_dir' and 'q->blk_trace->dir' could be the same dir. And in __blk_release_queue(), blk_mq_debugfs_unregister() will remove everything inside the dir. With futher investigation of the reporduce repro, the problem can be reporduced by following procedure: 1. LOOP_CTL_ADD, create a request_queue q1, blk_mq_debugfs_register() will create the dir. 2. LOOP_CTL_REMOVE, blk_release_queue() will add q1 to release queue. 3. LOOP_CTL_ADD, create another request_queue q2,blk_mq_debugfs_register() will fail because the dir aready exist. 4. BLKTRACESETUP, create two files(msg and dropped) inside the dir. 5. call __blk_release_queue() for q1, debugfs_remove_recursive() will delete the files created in step 4. 6. LOOP_CTL_REMOVE, blk_release_queue() will add q2 to release queue. And when __blk_release_queue() is called for q2, blk_trace_shutdown() will try to release the two files created in step 4, wich are aready released in step 5. thread1 |kworker |thread2 ----------------------- | ------------------------ | -------------------- loop_control_ioctl | | loop_add | | blk_mq_debugfs_register| | debugfs_create_dir | | loop_control_ioctl | | loop_remove | | blk_release_queue | | schedule_work | | | |loop_control_ioctl | | loop_add | | ... | |blk_trace_ioctl | | __blk_trace_setup | | debugfs_create_file |__blk_release_queue | | blk_mq_debugfs_unregister| | debugfs_remove_recursive| | |loop_control_ioctl | | loop_remove | | ... |__blk_release_queue | | blk_trace_shutdown | | debugfs_remove | commit dc9edc44de6c ("block: Fix a blk_exit_rl() regression") pushed the final release of request_queue to a workqueue, so, when loop_add() is called again(step 3), __blk_release_queue() might not been called yet, which causes the problem. Fix the problem by renaming 'q->debugfs_dir' or 'q->blk_trace->dir' in blk_unregister_queue() if they exist. [1] https://syzkaller.appspot.com/bug?extid=903b72a010ad6b7a40f2 References: CVE-2019-19770 Fixes: commit dc9edc44de6c ("block: Fix a blk_exit_rl() regression") Reported-by: syzbot Signed-off-by: yu kuai Reviewed-by: Jason Yan Signed-off-by: Yang Yingliang Signed-off-by: Ywenrui --- block/blk-sysfs.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c index 8286640d4d66..d249d7f45875 100644 --- a/block/blk-sysfs.c +++ b/block/blk-sysfs.c @@ -11,6 +11,7 @@ #include #include #include +#include #include "blk.h" #include "blk-mq.h" @@ -958,6 +959,48 @@ int blk_register_queue(struct gendisk *disk) } EXPORT_SYMBOL_GPL(blk_register_queue); +#ifdef CONFIG_DEBUG_FS +/* + * blk_prepare_release_queue - rename q->debugfs_dir and q->blk_trace->dir + * @q: request_queue of which the dir to be renamed belong to. + * + * Because the final release of request_queue is in a workqueue, the + * cleanup might not been finished yet while the same device start to + * create. It's not correct if q->debugfs_dir still exist while trying + * to create a new one. + */ +static void blk_prepare_release_queue(struct request_queue *q) +{ + struct dentry *new = NULL; + struct dentry **old = NULL; + char name[DNAME_INLINE_LEN]; + int i = 0; + +#ifdef CONFIG_BLK_DEBUG_FS + if (!IS_ERR_OR_NULL(q->debugfs_dir)) + old = &q->debugfs_dir; +#endif +#ifdef CONFIG_BLK_DEV_IO_TRACE + /* q->debugfs_dir and q->blk_trace->dir can't both exist */ + if (q->blk_trace && !IS_ERR_OR_NULL(q->blk_trace->dir)) + old = &q->blk_trace->dir; +#endif + if (old == NULL) + return; +#define MAX_ATTEMPT 1024 + while (new == NULL && i < MAX_ATTEMPT) { + sprintf(name, "ready_to_remove_%s_%d", + kobject_name(q->kobj.parent), i++); + new = debugfs_rename(blk_debugfs_root, *old, + blk_debugfs_root, name); + } + if (new) + *old = new; +} +#else +#define blk_prepare_release_queue(q) do { } while (0) +#endif + /** * blk_unregister_queue - counterpart of blk_register_queue() * @disk: Disk of which the request queue should be unregistered from sysfs. @@ -982,6 +1025,7 @@ void blk_unregister_queue(struct gendisk *disk) * concurrent elv_iosched_store() calls. */ mutex_lock(&q->sysfs_lock); + blk_prepare_release_queue(q); blk_queue_flag_clear(QUEUE_FLAG_REGISTERED, q); -- Gitee