Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 028b39e3 authored by Bart Van Assche's avatar Bart Van Assche Committed by Mike Snitzer
Browse files

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: default avatarBart Van Assche <bart.vanassche@sandisk.com>
Signed-off-by: default avatarMike Snitzer <snitzer@redhat.com>
parent 350b5393
Loading
Loading
Loading
Loading
+6 −12
Original line number Original line Diff line number Diff line
@@ -1670,8 +1670,7 @@ static int check_version(unsigned int cmd, struct dm_ioctl __user *user)
	return r;
	return r;
}
}


#define DM_PARAMS_KMALLOC	0x0001	/* Params alloced with kmalloc */
#define DM_PARAMS_MALLOC	0x0001	/* Params allocated with kvmalloc() */
#define DM_PARAMS_VMALLOC	0x0002	/* Params alloced with vmalloc */
#define DM_WIPE_BUFFER		0x0010	/* Wipe input buffer before returning from ioctl */
#define DM_WIPE_BUFFER		0x0010	/* Wipe input buffer before returning from ioctl */


static void free_params(struct dm_ioctl *param, size_t param_size, int param_flags)
static 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
	if (param_flags & DM_WIPE_BUFFER)
	if (param_flags & DM_WIPE_BUFFER)
		memset(param, 0, param_size);
		memset(param, 0, param_size);


	if (param_flags & DM_PARAMS_KMALLOC)
	if (param_flags & DM_PARAMS_MALLOC)
		kfree(param);
		kvfree(param);
	if (param_flags & DM_PARAMS_VMALLOC)
		vfree(param);
}
}


static int copy_params(struct dm_ioctl __user *user, struct dm_ioctl *param_kernel,
static 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
	 * Use kmalloc() rather than vmalloc() when we can.
	 * Use kmalloc() rather than vmalloc() when we can.
	 */
	 */
	dmi = NULL;
	dmi = NULL;
	if (param_kernel->data_size <= KMALLOC_MAX_SIZE) {
	if (param_kernel->data_size <= KMALLOC_MAX_SIZE)
		dmi = kmalloc(param_kernel->data_size, GFP_NOIO | __GFP_NORETRY | __GFP_NOMEMALLOC | __GFP_NOWARN);
		dmi = kmalloc(param_kernel->data_size, GFP_NOIO | __GFP_NORETRY | __GFP_NOMEMALLOC | __GFP_NOWARN);
		if (dmi)
			*param_flags |= DM_PARAMS_KMALLOC;
	}


	if (!dmi) {
	if (!dmi) {
		unsigned noio_flag;
		unsigned noio_flag;
		noio_flag = memalloc_noio_save();
		noio_flag = memalloc_noio_save();
		dmi = __vmalloc(param_kernel->data_size, GFP_NOIO | __GFP_HIGH | __GFP_HIGHMEM, PAGE_KERNEL);
		dmi = __vmalloc(param_kernel->data_size, GFP_NOIO | __GFP_HIGH | __GFP_HIGHMEM, PAGE_KERNEL);
		memalloc_noio_restore(noio_flag);
		memalloc_noio_restore(noio_flag);
		if (dmi)
			*param_flags |= DM_PARAMS_VMALLOC;
	}
	}


	if (!dmi) {
	if (!dmi) {
@@ -1735,6 +1727,8 @@ static int copy_params(struct dm_ioctl __user *user, struct dm_ioctl *param_kern
		return -ENOMEM;
		return -ENOMEM;
	}
	}


	*param_flags |= DM_PARAMS_MALLOC;

	if (copy_from_user(dmi, user, param_kernel->data_size))
	if (copy_from_user(dmi, user, param_kernel->data_size))
		goto bad;
		goto bad;