[PATCH 02/15] ACPI: thinkpad-acpi: fix LED handling on older ThinkPads

!MAILaRCHIVE_VOTE_RePLACE
Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]
To: <linux-kernel@...>
Cc: Ivo van Doorn <IvDoorn@...>, Thomas Renninger <trenn@...>, Henrique de Moraes Holschuh <hmh@...>, Adrian Bunk <bunk@...>
Date: Sunday, May 18, 2008 - 2:47 pm

The less tested codepaths for LED handling, used on ThinkPads 570, 600e/x,
770e, 770x, A21e, A2xm/p, T20-22, X20 and maybe a few others, would write
data to kernel memory it had no business touching, for leds number 3 and
above.  If one is lucky, that illegal write would cause an OOPS, but
chances are it would silently corrupt a byte.

The problem was introduced in commit af116101, "ACPI: thinkpad-acpi: add
sysfs led class support to thinkpad leds (v3.2)".

Fix the bug by refactoring the entire code to be far more obvious on what
it wants to do.  Also do some defensive "constification".

Issue reported by Karol Lewandowski <lmctlx@gmail.com> (he's an lucky guy
and got an OOPS instead of silent corruption :-) ).

Root cause of the OOPS identified by Adrian Bunk <bunk@kernel.org>.
Thanks, Adrian!

Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
Tested-by: Karol Lewandowski <lmctlx@gmail.com>
Cc: Adrian Bunk <bunk@kernel.org>
---
 drivers/misc/thinkpad_acpi.c |   55 +++++++++++++++++++++--------------------
 1 files changed, 28 insertions(+), 27 deletions(-)

diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c
index 3c53668..5a560d9 100644
--- a/drivers/misc/thinkpad_acpi.c
+++ b/drivers/misc/thinkpad_acpi.c
@@ -3853,7 +3853,7 @@ static const char const *tpacpi_led_names[TPACPI_LED_NUMLEDS] = {
 	"tpacpi::standby",
 };
 
-static int led_get_status(unsigned int led)
+static int led_get_status(const unsigned int led)
 {
 	int status;
 	enum led_status_t led_s;
@@ -3877,41 +3877,42 @@ static int led_get_status(unsigned int led)
 	/* not reached */
 }
 
-static int led_set_status(unsigned int led, enum led_status_t ledstatus)
+static int led_set_status(const unsigned int led,
+			  const enum led_status_t ledstatus)
 {
 	/* off, on, blink. Index is led_status_t */
-	static const int const led_sled_arg1[] = { 0, 1, 3 };
-	static const int const led_exp_hlbl[] = { 0, 0, 1 };	/* led# * */
-	static const int const led_exp_hlcl[] = { 0, 1, 1 };	/* led# * */
-	static const int const led_led_arg1[] = { 0, 0x80, 0xc0 };
+	static const unsigned int const led_sled_arg1[] = { 0, 1, 3 };
+	static const unsigned int const led_led_arg1[] = { 0, 0x80, 0xc0 };
 
 	int rc = 0;
 
 	switch (led_supported) {
 	case TPACPI_LED_570:
-			/* 570 */
-			led = 1 << led;
-			if (!acpi_evalf(led_handle, NULL, NULL, "vdd",
-					led, led_sled_arg1[ledstatus]))
-				rc = -EIO;
-			break;
+		/* 570 */
+		if (led > 7)
+			return -EINVAL;
+		if (!acpi_evalf(led_handle, NULL, NULL, "vdd",
+				(1 << led), led_sled_arg1[ledstatus]))
+			rc = -EIO;
+		break;
 	case TPACPI_LED_OLD:
-			/* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20 */
-			led = 1 << led;
-			rc = ec_write(TPACPI_LED_EC_HLMS, led);
-			if (rc >= 0)
-				rc = ec_write(TPACPI_LED_EC_HLBL,
-					      led * led_exp_hlbl[ledstatus]);
-			if (rc >= 0)
-				rc = ec_write(TPACPI_LED_EC_HLCL,
-					      led * led_exp_hlcl[ledstatus]);
-			break;
+		/* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20 */
+		if (led > 7)
+			return -EINVAL;
+		rc = ec_write(TPACPI_LED_EC_HLMS, (1 << led));
+		if (rc >= 0)
+			rc = ec_write(TPACPI_LED_EC_HLBL,
+				      (ledstatus == TPACPI_LED_BLINK) << led);
+		if (rc >= 0)
+			rc = ec_write(TPACPI_LED_EC_HLCL,
+				      (ledstatus != TPACPI_LED_OFF) << led);
+		break;
 	case TPACPI_LED_NEW:
-			/* all others */
-			if (!acpi_evalf(led_handle, NULL, NULL, "vdd",
-					led, led_led_arg1[ledstatus]))
-				rc = -EIO;
-			break;
+		/* all others */
+		if (!acpi_evalf(led_handle, NULL, NULL, "vdd",
+				led, led_led_arg1[ledstatus]))
+			rc = -EIO;
+		break;
 	default:
 		rc = -ENXIO;
 	}
-- 
1.5.5.1

--
Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]

