Skip to content

Commit 5610bcf

Browse files
V4belhdeller
authored andcommitted
fbdev: smscufx: Fix use-after-free in ufx_ops_open()
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>
1 parent e69dade commit 5610bcf

File tree

1 file changed

+13
-1
lines changed

1 file changed

+13
-1
lines changed

drivers/video/fbdev/smscufx.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,8 @@ static int ufx_submit_urb(struct ufx_data *dev, struct urb * urb, size_t len);
137137
static int ufx_alloc_urb_list(struct ufx_data *dev, int count, size_t size);
138138
static void ufx_free_urb_list(struct ufx_data *dev);
139139

140+
static DEFINE_MUTEX(disconnect_mutex);
141+
140142
/* reads a control register */
141143
static int ufx_reg_read(struct ufx_data *dev, u32 index, u32 *data)
142144
{
@@ -1071,9 +1073,13 @@ static int ufx_ops_open(struct fb_info *info, int user)
10711073
if (user == 0 && !console)
10721074
return -EBUSY;
10731075

1076+
mutex_lock(&disconnect_mutex);
1077+
10741078
/* If the USB device is gone, we don't accept new opens */
1075-
if (dev->virtualized)
1079+
if (dev->virtualized) {
1080+
mutex_unlock(&disconnect_mutex);
10761081
return -ENODEV;
1082+
}
10771083

10781084
dev->fb_count++;
10791085

@@ -1097,6 +1103,8 @@ static int ufx_ops_open(struct fb_info *info, int user)
10971103
pr_debug("open /dev/fb%d user=%d fb_info=%p count=%d",
10981104
info->node, user, info, dev->fb_count);
10991105

1106+
mutex_unlock(&disconnect_mutex);
1107+
11001108
return 0;
11011109
}
11021110

@@ -1741,6 +1749,8 @@ static void ufx_usb_disconnect(struct usb_interface *interface)
17411749
{
17421750
struct ufx_data *dev;
17431751

1752+
mutex_lock(&disconnect_mutex);
1753+
17441754
dev = usb_get_intfdata(interface);
17451755

17461756
pr_debug("USB disconnect starting\n");
@@ -1761,6 +1771,8 @@ static void ufx_usb_disconnect(struct usb_interface *interface)
17611771
kref_put(&dev->kref, ufx_free);
17621772

17631773
/* consider ufx_data freed */
1774+
1775+
mutex_unlock(&disconnect_mutex);
17641776
}
17651777

17661778
static struct usb_driver ufx_driver = {

0 commit comments

Comments
 (0)