Commit 103da066 authored by Sergey Shtylyov's avatar Sergey Shtylyov Committed by Ulf Hansson
Browse files

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: default avatarSergey Shtylyov <s.shtylyov@omp.ru>
Link: https://lore.kernel.org/r/eea3b0bd-6091-f005-7189-b5b7868abdb6@omp.ru


Signed-off-by: default avatarUlf Hansson <ulf.hansson@linaro.org>
parent 7792fdf6
Loading
Loading
Loading
Loading
+9 −7
Original line number Diff line number Diff line
@@ -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]);
	}