Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

leds: trigger: ledtrig-backlight: Fix invalid memory access in fb_event notification callback

fb_notifier_callback is called on any event fired by
fb_notifier_call_chain. Events may, or may not contain some data
(fb_event.data). In case of FB_EVENT_BLANK fb_event.data contains a
pointer to an integer holdingthe blank state. The Problem is, that in
ledtrig-backlight.c - fb_notifier_callback the pointer to blank state
is dereferenced BEFORE the event-type is checked.

Obviously this leads to problems with other events than FB_EVENT_BLANK,
where fb_event.data is undefined or NULL. It seems, that this problem
existed ever since the driver was added.

Like in drivers/video/backlight/backlight.c line 43 I would suggest to
return immediately on events other than FB_EVENT_BLANK.

Signed-off-by: Manfred Schlaegl <manfred.schlaegl@gmx.at>
Signed-off-by: Bryan Wu <cooloney@gmail.com>

authored by

Manfred Schlaegl and committed by
Bryan Wu
c945cbcf 8a6acd64

+16 -14
+16 -14
drivers/leds/trigger/ledtrig-backlight.c
··· 36 36 struct bl_trig_notifier, notifier); 37 37 struct led_classdev *led = n->led; 38 38 struct fb_event *fb_event = data; 39 - int *blank = fb_event->data; 40 - int new_status = *blank ? BLANK : UNBLANK; 39 + int *blank; 40 + int new_status; 41 41 42 - switch (event) { 43 - case FB_EVENT_BLANK: 44 - if (new_status == n->old_status) 45 - break; 42 + /* If we aren't interested in this event, skip it immediately ... */ 43 + if (event != FB_EVENT_BLANK) 44 + return 0; 46 45 47 - if ((n->old_status == UNBLANK) ^ n->invert) { 48 - n->brightness = led->brightness; 49 - __led_set_brightness(led, LED_OFF); 50 - } else { 51 - __led_set_brightness(led, n->brightness); 52 - } 46 + blank = fb_event->data; 47 + new_status = *blank ? BLANK : UNBLANK; 53 48 54 - n->old_status = new_status; 49 + if (new_status == n->old_status) 50 + return 0; 55 51 56 - break; 52 + if ((n->old_status == UNBLANK) ^ n->invert) { 53 + n->brightness = led->brightness; 54 + __led_set_brightness(led, LED_OFF); 55 + } else { 56 + __led_set_brightness(led, n->brightness); 57 57 } 58 + 59 + n->old_status = new_status; 58 60 59 61 return 0; 60 62 }