Commit 762a3af6 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Linus Torvalds

exec: open code copy_string_kernel

Currently copy_string_kernel is just a wrapper around copy_strings that
simplifies the calling conventions and uses set_fs to allow passing a
kernel pointer.  But due to the fact the we only need to handle a single
kernel argument pointer, the logic can be sigificantly simplified while
getting rid of the set_fs.
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Cc: Alexander Viro <viro@zeniv.linux.org.uk>
Link: http://lkml.kernel.org/r/20200501104105.2621149-3-hch@lst.deSigned-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 986db2d1
...@@ -592,17 +592,42 @@ static int copy_strings(int argc, struct user_arg_ptr argv, ...@@ -592,17 +592,42 @@ static int copy_strings(int argc, struct user_arg_ptr argv,
*/ */
int copy_string_kernel(const char *arg, struct linux_binprm *bprm) int copy_string_kernel(const char *arg, struct linux_binprm *bprm)
{ {
int r; int len = strnlen(arg, MAX_ARG_STRLEN) + 1 /* terminating NUL */;
mm_segment_t oldfs = get_fs(); unsigned long pos = bprm->p;
struct user_arg_ptr argv = {
.ptr.native = (const char __user *const __user *)&arg, if (len == 0)
}; return -EFAULT;
if (!valid_arg_len(bprm, len))
return -E2BIG;
/* We're going to work our way backwards. */
arg += len;
bprm->p -= len;
if (IS_ENABLED(CONFIG_MMU) && bprm->p < bprm->argmin)
return -E2BIG;
while (len > 0) {
unsigned int bytes_to_copy = min_t(unsigned int, len,
min_not_zero(offset_in_page(pos), PAGE_SIZE));
struct page *page;
char *kaddr;
set_fs(KERNEL_DS); pos -= bytes_to_copy;
r = copy_strings(1, argv, bprm); arg -= bytes_to_copy;
set_fs(oldfs); len -= bytes_to_copy;
return r; page = get_arg_page(bprm, pos, 1);
if (!page)
return -E2BIG;
kaddr = kmap_atomic(page);
flush_arg_page(bprm, pos & PAGE_MASK, page);
memcpy(kaddr + offset_in_page(pos), arg, bytes_to_copy);
flush_kernel_dcache_page(page);
kunmap_atomic(kaddr);
put_arg_page(page);
}
return 0;
} }
EXPORT_SYMBOL(copy_string_kernel); EXPORT_SYMBOL(copy_string_kernel);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment