mmc: core: block: fix sloppy typing in mmc_blk_ioctl_multi_cmd()
authorSergey Shtylyov <s.shtylyov@omp.ru>
Wed, 30 Mar 2022 21:09:07 +0000 (00:09 +0300)
committerUlf Hansson <ulf.hansson@linaro.org>
Tue, 26 Apr 2022 12:05:19 +0000 (14:05 +0200)
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>
Link: https://lore.kernel.org/r/eea3b0bd-6091-f005-7189-b5b7868abdb6@omp.ru
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
drivers/mmc/core/block.c

index 506dc90..b35e7a9 100644 (file)
@@ -676,8 +676,9 @@ static int mmc_blk_ioctl_multi_cmd(struct mmc_blk_data *md,
        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(struct mmc_blk_data *md,
        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(struct mmc_blk_data *md,
        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]);
        }