Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 83c742c3 authored by Shawn Lin's avatar Shawn Lin Committed by Ulf Hansson
Browse files

mmc: block: fix ABI regression of mmc_blk_ioctl



If mmc_blk_ioctl returns -EINVAL, blkdev_ioctl continues to
work without returning err to user-space. But now we check
CAP_SYS_RAWIO firstly, so we return -EPERM to blkdev_ioctl,
which make blkdev_ioctl return -EPERM to user-space directly.
So this will break all the ioctl with BLKROSET. Now we find
Android-adb suffer it for the following log:

remount of /system failed;
couldn't make block device writable: Operation not permitted
openat(AT_FDCWD, "/dev/block/platform/ff420000.dwmmc/by-name/system", O_RDONLY) = 3
ioctl(3, BLKROSET, 0)  = -1 EPERM (Operation not permitted)

Fixes: a5f5774c ("mmc: block: Add new ioctl to send multi commands")
Cc: stable@vger.kernel.org
Signed-off-by: default avatarShawn Lin <shawn.lin@rock-chips.com>
Signed-off-by: default avatarUlf Hansson <ulf.hansson@linaro.org>
parent 93c77d29
Loading
Loading
Loading
Loading
+16 −8
Original line number Original line Diff line number Diff line
@@ -589,6 +589,14 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev,
	struct mmc_card *card;
	struct mmc_card *card;
	int err = 0, ioc_err = 0;
	int err = 0, ioc_err = 0;


	/*
	 * The caller must have CAP_SYS_RAWIO, and must be calling this on the
	 * whole block device, not on a partition.  This prevents overspray
	 * between sibling partitions.
	 */
	if ((!capable(CAP_SYS_RAWIO)) || (bdev != bdev->bd_contains))
		return -EPERM;

	idata = mmc_blk_ioctl_copy_from_user(ic_ptr);
	idata = mmc_blk_ioctl_copy_from_user(ic_ptr);
	if (IS_ERR(idata))
	if (IS_ERR(idata))
		return PTR_ERR(idata);
		return PTR_ERR(idata);
@@ -631,6 +639,14 @@ static int mmc_blk_ioctl_multi_cmd(struct block_device *bdev,
	int i, err = 0, ioc_err = 0;
	int i, err = 0, ioc_err = 0;
	__u64 num_of_cmds;
	__u64 num_of_cmds;


	/*
	 * The caller must have CAP_SYS_RAWIO, and must be calling this on the
	 * whole block device, not on a partition.  This prevents overspray
	 * between sibling partitions.
	 */
	if ((!capable(CAP_SYS_RAWIO)) || (bdev != bdev->bd_contains))
		return -EPERM;

	if (copy_from_user(&num_of_cmds, &user->num_of_cmds,
	if (copy_from_user(&num_of_cmds, &user->num_of_cmds,
			   sizeof(num_of_cmds)))
			   sizeof(num_of_cmds)))
		return -EFAULT;
		return -EFAULT;
@@ -688,14 +704,6 @@ static int mmc_blk_ioctl_multi_cmd(struct block_device *bdev,
static int mmc_blk_ioctl(struct block_device *bdev, fmode_t mode,
static int mmc_blk_ioctl(struct block_device *bdev, fmode_t mode,
	unsigned int cmd, unsigned long arg)
	unsigned int cmd, unsigned long arg)
{
{
	/*
	 * The caller must have CAP_SYS_RAWIO, and must be calling this on the
	 * whole block device, not on a partition.  This prevents overspray
	 * between sibling partitions.
	 */
	if ((!capable(CAP_SYS_RAWIO)) || (bdev != bdev->bd_contains))
		return -EPERM;

	switch (cmd) {
	switch (cmd) {
	case MMC_IOC_CMD:
	case MMC_IOC_CMD:
		return mmc_blk_ioctl_cmd(bdev,
		return mmc_blk_ioctl_cmd(bdev,