diff options
author | Brian Norris <briannorris@chromium.org> | 2016-05-27 12:45:49 -0400 |
---|---|---|
committer | Thierry Reding <thierry.reding@gmail.com> | 2016-06-10 08:21:00 -0400 |
commit | ef2bf4997f7da6efa8540d9cf726c44bf2b863af (patch) | |
tree | a90229605b8dfeedd6bb010dffee63e3df74b417 | |
parent | 1a695a905c18548062509178b98bc91e67510864 (diff) |
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.c | 3 | ||||
-rw-r--r-- | include/linux/pwm.h | 3 |
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) | |||
457 | { | 457 | { |
458 | int err; | 458 | int err; |
459 | 459 | ||
460 | if (!pwm) | 460 | if (!pwm || !state || !state->period || |
461 | state->duty_cycle > state->period) | ||
461 | return -EINVAL; | 462 | return -EINVAL; |
462 | 463 | ||
463 | if (!memcmp(state, &pwm->state, sizeof(*state))) | 464 | 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, | |||
235 | if (!pwm) | 235 | if (!pwm) |
236 | return -EINVAL; | 236 | return -EINVAL; |
237 | 237 | ||
238 | if (duty_ns < 0 || period_ns < 0) | ||
239 | return -EINVAL; | ||
240 | |||
238 | pwm_get_state(pwm, &state); | 241 | pwm_get_state(pwm, &state); |
239 | if (state.duty_cycle == duty_ns && state.period == period_ns) | 242 | if (state.duty_cycle == duty_ns && state.period == period_ns) |
240 | return 0; | 243 | return 0; |