A previous patch which introduced support for capabilities in the MMC_IOC_{MULTI_}CMD ioctls also hard-coded the ioctl values to maintain compatibility with non-PCuABI ioctl handlers such as those found in block.c.
This patch therefore removes the hard-coding of these ioctl values, and enforces compatibility by accounting for the change in values if the ioctl handler is running in compat64.
Signed-off-by: Akram Ahmad Akram.Ahmad@arm.com --- drivers/mmc/core/block.c | 21 +++++++++++++++++++++ include/uapi/linux/mmc/ioctl.h | 21 +++++++++------------ 2 files changed, 30 insertions(+), 12 deletions(-)
diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c index 17a1d24bdaed..acb7f3a9b31a 100644 --- a/drivers/mmc/core/block.c +++ b/drivers/mmc/core/block.c @@ -76,6 +76,15 @@ MODULE_ALIAS("mmc:block"); #define MMC_EXTRACT_INDEX_FROM_ARG(x) ((x & 0x00FF0000) >> 16) #define MMC_EXTRACT_VALUE_FROM_ARG(x) ((x & 0x0000FF00) >> 8)
+/* + * The compat_mmc_ioc_{multi_}cmd structs have different sizes in PCuABI and in + * compat64, which affects the expected MMC_IOC_{MULTI_}CMD ioctl values. The + * following ioctl values reflect the sizes of the compat64 structs defined in + * this file. + */ +#define COMPAT64_MMC_IOC_CMD _IOWR(MMC_BLOCK_MAJOR, 0, struct compat_mmc_ioc_cmd) +#define COMPAT64_MMC_IOC_MULTI_CMD _IOWR(MMC_BLOCK_MAJOR, 1, struct compat_mmc_ioc_multi_cmd) + static DEFINE_MUTEX(block_mutex);
/* @@ -858,6 +867,9 @@ static int mmc_blk_ioctl(struct block_device *bdev, blk_mode_t mode, int ret;
switch (cmd) { + case COMPAT64_MMC_IOC_CMD: + if (!in_compat64_syscall()) + return -EINVAL; case MMC_IOC_CMD: ret = mmc_blk_check_blkdev(bdev); if (ret) @@ -870,6 +882,9 @@ static int mmc_blk_ioctl(struct block_device *bdev, blk_mode_t mode, NULL); mmc_blk_put(md); return ret; + case COMPAT64_MMC_IOC_MULTI_CMD: + if (!in_compat64_syscall()) + return -EINVAL; case MMC_IOC_MULTI_CMD: ret = mmc_blk_check_blkdev(bdev); if (ret) @@ -2678,11 +2693,17 @@ static long mmc_rpmb_ioctl(struct file *filp, unsigned int cmd, int ret;
switch (cmd) { + case COMPAT64_MMC_IOC_CMD: + if (!in_compat64_syscall()) + return -EINVAL; case MMC_IOC_CMD: ret = mmc_blk_ioctl_cmd(rpmb->md, (struct mmc_ioc_cmd __user *)arg, rpmb); break; + case COMPAT64_MMC_IOC_MULTI_CMD: + if (!in_compat64_syscall()) + return -EINVAL; case MMC_IOC_MULTI_CMD: ret = mmc_blk_ioctl_multi_cmd(rpmb->md, (struct mmc_ioc_multi_cmd __user *)arg, diff --git a/include/uapi/linux/mmc/ioctl.h b/include/uapi/linux/mmc/ioctl.h index 9d34bfc49198..e99d932268c6 100644 --- a/include/uapi/linux/mmc/ioctl.h +++ b/include/uapi/linux/mmc/ioctl.h @@ -67,26 +67,23 @@ struct mmc_ioc_multi_cmd { /* * The size of struct mmc_ioc_cmd changes in PCuABI due to the use of * __kernel_uintptr_t, which in turn modifies the command value for this - * ioctl. It is therefore necessary to hard-code the value for the ioctl - * using the size of the struct that is expected in any ABI other than - * PCuABI, to ensure that the value for MMC_IOC_CMD is unchanged. The - * original definition is as follows: - * - * #define MMC_IOC_CMD _IOWR(MMC_BLOCK_MAJOR, 0, struct mmc_ioc_cmd) + * ioctl. As this command value is not hard-coded to represent the original + * size of the struct, any ioctl handlers in compat64 must handle this change + * in values instead. */ -#define MMC_IOC_CMD _IOC(_IOC_READ|_IOC_WRITE, MMC_BLOCK_MAJOR, 0, 72) +#define MMC_IOC_CMD _IOWR(MMC_BLOCK_MAJOR, 0, struct mmc_ioc_cmd) + /* * MMC_IOC_MULTI_CMD: Used to send an array of MMC commands described by * the structure mmc_ioc_multi_cmd. The MMC driver will issue all * commands in array in sequence to card. * * Note: the size of struct mmc_ioc_multi_cmd changes in PCuABI, due to the - * increased alignment of struct mmc_ioc_cmd. For that reason, its value needs - * to be hard-coded too. Original definition: - * - * #define MMC_IOC_MULTI_CMD _IOWR(MMC_BLOCK_MAJOR, 1, struct mmc_ioc_multi_cmd) + * increased alignment of struct mmc_ioc_cmd. Similarly to MMC_IOC_CMD, any + * ioctl handlers must account for this change when running in compat64. */ -#define MMC_IOC_MULTI_CMD _IOC(_IOC_READ|_IOC_WRITE, MMC_BLOCK_MAJOR, 1, 8) +#define MMC_IOC_MULTI_CMD _IOWR(MMC_BLOCK_MAJOR, 1, struct mmc_ioc_multi_cmd) + /* * Since this ioctl is only meant to enhance (and not replace) normal access * to the mmc bus device, an upper data transfer limit of MMC_IOC_MAX_BYTES