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

Commit ba2d0162 authored by Oleg Nesterov's avatar Oleg Nesterov
Browse files

exec: introduce struct user_arg_ptr



No functional changes, preparation.

Introduce struct user_arg_ptr, change do_execve() paths to use it
instead of "char __user * const __user *argv".

This makes the argv/envp arguments opaque, we are ready to handle the
compat case which needs argv pointing to compat_uptr_t.

Suggested-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: default avatarOleg Nesterov <oleg@redhat.com>
Reviewed-by: default avatarKOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
Tested-by: default avatarKOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
parent 1d1dbf81
Loading
Loading
Loading
Loading
+30 −12
Original line number Original line Diff line number Diff line
@@ -398,12 +398,15 @@ err:
	return err;
	return err;
}
}


static const char __user *
struct user_arg_ptr {
get_user_arg_ptr(const char __user * const __user *argv, int nr)
	const char __user *const __user *native;
};

static const char __user *get_user_arg_ptr(struct user_arg_ptr argv, int nr)
{
{
	const char __user *ptr;
	const char __user *ptr;


	if (get_user(ptr, argv + nr))
	if (get_user(ptr, argv.native + nr))
		return ERR_PTR(-EFAULT);
		return ERR_PTR(-EFAULT);


	return ptr;
	return ptr;
@@ -412,11 +415,11 @@ get_user_arg_ptr(const char __user * const __user *argv, int nr)
/*
/*
 * count() counts the number of strings in array ARGV.
 * count() counts the number of strings in array ARGV.
 */
 */
static int count(const char __user * const __user * argv, int max)
static int count(struct user_arg_ptr argv, int max)
{
{
	int i = 0;
	int i = 0;


	if (argv != NULL) {
	if (argv.native != NULL) {
		for (;;) {
		for (;;) {
			const char __user *p = get_user_arg_ptr(argv, i);
			const char __user *p = get_user_arg_ptr(argv, i);


@@ -442,7 +445,7 @@ static int count(const char __user * const __user * argv, int max)
 * processes's memory to the new process's stack.  The call to get_user_pages()
 * processes's memory to the new process's stack.  The call to get_user_pages()
 * ensures the destination page is created and not swapped out.
 * ensures the destination page is created and not swapped out.
 */
 */
static int copy_strings(int argc, const char __user *const __user *argv,
static int copy_strings(int argc, struct user_arg_ptr argv,
			struct linux_binprm *bprm)
			struct linux_binprm *bprm)
{
{
	struct page *kmapped_page = NULL;
	struct page *kmapped_page = NULL;
@@ -533,14 +536,19 @@ out:
/*
/*
 * Like copy_strings, but get argv and its values from kernel memory.
 * Like copy_strings, but get argv and its values from kernel memory.
 */
 */
int copy_strings_kernel(int argc, const char *const *argv,
int copy_strings_kernel(int argc, const char *const *__argv,
			struct linux_binprm *bprm)
			struct linux_binprm *bprm)
{
{
	int r;
	int r;
	mm_segment_t oldfs = get_fs();
	mm_segment_t oldfs = get_fs();
	struct user_arg_ptr argv = {
		.native = (const char __user *const  __user *)__argv,
	};

	set_fs(KERNEL_DS);
	set_fs(KERNEL_DS);
	r = copy_strings(argc, (const char __user *const  __user *)argv, bprm);
	r = copy_strings(argc, argv, bprm);
	set_fs(oldfs);
	set_fs(oldfs);

	return r;
	return r;
}
}
EXPORT_SYMBOL(copy_strings_kernel);
EXPORT_SYMBOL(copy_strings_kernel);
@@ -1393,9 +1401,9 @@ EXPORT_SYMBOL(search_binary_handler);
/*
/*
 * sys_execve() executes a new program.
 * sys_execve() executes a new program.
 */
 */
int do_execve(const char * filename,
static int do_execve_common(const char *filename,
	const char __user *const __user *argv,
				struct user_arg_ptr argv,
	const char __user *const __user *envp,
				struct user_arg_ptr envp,
				struct pt_regs *regs)
				struct pt_regs *regs)
{
{
	struct linux_binprm *bprm;
	struct linux_binprm *bprm;
@@ -1503,6 +1511,16 @@ out_ret:
	return retval;
	return retval;
}
}


int do_execve(const char *filename,
	const char __user *const __user *__argv,
	const char __user *const __user *__envp,
	struct pt_regs *regs)
{
	struct user_arg_ptr argv = { .native = __argv };
	struct user_arg_ptr envp = { .native = __envp };
	return do_execve_common(filename, argv, envp, regs);
}

void set_binfmt(struct linux_binfmt *new)
void set_binfmt(struct linux_binfmt *new)
{
{
	struct mm_struct *mm = current->mm;
	struct mm_struct *mm = current->mm;