--- /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
+@@ -140,6 +140,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)
+ {
+@@ -1073,9 +1075,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++;
+
+@@ -1100,6 +1106,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;
+ }
+
+@@ -1762,6 +1770,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");
+@@ -1782,6 +1792,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 = {