From: Nick Desaulniers <ndesaulniers@google.com>
To: linux@roeck-us.net
Cc: clang-built-linux@googlegroups.com, jdelvare@suse.com,
"Nick Desaulniers" <ndesaulniers@google.com>,
"Tomasz Paweł Gajc" <tpgxyz@gmail.com>,
"Nathan Chancellor" <natechancellor@gmail.com>,
"Henrik Rydberg" <rydberg@bitmath.org>,
linux-hwmon@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH v2] hwmon: (applesmc) fix UB and udelay overflow
Date: Tue, 24 Sep 2019 10:47:28 -0700 [thread overview]
Message-ID: <20190924174728.201464-1-ndesaulniers@google.com> (raw)
In-Reply-To: <CAKwvOd=GVdHhsdHOMpuhEKkWMssW37keqX5c59+6fiEgLs+Q1g@mail.gmail.com>
Fixes the following 2 issues in the driver:
1. Left shifting a signed integer is undefined behavior. Unsigned
integral types should be used for bitwise operations.
2. The delay scales from 0x0010 to 0x20000 by powers of 2, but udelay
will result in a linkage failure when given a constant that's greater
than 20000 (0x4E20). Agressive loop unrolling can fully unroll the
loop, resulting in later iterations overflowing the call to udelay.
2 is fixed via splitting the loop in two, iterating the first up to the
point where udelay would overflow, then switching to mdelay, as
suggested in Documentation/timers/timers-howto.rst.
Reported-by: Tomasz Paweł Gajc <tpgxyz@gmail.com>
Link: https://github.com/ClangBuiltLinux/linux/issues/678
Debugged-by: Nathan Chancellor <natechancellor@gmail.com>
Signed-off-by: Nick Desaulniers <ndesaulniers@google.com>
---
Changes V1 -> V2:
* The first loop in send_byte() needs to break out on the same condition
now. Technically, the loop condition could even be removed. The diff
looks funny because of the duplicated logic between existing and newly
added for loops.
drivers/hwmon/applesmc.c | 35 +++++++++++++++++++++++++++++++----
1 file changed, 31 insertions(+), 4 deletions(-)
diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c
index 183ff3d25129..c76adb504dff 100644
--- a/drivers/hwmon/applesmc.c
+++ b/drivers/hwmon/applesmc.c
@@ -46,6 +46,7 @@
#define APPLESMC_MIN_WAIT 0x0010
#define APPLESMC_RETRY_WAIT 0x0100
#define APPLESMC_MAX_WAIT 0x20000
+#define APPLESMC_UDELAY_MAX 20000
#define APPLESMC_READ_CMD 0x10
#define APPLESMC_WRITE_CMD 0x11
@@ -157,14 +158,23 @@ static struct workqueue_struct *applesmc_led_wq;
static int wait_read(void)
{
u8 status;
- int us;
- for (us = APPLESMC_MIN_WAIT; us < APPLESMC_MAX_WAIT; us <<= 1) {
+ unsigned int us;
+
+ for (us = APPLESMC_MIN_WAIT; us < APPLESMC_UDELAY_MAX; us <<= 1) {
udelay(us);
status = inb(APPLESMC_CMD_PORT);
/* read: wait for smc to settle */
if (status & 0x01)
return 0;
}
+ /* switch to mdelay for longer sleeps */
+ for (; us < APPLESMC_MAX_WAIT; us <<= 1) {
+ mdelay(us);
+ status = inb(APPLESMC_CMD_PORT);
+ /* read: wait for smc to settle */
+ if (status & 0x01)
+ return 0;
+ }
pr_warn("wait_read() fail: 0x%02x\n", status);
return -EIO;
@@ -177,10 +187,10 @@ static int wait_read(void)
static int send_byte(u8 cmd, u16 port)
{
u8 status;
- int us;
+ unsigned int us;
outb(cmd, port);
- for (us = APPLESMC_MIN_WAIT; us < APPLESMC_MAX_WAIT; us <<= 1) {
+ for (us = APPLESMC_MIN_WAIT; us < APPLESMC_UDELAY_MAX; us <<= 1) {
udelay(us);
status = inb(APPLESMC_CMD_PORT);
/* write: wait for smc to settle */
@@ -190,6 +200,23 @@ static int send_byte(u8 cmd, u16 port)
if (status & 0x04)
return 0;
/* timeout: give up */
+ if (us << 1 == APPLESMC_UDELAY_MAX)
+ break;
+ /* busy: long wait and resend */
+ udelay(APPLESMC_RETRY_WAIT);
+ outb(cmd, port);
+ }
+ /* switch to mdelay for longer sleeps */
+ for (; us < APPLESMC_MAX_WAIT; us <<= 1) {
+ mdelay(us);
+ status = inb(APPLESMC_CMD_PORT);
+ /* write: wait for smc to settle */
+ if (status & 0x02)
+ continue;
+ /* ready: cmd accepted, return */
+ if (status & 0x04)
+ return 0;
+ /* timeout: give up */
if (us << 1 == APPLESMC_MAX_WAIT)
break;
/* busy: long wait and resend */
--
2.23.0.351.gc4317032e6-goog
next prev parent reply other threads:[~2019-09-24 17:47 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-09-24 17:37 [PATCH] hwmon: (applesmc) fix UB and udelay overflow Nick Desaulniers
2019-09-24 17:42 ` Nick Desaulniers
2019-09-24 17:47 ` Nick Desaulniers [this message]
2019-09-24 18:38 ` [PATCH v2] " Nathan Chancellor
2019-09-24 19:36 ` Nick Desaulniers
2019-09-24 19:41 ` Nathan Chancellor
2019-09-30 21:46 ` Cengiz Can
2019-10-01 0:01 ` Guenter Roeck
2019-10-02 21:43 ` Nick Desaulniers
2019-10-03 1:17 ` Guenter Roeck
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20190924174728.201464-1-ndesaulniers@google.com \
--to=ndesaulniers@google.com \
--cc=clang-built-linux@googlegroups.com \
--cc=jdelvare@suse.com \
--cc=linux-hwmon@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux@roeck-us.net \
--cc=natechancellor@gmail.com \
--cc=rydberg@bitmath.org \
--cc=tpgxyz@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).