OSDN Git Service

ARM: tegra: Enable PLLP bypass during Tegra124 LP1
[sagit-ice-cold/kernel_xiaomi_msm8998.git] / fs / exec.c
index 3a6de10..bb70472 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -191,6 +191,7 @@ static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos,
 {
        struct page *page;
        int ret;
+       unsigned int gup_flags = FOLL_FORCE;
 
 #ifdef CONFIG_STACK_GROWSUP
        if (write) {
@@ -199,14 +200,35 @@ static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos,
                        return NULL;
        }
 #endif
-       ret = get_user_pages(current, bprm->mm, pos,
-                       1, write, 1, &page, NULL);
+
+       if (write)
+               gup_flags |= FOLL_WRITE;
+
+       ret = get_user_pages(current, bprm->mm, pos, 1, gup_flags,
+                       &page, NULL);
        if (ret <= 0)
                return NULL;
 
        if (write) {
                unsigned long size = bprm->vma->vm_end - bprm->vma->vm_start;
-               struct rlimit *rlim;
+               unsigned long ptr_size, limit;
+
+               /*
+                * Since the stack will hold pointers to the strings, we
+                * must account for them as well.
+                *
+                * The size calculation is the entire vma while each arg page is
+                * built, so each time we get here it's calculating how far it
+                * is currently (rather than each call being just the newly
+                * added size from the arg page).  As a result, we need to
+                * always add the entire size of the pointers, so that on the
+                * last call to get_arg_page() we'll actually have the entire
+                * correct size.
+                */
+               ptr_size = (bprm->argc + bprm->envc) * sizeof(void *);
+               if (ptr_size > ULONG_MAX - size)
+                       goto fail;
+               size += ptr_size;
 
                acct_arg_size(bprm, size / PAGE_SIZE);
 
@@ -218,20 +240,24 @@ static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos,
                        return page;
 
                /*
-                * Limit to 1/4-th the stack size for the argv+env strings.
+                * Limit to 1/4 of the max stack size or 3/4 of _STK_LIM
+                * (whichever is smaller) for the argv+env strings.
                 * This ensures that:
                 *  - the remaining binfmt code will not run out of stack space,
                 *  - the program will have a reasonable amount of stack left
                 *    to work from.
                 */
-               rlim = current->signal->rlim;
-               if (size > ACCESS_ONCE(rlim[RLIMIT_STACK].rlim_cur) / 4) {
-                       put_page(page);
-                       return NULL;
-               }
+               limit = _STK_LIM / 4 * 3;
+               limit = min(limit, rlimit(RLIMIT_STACK) / 4);
+               if (size > limit)
+                       goto fail;
        }
 
        return page;
+
+fail:
+       put_page(page);
+       return NULL;
 }
 
 static void put_arg_page(struct page *page)
@@ -1056,15 +1082,14 @@ killed:
        return -EAGAIN;
 }
 
-char *get_task_comm(char *buf, struct task_struct *tsk)
+char *__get_task_comm(char *buf, size_t buf_size, struct task_struct *tsk)
 {
-       /* buf must be at least sizeof(tsk->comm) in size */
        task_lock(tsk);
-       strncpy(buf, tsk->comm, sizeof(tsk->comm));
+       strncpy(buf, tsk->comm, buf_size);
        task_unlock(tsk);
        return buf;
 }
-EXPORT_SYMBOL_GPL(get_task_comm);
+EXPORT_SYMBOL_GPL(__get_task_comm);
 
 /*
  * These functions flushes out all traces of the currently running executable
@@ -1617,7 +1642,7 @@ static int do_execveat_common(int fd, struct filename *filename,
        current->fs->in_exec = 0;
        current->in_execve = 0;
        acct_update_integrals(current);
-       task_numa_free(current);
+       task_numa_free(current, false);
        free_bprm(bprm);
        kfree(pathbuf);
        putname(filename);