aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/dm-ioctl.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-12-21 20:08:06 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2012-12-21 20:08:06 -0500
commitb49249d10324d0fd6fb29725c2807dfd80d0edbc (patch)
tree9a8fa724e6c9f9283530979c6e32a311c74999d5 /drivers/md/dm-ioctl.c
parent10532b560bacf23766f9c7dc09778b31b198ff45 (diff)
parent45e621d45e24ffc4cb2b2935e8438987b860063a (diff)
Merge tag 'dm-3.8-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/agk/linux-dm
Pull dm update from Alasdair G Kergon: "Miscellaneous device-mapper fixes, cleanups and performance improvements. Of particular note: - Disable broken WRITE SAME support in all targets except linear and striped. Use it when kcopyd is zeroing blocks. - Remove several mempools from targets by moving the data into the bio's new front_pad area(which dm calls 'per_bio_data'). - Fix a race in thin provisioning if discards are misused. - Prevent userspace from interfering with the ioctl parameters and use kmalloc for the data buffer if it's small instead of vmalloc. - Throttle some annoying error messages when I/O fails." * tag 'dm-3.8-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/agk/linux-dm: (36 commits) dm stripe: add WRITE SAME support dm: remove map_info dm snapshot: do not use map_context dm thin: dont use map_context dm raid1: dont use map_context dm flakey: dont use map_context dm raid1: rename read_record to bio_record dm: move target request nr to dm_target_io dm snapshot: use per_bio_data dm verity: use per_bio_data dm raid1: use per_bio_data dm: introduce per_bio_data dm kcopyd: add WRITE SAME support to dm_kcopyd_zero dm linear: add WRITE SAME support dm: add WRITE SAME support dm: prepare to support WRITE SAME dm ioctl: use kmalloc if possible dm ioctl: remove PF_MEMALLOC dm persistent data: improve improve space map block alloc failure message dm thin: use DMERR_LIMIT for errors ...
Diffstat (limited to 'drivers/md/dm-ioctl.c')
-rw-r--r--drivers/md/dm-ioctl.c64
1 files changed, 43 insertions, 21 deletions
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index afd95986d099..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,7 +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
1559 dmi = vmalloc(tmp.data_size); 1573 *param_flags = secure_data ? DM_WIPE_BUFFER : 0;
1574
1575 /*
1576 * Try to avoid low memory issues when a device is suspended.
1577 * Use kmalloc() rather than vmalloc() when we can.
1578 */
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
1560 if (!dmi) { 1588 if (!dmi) {
1561 if (secure_data && clear_user(user, tmp.data_size)) 1589 if (secure_data && clear_user(user, tmp.data_size))
1562 return -EFAULT; 1590 return -EFAULT;
@@ -1566,6 +1594,14 @@ static int copy_params(struct dm_ioctl __user *user, struct dm_ioctl **param)
1566 if (copy_from_user(dmi, user, tmp.data_size)) 1594 if (copy_from_user(dmi, user, tmp.data_size))
1567 goto bad; 1595 goto bad;
1568 1596
1597 /*
1598 * Abort if something changed the ioctl data while it was being copied.
1599 */
1600 if (dmi->data_size != tmp.data_size) {
1601 DMERR("rejecting ioctl: data size modified while processing parameters");
1602 goto bad;
1603 }
1604
1569 /* Wipe the user buffer so we do not return it to userspace */ 1605 /* Wipe the user buffer so we do not return it to userspace */
1570 if (secure_data && clear_user(user, tmp.data_size)) 1606 if (secure_data && clear_user(user, tmp.data_size))
1571 goto bad; 1607 goto bad;
@@ -1574,9 +1610,8 @@ static int copy_params(struct dm_ioctl __user *user, struct dm_ioctl **param)
1574 return 0; 1610 return 0;
1575 1611
1576bad: 1612bad:
1577 if (secure_data) 1613 free_params(dmi, tmp.data_size, *param_flags);
1578 memset(dmi, 0, tmp.data_size); 1614
1579 vfree(dmi);
1580 return -EFAULT; 1615 return -EFAULT;
1581} 1616}
1582 1617
@@ -1613,7 +1648,7 @@ static int validate_params(uint cmd, struct dm_ioctl *param)
1613static int ctl_ioctl(uint command, struct dm_ioctl __user *user) 1648static int ctl_ioctl(uint command, struct dm_ioctl __user *user)
1614{ 1649{
1615 int r = 0; 1650 int r = 0;
1616 int wipe_buffer; 1651 int param_flags;
1617 unsigned int cmd; 1652 unsigned int cmd;
1618 struct dm_ioctl *uninitialized_var(param); 1653 struct dm_ioctl *uninitialized_var(param);
1619 ioctl_fn fn = NULL; 1654 ioctl_fn fn = NULL;
@@ -1649,24 +1684,14 @@ static int ctl_ioctl(uint command, struct dm_ioctl __user *user)
1649 } 1684 }
1650 1685
1651 /* 1686 /*
1652 * Trying to avoid low memory issues when a device is
1653 * suspended.
1654 */
1655 current->flags |= PF_MEMALLOC;
1656
1657 /*
1658 * Copy the parameters into kernel space. 1687 * Copy the parameters into kernel space.
1659 */ 1688 */
1660 r = copy_params(user, &param); 1689 r = copy_params(user, &param, &param_flags);
1661
1662 current->flags &= ~PF_MEMALLOC;
1663 1690
1664 if (r) 1691 if (r)
1665 return r; 1692 return r;
1666 1693
1667 input_param_size = param->data_size; 1694 input_param_size = param->data_size;
1668 wipe_buffer = param->flags & DM_SECURE_DATA_FLAG;
1669
1670 r = validate_params(cmd, param); 1695 r = validate_params(cmd, param);
1671 if (r) 1696 if (r)
1672 goto out; 1697 goto out;
@@ -1681,10 +1706,7 @@ static int ctl_ioctl(uint command, struct dm_ioctl __user *user)
1681 r = -EFAULT; 1706 r = -EFAULT;
1682 1707
1683out: 1708out:
1684 if (wipe_buffer) 1709 free_params(param, input_param_size, param_flags);
1685 memset(param, 0, input_param_size);
1686
1687 vfree(param);
1688 return r; 1710 return r;
1689} 1711}
1690 1712