From 48cb49250b7fe208bdb71629a18e536cb431f6f2 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 18 Feb 2024 10:41:26 +0100 Subject: [PATCH] 5.15-stable patches added patches: btrfs-do-not-assert-if-the-newly-created-subvolume-already-got-read.patch btrfs-forbid-creating-subvol-qgroups.patch btrfs-forbid-deleting-live-subvol-qgroup.patch btrfs-send-return-eopnotsupp-on-unknown-flags.patch --- ...y-created-subvolume-already-got-read.patch | 92 +++++++++++++++++++ ...btrfs-forbid-creating-subvol-qgroups.patch | 40 ++++++++ ...s-forbid-deleting-live-subvol-qgroup.patch | 54 +++++++++++ ...d-return-eopnotsupp-on-unknown-flags.patch | 35 +++++++ queue-5.15/series | 4 + 5 files changed, 225 insertions(+) create mode 100644 queue-5.15/btrfs-do-not-assert-if-the-newly-created-subvolume-already-got-read.patch create mode 100644 queue-5.15/btrfs-forbid-creating-subvol-qgroups.patch create mode 100644 queue-5.15/btrfs-forbid-deleting-live-subvol-qgroup.patch create mode 100644 queue-5.15/btrfs-send-return-eopnotsupp-on-unknown-flags.patch diff --git a/queue-5.15/btrfs-do-not-assert-if-the-newly-created-subvolume-already-got-read.patch b/queue-5.15/btrfs-do-not-assert-if-the-newly-created-subvolume-already-got-read.patch new file mode 100644 index 00000000000..19e4b9d1528 --- /dev/null +++ b/queue-5.15/btrfs-do-not-assert-if-the-newly-created-subvolume-already-got-read.patch @@ -0,0 +1,92 @@ +From e03ee2fe873eb68c1f9ba5112fee70303ebf9dfb Mon Sep 17 00:00:00 2001 +From: Qu Wenruo +Date: Sat, 20 Jan 2024 19:41:28 +1030 +Subject: btrfs: do not ASSERT() if the newly created subvolume already got read + +From: Qu Wenruo + +commit e03ee2fe873eb68c1f9ba5112fee70303ebf9dfb upstream. + +[BUG] +There is a syzbot crash, triggered by the ASSERT() during subvolume +creation: + + assertion failed: !anon_dev, in fs/btrfs/disk-io.c:1319 + ------------[ cut here ]------------ + kernel BUG at fs/btrfs/disk-io.c:1319! + invalid opcode: 0000 [#1] PREEMPT SMP KASAN + RIP: 0010:btrfs_get_root_ref.part.0+0x9aa/0xa60 + + btrfs_get_new_fs_root+0xd3/0xf0 + create_subvol+0xd02/0x1650 + btrfs_mksubvol+0xe95/0x12b0 + __btrfs_ioctl_snap_create+0x2f9/0x4f0 + btrfs_ioctl_snap_create+0x16b/0x200 + btrfs_ioctl+0x35f0/0x5cf0 + __x64_sys_ioctl+0x19d/0x210 + do_syscall_64+0x3f/0xe0 + entry_SYSCALL_64_after_hwframe+0x63/0x6b + ---[ end trace 0000000000000000 ]--- + +[CAUSE] +During create_subvol(), after inserting root item for the newly created +subvolume, we would trigger btrfs_get_new_fs_root() to get the +btrfs_root of that subvolume. + +The idea here is, we have preallocated an anonymous device number for +the subvolume, thus we can assign it to the new subvolume. + +But there is really nothing preventing things like backref walk to read +the new subvolume. +If that happens before we call btrfs_get_new_fs_root(), the subvolume +would be read out, with a new anonymous device number assigned already. + +In that case, we would trigger ASSERT(), as we really expect no one to +read out that subvolume (which is not yet accessible from the fs). +But things like backref walk is still possible to trigger the read on +the subvolume. + +Thus our assumption on the ASSERT() is not correct in the first place. + +[FIX] +Fix it by removing the ASSERT(), and just free the @anon_dev, reset it +to 0, and continue. + +If the subvolume tree is read out by something else, it should have +already get a new anon_dev assigned thus we only need to free the +preallocated one. + +Reported-by: Chenyuan Yang +Fixes: 2dfb1e43f57d ("btrfs: preallocate anon block device at first phase of snapshot creation") +CC: stable@vger.kernel.org # 5.15+ +Reviewed-by: Filipe Manana +Signed-off-by: Qu Wenruo +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Greg Kroah-Hartman +--- + fs/btrfs/disk-io.c | 13 +++++++++++-- + 1 file changed, 11 insertions(+), 2 deletions(-) + +--- a/fs/btrfs/disk-io.c ++++ b/fs/btrfs/disk-io.c +@@ -1619,8 +1619,17 @@ static struct btrfs_root *btrfs_get_root + again: + root = btrfs_lookup_fs_root(fs_info, objectid); + if (root) { +- /* Shouldn't get preallocated anon_dev for cached roots */ +- ASSERT(!anon_dev); ++ /* ++ * Some other caller may have read out the newly inserted ++ * subvolume already (for things like backref walk etc). Not ++ * that common but still possible. In that case, we just need ++ * to free the anon_dev. ++ */ ++ if (unlikely(anon_dev)) { ++ free_anon_bdev(anon_dev); ++ anon_dev = 0; ++ } ++ + if (check_ref && btrfs_root_refs(&root->root_item) == 0) { + btrfs_put_root(root); + return ERR_PTR(-ENOENT); diff --git a/queue-5.15/btrfs-forbid-creating-subvol-qgroups.patch b/queue-5.15/btrfs-forbid-creating-subvol-qgroups.patch new file mode 100644 index 00000000000..1fa709299bc --- /dev/null +++ b/queue-5.15/btrfs-forbid-creating-subvol-qgroups.patch @@ -0,0 +1,40 @@ +From 0c309d66dacddf8ce939b891d9ead4a8e21ad6f0 Mon Sep 17 00:00:00 2001 +From: Boris Burkov +Date: Wed, 10 Jan 2024 17:51:26 -0800 +Subject: btrfs: forbid creating subvol qgroups + +From: Boris Burkov + +commit 0c309d66dacddf8ce939b891d9ead4a8e21ad6f0 upstream. + +Creating a qgroup 0/subvolid leads to various races and it isn't +helpful, because you can't specify a subvol id when creating a subvol, +so you can't be sure it will be the right one. Any requirements on the +automatic subvol can be gratified by using a higher level qgroup and the +inheritance parameters of subvol creation. + +Fixes: cecbb533b5fc ("btrfs: record simple quota deltas in delayed refs") +CC: stable@vger.kernel.org # 4.14+ +Reviewed-by: Qu Wenruo +Signed-off-by: Boris Burkov +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Greg Kroah-Hartman +--- + fs/btrfs/ioctl.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/fs/btrfs/ioctl.c ++++ b/fs/btrfs/ioctl.c +@@ -4338,6 +4338,11 @@ static long btrfs_ioctl_qgroup_create(st + goto out; + } + ++ if (sa->create && is_fstree(sa->qgroupid)) { ++ ret = -EINVAL; ++ goto out; ++ } ++ + trans = btrfs_join_transaction(root); + if (IS_ERR(trans)) { + ret = PTR_ERR(trans); diff --git a/queue-5.15/btrfs-forbid-deleting-live-subvol-qgroup.patch b/queue-5.15/btrfs-forbid-deleting-live-subvol-qgroup.patch new file mode 100644 index 00000000000..25bba899e49 --- /dev/null +++ b/queue-5.15/btrfs-forbid-deleting-live-subvol-qgroup.patch @@ -0,0 +1,54 @@ +From a8df35619948bd8363d330c20a90c9a7fbff28c0 Mon Sep 17 00:00:00 2001 +From: Boris Burkov +Date: Wed, 10 Jan 2024 17:30:00 -0800 +Subject: btrfs: forbid deleting live subvol qgroup + +From: Boris Burkov + +commit a8df35619948bd8363d330c20a90c9a7fbff28c0 upstream. + +If a subvolume still exists, forbid deleting its qgroup 0/subvolid. +This behavior generally leads to incorrect behavior in squotas and +doesn't have a legitimate purpose. + +Fixes: cecbb533b5fc ("btrfs: record simple quota deltas in delayed refs") +CC: stable@vger.kernel.org # 5.4+ +Reviewed-by: Qu Wenruo +Signed-off-by: Boris Burkov +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Greg Kroah-Hartman +--- + fs/btrfs/qgroup.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +--- a/fs/btrfs/qgroup.c ++++ b/fs/btrfs/qgroup.c +@@ -1608,6 +1608,15 @@ out: + return ret; + } + ++static bool qgroup_has_usage(struct btrfs_qgroup *qgroup) ++{ ++ return (qgroup->rfer > 0 || qgroup->rfer_cmpr > 0 || ++ qgroup->excl > 0 || qgroup->excl_cmpr > 0 || ++ qgroup->rsv.values[BTRFS_QGROUP_RSV_DATA] > 0 || ++ qgroup->rsv.values[BTRFS_QGROUP_RSV_META_PREALLOC] > 0 || ++ qgroup->rsv.values[BTRFS_QGROUP_RSV_META_PERTRANS] > 0); ++} ++ + int btrfs_remove_qgroup(struct btrfs_trans_handle *trans, u64 qgroupid) + { + struct btrfs_fs_info *fs_info = trans->fs_info; +@@ -1627,6 +1636,11 @@ int btrfs_remove_qgroup(struct btrfs_tra + goto out; + } + ++ if (is_fstree(qgroupid) && qgroup_has_usage(qgroup)) { ++ ret = -EBUSY; ++ goto out; ++ } ++ + /* Check if there are no children of this qgroup */ + if (!list_empty(&qgroup->members)) { + ret = -EBUSY; diff --git a/queue-5.15/btrfs-send-return-eopnotsupp-on-unknown-flags.patch b/queue-5.15/btrfs-send-return-eopnotsupp-on-unknown-flags.patch new file mode 100644 index 00000000000..f7987f9a2e3 --- /dev/null +++ b/queue-5.15/btrfs-send-return-eopnotsupp-on-unknown-flags.patch @@ -0,0 +1,35 @@ +From f884a9f9e59206a2d41f265e7e403f080d10b493 Mon Sep 17 00:00:00 2001 +From: David Sterba +Date: Wed, 10 Jan 2024 17:48:44 +0100 +Subject: btrfs: send: return EOPNOTSUPP on unknown flags + +From: David Sterba + +commit f884a9f9e59206a2d41f265e7e403f080d10b493 upstream. + +When some ioctl flags are checked we return EOPNOTSUPP, like for +BTRFS_SCRUB_SUPPORTED_FLAGS, BTRFS_SUBVOL_CREATE_ARGS_MASK or fallocate +modes. The EINVAL is supposed to be for a supported but invalid +values or combination of options. Fix that when checking send flags so +it's consistent with the rest. + +CC: stable@vger.kernel.org # 4.14+ +Link: https://lore.kernel.org/linux-btrfs/CAL3q7H5rryOLzp3EKq8RTbjMHMHeaJubfpsVLF6H4qJnKCUR1w@mail.gmail.com/ +Reviewed-by: Filipe Manana +Signed-off-by: David Sterba +Signed-off-by: Greg Kroah-Hartman +--- + fs/btrfs/send.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/btrfs/send.c ++++ b/fs/btrfs/send.c +@@ -7558,7 +7558,7 @@ long btrfs_ioctl_send(struct file *mnt_f + } + + if (arg->flags & ~BTRFS_SEND_FLAG_MASK) { +- ret = -EINVAL; ++ ret = -EOPNOTSUPP; + goto out; + } + diff --git a/queue-5.15/series b/queue-5.15/series index afd99c15699..acb65d93c4a 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -350,3 +350,7 @@ clocksource-skip-watchdog-check-for-large-watchdog-intervals.patch net-stmmac-xgmac-use-define-for-string-constants.patch net-stmmac-xgmac-fix-a-typo-of-register-name-in-dpp-safety-handling.patch netfilter-nft_set_rbtree-skip-end-interval-element-from-gc.patch +btrfs-forbid-creating-subvol-qgroups.patch +btrfs-do-not-assert-if-the-newly-created-subvolume-already-got-read.patch +btrfs-forbid-deleting-live-subvol-qgroup.patch +btrfs-send-return-eopnotsupp-on-unknown-flags.patch -- 2.47.3