|
@@ -1306,241 +1306,6 @@ compat_sys_openat(unsigned int dfd, const char __user *filename, int flags, int
|
|
|
return do_sys_open(dfd, filename, flags, mode);
|
|
|
}
|
|
|
|
|
|
-/*
|
|
|
- * compat_count() counts the number of arguments/envelopes. It is basically
|
|
|
- * a copy of count() from fs/exec.c, except that it works with 32 bit argv
|
|
|
- * and envp pointers.
|
|
|
- */
|
|
|
-static int compat_count(compat_uptr_t __user *argv, int max)
|
|
|
-{
|
|
|
- int i = 0;
|
|
|
-
|
|
|
- if (argv != NULL) {
|
|
|
- for (;;) {
|
|
|
- compat_uptr_t p;
|
|
|
-
|
|
|
- if (get_user(p, argv))
|
|
|
- return -EFAULT;
|
|
|
- if (!p)
|
|
|
- break;
|
|
|
- argv++;
|
|
|
- if (i++ >= max)
|
|
|
- return -E2BIG;
|
|
|
-
|
|
|
- if (fatal_signal_pending(current))
|
|
|
- return -ERESTARTNOHAND;
|
|
|
- cond_resched();
|
|
|
- }
|
|
|
- }
|
|
|
- return i;
|
|
|
-}
|
|
|
-
|
|
|
-/*
|
|
|
- * compat_copy_strings() is basically a copy of copy_strings() from fs/exec.c
|
|
|
- * except that it works with 32 bit argv and envp pointers.
|
|
|
- */
|
|
|
-static int compat_copy_strings(int argc, compat_uptr_t __user *argv,
|
|
|
- struct linux_binprm *bprm)
|
|
|
-{
|
|
|
- struct page *kmapped_page = NULL;
|
|
|
- char *kaddr = NULL;
|
|
|
- unsigned long kpos = 0;
|
|
|
- int ret;
|
|
|
-
|
|
|
- while (argc-- > 0) {
|
|
|
- compat_uptr_t str;
|
|
|
- int len;
|
|
|
- unsigned long pos;
|
|
|
-
|
|
|
- if (get_user(str, argv+argc) ||
|
|
|
- !(len = strnlen_user(compat_ptr(str), MAX_ARG_STRLEN))) {
|
|
|
- ret = -EFAULT;
|
|
|
- goto out;
|
|
|
- }
|
|
|
-
|
|
|
- if (len > MAX_ARG_STRLEN) {
|
|
|
- ret = -E2BIG;
|
|
|
- goto out;
|
|
|
- }
|
|
|
-
|
|
|
- /* We're going to work our way backwords. */
|
|
|
- pos = bprm->p;
|
|
|
- str += len;
|
|
|
- bprm->p -= len;
|
|
|
-
|
|
|
- while (len > 0) {
|
|
|
- int offset, bytes_to_copy;
|
|
|
-
|
|
|
- if (fatal_signal_pending(current)) {
|
|
|
- ret = -ERESTARTNOHAND;
|
|
|
- goto out;
|
|
|
- }
|
|
|
- cond_resched();
|
|
|
-
|
|
|
- offset = pos % PAGE_SIZE;
|
|
|
- if (offset == 0)
|
|
|
- offset = PAGE_SIZE;
|
|
|
-
|
|
|
- bytes_to_copy = offset;
|
|
|
- if (bytes_to_copy > len)
|
|
|
- bytes_to_copy = len;
|
|
|
-
|
|
|
- offset -= bytes_to_copy;
|
|
|
- pos -= bytes_to_copy;
|
|
|
- str -= bytes_to_copy;
|
|
|
- len -= bytes_to_copy;
|
|
|
-
|
|
|
- if (!kmapped_page || kpos != (pos & PAGE_MASK)) {
|
|
|
- struct page *page;
|
|
|
-
|
|
|
- page = get_arg_page(bprm, pos, 1);
|
|
|
- if (!page) {
|
|
|
- ret = -E2BIG;
|
|
|
- goto out;
|
|
|
- }
|
|
|
-
|
|
|
- if (kmapped_page) {
|
|
|
- flush_kernel_dcache_page(kmapped_page);
|
|
|
- kunmap(kmapped_page);
|
|
|
- put_page(kmapped_page);
|
|
|
- }
|
|
|
- kmapped_page = page;
|
|
|
- kaddr = kmap(kmapped_page);
|
|
|
- kpos = pos & PAGE_MASK;
|
|
|
- flush_cache_page(bprm->vma, kpos,
|
|
|
- page_to_pfn(kmapped_page));
|
|
|
- }
|
|
|
- if (copy_from_user(kaddr+offset, compat_ptr(str),
|
|
|
- bytes_to_copy)) {
|
|
|
- ret = -EFAULT;
|
|
|
- goto out;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- ret = 0;
|
|
|
-out:
|
|
|
- if (kmapped_page) {
|
|
|
- flush_kernel_dcache_page(kmapped_page);
|
|
|
- kunmap(kmapped_page);
|
|
|
- put_page(kmapped_page);
|
|
|
- }
|
|
|
- return ret;
|
|
|
-}
|
|
|
-
|
|
|
-/*
|
|
|
- * compat_do_execve() is mostly a copy of do_execve(), with the exception
|
|
|
- * that it processes 32 bit argv and envp pointers.
|
|
|
- */
|
|
|
-int compat_do_execve(char * filename,
|
|
|
- compat_uptr_t __user *argv,
|
|
|
- compat_uptr_t __user *envp,
|
|
|
- struct pt_regs * regs)
|
|
|
-{
|
|
|
- struct linux_binprm *bprm;
|
|
|
- struct file *file;
|
|
|
- struct files_struct *displaced;
|
|
|
- bool clear_in_exec;
|
|
|
- int retval;
|
|
|
-
|
|
|
- retval = unshare_files(&displaced);
|
|
|
- if (retval)
|
|
|
- goto out_ret;
|
|
|
-
|
|
|
- retval = -ENOMEM;
|
|
|
- bprm = kzalloc(sizeof(*bprm), GFP_KERNEL);
|
|
|
- if (!bprm)
|
|
|
- goto out_files;
|
|
|
-
|
|
|
- retval = prepare_bprm_creds(bprm);
|
|
|
- if (retval)
|
|
|
- goto out_free;
|
|
|
-
|
|
|
- retval = check_unsafe_exec(bprm);
|
|
|
- if (retval < 0)
|
|
|
- goto out_free;
|
|
|
- clear_in_exec = retval;
|
|
|
- current->in_execve = 1;
|
|
|
-
|
|
|
- file = open_exec(filename);
|
|
|
- retval = PTR_ERR(file);
|
|
|
- if (IS_ERR(file))
|
|
|
- goto out_unmark;
|
|
|
-
|
|
|
- sched_exec();
|
|
|
-
|
|
|
- bprm->file = file;
|
|
|
- bprm->filename = filename;
|
|
|
- bprm->interp = filename;
|
|
|
-
|
|
|
- retval = bprm_mm_init(bprm);
|
|
|
- if (retval)
|
|
|
- goto out_file;
|
|
|
-
|
|
|
- bprm->argc = compat_count(argv, MAX_ARG_STRINGS);
|
|
|
- if ((retval = bprm->argc) < 0)
|
|
|
- goto out;
|
|
|
-
|
|
|
- bprm->envc = compat_count(envp, MAX_ARG_STRINGS);
|
|
|
- if ((retval = bprm->envc) < 0)
|
|
|
- goto out;
|
|
|
-
|
|
|
- retval = prepare_binprm(bprm);
|
|
|
- if (retval < 0)
|
|
|
- goto out;
|
|
|
-
|
|
|
- retval = copy_strings_kernel(1, &bprm->filename, bprm);
|
|
|
- if (retval < 0)
|
|
|
- goto out;
|
|
|
-
|
|
|
- bprm->exec = bprm->p;
|
|
|
- retval = compat_copy_strings(bprm->envc, envp, bprm);
|
|
|
- if (retval < 0)
|
|
|
- goto out;
|
|
|
-
|
|
|
- retval = compat_copy_strings(bprm->argc, argv, bprm);
|
|
|
- if (retval < 0)
|
|
|
- goto out;
|
|
|
-
|
|
|
- retval = search_binary_handler(bprm, regs);
|
|
|
- if (retval < 0)
|
|
|
- goto out;
|
|
|
-
|
|
|
- /* execve succeeded */
|
|
|
- current->fs->in_exec = 0;
|
|
|
- current->in_execve = 0;
|
|
|
- acct_update_integrals(current);
|
|
|
- free_bprm(bprm);
|
|
|
- if (displaced)
|
|
|
- put_files_struct(displaced);
|
|
|
- return retval;
|
|
|
-
|
|
|
-out:
|
|
|
- if (bprm->mm) {
|
|
|
- acct_arg_size(bprm, 0);
|
|
|
- mmput(bprm->mm);
|
|
|
- }
|
|
|
-
|
|
|
-out_file:
|
|
|
- if (bprm->file) {
|
|
|
- allow_write_access(bprm->file);
|
|
|
- fput(bprm->file);
|
|
|
- }
|
|
|
-
|
|
|
-out_unmark:
|
|
|
- if (clear_in_exec)
|
|
|
- current->fs->in_exec = 0;
|
|
|
- current->in_execve = 0;
|
|
|
-
|
|
|
-out_free:
|
|
|
- free_bprm(bprm);
|
|
|
-
|
|
|
-out_files:
|
|
|
- if (displaced)
|
|
|
- reset_files_struct(displaced);
|
|
|
-out_ret:
|
|
|
- return retval;
|
|
|
-}
|
|
|
-
|
|
|
#define __COMPAT_NFDBITS (8 * sizeof(compat_ulong_t))
|
|
|
|
|
|
static int poll_select_copy_remaining(struct timespec *end_time, void __user *p,
|