aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md
diff options
context:
space:
mode:
authorMilan Broz <mbroz@redhat.com>2011-03-24 09:54:30 -0400
committerAlasdair G Kergon <agk@redhat.com>2011-03-24 09:54:30 -0400
commitf868120549fc1664b2c451d4b9882a363928c698 (patch)
tree20d95a8f3b9fac1348bd42a5ff1e3f9d43918b93 /drivers/md
parent6bb43b5d1f54fb44c0408d86d5e71e4405a3ebe1 (diff)
dm ioctl: add flag to wipe buffers for secure data
Add DM_SECURE_DATA_FLAG which userspace can use to ensure that all buffers allocated for dm-ioctl are wiped immediately after use. The user buffer is wiped as well (we do not want to keep and return sensitive data back to userspace if the flag is set). Wiping is useful for cryptsetup to ensure that the key is present in memory only in defined places and only for the time needed. (For crypt, key can be present in table during load or table status, wait and message commands). Signed-off-by: Milan Broz <mbroz@redhat.com> Signed-off-by: Alasdair G Kergon <agk@redhat.com>
Diffstat (limited to 'drivers/md')
-rw-r--r--drivers/md/dm-ioctl.c23
1 files changed, 21 insertions, 2 deletions
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index 3a8f6a0e6eb5..4cacdad2270a 100644
--- a/drivers/md/dm-ioctl.c
+++ b/drivers/md/dm-ioctl.c
@@ -1504,6 +1504,7 @@ static int check_version(unsigned int cmd, struct dm_ioctl __user *user)
1504static 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)
1505{ 1505{
1506 struct dm_ioctl tmp, *dmi; 1506 struct dm_ioctl tmp, *dmi;
1507 int secure_data;
1507 1508
1508 if (copy_from_user(&tmp, user, sizeof(tmp) - sizeof(tmp.data))) 1509 if (copy_from_user(&tmp, user, sizeof(tmp) - sizeof(tmp.data)))
1509 return -EFAULT; 1510 return -EFAULT;
@@ -1511,17 +1512,28 @@ static int copy_params(struct dm_ioctl __user *user, struct dm_ioctl **param)
1511 if (tmp.data_size < (sizeof(tmp) - sizeof(tmp.data))) 1512 if (tmp.data_size < (sizeof(tmp) - sizeof(tmp.data)))
1512 return -EINVAL; 1513 return -EINVAL;
1513 1514
1515 secure_data = tmp.flags & DM_SECURE_DATA_FLAG;
1516
1514 dmi = vmalloc(tmp.data_size); 1517 dmi = vmalloc(tmp.data_size);
1515 if (!dmi) 1518 if (!dmi) {
1519 if (secure_data && clear_user(user, tmp.data_size))
1520 return -EFAULT;
1516 return -ENOMEM; 1521 return -ENOMEM;
1522 }
1517 1523
1518 if (copy_from_user(dmi, user, tmp.data_size)) 1524 if (copy_from_user(dmi, user, tmp.data_size))
1519 goto bad; 1525 goto bad;
1520 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
1521 *param = dmi; 1531 *param = dmi;
1522 return 0; 1532 return 0;
1523 1533
1524bad: 1534bad:
1535 if (secure_data)
1536 memset(dmi, 0, tmp.data_size);
1525 vfree(dmi); 1537 vfree(dmi);
1526 return -EFAULT; 1538 return -EFAULT;
1527} 1539}
@@ -1531,6 +1543,7 @@ static int validate_params(uint cmd, struct dm_ioctl *param)
1531 /* Always clear this flag */ 1543 /* Always clear this flag */
1532 param->flags &= ~DM_BUFFER_FULL_FLAG; 1544 param->flags &= ~DM_BUFFER_FULL_FLAG;
1533 param->flags &= ~DM_UEVENT_GENERATED_FLAG; 1545 param->flags &= ~DM_UEVENT_GENERATED_FLAG;
1546 param->flags &= ~DM_SECURE_DATA_FLAG;
1534 1547
1535 /* Ignores parameters */ 1548 /* Ignores parameters */
1536 if (cmd == DM_REMOVE_ALL_CMD || 1549 if (cmd == DM_REMOVE_ALL_CMD ||
@@ -1558,6 +1571,7 @@ static int validate_params(uint cmd, struct dm_ioctl *param)
1558static int ctl_ioctl(uint command, struct dm_ioctl __user *user) 1571static int ctl_ioctl(uint command, struct dm_ioctl __user *user)
1559{ 1572{
1560 int r = 0; 1573 int r = 0;
1574 int wipe_buffer;
1561 unsigned int cmd; 1575 unsigned int cmd;
1562 struct dm_ioctl *uninitialized_var(param); 1576 struct dm_ioctl *uninitialized_var(param);
1563 ioctl_fn fn = NULL; 1577 ioctl_fn fn = NULL;
@@ -1602,13 +1616,15 @@ static int ctl_ioctl(uint command, struct dm_ioctl __user *user)
1602 * Copy the parameters into kernel space. 1616 * Copy the parameters into kernel space.
1603 */ 1617 */
1604 r = copy_params(user, &param); 1618 r = copy_params(user, &param);
1605 input_param_size = param->data_size;
1606 1619
1607 current->flags &= ~PF_MEMALLOC; 1620 current->flags &= ~PF_MEMALLOC;
1608 1621
1609 if (r) 1622 if (r)
1610 return r; 1623 return r;
1611 1624
1625 input_param_size = param->data_size;
1626 wipe_buffer = param->flags & DM_SECURE_DATA_FLAG;
1627
1612 r = validate_params(cmd, param); 1628 r = validate_params(cmd, param);
1613 if (r) 1629 if (r)
1614 goto out; 1630 goto out;
@@ -1623,6 +1639,9 @@ static int ctl_ioctl(uint command, struct dm_ioctl __user *user)
1623 r = -EFAULT; 1639 r = -EFAULT;
1624 1640
1625out: 1641out:
1642 if (wipe_buffer)
1643 memset(param, 0, input_param_size);
1644
1626 vfree(param); 1645 vfree(param);
1627 return r; 1646 return r;
1628} 1647}