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

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
...@@ -81,6 +81,7 @@ struct appledisplay { ...@@ -81,6 +81,7 @@ struct appledisplay {
struct delayed_work work; struct delayed_work work;
int button_pressed; int button_pressed;
spinlock_t lock; spinlock_t lock;
struct mutex sysfslock; /* concurrent read and write */
}; };
static atomic_t count_displays = ATOMIC_INIT(0); static atomic_t count_displays = ATOMIC_INIT(0);
...@@ -144,6 +145,7 @@ static int appledisplay_bl_update_status(struct backlight_device *bd) ...@@ -144,6 +145,7 @@ static int appledisplay_bl_update_status(struct backlight_device *bd)
struct appledisplay *pdata = bl_get_data(bd); struct appledisplay *pdata = bl_get_data(bd);
int retval; int retval;
mutex_lock(&pdata->sysfslock);
pdata->msgdata[0] = 0x10; pdata->msgdata[0] = 0x10;
pdata->msgdata[1] = bd->props.brightness; pdata->msgdata[1] = bd->props.brightness;
...@@ -156,6 +158,7 @@ static int appledisplay_bl_update_status(struct backlight_device *bd) ...@@ -156,6 +158,7 @@ static int appledisplay_bl_update_status(struct backlight_device *bd)
0, 0,
pdata->msgdata, 2, pdata->msgdata, 2,
ACD_USB_TIMEOUT); ACD_USB_TIMEOUT);
mutex_unlock(&pdata->sysfslock);
return retval; return retval;
} }
...@@ -163,8 +166,9 @@ static int appledisplay_bl_update_status(struct backlight_device *bd) ...@@ -163,8 +166,9 @@ static int appledisplay_bl_update_status(struct backlight_device *bd)
static int appledisplay_bl_get_brightness(struct backlight_device *bd) static int appledisplay_bl_get_brightness(struct backlight_device *bd)
{ {
struct appledisplay *pdata = bl_get_data(bd); struct appledisplay *pdata = bl_get_data(bd);
int retval; int retval, brightness;
mutex_lock(&pdata->sysfslock);
retval = usb_control_msg( retval = usb_control_msg(
pdata->udev, pdata->udev,
usb_rcvctrlpipe(pdata->udev, 0), usb_rcvctrlpipe(pdata->udev, 0),
...@@ -174,11 +178,13 @@ static int appledisplay_bl_get_brightness(struct backlight_device *bd) ...@@ -174,11 +178,13 @@ static int appledisplay_bl_get_brightness(struct backlight_device *bd)
0, 0,
pdata->msgdata, 2, pdata->msgdata, 2,
ACD_USB_TIMEOUT); ACD_USB_TIMEOUT);
brightness = pdata->msgdata[1];
mutex_unlock(&pdata->sysfslock);
if (retval < 0) if (retval < 0)
return retval; return retval;
else else
return pdata->msgdata[1]; return brightness;
} }
static const struct backlight_ops appledisplay_bl_data = { static const struct backlight_ops appledisplay_bl_data = {
...@@ -241,6 +247,7 @@ static int appledisplay_probe(struct usb_interface *iface, ...@@ -241,6 +247,7 @@ static int appledisplay_probe(struct usb_interface *iface,
spin_lock_init(&pdata->lock); spin_lock_init(&pdata->lock);
INIT_DELAYED_WORK(&pdata->work, appledisplay_work); INIT_DELAYED_WORK(&pdata->work, appledisplay_work);
mutex_init(&pdata->sysfslock);
/* Allocate buffer for control messages */ /* Allocate buffer for control messages */
pdata->msgdata = kmalloc(ACD_MSG_BUFFER_LEN, GFP_KERNEL); pdata->msgdata = kmalloc(ACD_MSG_BUFFER_LEN, GFP_KERNEL);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment