diff options
| author | Dan Carpenter <dan.carpenter@oracle.com> | 2016-06-21 09:58:46 -0400 |
|---|---|---|
| committer | Olof Johansson <olof@lixom.net> | 2016-07-05 17:01:52 -0400 |
| commit | 096cdc6f52225835ff503f987a0d68ef770bb78e (patch) | |
| tree | 7e123fe975c5578ff97ad21811f9e4500210fb0c | |
| parent | 33688abb2802ff3a230bd2441f765477b94cc89e (diff) | |
platform/chrome: cros_ec_dev - double fetch bug in ioctl
We verify "u_cmd.outsize" and "u_cmd.insize" but we need to make sure
that those values have not changed between the two copy_from_user()
calls. Otherwise it could lead to a buffer overflow.
Additionally, cros_ec_cmd_xfer() can set s_cmd->insize to a lower value.
We should use the new smaller value so we don't copy too much data to
the user.
Reported-by: Pengfei Wang <wpengfeinudt@gmail.com>
Fixes: a841178445bb ('mfd: cros_ec: Use a zero-length array for command data')
Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
Reviewed-by: Kees Cook <keescook@chromium.org>
Tested-by: Gwendal Grignou <gwendal@chromium.org>
Cc: <stable@vger.kernel.org> # v4.2+
Signed-off-by: Olof Johansson <olof@lixom.net>
| -rw-r--r-- | drivers/platform/chrome/cros_ec_dev.c | 8 |
1 files changed, 7 insertions, 1 deletions
diff --git a/drivers/platform/chrome/cros_ec_dev.c b/drivers/platform/chrome/cros_ec_dev.c index 6d8ee3b15872..8abd80dbcbed 100644 --- a/drivers/platform/chrome/cros_ec_dev.c +++ b/drivers/platform/chrome/cros_ec_dev.c | |||
| @@ -151,13 +151,19 @@ static long ec_device_ioctl_xcmd(struct cros_ec_dev *ec, void __user *arg) | |||
| 151 | goto exit; | 151 | goto exit; |
| 152 | } | 152 | } |
| 153 | 153 | ||
| 154 | if (u_cmd.outsize != s_cmd->outsize || | ||
| 155 | u_cmd.insize != s_cmd->insize) { | ||
| 156 | ret = -EINVAL; | ||
| 157 | goto exit; | ||
| 158 | } | ||
| 159 | |||
| 154 | s_cmd->command += ec->cmd_offset; | 160 | s_cmd->command += ec->cmd_offset; |
| 155 | ret = cros_ec_cmd_xfer(ec->ec_dev, s_cmd); | 161 | ret = cros_ec_cmd_xfer(ec->ec_dev, s_cmd); |
| 156 | /* Only copy data to userland if data was received. */ | 162 | /* Only copy data to userland if data was received. */ |
| 157 | if (ret < 0) | 163 | if (ret < 0) |
| 158 | goto exit; | 164 | goto exit; |
| 159 | 165 | ||
| 160 | if (copy_to_user(arg, s_cmd, sizeof(*s_cmd) + u_cmd.insize)) | 166 | if (copy_to_user(arg, s_cmd, sizeof(*s_cmd) + s_cmd->insize)) |
| 161 | ret = -EFAULT; | 167 | ret = -EFAULT; |
| 162 | exit: | 168 | exit: |
| 163 | kfree(s_cmd); | 169 | kfree(s_cmd); |
