From: Greg Kroah-Hartman Date: Sun, 16 Oct 2022 12:31:34 +0000 (+0200) Subject: 6.0-stable patches X-Git-Tag: v5.4.219~128 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=cd8d3c89488edfc499c3a2f1131304271bb239de;p=thirdparty%2Fkernel%2Fstable-queue.git 6.0-stable patches added patches: btrfs-enhance-unsupported-compat-ro-flags-handling.patch btrfs-fix-alignment-of-vma-for-memory-mapped-files-on-thp.patch btrfs-fix-missed-extent-on-fsync-after-dropping-extent-maps.patch btrfs-fix-race-between-quota-enable-and-quota-rescan-ioctl.patch btrfs-set-generation-before-calling-btrfs_clean_tree_block-in-btrfs_init_new_buffer.patch fbdev-smscufx-fix-use-after-free-in-ufx_ops_open.patch fs-record-i_dirty_time-even-if-inode-already-has-i_dirty_inode.patch gpio-rockchip-request-gpio-mux-to-pinctrl-when-setting-direction.patch hwrng-core-let-sleep-be-interrupted-when-unregistering-hwrng.patch ksmbd-fix-endless-loop-when-encryption-for-response-fails.patch ksmbd-fix-incorrect-handling-of-iterate_dir.patch ksmbd-fix-user-namespace-mapping.patch ksmbd-fix-wrong-return-value-and-message-length-check-in-smb2_ioctl.patch pinctrl-rockchip-add-pinmux_ops.gpio_set_direction-callback.patch smb3-do-not-log-confusing-message-when-server-returns-no-network-interfaces.patch --- diff --git a/queue-6.0/btrfs-enhance-unsupported-compat-ro-flags-handling.patch b/queue-6.0/btrfs-enhance-unsupported-compat-ro-flags-handling.patch new file mode 100644 index 00000000000..da8fcfaf646 --- /dev/null +++ b/queue-6.0/btrfs-enhance-unsupported-compat-ro-flags-handling.patch @@ -0,0 +1,86 @@ +From 81d5d61454c365718655cfc87d8200c84e25d596 Mon Sep 17 00:00:00 2001 +From: Qu Wenruo +Date: Tue, 9 Aug 2022 13:02:16 +0800 +Subject: btrfs: enhance unsupported compat RO flags handling + +From: Qu Wenruo + +commit 81d5d61454c365718655cfc87d8200c84e25d596 upstream. + +Currently there are two corner cases not handling compat RO flags +correctly: + +- Remount + We can still mount the fs RO with compat RO flags, then remount it RW. + We should not allow any write into a fs with unsupported RO flags. + +- Still try to search block group items + In fact, behavior/on-disk format change to extent tree should not + need a full incompat flag. + + And since we can ensure fs with unsupported RO flags never got any + writes (with above case fixed), then we can even skip block group + items search at mount time. + +This patch will enhance the unsupported RO compat flags by: + +- Reject read-write remount if there are unsupported RO compat flags + +- Go dummy block group items directly for unsupported RO compat flags + In fact, only changes to chunk/subvolume/root/csum trees should go + incompat flags. + +The latter part should allow future change to extent tree to be compat +RO flags. + +Thus this patch also needs to be backported to all stable trees. + +CC: stable@vger.kernel.org # 4.9+ +Reviewed-by: Nikolay Borisov +Signed-off-by: Qu Wenruo +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Greg Kroah-Hartman +--- + fs/btrfs/block-group.c | 11 ++++++++++- + fs/btrfs/super.c | 9 +++++++++ + 2 files changed, 19 insertions(+), 1 deletion(-) + +--- a/fs/btrfs/block-group.c ++++ b/fs/btrfs/block-group.c +@@ -2190,7 +2190,16 @@ int btrfs_read_block_groups(struct btrfs + int need_clear = 0; + u64 cache_gen; + +- if (!root) ++ /* ++ * Either no extent root (with ibadroots rescue option) or we have ++ * unsupported RO options. The fs can never be mounted read-write, so no ++ * need to waste time searching block group items. ++ * ++ * This also allows new extent tree related changes to be RO compat, ++ * no need for a full incompat flag. ++ */ ++ if (!root || (btrfs_super_compat_ro_flags(info->super_copy) & ++ ~BTRFS_FEATURE_COMPAT_RO_SUPP)) + return fill_dummy_bgs(info); + + key.objectid = 0; +--- a/fs/btrfs/super.c ++++ b/fs/btrfs/super.c +@@ -2112,6 +2112,15 @@ static int btrfs_remount(struct super_bl + ret = -EINVAL; + goto restore; + } ++ if (btrfs_super_compat_ro_flags(fs_info->super_copy) & ++ ~BTRFS_FEATURE_COMPAT_RO_SUPP) { ++ btrfs_err(fs_info, ++ "can not remount read-write due to unsupported optional flags 0x%llx", ++ btrfs_super_compat_ro_flags(fs_info->super_copy) & ++ ~BTRFS_FEATURE_COMPAT_RO_SUPP); ++ ret = -EINVAL; ++ goto restore; ++ } + if (fs_info->fs_devices->rw_devices == 0) { + ret = -EACCES; + goto restore; diff --git a/queue-6.0/btrfs-fix-alignment-of-vma-for-memory-mapped-files-on-thp.patch b/queue-6.0/btrfs-fix-alignment-of-vma-for-memory-mapped-files-on-thp.patch new file mode 100644 index 00000000000..f5de16b5dbf --- /dev/null +++ b/queue-6.0/btrfs-fix-alignment-of-vma-for-memory-mapped-files-on-thp.patch @@ -0,0 +1,67 @@ +From b0c582233a8563f3c4228df838cdc67a8807ec78 Mon Sep 17 00:00:00 2001 +From: Alexander Zhu +Date: Tue, 2 Aug 2022 13:32:46 -0700 +Subject: btrfs: fix alignment of VMA for memory mapped files on THP + +From: Alexander Zhu + +commit b0c582233a8563f3c4228df838cdc67a8807ec78 upstream. + +With CONFIG_READ_ONLY_THP_FOR_FS, the Linux kernel supports using THPs for +read-only mmapped files, such as shared libraries. However, the kernel +makes no attempt to actually align those mappings on 2MB boundaries, +which makes it impossible to use those THPs most of the time. This issue +applies to general file mapping THP as well as existing setups using +CONFIG_READ_ONLY_THP_FOR_FS. This is easily fixed by using +thp_get_unmapped_area for the unmapped_area function in btrfs, which +is what ext2, ext4, fuse, and xfs all use. + +Initially btrfs had been left out in commit 8c07fc452ac0 ("btrfs: fix +alignment of VMA for memory mapped files on THP") as btrfs does not support +DAX. However, commit 1854bc6e2420 ("mm/readahead: Align file mappings +for non-DAX") removed the DAX requirement. We should now be able to call +thp_get_unmapped_area() for btrfs. + +The problem can be seen in /proc/PID/smaps where THPeligible is set to 0 +on mappings to eligible shared object files as shown below. + +Before this patch: + + 7fc6a7e18000-7fc6a80cc000 r-xp 00000000 00:1e 199856 + /usr/lib64/libcrypto.so.1.1.1k + Size: 2768 kB + THPeligible: 0 + VmFlags: rd ex mr mw me + +With this patch the library is mapped at a 2MB aligned address: + + fbdfe200000-7fbdfe4b4000 r-xp 00000000 00:1e 199856 + /usr/lib64/libcrypto.so.1.1.1k + Size: 2768 kB + THPeligible: 1 + VmFlags: rd ex mr mw me + +This fixes the alignment of VMAs for any mmap of a file that has the +rd and ex permissions and size >= 2MB. The VMA alignment and +THPeligible field for anonymous memory is handled separately and +is thus not effected by this change. + +CC: stable@vger.kernel.org # 5.18+ +Signed-off-by: Alexander Zhu +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Greg Kroah-Hartman +--- + fs/btrfs/file.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/fs/btrfs/file.c ++++ b/fs/btrfs/file.c +@@ -3810,6 +3810,7 @@ const struct file_operations btrfs_file_ + .mmap = btrfs_file_mmap, + .open = btrfs_file_open, + .release = btrfs_release_file, ++ .get_unmapped_area = thp_get_unmapped_area, + .fsync = btrfs_sync_file, + .fallocate = btrfs_fallocate, + .unlocked_ioctl = btrfs_ioctl, diff --git a/queue-6.0/btrfs-fix-missed-extent-on-fsync-after-dropping-extent-maps.patch b/queue-6.0/btrfs-fix-missed-extent-on-fsync-after-dropping-extent-maps.patch new file mode 100644 index 00000000000..f23c7fc73e9 --- /dev/null +++ b/queue-6.0/btrfs-fix-missed-extent-on-fsync-after-dropping-extent-maps.patch @@ -0,0 +1,153 @@ +From cef7820d6abf8d61f8e1db411eae3c712f6d72a2 Mon Sep 17 00:00:00 2001 +From: Filipe Manana +Date: Mon, 19 Sep 2022 15:06:28 +0100 +Subject: btrfs: fix missed extent on fsync after dropping extent maps + +From: Filipe Manana + +commit cef7820d6abf8d61f8e1db411eae3c712f6d72a2 upstream. + +When dropping extent maps for a range, through btrfs_drop_extent_cache(), +if we find an extent map that starts before our target range and/or ends +before the target range, and we are not able to allocate extent maps for +splitting that extent map, then we don't fail and simply remove the entire +extent map from the inode's extent map tree. + +This is generally fine, because in case anyone needs to access the extent +map, it can just load it again later from the respective file extent +item(s) in the subvolume btree. However, if that extent map is new and is +in the list of modified extents, then a fast fsync will miss the parts of +the extent that were outside our range (that needed to be split), +therefore not logging them. Fix that by marking the inode for a full +fsync. This issue was introduced after removing BUG_ON()s triggered when +the split extent map allocations failed, done by commit 7014cdb49305ed +("Btrfs: btrfs_drop_extent_cache should never fail"), back in 2012, and +the fast fsync path already existed but was very recent. + +Also, in the case where we could allocate extent maps for the split +operations but then fail to add a split extent map to the tree, mark the +inode for a full fsync as well. This is not supposed to ever fail, and we +assert that, but in case assertions are disabled (CONFIG_BTRFS_ASSERT is +not set), it's the correct thing to do to make sure a fast fsync will not +miss a new extent. + +CC: stable@vger.kernel.org # 5.15+ +Reviewed-by: Anand Jain +Signed-off-by: Filipe Manana +Signed-off-by: David Sterba +Signed-off-by: Greg Kroah-Hartman +--- + fs/btrfs/file.c | 58 ++++++++++++++++++++++++++++++++++++++++++++------------ + 1 file changed, 46 insertions(+), 12 deletions(-) + +--- a/fs/btrfs/file.c ++++ b/fs/btrfs/file.c +@@ -523,6 +523,7 @@ void btrfs_drop_extent_cache(struct btrf + testend = 0; + } + while (1) { ++ bool ends_after_range = false; + int no_splits = 0; + + modified = false; +@@ -539,10 +540,12 @@ void btrfs_drop_extent_cache(struct btrf + write_unlock(&em_tree->lock); + break; + } ++ if (testend && em->start + em->len > start + len) ++ ends_after_range = true; + flags = em->flags; + gen = em->generation; + if (skip_pinned && test_bit(EXTENT_FLAG_PINNED, &em->flags)) { +- if (testend && em->start + em->len >= start + len) { ++ if (ends_after_range) { + free_extent_map(em); + write_unlock(&em_tree->lock); + break; +@@ -592,7 +595,7 @@ void btrfs_drop_extent_cache(struct btrf + split = split2; + split2 = NULL; + } +- if (testend && em->start + em->len > start + len) { ++ if (ends_after_range) { + u64 diff = start + len - em->start; + + split->start = start + len; +@@ -630,14 +633,42 @@ void btrfs_drop_extent_cache(struct btrf + } else { + ret = add_extent_mapping(em_tree, split, + modified); +- ASSERT(ret == 0); /* Logic error */ ++ /* Logic error, shouldn't happen. */ ++ ASSERT(ret == 0); ++ if (WARN_ON(ret != 0) && modified) ++ btrfs_set_inode_full_sync(inode); + } + free_extent_map(split); + split = NULL; + } + next: +- if (extent_map_in_tree(em)) ++ if (extent_map_in_tree(em)) { ++ /* ++ * If the extent map is still in the tree it means that ++ * either of the following is true: ++ * ++ * 1) It fits entirely in our range (doesn't end beyond ++ * it or starts before it); ++ * ++ * 2) It starts before our range and/or ends after our ++ * range, and we were not able to allocate the extent ++ * maps for split operations, @split and @split2. ++ * ++ * If we are at case 2) then we just remove the entire ++ * extent map - this is fine since if anyone needs it to ++ * access the subranges outside our range, will just ++ * load it again from the subvolume tree's file extent ++ * item. However if the extent map was in the list of ++ * modified extents, then we must mark the inode for a ++ * full fsync, otherwise a fast fsync will miss this ++ * extent if it's new and needs to be logged. ++ */ ++ if ((em->start < start || ends_after_range) && modified) { ++ ASSERT(no_splits); ++ btrfs_set_inode_full_sync(inode); ++ } + remove_extent_mapping(em_tree, em); ++ } + write_unlock(&em_tree->lock); + + /* once for us */ +@@ -2201,14 +2232,6 @@ int btrfs_sync_file(struct file *file, l + atomic_inc(&root->log_batch); + + /* +- * Always check for the full sync flag while holding the inode's lock, +- * to avoid races with other tasks. The flag must be either set all the +- * time during logging or always off all the time while logging. +- */ +- full_sync = test_bit(BTRFS_INODE_NEEDS_FULL_SYNC, +- &BTRFS_I(inode)->runtime_flags); +- +- /* + * Before we acquired the inode's lock and the mmap lock, someone may + * have dirtied more pages in the target range. We need to make sure + * that writeback for any such pages does not start while we are logging +@@ -2233,6 +2256,17 @@ int btrfs_sync_file(struct file *file, l + } + + /* ++ * Always check for the full sync flag while holding the inode's lock, ++ * to avoid races with other tasks. The flag must be either set all the ++ * time during logging or always off all the time while logging. ++ * We check the flag here after starting delalloc above, because when ++ * running delalloc the full sync flag may be set if we need to drop ++ * extra extent map ranges due to temporary memory allocation failures. ++ */ ++ full_sync = test_bit(BTRFS_INODE_NEEDS_FULL_SYNC, ++ &BTRFS_I(inode)->runtime_flags); ++ ++ /* + * We have to do this here to avoid the priority inversion of waiting on + * IO of a lower priority task while holding a transaction open. + * diff --git a/queue-6.0/btrfs-fix-race-between-quota-enable-and-quota-rescan-ioctl.patch b/queue-6.0/btrfs-fix-race-between-quota-enable-and-quota-rescan-ioctl.patch new file mode 100644 index 00000000000..735d23db12e --- /dev/null +++ b/queue-6.0/btrfs-fix-race-between-quota-enable-and-quota-rescan-ioctl.patch @@ -0,0 +1,60 @@ +From 331cd9461412e103d07595a10289de90004ac890 Mon Sep 17 00:00:00 2001 +From: Filipe Manana +Date: Tue, 23 Aug 2022 12:45:42 +0100 +Subject: btrfs: fix race between quota enable and quota rescan ioctl + +From: Filipe Manana + +commit 331cd9461412e103d07595a10289de90004ac890 upstream. + +When enabling quotas, at btrfs_quota_enable(), after committing the +transaction, we change fs_info->quota_root to point to the quota root we +created and set BTRFS_FS_QUOTA_ENABLED at fs_info->flags. Then we try +to start the qgroup rescan worker, first by initializing it with a call +to qgroup_rescan_init() - however if that fails we end up freeing the +quota root but we leave fs_info->quota_root still pointing to it, this +can later result in a use-after-free somewhere else. + +We have previously set the flags BTRFS_FS_QUOTA_ENABLED and +BTRFS_QGROUP_STATUS_FLAG_ON, so we can only fail with -EINPROGRESS at +btrfs_quota_enable(), which is possible if someone already called the +quota rescan ioctl, and therefore started the rescan worker. + +So fix this by ignoring an -EINPROGRESS and asserting we can't get any +other error. + +Reported-by: Ye Bin +Link: https://lore.kernel.org/linux-btrfs/20220823015931.421355-1-yebin10@huawei.com/ +CC: stable@vger.kernel.org # 4.19+ +Reviewed-by: Qu Wenruo +Signed-off-by: Filipe Manana +Signed-off-by: David Sterba +Signed-off-by: Greg Kroah-Hartman +--- + fs/btrfs/qgroup.c | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +--- a/fs/btrfs/qgroup.c ++++ b/fs/btrfs/qgroup.c +@@ -1174,6 +1174,21 @@ out_add_root: + fs_info->qgroup_rescan_running = true; + btrfs_queue_work(fs_info->qgroup_rescan_workers, + &fs_info->qgroup_rescan_work); ++ } else { ++ /* ++ * We have set both BTRFS_FS_QUOTA_ENABLED and ++ * BTRFS_QGROUP_STATUS_FLAG_ON, so we can only fail with ++ * -EINPROGRESS. That can happen because someone started the ++ * rescan worker by calling quota rescan ioctl before we ++ * attempted to initialize the rescan worker. Failure due to ++ * quotas disabled in the meanwhile is not possible, because ++ * we are holding a write lock on fs_info->subvol_sem, which ++ * is also acquired when disabling quotas. ++ * Ignore such error, and any other error would need to undo ++ * everything we did in the transaction we just committed. ++ */ ++ ASSERT(ret == -EINPROGRESS); ++ ret = 0; + } + + out_free_path: diff --git a/queue-6.0/btrfs-set-generation-before-calling-btrfs_clean_tree_block-in-btrfs_init_new_buffer.patch b/queue-6.0/btrfs-set-generation-before-calling-btrfs_clean_tree_block-in-btrfs_init_new_buffer.patch new file mode 100644 index 00000000000..319394d172d --- /dev/null +++ b/queue-6.0/btrfs-set-generation-before-calling-btrfs_clean_tree_block-in-btrfs_init_new_buffer.patch @@ -0,0 +1,43 @@ +From cbddcc4fa3443fe8cfb2ff8e210deb1f6a0eea38 Mon Sep 17 00:00:00 2001 +From: Tetsuo Handa +Date: Tue, 20 Sep 2022 22:43:51 +0900 +Subject: btrfs: set generation before calling btrfs_clean_tree_block in btrfs_init_new_buffer + +From: Tetsuo Handa + +commit cbddcc4fa3443fe8cfb2ff8e210deb1f6a0eea38 upstream. + +syzbot is reporting uninit-value in btrfs_clean_tree_block() [1], for +commit bc877d285ca3dba2 ("btrfs: Deduplicate extent_buffer init code") +missed that btrfs_set_header_generation() in btrfs_init_new_buffer() must +not be moved to after clean_tree_block() because clean_tree_block() is +calling btrfs_header_generation() since commit 55c69072d6bd5be1 ("Btrfs: +Fix extent_buffer usage when nodesize != leafsize"). + +Since memzero_extent_buffer() will reset "struct btrfs_header" part, we +can't move btrfs_set_header_generation() to before memzero_extent_buffer(). +Just re-add btrfs_set_header_generation() before btrfs_clean_tree_block(). + +Link: https://syzkaller.appspot.com/bug?extid=fba8e2116a12609b6c59 [1] +Reported-by: syzbot +Fixes: bc877d285ca3dba2 ("btrfs: Deduplicate extent_buffer init code") +CC: stable@vger.kernel.org # 4.19+ +Signed-off-by: Tetsuo Handa +Signed-off-by: David Sterba +Signed-off-by: Greg Kroah-Hartman +--- + fs/btrfs/extent-tree.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -4888,6 +4888,9 @@ btrfs_init_new_buffer(struct btrfs_trans + !test_bit(BTRFS_ROOT_RESET_LOCKDEP_CLASS, &root->state)) + lockdep_owner = BTRFS_FS_TREE_OBJECTID; + ++ /* btrfs_clean_tree_block() accesses generation field. */ ++ btrfs_set_header_generation(buf, trans->transid); ++ + /* + * This needs to stay, because we could allocate a freed block from an + * old tree into a new tree, so we need to make sure this new block is diff --git a/queue-6.0/fbdev-smscufx-fix-use-after-free-in-ufx_ops_open.patch b/queue-6.0/fbdev-smscufx-fix-use-after-free-in-ufx_ops_open.patch new file mode 100644 index 00000000000..8f02335f50c --- /dev/null +++ b/queue-6.0/fbdev-smscufx-fix-use-after-free-in-ufx_ops_open.patch @@ -0,0 +1,79 @@ +From 5610bcfe8693c02e2e4c8b31427f1bdbdecc839c Mon Sep 17 00:00:00 2001 +From: Hyunwoo Kim +Date: Sun, 25 Sep 2022 06:32:43 -0700 +Subject: fbdev: smscufx: Fix use-after-free in ufx_ops_open() + +From: Hyunwoo Kim + +commit 5610bcfe8693c02e2e4c8b31427f1bdbdecc839c upstream. + +A race condition may occur if the user physically removes the +USB device while calling open() for this device node. + +This is a race condition between the ufx_ops_open() function and +the ufx_usb_disconnect() function, which may eventually result in UAF. + +So, add a mutex to the ufx_ops_open() and ufx_usb_disconnect() functions +to avoid race contidion of krefs. + +Signed-off-by: Hyunwoo Kim +Cc: stable@vger.kernel.org +Signed-off-by: Helge Deller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/video/fbdev/smscufx.c | 14 +++++++++++++- + 1 file changed, 13 insertions(+), 1 deletion(-) + +--- a/drivers/video/fbdev/smscufx.c ++++ b/drivers/video/fbdev/smscufx.c +@@ -137,6 +137,8 @@ static int ufx_submit_urb(struct ufx_dat + static int ufx_alloc_urb_list(struct ufx_data *dev, int count, size_t size); + static void ufx_free_urb_list(struct ufx_data *dev); + ++static DEFINE_MUTEX(disconnect_mutex); ++ + /* reads a control register */ + static int ufx_reg_read(struct ufx_data *dev, u32 index, u32 *data) + { +@@ -1071,9 +1073,13 @@ static int ufx_ops_open(struct fb_info * + if (user == 0 && !console) + return -EBUSY; + ++ mutex_lock(&disconnect_mutex); ++ + /* If the USB device is gone, we don't accept new opens */ +- if (dev->virtualized) ++ if (dev->virtualized) { ++ mutex_unlock(&disconnect_mutex); + return -ENODEV; ++ } + + dev->fb_count++; + +@@ -1097,6 +1103,8 @@ static int ufx_ops_open(struct fb_info * + pr_debug("open /dev/fb%d user=%d fb_info=%p count=%d", + info->node, user, info, dev->fb_count); + ++ mutex_unlock(&disconnect_mutex); ++ + return 0; + } + +@@ -1741,6 +1749,8 @@ static void ufx_usb_disconnect(struct us + { + struct ufx_data *dev; + ++ mutex_lock(&disconnect_mutex); ++ + dev = usb_get_intfdata(interface); + + pr_debug("USB disconnect starting\n"); +@@ -1761,6 +1771,8 @@ static void ufx_usb_disconnect(struct us + kref_put(&dev->kref, ufx_free); + + /* consider ufx_data freed */ ++ ++ mutex_unlock(&disconnect_mutex); + } + + static struct usb_driver ufx_driver = { diff --git a/queue-6.0/fs-record-i_dirty_time-even-if-inode-already-has-i_dirty_inode.patch b/queue-6.0/fs-record-i_dirty_time-even-if-inode-already-has-i_dirty_inode.patch new file mode 100644 index 00000000000..931d16f1f5e --- /dev/null +++ b/queue-6.0/fs-record-i_dirty_time-even-if-inode-already-has-i_dirty_inode.patch @@ -0,0 +1,185 @@ +From cbfecb927f429a6fa613d74b998496bd71e4438a Mon Sep 17 00:00:00 2001 +From: Lukas Czerner +Date: Thu, 25 Aug 2022 12:06:57 +0200 +Subject: fs: record I_DIRTY_TIME even if inode already has I_DIRTY_INODE + +From: Lukas Czerner + +commit cbfecb927f429a6fa613d74b998496bd71e4438a upstream. + +Currently the I_DIRTY_TIME will never get set if the inode already has +I_DIRTY_INODE with assumption that it supersedes I_DIRTY_TIME. That's +true, however ext4 will only update the on-disk inode in +->dirty_inode(), not on actual writeback. As a result if the inode +already has I_DIRTY_INODE state by the time we get to +__mark_inode_dirty() only with I_DIRTY_TIME, the time was already filled +into on-disk inode and will not get updated until the next I_DIRTY_INODE +update, which might never come if we crash or get a power failure. + +The problem can be reproduced on ext4 by running xfstest generic/622 +with -o iversion mount option. + +Fix it by allowing I_DIRTY_TIME to be set even if the inode already has +I_DIRTY_INODE. Also make sure that the case is properly handled in +writeback_single_inode() as well. Additionally changes in +xfs_fs_dirty_inode() was made to accommodate for I_DIRTY_TIME in flag. + +Thanks Jan Kara for suggestions on how to make this work properly. + +Cc: Dave Chinner +Cc: Christoph Hellwig +Cc: stable@kernel.org +Signed-off-by: Lukas Czerner +Suggested-by: Jan Kara +Reviewed-by: Jan Kara +Link: https://lore.kernel.org/r/20220825100657.44217-1-lczerner@redhat.com +Signed-off-by: Theodore Ts'o +Signed-off-by: Greg Kroah-Hartman +--- + Documentation/filesystems/vfs.rst | 3 +++ + fs/fs-writeback.c | 37 +++++++++++++++++++++++++------------ + fs/xfs/xfs_super.c | 10 ++++++++-- + include/linux/fs.h | 9 +++++---- + 4 files changed, 41 insertions(+), 18 deletions(-) + +--- a/Documentation/filesystems/vfs.rst ++++ b/Documentation/filesystems/vfs.rst +@@ -274,6 +274,9 @@ or bottom half). + This is specifically for the inode itself being marked dirty, + not its data. If the update needs to be persisted by fdatasync(), + then I_DIRTY_DATASYNC will be set in the flags argument. ++ I_DIRTY_TIME will be set in the flags in case lazytime is enabled ++ and struct inode has times updated since the last ->dirty_inode ++ call. + + ``write_inode`` + this method is called when the VFS needs to write an inode to +--- a/fs/fs-writeback.c ++++ b/fs/fs-writeback.c +@@ -1718,9 +1718,14 @@ static int writeback_single_inode(struct + */ + if (!(inode->i_state & I_DIRTY_ALL)) + inode_cgwb_move_to_attached(inode, wb); +- else if (!(inode->i_state & I_SYNC_QUEUED) && +- (inode->i_state & I_DIRTY)) +- redirty_tail_locked(inode, wb); ++ else if (!(inode->i_state & I_SYNC_QUEUED)) { ++ if ((inode->i_state & I_DIRTY)) ++ redirty_tail_locked(inode, wb); ++ else if (inode->i_state & I_DIRTY_TIME) { ++ inode->dirtied_when = jiffies; ++ inode_io_list_move_locked(inode, wb, &wb->b_dirty_time); ++ } ++ } + + spin_unlock(&wb->list_lock); + inode_sync_complete(inode); +@@ -2370,6 +2375,20 @@ void __mark_inode_dirty(struct inode *in + + if (flags & I_DIRTY_INODE) { + /* ++ * Inode timestamp update will piggback on this dirtying. ++ * We tell ->dirty_inode callback that timestamps need to ++ * be updated by setting I_DIRTY_TIME in flags. ++ */ ++ if (inode->i_state & I_DIRTY_TIME) { ++ spin_lock(&inode->i_lock); ++ if (inode->i_state & I_DIRTY_TIME) { ++ inode->i_state &= ~I_DIRTY_TIME; ++ flags |= I_DIRTY_TIME; ++ } ++ spin_unlock(&inode->i_lock); ++ } ++ ++ /* + * Notify the filesystem about the inode being dirtied, so that + * (if needed) it can update on-disk fields and journal the + * inode. This is only needed when the inode itself is being +@@ -2378,7 +2397,8 @@ void __mark_inode_dirty(struct inode *in + */ + trace_writeback_dirty_inode_start(inode, flags); + if (sb->s_op->dirty_inode) +- sb->s_op->dirty_inode(inode, flags & I_DIRTY_INODE); ++ sb->s_op->dirty_inode(inode, ++ flags & (I_DIRTY_INODE | I_DIRTY_TIME)); + trace_writeback_dirty_inode(inode, flags); + + /* I_DIRTY_INODE supersedes I_DIRTY_TIME. */ +@@ -2399,21 +2419,15 @@ void __mark_inode_dirty(struct inode *in + */ + smp_mb(); + +- if (((inode->i_state & flags) == flags) || +- (dirtytime && (inode->i_state & I_DIRTY_INODE))) ++ if ((inode->i_state & flags) == flags) + return; + + spin_lock(&inode->i_lock); +- if (dirtytime && (inode->i_state & I_DIRTY_INODE)) +- goto out_unlock_inode; + if ((inode->i_state & flags) != flags) { + const int was_dirty = inode->i_state & I_DIRTY; + + inode_attach_wb(inode, NULL); + +- /* I_DIRTY_INODE supersedes I_DIRTY_TIME. */ +- if (flags & I_DIRTY_INODE) +- inode->i_state &= ~I_DIRTY_TIME; + inode->i_state |= flags; + + /* +@@ -2486,7 +2500,6 @@ void __mark_inode_dirty(struct inode *in + out_unlock: + if (wb) + spin_unlock(&wb->list_lock); +-out_unlock_inode: + spin_unlock(&inode->i_lock); + } + EXPORT_SYMBOL(__mark_inode_dirty); +--- a/fs/xfs/xfs_super.c ++++ b/fs/xfs/xfs_super.c +@@ -653,7 +653,7 @@ xfs_fs_destroy_inode( + static void + xfs_fs_dirty_inode( + struct inode *inode, +- int flag) ++ int flags) + { + struct xfs_inode *ip = XFS_I(inode); + struct xfs_mount *mp = ip->i_mount; +@@ -661,7 +661,13 @@ xfs_fs_dirty_inode( + + if (!(inode->i_sb->s_flags & SB_LAZYTIME)) + return; +- if (flag != I_DIRTY_SYNC || !(inode->i_state & I_DIRTY_TIME)) ++ ++ /* ++ * Only do the timestamp update if the inode is dirty (I_DIRTY_SYNC) ++ * and has dirty timestamp (I_DIRTY_TIME). I_DIRTY_TIME can be passed ++ * in flags possibly together with I_DIRTY_SYNC. ++ */ ++ if ((flags & ~I_DIRTY_TIME) != I_DIRTY_SYNC || !(flags & I_DIRTY_TIME)) + return; + + if (xfs_trans_alloc(mp, &M_RES(mp)->tr_fsyncts, 0, 0, 0, &tp)) +--- a/include/linux/fs.h ++++ b/include/linux/fs.h +@@ -2371,13 +2371,14 @@ static inline void kiocb_clone(struct ki + * don't have to write inode on fdatasync() when only + * e.g. the timestamps have changed. + * I_DIRTY_PAGES Inode has dirty pages. Inode itself may be clean. +- * I_DIRTY_TIME The inode itself only has dirty timestamps, and the ++ * I_DIRTY_TIME The inode itself has dirty timestamps, and the + * lazytime mount option is enabled. We keep track of this + * separately from I_DIRTY_SYNC in order to implement + * lazytime. This gets cleared if I_DIRTY_INODE +- * (I_DIRTY_SYNC and/or I_DIRTY_DATASYNC) gets set. I.e. +- * either I_DIRTY_TIME *or* I_DIRTY_INODE can be set in +- * i_state, but not both. I_DIRTY_PAGES may still be set. ++ * (I_DIRTY_SYNC and/or I_DIRTY_DATASYNC) gets set. But ++ * I_DIRTY_TIME can still be set if I_DIRTY_SYNC is already ++ * in place because writeback might already be in progress ++ * and we don't want to lose the time update + * I_NEW Serves as both a mutex and completion notification. + * New inodes set I_NEW. If two processes both create + * the same inode, one of them will release its inode and diff --git a/queue-6.0/gpio-rockchip-request-gpio-mux-to-pinctrl-when-setting-direction.patch b/queue-6.0/gpio-rockchip-request-gpio-mux-to-pinctrl-when-setting-direction.patch new file mode 100644 index 00000000000..aefc36a31c4 --- /dev/null +++ b/queue-6.0/gpio-rockchip-request-gpio-mux-to-pinctrl-when-setting-direction.patch @@ -0,0 +1,57 @@ +From 8ea8af6c8469156ac2042d83d73f6b74eb4b4b45 Mon Sep 17 00:00:00 2001 +From: Quentin Schulz +Date: Fri, 30 Sep 2022 15:20:33 +0200 +Subject: gpio: rockchip: request GPIO mux to pinctrl when setting direction + +From: Quentin Schulz + +commit 8ea8af6c8469156ac2042d83d73f6b74eb4b4b45 upstream. + +Before the split of gpio and pinctrl sections in their own driver, +rockchip_set_mux was called in pinmux_ops.gpio_set_direction for +configuring a pin in its GPIO function. + +This is essential for cases where pinctrl is "bypassed" by gpio +consumers otherwise the GPIO function is not configured for the pin and +it does not work. Such was the case for the sysfs/libgpiod userspace +GPIO handling. + +Let's call pinctrl_gpio_direction_input/output when setting the +direction of a GPIO so that the pinctrl core requests from the rockchip +pinctrl driver to put the pin in its GPIO function. + +Fixes: 9ce9a02039de ("pinctrl/rockchip: drop the gpio related codes") +Fixes: 936ee2675eee ("gpio/rockchip: add driver for rockchip gpio") +Cc: stable@vger.kernel.org +Reviewed-by: Heiko Stuebner +Signed-off-by: Quentin Schulz +Link: https://lore.kernel.org/r/20220930132033.4003377-3-foss+kernel@0leil.net +Signed-off-by: Linus Walleij +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpio/gpio-rockchip.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/drivers/gpio/gpio-rockchip.c ++++ b/drivers/gpio/gpio-rockchip.c +@@ -19,6 +19,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -156,6 +157,12 @@ static int rockchip_gpio_set_direction(s + unsigned long flags; + u32 data = input ? 0 : 1; + ++ ++ if (input) ++ pinctrl_gpio_direction_input(bank->pin_base + offset); ++ else ++ pinctrl_gpio_direction_output(bank->pin_base + offset); ++ + raw_spin_lock_irqsave(&bank->slock, flags); + rockchip_gpio_writel_bit(bank, offset, data, bank->gpio_regs->port_ddr); + raw_spin_unlock_irqrestore(&bank->slock, flags); diff --git a/queue-6.0/hwrng-core-let-sleep-be-interrupted-when-unregistering-hwrng.patch b/queue-6.0/hwrng-core-let-sleep-be-interrupted-when-unregistering-hwrng.patch new file mode 100644 index 00000000000..21987256c56 --- /dev/null +++ b/queue-6.0/hwrng-core-let-sleep-be-interrupted-when-unregistering-hwrng.patch @@ -0,0 +1,131 @@ +From 36cb6494429bd64b27b7ff8b4af56f8e526da2b4 Mon Sep 17 00:00:00 2001 +From: "Jason A. Donenfeld" +Date: Thu, 28 Jul 2022 18:22:20 +0800 +Subject: hwrng: core - let sleep be interrupted when unregistering hwrng +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Jason A. Donenfeld + +commit 36cb6494429bd64b27b7ff8b4af56f8e526da2b4 upstream. + +There are two deadlock scenarios that need addressing, which cause +problems when the computer goes to sleep, the interface is set down, and +hwrng_unregister() is called. When the deadlock is hit, sleep is delayed +for tens of seconds, causing it to fail. These scenarios are: + +1) The hwrng kthread can't be stopped while it's sleeping, because it + uses msleep_interruptible() which does not react to kthread_stop. + +2) A normal user thread can't be interrupted by hwrng_unregister() while + it's sleeping, because hwrng_unregister() is called from elsewhere. + +We solve both issues by add a completion object called dying that +fulfils waiters once we have started the process in hwrng_unregister. + +At the same time, we should cleanup a common and useless dmesg splat +in the same area. + +Cc: +Reported-by: Gregory Erwin +Fixes: fcd09c90c3c5 ("ath9k: use hw_random API instead of directly dumping into random.c") +Link: https://lore.kernel.org/all/CAO+Okf6ZJC5-nTE_EJUGQtd8JiCkiEHytGgDsFGTEjs0c00giw@mail.gmail.com/ +Link: https://lore.kernel.org/lkml/CAO+Okf5k+C+SE6pMVfPf-d8MfVPVq4PO7EY8Hys_DVXtent3HA@mail.gmail.com/ +Link: https://bugs.archlinux.org/task/75138 +Signed-off-by: Jason A. Donenfeld +Signed-off-by: Herbert Xu +Acked-by: Toke Høiland-Jørgensen +Acked-by: Kalle Valo +Signed-off-by: Herbert Xu +Signed-off-by: Greg Kroah-Hartman +--- + drivers/char/hw_random/core.c | 19 +++++++++++++++---- + drivers/net/wireless/ath/ath9k/rng.c | 3 ++- + include/linux/hw_random.h | 3 +++ + 3 files changed, 20 insertions(+), 5 deletions(-) + +--- a/drivers/char/hw_random/core.c ++++ b/drivers/char/hw_random/core.c +@@ -507,16 +507,17 @@ static int hwrng_fillfn(void *unused) + rng->quality = current_quality; /* obsolete */ + quality = rng->quality; + mutex_unlock(&reading_mutex); ++ ++ if (rc <= 0) ++ hwrng_msleep(rng, 10000); ++ + put_rng(rng); + + if (!quality) + break; + +- if (rc <= 0) { +- pr_warn("hwrng: no data available\n"); +- msleep_interruptible(10000); ++ if (rc <= 0) + continue; +- } + + /* If we cannot credit at least one bit of entropy, + * keep track of the remainder for the next iteration +@@ -570,6 +571,7 @@ int hwrng_register(struct hwrng *rng) + + init_completion(&rng->cleanup_done); + complete(&rng->cleanup_done); ++ init_completion(&rng->dying); + + if (!current_rng || + (!cur_rng_set_by_user && rng->quality > current_rng->quality)) { +@@ -617,6 +619,7 @@ void hwrng_unregister(struct hwrng *rng) + + old_rng = current_rng; + list_del(&rng->list); ++ complete_all(&rng->dying); + if (current_rng == rng) { + err = enable_best_rng(); + if (err) { +@@ -685,6 +688,14 @@ void devm_hwrng_unregister(struct device + } + EXPORT_SYMBOL_GPL(devm_hwrng_unregister); + ++long hwrng_msleep(struct hwrng *rng, unsigned int msecs) ++{ ++ unsigned long timeout = msecs_to_jiffies(msecs) + 1; ++ ++ return wait_for_completion_interruptible_timeout(&rng->dying, timeout); ++} ++EXPORT_SYMBOL_GPL(hwrng_msleep); ++ + static int __init hwrng_modinit(void) + { + int ret; +--- a/drivers/net/wireless/ath/ath9k/rng.c ++++ b/drivers/net/wireless/ath/ath9k/rng.c +@@ -83,7 +83,8 @@ static int ath9k_rng_read(struct hwrng * + if (!wait || !max || likely(bytes_read) || fail_stats > 110) + break; + +- msleep_interruptible(ath9k_rng_delay_get(++fail_stats)); ++ if (hwrng_msleep(rng, ath9k_rng_delay_get(++fail_stats))) ++ break; + } + + if (wait && !bytes_read && max) +--- a/include/linux/hw_random.h ++++ b/include/linux/hw_random.h +@@ -50,6 +50,7 @@ struct hwrng { + struct list_head list; + struct kref ref; + struct completion cleanup_done; ++ struct completion dying; + }; + + struct device; +@@ -61,4 +62,6 @@ extern int devm_hwrng_register(struct de + extern void hwrng_unregister(struct hwrng *rng); + extern void devm_hwrng_unregister(struct device *dve, struct hwrng *rng); + ++extern long hwrng_msleep(struct hwrng *rng, unsigned int msecs); ++ + #endif /* LINUX_HWRANDOM_H_ */ diff --git a/queue-6.0/ksmbd-fix-endless-loop-when-encryption-for-response-fails.patch b/queue-6.0/ksmbd-fix-endless-loop-when-encryption-for-response-fails.patch new file mode 100644 index 00000000000..b3ee7a2a8f8 --- /dev/null +++ b/queue-6.0/ksmbd-fix-endless-loop-when-encryption-for-response-fails.patch @@ -0,0 +1,35 @@ +From 360c8ee6fefdb496fffd2c18bb9a96a376a1a804 Mon Sep 17 00:00:00 2001 +From: Namjae Jeon +Date: Thu, 22 Sep 2022 23:35:43 +0900 +Subject: ksmbd: fix endless loop when encryption for response fails + +From: Namjae Jeon + +commit 360c8ee6fefdb496fffd2c18bb9a96a376a1a804 upstream. + +If ->encrypt_resp return error, goto statement cause endless loop. +It send an error response immediately after removing it. + +Fixes: 0626e6641f6b ("cifsd: add server handler for central processing and tranport layers") +Cc: stable@vger.kernel.org +Signed-off-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman +--- + fs/ksmbd/server.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +--- a/fs/ksmbd/server.c ++++ b/fs/ksmbd/server.c +@@ -235,10 +235,8 @@ send: + if (work->sess && work->sess->enc && work->encrypted && + conn->ops->encrypt_resp) { + rc = conn->ops->encrypt_resp(work); +- if (rc < 0) { ++ if (rc < 0) + conn->ops->set_rsp_status(work, STATUS_DATA_ERROR); +- goto send; +- } + } + + ksmbd_conn_write(work); diff --git a/queue-6.0/ksmbd-fix-incorrect-handling-of-iterate_dir.patch b/queue-6.0/ksmbd-fix-incorrect-handling-of-iterate_dir.patch new file mode 100644 index 00000000000..1e321b0c666 --- /dev/null +++ b/queue-6.0/ksmbd-fix-incorrect-handling-of-iterate_dir.patch @@ -0,0 +1,77 @@ +From 88541cb414b7a2450c45fc9c131b37b5753b7679 Mon Sep 17 00:00:00 2001 +From: Namjae Jeon +Date: Fri, 9 Sep 2022 17:43:53 +0900 +Subject: ksmbd: fix incorrect handling of iterate_dir + +From: Namjae Jeon + +commit 88541cb414b7a2450c45fc9c131b37b5753b7679 upstream. + +if iterate_dir() returns non-negative value, caller has to treat it +as normal and check there is any error while populating dentry +information. ksmbd doesn't have to do anything because ksmbd already +checks too small OutputBufferLength to store one file information. + +And because ctx->pos is set to file->f_pos when iterative_dir is called, +remove restart_ctx(). And if iterate_dir() return -EIO, which mean +directory entry is corrupted, return STATUS_FILE_CORRUPT_ERROR error +response. + +This patch fixes some failure of SMB2_QUERY_DIRECTORY, which happens when +ntfs3 is local filesystem. + +Fixes: e2f34481b24d ("cifsd: add server-side procedures for SMB3") +Cc: stable@vger.kernel.org +Signed-off-by: Hyunchul Lee +Signed-off-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman +--- + fs/ksmbd/smb2pdu.c | 14 ++++---------- + 1 file changed, 4 insertions(+), 10 deletions(-) + +--- a/fs/ksmbd/smb2pdu.c ++++ b/fs/ksmbd/smb2pdu.c +@@ -3808,11 +3808,6 @@ static int __query_dir(struct dir_contex + return 0; + } + +-static void restart_ctx(struct dir_context *ctx) +-{ +- ctx->pos = 0; +-} +- + static int verify_info_level(int info_level) + { + switch (info_level) { +@@ -3921,7 +3916,6 @@ int smb2_query_dir(struct ksmbd_work *wo + if (srch_flag & SMB2_REOPEN || srch_flag & SMB2_RESTART_SCANS) { + ksmbd_debug(SMB, "Restart directory scan\n"); + generic_file_llseek(dir_fp->filp, 0, SEEK_SET); +- restart_ctx(&dir_fp->readdir_data.ctx); + } + + memset(&d_info, 0, sizeof(struct ksmbd_dir_info)); +@@ -3968,11 +3962,9 @@ int smb2_query_dir(struct ksmbd_work *wo + */ + if (!d_info.out_buf_len && !d_info.num_entry) + goto no_buf_len; +- if (rc == 0) +- restart_ctx(&dir_fp->readdir_data.ctx); +- if (rc == -ENOSPC) ++ if (rc > 0 || rc == -ENOSPC) + rc = 0; +- if (rc) ++ else if (rc) + goto err_out; + + d_info.wptr = d_info.rptr; +@@ -4029,6 +4021,8 @@ err_out2: + rsp->hdr.Status = STATUS_NO_MEMORY; + else if (rc == -EFAULT) + rsp->hdr.Status = STATUS_INVALID_INFO_CLASS; ++ else if (rc == -EIO) ++ rsp->hdr.Status = STATUS_FILE_CORRUPT_ERROR; + if (!rsp->hdr.Status) + rsp->hdr.Status = STATUS_UNEXPECTED_IO_ERROR; + diff --git a/queue-6.0/ksmbd-fix-user-namespace-mapping.patch b/queue-6.0/ksmbd-fix-user-namespace-mapping.patch new file mode 100644 index 00000000000..dd5d56f35ea --- /dev/null +++ b/queue-6.0/ksmbd-fix-user-namespace-mapping.patch @@ -0,0 +1,58 @@ +From 7c88c1e0ab1704bacb751341ee6431c3be34b834 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micka=C3=ABl=20Sala=C3=BCn?= +Date: Thu, 29 Sep 2022 12:04:47 +0200 +Subject: ksmbd: Fix user namespace mapping +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Mickaël Salaün + +commit 7c88c1e0ab1704bacb751341ee6431c3be34b834 upstream. + +A kernel daemon should not rely on the current thread, which is unknown +and might be malicious. Before this security fix, +ksmbd_override_fsids() didn't correctly override FS UID/GID which means +that arbitrary user space threads could trick the kernel to impersonate +arbitrary users or groups for file system access checks, leading to +file system access bypass. + +This was found while investigating truncate support for Landlock: +https://lore.kernel.org/r/CAKYAXd8fpMJ7guizOjHgxEyyjoUwPsx3jLOPZP=wPYcbhkVXqA@mail.gmail.com + +Fixes: e2f34481b24d ("cifsd: add server-side procedures for SMB3") +Cc: Hyunchul Lee +Cc: Steve French +Cc: stable@vger.kernel.org +Signed-off-by: Mickaël Salaün +Link: https://lore.kernel.org/r/20220929100447.108468-1-mic@digikod.net +Acked-by: Christian Brauner (Microsoft) +Acked-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman +--- + fs/ksmbd/smb_common.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/fs/ksmbd/smb_common.c ++++ b/fs/ksmbd/smb_common.c +@@ -4,6 +4,8 @@ + * Copyright (C) 2018 Namjae Jeon + */ + ++#include ++ + #include "smb_common.h" + #include "server.h" + #include "misc.h" +@@ -625,8 +627,8 @@ int ksmbd_override_fsids(struct ksmbd_wo + if (!cred) + return -ENOMEM; + +- cred->fsuid = make_kuid(current_user_ns(), uid); +- cred->fsgid = make_kgid(current_user_ns(), gid); ++ cred->fsuid = make_kuid(&init_user_ns, uid); ++ cred->fsgid = make_kgid(&init_user_ns, gid); + + gi = groups_alloc(0); + if (!gi) { diff --git a/queue-6.0/ksmbd-fix-wrong-return-value-and-message-length-check-in-smb2_ioctl.patch b/queue-6.0/ksmbd-fix-wrong-return-value-and-message-length-check-in-smb2_ioctl.patch new file mode 100644 index 00000000000..d1ada333def --- /dev/null +++ b/queue-6.0/ksmbd-fix-wrong-return-value-and-message-length-check-in-smb2_ioctl.patch @@ -0,0 +1,56 @@ +From b1763d265af62800ec96eeb79803c4c537dcef3a Mon Sep 17 00:00:00 2001 +From: Zhang Xiaoxu +Date: Mon, 26 Sep 2022 11:36:30 +0800 +Subject: ksmbd: Fix wrong return value and message length check in smb2_ioctl() + +From: Zhang Xiaoxu + +commit b1763d265af62800ec96eeb79803c4c537dcef3a upstream. + +Commit c7803b05f74b ("smb3: fix ksmbd bigendian bug in oplock +break, and move its struct to smbfs_common") use the defination +of 'struct validate_negotiate_info_req' in smbfs_common, the +array length of 'Dialects' changed from 1 to 4, but the protocol +does not require the client to send all 4. This lead the request +which satisfied with protocol and server to fail. + +So just ensure the request payload has the 'DialectCount' in +smb2_ioctl(), then fsctl_validate_negotiate_info() will use it +to validate the payload length and each dialect. + +Also when the {in, out}_buf_len is less than the required, should +goto out to initialize the status in the response header. + +Fixes: f7db8fd03a4b ("ksmbd: add validation in smb2_ioctl") +Cc: stable@vger.kernel.org +Signed-off-by: Zhang Xiaoxu +Acked-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman +--- + fs/ksmbd/smb2pdu.c | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +--- a/fs/ksmbd/smb2pdu.c ++++ b/fs/ksmbd/smb2pdu.c +@@ -7637,11 +7637,16 @@ int smb2_ioctl(struct ksmbd_work *work) + goto out; + } + +- if (in_buf_len < sizeof(struct validate_negotiate_info_req)) +- return -EINVAL; ++ if (in_buf_len < offsetof(struct validate_negotiate_info_req, ++ Dialects)) { ++ ret = -EINVAL; ++ goto out; ++ } + +- if (out_buf_len < sizeof(struct validate_negotiate_info_rsp)) +- return -EINVAL; ++ if (out_buf_len < sizeof(struct validate_negotiate_info_rsp)) { ++ ret = -EINVAL; ++ goto out; ++ } + + ret = fsctl_validate_negotiate_info(conn, + (struct validate_negotiate_info_req *)&req->Buffer[0], diff --git a/queue-6.0/pinctrl-rockchip-add-pinmux_ops.gpio_set_direction-callback.patch b/queue-6.0/pinctrl-rockchip-add-pinmux_ops.gpio_set_direction-callback.patch new file mode 100644 index 00000000000..f0304419c3a --- /dev/null +++ b/queue-6.0/pinctrl-rockchip-add-pinmux_ops.gpio_set_direction-callback.patch @@ -0,0 +1,60 @@ +From 4635c0e2a7f7f3568cbfccae70121f9835efa62c Mon Sep 17 00:00:00 2001 +From: Quentin Schulz +Date: Fri, 30 Sep 2022 15:20:32 +0200 +Subject: pinctrl: rockchip: add pinmux_ops.gpio_set_direction callback + +From: Quentin Schulz + +commit 4635c0e2a7f7f3568cbfccae70121f9835efa62c upstream. + +Before the split of gpio and pinctrl sections in their own driver, +rockchip_set_mux was called in pinmux_ops.gpio_set_direction for +configuring a pin in its GPIO function. + +This is essential for cases where pinctrl is "bypassed" by gpio +consumers otherwise the GPIO function is not configured for the pin and +it does not work. Such was the case for the sysfs/libgpiod userspace +GPIO handling. + +Let's re-implement the pinmux_ops.gpio_set_direction callback so that +the gpio subsystem can request from the pinctrl driver to put the pin in +its GPIO function. + +Fixes: 9ce9a02039de ("pinctrl/rockchip: drop the gpio related codes") +Cc: stable@vger.kernel.org +Reviewed-by: Heiko Stuebner +Signed-off-by: Quentin Schulz +Link: https://lore.kernel.org/r/20220930132033.4003377-2-foss+kernel@0leil.net +Signed-off-by: Linus Walleij +Signed-off-by: Greg Kroah-Hartman +--- + drivers/pinctrl/pinctrl-rockchip.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +--- a/drivers/pinctrl/pinctrl-rockchip.c ++++ b/drivers/pinctrl/pinctrl-rockchip.c +@@ -2393,11 +2393,24 @@ static int rockchip_pmx_set(struct pinct + return 0; + } + ++static int rockchip_pmx_gpio_set_direction(struct pinctrl_dev *pctldev, ++ struct pinctrl_gpio_range *range, ++ unsigned offset, ++ bool input) ++{ ++ struct rockchip_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); ++ struct rockchip_pin_bank *bank; ++ ++ bank = pin_to_bank(info, offset); ++ return rockchip_set_mux(bank, offset - bank->pin_base, RK_FUNC_GPIO); ++} ++ + static const struct pinmux_ops rockchip_pmx_ops = { + .get_functions_count = rockchip_pmx_get_funcs_count, + .get_function_name = rockchip_pmx_get_func_name, + .get_function_groups = rockchip_pmx_get_groups, + .set_mux = rockchip_pmx_set, ++ .gpio_set_direction = rockchip_pmx_gpio_set_direction, + }; + + /* diff --git a/queue-6.0/series b/queue-6.0/series index 13cc38cc9d8..76346a5e879 100644 --- a/queue-6.0/series +++ b/queue-6.0/series @@ -105,3 +105,18 @@ slimbus-qcom-ngd-use-correct-error-in-message-of-pdr_add_lookup-failure.patch slimbus-qcom-ngd-cleanup-in-probe-error-path.patch scsi-lpfc-rework-mib-rx-monitor-debug-info-logic.patch scsi-qedf-populate-sysfs-attributes-for-vport.patch +gpio-rockchip-request-gpio-mux-to-pinctrl-when-setting-direction.patch +pinctrl-rockchip-add-pinmux_ops.gpio_set_direction-callback.patch +fbdev-smscufx-fix-use-after-free-in-ufx_ops_open.patch +hwrng-core-let-sleep-be-interrupted-when-unregistering-hwrng.patch +smb3-do-not-log-confusing-message-when-server-returns-no-network-interfaces.patch +ksmbd-fix-incorrect-handling-of-iterate_dir.patch +ksmbd-fix-endless-loop-when-encryption-for-response-fails.patch +ksmbd-fix-wrong-return-value-and-message-length-check-in-smb2_ioctl.patch +ksmbd-fix-user-namespace-mapping.patch +fs-record-i_dirty_time-even-if-inode-already-has-i_dirty_inode.patch +btrfs-fix-alignment-of-vma-for-memory-mapped-files-on-thp.patch +btrfs-enhance-unsupported-compat-ro-flags-handling.patch +btrfs-fix-race-between-quota-enable-and-quota-rescan-ioctl.patch +btrfs-fix-missed-extent-on-fsync-after-dropping-extent-maps.patch +btrfs-set-generation-before-calling-btrfs_clean_tree_block-in-btrfs_init_new_buffer.patch diff --git a/queue-6.0/smb3-do-not-log-confusing-message-when-server-returns-no-network-interfaces.patch b/queue-6.0/smb3-do-not-log-confusing-message-when-server-returns-no-network-interfaces.patch new file mode 100644 index 00000000000..b49b012b05e --- /dev/null +++ b/queue-6.0/smb3-do-not-log-confusing-message-when-server-returns-no-network-interfaces.patch @@ -0,0 +1,111 @@ +From 4659f01e3cd94f64d9bd06764ace2ef8fe1b6227 Mon Sep 17 00:00:00 2001 +From: Steve French +Date: Sat, 1 Oct 2022 11:44:08 -0500 +Subject: smb3: do not log confusing message when server returns no network interfaces + +From: Steve French + +commit 4659f01e3cd94f64d9bd06764ace2ef8fe1b6227 upstream. + +Some servers can return an empty network interface list so, unless +multichannel is requested, no need to log an error for this, and +when multichannel is requested on mount but no interfaces, log +something less confusing. For this case change + parse_server_interfaces: malformed interface info +to + empty network interface list returned by server localhost + +Also do not relog this error every ten minutes (only log on mount, once) + +Cc: +Reviewed-by: Paulo Alcantara (SUSE) +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman +--- + fs/cifs/cifsproto.h | 2 +- + fs/cifs/connect.c | 2 +- + fs/cifs/smb2ops.c | 23 ++++++++++++++++++----- + 3 files changed, 20 insertions(+), 7 deletions(-) + +--- a/fs/cifs/cifsproto.h ++++ b/fs/cifs/cifsproto.h +@@ -639,7 +639,7 @@ cifs_chan_is_iface_active(struct cifs_se + int + cifs_chan_update_iface(struct cifs_ses *ses, struct TCP_Server_Info *server); + int +-SMB3_request_interfaces(const unsigned int xid, struct cifs_tcon *tcon); ++SMB3_request_interfaces(const unsigned int xid, struct cifs_tcon *tcon, bool in_mount); + + void extract_unc_hostname(const char *unc, const char **h, size_t *len); + int copy_path_name(char *dst, const char *src); +--- a/fs/cifs/connect.c ++++ b/fs/cifs/connect.c +@@ -155,7 +155,7 @@ static void smb2_query_server_interfaces + /* + * query server network interfaces, in case they change + */ +- rc = SMB3_request_interfaces(0, tcon); ++ rc = SMB3_request_interfaces(0, tcon, false); + if (rc) { + cifs_dbg(FYI, "%s: failed to query server interfaces: %d\n", + __func__, rc); +--- a/fs/cifs/smb2ops.c ++++ b/fs/cifs/smb2ops.c +@@ -512,8 +512,7 @@ smb3_negotiate_rsize(struct cifs_tcon *t + + static int + parse_server_interfaces(struct network_interface_info_ioctl_rsp *buf, +- size_t buf_len, +- struct cifs_ses *ses) ++ size_t buf_len, struct cifs_ses *ses, bool in_mount) + { + struct network_interface_info_ioctl_rsp *p; + struct sockaddr_in *addr4; +@@ -543,6 +542,20 @@ parse_server_interfaces(struct network_i + } + spin_unlock(&ses->iface_lock); + ++ /* ++ * Samba server e.g. can return an empty interface list in some cases, ++ * which would only be a problem if we were requesting multichannel ++ */ ++ if (bytes_left == 0) { ++ /* avoid spamming logs every 10 minutes, so log only in mount */ ++ if ((ses->chan_max > 1) && in_mount) ++ cifs_dbg(VFS, ++ "empty network interface list returned by server %s\n", ++ ses->server->hostname); ++ rc = -EINVAL; ++ goto out; ++ } ++ + while (bytes_left >= sizeof(*p)) { + memset(&tmp_iface, 0, sizeof(tmp_iface)); + tmp_iface.speed = le64_to_cpu(p->LinkSpeed); +@@ -673,7 +686,7 @@ out: + } + + int +-SMB3_request_interfaces(const unsigned int xid, struct cifs_tcon *tcon) ++SMB3_request_interfaces(const unsigned int xid, struct cifs_tcon *tcon, bool in_mount) + { + int rc; + unsigned int ret_data_len = 0; +@@ -693,7 +706,7 @@ SMB3_request_interfaces(const unsigned i + goto out; + } + +- rc = parse_server_interfaces(out_buf, ret_data_len, ses); ++ rc = parse_server_interfaces(out_buf, ret_data_len, ses, in_mount); + if (rc) + goto out; + +@@ -729,7 +742,7 @@ smb3_qfs_tcon(const unsigned int xid, st + if (rc) + return; + +- SMB3_request_interfaces(xid, tcon); ++ SMB3_request_interfaces(xid, tcon, true /* called during mount */); + + SMB2_QFS_attr(xid, tcon, fid.persistent_fid, fid.volatile_fid, + FS_ATTRIBUTE_INFORMATION);