diff mbox series

mmc: core: block: fix sloppy typing in mmc_blk_ioctl_multi_cmd()

Message ID eea3b0bd-6091-f005-7189-b5b7868abdb6@omp.ru (mailing list archive)
State New, archived
Headers show
Series mmc: core: block: fix sloppy typing in mmc_blk_ioctl_multi_cmd() | expand

Commit Message

Sergey Shtylyov March 30, 2022, 9:09 p.m. UTC
Despite mmc_ioc_multi_cmd::num_of_cmds is a 64-bit field, its maximum
value is limited to MMC_IOC_MAX_CMDS (only 255); using a 64-bit local
variable to hold a copy of that field leads to gcc generating ineffective
loop code: despite the source code using an *int* variable for the loop
counters,  the 32-bit object code uses 64-bit unsigned counters.  Also,
gcc has to drop the most significant word of that 64-bit variable when
calling kcalloc() and assigning to mmc_queue_req::ioc_count anyway.
Using the *unsigned int* variable instead results in a better code.

Found by Linux Verification Center (linuxtesting.org) with the SVACE static
analysis tool.

Signed-off-by: Sergey Shtylyov <s.shtylyov@omp.ru>

---
This patch is against the 'next' branch of Ulf Hansson's 'mmc.git' repo.

 drivers/mmc/core/block.c |   16 +++++++++-------
 1 file changed, 9 insertions(+), 7 deletions(-)

Comments

Ulf Hansson April 6, 2022, 2:55 p.m. UTC | #1
On Wed, 30 Mar 2022 at 23:09, Sergey Shtylyov <s.shtylyov@omp.ru> wrote:
>
> Despite mmc_ioc_multi_cmd::num_of_cmds is a 64-bit field, its maximum
> value is limited to MMC_IOC_MAX_CMDS (only 255); using a 64-bit local
> variable to hold a copy of that field leads to gcc generating ineffective
> loop code: despite the source code using an *int* variable for the loop
> counters,  the 32-bit object code uses 64-bit unsigned counters.  Also,
> gcc has to drop the most significant word of that 64-bit variable when
> calling kcalloc() and assigning to mmc_queue_req::ioc_count anyway.
> Using the *unsigned int* variable instead results in a better code.
>
> Found by Linux Verification Center (linuxtesting.org) with the SVACE static
> analysis tool.
>
> Signed-off-by: Sergey Shtylyov <s.shtylyov@omp.ru>

Applied for next, thanks!

Kind regards
Uffe


