From 125907f2b575aba4f6c8118544b0d179a210c47a Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 8 Sep 2022 19:09:51 +0200 Subject: [PATCH] 4.14-stable patches added patches: efi-capsule-loader-fix-use-after-free-in-efi_capsule_write.patch fs-only-do-a-memory-barrier-for-the-first-set_buffer_uptodate.patch revert-mm-kmemleak-take-a-full-lowmem-check-in-kmemleak_-_phys.patch wifi-iwlegacy-4965-corrected-fix-for-potential-off-by-one-overflow-in-il4965_rs_fill_link_cmd.patch --- ...-use-after-free-in-efi_capsule_write.patch | 82 +++++++++++++++++ ...er-for-the-first-set_buffer_uptodate.patch | 72 +++++++++++++++ ...full-lowmem-check-in-kmemleak_-_phys.patch | 88 +++++++++++++++++++ queue-4.14/series | 4 + ...-overflow-in-il4965_rs_fill_link_cmd.patch | 51 +++++++++++ 5 files changed, 297 insertions(+) create mode 100644 queue-4.14/efi-capsule-loader-fix-use-after-free-in-efi_capsule_write.patch create mode 100644 queue-4.14/fs-only-do-a-memory-barrier-for-the-first-set_buffer_uptodate.patch create mode 100644 queue-4.14/revert-mm-kmemleak-take-a-full-lowmem-check-in-kmemleak_-_phys.patch create mode 100644 queue-4.14/wifi-iwlegacy-4965-corrected-fix-for-potential-off-by-one-overflow-in-il4965_rs_fill_link_cmd.patch diff --git a/queue-4.14/efi-capsule-loader-fix-use-after-free-in-efi_capsule_write.patch b/queue-4.14/efi-capsule-loader-fix-use-after-free-in-efi_capsule_write.patch new file mode 100644 index 00000000000..23ddbc73f67 --- /dev/null +++ b/queue-4.14/efi-capsule-loader-fix-use-after-free-in-efi_capsule_write.patch @@ -0,0 +1,82 @@ +From 9cb636b5f6a8cc6d1b50809ec8f8d33ae0c84c95 Mon Sep 17 00:00:00 2001 +From: Hyunwoo Kim +Date: Wed, 7 Sep 2022 09:07:14 -0700 +Subject: efi: capsule-loader: Fix use-after-free in efi_capsule_write + +From: Hyunwoo Kim + +commit 9cb636b5f6a8cc6d1b50809ec8f8d33ae0c84c95 upstream. + +A race condition may occur if the user calls close() on another thread +during a write() operation on the device node of the efi capsule. + +This is a race condition that occurs between the efi_capsule_write() and +efi_capsule_flush() functions of efi_capsule_fops, which ultimately +results in UAF. + +So, the page freeing process is modified to be done in +efi_capsule_release() instead of efi_capsule_flush(). + +Cc: # v4.9+ +Signed-off-by: Hyunwoo Kim +Link: https://lore.kernel.org/all/20220907102920.GA88602@ubuntu/ +Signed-off-by: Ard Biesheuvel +Signed-off-by: Greg Kroah-Hartman +--- + drivers/firmware/efi/capsule-loader.c | 31 +++++++------------------------ + 1 file changed, 7 insertions(+), 24 deletions(-) + +--- a/drivers/firmware/efi/capsule-loader.c ++++ b/drivers/firmware/efi/capsule-loader.c +@@ -238,29 +238,6 @@ failed: + } + + /** +- * efi_capsule_flush - called by file close or file flush +- * @file: file pointer +- * @id: not used +- * +- * If a capsule is being partially uploaded then calling this function +- * will be treated as upload termination and will free those completed +- * buffer pages and -ECANCELED will be returned. +- **/ +-static int efi_capsule_flush(struct file *file, fl_owner_t id) +-{ +- int ret = 0; +- struct capsule_info *cap_info = file->private_data; +- +- if (cap_info->index > 0) { +- pr_err("capsule upload not complete\n"); +- efi_free_all_buff_pages(cap_info); +- ret = -ECANCELED; +- } +- +- return ret; +-} +- +-/** + * efi_capsule_release - called by file close + * @inode: not used + * @file: file pointer +@@ -272,6 +249,13 @@ static int efi_capsule_release(struct in + { + struct capsule_info *cap_info = file->private_data; + ++ if (cap_info->index > 0 && ++ (cap_info->header.headersize == 0 || ++ cap_info->count < cap_info->total_size)) { ++ pr_err("capsule upload not complete\n"); ++ efi_free_all_buff_pages(cap_info); ++ } ++ + kfree(cap_info->pages); + kfree(cap_info->phys); + kfree(file->private_data); +@@ -319,7 +303,6 @@ static const struct file_operations efi_ + .owner = THIS_MODULE, + .open = efi_capsule_open, + .write = efi_capsule_write, +- .flush = efi_capsule_flush, + .release = efi_capsule_release, + .llseek = no_llseek, + }; diff --git a/queue-4.14/fs-only-do-a-memory-barrier-for-the-first-set_buffer_uptodate.patch b/queue-4.14/fs-only-do-a-memory-barrier-for-the-first-set_buffer_uptodate.patch new file mode 100644 index 00000000000..6dad1e3f34b --- /dev/null +++ b/queue-4.14/fs-only-do-a-memory-barrier-for-the-first-set_buffer_uptodate.patch @@ -0,0 +1,72 @@ +From 2f79cdfe58c13949bbbb65ba5926abfe9561d0ec Mon Sep 17 00:00:00 2001 +From: Linus Torvalds +Date: Wed, 31 Aug 2022 09:46:12 -0700 +Subject: fs: only do a memory barrier for the first set_buffer_uptodate() + +From: Linus Torvalds + +commit 2f79cdfe58c13949bbbb65ba5926abfe9561d0ec upstream. + +Commit d4252071b97d ("add barriers to buffer_uptodate and +set_buffer_uptodate") added proper memory barriers to the buffer head +BH_Uptodate bit, so that anybody who tests a buffer for being up-to-date +will be guaranteed to actually see initialized state. + +However, that commit didn't _just_ add the memory barrier, it also ended +up dropping the "was it already set" logic that the BUFFER_FNS() macro +had. + +That's conceptually the right thing for a generic "this is a memory +barrier" operation, but in the case of the buffer contents, we really +only care about the memory barrier for the _first_ time we set the bit, +in that the only memory ordering protection we need is to avoid anybody +seeing uninitialized memory contents. + +Any other access ordering wouldn't be about the BH_Uptodate bit anyway, +and would require some other proper lock (typically BH_Lock or the folio +lock). A reader that races with somebody invalidating the buffer head +isn't an issue wrt the memory ordering, it's a serialization issue. + +Now, you'd think that the buffer head operations don't matter in this +day and age (and I certainly thought so), but apparently some loads +still end up being heavy users of buffer heads. In particular, the +kernel test robot reported that not having this bit access optimization +in place caused a noticeable direct IO performance regression on ext4: + + fxmark.ssd_ext4_no_jnl_DWTL_54_directio.works/sec -26.5% regression + +although you presumably need a fast disk and a lot of cores to actually +notice. + +Link: https://lore.kernel.org/all/Yw8L7HTZ%2FdE2%2Fo9C@xsang-OptiPlex-9020/ +Reported-by: kernel test robot +Tested-by: Fengwei Yin +Cc: Mikulas Patocka +Cc: Matthew Wilcox (Oracle) +Cc: stable@kernel.org +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/buffer_head.h | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +--- a/include/linux/buffer_head.h ++++ b/include/linux/buffer_head.h +@@ -134,6 +134,17 @@ BUFFER_FNS(Defer_Completion, defer_compl + static __always_inline void set_buffer_uptodate(struct buffer_head *bh) + { + /* ++ * If somebody else already set this uptodate, they will ++ * have done the memory barrier, and a reader will thus ++ * see *some* valid buffer state. ++ * ++ * Any other serialization (with IO errors or whatever that ++ * might clear the bit) has to come from other state (eg BH_Lock). ++ */ ++ if (test_bit(BH_Uptodate, &bh->b_state)) ++ return; ++ ++ /* + * make it consistent with folio_mark_uptodate + * pairs with smp_load_acquire in buffer_uptodate + */ diff --git a/queue-4.14/revert-mm-kmemleak-take-a-full-lowmem-check-in-kmemleak_-_phys.patch b/queue-4.14/revert-mm-kmemleak-take-a-full-lowmem-check-in-kmemleak_-_phys.patch new file mode 100644 index 00000000000..0741d0ebb9c --- /dev/null +++ b/queue-4.14/revert-mm-kmemleak-take-a-full-lowmem-check-in-kmemleak_-_phys.patch @@ -0,0 +1,88 @@ +From yee.lee@mediatek.com Thu Sep 8 19:05:17 2022 +From: +Date: Tue, 6 Sep 2022 15:03:06 +0800 +Subject: Revert "mm: kmemleak: take a full lowmem check in kmemleak_*_phys()" +To: +Cc: , Yee Lee , , Catalin Marinas , "Andrew Morton" , Matthias Brugger , "open list:MEMORY MANAGEMENT" , "moderated list:ARM/Mediatek SoC support" , "moderated list:ARM/Mediatek SoC support" +Message-ID: <20220906070309.18809-1-yee.lee@mediatek.com> + +From: Yee Lee + +This reverts commit 23c2d497de21f25898fbea70aeb292ab8acc8c94. + +Commit 23c2d497de21 ("mm: kmemleak: take a full lowmem check in +kmemleak_*_phys()") brought false leak alarms on some archs like arm64 +that does not init pfn boundary in early booting. The final solution +lands on linux-6.0: commit 0c24e061196c ("mm: kmemleak: add rbtree and +store physical address for objects allocated with PA"). + +Revert this commit before linux-6.0. The original issue of invalid PA +can be mitigated by additional check in devicetree. + +The false alarm report is as following: Kmemleak output: (Qemu/arm64) +unreferenced object 0xffff0000c0170a00 (size 128): + comm "swapper/0", pid 1, jiffies 4294892404 (age 126.208s) + hex dump (first 32 bytes): + 62 61 73 65 00 00 00 00 00 00 00 00 00 00 00 00 base............ + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ + backtrace: + [<(____ptrval____)>] __kmalloc_track_caller+0x1b0/0x2e4 + [<(____ptrval____)>] kstrdup_const+0x8c/0xc4 + [<(____ptrval____)>] kvasprintf_const+0xbc/0xec + [<(____ptrval____)>] kobject_set_name_vargs+0x58/0xe4 + [<(____ptrval____)>] kobject_add+0x84/0x100 + [<(____ptrval____)>] __of_attach_node_sysfs+0x78/0xec + [<(____ptrval____)>] of_core_init+0x68/0x104 + [<(____ptrval____)>] driver_init+0x28/0x48 + [<(____ptrval____)>] do_basic_setup+0x14/0x28 + [<(____ptrval____)>] kernel_init_freeable+0x110/0x178 + [<(____ptrval____)>] kernel_init+0x20/0x1a0 + [<(____ptrval____)>] ret_from_fork+0x10/0x20 + +This pacth is also applicable to linux-5.17.y/linux-5.18.y/linux-5.19.y + +Cc: +Signed-off-by: Yee Lee +Signed-off-by: Greg Kroah-Hartman +--- + mm/kmemleak.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/mm/kmemleak.c ++++ b/mm/kmemleak.c +@@ -1192,7 +1192,7 @@ EXPORT_SYMBOL(kmemleak_no_scan); + void __ref kmemleak_alloc_phys(phys_addr_t phys, size_t size, int min_count, + gfp_t gfp) + { +- if (PHYS_PFN(phys) >= min_low_pfn && PHYS_PFN(phys) < max_low_pfn) ++ if (!IS_ENABLED(CONFIG_HIGHMEM) || PHYS_PFN(phys) < max_low_pfn) + kmemleak_alloc(__va(phys), size, min_count, gfp); + } + EXPORT_SYMBOL(kmemleak_alloc_phys); +@@ -1203,7 +1203,7 @@ EXPORT_SYMBOL(kmemleak_alloc_phys); + */ + void __ref kmemleak_free_part_phys(phys_addr_t phys, size_t size) + { +- if (PHYS_PFN(phys) >= min_low_pfn && PHYS_PFN(phys) < max_low_pfn) ++ if (!IS_ENABLED(CONFIG_HIGHMEM) || PHYS_PFN(phys) < max_low_pfn) + kmemleak_free_part(__va(phys), size); + } + EXPORT_SYMBOL(kmemleak_free_part_phys); +@@ -1214,7 +1214,7 @@ EXPORT_SYMBOL(kmemleak_free_part_phys); + */ + void __ref kmemleak_not_leak_phys(phys_addr_t phys) + { +- if (PHYS_PFN(phys) >= min_low_pfn && PHYS_PFN(phys) < max_low_pfn) ++ if (!IS_ENABLED(CONFIG_HIGHMEM) || PHYS_PFN(phys) < max_low_pfn) + kmemleak_not_leak(__va(phys)); + } + EXPORT_SYMBOL(kmemleak_not_leak_phys); +@@ -1225,7 +1225,7 @@ EXPORT_SYMBOL(kmemleak_not_leak_phys); + */ + void __ref kmemleak_ignore_phys(phys_addr_t phys) + { +- if (PHYS_PFN(phys) >= min_low_pfn && PHYS_PFN(phys) < max_low_pfn) ++ if (!IS_ENABLED(CONFIG_HIGHMEM) || PHYS_PFN(phys) < max_low_pfn) + kmemleak_ignore(__va(phys)); + } + EXPORT_SYMBOL(kmemleak_ignore_phys); diff --git a/queue-4.14/series b/queue-4.14/series index df58b175856..a5360722192 100644 --- a/queue-4.14/series +++ b/queue-4.14/series @@ -31,3 +31,7 @@ wifi-mac80211-don-t-finalize-csa-in-ibss-mode-if-state-is-disconnected.patch net-mac802154-fix-a-condition-in-the-receive-path.patch alsa-seq-oss-fix-data-race-for-max_midi_devs-access.patch alsa-seq-fix-data-race-at-module-auto-loading.patch +efi-capsule-loader-fix-use-after-free-in-efi_capsule_write.patch +wifi-iwlegacy-4965-corrected-fix-for-potential-off-by-one-overflow-in-il4965_rs_fill_link_cmd.patch +fs-only-do-a-memory-barrier-for-the-first-set_buffer_uptodate.patch +revert-mm-kmemleak-take-a-full-lowmem-check-in-kmemleak_-_phys.patch diff --git a/queue-4.14/wifi-iwlegacy-4965-corrected-fix-for-potential-off-by-one-overflow-in-il4965_rs_fill_link_cmd.patch b/queue-4.14/wifi-iwlegacy-4965-corrected-fix-for-potential-off-by-one-overflow-in-il4965_rs_fill_link_cmd.patch new file mode 100644 index 00000000000..2be47fb2a76 --- /dev/null +++ b/queue-4.14/wifi-iwlegacy-4965-corrected-fix-for-potential-off-by-one-overflow-in-il4965_rs_fill_link_cmd.patch @@ -0,0 +1,51 @@ +From 6d0ef7241553f3553a0a2764c69b07892705924c Mon Sep 17 00:00:00 2001 +From: Stanislaw Gruszka +Date: Mon, 15 Aug 2022 09:37:37 +0200 +Subject: wifi: iwlegacy: 4965: corrected fix for potential off-by-one overflow in il4965_rs_fill_link_cmd() + +From: Stanislaw Gruszka + +commit 6d0ef7241553f3553a0a2764c69b07892705924c upstream. + +This reverts commit a8eb8e6f7159c7c20c0ddac428bde3d110890aa7 as +it can cause invalid link quality command sent to the firmware +and address the off-by-one issue by fixing condition of while loop. + +Cc: stable@vger.kernel.org +Fixes: a8eb8e6f7159 ("wifi: iwlegacy: 4965: fix potential off-by-one overflow in il4965_rs_fill_link_cmd()") +Signed-off-by: Stanislaw Gruszka +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20220815073737.GA999388@wp.pl +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/wireless/intel/iwlegacy/4965-rs.c | 5 +---- + 1 file changed, 1 insertion(+), 4 deletions(-) + +--- a/drivers/net/wireless/intel/iwlegacy/4965-rs.c ++++ b/drivers/net/wireless/intel/iwlegacy/4965-rs.c +@@ -2424,7 +2424,7 @@ il4965_rs_fill_link_cmd(struct il_priv * + /* Repeat initial/next rate. + * For legacy IL_NUMBER_TRY == 1, this loop will not execute. + * For HT IL_HT_NUMBER_TRY == 3, this executes twice. */ +- while (repeat_rate > 0) { ++ while (repeat_rate > 0 && idx < (LINK_QUAL_MAX_RETRY_NUM - 1)) { + if (is_legacy(tbl_type.lq_type)) { + if (ant_toggle_cnt < NUM_TRY_BEFORE_ANT_TOGGLE) + ant_toggle_cnt++; +@@ -2443,8 +2443,6 @@ il4965_rs_fill_link_cmd(struct il_priv * + cpu_to_le32(new_rate); + repeat_rate--; + idx++; +- if (idx >= LINK_QUAL_MAX_RETRY_NUM) +- goto out; + } + + il4965_rs_get_tbl_info_from_mcs(new_rate, lq_sta->band, +@@ -2489,7 +2487,6 @@ il4965_rs_fill_link_cmd(struct il_priv * + repeat_rate--; + } + +-out: + lq_cmd->agg_params.agg_frame_cnt_limit = LINK_QUAL_AGG_FRAME_LIMIT_DEF; + lq_cmd->agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF; + -- 2.47.3