]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 16 Oct 2022 12:31:06 +0000 (14:31 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 16 Oct 2022 12:31:06 +0000 (14:31 +0200)
added patches:
btrfs-fix-race-between-quota-enable-and-quota-rescan-ioctl.patch
fbdev-smscufx-fix-use-after-free-in-ufx_ops_open.patch

queue-5.4/btrfs-fix-race-between-quota-enable-and-quota-rescan-ioctl.patch [new file with mode: 0644]
queue-5.4/fbdev-smscufx-fix-use-after-free-in-ufx_ops_open.patch [new file with mode: 0644]
queue-5.4/series

diff --git a/queue-5.4/btrfs-fix-race-between-quota-enable-and-quota-rescan-ioctl.patch b/queue-5.4/btrfs-fix-race-between-quota-enable-and-quota-rescan-ioctl.patch
new file mode 100644 (file)
index 0000000..5dffadd
--- /dev/null
@@ -0,0 +1,60 @@
+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
+@@ -1075,6 +1075,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-5.4/fbdev-smscufx-fix-use-after-free-in-ufx_ops_open.patch b/queue-5.4/fbdev-smscufx-fix-use-after-free-in-ufx_ops_open.patch
new file mode 100644 (file)
index 0000000..f2c74f1
--- /dev/null
@@ -0,0 +1,79 @@
+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)
+ {
+@@ -1070,9 +1072,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++;
+@@ -1096,6 +1102,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 = {
index c3db2a0c37e05285edada364e3c1849067c615c2..e695a46550779f2c314dff99ca0862738c053cf4 100644 (file)
@@ -31,3 +31,5 @@ riscv-pass-mno-relax-only-on-lld-15.0.0.patch
 um-cpuinfo-fix-a-warning-for-config_cpumask_offstack.patch
 pci-sanitise-firmware-bar-assignments-behind-a-pci-pci-bridge.patch
 powerpc-boot-explicitly-disable-usage-of-spe-instructions.patch
+fbdev-smscufx-fix-use-after-free-in-ufx_ops_open.patch
+btrfs-fix-race-between-quota-enable-and-quota-rescan-ioctl.patch