>
> ---
> This patch is against the 'next' branch of Ulf Hansson's 'mmc.git' repo.
>
>  drivers/mmc/core/block.c |   16 +++++++++-------
>  1 file changed, 9 insertions(+), 7 deletions(-)
>
> Index: mmc/drivers/mmc/core/block.c
> ===================================================================
> --- mmc.orig/drivers/mmc/core/block.c
> +++ mmc/drivers/mmc/core/block.c
> @@ -676,8 +676,9 @@ static int mmc_blk_ioctl_multi_cmd(struc
>         struct mmc_ioc_cmd __user *cmds = user->cmds;
>         struct mmc_card *card;
>         struct mmc_queue *mq;
> -       int i, err = 0, ioc_err = 0;
> +       int err = 0, ioc_err = 0;
>         __u64 num_of_cmds;
> +       unsigned int i, n;
>         struct request *req;
>
>         if (copy_from_user(&num_of_cmds, &user->num_of_cmds,
> @@ -690,15 +691,16 @@ static int mmc_blk_ioctl_multi_cmd(struc
>         if (num_of_cmds > MMC_IOC_MAX_CMDS)
>                 return -EINVAL;
>
> -       idata = kcalloc(num_of_cmds, sizeof(*idata), GFP_KERNEL);
> +       n = num_of_cmds;
> +       idata = kcalloc(n, sizeof(*idata), GFP_KERNEL);
>         if (!idata)
>                 return -ENOMEM;
>
> -       for (i = 0; i < num_of_cmds; i++) {
> +       for (i = 0; i < n; i++) {
>                 idata[i] = mmc_blk_ioctl_copy_from_user(&cmds[i]);
>                 if (IS_ERR(idata[i])) {
>                         err = PTR_ERR(idata[i]);
> -                       num_of_cmds = i;
> +                       n = i;
>                         goto cmd_err;
>                 }
>                 /* This will be NULL on non-RPMB ioctl():s */
> @@ -725,18 +727,18 @@ static int mmc_blk_ioctl_multi_cmd(struc
>         req_to_mmc_queue_req(req)->drv_op =
>                 rpmb ? MMC_DRV_OP_IOCTL_RPMB : MMC_DRV_OP_IOCTL;
>         req_to_mmc_queue_req(req)->drv_op_data = idata;
> -       req_to_mmc_queue_req(req)->ioc_count = num_of_cmds;
> +       req_to_mmc_queue_req(req)->ioc_count = n;
>         blk_execute_rq(req, false);
>         ioc_err = req_to_mmc_queue_req(req)->drv_op_result;
>
>         /* copy to user if data and response */
> -       for (i = 0; i < num_of_cmds && !err; i++)
> +       for (i = 0; i < n && !err; i++)
>                 err = mmc_blk_ioctl_copy_to_user(&cmds[i], idata[i]);
>
>         blk_mq_free_request(req);
>
>  cmd_err:
> -       for (i = 0; i < num_of_cmds; i++) {
> +       for (i = 0; i < n; i++) {
>                 kfree(idata[i]->buf);
>                 kfree(idata[i]);
>         }
diff mbox series

Patch

Index: mmc/drivers/mmc/core/block.c
===================================================================
--- mmc.orig/drivers/mmc/core/block.c
+++ mmc/drivers/mmc/core/block.c
@@ -676,8 +676,9 @@  static int mmc_blk_ioctl_multi_cmd(struc
 	struct mmc_ioc_cmd __user *cmds = user->cmds;
 	struct mmc_card *card;
 	struct mmc_queue *mq;
-	int i, err = 0, ioc_err = 0;
+	int err = 0, ioc_err = 0;
 	__u64 num_of_cmds;
+	unsigned int i, n;
 	struct request *req;
 
 	if (copy_from_user(&num_of_cmds, &user->num_of_cmds,
@@ -690,15 +691,16 @@  static int mmc_blk_ioctl_multi_cmd(struc
 	if (num_of_cmds > MMC_IOC_MAX_CMDS)
 		return -EINVAL;
 
-	idata = kcalloc(num_of_cmds, sizeof(*idata), GFP_KERNEL);
+	n = num_of_cmds;
+	idata = kcalloc(n, sizeof(*idata), GFP_KERNEL);
 	if (!idata)
 		return -ENOMEM;
 
-	for (i = 0; i < num_of_cmds; i++) {
+	for (i = 0; i < n; i++) {
 		idata[i] = mmc_blk_ioctl_copy_from_user(&cmds[i]);
 		if (IS_ERR(idata[i])) {
 			err = PTR_ERR(idata[i]);
-			num_of_cmds = i;
+			n = i;
 			goto cmd_err;
 		}
 		/* This will be NULL on non-RPMB ioctl():s */
@@ -725,18 +727,18 @@  static int mmc_blk_ioctl_multi_cmd(struc
 	req_to_mmc_queue_req(req)->drv_op =
 		rpmb ? MMC_DRV_OP_IOCTL_RPMB : MMC_DRV_OP_IOCTL;
 	req_to_mmc_queue_req(req)->drv_op_data = idata;
-	req_to_mmc_queue_req(req)->ioc_count = num_of_cmds;
+	req_to_mmc_queue_req(req)->ioc_count = n;
 	blk_execute_rq(req, false);
 	ioc_err = req_to_mmc_queue_req(req)->drv_op_result;
 
 	/* copy to user if data and response */
-	for (i = 0; i < num_of_cmds && !err; i++)
+	for (i = 0; i < n && !err; i++)
 		err = mmc_blk_ioctl_copy_to_user(&cmds[i], idata[i]);
 
 	blk_mq_free_request(req);
 
 cmd_err:
-	for (i = 0; i < num_of_cmds; i++) {
+	for (i = 0; i < n; i++) {
 		kfree(idata[i]->buf);
 		kfree(idata[i]);
 	}