summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrian Norris <briannorris@chromium.org>2016-05-27 09:45:49 -0700
committerThierry Reding <thierry.reding@gmail.com>2016-06-10 14:21:00 +0200
commitef2bf4997f7da6efa8540d9cf726c44bf2b863af (patch)
treea90229605b8dfeedd6bb010dffee63e3df74b417
parent1a695a905c18548062509178b98bc91e67510864 (diff)
downloadlwn-ef2bf4997f7da6efa8540d9cf726c44bf2b863af.tar.gz
lwn-ef2bf4997f7da6efa8540d9cf726c44bf2b863af.zip
pwm: Improve args checking in pwm_apply_state()
It seems like in the process of refactoring pwm_config() to utilize the newly-introduced pwm_apply_state() API, some args/bounds checking was dropped. In particular, I noted that we are now allowing invalid period selections, e.g.: # echo 1 > /sys/class/pwm/pwmchip0/export # cat /sys/class/pwm/pwmchip0/pwm1/period 100 # echo 101 > /sys/class/pwm/pwmchip0/pwm1/duty_cycle [... driver may or may not reject the value, or trigger some logic bug ...] It's better to see: # echo 1 > /sys/class/pwm/pwmchip0/export # cat /sys/class/pwm/pwmchip0/pwm1/period 100 # echo 101 > /sys/class/pwm/pwmchip0/pwm1/duty_cycle -bash: echo: write error: Invalid argument This patch reintroduces some bounds checks in both pwm_config() (for its signed parameters; we don't want to convert negative values into large unsigned values) and in pwm_apply_state() (which fix the above described behavior, as well as other potential API misuses). Fixes: 5ec803edcb70 ("pwm: Add core infrastructure to allow atomic updates") Signed-off-by: Brian Norris <briannorris@chromium.org> Acked-by: Boris Brezillon <boris.brezillon@free-electrons.com> Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
-rw-r--r--drivers/pwm/core.c3
-rw-r--r--include/linux/pwm.h3
2 files changed, 5 insertions, 1 deletions
diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c
index dba3843c53b8..ed337a8c34ab 100644
--- a/drivers/pwm/core.c
+++ b/drivers/pwm/core.c
@@ -457,7 +457,8 @@ int pwm_apply_state(struct pwm_device *pwm, struct pwm_state *state)
{
int err;
- if (!pwm)
+ if (!pwm || !state || !state->period ||
+ state->duty_cycle > state->period)
return -EINVAL;
if (!memcmp(state, &pwm->state, sizeof(*state)))
diff --git a/include/linux/pwm.h b/include/linux/pwm.h
index 17018f3c066e..908b67c847cd 100644
--- a/include/linux/pwm.h
+++ b/include/linux/pwm.h
@@ -235,6 +235,9 @@ static inline int pwm_config(struct pwm_device *pwm, int duty_ns,
if (!pwm)
return -EINVAL;
+ if (duty_ns < 0 || period_ns < 0)
+ return -EINVAL;
+
pwm_get_state(pwm, &state);
if (state.duty_cycle == duty_ns && state.period == period_ns)
return 0;