Messages in current thread:
[RFC] rfkill class rework, Henrique de Moraes Holschuh..., (Sun May 18, 2:47 pm)
[PATCH 08/15] rfkill: add read-write rfkill switch support, Henrique de Moraes Holschuh..., (Sun May 18, 2:47 pm)
[PATCH 15/15] rfkill: document rw rfkill switches and clarif..., Henrique de Moraes Holschuh..., (Sun May 18, 2:48 pm)
Re: [PATCH 15/15] rfkill: document rw rfkill switches and cl..., Henrique de Moraes Holschuh..., (Tue May 20, 11:54 am)
Re: [PATCH 15/15] rfkill: document rw rfkill switches and cl..., Henrique de Moraes Holschuh..., (Tue May 20, 9:44 pm)
[PATCH 15/15] rfkill: document rw rfkill switches and clarif..., Henrique de Moraes Holschuh..., (Wed May 28, 8:45 pm)
Re: [PATCH 15/15] rfkill: document rw rfkill switches and cl..., Henrique de Moraes Holschuh..., (Thu May 29, 12:26 pm)
Re: [PATCH 15/15] rfkill: document rw rfkill switches and cl..., Henrique de Moraes Holschuh..., (Thu May 29, 1:22 pm)
Re: [PATCH 15/15] rfkill: document rw rfkill switches and cl..., Henrique de Moraes Holschuh..., (Tue Jun 3, 11:11 pm)
Re: [PATCH 15/15] rfkill: document rw rfkill switches and cl..., Henrique de Moraes Holschuh..., (Thu May 29, 1:46 pm)
Re: [PATCH 15/15] rfkill: document rw rfkill switches and cl..., Henrique de Moraes Holschuh..., (Thu May 29, 5:16 pm)
[PATCH] Input: rename SW_RADIO to SW_RFKILL_ALL (v2), Henrique de Moraes Holschuh..., (Thu May 29, 5:25 pm)
Re: [PATCH 15/15] rfkill: document rw rfkill switches and cl..., Henrique de Moraes Holschuh..., (Mon May 19, 6:04 pm)
[PATCH 14/15] rfkill: do not allow userspace to override ALL..., Henrique de Moraes Holschuh..., (Sun May 18, 2:48 pm)
Re: [PATCH 14/15] rfkill: do not allow userspace to override..., Henrique de Moraes Holschuh..., (Thu May 22, 4:51 pm)
Re: [PATCH 14/15] rfkill: do not allow userspace to override..., Henrique de Moraes Holschuh..., (Tue May 27, 10:08 am)
Re: [PATCH 14/15] rfkill: do not allow userspace to override..., Henrique de Moraes Holschuh..., (Tue May 27, 1:41 pm)
[PATCH 11/15] rfkill: add notifier chains support, Henrique de Moraes Holschuh..., (Sun May 18, 2:48 pm)
Re: [PATCH 11/15] rfkill: add notifier chains support, Ivo van Doorn, (Tue May 20, 6:09 am)
Re: [PATCH 11/15] rfkill: add notifier chains support, Thomas Renninger, (Mon May 19, 4:44 am)
Re: [PATCH 11/15] rfkill: add notifier chains support, Henrique de Moraes Holschuh..., (Mon May 19, 9:10 am)
[PATCH 10/15] rfkill: rework suspend and resume handlers, Henrique de Moraes Holschuh..., (Sun May 18, 2:48 pm)
[PATCH 09/15] rfkill: add the WWAN radio type, Henrique de Moraes Holschuh..., (Sun May 18, 2:47 pm)
Re: [PATCH 09/15] rfkill: add the WWAN radio type, Ivo van Doorn, (Tue May 20, 6:08 am)
Re: [PATCH 09/15] rfkill: add the WWAN radio type, Henrique de Moraes Holschuh..., (Tue May 20, 9:12 pm)
Re: [PATCH 09/15] rfkill: add the WWAN radio type, Inaky Perez-Gonzalez, (Tue May 20, 11:35 pm)
Re: [PATCH 09/15] rfkill: add the WWAN radio type, Henrique de Moraes Holschuh..., (Tue May 20, 11:42 pm)
Re: [PATCH 09/15] rfkill: add the WWAN radio type, Inaky Perez-Gonzalez, (Wed May 21, 2:48 am)
Re: [PATCH 09/15] rfkill: add the WWAN radio type, Henrique de Moraes Holschuh..., (Wed May 21, 10:07 am)
[PATCH 13/15] rfkill: add uevent notifications, Henrique de Moraes Holschuh..., (Sun May 18, 2:48 pm)
Re: [PATCH 13/15] rfkill: add uevent notifications, Ivo van Doorn, (Tue May 20, 6:09 am)
[PATCH 12/15] rfkill: add type string helper, Henrique de Moraes Holschuh..., (Sun May 18, 2:48 pm)
Re: [PATCH 12/15] rfkill: add type string helper, Ivo van Doorn, (Tue May 20, 6:09 am)
[PATCH 07/15] rfkill: add parameter to disable radios by def..., Henrique de Moraes Holschuh..., (Sun May 18, 2:47 pm)
[PATCH 06/15] rfkill: handle SW_RFKILL_ALL events, Henrique de Moraes Holschuh..., (Sun May 18, 2:47 pm)
Re: [PATCH 06/15] rfkill: handle SW_RFKILL_ALL events, Ivo van Doorn, (Tue May 20, 6:08 am)
[PATCH 01/15] ACPI: thinkpad-acpi: fix initialization error ..., Henrique de Moraes Holschuh..., (Sun May 18, 2:47 pm)
[PATCH 05/15] rfkill: fix minor typo in kernel doc, Henrique de Moraes Holschuh..., (Sun May 18, 2:47 pm)
Re: [PATCH 05/15] rfkill: fix minor typo in kernel doc, Ivo van Doorn, (Tue May 20, 6:08 am)
[PATCH 04/15] rfkill: clarify meaning of rfkill states, Henrique de Moraes Holschuh..., (Sun May 18, 2:47 pm)
[PATCH 03/15] Input: rename SW_RADIO to SW_RFKILL_ALL (v2), Henrique de Moraes Holschuh..., (Sun May 18, 2:47 pm)
[PATCH 02/15] ACPI: thinkpad-acpi: fix LED handling on older..., Henrique de Moraes Holschuh..., (Sun May 18, 2:47 pm)