aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/md')
-rw-r--r--drivers/md/dm-ioctl.c45
1 files changed, 32 insertions, 13 deletions
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index a37aeba7dc1b..0666b5d14b88 100644
--- a/drivers/md/dm-ioctl.c
+++ b/drivers/md/dm-ioctl.c
@@ -1543,7 +1543,21 @@ static int check_version(unsigned int cmd, struct dm_ioctl __user *user)
1543 return r; 1543 return r;
1544} 1544}
1545 1545
1546static int copy_params(struct dm_ioctl __user *user, struct dm_ioctl **param) 1546#define DM_PARAMS_VMALLOC 0x0001 /* Params alloced with vmalloc not kmalloc */
1547#define DM_WIPE_BUFFER 0x0010 /* Wipe input buffer before returning from ioctl */
1548
1549static void free_params(struct dm_ioctl *param, size_t param_size, int param_flags)
1550{
1551 if (param_flags & DM_WIPE_BUFFER)
1552 memset(param, 0, param_size);
1553
1554 if (param_flags & DM_PARAMS_VMALLOC)
1555 vfree(param);
1556 else
1557 kfree(param);
1558}
1559
1560static int copy_params(struct dm_ioctl __user *user, struct dm_ioctl **param, int *param_flags)
1547{ 1561{
1548 struct dm_ioctl tmp, *dmi; 1562 struct dm_ioctl tmp, *dmi;
1549 int secure_data; 1563 int secure_data;
@@ -1556,10 +1570,21 @@ static int copy_params(struct dm_ioctl __user *user, struct dm_ioctl **param)
1556 1570
1557 secure_data = tmp.flags & DM_SECURE_DATA_FLAG; 1571 secure_data = tmp.flags & DM_SECURE_DATA_FLAG;
1558 1572
1573 *param_flags = secure_data ? DM_WIPE_BUFFER : 0;
1574
1559 /* 1575 /*
1560 * Try to avoid low memory issues when a device is suspended. 1576 * Try to avoid low memory issues when a device is suspended.
1577 * Use kmalloc() rather than vmalloc() when we can.
1561 */ 1578 */
1562 dmi = __vmalloc(tmp.data_size, GFP_NOIO | __GFP_REPEAT | __GFP_HIGH, PAGE_KERNEL); 1579 dmi = NULL;
1580 if (tmp.data_size <= KMALLOC_MAX_SIZE)
1581 dmi = kmalloc(tmp.data_size, GFP_NOIO | __GFP_NORETRY | __GFP_NOMEMALLOC | __GFP_NOWARN);
1582
1583 if (!dmi) {
1584 dmi = __vmalloc(tmp.data_size, GFP_NOIO | __GFP_REPEAT | __GFP_HIGH, PAGE_KERNEL);
1585 *param_flags |= DM_PARAMS_VMALLOC;
1586 }
1587
1563 if (!dmi) { 1588 if (!dmi) {
1564 if (secure_data && clear_user(user, tmp.data_size)) 1589 if (secure_data && clear_user(user, tmp.data_size))
1565 return -EFAULT; 1590 return -EFAULT;
@@ -1585,9 +1610,8 @@ static int copy_params(struct dm_ioctl __user *user, struct dm_ioctl **param)
1585 return 0; 1610 return 0;
1586 1611
1587bad: 1612bad:
1588 if (secure_data) 1613 free_params(dmi, tmp.data_size, *param_flags);
1589 memset(dmi, 0, tmp.data_size); 1614
1590 vfree(dmi);
1591 return -EFAULT; 1615 return -EFAULT;
1592} 1616}
1593 1617
@@ -1624,7 +1648,7 @@ static int validate_params(uint cmd, struct dm_ioctl *param)
1624static int ctl_ioctl(uint command, struct dm_ioctl __user *user) 1648static int ctl_ioctl(uint command, struct dm_ioctl __user *user)
1625{ 1649{
1626 int r = 0; 1650 int r = 0;
1627 int wipe_buffer; 1651 int param_flags;
1628 unsigned int cmd; 1652 unsigned int cmd;
1629 struct dm_ioctl *uninitialized_var(param); 1653 struct dm_ioctl *uninitialized_var(param);
1630 ioctl_fn fn = NULL; 1654 ioctl_fn fn = NULL;
@@ -1662,14 +1686,12 @@ static int ctl_ioctl(uint command, struct dm_ioctl __user *user)
1662 /* 1686 /*
1663 * Copy the parameters into kernel space. 1687 * Copy the parameters into kernel space.
1664 */ 1688 */
1665 r = copy_params(user, &param); 1689 r = copy_params(user, &param, &param_flags);
1666 1690
1667 if (r) 1691 if (r)
1668 return r; 1692 return r;
1669 1693
1670 input_param_size = param->data_size; 1694 input_param_size = param->data_size;
1671 wipe_buffer = param->flags & DM_SECURE_DATA_FLAG;
1672
1673 r = validate_params(cmd, param); 1695 r = validate_params(cmd, param);
1674 if (r) 1696 if (r)
1675 goto out; 1697 goto out;
@@ -1684,10 +1706,7 @@ static int ctl_ioctl(uint command, struct dm_ioctl __user *user)
1684 r = -EFAULT; 1706 r = -EFAULT;
1685 1707
1686out: 1708out:
1687 if (wipe_buffer) 1709 free_params(param, input_param_size, param_flags);
1688 memset(param, 0, input_param_size);
1689
1690 vfree(param);
1691 return r; 1710 return r;
1692} 1711}
1693 1712