]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 23 Jan 2022 17:19:01 +0000 (18:19 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 23 Jan 2022 17:19:01 +0000 (18:19 +0100)
added patches:
btrfs-check-the-root-node-for-uptodate-before-returning-it.patch
btrfs-fix-deadlock-between-quota-enable-and-other-quota-operations.patch
btrfs-respect-the-max-size-in-the-header-when-activating-swap-file.patch
ext4-make-sure-quota-gets-properly-shutdown-on-error.patch
ext4-make-sure-to-reset-inode-lockdep-class-when-quota-enabling-fails.patch

queue-5.4/btrfs-check-the-root-node-for-uptodate-before-returning-it.patch [new file with mode: 0644]
queue-5.4/btrfs-fix-deadlock-between-quota-enable-and-other-quota-operations.patch [new file with mode: 0644]
queue-5.4/btrfs-respect-the-max-size-in-the-header-when-activating-swap-file.patch [new file with mode: 0644]
queue-5.4/ext4-make-sure-quota-gets-properly-shutdown-on-error.patch [new file with mode: 0644]
queue-5.4/ext4-make-sure-to-reset-inode-lockdep-class-when-quota-enabling-fails.patch [new file with mode: 0644]
queue-5.4/series

diff --git a/queue-5.4/btrfs-check-the-root-node-for-uptodate-before-returning-it.patch b/queue-5.4/btrfs-check-the-root-node-for-uptodate-before-returning-it.patch
new file mode 100644 (file)
index 0000000..3db5b9c
--- /dev/null
@@ -0,0 +1,68 @@
+From 120de408e4b97504a2d9b5ca534b383de2c73d49 Mon Sep 17 00:00:00 2001
+From: Josef Bacik <josef@toxicpanda.com>
+Date: Wed, 24 Nov 2021 14:14:24 -0500
+Subject: btrfs: check the root node for uptodate before returning it
+
+From: Josef Bacik <josef@toxicpanda.com>
+
+commit 120de408e4b97504a2d9b5ca534b383de2c73d49 upstream.
+
+Now that we clear the extent buffer uptodate if we fail to write it out
+we need to check to see if our root node is uptodate before we search
+down it.  Otherwise we could return stale data (or potentially corrupt
+data that was caught by the write verification step) and think that the
+path is OK to search down.
+
+CC: stable@vger.kernel.org # 5.4+
+Reviewed-by: Nikolay Borisov <nborisov@suse.com>
+Signed-off-by: Josef Bacik <josef@toxicpanda.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/btrfs/ctree.c |   19 +++++++++++++++----
+ 1 file changed, 15 insertions(+), 4 deletions(-)
+
+--- a/fs/btrfs/ctree.c
++++ b/fs/btrfs/ctree.c
+@@ -2658,12 +2658,9 @@ static struct extent_buffer *btrfs_searc
+ {
+       struct btrfs_fs_info *fs_info = root->fs_info;
+       struct extent_buffer *b;
+-      int root_lock;
++      int root_lock = 0;
+       int level = 0;
+-      /* We try very hard to do read locks on the root */
+-      root_lock = BTRFS_READ_LOCK;
+-
+       if (p->search_commit_root) {
+               /*
+                * The commit roots are read only so we always do read locks,
+@@ -2701,6 +2698,9 @@ static struct extent_buffer *btrfs_searc
+               goto out;
+       }
++      /* We try very hard to do read locks on the root */
++      root_lock = BTRFS_READ_LOCK;
++
+       /*
+        * If the level is set to maximum, we can skip trying to get the read
+        * lock.
+@@ -2727,6 +2727,17 @@ static struct extent_buffer *btrfs_searc
+       level = btrfs_header_level(b);
+ out:
++      /*
++       * The root may have failed to write out at some point, and thus is no
++       * longer valid, return an error in this case.
++       */
++      if (!extent_buffer_uptodate(b)) {
++              if (root_lock)
++                      btrfs_tree_unlock_rw(b, root_lock);
++              free_extent_buffer(b);
++              return ERR_PTR(-EIO);
++      }
++
+       p->nodes[level] = b;
+       if (!p->skip_locking)
+               p->locks[level] = root_lock;
diff --git a/queue-5.4/btrfs-fix-deadlock-between-quota-enable-and-other-quota-operations.patch b/queue-5.4/btrfs-fix-deadlock-between-quota-enable-and-other-quota-operations.patch
new file mode 100644 (file)
index 0000000..49d37b9
--- /dev/null
@@ -0,0 +1,128 @@
+From 232796df8c1437c41d308d161007f0715bac0a54 Mon Sep 17 00:00:00 2001
+From: Filipe Manana <fdmanana@suse.com>
+Date: Wed, 27 Oct 2021 18:30:25 +0100
+Subject: btrfs: fix deadlock between quota enable and other quota operations
+
+From: Filipe Manana <fdmanana@suse.com>
+
+commit 232796df8c1437c41d308d161007f0715bac0a54 upstream.
+
+When enabling quotas, we attempt to commit a transaction while holding the
+mutex fs_info->qgroup_ioctl_lock. This can result on a deadlock with other
+quota operations such as:
+
+- qgroup creation and deletion, ioctl BTRFS_IOC_QGROUP_CREATE;
+
+- adding and removing qgroup relations, ioctl BTRFS_IOC_QGROUP_ASSIGN.
+
+This is because these operations join a transaction and after that they
+attempt to lock the mutex fs_info->qgroup_ioctl_lock. Acquiring that mutex
+after joining or starting a transaction is a pattern followed everywhere
+in qgroups, so the quota enablement operation is the one at fault here,
+and should not commit a transaction while holding that mutex.
+
+Fix this by making the transaction commit while not holding the mutex.
+We are safe from two concurrent tasks trying to enable quotas because
+we are serialized by the rw semaphore fs_info->subvol_sem at
+btrfs_ioctl_quota_ctl(), which is the only call site for enabling
+quotas.
+
+When this deadlock happens, it produces a trace like the following:
+
+  INFO: task syz-executor:25604 blocked for more than 143 seconds.
+  Not tainted 5.15.0-rc6 #4
+  "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
+  task:syz-executor state:D stack:24800 pid:25604 ppid: 24873 flags:0x00004004
+  Call Trace:
+  context_switch kernel/sched/core.c:4940 [inline]
+  __schedule+0xcd9/0x2530 kernel/sched/core.c:6287
+  schedule+0xd3/0x270 kernel/sched/core.c:6366
+  btrfs_commit_transaction+0x994/0x2e90 fs/btrfs/transaction.c:2201
+  btrfs_quota_enable+0x95c/0x1790 fs/btrfs/qgroup.c:1120
+  btrfs_ioctl_quota_ctl fs/btrfs/ioctl.c:4229 [inline]
+  btrfs_ioctl+0x637e/0x7b70 fs/btrfs/ioctl.c:5010
+  vfs_ioctl fs/ioctl.c:51 [inline]
+  __do_sys_ioctl fs/ioctl.c:874 [inline]
+  __se_sys_ioctl fs/ioctl.c:860 [inline]
+  __x64_sys_ioctl+0x193/0x200 fs/ioctl.c:860
+  do_syscall_x64 arch/x86/entry/common.c:50 [inline]
+  do_syscall_64+0x35/0xb0 arch/x86/entry/common.c:80
+  entry_SYSCALL_64_after_hwframe+0x44/0xae
+  RIP: 0033:0x7f86920b2c4d
+  RSP: 002b:00007f868f61ac58 EFLAGS: 00000246 ORIG_RAX: 0000000000000010
+  RAX: ffffffffffffffda RBX: 00007f86921d90a0 RCX: 00007f86920b2c4d
+  RDX: 0000000020005e40 RSI: 00000000c0109428 RDI: 0000000000000008
+  RBP: 00007f869212bd80 R08: 0000000000000000 R09: 0000000000000000
+  R10: 0000000000000000 R11: 0000000000000246 R12: 00007f86921d90a0
+  R13: 00007fff6d233e4f R14: 00007fff6d233ff0 R15: 00007f868f61adc0
+  INFO: task syz-executor:25628 blocked for more than 143 seconds.
+  Not tainted 5.15.0-rc6 #4
+  "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
+  task:syz-executor state:D stack:29080 pid:25628 ppid: 24873 flags:0x00004004
+  Call Trace:
+  context_switch kernel/sched/core.c:4940 [inline]
+  __schedule+0xcd9/0x2530 kernel/sched/core.c:6287
+  schedule+0xd3/0x270 kernel/sched/core.c:6366
+  schedule_preempt_disabled+0xf/0x20 kernel/sched/core.c:6425
+  __mutex_lock_common kernel/locking/mutex.c:669 [inline]
+  __mutex_lock+0xc96/0x1680 kernel/locking/mutex.c:729
+  btrfs_remove_qgroup+0xb7/0x7d0 fs/btrfs/qgroup.c:1548
+  btrfs_ioctl_qgroup_create fs/btrfs/ioctl.c:4333 [inline]
+  btrfs_ioctl+0x683c/0x7b70 fs/btrfs/ioctl.c:5014
+  vfs_ioctl fs/ioctl.c:51 [inline]
+  __do_sys_ioctl fs/ioctl.c:874 [inline]
+  __se_sys_ioctl fs/ioctl.c:860 [inline]
+  __x64_sys_ioctl+0x193/0x200 fs/ioctl.c:860
+  do_syscall_x64 arch/x86/entry/common.c:50 [inline]
+  do_syscall_64+0x35/0xb0 arch/x86/entry/common.c:80
+  entry_SYSCALL_64_after_hwframe+0x44/0xae
+
+Reported-by: Hao Sun <sunhao.th@gmail.com>
+Link: https://lore.kernel.org/linux-btrfs/CACkBjsZQF19bQ1C6=yetF3BvL10OSORpFUcWXTP6HErshDB4dQ@mail.gmail.com/
+Fixes: 340f1aa27f36 ("btrfs: qgroups: Move transaction management inside btrfs_quota_enable/disable")
+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 |   19 +++++++++++++++++++
+ 1 file changed, 19 insertions(+)
+
+--- a/fs/btrfs/qgroup.c
++++ b/fs/btrfs/qgroup.c
+@@ -890,6 +890,14 @@ int btrfs_quota_enable(struct btrfs_fs_i
+       int ret = 0;
+       int slot;
++      /*
++       * We need to have subvol_sem write locked, to prevent races between
++       * concurrent tasks trying to enable quotas, because we will unlock
++       * and relock qgroup_ioctl_lock before setting fs_info->quota_root
++       * and before setting BTRFS_FS_QUOTA_ENABLED.
++       */
++      lockdep_assert_held_write(&fs_info->subvol_sem);
++
+       mutex_lock(&fs_info->qgroup_ioctl_lock);
+       if (fs_info->quota_root)
+               goto out;
+@@ -1035,8 +1043,19 @@ out_add_root:
+               goto out_free_path;
+       }
++      mutex_unlock(&fs_info->qgroup_ioctl_lock);
++      /*
++       * Commit the transaction while not holding qgroup_ioctl_lock, to avoid
++       * a deadlock with tasks concurrently doing other qgroup operations, such
++       * adding/removing qgroups or adding/deleting qgroup relations for example,
++       * because all qgroup operations first start or join a transaction and then
++       * lock the qgroup_ioctl_lock mutex.
++       * We are safe from a concurrent task trying to enable quotas, by calling
++       * this function, since we are serialized by fs_info->subvol_sem.
++       */
+       ret = btrfs_commit_transaction(trans);
+       trans = NULL;
++      mutex_lock(&fs_info->qgroup_ioctl_lock);
+       if (ret)
+               goto out_free_path;
diff --git a/queue-5.4/btrfs-respect-the-max-size-in-the-header-when-activating-swap-file.patch b/queue-5.4/btrfs-respect-the-max-size-in-the-header-when-activating-swap-file.patch
new file mode 100644 (file)
index 0000000..fdd12fb
--- /dev/null
@@ -0,0 +1,65 @@
+From c2f822635df873c510bda6fb7fd1b10b7c31be2d Mon Sep 17 00:00:00 2001
+From: Filipe Manana <fdmanana@suse.com>
+Date: Thu, 16 Dec 2021 15:00:32 +0000
+Subject: btrfs: respect the max size in the header when activating swap file
+
+From: Filipe Manana <fdmanana@suse.com>
+
+commit c2f822635df873c510bda6fb7fd1b10b7c31be2d upstream.
+
+If we extended the size of a swapfile after its header was created (by the
+mkswap utility) and then try to activate it, we will map the entire file
+when activating the swap file, instead of limiting to the max size defined
+in the swap file's header.
+
+Currently test case generic/643 from fstests fails because we do not
+respect that size limit defined in the swap file's header.
+
+So fix this by not mapping file ranges beyond the max size defined in the
+swap header.
+
+This is the same type of bug that iomap used to have, and was fixed in
+commit 36ca7943ac18ae ("mm/swap: consider max pages in
+iomap_swapfile_add_extent").
+
+Fixes: ed46ff3d423780 ("Btrfs: support swap files")
+CC: stable@vger.kernel.org # 5.4+
+Reviewed-and-tested-by: Josef Bacik <josef@toxicpanda.com
+Signed-off-by: Filipe Manana <fdmanana@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/inode.c |   11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+--- a/fs/btrfs/inode.c
++++ b/fs/btrfs/inode.c
+@@ -10808,9 +10808,19 @@ static int btrfs_add_swap_extent(struct
+                                struct btrfs_swap_info *bsi)
+ {
+       unsigned long nr_pages;
++      unsigned long max_pages;
+       u64 first_ppage, first_ppage_reported, next_ppage;
+       int ret;
++      /*
++       * Our swapfile may have had its size extended after the swap header was
++       * written. In that case activating the swapfile should not go beyond
++       * the max size set in the swap header.
++       */
++      if (bsi->nr_pages >= sis->max)
++              return 0;
++
++      max_pages = sis->max - bsi->nr_pages;
+       first_ppage = ALIGN(bsi->block_start, PAGE_SIZE) >> PAGE_SHIFT;
+       next_ppage = ALIGN_DOWN(bsi->block_start + bsi->block_len,
+                               PAGE_SIZE) >> PAGE_SHIFT;
+@@ -10818,6 +10828,7 @@ static int btrfs_add_swap_extent(struct
+       if (first_ppage >= next_ppage)
+               return 0;
+       nr_pages = next_ppage - first_ppage;
++      nr_pages = min(nr_pages, max_pages);
+       first_ppage_reported = first_ppage;
+       if (bsi->start == 0)
diff --git a/queue-5.4/ext4-make-sure-quota-gets-properly-shutdown-on-error.patch b/queue-5.4/ext4-make-sure-quota-gets-properly-shutdown-on-error.patch
new file mode 100644 (file)
index 0000000..e5c20a2
--- /dev/null
@@ -0,0 +1,51 @@
+From 15fc69bbbbbc8c72e5f6cc4e1be0f51283c5448e Mon Sep 17 00:00:00 2001
+From: Jan Kara <jack@suse.cz>
+Date: Thu, 7 Oct 2021 17:53:35 +0200
+Subject: ext4: make sure quota gets properly shutdown on error
+
+From: Jan Kara <jack@suse.cz>
+
+commit 15fc69bbbbbc8c72e5f6cc4e1be0f51283c5448e upstream.
+
+When we hit an error when enabling quotas and setting inode flags, we do
+not properly shutdown quota subsystem despite returning error from
+Q_QUOTAON quotactl. This can lead to some odd situations like kernel
+using quota file while it is still writeable for userspace. Make sure we
+properly cleanup the quota subsystem in case of error.
+
+Signed-off-by: Jan Kara <jack@suse.cz>
+Cc: stable@kernel.org
+Link: https://lore.kernel.org/r/20211007155336.12493-2-jack@suse.cz
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ext4/super.c |   10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -5912,10 +5912,7 @@ static int ext4_quota_on(struct super_bl
+       lockdep_set_quota_inode(path->dentry->d_inode, I_DATA_SEM_QUOTA);
+       err = dquot_quota_on(sb, type, format_id, path);
+-      if (err) {
+-              lockdep_set_quota_inode(path->dentry->d_inode,
+-                                           I_DATA_SEM_NORMAL);
+-      } else {
++      if (!err) {
+               struct inode *inode = d_inode(path->dentry);
+               handle_t *handle;
+@@ -5935,7 +5932,12 @@ static int ext4_quota_on(struct super_bl
+               ext4_journal_stop(handle);
+       unlock_inode:
+               inode_unlock(inode);
++              if (err)
++                      dquot_quota_off(sb, type);
+       }
++      if (err)
++              lockdep_set_quota_inode(path->dentry->d_inode,
++                                           I_DATA_SEM_NORMAL);
+       return err;
+ }
diff --git a/queue-5.4/ext4-make-sure-to-reset-inode-lockdep-class-when-quota-enabling-fails.patch b/queue-5.4/ext4-make-sure-to-reset-inode-lockdep-class-when-quota-enabling-fails.patch
new file mode 100644 (file)
index 0000000..f1f4a9b
--- /dev/null
@@ -0,0 +1,49 @@
+From 4013d47a5307fdb5c13370b5392498b00fedd274 Mon Sep 17 00:00:00 2001
+From: Jan Kara <jack@suse.cz>
+Date: Thu, 7 Oct 2021 17:53:36 +0200
+Subject: ext4: make sure to reset inode lockdep class when quota enabling fails
+
+From: Jan Kara <jack@suse.cz>
+
+commit 4013d47a5307fdb5c13370b5392498b00fedd274 upstream.
+
+When we succeed in enabling some quota type but fail to enable another
+one with quota feature, we correctly disable all enabled quota types.
+However we forget to reset i_data_sem lockdep class. When the inode gets
+freed and reused, it will inherit this lockdep class (i_data_sem is
+initialized only when a slab is created) and thus eventually lockdep
+barfs about possible deadlocks.
+
+Reported-and-tested-by: syzbot+3b6f9218b1301ddda3e2@syzkaller.appspotmail.com
+Signed-off-by: Jan Kara <jack@suse.cz>
+Cc: stable@kernel.org
+Link: https://lore.kernel.org/r/20211007155336.12493-3-jack@suse.cz
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ext4/super.c |   13 ++++++++++++-
+ 1 file changed, 12 insertions(+), 1 deletion(-)
+
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -5998,8 +5998,19 @@ static int ext4_enable_quotas(struct sup
+                                       "Failed to enable quota tracking "
+                                       "(type=%d, err=%d). Please run "
+                                       "e2fsck to fix.", type, err);
+-                              for (type--; type >= 0; type--)
++                              for (type--; type >= 0; type--) {
++                                      struct inode *inode;
++
++                                      inode = sb_dqopt(sb)->files[type];
++                                      if (inode)
++                                              inode = igrab(inode);
+                                       dquot_quota_off(sb, type);
++                                      if (inode) {
++                                              lockdep_set_quota_inode(inode,
++                                                      I_DATA_SEM_NORMAL);
++                                              iput(inode);
++                                      }
++                              }
+                               return err;
+                       }
index 84a5ef7e4fde485cf528a101a0581f3524cc2418..45d0f7741ed1294390cf4f5710f9c5edc94d4f04 100644 (file)
@@ -262,3 +262,8 @@ pci-pci-bridge-emul-properly-mark-reserved-pcie-bits-in-pci-config-space.patch
 pci-pci-bridge-emul-correctly-set-pcie-capabilities.patch
 pci-pci-bridge-emul-set-pci_status_cap_list-for-pcie-device.patch
 xfrm-fix-policy-lookup-for-ipv6-gre-packets.patch
+btrfs-fix-deadlock-between-quota-enable-and-other-quota-operations.patch
+btrfs-check-the-root-node-for-uptodate-before-returning-it.patch
+btrfs-respect-the-max-size-in-the-header-when-activating-swap-file.patch
+ext4-make-sure-to-reset-inode-lockdep-class-when-quota-enabling-fails.patch
+ext4-make-sure-quota-gets-properly-shutdown-on-error.patch