Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 552e1f26 authored by Oliver Neukum's avatar Oliver Neukum Committed by Greg Kroah-Hartman
Browse files

USB: appledisplay: fix race between reading and writing from the device



The workqueue handler may call appledisplay_bl_get_brightness() while
user space calls appledisplay_bl_update_status(). As they share a
buffer that must not happen. Use a mutex for mutual exclusion.

Signed-off-by: default avatarOliver Neukum <oneukum@suse.de>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent d846b765
Loading
Loading
Loading
Loading
+10 −3
Original line number Diff line number Diff line
@@ -81,6 +81,7 @@ struct appledisplay {
	struct delayed_work work;
	int button_pressed;
	spinlock_t lock;
	struct mutex sysfslock;		/* concurrent read and write */
};

static atomic_t count_displays = ATOMIC_INIT(0);
@@ -144,6 +145,7 @@ static int appledisplay_bl_update_status(struct backlight_device *bd)
	struct appledisplay *pdata = bl_get_data(bd);
	int retval;

	mutex_lock(&pdata->sysfslock);
	pdata->msgdata[0] = 0x10;
	pdata->msgdata[1] = bd->props.brightness;

@@ -156,6 +158,7 @@ static int appledisplay_bl_update_status(struct backlight_device *bd)
		0,
		pdata->msgdata, 2,
		ACD_USB_TIMEOUT);
	mutex_unlock(&pdata->sysfslock);
	
	return retval;
}
@@ -163,8 +166,9 @@ static int appledisplay_bl_update_status(struct backlight_device *bd)
static int appledisplay_bl_get_brightness(struct backlight_device *bd)
{
	struct appledisplay *pdata = bl_get_data(bd);
	int retval;
	int retval, brightness;

	mutex_lock(&pdata->sysfslock);
	retval = usb_control_msg(
		pdata->udev,
		usb_rcvctrlpipe(pdata->udev, 0),
@@ -174,11 +178,13 @@ static int appledisplay_bl_get_brightness(struct backlight_device *bd)
		0,
		pdata->msgdata, 2,
		ACD_USB_TIMEOUT);
	brightness = pdata->msgdata[1];
	mutex_unlock(&pdata->sysfslock);

	if (retval < 0)
		return retval;
	else
		return pdata->msgdata[1];
		return brightness;
}

static const struct backlight_ops appledisplay_bl_data = {
@@ -241,6 +247,7 @@ static int appledisplay_probe(struct usb_interface *iface,

	spin_lock_init(&pdata->lock);
	INIT_DELAYED_WORK(&pdata->work, appledisplay_work);
	mutex_init(&pdata->sysfslock);

	/* Allocate buffer for control messages */
	pdata->msgdata = kmalloc(ACD_MSG_BUFFER_LEN, GFP_KERNEL);