Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

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>

authored by

Sergey Shtylyov and committed by
Ulf Hansson
103da066 7792fdf6

+9 -7
+9 -7
drivers/mmc/core/block.c
··· 676 676 struct mmc_ioc_cmd __user *cmds = user->cmds; 677 677 struct mmc_card *card; 678 678 struct mmc_queue *mq; 679 - int i, err = 0, ioc_err = 0; 679 + int err = 0, ioc_err = 0; 680 680 __u64 num_of_cmds; 681 + unsigned int i, n; 681 682 struct request *req; 682 683 683 684 if (copy_from_user(&num_of_cmds, &user->num_of_cmds, ··· 691 690 if (num_of_cmds > MMC_IOC_MAX_CMDS) 692 691 return -EINVAL; 693 692 694 - idata = kcalloc(num_of_cmds, sizeof(*idata), GFP_KERNEL); 693 + n = num_of_cmds; 694 + idata = kcalloc(n, sizeof(*idata), GFP_KERNEL); 695 695 if (!idata) 696 696 return -ENOMEM; 697 697 698 - for (i = 0; i < num_of_cmds; i++) { 698 + for (i = 0; i < n; i++) { 699 699 idata[i] = mmc_blk_ioctl_copy_from_user(&cmds[i]); 700 700 if (IS_ERR(idata[i])) { 701 701 err = PTR_ERR(idata[i]); 702 - num_of_cmds = i; 702 + n = i; 703 703 goto cmd_err; 704 704 } 705 705 /* This will be NULL on non-RPMB ioctl():s */ ··· 727 725 req_to_mmc_queue_req(req)->drv_op = 728 726 rpmb ? MMC_DRV_OP_IOCTL_RPMB : MMC_DRV_OP_IOCTL; 729 727 req_to_mmc_queue_req(req)->drv_op_data = idata; 730 - req_to_mmc_queue_req(req)->ioc_count = num_of_cmds; 728 + req_to_mmc_queue_req(req)->ioc_count = n; 731 729 blk_execute_rq(req, false); 732 730 ioc_err = req_to_mmc_queue_req(req)->drv_op_result; 733 731 734 732 /* copy to user if data and response */ 735 - for (i = 0; i < num_of_cmds && !err; i++) 733 + for (i = 0; i < n && !err; i++) 736 734 err = mmc_blk_ioctl_copy_to_user(&cmds[i], idata[i]); 737 735 738 736 blk_mq_free_request(req); 739 737 740 738 cmd_err: 741 - for (i = 0; i < num_of_cmds; i++) { 739 + for (i = 0; i < n; i++) { 742 740 kfree(idata[i]->buf); 743 741 kfree(idata[i]); 744 742 }