Commit ef2bf499 authored by Brian Norris's avatar Brian Norris Committed by Thierry Reding

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: 5ec803ed ("pwm: Add core infrastructure to allow atomic updates")
Signed-off-by: default avatarBrian Norris <briannorris@chromium.org>
Acked-by: default avatarBoris Brezillon <boris.brezillon@free-electrons.com>
Signed-off-by: default avatarThierry Reding <thierry.reding@gmail.com>
parent 1a695a90
...@@ -457,7 +457,8 @@ int pwm_apply_state(struct pwm_device *pwm, struct pwm_state *state) ...@@ -457,7 +457,8 @@ int pwm_apply_state(struct pwm_device *pwm, struct pwm_state *state)
{ {
int err; int err;
if (!pwm) if (!pwm || !state || !state->period ||
state->duty_cycle > state->period)
return -EINVAL; return -EINVAL;
if (!memcmp(state, &pwm->state, sizeof(*state))) if (!memcmp(state, &pwm->state, sizeof(*state)))
......
...@@ -235,6 +235,9 @@ static inline int pwm_config(struct pwm_device *pwm, int duty_ns, ...@@ -235,6 +235,9 @@ static inline int pwm_config(struct pwm_device *pwm, int duty_ns,
if (!pwm) if (!pwm)
return -EINVAL; return -EINVAL;
if (duty_ns < 0 || period_ns < 0)
return -EINVAL;
pwm_get_state(pwm, &state); pwm_get_state(pwm, &state);
if (state.duty_cycle == duty_ns && state.period == period_ns) if (state.duty_cycle == duty_ns && state.period == period_ns)
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment