aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBart Van Assche <bart.vanassche@sandisk.com>2016-06-28 10:36:46 -0400
committerMike Snitzer <snitzer@redhat.com>2016-07-01 10:54:11 -0400
commit028b39e314dd8b4ab8d3ac401285db40ab1f39d8 (patch)
tree2166607510865429e81e9a7ad52062f9817a919d
parent350b53932810840a0c68467d7d78795010929940 (diff)
dm ioctl: Simplify parameter buffer management code
Merge the two DM_PARAMS_[KV]MALLOC flags into a single flag. Doing so avoids the crashes seen with previous attempts to consolidate buffer management to use kvfree() without first flagging that memory had actually been allocated. Signed-off-by: Bart Van Assche <bart.vanassche@sandisk.com> Signed-off-by: Mike Snitzer <snitzer@redhat.com>
-rw-r--r--drivers/md/dm-ioctl.c18
1 files changed, 6 insertions, 12 deletions
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index b59e34595ad8..96df89a31f42 100644
--- a/drivers/md/dm-ioctl.c
+++ b/drivers/md/dm-ioctl.c
@@ -1670,8 +1670,7 @@ static int check_version(unsigned int cmd, struct dm_ioctl __user *user)
1670 return r; 1670 return r;
1671} 1671}
1672 1672
1673#define DM_PARAMS_KMALLOC 0x0001 /* Params alloced with kmalloc */ 1673#define DM_PARAMS_MALLOC 0x0001 /* Params allocated with kvmalloc() */
1674#define DM_PARAMS_VMALLOC 0x0002 /* Params alloced with vmalloc */
1675#define DM_WIPE_BUFFER 0x0010 /* Wipe input buffer before returning from ioctl */ 1674#define DM_WIPE_BUFFER 0x0010 /* Wipe input buffer before returning from ioctl */
1676 1675
1677static void free_params(struct dm_ioctl *param, size_t param_size, int param_flags) 1676static void free_params(struct dm_ioctl *param, size_t param_size, int param_flags)
@@ -1679,10 +1678,8 @@ static void free_params(struct dm_ioctl *param, size_t param_size, int param_fla
1679 if (param_flags & DM_WIPE_BUFFER) 1678 if (param_flags & DM_WIPE_BUFFER)
1680 memset(param, 0, param_size); 1679 memset(param, 0, param_size);
1681 1680
1682 if (param_flags & DM_PARAMS_KMALLOC) 1681 if (param_flags & DM_PARAMS_MALLOC)
1683 kfree(param); 1682 kvfree(param);
1684 if (param_flags & DM_PARAMS_VMALLOC)
1685 vfree(param);
1686} 1683}
1687 1684
1688static int copy_params(struct dm_ioctl __user *user, struct dm_ioctl *param_kernel, 1685static int copy_params(struct dm_ioctl __user *user, struct dm_ioctl *param_kernel,
@@ -1714,19 +1711,14 @@ static int copy_params(struct dm_ioctl __user *user, struct dm_ioctl *param_kern
1714 * Use kmalloc() rather than vmalloc() when we can. 1711 * Use kmalloc() rather than vmalloc() when we can.
1715 */ 1712 */
1716 dmi = NULL; 1713 dmi = NULL;
1717 if (param_kernel->data_size <= KMALLOC_MAX_SIZE) { 1714 if (param_kernel->data_size <= KMALLOC_MAX_SIZE)
1718 dmi = kmalloc(param_kernel->data_size, GFP_NOIO | __GFP_NORETRY | __GFP_NOMEMALLOC | __GFP_NOWARN); 1715 dmi = kmalloc(param_kernel->data_size, GFP_NOIO | __GFP_NORETRY | __GFP_NOMEMALLOC | __GFP_NOWARN);
1719 if (dmi)
1720 *param_flags |= DM_PARAMS_KMALLOC;
1721 }
1722 1716
1723 if (!dmi) { 1717 if (!dmi) {
1724 unsigned noio_flag; 1718 unsigned noio_flag;
1725 noio_flag = memalloc_noio_save(); 1719 noio_flag = memalloc_noio_save();
1726 dmi = __vmalloc(param_kernel->data_size, GFP_NOIO | __GFP_HIGH | __GFP_HIGHMEM, PAGE_KERNEL); 1720 dmi = __vmalloc(param_kernel->data_size, GFP_NOIO | __GFP_HIGH | __GFP_HIGHMEM, PAGE_KERNEL);
1727 memalloc_noio_restore(noio_flag); 1721 memalloc_noio_restore(noio_flag);
1728 if (dmi)
1729 *param_flags |= DM_PARAMS_VMALLOC;
1730 } 1722 }
1731 1723
1732 if (!dmi) { 1724 if (!dmi) {
@@ -1735,6 +1727,8 @@ static int copy_params(struct dm_ioctl __user *user, struct dm_ioctl *param_kern
1735 return -ENOMEM; 1727 return -ENOMEM;
1736 } 1728 }
1737 1729
1730 *param_flags |= DM_PARAMS_MALLOC;
1731
1738 if (copy_from_user(dmi, user, param_kernel->data_size)) 1732 if (copy_from_user(dmi, user, param_kernel->data_size))
1739 goto bad; 1733 goto bad;
1740 1734