Message ID | 9a0cb0c1-a974-4f10-bc8d-94437983639a@moroto.mountain |
---|---|
State | Accepted |
Commit | ea33cb6fc2788f9fe248d49e1c0b2553a58436ef |
Headers | show |
Series | [1/5,v4] accel/qaic: tighten bounds checking in encode_message() | expand |
On 7/11/2023 1:50 PM, Dan Carpenter wrote: > There are several issues in this code. The check at the start of the > loop: > > if (user_len >= user_msg->len) { > > This check does not ensure that we have enough space for the trans_hdr > (8 bytes). Instead the check needs to be: > > if (user_len > user_msg->len - sizeof(*trans_hdr)) { > > That subtraction is done as an unsigned long we want to avoid > negatives. Add a lower bound to the start of the function. > > if (user_msg->len < sizeof(*trans_hdr)) > > There is a second integer underflow which can happen if > trans_hdr->len is zero inside the encode_passthrough() function. > > memcpy(out_trans->data, in_trans->data, in_trans->hdr.len - sizeof(in_trans->hdr)); > > Instead of adding a check to encode_passthrough() it's better to check > in this central place. Add that check: > > if (trans_hdr->len < sizeof(trans_hdr) > > The final concern is that the "user_len + trans_hdr->len" might have an > integer overflow bug. Use size_add() to prevent that. > > - if (user_len + trans_hdr->len > user_msg->len) { > + if (size_add(user_len, trans_hdr->len) > user_msg->len) { > > Fixes: 129776ac2e38 ("accel/qaic: Add control path") > Signed-off-by: Dan Carpenter <dan.carpenter@linaro.org> Reviewed-by: Pranjal Ramajor Asha Kanojiya <quic_pkanojiy@quicinc.com>
On 7/14/2023 5:41 AM, Pranjal Ramajor Asha Kanojiya wrote: > > > On 7/11/2023 1:50 PM, Dan Carpenter wrote: >> There are several issues in this code. The check at the start of the >> loop: >> >> if (user_len >= user_msg->len) { >> >> This check does not ensure that we have enough space for the trans_hdr >> (8 bytes). Instead the check needs to be: >> >> if (user_len > user_msg->len - sizeof(*trans_hdr)) { >> >> That subtraction is done as an unsigned long we want to avoid >> negatives. Add a lower bound to the start of the function. >> >> if (user_msg->len < sizeof(*trans_hdr)) >> >> There is a second integer underflow which can happen if >> trans_hdr->len is zero inside the encode_passthrough() function. >> >> memcpy(out_trans->data, in_trans->data, in_trans->hdr.len - >> sizeof(in_trans->hdr)); >> >> Instead of adding a check to encode_passthrough() it's better to check >> in this central place. Add that check: >> >> if (trans_hdr->len < sizeof(trans_hdr) >> >> The final concern is that the "user_len + trans_hdr->len" might have an >> integer overflow bug. Use size_add() to prevent that. >> >> - if (user_len + trans_hdr->len > user_msg->len) { >> + if (size_add(user_len, trans_hdr->len) > user_msg->len) { >> >> Fixes: 129776ac2e38 ("accel/qaic: Add control path") >> Signed-off-by: Dan Carpenter <dan.carpenter@linaro.org> > > Reviewed-by: Pranjal Ramajor Asha Kanojiya <quic_pkanojiy@quicinc.com> > Applied to drm-misc-fixes -Jeff
diff --git a/drivers/accel/qaic/qaic_control.c b/drivers/accel/qaic/qaic_control.c index 5c57f7b4494e..2fdd5959c52f 100644 --- a/drivers/accel/qaic/qaic_control.c +++ b/drivers/accel/qaic/qaic_control.c @@ -14,6 +14,7 @@ #include <linux/mm.h> #include <linux/moduleparam.h> #include <linux/mutex.h> +#include <linux/overflow.h> #include <linux/pci.h> #include <linux/scatterlist.h> #include <linux/types.h> @@ -748,7 +749,8 @@ static int encode_message(struct qaic_device *qdev, struct manage_msg *user_msg, int ret; int i; - if (!user_msg->count) { + if (!user_msg->count || + user_msg->len < sizeof(*trans_hdr)) { ret = -EINVAL; goto out; } @@ -765,12 +767,13 @@ static int encode_message(struct qaic_device *qdev, struct manage_msg *user_msg, } for (i = 0; i < user_msg->count; ++i) { - if (user_len >= user_msg->len) { + if (user_len > user_msg->len - sizeof(*trans_hdr)) { ret = -EINVAL; break; } trans_hdr = (struct qaic_manage_trans_hdr *)(user_msg->data + user_len); - if (user_len + trans_hdr->len > user_msg->len) { + if (trans_hdr->len < sizeof(trans_hdr) || + size_add(user_len, trans_hdr->len) > user_msg->len) { ret = -EINVAL; break; }
There are several issues in this code. The check at the start of the loop: if (user_len >= user_msg->len) { This check does not ensure that we have enough space for the trans_hdr (8 bytes). Instead the check needs to be: if (user_len > user_msg->len - sizeof(*trans_hdr)) { That subtraction is done as an unsigned long we want to avoid negatives. Add a lower bound to the start of the function. if (user_msg->len < sizeof(*trans_hdr)) There is a second integer underflow which can happen if trans_hdr->len is zero inside the encode_passthrough() function. memcpy(out_trans->data, in_trans->data, in_trans->hdr.len - sizeof(in_trans->hdr)); Instead of adding a check to encode_passthrough() it's better to check in this central place. Add that check: if (trans_hdr->len < sizeof(trans_hdr) The final concern is that the "user_len + trans_hdr->len" might have an integer overflow bug. Use size_add() to prevent that. - if (user_len + trans_hdr->len > user_msg->len) { + if (size_add(user_len, trans_hdr->len) > user_msg->len) { Fixes: 129776ac2e38 ("accel/qaic: Add control path") Signed-off-by: Dan Carpenter <dan.carpenter@linaro.org> --- v4: send this patch. v2: * Fix the >= vs > bug in: if (user_len > user_msg->len - sizeof(*trans_hdr)) { * include overflow.h --- drivers/accel/qaic/qaic_control.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)