aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/dm-ioctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/md/dm-ioctl.c')
-rw-r--r--drivers/md/dm-ioctl.c46
1 files changed, 31 insertions, 15 deletions
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index 6d12775a1061..4cacdad2270a 100644
--- a/drivers/md/dm-ioctl.c
+++ b/drivers/md/dm-ioctl.c
@@ -1501,14 +1501,10 @@ static int check_version(unsigned int cmd, struct dm_ioctl __user *user)
1501 return r; 1501 return r;
1502} 1502}
1503 1503
1504static void free_params(struct dm_ioctl *param)
1505{
1506 vfree(param);
1507}
1508
1509static int copy_params(struct dm_ioctl __user *user, struct dm_ioctl **param) 1504static int copy_params(struct dm_ioctl __user *user, struct dm_ioctl **param)
1510{ 1505{
1511 struct dm_ioctl tmp, *dmi; 1506 struct dm_ioctl tmp, *dmi;
1507 int secure_data;
1512 1508
1513 if (copy_from_user(&tmp, user, sizeof(tmp) - sizeof(tmp.data))) 1509 if (copy_from_user(&tmp, user, sizeof(tmp) - sizeof(tmp.data)))
1514 return -EFAULT; 1510 return -EFAULT;
@@ -1516,17 +1512,30 @@ static int copy_params(struct dm_ioctl __user *user, struct dm_ioctl **param)
1516 if (tmp.data_size < (sizeof(tmp) - sizeof(tmp.data))) 1512 if (tmp.data_size < (sizeof(tmp) - sizeof(tmp.data)))
1517 return -EINVAL; 1513 return -EINVAL;
1518 1514
1515 secure_data = tmp.flags & DM_SECURE_DATA_FLAG;
1516
1519 dmi = vmalloc(tmp.data_size); 1517 dmi = vmalloc(tmp.data_size);
1520 if (!dmi) 1518 if (!dmi) {
1519 if (secure_data && clear_user(user, tmp.data_size))
1520 return -EFAULT;
1521 return -ENOMEM; 1521 return -ENOMEM;
1522
1523 if (copy_from_user(dmi, user, tmp.data_size)) {
1524 vfree(dmi);
1525 return -EFAULT;
1526 } 1522 }
1527 1523
1524 if (copy_from_user(dmi, user, tmp.data_size))
1525 goto bad;
1526
1527 /* Wipe the user buffer so we do not return it to userspace */
1528 if (secure_data && clear_user(user, tmp.data_size))
1529 goto bad;
1530
1528 *param = dmi; 1531 *param = dmi;
1529 return 0; 1532 return 0;
1533
1534bad:
1535 if (secure_data)
1536 memset(dmi, 0, tmp.data_size);
1537 vfree(dmi);
1538 return -EFAULT;
1530} 1539}
1531 1540
1532static int validate_params(uint cmd, struct dm_ioctl *param) 1541static int validate_params(uint cmd, struct dm_ioctl *param)
@@ -1534,6 +1543,7 @@ static int validate_params(uint cmd, struct dm_ioctl *param)
1534 /* Always clear this flag */ 1543 /* Always clear this flag */
1535 param->flags &= ~DM_BUFFER_FULL_FLAG; 1544 param->flags &= ~DM_BUFFER_FULL_FLAG;
1536 param->flags &= ~DM_UEVENT_GENERATED_FLAG; 1545 param->flags &= ~DM_UEVENT_GENERATED_FLAG;
1546 param->flags &= ~DM_SECURE_DATA_FLAG;
1537 1547
1538 /* Ignores parameters */ 1548 /* Ignores parameters */
1539 if (cmd == DM_REMOVE_ALL_CMD || 1549 if (cmd == DM_REMOVE_ALL_CMD ||
@@ -1561,10 +1571,11 @@ static int validate_params(uint cmd, struct dm_ioctl *param)
1561static int ctl_ioctl(uint command, struct dm_ioctl __user *user) 1571static int ctl_ioctl(uint command, struct dm_ioctl __user *user)
1562{ 1572{
1563 int r = 0; 1573 int r = 0;
1574 int wipe_buffer;
1564 unsigned int cmd; 1575 unsigned int cmd;
1565 struct dm_ioctl *uninitialized_var(param); 1576 struct dm_ioctl *uninitialized_var(param);
1566 ioctl_fn fn = NULL; 1577 ioctl_fn fn = NULL;
1567 size_t param_size; 1578 size_t input_param_size;
1568 1579
1569 /* only root can play with this */ 1580 /* only root can play with this */
1570 if (!capable(CAP_SYS_ADMIN)) 1581 if (!capable(CAP_SYS_ADMIN))
@@ -1611,13 +1622,15 @@ static int ctl_ioctl(uint command, struct dm_ioctl __user *user)
1611 if (r) 1622 if (r)
1612 return r; 1623 return r;
1613 1624
1625 input_param_size = param->data_size;
1626 wipe_buffer = param->flags & DM_SECURE_DATA_FLAG;
1627
1614 r = validate_params(cmd, param); 1628 r = validate_params(cmd, param);
1615 if (r) 1629 if (r)
1616 goto out; 1630 goto out;
1617 1631
1618 param_size = param->data_size;
1619 param->data_size = sizeof(*param); 1632 param->data_size = sizeof(*param);
1620 r = fn(param, param_size); 1633 r = fn(param, input_param_size);
1621 1634
1622 /* 1635 /*
1623 * Copy the results back to userland. 1636 * Copy the results back to userland.
@@ -1625,8 +1638,11 @@ static int ctl_ioctl(uint command, struct dm_ioctl __user *user)
1625 if (!r && copy_to_user(user, param, param->data_size)) 1638 if (!r && copy_to_user(user, param, param->data_size))
1626 r = -EFAULT; 1639 r = -EFAULT;
1627 1640
1628 out: 1641out:
1629 free_params(param); 1642 if (wipe_buffer)
1643 memset(param, 0, input_param_size);
1644
1645 vfree(param);
1630 return r; 1646 return r;
1631} 1647}
1632 1648