From: Greg Kroah-Hartman Date: Sun, 23 Aug 2020 12:38:25 +0000 (+0200) Subject: 4.19-stable patches X-Git-Tag: v4.4.234~48 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=34a700055f0e3bd939986eaa30d8fe2f7610179b;p=thirdparty%2Fkernel%2Fstable-queue.git 4.19-stable patches added patches: drm-amd-display-fix-pow-crashing-when-given-base-0.patch ext4-fix-checking-of-directory-entry-validity-for-inline-directories.patch jbd2-add-the-missing-unlock_buffer-in-the-error-path-of-jbd2_write_superblock.patch kernel-relay.c-fix-memleak-on-destroy-relay-channel.patch mm-include-cma-pages-in-lowmem_reserve-at-boot.patch mm-memory.c-skip-spurious-tlb-flush-for-retried-page-fault.patch mm-page_alloc-fix-core-hung-in-free_pcppages_bulk.patch romfs-fix-uninitialized-memory-leak-in-romfs_dev_read.patch scsi-zfcp-fix-use-after-free-in-request-timeout-handlers.patch --- diff --git a/queue-4.19/drm-amd-display-fix-pow-crashing-when-given-base-0.patch b/queue-4.19/drm-amd-display-fix-pow-crashing-when-given-base-0.patch new file mode 100644 index 00000000000..fe58232be0d --- /dev/null +++ b/queue-4.19/drm-amd-display-fix-pow-crashing-when-given-base-0.patch @@ -0,0 +1,36 @@ +From d2e59d0ff4c44d1f6f8ed884a5bea7d1bb7fd98c Mon Sep 17 00:00:00 2001 +From: Krunoslav Kovac +Date: Thu, 6 Aug 2020 17:54:47 -0400 +Subject: drm/amd/display: fix pow() crashing when given base 0 + +From: Krunoslav Kovac + +commit d2e59d0ff4c44d1f6f8ed884a5bea7d1bb7fd98c upstream. + +[Why&How] +pow(a,x) is implemented as exp(x*log(a)). log(0) will crash. +So return 0^x = 0, unless x=0, convention seems to be 0^0 = 1. + +Cc: stable@vger.kernel.org +Signed-off-by: Krunoslav Kovac +Reviewed-by: Anthony Koo +Acked-by: Rodrigo Siqueira +Signed-off-by: Alex Deucher +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/amd/display/include/fixed31_32.h | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/gpu/drm/amd/display/include/fixed31_32.h ++++ b/drivers/gpu/drm/amd/display/include/fixed31_32.h +@@ -431,6 +431,9 @@ struct fixed31_32 dc_fixpt_log(struct fi + */ + static inline struct fixed31_32 dc_fixpt_pow(struct fixed31_32 arg1, struct fixed31_32 arg2) + { ++ if (arg1.value == 0) ++ return arg2.value == 0 ? dc_fixpt_one : dc_fixpt_zero; ++ + return dc_fixpt_exp( + dc_fixpt_mul( + dc_fixpt_log(arg1), diff --git a/queue-4.19/ext4-fix-checking-of-directory-entry-validity-for-inline-directories.patch b/queue-4.19/ext4-fix-checking-of-directory-entry-validity-for-inline-directories.patch new file mode 100644 index 00000000000..cda2bdbab8d --- /dev/null +++ b/queue-4.19/ext4-fix-checking-of-directory-entry-validity-for-inline-directories.patch @@ -0,0 +1,56 @@ +From 7303cb5bfe845f7d43cd9b2dbd37dbb266efda9b Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Fri, 31 Jul 2020 18:21:35 +0200 +Subject: ext4: fix checking of directory entry validity for inline directories + +From: Jan Kara + +commit 7303cb5bfe845f7d43cd9b2dbd37dbb266efda9b upstream. + +ext4_search_dir() and ext4_generic_delete_entry() can be called both for +standard director blocks and for inline directories stored inside inode +or inline xattr space. For the second case we didn't call +ext4_check_dir_entry() with proper constraints that could result in +accepting corrupted directory entry as well as false positive filesystem +errors like: + +EXT4-fs error (device dm-0): ext4_search_dir:1395: inode #28320400: +block 113246792: comm dockerd: bad entry in directory: directory entry too +close to block end - offset=0, inode=28320403, rec_len=32, name_len=8, +size=4096 + +Fix the arguments passed to ext4_check_dir_entry(). + +Fixes: 109ba779d6cc ("ext4: check for directory entries too close to block end") +CC: stable@vger.kernel.org +Signed-off-by: Jan Kara +Link: https://lore.kernel.org/r/20200731162135.8080-1-jack@suse.cz +Signed-off-by: Theodore Ts'o +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/namei.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/fs/ext4/namei.c ++++ b/fs/ext4/namei.c +@@ -1309,8 +1309,8 @@ int ext4_search_dir(struct buffer_head * + ext4_match(fname, de)) { + /* found a match - just to be sure, do + * a full check */ +- if (ext4_check_dir_entry(dir, NULL, de, bh, bh->b_data, +- bh->b_size, offset)) ++ if (ext4_check_dir_entry(dir, NULL, de, bh, search_buf, ++ buf_size, offset)) + return -1; + *res_dir = de; + return 1; +@@ -2344,7 +2344,7 @@ int ext4_generic_delete_entry(handle_t * + de = (struct ext4_dir_entry_2 *)entry_buf; + while (i < buf_size - csum_size) { + if (ext4_check_dir_entry(dir, NULL, de, bh, +- bh->b_data, bh->b_size, i)) ++ entry_buf, buf_size, i)) + return -EFSCORRUPTED; + if (de == de_del) { + if (pde) diff --git a/queue-4.19/jbd2-add-the-missing-unlock_buffer-in-the-error-path-of-jbd2_write_superblock.patch b/queue-4.19/jbd2-add-the-missing-unlock_buffer-in-the-error-path-of-jbd2_write_superblock.patch new file mode 100644 index 00000000000..6544d187bdb --- /dev/null +++ b/queue-4.19/jbd2-add-the-missing-unlock_buffer-in-the-error-path-of-jbd2_write_superblock.patch @@ -0,0 +1,39 @@ +From ef3f5830b859604eda8723c26d90ab23edc027a4 Mon Sep 17 00:00:00 2001 +From: "zhangyi (F)" +Date: Sat, 20 Jun 2020 14:19:48 +0800 +Subject: jbd2: add the missing unlock_buffer() in the error path of jbd2_write_superblock() + +From: zhangyi (F) + +commit ef3f5830b859604eda8723c26d90ab23edc027a4 upstream. + +jbd2_write_superblock() is under the buffer lock of journal superblock +before ending that superblock write, so add a missing unlock_buffer() in +in the error path before submitting buffer. + +Fixes: 742b06b5628f ("jbd2: check superblock mapped prior to committing") +Signed-off-by: zhangyi (F) +Reviewed-by: Ritesh Harjani +Cc: stable@kernel.org +Link: https://lore.kernel.org/r/20200620061948.2049579-1-yi.zhang@huawei.com +Signed-off-by: Theodore Ts'o +Signed-off-by: Greg Kroah-Hartman + +--- + fs/jbd2/journal.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/fs/jbd2/journal.c ++++ b/fs/jbd2/journal.c +@@ -1370,8 +1370,10 @@ static int jbd2_write_superblock(journal + int ret; + + /* Buffer got discarded which means block device got invalidated */ +- if (!buffer_mapped(bh)) ++ if (!buffer_mapped(bh)) { ++ unlock_buffer(bh); + return -EIO; ++ } + + trace_jbd2_write_superblock(journal, write_flags); + if (!(journal->j_flags & JBD2_BARRIER)) diff --git a/queue-4.19/kernel-relay.c-fix-memleak-on-destroy-relay-channel.patch b/queue-4.19/kernel-relay.c-fix-memleak-on-destroy-relay-channel.patch new file mode 100644 index 00000000000..ab5bfb61b61 --- /dev/null +++ b/queue-4.19/kernel-relay.c-fix-memleak-on-destroy-relay-channel.patch @@ -0,0 +1,65 @@ +From 71e843295c680898959b22dc877ae3839cc22470 Mon Sep 17 00:00:00 2001 +From: Wei Yongjun +Date: Thu, 20 Aug 2020 17:42:14 -0700 +Subject: kernel/relay.c: fix memleak on destroy relay channel + +From: Wei Yongjun + +commit 71e843295c680898959b22dc877ae3839cc22470 upstream. + +kmemleak report memory leak as follows: + + unreferenced object 0x607ee4e5f948 (size 8): + comm "syz-executor.1", pid 2098, jiffies 4295031601 (age 288.468s) + hex dump (first 8 bytes): + 00 00 00 00 00 00 00 00 ........ + backtrace: + relay_open kernel/relay.c:583 [inline] + relay_open+0xb6/0x970 kernel/relay.c:563 + do_blk_trace_setup+0x4a8/0xb20 kernel/trace/blktrace.c:557 + __blk_trace_setup+0xb6/0x150 kernel/trace/blktrace.c:597 + blk_trace_ioctl+0x146/0x280 kernel/trace/blktrace.c:738 + blkdev_ioctl+0xb2/0x6a0 block/ioctl.c:613 + block_ioctl+0xe5/0x120 fs/block_dev.c:1871 + vfs_ioctl fs/ioctl.c:48 [inline] + __do_sys_ioctl fs/ioctl.c:753 [inline] + __se_sys_ioctl fs/ioctl.c:739 [inline] + __x64_sys_ioctl+0x170/0x1ce fs/ioctl.c:739 + do_syscall_64+0x33/0x40 arch/x86/entry/common.c:46 + entry_SYSCALL_64_after_hwframe+0x44/0xa9 + +'chan->buf' is malloced in relay_open() by alloc_percpu() but not free +while destroy the relay channel. Fix it by adding free_percpu() before +return from relay_destroy_channel(). + +Fixes: 017c59c042d0 ("relay: Use per CPU constructs for the relay channel buffer pointers") +Reported-by: Hulk Robot +Signed-off-by: Wei Yongjun +Signed-off-by: Andrew Morton +Reviewed-by: Chris Wilson +Cc: Al Viro +Cc: Michael Ellerman +Cc: David Rientjes +Cc: Michel Lespinasse +Cc: Daniel Axtens +Cc: Thomas Gleixner +Cc: Akash Goel +Cc: +Link: http://lkml.kernel.org/r/20200817122826.48518-1-weiyongjun1@huawei.com +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + kernel/relay.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/kernel/relay.c ++++ b/kernel/relay.c +@@ -197,6 +197,7 @@ free_buf: + static void relay_destroy_channel(struct kref *kref) + { + struct rchan *chan = container_of(kref, struct rchan, kref); ++ free_percpu(chan->buf); + kfree(chan); + } + diff --git a/queue-4.19/mm-include-cma-pages-in-lowmem_reserve-at-boot.patch b/queue-4.19/mm-include-cma-pages-in-lowmem_reserve-at-boot.patch new file mode 100644 index 00000000000..7b5b7c4bcd8 --- /dev/null +++ b/queue-4.19/mm-include-cma-pages-in-lowmem_reserve-at-boot.patch @@ -0,0 +1,85 @@ +From e08d3fdfe2dafa0331843f70ce1ff6c1c4900bf4 Mon Sep 17 00:00:00 2001 +From: Doug Berger +Date: Thu, 20 Aug 2020 17:42:24 -0700 +Subject: mm: include CMA pages in lowmem_reserve at boot + +From: Doug Berger + +commit e08d3fdfe2dafa0331843f70ce1ff6c1c4900bf4 upstream. + +The lowmem_reserve arrays provide a means of applying pressure against +allocations from lower zones that were targeted at higher zones. Its +values are a function of the number of pages managed by higher zones and +are assigned by a call to the setup_per_zone_lowmem_reserve() function. + +The function is initially called at boot time by the function +init_per_zone_wmark_min() and may be called later by accesses of the +/proc/sys/vm/lowmem_reserve_ratio sysctl file. + +The function init_per_zone_wmark_min() was moved up from a module_init to +a core_initcall to resolve a sequencing issue with khugepaged. +Unfortunately this created a sequencing issue with CMA page accounting. + +The CMA pages are added to the managed page count of a zone when +cma_init_reserved_areas() is called at boot also as a core_initcall. This +makes it uncertain whether the CMA pages will be added to the managed page +counts of their zones before or after the call to +init_per_zone_wmark_min() as it becomes dependent on link order. With the +current link order the pages are added to the managed count after the +lowmem_reserve arrays are initialized at boot. + +This means the lowmem_reserve values at boot may be lower than the values +used later if /proc/sys/vm/lowmem_reserve_ratio is accessed even if the +ratio values are unchanged. + +In many cases the difference is not significant, but for example +an ARM platform with 1GB of memory and the following memory layout + + cma: Reserved 256 MiB at 0x0000000030000000 + Zone ranges: + DMA [mem 0x0000000000000000-0x000000002fffffff] + Normal empty + HighMem [mem 0x0000000030000000-0x000000003fffffff] + +would result in 0 lowmem_reserve for the DMA zone. This would allow +userspace to deplete the DMA zone easily. + +Funnily enough + + $ cat /proc/sys/vm/lowmem_reserve_ratio + +would fix up the situation because as a side effect it forces +setup_per_zone_lowmem_reserve. + +This commit breaks the link order dependency by invoking +init_per_zone_wmark_min() as a postcore_initcall so that the CMA pages +have the chance to be properly accounted in their zone(s) and allowing +the lowmem_reserve arrays to receive consistent values. + +Fixes: bc22af74f271 ("mm: update min_free_kbytes from khugepaged after core initialization") +Signed-off-by: Doug Berger +Signed-off-by: Andrew Morton +Acked-by: Michal Hocko +Cc: Jason Baron +Cc: David Rientjes +Cc: "Kirill A. Shutemov" +Cc: +Link: http://lkml.kernel.org/r/1597423766-27849-1-git-send-email-opendmb@gmail.com +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + mm/page_alloc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/mm/page_alloc.c ++++ b/mm/page_alloc.c +@@ -7395,7 +7395,7 @@ int __meminit init_per_zone_wmark_min(vo + + return 0; + } +-core_initcall(init_per_zone_wmark_min) ++postcore_initcall(init_per_zone_wmark_min) + + /* + * min_free_kbytes_sysctl_handler - just a wrapper around proc_dointvec() so diff --git a/queue-4.19/mm-memory.c-skip-spurious-tlb-flush-for-retried-page-fault.patch b/queue-4.19/mm-memory.c-skip-spurious-tlb-flush-for-retried-page-fault.patch new file mode 100644 index 00000000000..c12f05008b5 --- /dev/null +++ b/queue-4.19/mm-memory.c-skip-spurious-tlb-flush-for-retried-page-fault.patch @@ -0,0 +1,52 @@ +From b7333b58f358f38d90d78e00c1ee5dec82df10ad Mon Sep 17 00:00:00 2001 +From: Yang Shi +Date: Fri, 14 Aug 2020 21:30:41 -0700 +Subject: mm/memory.c: skip spurious TLB flush for retried page fault + +From: Yang Shi + +commit b7333b58f358f38d90d78e00c1ee5dec82df10ad upstream. + +Recently we found regression when running will_it_scale/page_fault3 test +on ARM64. Over 70% down for the multi processes cases and over 20% down +for the multi threads cases. It turns out the regression is caused by +commit 89b15332af7c ("mm: drop mmap_sem before calling +balance_dirty_pages() in write fault"). + +The test mmaps a memory size file then write to the mapping, this would +make all memory dirty and trigger dirty pages throttle, that upstream +commit would release mmap_sem then retry the page fault. The retried +page fault would see correct PTEs installed then just fall through to +spurious TLB flush. The regression is caused by the excessive spurious +TLB flush. It is fine on x86 since x86's spurious TLB flush is no-op. + +We could just skip the spurious TLB flush to mitigate the regression. + +Suggested-by: Linus Torvalds +Reported-by: Xu Yu +Debugged-by: Xu Yu +Tested-by: Xu Yu +Cc: Johannes Weiner +Cc: Catalin Marinas +Cc: Will Deacon +Cc: +Signed-off-by: Yang Shi +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + mm/memory.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/mm/memory.c ++++ b/mm/memory.c +@@ -4062,6 +4062,9 @@ static vm_fault_t handle_pte_fault(struc + vmf->flags & FAULT_FLAG_WRITE)) { + update_mmu_cache(vmf->vma, vmf->address, vmf->pte); + } else { ++ /* Skip spurious TLB flush for retried page fault */ ++ if (vmf->flags & FAULT_FLAG_TRIED) ++ goto unlock; + /* + * This is needed only for protection faults but the arch code + * is not yet telling us if this is a protection fault or not. diff --git a/queue-4.19/mm-page_alloc-fix-core-hung-in-free_pcppages_bulk.patch b/queue-4.19/mm-page_alloc-fix-core-hung-in-free_pcppages_bulk.patch new file mode 100644 index 00000000000..8a64a77f039 --- /dev/null +++ b/queue-4.19/mm-page_alloc-fix-core-hung-in-free_pcppages_bulk.patch @@ -0,0 +1,100 @@ +From 88e8ac11d2ea3acc003cf01bb5a38c8aa76c3cfd Mon Sep 17 00:00:00 2001 +From: Charan Teja Reddy +Date: Thu, 20 Aug 2020 17:42:27 -0700 +Subject: mm, page_alloc: fix core hung in free_pcppages_bulk() + +From: Charan Teja Reddy + +commit 88e8ac11d2ea3acc003cf01bb5a38c8aa76c3cfd upstream. + +The following race is observed with the repeated online, offline and a +delay between two successive online of memory blocks of movable zone. + +P1 P2 + +Online the first memory block in +the movable zone. The pcp struct +values are initialized to default +values,i.e., pcp->high = 0 & +pcp->batch = 1. + + Allocate the pages from the + movable zone. + +Try to Online the second memory +block in the movable zone thus it +entered the online_pages() but yet +to call zone_pcp_update(). + This process is entered into + the exit path thus it tries + to release the order-0 pages + to pcp lists through + free_unref_page_commit(). + As pcp->high = 0, pcp->count = 1 + proceed to call the function + free_pcppages_bulk(). +Update the pcp values thus the +new pcp values are like, say, +pcp->high = 378, pcp->batch = 63. + Read the pcp's batch value using + READ_ONCE() and pass the same to + free_pcppages_bulk(), pcp values + passed here are, batch = 63, + count = 1. + + Since num of pages in the pcp + lists are less than ->batch, + then it will stuck in + while(list_empty(list)) loop + with interrupts disabled thus + a core hung. + +Avoid this by ensuring free_pcppages_bulk() is called with proper count of +pcp list pages. + +The mentioned race is some what easily reproducible without [1] because +pcp's are not updated for the first memory block online and thus there is +a enough race window for P2 between alloc+free and pcp struct values +update through onlining of second memory block. + +With [1], the race still exists but it is very narrow as we update the pcp +struct values for the first memory block online itself. + +This is not limited to the movable zone, it could also happen in cases +with the normal zone (e.g., hotplug to a node that only has DMA memory, or +no other memory yet). + +[1]: https://patchwork.kernel.org/patch/11696389/ + +Fixes: 5f8dcc21211a ("page-allocator: split per-cpu list into one-list-per-migrate-type") +Signed-off-by: Charan Teja Reddy +Signed-off-by: Andrew Morton +Acked-by: David Hildenbrand +Acked-by: David Rientjes +Acked-by: Michal Hocko +Cc: Michal Hocko +Cc: Vlastimil Babka +Cc: Vinayak Menon +Cc: [2.6+] +Link: http://lkml.kernel.org/r/1597150703-19003-1-git-send-email-charante@codeaurora.org +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + mm/page_alloc.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/mm/page_alloc.c ++++ b/mm/page_alloc.c +@@ -1115,6 +1115,11 @@ static void free_pcppages_bulk(struct zo + struct page *page, *tmp; + LIST_HEAD(head); + ++ /* ++ * Ensure proper count is passed which otherwise would stuck in the ++ * below while (list_empty(list)) loop. ++ */ ++ count = min(pcp->count, count); + while (count) { + struct list_head *list; + diff --git a/queue-4.19/romfs-fix-uninitialized-memory-leak-in-romfs_dev_read.patch b/queue-4.19/romfs-fix-uninitialized-memory-leak-in-romfs_dev_read.patch new file mode 100644 index 00000000000..9a75279c636 --- /dev/null +++ b/queue-4.19/romfs-fix-uninitialized-memory-leak-in-romfs_dev_read.patch @@ -0,0 +1,55 @@ +From bcf85fcedfdd17911982a3e3564fcfec7b01eebd Mon Sep 17 00:00:00 2001 +From: Jann Horn +Date: Thu, 20 Aug 2020 17:42:11 -0700 +Subject: romfs: fix uninitialized memory leak in romfs_dev_read() + +From: Jann Horn + +commit bcf85fcedfdd17911982a3e3564fcfec7b01eebd upstream. + +romfs has a superblock field that limits the size of the filesystem; data +beyond that limit is never accessed. + +romfs_dev_read() fetches a caller-supplied number of bytes from the +backing device. It returns 0 on success or an error code on failure; +therefore, its API can't represent short reads, it's all-or-nothing. + +However, when romfs_dev_read() detects that the requested operation would +cross the filesystem size limit, it currently silently truncates the +requested number of bytes. This e.g. means that when the content of a +file with size 0x1000 starts one byte before the filesystem size limit, +->readpage() will only fill a single byte of the supplied page while +leaving the rest uninitialized, leaking that uninitialized memory to +userspace. + +Fix it by returning an error code instead of truncating the read when the +requested read operation would go beyond the end of the filesystem. + +Fixes: da4458bda237 ("NOMMU: Make it possible for RomFS to use MTD devices directly") +Signed-off-by: Jann Horn +Signed-off-by: Andrew Morton +Reviewed-by: Greg Kroah-Hartman +Cc: David Howells +Cc: +Link: http://lkml.kernel.org/r/20200818013202.2246365-1-jannh@google.com +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + fs/romfs/storage.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +--- a/fs/romfs/storage.c ++++ b/fs/romfs/storage.c +@@ -221,10 +221,8 @@ int romfs_dev_read(struct super_block *s + size_t limit; + + limit = romfs_maxsize(sb); +- if (pos >= limit) ++ if (pos >= limit || buflen > limit - pos) + return -EIO; +- if (buflen > limit - pos) +- buflen = limit - pos; + + #ifdef CONFIG_ROMFS_ON_MTD + if (sb->s_mtd) diff --git a/queue-4.19/scsi-zfcp-fix-use-after-free-in-request-timeout-handlers.patch b/queue-4.19/scsi-zfcp-fix-use-after-free-in-request-timeout-handlers.patch new file mode 100644 index 00000000000..b68406f7f38 --- /dev/null +++ b/queue-4.19/scsi-zfcp-fix-use-after-free-in-request-timeout-handlers.patch @@ -0,0 +1,85 @@ +From 2d9a2c5f581be3991ba67fa9e7497c711220ea8e Mon Sep 17 00:00:00 2001 +From: Steffen Maier +Date: Thu, 13 Aug 2020 17:28:56 +0200 +Subject: scsi: zfcp: Fix use-after-free in request timeout handlers + +From: Steffen Maier + +commit 2d9a2c5f581be3991ba67fa9e7497c711220ea8e upstream. + +Before v4.15 commit 75492a51568b ("s390/scsi: Convert timers to use +timer_setup()"), we intentionally only passed zfcp_adapter as context +argument to zfcp_fsf_request_timeout_handler(). Since we only trigger +adapter recovery, it was unnecessary to sync against races between timeout +and (late) completion. Likewise, we only passed zfcp_erp_action as context +argument to zfcp_erp_timeout_handler(). Since we only wakeup an ERP action, +it was unnecessary to sync against races between timeout and (late) +completion. + +Meanwhile the timeout handlers get timer_list as context argument and do a +timer-specific container-of to zfcp_fsf_req which can have been freed. + +Fix it by making sure that any request timeout handlers, that might just +have started before del_timer(), are completed by using del_timer_sync() +instead. This ensures the request free happens afterwards. + +Space time diagram of potential use-after-free: + +Basic idea is to have 2 or more pending requests whose timeouts run out at +almost the same time. + +req 1 timeout ERP thread req 2 timeout +---------------- ---------------- --------------------------------------- +zfcp_fsf_request_timeout_handler +fsf_req = from_timer(fsf_req, t, timer) +adapter = fsf_req->adapter +zfcp_qdio_siosl(adapter) +zfcp_erp_adapter_reopen(adapter,...) + zfcp_erp_strategy + ... + zfcp_fsf_req_dismiss_all + list_for_each_entry_safe + zfcp_fsf_req_complete 1 + del_timer 1 + zfcp_fsf_req_free 1 + zfcp_fsf_req_complete 2 + zfcp_fsf_request_timeout_handler + del_timer 2 + fsf_req = from_timer(fsf_req, t, timer) + zfcp_fsf_req_free 2 + adapter = fsf_req->adapter + ^^^^^^^ already freed + +Link: https://lore.kernel.org/r/20200813152856.50088-1-maier@linux.ibm.com +Fixes: 75492a51568b ("s390/scsi: Convert timers to use timer_setup()") +Cc: #4.15+ +Suggested-by: Julian Wiedmann +Reviewed-by: Julian Wiedmann +Signed-off-by: Steffen Maier +Signed-off-by: Martin K. Petersen +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/s390/scsi/zfcp_fsf.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/s390/scsi/zfcp_fsf.c ++++ b/drivers/s390/scsi/zfcp_fsf.c +@@ -403,7 +403,7 @@ static void zfcp_fsf_req_complete(struct + return; + } + +- del_timer(&req->timer); ++ del_timer_sync(&req->timer); + zfcp_fsf_protstatus_eval(req); + zfcp_fsf_fsfstatus_eval(req); + req->handler(req); +@@ -758,7 +758,7 @@ static int zfcp_fsf_req_send(struct zfcp + req->qdio_req.qdio_outb_usage = atomic_read(&qdio->req_q_free); + req->issued = get_tod_clock(); + if (zfcp_qdio_send(qdio, &req->qdio_req)) { +- del_timer(&req->timer); ++ del_timer_sync(&req->timer); + /* lookup request again, list might have changed */ + zfcp_reqlist_find_rm(adapter->req_list, req_id); + zfcp_erp_adapter_reopen(adapter, 0, "fsrs__1"); diff --git a/queue-4.19/series b/queue-4.19/series index cde58cf4813..fe4063d63be 100644 --- a/queue-4.19/series +++ b/queue-4.19/series @@ -7,3 +7,12 @@ btrfs-don-t-show-full-path-of-bind-mounts-in-subvol.patch btrfs-move-free_pages_out-label-in-inline-extent-han.patch btrfs-inode-fix-null-pointer-dereference-if-inode-do.patch btrfs-sysfs-use-nofs-for-device-creation.patch +romfs-fix-uninitialized-memory-leak-in-romfs_dev_read.patch +kernel-relay.c-fix-memleak-on-destroy-relay-channel.patch +mm-include-cma-pages-in-lowmem_reserve-at-boot.patch +mm-page_alloc-fix-core-hung-in-free_pcppages_bulk.patch +ext4-fix-checking-of-directory-entry-validity-for-inline-directories.patch +jbd2-add-the-missing-unlock_buffer-in-the-error-path-of-jbd2_write_superblock.patch +scsi-zfcp-fix-use-after-free-in-request-timeout-handlers.patch +mm-memory.c-skip-spurious-tlb-flush-for-retried-page-fault.patch +drm-amd-display-fix-pow-crashing-when-given-base-0.patch