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: Oliver Neukum <oneukum@suse.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
d846b7650d
commit
552e1f2679
|
@ -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,15 +158,17 @@ static int appledisplay_bl_update_status(struct backlight_device *bd)
|
|||
0,
|
||||
pdata->msgdata, 2,
|
||||
ACD_USB_TIMEOUT);
|
||||
|
||||
mutex_unlock(&pdata->sysfslock);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
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);
|
||||
|
|
Loading…
Reference in a new issue