--- /dev/null
+From 81d5d61454c365718655cfc87d8200c84e25d596 Mon Sep 17 00:00:00 2001
+From: Qu Wenruo <wqu@suse.com>
+Date: Tue, 9 Aug 2022 13:02:16 +0800
+Subject: btrfs: enhance unsupported compat RO flags handling
+
+From: Qu Wenruo <wqu@suse.com>
+
+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 <nborisov@suse.com>
+Signed-off-by: Qu Wenruo <wqu@suse.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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
+@@ -2191,7 +2191,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
+@@ -2113,6 +2113,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;
--- /dev/null
+From b0c582233a8563f3c4228df838cdc67a8807ec78 Mon Sep 17 00:00:00 2001
+From: Alexander Zhu <alexlzhu@fb.com>
+Date: Tue, 2 Aug 2022 13:32:46 -0700
+Subject: btrfs: fix alignment of VMA for memory mapped files on THP
+
+From: Alexander Zhu <alexlzhu@fb.com>
+
+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 <alexlzhu@fb.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/btrfs/file.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
+index 5a3f6e0d9688..8dfce1c40b5f 100644
+--- a/fs/btrfs/file.c
++++ b/fs/btrfs/file.c
+@@ -3810,6 +3810,7 @@ const struct file_operations btrfs_file_operations = {
+ .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,
+--
+2.38.0
+
--- /dev/null
+From cef7820d6abf8d61f8e1db411eae3c712f6d72a2 Mon Sep 17 00:00:00 2001
+From: Filipe Manana <fdmanana@suse.com>
+Date: Mon, 19 Sep 2022 15:06:28 +0100
+Subject: btrfs: fix missed extent on fsync after dropping extent maps
+
+From: Filipe Manana <fdmanana@suse.com>
+
+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 <anand.jain@oracle.com>
+Signed-off-by: Filipe Manana <fdmanana@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 */
+@@ -2202,14 +2233,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
+@@ -2234,6 +2257,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.
+ *
--- /dev/null
+From 331cd9461412e103d07595a10289de90004ac890 Mon Sep 17 00:00:00 2001
+From: Filipe Manana <fdmanana@suse.com>
+Date: Tue, 23 Aug 2022 12:45:42 +0100
+Subject: btrfs: fix race between quota enable and quota rescan ioctl
+
+From: Filipe Manana <fdmanana@suse.com>
+
+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 <yebin10@huawei.com>
+Link: https://lore.kernel.org/linux-btrfs/20220823015931.421355-1-yebin10@huawei.com/
+CC: stable@vger.kernel.org # 4.19+
+Reviewed-by: Qu Wenruo <wqu@suse.com>
+Signed-off-by: Filipe Manana <fdmanana@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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:
--- /dev/null
+From cbddcc4fa3443fe8cfb2ff8e210deb1f6a0eea38 Mon Sep 17 00:00:00 2001
+From: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
+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 <penguin-kernel@I-love.SAKURA.ne.jp>
+
+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 <syzbot+fba8e2116a12609b6c59@syzkaller.appspotmail.com>
+Fixes: bc877d285ca3dba2 ("btrfs: Deduplicate extent_buffer init code")
+CC: stable@vger.kernel.org # 4.19+
+Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/btrfs/extent-tree.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/fs/btrfs/extent-tree.c
++++ b/fs/btrfs/extent-tree.c
+@@ -4904,6 +4904,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
--- /dev/null
+From 5610bcfe8693c02e2e4c8b31427f1bdbdecc839c Mon Sep 17 00:00:00 2001
+From: Hyunwoo Kim <imv4bel@gmail.com>
+Date: Sun, 25 Sep 2022 06:32:43 -0700
+Subject: fbdev: smscufx: Fix use-after-free in ufx_ops_open()
+
+From: Hyunwoo Kim <imv4bel@gmail.com>
+
+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 <imv4bel@gmail.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Helge Deller <deller@gmx.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 = {
--- /dev/null
+From cbfecb927f429a6fa613d74b998496bd71e4438a Mon Sep 17 00:00:00 2001
+From: Lukas Czerner <lczerner@redhat.com>
+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 <lczerner@redhat.com>
+
+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 <david@fromorbit.com>
+Cc: Christoph Hellwig <hch@infradead.org>
+Cc: stable@kernel.org
+Signed-off-by: Lukas Czerner <lczerner@redhat.com>
+Suggested-by: Jan Kara <jack@suse.cz>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Link: https://lore.kernel.org/r/20220825100657.44217-1-lczerner@redhat.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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
+@@ -650,7 +650,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;
+@@ -658,7 +658,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
+@@ -2241,13 +2241,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
--- /dev/null
+From 8ea8af6c8469156ac2042d83d73f6b74eb4b4b45 Mon Sep 17 00:00:00 2001
+From: Quentin Schulz <quentin.schulz@theobroma-systems.com>
+Date: Fri, 30 Sep 2022 15:20:33 +0200
+Subject: gpio: rockchip: request GPIO mux to pinctrl when setting direction
+
+From: Quentin Schulz <quentin.schulz@theobroma-systems.com>
+
+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 <heiko@sntech.de>
+Signed-off-by: Quentin Schulz <quentin.schulz@theobroma-systems.com>
+Link: https://lore.kernel.org/r/20220930132033.4003377-3-foss+kernel@0leil.net
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 <linux/of_address.h>
+ #include <linux/of_device.h>
+ #include <linux/of_irq.h>
++#include <linux/pinctrl/consumer.h>
+ #include <linux/pinctrl/pinconf-generic.h>
+ #include <linux/regmap.h>
+
+@@ -155,6 +156,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);
--- /dev/null
+From 36cb6494429bd64b27b7ff8b4af56f8e526da2b4 Mon Sep 17 00:00:00 2001
+From: "Jason A. Donenfeld" <Jason@zx2c4.com>
+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 <Jason@zx2c4.com>
+
+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: <stable@vger.kernel.org>
+Reported-by: Gregory Erwin <gregerwin256@gmail.com>
+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 <Jason@zx2c4.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Acked-by: Toke Høiland-Jørgensen <toke@toke.dk>
+Acked-by: Kalle Valo <kvalo@kernel.org>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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(-)
+
+diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c
+index 16f227b995e8..d7045dfaf16c 100644
+--- 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 *dev, struct hwrng *rng)
+ }
+ 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;
+diff --git a/drivers/net/wireless/ath/ath9k/rng.c b/drivers/net/wireless/ath/ath9k/rng.c
+index cb5414265a9b..58c0ab01771b 100644
+--- 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 *rng, void *buf, size_t max, bool wait)
+ 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)
+diff --git a/include/linux/hw_random.h b/include/linux/hw_random.h
+index aa1d4da03538..77c2885c4c13 100644
+--- 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 device *dev, struct hwrng *rng);
+ 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_ */
+--
+2.38.0
+
--- /dev/null
+From 360c8ee6fefdb496fffd2c18bb9a96a376a1a804 Mon Sep 17 00:00:00 2001
+From: Namjae Jeon <linkinjeon@kernel.org>
+Date: Thu, 22 Sep 2022 23:35:43 +0900
+Subject: ksmbd: fix endless loop when encryption for response fails
+
+From: Namjae Jeon <linkinjeon@kernel.org>
+
+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 <linkinjeon@kernel.org>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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);
--- /dev/null
+From 88541cb414b7a2450c45fc9c131b37b5753b7679 Mon Sep 17 00:00:00 2001
+From: Namjae Jeon <linkinjeon@kernel.org>
+Date: Fri, 9 Sep 2022 17:43:53 +0900
+Subject: ksmbd: fix incorrect handling of iterate_dir
+
+From: Namjae Jeon <linkinjeon@kernel.org>
+
+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 <hyc.lee@gmail.com>
+Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ksmbd/smb2pdu.c | 14 ++++----------
+ 1 file changed, 4 insertions(+), 10 deletions(-)
+
+--- a/fs/ksmbd/smb2pdu.c
++++ b/fs/ksmbd/smb2pdu.c
+@@ -3798,11 +3798,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) {
+@@ -3911,7 +3906,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));
+@@ -3958,11 +3952,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;
+@@ -4019,6 +4011,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;
+
--- /dev/null
+From 7c88c1e0ab1704bacb751341ee6431c3be34b834 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Micka=C3=ABl=20Sala=C3=BCn?= <mic@digikod.net>
+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 <mic@digikod.net>
+
+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 <hyc.lee@gmail.com>
+Cc: Steve French <smfrench@gmail.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Mickaël Salaün <mic@digikod.net>
+Link: https://lore.kernel.org/r/20220929100447.108468-1-mic@digikod.net
+Acked-by: Christian Brauner (Microsoft) <brauner@kernel.org>
+Acked-by: Namjae Jeon <linkinjeon@kernel.org>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 <linkinjeon@kernel.org>
+ */
+
++#include <linux/user_namespace.h>
++
+ #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) {
--- /dev/null
+From b1763d265af62800ec96eeb79803c4c537dcef3a Mon Sep 17 00:00:00 2001
+From: Zhang Xiaoxu <zhangxiaoxu5@huawei.com>
+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 <zhangxiaoxu5@huawei.com>
+
+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 <zhangxiaoxu5@huawei.com>
+Acked-by: Namjae Jeon <linkinjeon@kernel.org>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ksmbd/smb2pdu.c | 13 +++++++++----
+ 1 file changed, 9 insertions(+), 4 deletions(-)
+
+--- a/fs/ksmbd/smb2pdu.c
++++ b/fs/ksmbd/smb2pdu.c
+@@ -7627,11 +7627,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],
--- /dev/null
+From 4635c0e2a7f7f3568cbfccae70121f9835efa62c Mon Sep 17 00:00:00 2001
+From: Quentin Schulz <quentin.schulz@theobroma-systems.com>
+Date: Fri, 30 Sep 2022 15:20:32 +0200
+Subject: pinctrl: rockchip: add pinmux_ops.gpio_set_direction callback
+
+From: Quentin Schulz <quentin.schulz@theobroma-systems.com>
+
+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 <heiko@sntech.de>
+Signed-off-by: Quentin Schulz <quentin.schulz@theobroma-systems.com>
+Link: https://lore.kernel.org/r/20220930132033.4003377-2-foss+kernel@0leil.net
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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,
+ };
+
+ /*
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
--- /dev/null
+From 4659f01e3cd94f64d9bd06764ace2ef8fe1b6227 Mon Sep 17 00:00:00 2001
+From: Steve French <stfrench@microsoft.com>
+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 <stfrench@microsoft.com>
+
+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: <stable@vger.kernel.org>
+Reviewed-by: Paulo Alcantara (SUSE) <pc@cjr.nz>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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
+@@ -642,7 +642,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
+@@ -511,8 +511,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;
+@@ -542,6 +541,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);
+@@ -672,7 +685,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;
+@@ -692,7 +705,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;
+
+@@ -1022,7 +1035,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);