VisionFive2 Linux kernel

StarFive Tech Linux Kernel for VisionFive (JH7110) boards (mirror)

More than 9999 Commits   35 Branches   59 Tags
457c899653991 (Thomas Gleixner             2019-05-19 13:08:55 +0100    1) // SPDX-License-Identifier: GPL-2.0-only
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700    2) /*
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700    3)  *  linux/fs/exec.c
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700    4)  *
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700    5)  *  Copyright (C) 1991, 1992  Linus Torvalds
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700    6)  */
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700    7) 
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700    8) /*
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700    9)  * #!-checking implemented by tytso.
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700   10)  */
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700   11) /*
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700   12)  * Demand-loading implemented 01.12.91 - no need to read anything but
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700   13)  * the header into memory. The inode of the executable is put into
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700   14)  * "current->executable", and page faults do the actual loading. Clean.
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700   15)  *
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700   16)  * Once more I can proudly say that linux stood up to being changed: it
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700   17)  * was less than 2 hours work to get demand-loading completely implemented.
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700   18)  *
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700   19)  * Demand loading changed July 1993 by Eric Youngdale.   Use mmap instead,
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700   20)  * current->executable is only used by the procfs.  This allows a dispatch
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700   21)  * table to check for several different types  of binary formats.  We keep
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700   22)  * trying until we recognize the file or we run out of supported binary
613cc2b6f272c (Aleksa Sarai                2016-12-21 16:26:24 +1100   23)  * formats.
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700   24)  */
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700   25) 
b89999d004931 (Scott Branden               2020-10-02 10:38:15 -0700   26) #include <linux/kernel_read_file.h>
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700   27) #include <linux/slab.h>
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700   28) #include <linux/file.h>
9f3acc3140444 (Al Viro                     2008-04-24 07:44:08 -0400   29) #include <linux/fdtable.h>
ba92a43dbaee3 (Hugh Dickins                2008-07-25 01:45:43 -0700   30) #include <linux/mm.h>
615d6e8756c87 (Davidlohr Bueso             2014-04-07 15:37:25 -0700   31) #include <linux/vmacache.h>
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700   32) #include <linux/stat.h>
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700   33) #include <linux/fcntl.h>
ba92a43dbaee3 (Hugh Dickins                2008-07-25 01:45:43 -0700   34) #include <linux/swap.h>
74aadce986052 (Neil Horman                 2007-10-16 23:26:35 -0700   35) #include <linux/string.h>
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700   36) #include <linux/init.h>
6e84f31522f93 (Ingo Molnar                 2017-02-08 18:51:29 +0100   37) #include <linux/sched/mm.h>
f7ccbae45c5e2 (Ingo Molnar                 2017-02-08 18:51:30 +0100   38) #include <linux/sched/coredump.h>
3f07c0144132e (Ingo Molnar                 2017-02-08 18:51:30 +0100   39) #include <linux/sched/signal.h>
6a3827d7509cb (Ingo Molnar                 2017-02-08 18:51:31 +0100   40) #include <linux/sched/numa_balancing.h>
299300258d1bc (Ingo Molnar                 2017-02-08 18:51:36 +0100   41) #include <linux/sched/task.h>
ca5b172bd2b2f (Hugh Dickins                2008-07-28 15:46:18 -0700   42) #include <linux/pagemap.h>
cdd6c482c9ff9 (Ingo Molnar                 2009-09-21 12:02:48 +0200   43) #include <linux/perf_event.h>
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700   44) #include <linux/highmem.h>
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700   45) #include <linux/spinlock.h>
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700   46) #include <linux/key.h>
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700   47) #include <linux/personality.h>
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700   48) #include <linux/binfmts.h>
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700   49) #include <linux/utsname.h>
84d737866e2ba (Sukadev Bhattiprolu         2006-12-08 02:38:01 -0800   50) #include <linux/pid_namespace.h>
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700   51) #include <linux/module.h>
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700   52) #include <linux/namei.h>
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700   53) #include <linux/mount.h>
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700   54) #include <linux/security.h>
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700   55) #include <linux/syscalls.h>
8f0ab51479512 (Jay Lan                     2006-09-30 23:28:59 -0700   56) #include <linux/tsacct_kern.h>
9f46080c41d5f (Matt Helsley                2005-11-07 00:59:16 -0800   57) #include <linux/cn_proc.h>
473ae30bc7b1d (Al Viro                     2006-04-26 14:04:08 -0400   58) #include <linux/audit.h>
6341c393fcc37 (Roland McGrath              2008-07-25 19:45:44 -0700   59) #include <linux/tracehook.h>
5f4123be3cdb1 (Johannes Berg               2008-07-09 10:28:40 +0200   60) #include <linux/kmod.h>
6110e3abbff8b (Eric Paris                  2008-12-17 13:53:20 -0500   61) #include <linux/fsnotify.h>
5ad4e53bd5406 (Al Viro                     2009-03-29 19:50:06 -0400   62) #include <linux/fs_struct.h>
3d5992d2ac7dc (Ying Han                    2010-10-26 14:21:23 -0700   63) #include <linux/oom.h>
0e028465d18b7 (Oleg Nesterov               2011-03-06 18:02:54 +0100   64) #include <linux/compat.h>
b44a7dfc6fa16 (Mimi Zohar                  2015-12-28 16:02:29 -0500   65) #include <linux/vmalloc.h>
0f2122045b946 (Jens Axboe                  2020-09-13 13:09:39 -0600   66) #include <linux/io_uring.h>
1446e1df9eb18 (Gabriel Krisman Bertazi     2020-11-27 14:32:34 -0500   67) #include <linux/syscall_user_dispatch.h>
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700   68) 
7c0f6ba682b9c (Linus Torvalds              2016-12-24 11:46:01 -0800   69) #include <linux/uaccess.h>
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700   70) #include <asm/mmu_context.h>
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700   71) #include <asm/tlb.h>
43d2b113241d6 (KAMEZAWA Hiroyuki           2012-01-10 15:08:09 -0800   72) 
43d2b113241d6 (KAMEZAWA Hiroyuki           2012-01-10 15:08:09 -0800   73) #include <trace/events/task.h>
a6f76f23d297f (David Howells               2008-11-14 10:39:24 +1100   74) #include "internal.h"
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700   75) 
4ff16c25e2cc4 (David Smith                 2012-02-07 10:11:05 -0600   76) #include <trace/events/sched.h>
4ff16c25e2cc4 (David Smith                 2012-02-07 10:11:05 -0600   77) 
56305aa9b6fab (Eric W. Biederman           2020-05-29 22:00:54 -0500   78) static int bprm_creds_from_file(struct linux_binprm *bprm);
56305aa9b6fab (Eric W. Biederman           2020-05-29 22:00:54 -0500   79) 
d6e711448137c (Alan Cox                    2005-06-23 00:09:43 -0700   80) int suid_dumpable = 0;
d6e711448137c (Alan Cox                    2005-06-23 00:09:43 -0700   81) 
e4dc1b14d8dc5 (Alexey Dobriyan             2007-10-16 23:26:03 -0700   82) static LIST_HEAD(formats);
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700   83) static DEFINE_RWLOCK(binfmt_lock);
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700   84) 
8fc3dc5a3a17a (Al Viro                     2012-03-17 03:05:16 -0400   85) void __register_binfmt(struct linux_binfmt * fmt, int insert)
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700   86) {
8fc3dc5a3a17a (Al Viro                     2012-03-17 03:05:16 -0400   87) 	BUG_ON(!fmt);
92eaa565add62 (Oleg Nesterov               2013-09-11 14:24:42 -0700   88) 	if (WARN_ON(!fmt->load_binary))
92eaa565add62 (Oleg Nesterov               2013-09-11 14:24:42 -0700   89) 		return;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700   90) 	write_lock(&binfmt_lock);
74641f584da8e (Ivan Kokshaysky             2009-04-30 15:08:49 -0700   91) 	insert ? list_add(&fmt->lh, &formats) :
74641f584da8e (Ivan Kokshaysky             2009-04-30 15:08:49 -0700   92) 		 list_add_tail(&fmt->lh, &formats);
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700   93) 	write_unlock(&binfmt_lock);
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700   94) }
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700   95) 
74641f584da8e (Ivan Kokshaysky             2009-04-30 15:08:49 -0700   96) EXPORT_SYMBOL(__register_binfmt);
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700   97) 
f6b450d489f2f (Alexey Dobriyan             2007-10-16 23:26:04 -0700   98) void unregister_binfmt(struct linux_binfmt * fmt)
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700   99) {
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  100) 	write_lock(&binfmt_lock);
e4dc1b14d8dc5 (Alexey Dobriyan             2007-10-16 23:26:03 -0700  101) 	list_del(&fmt->lh);
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  102) 	write_unlock(&binfmt_lock);
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  103) }
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  104) 
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  105) EXPORT_SYMBOL(unregister_binfmt);
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  106) 
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  107) static inline void put_binfmt(struct linux_binfmt * fmt)
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  108) {
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  109) 	module_put(fmt->module);
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  110) }
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  111) 
90f8572b0f021 (Eric W. Biederman           2015-06-29 14:42:03 -0500  112) bool path_noexec(const struct path *path)
90f8572b0f021 (Eric W. Biederman           2015-06-29 14:42:03 -0500  113) {
90f8572b0f021 (Eric W. Biederman           2015-06-29 14:42:03 -0500  114) 	return (path->mnt->mnt_flags & MNT_NOEXEC) ||
90f8572b0f021 (Eric W. Biederman           2015-06-29 14:42:03 -0500  115) 	       (path->mnt->mnt_sb->s_iflags & SB_I_NOEXEC);
90f8572b0f021 (Eric W. Biederman           2015-06-29 14:42:03 -0500  116) }
90f8572b0f021 (Eric W. Biederman           2015-06-29 14:42:03 -0500  117) 
69369a7003735 (Josh Triplett               2014-04-03 14:48:27 -0700  118) #ifdef CONFIG_USELIB
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  119) /*
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  120)  * Note that a shared library must be both readable and executable due to
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  121)  * security reasons.
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  122)  *
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  123)  * Also note that we take the address to load from from the file itself.
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  124)  */
1e7bfb2134dfe (Heiko Carstens              2009-01-14 14:14:29 +0100  125) SYSCALL_DEFINE1(uselib, const char __user *, library)
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  126) {
72c2d53192004 (Al Viro                     2013-09-22 16:27:52 -0400  127) 	struct linux_binfmt *fmt;
964bd183624c0 (Al Viro                     2008-07-26 03:33:14 -0400  128) 	struct file *file;
91a27b2a75678 (Jeff Layton                 2012-10-10 15:25:28 -0400  129) 	struct filename *tmp = getname(library);
964bd183624c0 (Al Viro                     2008-07-26 03:33:14 -0400  130) 	int error = PTR_ERR(tmp);
47c805dc2d2df (Al Viro                     2011-02-23 17:44:09 -0500  131) 	static const struct open_flags uselib_flags = {
47c805dc2d2df (Al Viro                     2011-02-23 17:44:09 -0500  132) 		.open_flag = O_LARGEFILE | O_RDONLY | __FMODE_EXEC,
62fb4a155f745 (Al Viro                     2015-12-26 22:33:24 -0500  133) 		.acc_mode = MAY_READ | MAY_EXEC,
f9652e10c12b4 (Al Viro                     2013-06-11 08:23:01 +0400  134) 		.intent = LOOKUP_OPEN,
f9652e10c12b4 (Al Viro                     2013-06-11 08:23:01 +0400  135) 		.lookup_flags = LOOKUP_FOLLOW,
47c805dc2d2df (Al Viro                     2011-02-23 17:44:09 -0500  136) 	};
964bd183624c0 (Al Viro                     2008-07-26 03:33:14 -0400  137) 
6e8341a11eb21 (Al Viro                     2009-04-06 11:16:22 -0400  138) 	if (IS_ERR(tmp))
6e8341a11eb21 (Al Viro                     2009-04-06 11:16:22 -0400  139) 		goto out;
6e8341a11eb21 (Al Viro                     2009-04-06 11:16:22 -0400  140) 
f9652e10c12b4 (Al Viro                     2013-06-11 08:23:01 +0400  141) 	file = do_filp_open(AT_FDCWD, tmp, &uselib_flags);
6e8341a11eb21 (Al Viro                     2009-04-06 11:16:22 -0400  142) 	putname(tmp);
6e8341a11eb21 (Al Viro                     2009-04-06 11:16:22 -0400  143) 	error = PTR_ERR(file);
6e8341a11eb21 (Al Viro                     2009-04-06 11:16:22 -0400  144) 	if (IS_ERR(file))
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  145) 		goto out;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  146) 
633fb6ac39801 (Kees Cook                   2020-08-11 18:36:26 -0700  147) 	/*
633fb6ac39801 (Kees Cook                   2020-08-11 18:36:26 -0700  148) 	 * may_open() has already checked for this, so it should be
633fb6ac39801 (Kees Cook                   2020-08-11 18:36:26 -0700  149) 	 * impossible to trip now. But we need to be extra cautious
633fb6ac39801 (Kees Cook                   2020-08-11 18:36:26 -0700  150) 	 * and check again at the very end too.
633fb6ac39801 (Kees Cook                   2020-08-11 18:36:26 -0700  151) 	 */
db19c91c3b75c (Kees Cook                   2020-08-11 18:36:23 -0700  152) 	error = -EACCES;
0fd338b2d2cdf (Kees Cook                   2020-08-11 18:36:30 -0700  153) 	if (WARN_ON_ONCE(!S_ISREG(file_inode(file)->i_mode) ||
0fd338b2d2cdf (Kees Cook                   2020-08-11 18:36:30 -0700  154) 			 path_noexec(&file->f_path)))
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  155) 		goto exit;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  156) 
2a12a9d781463 (Eric Paris                  2009-12-17 21:24:21 -0500  157) 	fsnotify_open(file);
6110e3abbff8b (Eric Paris                  2008-12-17 13:53:20 -0500  158) 
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  159) 	error = -ENOEXEC;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  160) 
72c2d53192004 (Al Viro                     2013-09-22 16:27:52 -0400  161) 	read_lock(&binfmt_lock);
72c2d53192004 (Al Viro                     2013-09-22 16:27:52 -0400  162) 	list_for_each_entry(fmt, &formats, lh) {
72c2d53192004 (Al Viro                     2013-09-22 16:27:52 -0400  163) 		if (!fmt->load_shlib)
72c2d53192004 (Al Viro                     2013-09-22 16:27:52 -0400  164) 			continue;
72c2d53192004 (Al Viro                     2013-09-22 16:27:52 -0400  165) 		if (!try_module_get(fmt->module))
72c2d53192004 (Al Viro                     2013-09-22 16:27:52 -0400  166) 			continue;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  167) 		read_unlock(&binfmt_lock);
72c2d53192004 (Al Viro                     2013-09-22 16:27:52 -0400  168) 		error = fmt->load_shlib(file);
72c2d53192004 (Al Viro                     2013-09-22 16:27:52 -0400  169) 		read_lock(&binfmt_lock);
72c2d53192004 (Al Viro                     2013-09-22 16:27:52 -0400  170) 		put_binfmt(fmt);
72c2d53192004 (Al Viro                     2013-09-22 16:27:52 -0400  171) 		if (error != -ENOEXEC)
72c2d53192004 (Al Viro                     2013-09-22 16:27:52 -0400  172) 			break;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  173) 	}
72c2d53192004 (Al Viro                     2013-09-22 16:27:52 -0400  174) 	read_unlock(&binfmt_lock);
6e8341a11eb21 (Al Viro                     2009-04-06 11:16:22 -0400  175) exit:
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  176) 	fput(file);
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  177) out:
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  178)   	return error;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  179) }
69369a7003735 (Josh Triplett               2014-04-03 14:48:27 -0700  180) #endif /* #ifdef CONFIG_USELIB */
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  181) 
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  182) #ifdef CONFIG_MMU
ae6b585eeb746 (Oleg Nesterov               2011-03-06 18:03:11 +0100  183) /*
ae6b585eeb746 (Oleg Nesterov               2011-03-06 18:03:11 +0100  184)  * The nascent bprm->mm is not visible until exec_mmap() but it can
ae6b585eeb746 (Oleg Nesterov               2011-03-06 18:03:11 +0100  185)  * use a lot of memory, account these pages in current->mm temporary
ae6b585eeb746 (Oleg Nesterov               2011-03-06 18:03:11 +0100  186)  * for oom_badness()->get_mm_rss(). Once exec succeeds or fails, we
ae6b585eeb746 (Oleg Nesterov               2011-03-06 18:03:11 +0100  187)  * change the counter back via acct_arg_size(0).
ae6b585eeb746 (Oleg Nesterov               2011-03-06 18:03:11 +0100  188)  */
0e028465d18b7 (Oleg Nesterov               2011-03-06 18:02:54 +0100  189) static void acct_arg_size(struct linux_binprm *bprm, unsigned long pages)
3c77f84572215 (Oleg Nesterov               2010-11-30 20:55:34 +0100  190) {
3c77f84572215 (Oleg Nesterov               2010-11-30 20:55:34 +0100  191) 	struct mm_struct *mm = current->mm;
3c77f84572215 (Oleg Nesterov               2010-11-30 20:55:34 +0100  192) 	long diff = (long)(pages - bprm->vma_pages);
3c77f84572215 (Oleg Nesterov               2010-11-30 20:55:34 +0100  193) 
3c77f84572215 (Oleg Nesterov               2010-11-30 20:55:34 +0100  194) 	if (!mm || !diff)
3c77f84572215 (Oleg Nesterov               2010-11-30 20:55:34 +0100  195) 		return;
3c77f84572215 (Oleg Nesterov               2010-11-30 20:55:34 +0100  196) 
3c77f84572215 (Oleg Nesterov               2010-11-30 20:55:34 +0100  197) 	bprm->vma_pages = pages;
3c77f84572215 (Oleg Nesterov               2010-11-30 20:55:34 +0100  198) 	add_mm_counter(mm, MM_ANONPAGES, diff);
3c77f84572215 (Oleg Nesterov               2010-11-30 20:55:34 +0100  199) }
3c77f84572215 (Oleg Nesterov               2010-11-30 20:55:34 +0100  200) 
0e028465d18b7 (Oleg Nesterov               2011-03-06 18:02:54 +0100  201) static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos,
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  202) 		int write)
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  203) {
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  204) 	struct page *page;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  205) 	int ret;
9beae1ea89305 (Lorenzo Stoakes             2016-10-13 01:20:17 +0100  206) 	unsigned int gup_flags = FOLL_FORCE;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  207) 
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  208) #ifdef CONFIG_STACK_GROWSUP
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  209) 	if (write) {
d05f3169c0fbc (Michal Hocko                2011-05-24 17:11:44 -0700  210) 		ret = expand_downwards(bprm->vma, pos);
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  211) 		if (ret < 0)
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  212) 			return NULL;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  213) 	}
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  214) #endif
9beae1ea89305 (Lorenzo Stoakes             2016-10-13 01:20:17 +0100  215) 
9beae1ea89305 (Lorenzo Stoakes             2016-10-13 01:20:17 +0100  216) 	if (write)
9beae1ea89305 (Lorenzo Stoakes             2016-10-13 01:20:17 +0100  217) 		gup_flags |= FOLL_WRITE;
9beae1ea89305 (Lorenzo Stoakes             2016-10-13 01:20:17 +0100  218) 
1e9877902dc7e (Dave Hansen                 2016-02-12 13:01:54 -0800  219) 	/*
1e9877902dc7e (Dave Hansen                 2016-02-12 13:01:54 -0800  220) 	 * We are doing an exec().  'current' is the process
1e9877902dc7e (Dave Hansen                 2016-02-12 13:01:54 -0800  221) 	 * doing the exec and bprm->mm is the new process's mm.
1e9877902dc7e (Dave Hansen                 2016-02-12 13:01:54 -0800  222) 	 */
64019a2e467a2 (Peter Xu                    2020-08-11 18:39:01 -0700  223) 	ret = get_user_pages_remote(bprm->mm, pos, 1, gup_flags,
5b56d49fc31db (Lorenzo Stoakes             2016-12-14 15:06:52 -0800  224) 			&page, NULL, NULL);
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  225) 	if (ret <= 0)
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  226) 		return NULL;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  227) 
655c16a8ce9c1 (Oleg Nesterov               2019-01-03 15:28:11 -0800  228) 	if (write)
655c16a8ce9c1 (Oleg Nesterov               2019-01-03 15:28:11 -0800  229) 		acct_arg_size(bprm, vma_pages(bprm->vma));
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  230) 
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  231) 	return page;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  232) }
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  233) 
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  234) static void put_arg_page(struct page *page)
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  235) {
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  236) 	put_page(page);
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  237) }
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  238) 
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  239) static void free_arg_pages(struct linux_binprm *bprm)
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  240) {
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  241) }
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  242) 
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  243) static void flush_arg_page(struct linux_binprm *bprm, unsigned long pos,
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  244) 		struct page *page)
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  245) {
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  246) 	flush_cache_page(bprm->vma, pos, page_to_pfn(page));
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  247) }
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  248) 
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  249) static int __bprm_mm_init(struct linux_binprm *bprm)
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  250) {
eaccbfa564e48 (Luiz Fernando N. Capitulino 2009-01-06 14:40:44 -0800  251) 	int err;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  252) 	struct vm_area_struct *vma = NULL;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  253) 	struct mm_struct *mm = bprm->mm;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  254) 
490fc053865c9 (Linus Torvalds              2018-07-21 15:24:03 -0700  255) 	bprm->vma = vma = vm_area_alloc(mm);
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  256) 	if (!vma)
eaccbfa564e48 (Luiz Fernando N. Capitulino 2009-01-06 14:40:44 -0800  257) 		return -ENOMEM;
bfd40eaff5abb (Kirill A. Shutemov          2018-07-26 16:37:35 -0700  258) 	vma_set_anonymous(vma);
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  259) 
d8ed45c5dcd45 (Michel Lespinasse           2020-06-08 21:33:25 -0700  260) 	if (mmap_write_lock_killable(mm)) {
f268dfe905d46 (Michal Hocko                2016-05-23 16:26:02 -0700  261) 		err = -EINTR;
f268dfe905d46 (Michal Hocko                2016-05-23 16:26:02 -0700  262) 		goto err_free;
f268dfe905d46 (Michal Hocko                2016-05-23 16:26:02 -0700  263) 	}
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  264) 
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  265) 	/*
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  266) 	 * Place the stack at the largest stack address the architecture
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  267) 	 * supports. Later, we'll move this to an appropriate place. We don't
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  268) 	 * use STACK_TOP because that can depend on attributes which aren't
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  269) 	 * configured yet.
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  270) 	 */
aacb3d17a73f6 (Michal Hocko                2011-07-26 16:08:40 -0700  271) 	BUILD_BUG_ON(VM_STACK_FLAGS & VM_STACK_INCOMPLETE_SETUP);
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  272) 	vma->vm_end = STACK_TOP_MAX;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  273) 	vma->vm_start = vma->vm_end - PAGE_SIZE;
d9104d1ca9662 (Cyrill Gorcunov             2013-09-11 14:22:24 -0700  274) 	vma->vm_flags = VM_SOFTDIRTY | VM_STACK_FLAGS | VM_STACK_INCOMPLETE_SETUP;
3ed75eb8f1cd8 (Coly Li                     2007-10-18 23:39:15 -0700  275) 	vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
462e635e5b73b (Tavis Ormandy               2010-12-09 15:29:42 +0100  276) 
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  277) 	err = insert_vm_struct(mm, vma);
eaccbfa564e48 (Luiz Fernando N. Capitulino 2009-01-06 14:40:44 -0800  278) 	if (err)
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  279) 		goto err;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  280) 
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  281) 	mm->stack_vm = mm->total_vm = 1;
d8ed45c5dcd45 (Michel Lespinasse           2020-06-08 21:33:25 -0700  282) 	mmap_write_unlock(mm);
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  283) 	bprm->p = vma->vm_end - sizeof(void *);
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  284) 	return 0;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  285) err:
d8ed45c5dcd45 (Michel Lespinasse           2020-06-08 21:33:25 -0700  286) 	mmap_write_unlock(mm);
f268dfe905d46 (Michal Hocko                2016-05-23 16:26:02 -0700  287) err_free:
eaccbfa564e48 (Luiz Fernando N. Capitulino 2009-01-06 14:40:44 -0800  288) 	bprm->vma = NULL;
3928d4f5ee37c (Linus Torvalds              2018-07-21 13:48:51 -0700  289) 	vm_area_free(vma);
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  290) 	return err;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  291) }
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  292) 
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  293) static bool valid_arg_len(struct linux_binprm *bprm, long len)
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  294) {
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  295) 	return len <= MAX_ARG_STRLEN;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  296) }
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  297) 
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  298) #else
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  299) 
0e028465d18b7 (Oleg Nesterov               2011-03-06 18:02:54 +0100  300) static inline void acct_arg_size(struct linux_binprm *bprm, unsigned long pages)
3c77f84572215 (Oleg Nesterov               2010-11-30 20:55:34 +0100  301) {
3c77f84572215 (Oleg Nesterov               2010-11-30 20:55:34 +0100  302) }
3c77f84572215 (Oleg Nesterov               2010-11-30 20:55:34 +0100  303) 
0e028465d18b7 (Oleg Nesterov               2011-03-06 18:02:54 +0100  304) static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos,
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  305) 		int write)
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  306) {
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  307) 	struct page *page;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  308) 
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  309) 	page = bprm->page[pos / PAGE_SIZE];
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  310) 	if (!page && write) {
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  311) 		page = alloc_page(GFP_HIGHUSER|__GFP_ZERO);
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  312) 		if (!page)
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  313) 			return NULL;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  314) 		bprm->page[pos / PAGE_SIZE] = page;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  315) 	}
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  316) 
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  317) 	return page;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  318) }
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  319) 
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  320) static void put_arg_page(struct page *page)
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  321) {
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  322) }
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  323) 
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  324) static void free_arg_page(struct linux_binprm *bprm, int i)
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  325) {
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  326) 	if (bprm->page[i]) {
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  327) 		__free_page(bprm->page[i]);
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  328) 		bprm->page[i] = NULL;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  329) 	}
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  330) }
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  331) 
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  332) static void free_arg_pages(struct linux_binprm *bprm)
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  333) {
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  334) 	int i;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  335) 
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  336) 	for (i = 0; i < MAX_ARG_PAGES; i++)
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  337) 		free_arg_page(bprm, i);
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  338) }
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  339) 
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  340) static void flush_arg_page(struct linux_binprm *bprm, unsigned long pos,
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  341) 		struct page *page)
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  342) {
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  343) }
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  344) 
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  345) static int __bprm_mm_init(struct linux_binprm *bprm)
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  346) {
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  347) 	bprm->p = PAGE_SIZE * MAX_ARG_PAGES - sizeof(void *);
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  348) 	return 0;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  349) }
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  350) 
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  351) static bool valid_arg_len(struct linux_binprm *bprm, long len)
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  352) {
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  353) 	return len <= bprm->p;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  354) }
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  355) 
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  356) #endif /* CONFIG_MMU */
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  357) 
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  358) /*
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  359)  * Create a new mm_struct and populate it with a temporary stack
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  360)  * vm_area_struct.  We don't have enough context at this point to set the stack
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  361)  * flags, permissions, and offset, so we use temporary values.  We'll update
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  362)  * them later in setup_arg_pages().
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  363)  */
9cc64ceaa8b8e (Yuanhan Liu                 2013-02-20 13:16:01 +1100  364) static int bprm_mm_init(struct linux_binprm *bprm)
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  365) {
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  366) 	int err;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  367) 	struct mm_struct *mm = NULL;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  368) 
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  369) 	bprm->mm = mm = mm_alloc();
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  370) 	err = -ENOMEM;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  371) 	if (!mm)
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  372) 		goto err;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  373) 
c31dbb146dd44 (Kees Cook                   2018-04-10 16:35:01 -0700  374) 	/* Save current stack limit for all calculations made during exec. */
c31dbb146dd44 (Kees Cook                   2018-04-10 16:35:01 -0700  375) 	task_lock(current->group_leader);
c31dbb146dd44 (Kees Cook                   2018-04-10 16:35:01 -0700  376) 	bprm->rlim_stack = current->signal->rlim[RLIMIT_STACK];
c31dbb146dd44 (Kees Cook                   2018-04-10 16:35:01 -0700  377) 	task_unlock(current->group_leader);
c31dbb146dd44 (Kees Cook                   2018-04-10 16:35:01 -0700  378) 
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  379) 	err = __bprm_mm_init(bprm);
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  380) 	if (err)
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  381) 		goto err;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  382) 
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  383) 	return 0;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  384) 
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  385) err:
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  386) 	if (mm) {
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  387) 		bprm->mm = NULL;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  388) 		mmdrop(mm);
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  389) 	}
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  390) 
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  391) 	return err;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  392) }
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  393) 
ba2d01629d0d1 (Oleg Nesterov               2011-03-06 18:02:37 +0100  394) struct user_arg_ptr {
0e028465d18b7 (Oleg Nesterov               2011-03-06 18:02:54 +0100  395) #ifdef CONFIG_COMPAT
0e028465d18b7 (Oleg Nesterov               2011-03-06 18:02:54 +0100  396) 	bool is_compat;
0e028465d18b7 (Oleg Nesterov               2011-03-06 18:02:54 +0100  397) #endif
0e028465d18b7 (Oleg Nesterov               2011-03-06 18:02:54 +0100  398) 	union {
0e028465d18b7 (Oleg Nesterov               2011-03-06 18:02:54 +0100  399) 		const char __user *const __user *native;
0e028465d18b7 (Oleg Nesterov               2011-03-06 18:02:54 +0100  400) #ifdef CONFIG_COMPAT
38b983b3461e7 (Al Viro                     2012-09-30 13:38:55 -0400  401) 		const compat_uptr_t __user *compat;
0e028465d18b7 (Oleg Nesterov               2011-03-06 18:02:54 +0100  402) #endif
0e028465d18b7 (Oleg Nesterov               2011-03-06 18:02:54 +0100  403) 	} ptr;
ba2d01629d0d1 (Oleg Nesterov               2011-03-06 18:02:37 +0100  404) };
ba2d01629d0d1 (Oleg Nesterov               2011-03-06 18:02:37 +0100  405) 
ba2d01629d0d1 (Oleg Nesterov               2011-03-06 18:02:37 +0100  406) static const char __user *get_user_arg_ptr(struct user_arg_ptr argv, int nr)
1d1dbf8135ab2 (Oleg Nesterov               2011-03-06 18:02:21 +0100  407) {
0e028465d18b7 (Oleg Nesterov               2011-03-06 18:02:54 +0100  408) 	const char __user *native;
0e028465d18b7 (Oleg Nesterov               2011-03-06 18:02:54 +0100  409) 
0e028465d18b7 (Oleg Nesterov               2011-03-06 18:02:54 +0100  410) #ifdef CONFIG_COMPAT
0e028465d18b7 (Oleg Nesterov               2011-03-06 18:02:54 +0100  411) 	if (unlikely(argv.is_compat)) {
0e028465d18b7 (Oleg Nesterov               2011-03-06 18:02:54 +0100  412) 		compat_uptr_t compat;
0e028465d18b7 (Oleg Nesterov               2011-03-06 18:02:54 +0100  413) 
0e028465d18b7 (Oleg Nesterov               2011-03-06 18:02:54 +0100  414) 		if (get_user(compat, argv.ptr.compat + nr))
0e028465d18b7 (Oleg Nesterov               2011-03-06 18:02:54 +0100  415) 			return ERR_PTR(-EFAULT);
1d1dbf8135ab2 (Oleg Nesterov               2011-03-06 18:02:21 +0100  416) 
0e028465d18b7 (Oleg Nesterov               2011-03-06 18:02:54 +0100  417) 		return compat_ptr(compat);
0e028465d18b7 (Oleg Nesterov               2011-03-06 18:02:54 +0100  418) 	}
0e028465d18b7 (Oleg Nesterov               2011-03-06 18:02:54 +0100  419) #endif
0e028465d18b7 (Oleg Nesterov               2011-03-06 18:02:54 +0100  420) 
0e028465d18b7 (Oleg Nesterov               2011-03-06 18:02:54 +0100  421) 	if (get_user(native, argv.ptr.native + nr))
1d1dbf8135ab2 (Oleg Nesterov               2011-03-06 18:02:21 +0100  422) 		return ERR_PTR(-EFAULT);
1d1dbf8135ab2 (Oleg Nesterov               2011-03-06 18:02:21 +0100  423) 
0e028465d18b7 (Oleg Nesterov               2011-03-06 18:02:54 +0100  424) 	return native;
1d1dbf8135ab2 (Oleg Nesterov               2011-03-06 18:02:21 +0100  425) }
1d1dbf8135ab2 (Oleg Nesterov               2011-03-06 18:02:21 +0100  426) 
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  427) /*
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  428)  * count() counts the number of strings in array ARGV.
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  429)  */
ba2d01629d0d1 (Oleg Nesterov               2011-03-06 18:02:37 +0100  430) static int count(struct user_arg_ptr argv, int max)
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  431) {
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  432) 	int i = 0;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  433) 
0e028465d18b7 (Oleg Nesterov               2011-03-06 18:02:54 +0100  434) 	if (argv.ptr.native != NULL) {
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  435) 		for (;;) {
1d1dbf8135ab2 (Oleg Nesterov               2011-03-06 18:02:21 +0100  436) 			const char __user *p = get_user_arg_ptr(argv, i);
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  437) 
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  438) 			if (!p)
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  439) 				break;
1d1dbf8135ab2 (Oleg Nesterov               2011-03-06 18:02:21 +0100  440) 
1d1dbf8135ab2 (Oleg Nesterov               2011-03-06 18:02:21 +0100  441) 			if (IS_ERR(p))
1d1dbf8135ab2 (Oleg Nesterov               2011-03-06 18:02:21 +0100  442) 				return -EFAULT;
1d1dbf8135ab2 (Oleg Nesterov               2011-03-06 18:02:21 +0100  443) 
6d92d4f6a7476 (Xi Wang                     2013-01-11 14:31:48 -0800  444) 			if (i >= max)
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  445) 				return -E2BIG;
6d92d4f6a7476 (Xi Wang                     2013-01-11 14:31:48 -0800  446) 			++i;
9aea5a65aa7a1 (Roland McGrath              2010-09-07 19:37:06 -0700  447) 
9aea5a65aa7a1 (Roland McGrath              2010-09-07 19:37:06 -0700  448) 			if (fatal_signal_pending(current))
9aea5a65aa7a1 (Roland McGrath              2010-09-07 19:37:06 -0700  449) 				return -ERESTARTNOHAND;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  450) 			cond_resched();
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  451) 		}
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  452) 	}
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  453) 	return i;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  454) }
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  455) 
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500  456) static int count_strings_kernel(const char *const *argv)
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500  457) {
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500  458) 	int i;
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500  459) 
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500  460) 	if (!argv)
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500  461) 		return 0;
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500  462) 
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500  463) 	for (i = 0; argv[i]; ++i) {
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500  464) 		if (i >= MAX_ARG_STRINGS)
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500  465) 			return -E2BIG;
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500  466) 		if (fatal_signal_pending(current))
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500  467) 			return -ERESTARTNOHAND;
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500  468) 		cond_resched();
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500  469) 	}
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500  470) 	return i;
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500  471) }
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500  472) 
d8b9cd549ecf0 (Eric W. Biederman           2020-07-12 08:23:54 -0500  473) static int bprm_stack_limits(struct linux_binprm *bprm)
655c16a8ce9c1 (Oleg Nesterov               2019-01-03 15:28:11 -0800  474) {
655c16a8ce9c1 (Oleg Nesterov               2019-01-03 15:28:11 -0800  475) 	unsigned long limit, ptr_size;
655c16a8ce9c1 (Oleg Nesterov               2019-01-03 15:28:11 -0800  476) 
655c16a8ce9c1 (Oleg Nesterov               2019-01-03 15:28:11 -0800  477) 	/*
655c16a8ce9c1 (Oleg Nesterov               2019-01-03 15:28:11 -0800  478) 	 * Limit to 1/4 of the max stack size or 3/4 of _STK_LIM
655c16a8ce9c1 (Oleg Nesterov               2019-01-03 15:28:11 -0800  479) 	 * (whichever is smaller) for the argv+env strings.
655c16a8ce9c1 (Oleg Nesterov               2019-01-03 15:28:11 -0800  480) 	 * This ensures that:
655c16a8ce9c1 (Oleg Nesterov               2019-01-03 15:28:11 -0800  481) 	 *  - the remaining binfmt code will not run out of stack space,
655c16a8ce9c1 (Oleg Nesterov               2019-01-03 15:28:11 -0800  482) 	 *  - the program will have a reasonable amount of stack left
655c16a8ce9c1 (Oleg Nesterov               2019-01-03 15:28:11 -0800  483) 	 *    to work from.
655c16a8ce9c1 (Oleg Nesterov               2019-01-03 15:28:11 -0800  484) 	 */
655c16a8ce9c1 (Oleg Nesterov               2019-01-03 15:28:11 -0800  485) 	limit = _STK_LIM / 4 * 3;
655c16a8ce9c1 (Oleg Nesterov               2019-01-03 15:28:11 -0800  486) 	limit = min(limit, bprm->rlim_stack.rlim_cur / 4);
655c16a8ce9c1 (Oleg Nesterov               2019-01-03 15:28:11 -0800  487) 	/*
655c16a8ce9c1 (Oleg Nesterov               2019-01-03 15:28:11 -0800  488) 	 * We've historically supported up to 32 pages (ARG_MAX)
655c16a8ce9c1 (Oleg Nesterov               2019-01-03 15:28:11 -0800  489) 	 * of argument strings even with small stacks
655c16a8ce9c1 (Oleg Nesterov               2019-01-03 15:28:11 -0800  490) 	 */
655c16a8ce9c1 (Oleg Nesterov               2019-01-03 15:28:11 -0800  491) 	limit = max_t(unsigned long, limit, ARG_MAX);
655c16a8ce9c1 (Oleg Nesterov               2019-01-03 15:28:11 -0800  492) 	/*
655c16a8ce9c1 (Oleg Nesterov               2019-01-03 15:28:11 -0800  493) 	 * We must account for the size of all the argv and envp pointers to
655c16a8ce9c1 (Oleg Nesterov               2019-01-03 15:28:11 -0800  494) 	 * the argv and envp strings, since they will also take up space in
655c16a8ce9c1 (Oleg Nesterov               2019-01-03 15:28:11 -0800  495) 	 * the stack. They aren't stored until much later when we can't
655c16a8ce9c1 (Oleg Nesterov               2019-01-03 15:28:11 -0800  496) 	 * signal to the parent that the child has run out of stack space.
655c16a8ce9c1 (Oleg Nesterov               2019-01-03 15:28:11 -0800  497) 	 * Instead, calculate it here so it's possible to fail gracefully.
655c16a8ce9c1 (Oleg Nesterov               2019-01-03 15:28:11 -0800  498) 	 */
655c16a8ce9c1 (Oleg Nesterov               2019-01-03 15:28:11 -0800  499) 	ptr_size = (bprm->argc + bprm->envc) * sizeof(void *);
655c16a8ce9c1 (Oleg Nesterov               2019-01-03 15:28:11 -0800  500) 	if (limit <= ptr_size)
655c16a8ce9c1 (Oleg Nesterov               2019-01-03 15:28:11 -0800  501) 		return -E2BIG;
655c16a8ce9c1 (Oleg Nesterov               2019-01-03 15:28:11 -0800  502) 	limit -= ptr_size;
655c16a8ce9c1 (Oleg Nesterov               2019-01-03 15:28:11 -0800  503) 
655c16a8ce9c1 (Oleg Nesterov               2019-01-03 15:28:11 -0800  504) 	bprm->argmin = bprm->p - limit;
655c16a8ce9c1 (Oleg Nesterov               2019-01-03 15:28:11 -0800  505) 	return 0;
655c16a8ce9c1 (Oleg Nesterov               2019-01-03 15:28:11 -0800  506) }
655c16a8ce9c1 (Oleg Nesterov               2019-01-03 15:28:11 -0800  507) 
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  508) /*
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  509)  * 'copy_strings()' copies argument/environment strings from the old
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  510)  * processes's memory to the new process's stack.  The call to get_user_pages()
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  511)  * ensures the destination page is created and not swapped out.
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  512)  */
ba2d01629d0d1 (Oleg Nesterov               2011-03-06 18:02:37 +0100  513) static int copy_strings(int argc, struct user_arg_ptr argv,
75c96f85845a6 (Adrian Bunk                 2005-05-05 16:16:09 -0700  514) 			struct linux_binprm *bprm)
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  515) {
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  516) 	struct page *kmapped_page = NULL;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  517) 	char *kaddr = NULL;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  518) 	unsigned long kpos = 0;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  519) 	int ret;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  520) 
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  521) 	while (argc-- > 0) {
d7627467b7a8d (David Howells               2010-08-17 23:52:56 +0100  522) 		const char __user *str;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  523) 		int len;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  524) 		unsigned long pos;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  525) 
1d1dbf8135ab2 (Oleg Nesterov               2011-03-06 18:02:21 +0100  526) 		ret = -EFAULT;
1d1dbf8135ab2 (Oleg Nesterov               2011-03-06 18:02:21 +0100  527) 		str = get_user_arg_ptr(argv, argc);
1d1dbf8135ab2 (Oleg Nesterov               2011-03-06 18:02:21 +0100  528) 		if (IS_ERR(str))
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  529) 			goto out;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  530) 
1d1dbf8135ab2 (Oleg Nesterov               2011-03-06 18:02:21 +0100  531) 		len = strnlen_user(str, MAX_ARG_STRLEN);
1d1dbf8135ab2 (Oleg Nesterov               2011-03-06 18:02:21 +0100  532) 		if (!len)
1d1dbf8135ab2 (Oleg Nesterov               2011-03-06 18:02:21 +0100  533) 			goto out;
1d1dbf8135ab2 (Oleg Nesterov               2011-03-06 18:02:21 +0100  534) 
1d1dbf8135ab2 (Oleg Nesterov               2011-03-06 18:02:21 +0100  535) 		ret = -E2BIG;
1d1dbf8135ab2 (Oleg Nesterov               2011-03-06 18:02:21 +0100  536) 		if (!valid_arg_len(bprm, len))
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  537) 			goto out;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  538) 
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  539) 		/* We're going to work our way backwords. */
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  540) 		pos = bprm->p;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  541) 		str += len;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  542) 		bprm->p -= len;
655c16a8ce9c1 (Oleg Nesterov               2019-01-03 15:28:11 -0800  543) #ifdef CONFIG_MMU
655c16a8ce9c1 (Oleg Nesterov               2019-01-03 15:28:11 -0800  544) 		if (bprm->p < bprm->argmin)
655c16a8ce9c1 (Oleg Nesterov               2019-01-03 15:28:11 -0800  545) 			goto out;
655c16a8ce9c1 (Oleg Nesterov               2019-01-03 15:28:11 -0800  546) #endif
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  547) 
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  548) 		while (len > 0) {
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  549) 			int offset, bytes_to_copy;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  550) 
9aea5a65aa7a1 (Roland McGrath              2010-09-07 19:37:06 -0700  551) 			if (fatal_signal_pending(current)) {
9aea5a65aa7a1 (Roland McGrath              2010-09-07 19:37:06 -0700  552) 				ret = -ERESTARTNOHAND;
9aea5a65aa7a1 (Roland McGrath              2010-09-07 19:37:06 -0700  553) 				goto out;
9aea5a65aa7a1 (Roland McGrath              2010-09-07 19:37:06 -0700  554) 			}
7993bc1f4663c (Roland McGrath              2010-09-07 19:36:28 -0700  555) 			cond_resched();
7993bc1f4663c (Roland McGrath              2010-09-07 19:36:28 -0700  556) 
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  557) 			offset = pos % PAGE_SIZE;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  558) 			if (offset == 0)
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  559) 				offset = PAGE_SIZE;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  560) 
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  561) 			bytes_to_copy = offset;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  562) 			if (bytes_to_copy > len)
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  563) 				bytes_to_copy = len;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  564) 
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  565) 			offset -= bytes_to_copy;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  566) 			pos -= bytes_to_copy;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  567) 			str -= bytes_to_copy;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  568) 			len -= bytes_to_copy;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  569) 
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  570) 			if (!kmapped_page || kpos != (pos & PAGE_MASK)) {
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  571) 				struct page *page;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  572) 
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  573) 				page = get_arg_page(bprm, pos, 1);
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  574) 				if (!page) {
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  575) 					ret = -E2BIG;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  576) 					goto out;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  577) 				}
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  578) 
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  579) 				if (kmapped_page) {
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  580) 					flush_kernel_dcache_page(kmapped_page);
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  581) 					kunmap(kmapped_page);
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  582) 					put_arg_page(kmapped_page);
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  583) 				}
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  584) 				kmapped_page = page;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  585) 				kaddr = kmap(kmapped_page);
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  586) 				kpos = pos & PAGE_MASK;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  587) 				flush_arg_page(bprm, kpos, kmapped_page);
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  588) 			}
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  589) 			if (copy_from_user(kaddr+offset, str, bytes_to_copy)) {
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  590) 				ret = -EFAULT;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  591) 				goto out;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  592) 			}
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  593) 		}
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  594) 	}
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  595) 	ret = 0;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  596) out:
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  597) 	if (kmapped_page) {
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  598) 		flush_kernel_dcache_page(kmapped_page);
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  599) 		kunmap(kmapped_page);
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  600) 		put_arg_page(kmapped_page);
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  601) 	}
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  602) 	return ret;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  603) }
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  604) 
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  605) /*
986db2d14a6dc (Christoph Hellwig           2020-06-04 16:51:14 -0700  606)  * Copy and argument/environment string from the kernel to the processes stack.
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  607)  */
986db2d14a6dc (Christoph Hellwig           2020-06-04 16:51:14 -0700  608) int copy_string_kernel(const char *arg, struct linux_binprm *bprm)
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  609) {
762a3af6faa06 (Christoph Hellwig           2020-06-04 16:51:18 -0700  610) 	int len = strnlen(arg, MAX_ARG_STRLEN) + 1 /* terminating NUL */;
762a3af6faa06 (Christoph Hellwig           2020-06-04 16:51:18 -0700  611) 	unsigned long pos = bprm->p;
762a3af6faa06 (Christoph Hellwig           2020-06-04 16:51:18 -0700  612) 
762a3af6faa06 (Christoph Hellwig           2020-06-04 16:51:18 -0700  613) 	if (len == 0)
762a3af6faa06 (Christoph Hellwig           2020-06-04 16:51:18 -0700  614) 		return -EFAULT;
762a3af6faa06 (Christoph Hellwig           2020-06-04 16:51:18 -0700  615) 	if (!valid_arg_len(bprm, len))
762a3af6faa06 (Christoph Hellwig           2020-06-04 16:51:18 -0700  616) 		return -E2BIG;
762a3af6faa06 (Christoph Hellwig           2020-06-04 16:51:18 -0700  617) 
762a3af6faa06 (Christoph Hellwig           2020-06-04 16:51:18 -0700  618) 	/* We're going to work our way backwards. */
762a3af6faa06 (Christoph Hellwig           2020-06-04 16:51:18 -0700  619) 	arg += len;
762a3af6faa06 (Christoph Hellwig           2020-06-04 16:51:18 -0700  620) 	bprm->p -= len;
762a3af6faa06 (Christoph Hellwig           2020-06-04 16:51:18 -0700  621) 	if (IS_ENABLED(CONFIG_MMU) && bprm->p < bprm->argmin)
762a3af6faa06 (Christoph Hellwig           2020-06-04 16:51:18 -0700  622) 		return -E2BIG;
ba2d01629d0d1 (Oleg Nesterov               2011-03-06 18:02:37 +0100  623) 
762a3af6faa06 (Christoph Hellwig           2020-06-04 16:51:18 -0700  624) 	while (len > 0) {
762a3af6faa06 (Christoph Hellwig           2020-06-04 16:51:18 -0700  625) 		unsigned int bytes_to_copy = min_t(unsigned int, len,
762a3af6faa06 (Christoph Hellwig           2020-06-04 16:51:18 -0700  626) 				min_not_zero(offset_in_page(pos), PAGE_SIZE));
762a3af6faa06 (Christoph Hellwig           2020-06-04 16:51:18 -0700  627) 		struct page *page;
762a3af6faa06 (Christoph Hellwig           2020-06-04 16:51:18 -0700  628) 		char *kaddr;
ba2d01629d0d1 (Oleg Nesterov               2011-03-06 18:02:37 +0100  629) 
762a3af6faa06 (Christoph Hellwig           2020-06-04 16:51:18 -0700  630) 		pos -= bytes_to_copy;
762a3af6faa06 (Christoph Hellwig           2020-06-04 16:51:18 -0700  631) 		arg -= bytes_to_copy;
762a3af6faa06 (Christoph Hellwig           2020-06-04 16:51:18 -0700  632) 		len -= bytes_to_copy;
ba2d01629d0d1 (Oleg Nesterov               2011-03-06 18:02:37 +0100  633) 
762a3af6faa06 (Christoph Hellwig           2020-06-04 16:51:18 -0700  634) 		page = get_arg_page(bprm, pos, 1);
762a3af6faa06 (Christoph Hellwig           2020-06-04 16:51:18 -0700  635) 		if (!page)
762a3af6faa06 (Christoph Hellwig           2020-06-04 16:51:18 -0700  636) 			return -E2BIG;
762a3af6faa06 (Christoph Hellwig           2020-06-04 16:51:18 -0700  637) 		kaddr = kmap_atomic(page);
762a3af6faa06 (Christoph Hellwig           2020-06-04 16:51:18 -0700  638) 		flush_arg_page(bprm, pos & PAGE_MASK, page);
762a3af6faa06 (Christoph Hellwig           2020-06-04 16:51:18 -0700  639) 		memcpy(kaddr + offset_in_page(pos), arg, bytes_to_copy);
762a3af6faa06 (Christoph Hellwig           2020-06-04 16:51:18 -0700  640) 		flush_kernel_dcache_page(page);
762a3af6faa06 (Christoph Hellwig           2020-06-04 16:51:18 -0700  641) 		kunmap_atomic(kaddr);
762a3af6faa06 (Christoph Hellwig           2020-06-04 16:51:18 -0700  642) 		put_arg_page(page);
762a3af6faa06 (Christoph Hellwig           2020-06-04 16:51:18 -0700  643) 	}
762a3af6faa06 (Christoph Hellwig           2020-06-04 16:51:18 -0700  644) 
762a3af6faa06 (Christoph Hellwig           2020-06-04 16:51:18 -0700  645) 	return 0;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  646) }
986db2d14a6dc (Christoph Hellwig           2020-06-04 16:51:14 -0700  647) EXPORT_SYMBOL(copy_string_kernel);
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  648) 
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500  649) static int copy_strings_kernel(int argc, const char *const *argv,
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500  650) 			       struct linux_binprm *bprm)
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500  651) {
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500  652) 	while (argc-- > 0) {
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500  653) 		int ret = copy_string_kernel(argv[argc], bprm);
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500  654) 		if (ret < 0)
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500  655) 			return ret;
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500  656) 		if (fatal_signal_pending(current))
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500  657) 			return -ERESTARTNOHAND;
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500  658) 		cond_resched();
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500  659) 	}
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500  660) 	return 0;
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500  661) }
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500  662) 
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  663) #ifdef CONFIG_MMU
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  664) 
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  665) /*
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  666)  * During bprm_mm_init(), we create a temporary stack at STACK_TOP_MAX.  Once
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  667)  * the binfmt code determines where the new stack should reside, we shift it to
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  668)  * its final location.  The process proceeds as follows:
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  669)  *
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  670)  * 1) Use shift to calculate the new vma endpoints.
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  671)  * 2) Extend vma to cover both the old and new ranges.  This ensures the
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  672)  *    arguments passed to subsequent functions are consistent.
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  673)  * 3) Move vma's page tables to the new range.
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  674)  * 4) Free up any cleared pgd range.
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  675)  * 5) Shrink the vma to cover only the new range.
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  676)  */
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  677) static int shift_arg_pages(struct vm_area_struct *vma, unsigned long shift)
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  678) {
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  679) 	struct mm_struct *mm = vma->vm_mm;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  680) 	unsigned long old_start = vma->vm_start;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  681) 	unsigned long old_end = vma->vm_end;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  682) 	unsigned long length = old_end - old_start;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  683) 	unsigned long new_start = old_start - shift;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  684) 	unsigned long new_end = old_end - shift;
d16dfc550f532 (Peter Zijlstra              2011-05-24 17:11:45 -0700  685) 	struct mmu_gather tlb;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  686) 
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  687) 	BUG_ON(new_start > new_end);
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  688) 
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  689) 	/*
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  690) 	 * ensure there are no vmas between where we want to go
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  691) 	 * and where we are
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  692) 	 */
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  693) 	if (vma != find_vma(mm, new_start))
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  694) 		return -EFAULT;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  695) 
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  696) 	/*
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  697) 	 * cover the whole range: [new_start, old_end)
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  698) 	 */
5beb49305251e (Rik van Riel                2010-03-05 13:42:07 -0800  699) 	if (vma_adjust(vma, new_start, old_end, vma->vm_pgoff, NULL))
5beb49305251e (Rik van Riel                2010-03-05 13:42:07 -0800  700) 		return -ENOMEM;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  701) 
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  702) 	/*
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  703) 	 * move the page tables downwards, on failure we rely on
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  704) 	 * process cleanup to remove whatever mess we made.
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  705) 	 */
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  706) 	if (length != move_page_tables(vma, old_start,
38a76013ad809 (Michel Lespinasse           2012-10-08 16:31:50 -0700  707) 				       vma, new_start, length, false))
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  708) 		return -ENOMEM;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  709) 
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  710) 	lru_add_drain();
a72afd873089c (Will Deacon                 2021-01-27 23:53:45 +0000  711) 	tlb_gather_mmu(&tlb, mm);
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  712) 	if (new_end > old_start) {
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  713) 		/*
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  714) 		 * when the old and new regions overlap clear from new_end.
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  715) 		 */
d16dfc550f532 (Peter Zijlstra              2011-05-24 17:11:45 -0700  716) 		free_pgd_range(&tlb, new_end, old_end, new_end,
6ee8630e02be6 (Hugh Dickins                2013-04-29 15:07:44 -0700  717) 			vma->vm_next ? vma->vm_next->vm_start : USER_PGTABLES_CEILING);
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  718) 	} else {
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  719) 		/*
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  720) 		 * otherwise, clean from old_start; this is done to not touch
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  721) 		 * the address space in [new_end, old_start) some architectures
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  722) 		 * have constraints on va-space that make this illegal (IA64) -
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  723) 		 * for the others its just a little faster.
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  724) 		 */
d16dfc550f532 (Peter Zijlstra              2011-05-24 17:11:45 -0700  725) 		free_pgd_range(&tlb, old_start, old_end, new_end,
6ee8630e02be6 (Hugh Dickins                2013-04-29 15:07:44 -0700  726) 			vma->vm_next ? vma->vm_next->vm_start : USER_PGTABLES_CEILING);
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  727) 	}
ae8eba8b5d723 (Will Deacon                 2021-01-27 23:53:43 +0000  728) 	tlb_finish_mmu(&tlb);
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  729) 
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  730) 	/*
5beb49305251e (Rik van Riel                2010-03-05 13:42:07 -0800  731) 	 * Shrink the vma to just the new range.  Always succeeds.
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  732) 	 */
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  733) 	vma_adjust(vma, new_start, new_end, vma->vm_pgoff, NULL);
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  734) 
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  735) 	return 0;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  736) }
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  737) 
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  738) /*
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  739)  * Finalizes the stack vm_area_struct. The flags and permissions are updated,
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  740)  * the stack is optionally relocated, and some extra space is added.
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  741)  */
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  742) int setup_arg_pages(struct linux_binprm *bprm,
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  743) 		    unsigned long stack_top,
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  744) 		    int executable_stack)
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  745) {
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  746) 	unsigned long ret;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  747) 	unsigned long stack_shift;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  748) 	struct mm_struct *mm = current->mm;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  749) 	struct vm_area_struct *vma = bprm->vma;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  750) 	struct vm_area_struct *prev = NULL;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  751) 	unsigned long vm_flags;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  752) 	unsigned long stack_base;
803bf5ec25994 (Michael Neuling             2010-02-10 13:56:42 -0800  753) 	unsigned long stack_size;
803bf5ec25994 (Michael Neuling             2010-02-10 13:56:42 -0800  754) 	unsigned long stack_expand;
803bf5ec25994 (Michael Neuling             2010-02-10 13:56:42 -0800  755) 	unsigned long rlim_stack;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  756) 
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  757) #ifdef CONFIG_STACK_GROWSUP
d71f290b4e98a (James Hogan                 2014-05-13 23:58:24 +0100  758) 	/* Limit stack size */
c31dbb146dd44 (Kees Cook                   2018-04-10 16:35:01 -0700  759) 	stack_base = bprm->rlim_stack.rlim_max;
22ee3ea588dfc (Helge Deller                2020-11-06 19:41:36 +0100  760) 
22ee3ea588dfc (Helge Deller                2020-11-06 19:41:36 +0100  761) 	stack_base = calc_max_stack_size(stack_base);
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  762) 
d045c77c1a697 (Helge Deller                2015-05-11 22:01:27 +0200  763) 	/* Add space for stack randomization. */
d045c77c1a697 (Helge Deller                2015-05-11 22:01:27 +0200  764) 	stack_base += (STACK_RND_MASK << PAGE_SHIFT);
d045c77c1a697 (Helge Deller                2015-05-11 22:01:27 +0200  765) 
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  766) 	/* Make sure we didn't let the argument array grow too large. */
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  767) 	if (vma->vm_end - vma->vm_start > stack_base)
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  768) 		return -ENOMEM;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  769) 
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  770) 	stack_base = PAGE_ALIGN(stack_top - stack_base);
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  771) 
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  772) 	stack_shift = vma->vm_start - stack_base;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  773) 	mm->arg_start = bprm->p - stack_shift;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  774) 	bprm->p = vma->vm_end - stack_shift;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  775) #else
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  776) 	stack_top = arch_align_stack(stack_top);
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  777) 	stack_top = PAGE_ALIGN(stack_top);
1b528181b2ffa (Roland McGrath              2010-09-07 19:35:49 -0700  778) 
1b528181b2ffa (Roland McGrath              2010-09-07 19:35:49 -0700  779) 	if (unlikely(stack_top < mmap_min_addr) ||
1b528181b2ffa (Roland McGrath              2010-09-07 19:35:49 -0700  780) 	    unlikely(vma->vm_end - vma->vm_start >= stack_top - mmap_min_addr))
1b528181b2ffa (Roland McGrath              2010-09-07 19:35:49 -0700  781) 		return -ENOMEM;
1b528181b2ffa (Roland McGrath              2010-09-07 19:35:49 -0700  782) 
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  783) 	stack_shift = vma->vm_end - stack_top;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  784) 
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  785) 	bprm->p -= stack_shift;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  786) 	mm->arg_start = bprm->p;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  787) #endif
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  788) 
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  789) 	if (bprm->loader)
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  790) 		bprm->loader -= stack_shift;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  791) 	bprm->exec -= stack_shift;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  792) 
d8ed45c5dcd45 (Michel Lespinasse           2020-06-08 21:33:25 -0700  793) 	if (mmap_write_lock_killable(mm))
f268dfe905d46 (Michal Hocko                2016-05-23 16:26:02 -0700  794) 		return -EINTR;
f268dfe905d46 (Michal Hocko                2016-05-23 16:26:02 -0700  795) 
96a8e13ed44e3 (Hugh Dickins                2008-07-10 21:19:20 +0100  796) 	vm_flags = VM_STACK_FLAGS;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  797) 
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  798) 	/*
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  799) 	 * Adjust stack execute permissions; explicitly enable for
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  800) 	 * EXSTACK_ENABLE_X, disable for EXSTACK_DISABLE_X and leave alone
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  801) 	 * (arch default) otherwise.
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  802) 	 */
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  803) 	if (unlikely(executable_stack == EXSTACK_ENABLE_X))
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  804) 		vm_flags |= VM_EXEC;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  805) 	else if (executable_stack == EXSTACK_DISABLE_X)
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  806) 		vm_flags &= ~VM_EXEC;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  807) 	vm_flags |= mm->def_flags;
a8bef8ff6ea15 (Mel Gorman                  2010-05-24 14:32:24 -0700  808) 	vm_flags |= VM_STACK_INCOMPLETE_SETUP;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  809) 
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  810) 	ret = mprotect_fixup(vma, &prev, vma->vm_start, vma->vm_end,
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  811) 			vm_flags);
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  812) 	if (ret)
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  813) 		goto out_unlock;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  814) 	BUG_ON(prev != vma);
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  815) 
47a2ebb7f5053 (Alexey Dobriyan             2020-01-30 22:17:29 -0800  816) 	if (unlikely(vm_flags & VM_EXEC)) {
47a2ebb7f5053 (Alexey Dobriyan             2020-01-30 22:17:29 -0800  817) 		pr_warn_once("process '%pD4' started with executable stack\n",
47a2ebb7f5053 (Alexey Dobriyan             2020-01-30 22:17:29 -0800  818) 			     bprm->file);
47a2ebb7f5053 (Alexey Dobriyan             2020-01-30 22:17:29 -0800  819) 	}
47a2ebb7f5053 (Alexey Dobriyan             2020-01-30 22:17:29 -0800  820) 
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  821) 	/* Move stack pages down in memory. */
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  822) 	if (stack_shift) {
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  823) 		ret = shift_arg_pages(vma, stack_shift);
fc63cf237078c (Anton Blanchard             2009-11-11 14:26:48 -0800  824) 		if (ret)
fc63cf237078c (Anton Blanchard             2009-11-11 14:26:48 -0800  825) 			goto out_unlock;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  826) 	}
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  827) 
a8bef8ff6ea15 (Mel Gorman                  2010-05-24 14:32:24 -0700  828) 	/* mprotect_fixup is overkill to remove the temporary stack flags */
a8bef8ff6ea15 (Mel Gorman                  2010-05-24 14:32:24 -0700  829) 	vma->vm_flags &= ~VM_STACK_INCOMPLETE_SETUP;
a8bef8ff6ea15 (Mel Gorman                  2010-05-24 14:32:24 -0700  830) 
5ef097dd7ba4e (Michael Neuling             2010-03-05 13:42:57 -0800  831) 	stack_expand = 131072UL; /* randomly 32*4k (or 2*64k) pages */
803bf5ec25994 (Michael Neuling             2010-02-10 13:56:42 -0800  832) 	stack_size = vma->vm_end - vma->vm_start;
803bf5ec25994 (Michael Neuling             2010-02-10 13:56:42 -0800  833) 	/*
803bf5ec25994 (Michael Neuling             2010-02-10 13:56:42 -0800  834) 	 * Align this down to a page boundary as expand_stack
803bf5ec25994 (Michael Neuling             2010-02-10 13:56:42 -0800  835) 	 * will align it up.
803bf5ec25994 (Michael Neuling             2010-02-10 13:56:42 -0800  836) 	 */
c31dbb146dd44 (Kees Cook                   2018-04-10 16:35:01 -0700  837) 	rlim_stack = bprm->rlim_stack.rlim_cur & PAGE_MASK;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  838) #ifdef CONFIG_STACK_GROWSUP
803bf5ec25994 (Michael Neuling             2010-02-10 13:56:42 -0800  839) 	if (stack_size + stack_expand > rlim_stack)
803bf5ec25994 (Michael Neuling             2010-02-10 13:56:42 -0800  840) 		stack_base = vma->vm_start + rlim_stack;
803bf5ec25994 (Michael Neuling             2010-02-10 13:56:42 -0800  841) 	else
803bf5ec25994 (Michael Neuling             2010-02-10 13:56:42 -0800  842) 		stack_base = vma->vm_end + stack_expand;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  843) #else
803bf5ec25994 (Michael Neuling             2010-02-10 13:56:42 -0800  844) 	if (stack_size + stack_expand > rlim_stack)
803bf5ec25994 (Michael Neuling             2010-02-10 13:56:42 -0800  845) 		stack_base = vma->vm_end - rlim_stack;
803bf5ec25994 (Michael Neuling             2010-02-10 13:56:42 -0800  846) 	else
803bf5ec25994 (Michael Neuling             2010-02-10 13:56:42 -0800  847) 		stack_base = vma->vm_start - stack_expand;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  848) #endif
3af9e859281bd (Eric B Munson               2010-05-18 15:30:49 +0100  849) 	current->mm->start_stack = bprm->p;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  850) 	ret = expand_stack(vma, stack_base);
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  851) 	if (ret)
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  852) 		ret = -EFAULT;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  853) 
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700  854) out_unlock:
d8ed45c5dcd45 (Michel Lespinasse           2020-06-08 21:33:25 -0700  855) 	mmap_write_unlock(mm);
fc63cf237078c (Anton Blanchard             2009-11-11 14:26:48 -0800  856) 	return ret;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  857) }
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  858) EXPORT_SYMBOL(setup_arg_pages);
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  859) 
7e7ec6a934349 (Nicolas Pitre               2016-07-24 11:30:18 -0400  860) #else
7e7ec6a934349 (Nicolas Pitre               2016-07-24 11:30:18 -0400  861) 
7e7ec6a934349 (Nicolas Pitre               2016-07-24 11:30:18 -0400  862) /*
7e7ec6a934349 (Nicolas Pitre               2016-07-24 11:30:18 -0400  863)  * Transfer the program arguments and environment from the holding pages
7e7ec6a934349 (Nicolas Pitre               2016-07-24 11:30:18 -0400  864)  * onto the stack. The provided stack pointer is adjusted accordingly.
7e7ec6a934349 (Nicolas Pitre               2016-07-24 11:30:18 -0400  865)  */
7e7ec6a934349 (Nicolas Pitre               2016-07-24 11:30:18 -0400  866) int transfer_args_to_stack(struct linux_binprm *bprm,
7e7ec6a934349 (Nicolas Pitre               2016-07-24 11:30:18 -0400  867) 			   unsigned long *sp_location)
7e7ec6a934349 (Nicolas Pitre               2016-07-24 11:30:18 -0400  868) {
7e7ec6a934349 (Nicolas Pitre               2016-07-24 11:30:18 -0400  869) 	unsigned long index, stop, sp;
7e7ec6a934349 (Nicolas Pitre               2016-07-24 11:30:18 -0400  870) 	int ret = 0;
7e7ec6a934349 (Nicolas Pitre               2016-07-24 11:30:18 -0400  871) 
7e7ec6a934349 (Nicolas Pitre               2016-07-24 11:30:18 -0400  872) 	stop = bprm->p >> PAGE_SHIFT;
7e7ec6a934349 (Nicolas Pitre               2016-07-24 11:30:18 -0400  873) 	sp = *sp_location;
7e7ec6a934349 (Nicolas Pitre               2016-07-24 11:30:18 -0400  874) 
7e7ec6a934349 (Nicolas Pitre               2016-07-24 11:30:18 -0400  875) 	for (index = MAX_ARG_PAGES - 1; index >= stop; index--) {
7e7ec6a934349 (Nicolas Pitre               2016-07-24 11:30:18 -0400  876) 		unsigned int offset = index == stop ? bprm->p & ~PAGE_MASK : 0;
7e7ec6a934349 (Nicolas Pitre               2016-07-24 11:30:18 -0400  877) 		char *src = kmap(bprm->page[index]) + offset;
7e7ec6a934349 (Nicolas Pitre               2016-07-24 11:30:18 -0400  878) 		sp -= PAGE_SIZE - offset;
7e7ec6a934349 (Nicolas Pitre               2016-07-24 11:30:18 -0400  879) 		if (copy_to_user((void *) sp, src, PAGE_SIZE - offset) != 0)
7e7ec6a934349 (Nicolas Pitre               2016-07-24 11:30:18 -0400  880) 			ret = -EFAULT;
7e7ec6a934349 (Nicolas Pitre               2016-07-24 11:30:18 -0400  881) 		kunmap(bprm->page[index]);
7e7ec6a934349 (Nicolas Pitre               2016-07-24 11:30:18 -0400  882) 		if (ret)
7e7ec6a934349 (Nicolas Pitre               2016-07-24 11:30:18 -0400  883) 			goto out;
7e7ec6a934349 (Nicolas Pitre               2016-07-24 11:30:18 -0400  884) 	}
7e7ec6a934349 (Nicolas Pitre               2016-07-24 11:30:18 -0400  885) 
7e7ec6a934349 (Nicolas Pitre               2016-07-24 11:30:18 -0400  886) 	*sp_location = sp;
7e7ec6a934349 (Nicolas Pitre               2016-07-24 11:30:18 -0400  887) 
7e7ec6a934349 (Nicolas Pitre               2016-07-24 11:30:18 -0400  888) out:
7e7ec6a934349 (Nicolas Pitre               2016-07-24 11:30:18 -0400  889) 	return ret;
7e7ec6a934349 (Nicolas Pitre               2016-07-24 11:30:18 -0400  890) }
7e7ec6a934349 (Nicolas Pitre               2016-07-24 11:30:18 -0400  891) EXPORT_SYMBOL(transfer_args_to_stack);
7e7ec6a934349 (Nicolas Pitre               2016-07-24 11:30:18 -0400  892) 
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  893) #endif /* CONFIG_MMU */
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  894) 
51f39a1f0cea1 (David Drysdale              2014-12-12 16:57:29 -0800  895) static struct file *do_open_execat(int fd, struct filename *name, int flags)
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  896) {
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  897) 	struct file *file;
e56b6a5dda1a3 (Christoph Hellwig           2008-05-19 07:53:34 +0200  898) 	int err;
51f39a1f0cea1 (David Drysdale              2014-12-12 16:57:29 -0800  899) 	struct open_flags open_exec_flags = {
47c805dc2d2df (Al Viro                     2011-02-23 17:44:09 -0500  900) 		.open_flag = O_LARGEFILE | O_RDONLY | __FMODE_EXEC,
62fb4a155f745 (Al Viro                     2015-12-26 22:33:24 -0500  901) 		.acc_mode = MAY_EXEC,
f9652e10c12b4 (Al Viro                     2013-06-11 08:23:01 +0400  902) 		.intent = LOOKUP_OPEN,
f9652e10c12b4 (Al Viro                     2013-06-11 08:23:01 +0400  903) 		.lookup_flags = LOOKUP_FOLLOW,
47c805dc2d2df (Al Viro                     2011-02-23 17:44:09 -0500  904) 	};
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  905) 
51f39a1f0cea1 (David Drysdale              2014-12-12 16:57:29 -0800  906) 	if ((flags & ~(AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH)) != 0)
51f39a1f0cea1 (David Drysdale              2014-12-12 16:57:29 -0800  907) 		return ERR_PTR(-EINVAL);
51f39a1f0cea1 (David Drysdale              2014-12-12 16:57:29 -0800  908) 	if (flags & AT_SYMLINK_NOFOLLOW)
51f39a1f0cea1 (David Drysdale              2014-12-12 16:57:29 -0800  909) 		open_exec_flags.lookup_flags &= ~LOOKUP_FOLLOW;
51f39a1f0cea1 (David Drysdale              2014-12-12 16:57:29 -0800  910) 	if (flags & AT_EMPTY_PATH)
51f39a1f0cea1 (David Drysdale              2014-12-12 16:57:29 -0800  911) 		open_exec_flags.lookup_flags |= LOOKUP_EMPTY;
51f39a1f0cea1 (David Drysdale              2014-12-12 16:57:29 -0800  912) 
51f39a1f0cea1 (David Drysdale              2014-12-12 16:57:29 -0800  913) 	file = do_filp_open(fd, name, &open_exec_flags);
6e8341a11eb21 (Al Viro                     2009-04-06 11:16:22 -0400  914) 	if (IS_ERR(file))
e56b6a5dda1a3 (Christoph Hellwig           2008-05-19 07:53:34 +0200  915) 		goto out;
e56b6a5dda1a3 (Christoph Hellwig           2008-05-19 07:53:34 +0200  916) 
633fb6ac39801 (Kees Cook                   2020-08-11 18:36:26 -0700  917) 	/*
633fb6ac39801 (Kees Cook                   2020-08-11 18:36:26 -0700  918) 	 * may_open() has already checked for this, so it should be
633fb6ac39801 (Kees Cook                   2020-08-11 18:36:26 -0700  919) 	 * impossible to trip now. But we need to be extra cautious
633fb6ac39801 (Kees Cook                   2020-08-11 18:36:26 -0700  920) 	 * and check again at the very end too.
633fb6ac39801 (Kees Cook                   2020-08-11 18:36:26 -0700  921) 	 */
e56b6a5dda1a3 (Christoph Hellwig           2008-05-19 07:53:34 +0200  922) 	err = -EACCES;
0fd338b2d2cdf (Kees Cook                   2020-08-11 18:36:30 -0700  923) 	if (WARN_ON_ONCE(!S_ISREG(file_inode(file)->i_mode) ||
0fd338b2d2cdf (Kees Cook                   2020-08-11 18:36:30 -0700  924) 			 path_noexec(&file->f_path)))
6e8341a11eb21 (Al Viro                     2009-04-06 11:16:22 -0400  925) 		goto exit;
e56b6a5dda1a3 (Christoph Hellwig           2008-05-19 07:53:34 +0200  926) 
e56b6a5dda1a3 (Christoph Hellwig           2008-05-19 07:53:34 +0200  927) 	err = deny_write_access(file);
6e8341a11eb21 (Al Viro                     2009-04-06 11:16:22 -0400  928) 	if (err)
6e8341a11eb21 (Al Viro                     2009-04-06 11:16:22 -0400  929) 		goto exit;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  930) 
51f39a1f0cea1 (David Drysdale              2014-12-12 16:57:29 -0800  931) 	if (name->name[0] != '\0')
51f39a1f0cea1 (David Drysdale              2014-12-12 16:57:29 -0800  932) 		fsnotify_open(file);
51f39a1f0cea1 (David Drysdale              2014-12-12 16:57:29 -0800  933) 
6e8341a11eb21 (Al Viro                     2009-04-06 11:16:22 -0400  934) out:
e56b6a5dda1a3 (Christoph Hellwig           2008-05-19 07:53:34 +0200  935) 	return file;
e56b6a5dda1a3 (Christoph Hellwig           2008-05-19 07:53:34 +0200  936) 
6e8341a11eb21 (Al Viro                     2009-04-06 11:16:22 -0400  937) exit:
6e8341a11eb21 (Al Viro                     2009-04-06 11:16:22 -0400  938) 	fput(file);
e56b6a5dda1a3 (Christoph Hellwig           2008-05-19 07:53:34 +0200  939) 	return ERR_PTR(err);
e56b6a5dda1a3 (Christoph Hellwig           2008-05-19 07:53:34 +0200  940) }
c4ad8f98bef77 (Linus Torvalds              2014-02-05 12:54:53 -0800  941) 
c4ad8f98bef77 (Linus Torvalds              2014-02-05 12:54:53 -0800  942) struct file *open_exec(const char *name)
c4ad8f98bef77 (Linus Torvalds              2014-02-05 12:54:53 -0800  943) {
5168910413830 (Paul Moore                  2015-01-22 00:00:03 -0500  944) 	struct filename *filename = getname_kernel(name);
5168910413830 (Paul Moore                  2015-01-22 00:00:03 -0500  945) 	struct file *f = ERR_CAST(filename);
5168910413830 (Paul Moore                  2015-01-22 00:00:03 -0500  946) 
5168910413830 (Paul Moore                  2015-01-22 00:00:03 -0500  947) 	if (!IS_ERR(filename)) {
5168910413830 (Paul Moore                  2015-01-22 00:00:03 -0500  948) 		f = do_open_execat(AT_FDCWD, filename, 0);
5168910413830 (Paul Moore                  2015-01-22 00:00:03 -0500  949) 		putname(filename);
5168910413830 (Paul Moore                  2015-01-22 00:00:03 -0500  950) 	}
5168910413830 (Paul Moore                  2015-01-22 00:00:03 -0500  951) 	return f;
c4ad8f98bef77 (Linus Torvalds              2014-02-05 12:54:53 -0800  952) }
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  953) EXPORT_SYMBOL(open_exec);
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  954) 
48304f7994d74 (Christoph Hellwig           2020-06-07 21:42:40 -0700  955) #if defined(CONFIG_HAVE_AOUT) || defined(CONFIG_BINFMT_FLAT) || \
48304f7994d74 (Christoph Hellwig           2020-06-07 21:42:40 -0700  956)     defined(CONFIG_BINFMT_ELF_FDPIC)
3dc20cb282ec0 (Al Viro                     2013-04-13 20:31:37 -0400  957) ssize_t read_code(struct file *file, unsigned long addr, loff_t pos, size_t len)
3dc20cb282ec0 (Al Viro                     2013-04-13 20:31:37 -0400  958) {
ec69557982563 (Al Viro                     2014-02-04 19:08:21 -0500  959) 	ssize_t res = vfs_read(file, (void __user *)addr, len, &pos);
3dc20cb282ec0 (Al Viro                     2013-04-13 20:31:37 -0400  960) 	if (res > 0)
bce2b68b891af (Christoph Hellwig           2020-06-07 21:42:43 -0700  961) 		flush_icache_user_range(addr, addr + len);
3dc20cb282ec0 (Al Viro                     2013-04-13 20:31:37 -0400  962) 	return res;
3dc20cb282ec0 (Al Viro                     2013-04-13 20:31:37 -0400  963) }
3dc20cb282ec0 (Al Viro                     2013-04-13 20:31:37 -0400  964) EXPORT_SYMBOL(read_code);
48304f7994d74 (Christoph Hellwig           2020-06-07 21:42:40 -0700  965) #endif
3dc20cb282ec0 (Al Viro                     2013-04-13 20:31:37 -0400  966) 
eea9673250db4 (Eric W. Biederman           2020-03-25 10:03:36 -0500  967) /*
eea9673250db4 (Eric W. Biederman           2020-03-25 10:03:36 -0500  968)  * Maps the mm_struct mm into the current task struct.
f7cfd871ae0c5 (Eric W. Biederman           2020-12-03 14:12:00 -0600  969)  * On success, this function returns with exec_update_lock
f7cfd871ae0c5 (Eric W. Biederman           2020-12-03 14:12:00 -0600  970)  * held for writing.
eea9673250db4 (Eric W. Biederman           2020-03-25 10:03:36 -0500  971)  */
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  972) static int exec_mmap(struct mm_struct *mm)
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  973) {
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  974) 	struct task_struct *tsk;
615d6e8756c87 (Davidlohr Bueso             2014-04-07 15:37:25 -0700  975) 	struct mm_struct *old_mm, *active_mm;
eea9673250db4 (Eric W. Biederman           2020-03-25 10:03:36 -0500  976) 	int ret;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  977) 
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  978) 	/* Notify parent that we're no longer interested in the old VM */
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  979) 	tsk = current;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  980) 	old_mm = current->mm;
4610ba7ad877f (Thomas Gleixner             2019-11-06 22:55:38 +0100  981) 	exec_mm_release(tsk, old_mm);
a28bf136e651e (Eric W. Biederman           2020-03-30 16:33:39 -0500  982) 	if (old_mm)
a28bf136e651e (Eric W. Biederman           2020-03-30 16:33:39 -0500  983) 		sync_mm_rss(old_mm);
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  984) 
f7cfd871ae0c5 (Eric W. Biederman           2020-12-03 14:12:00 -0600  985) 	ret = down_write_killable(&tsk->signal->exec_update_lock);
eea9673250db4 (Eric W. Biederman           2020-03-25 10:03:36 -0500  986) 	if (ret)
eea9673250db4 (Eric W. Biederman           2020-03-25 10:03:36 -0500  987) 		return ret;
eea9673250db4 (Eric W. Biederman           2020-03-25 10:03:36 -0500  988) 
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  989) 	if (old_mm) {
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  990) 		/*
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  991) 		 * Make sure that if there is a core dump in progress
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  992) 		 * for the old mm, we get out and die instead of going
c1e8d7c6a7a68 (Michel Lespinasse           2020-06-08 21:33:54 -0700  993) 		 * through with the exec.  We must hold mmap_lock around
999d9fc1670bc (Oleg Nesterov               2008-07-25 01:47:41 -0700  994) 		 * checking core_state and changing tsk->mm.
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700  995) 		 */
d8ed45c5dcd45 (Michel Lespinasse           2020-06-08 21:33:25 -0700  996) 		mmap_read_lock(old_mm);
999d9fc1670bc (Oleg Nesterov               2008-07-25 01:47:41 -0700  997) 		if (unlikely(old_mm->core_state)) {
d8ed45c5dcd45 (Michel Lespinasse           2020-06-08 21:33:25 -0700  998) 			mmap_read_unlock(old_mm);
f7cfd871ae0c5 (Eric W. Biederman           2020-12-03 14:12:00 -0600  999) 			up_write(&tsk->signal->exec_update_lock);
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1000) 			return -EINTR;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1001) 		}
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1002) 	}
eea9673250db4 (Eric W. Biederman           2020-03-25 10:03:36 -0500 1003) 
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1004) 	task_lock(tsk);
227a4aadc75ba (Mathieu Desnoyers           2019-09-19 13:37:02 -0400 1005) 	membarrier_exec_mmap(mm);
d53c3dfb23c45 (Nicholas Piggin             2020-09-14 14:52:16 +1000 1006) 
d53c3dfb23c45 (Nicholas Piggin             2020-09-14 14:52:16 +1000 1007) 	local_irq_disable();
d53c3dfb23c45 (Nicholas Piggin             2020-09-14 14:52:16 +1000 1008) 	active_mm = tsk->active_mm;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1009) 	tsk->active_mm = mm;
d53c3dfb23c45 (Nicholas Piggin             2020-09-14 14:52:16 +1000 1010) 	tsk->mm = mm;
d53c3dfb23c45 (Nicholas Piggin             2020-09-14 14:52:16 +1000 1011) 	/*
d53c3dfb23c45 (Nicholas Piggin             2020-09-14 14:52:16 +1000 1012) 	 * This prevents preemption while active_mm is being loaded and
d53c3dfb23c45 (Nicholas Piggin             2020-09-14 14:52:16 +1000 1013) 	 * it and mm are being updated, which could cause problems for
d53c3dfb23c45 (Nicholas Piggin             2020-09-14 14:52:16 +1000 1014) 	 * lazy tlb mm refcounting when these are updated by context
d53c3dfb23c45 (Nicholas Piggin             2020-09-14 14:52:16 +1000 1015) 	 * switches. Not all architectures can handle irqs off over
d53c3dfb23c45 (Nicholas Piggin             2020-09-14 14:52:16 +1000 1016) 	 * activate_mm yet.
d53c3dfb23c45 (Nicholas Piggin             2020-09-14 14:52:16 +1000 1017) 	 */
d53c3dfb23c45 (Nicholas Piggin             2020-09-14 14:52:16 +1000 1018) 	if (!IS_ENABLED(CONFIG_ARCH_WANT_IRQS_OFF_ACTIVATE_MM))
d53c3dfb23c45 (Nicholas Piggin             2020-09-14 14:52:16 +1000 1019) 		local_irq_enable();
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1020) 	activate_mm(active_mm, mm);
d53c3dfb23c45 (Nicholas Piggin             2020-09-14 14:52:16 +1000 1021) 	if (IS_ENABLED(CONFIG_ARCH_WANT_IRQS_OFF_ACTIVATE_MM))
d53c3dfb23c45 (Nicholas Piggin             2020-09-14 14:52:16 +1000 1022) 		local_irq_enable();
615d6e8756c87 (Davidlohr Bueso             2014-04-07 15:37:25 -0700 1023) 	tsk->mm->vmacache_seqnum = 0;
615d6e8756c87 (Davidlohr Bueso             2014-04-07 15:37:25 -0700 1024) 	vmacache_flush(tsk);
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1025) 	task_unlock(tsk);
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1026) 	if (old_mm) {
d8ed45c5dcd45 (Michel Lespinasse           2020-06-08 21:33:25 -0700 1027) 		mmap_read_unlock(old_mm);
7dddb12c63553 (Eric Sesterhenn             2006-04-01 01:13:38 +0200 1028) 		BUG_ON(active_mm != old_mm);
701085b219016 (Oleg Nesterov               2012-03-19 17:04:01 +0100 1029) 		setmax_mm_hiwater_rss(&tsk->signal->maxrss, old_mm);
31a78f23bac00 (Balbir Singh                2008-09-28 23:09:31 +0100 1030) 		mm_update_next_owner(old_mm);
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1031) 		mmput(old_mm);
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1032) 		return 0;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1033) 	}
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1034) 	mmdrop(active_mm);
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1035) 	return 0;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1036) }
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1037) 
858119e159384 (Arjan van de Ven            2006-01-14 13:20:43 -0800 1038) static int de_thread(struct task_struct *tsk)
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1039) {
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1040) 	struct signal_struct *sig = tsk->signal;
b2c903b879046 (Oleg Nesterov               2007-10-16 23:27:22 -0700 1041) 	struct sighand_struct *oldsighand = tsk->sighand;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1042) 	spinlock_t *lock = &oldsighand->siglock;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1043) 
aafe6c2a2b6bc (Eric W. Biederman           2006-09-27 01:51:13 -0700 1044) 	if (thread_group_empty(tsk))
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1045) 		goto no_thread_group;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1046) 
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1047) 	/*
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1048) 	 * Kill all other threads in the thread group.
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1049) 	 */
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1050) 	spin_lock_irq(lock);
ed5d2cac11420 (Oleg Nesterov               2008-02-04 22:27:24 -0800 1051) 	if (signal_group_exit(sig)) {
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1052) 		/*
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1053) 		 * Another group action in progress, just
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1054) 		 * return so that the signal is processed.
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1055) 		 */
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1056) 		spin_unlock_irq(lock);
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1057) 		return -EAGAIN;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1058) 	}
d344193a05da8 (Oleg Nesterov               2010-05-26 14:43:11 -0700 1059) 
ed5d2cac11420 (Oleg Nesterov               2008-02-04 22:27:24 -0800 1060) 	sig->group_exit_task = tsk;
d344193a05da8 (Oleg Nesterov               2010-05-26 14:43:11 -0700 1061) 	sig->notify_count = zap_other_threads(tsk);
d344193a05da8 (Oleg Nesterov               2010-05-26 14:43:11 -0700 1062) 	if (!thread_group_leader(tsk))
d344193a05da8 (Oleg Nesterov               2010-05-26 14:43:11 -0700 1063) 		sig->notify_count--;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1064) 
d344193a05da8 (Oleg Nesterov               2010-05-26 14:43:11 -0700 1065) 	while (sig->notify_count) {
d5bbd43d5f450 (Oleg Nesterov               2012-10-08 19:13:01 +0200 1066) 		__set_current_state(TASK_KILLABLE);
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1067) 		spin_unlock_irq(lock);
a72173ecfc677 (Rafael J. Wysocki           2018-12-03 13:04:18 +0100 1068) 		schedule();
08d405c8b845a (Davidlohr Bueso             2019-01-03 15:28:58 -0800 1069) 		if (__fatal_signal_pending(tsk))
d5bbd43d5f450 (Oleg Nesterov               2012-10-08 19:13:01 +0200 1070) 			goto killed;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1071) 		spin_lock_irq(lock);
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1072) 	}
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1073) 	spin_unlock_irq(lock);
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1074) 
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1075) 	/*
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1076) 	 * At this point all other threads have exited, all we have to
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1077) 	 * do is to wait for the thread group leader to become inactive,
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1078) 	 * and to assume its PID:
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1079) 	 */
aafe6c2a2b6bc (Eric W. Biederman           2006-09-27 01:51:13 -0700 1080) 	if (!thread_group_leader(tsk)) {
8187926bdae98 (Oleg Nesterov               2008-12-01 14:18:16 -0800 1081) 		struct task_struct *leader = tsk->group_leader;
6db840fa78879 (Oleg Nesterov               2007-10-16 23:27:23 -0700 1082) 
6db840fa78879 (Oleg Nesterov               2007-10-16 23:27:23 -0700 1083) 		for (;;) {
780de9dd2720d (Ingo Molnar                 2017-02-02 11:50:56 +0100 1084) 			cgroup_threadgroup_change_begin(tsk);
6db840fa78879 (Oleg Nesterov               2007-10-16 23:27:23 -0700 1085) 			write_lock_irq(&tasklist_lock);
dfcce791fb0ad (Kirill Tkhai                2015-04-16 12:48:01 -0700 1086) 			/*
dfcce791fb0ad (Kirill Tkhai                2015-04-16 12:48:01 -0700 1087) 			 * Do this under tasklist_lock to ensure that
dfcce791fb0ad (Kirill Tkhai                2015-04-16 12:48:01 -0700 1088) 			 * exit_notify() can't miss ->group_exit_task
dfcce791fb0ad (Kirill Tkhai                2015-04-16 12:48:01 -0700 1089) 			 */
dfcce791fb0ad (Kirill Tkhai                2015-04-16 12:48:01 -0700 1090) 			sig->notify_count = -1;
6db840fa78879 (Oleg Nesterov               2007-10-16 23:27:23 -0700 1091) 			if (likely(leader->exit_state))
6db840fa78879 (Oleg Nesterov               2007-10-16 23:27:23 -0700 1092) 				break;
d5bbd43d5f450 (Oleg Nesterov               2012-10-08 19:13:01 +0200 1093) 			__set_current_state(TASK_KILLABLE);
6db840fa78879 (Oleg Nesterov               2007-10-16 23:27:23 -0700 1094) 			write_unlock_irq(&tasklist_lock);
780de9dd2720d (Ingo Molnar                 2017-02-02 11:50:56 +0100 1095) 			cgroup_threadgroup_change_end(tsk);
a72173ecfc677 (Rafael J. Wysocki           2018-12-03 13:04:18 +0100 1096) 			schedule();
08d405c8b845a (Davidlohr Bueso             2019-01-03 15:28:58 -0800 1097) 			if (__fatal_signal_pending(tsk))
d5bbd43d5f450 (Oleg Nesterov               2012-10-08 19:13:01 +0200 1098) 				goto killed;
6db840fa78879 (Oleg Nesterov               2007-10-16 23:27:23 -0700 1099) 		}
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1100) 
f5e902817fee1 (Roland McGrath              2006-04-10 22:54:16 -0700 1101) 		/*
f5e902817fee1 (Roland McGrath              2006-04-10 22:54:16 -0700 1102) 		 * The only record we have of the real-time age of a
f5e902817fee1 (Roland McGrath              2006-04-10 22:54:16 -0700 1103) 		 * process, regardless of execs it's done, is start_time.
f5e902817fee1 (Roland McGrath              2006-04-10 22:54:16 -0700 1104) 		 * All the past CPU time is accumulated in signal_struct
f5e902817fee1 (Roland McGrath              2006-04-10 22:54:16 -0700 1105) 		 * from sister threads now dead.  But in this non-leader
f5e902817fee1 (Roland McGrath              2006-04-10 22:54:16 -0700 1106) 		 * exec, nothing survives from the original leader thread,
f5e902817fee1 (Roland McGrath              2006-04-10 22:54:16 -0700 1107) 		 * whose birth marks the true age of this process now.
f5e902817fee1 (Roland McGrath              2006-04-10 22:54:16 -0700 1108) 		 * When we take on its identity by switching to its PID, we
f5e902817fee1 (Roland McGrath              2006-04-10 22:54:16 -0700 1109) 		 * also take its birthdate (always earlier than our own).
f5e902817fee1 (Roland McGrath              2006-04-10 22:54:16 -0700 1110) 		 */
aafe6c2a2b6bc (Eric W. Biederman           2006-09-27 01:51:13 -0700 1111) 		tsk->start_time = leader->start_time;
cf25e24db61cc (Peter Zijlstra              2019-11-07 11:07:58 +0100 1112) 		tsk->start_boottime = leader->start_boottime;
f5e902817fee1 (Roland McGrath              2006-04-10 22:54:16 -0700 1113) 
bac0abd6174e4 (Pavel Emelyanov             2007-10-18 23:40:18 -0700 1114) 		BUG_ON(!same_thread_group(leader, tsk));
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1115) 		/*
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1116) 		 * An exec() starts a new thread group with the
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1117) 		 * TGID of the previous thread group. Rehash the
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1118) 		 * two threads with a switched PID, and release
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1119) 		 * the former thread group leader:
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1120) 		 */
d73d65293e3e2 (Eric W. Biederman           2006-03-28 16:11:03 -0800 1121) 
d73d65293e3e2 (Eric W. Biederman           2006-03-28 16:11:03 -0800 1122) 		/* Become a process group leader with the old leader's pid.
c18258c6f0848 (Eric W. Biederman           2006-09-27 01:51:06 -0700 1123) 		 * The old leader becomes a thread of the this thread group.
d73d65293e3e2 (Eric W. Biederman           2006-03-28 16:11:03 -0800 1124) 		 */
6b03d1304a32d (Eric W. Biederman           2020-04-19 06:35:02 -0500 1125) 		exchange_tids(tsk, leader);
6883f81aac6f4 (Eric W. Biederman           2017-06-04 04:32:13 -0500 1126) 		transfer_pid(leader, tsk, PIDTYPE_TGID);
aafe6c2a2b6bc (Eric W. Biederman           2006-09-27 01:51:13 -0700 1127) 		transfer_pid(leader, tsk, PIDTYPE_PGID);
aafe6c2a2b6bc (Eric W. Biederman           2006-09-27 01:51:13 -0700 1128) 		transfer_pid(leader, tsk, PIDTYPE_SID);
9cd80bbb07fcd (Oleg Nesterov               2009-12-17 15:27:15 -0800 1129) 
aafe6c2a2b6bc (Eric W. Biederman           2006-09-27 01:51:13 -0700 1130) 		list_replace_rcu(&leader->tasks, &tsk->tasks);
9cd80bbb07fcd (Oleg Nesterov               2009-12-17 15:27:15 -0800 1131) 		list_replace_init(&leader->sibling, &tsk->sibling);
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1132) 
aafe6c2a2b6bc (Eric W. Biederman           2006-09-27 01:51:13 -0700 1133) 		tsk->group_leader = tsk;
aafe6c2a2b6bc (Eric W. Biederman           2006-09-27 01:51:13 -0700 1134) 		leader->group_leader = tsk;
de12a7878c11f (Eric W. Biederman           2006-04-10 17:16:49 -0600 1135) 
aafe6c2a2b6bc (Eric W. Biederman           2006-09-27 01:51:13 -0700 1136) 		tsk->exit_signal = SIGCHLD;
087806b128156 (Oleg Nesterov               2011-06-22 23:10:26 +0200 1137) 		leader->exit_signal = -1;
962b564cf1ec8 (Oleg Nesterov               2005-11-23 13:37:43 -0800 1138) 
962b564cf1ec8 (Oleg Nesterov               2005-11-23 13:37:43 -0800 1139) 		BUG_ON(leader->exit_state != EXIT_ZOMBIE);
962b564cf1ec8 (Oleg Nesterov               2005-11-23 13:37:43 -0800 1140) 		leader->exit_state = EXIT_DEAD;
eac1b5e57d7ab (Oleg Nesterov               2011-07-21 20:00:43 +0200 1141) 
eac1b5e57d7ab (Oleg Nesterov               2011-07-21 20:00:43 +0200 1142) 		/*
eac1b5e57d7ab (Oleg Nesterov               2011-07-21 20:00:43 +0200 1143) 		 * We are going to release_task()->ptrace_unlink() silently,
eac1b5e57d7ab (Oleg Nesterov               2011-07-21 20:00:43 +0200 1144) 		 * the tracer can sleep in do_wait(). EXIT_DEAD guarantees
eac1b5e57d7ab (Oleg Nesterov               2011-07-21 20:00:43 +0200 1145) 		 * the tracer wont't block again waiting for this thread.
eac1b5e57d7ab (Oleg Nesterov               2011-07-21 20:00:43 +0200 1146) 		 */
eac1b5e57d7ab (Oleg Nesterov               2011-07-21 20:00:43 +0200 1147) 		if (unlikely(leader->ptrace))
eac1b5e57d7ab (Oleg Nesterov               2011-07-21 20:00:43 +0200 1148) 			__wake_up_parent(leader, leader->parent);
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1149) 		write_unlock_irq(&tasklist_lock);
780de9dd2720d (Ingo Molnar                 2017-02-02 11:50:56 +0100 1150) 		cgroup_threadgroup_change_end(tsk);
8187926bdae98 (Oleg Nesterov               2008-12-01 14:18:16 -0800 1151) 
8187926bdae98 (Oleg Nesterov               2008-12-01 14:18:16 -0800 1152) 		release_task(leader);
ed5d2cac11420 (Oleg Nesterov               2008-02-04 22:27:24 -0800 1153) 	}
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1154) 
6db840fa78879 (Oleg Nesterov               2007-10-16 23:27:23 -0700 1155) 	sig->group_exit_task = NULL;
6db840fa78879 (Oleg Nesterov               2007-10-16 23:27:23 -0700 1156) 	sig->notify_count = 0;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1157) 
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1158) no_thread_group:
e636825346b36 (Oleg Nesterov               2012-03-19 17:03:22 +0100 1159) 	/* we have changed execution domain */
e636825346b36 (Oleg Nesterov               2012-03-19 17:03:22 +0100 1160) 	tsk->exit_signal = SIGCHLD;
e636825346b36 (Oleg Nesterov               2012-03-19 17:03:22 +0100 1161) 
0216915592454 (Eric W. Biederman           2020-03-25 10:00:21 -0500 1162) 	BUG_ON(!thread_group_leader(tsk));
0216915592454 (Eric W. Biederman           2020-03-25 10:00:21 -0500 1163) 	return 0;
0216915592454 (Eric W. Biederman           2020-03-25 10:00:21 -0500 1164) 
0216915592454 (Eric W. Biederman           2020-03-25 10:00:21 -0500 1165) killed:
0216915592454 (Eric W. Biederman           2020-03-25 10:00:21 -0500 1166) 	/* protects against exit_notify() and __exit_signal() */
0216915592454 (Eric W. Biederman           2020-03-25 10:00:21 -0500 1167) 	read_lock(&tasklist_lock);
0216915592454 (Eric W. Biederman           2020-03-25 10:00:21 -0500 1168) 	sig->group_exit_task = NULL;
0216915592454 (Eric W. Biederman           2020-03-25 10:00:21 -0500 1169) 	sig->notify_count = 0;
0216915592454 (Eric W. Biederman           2020-03-25 10:00:21 -0500 1170) 	read_unlock(&tasklist_lock);
0216915592454 (Eric W. Biederman           2020-03-25 10:00:21 -0500 1171) 	return -EAGAIN;
0216915592454 (Eric W. Biederman           2020-03-25 10:00:21 -0500 1172) }
0216915592454 (Eric W. Biederman           2020-03-25 10:00:21 -0500 1173) 
0216915592454 (Eric W. Biederman           2020-03-25 10:00:21 -0500 1174) 
7a60ef4803d54 (Eric W. Biederman           2020-03-08 12:04:44 -0500 1175) /*
7a60ef4803d54 (Eric W. Biederman           2020-03-08 12:04:44 -0500 1176)  * This function makes sure the current process has its own signal table,
7a60ef4803d54 (Eric W. Biederman           2020-03-08 12:04:44 -0500 1177)  * so that flush_signal_handlers can later reset the handlers without
7a60ef4803d54 (Eric W. Biederman           2020-03-08 12:04:44 -0500 1178)  * disturbing other processes.  (Other processes might share the signal
7a60ef4803d54 (Eric W. Biederman           2020-03-08 12:04:44 -0500 1179)  * table via the CLONE_SIGHAND option to clone().)
7a60ef4803d54 (Eric W. Biederman           2020-03-08 12:04:44 -0500 1180)  */
0216915592454 (Eric W. Biederman           2020-03-25 10:00:21 -0500 1181) static int unshare_sighand(struct task_struct *me)
0216915592454 (Eric W. Biederman           2020-03-25 10:00:21 -0500 1182) {
0216915592454 (Eric W. Biederman           2020-03-25 10:00:21 -0500 1183) 	struct sighand_struct *oldsighand = me->sighand;
329f7dba5f7dc (Oleg Nesterov               2005-11-07 21:12:43 +0300 1184) 
d036bda7d0e72 (Elena Reshetova             2019-01-18 14:27:26 +0200 1185) 	if (refcount_read(&oldsighand->count) != 1) {
b2c903b879046 (Oleg Nesterov               2007-10-16 23:27:22 -0700 1186) 		struct sighand_struct *newsighand;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1187) 		/*
b2c903b879046 (Oleg Nesterov               2007-10-16 23:27:22 -0700 1188) 		 * This ->sighand is shared with the CLONE_SIGHAND
b2c903b879046 (Oleg Nesterov               2007-10-16 23:27:22 -0700 1189) 		 * but not CLONE_THREAD task, switch to the new one.
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1190) 		 */
b2c903b879046 (Oleg Nesterov               2007-10-16 23:27:22 -0700 1191) 		newsighand = kmem_cache_alloc(sighand_cachep, GFP_KERNEL);
b2c903b879046 (Oleg Nesterov               2007-10-16 23:27:22 -0700 1192) 		if (!newsighand)
b2c903b879046 (Oleg Nesterov               2007-10-16 23:27:22 -0700 1193) 			return -ENOMEM;
b2c903b879046 (Oleg Nesterov               2007-10-16 23:27:22 -0700 1194) 
d036bda7d0e72 (Elena Reshetova             2019-01-18 14:27:26 +0200 1195) 		refcount_set(&newsighand->count, 1);
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1196) 		memcpy(newsighand->action, oldsighand->action,
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1197) 		       sizeof(newsighand->action));
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1198) 
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1199) 		write_lock_irq(&tasklist_lock);
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1200) 		spin_lock(&oldsighand->siglock);
0216915592454 (Eric W. Biederman           2020-03-25 10:00:21 -0500 1201) 		rcu_assign_pointer(me->sighand, newsighand);
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1202) 		spin_unlock(&oldsighand->siglock);
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1203) 		write_unlock_irq(&tasklist_lock);
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1204) 
fba2afaaec790 (Davide Libenzi              2007-05-10 22:23:13 -0700 1205) 		__cleanup_sighand(oldsighand);
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1206) 	}
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1207) 	return 0;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1208) }
0840a90d943bc (Oleg Nesterov               2007-10-16 23:27:22 -0700 1209) 
3756f6401c302 (Arnd Bergmann               2017-12-14 15:32:41 -0800 1210) char *__get_task_comm(char *buf, size_t buf_size, struct task_struct *tsk)
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1211) {
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1212) 	task_lock(tsk);
3756f6401c302 (Arnd Bergmann               2017-12-14 15:32:41 -0800 1213) 	strncpy(buf, tsk->comm, buf_size);
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1214) 	task_unlock(tsk);
59714d65dfbc8 (Andrew Morton               2008-02-04 22:27:21 -0800 1215) 	return buf;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1216) }
3756f6401c302 (Arnd Bergmann               2017-12-14 15:32:41 -0800 1217) EXPORT_SYMBOL_GPL(__get_task_comm);
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1218) 
6a6d27de340c8 (Al Viro                     2012-08-21 09:56:33 -0400 1219) /*
6a6d27de340c8 (Al Viro                     2012-08-21 09:56:33 -0400 1220)  * These functions flushes out all traces of the currently running executable
6a6d27de340c8 (Al Viro                     2012-08-21 09:56:33 -0400 1221)  * so that a new one can be started
6a6d27de340c8 (Al Viro                     2012-08-21 09:56:33 -0400 1222)  */
6a6d27de340c8 (Al Viro                     2012-08-21 09:56:33 -0400 1223) 
82b897782d10f (Adrian Hunter               2014-05-28 11:45:04 +0300 1224) void __set_task_comm(struct task_struct *tsk, const char *buf, bool exec)
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1225) {
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1226) 	task_lock(tsk);
43d2b113241d6 (KAMEZAWA Hiroyuki           2012-01-10 15:08:09 -0800 1227) 	trace_task_rename(tsk, buf);
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1228) 	strlcpy(tsk->comm, buf, sizeof(tsk->comm));
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1229) 	task_unlock(tsk);
82b897782d10f (Adrian Hunter               2014-05-28 11:45:04 +0300 1230) 	perf_event_comm(tsk, exec);
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1231) }
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1232) 
a9208e42ba99b (Kees Cook                   2017-07-18 15:25:30 -0700 1233) /*
a9208e42ba99b (Kees Cook                   2017-07-18 15:25:30 -0700 1234)  * Calling this is the point of no return. None of the failures will be
a9208e42ba99b (Kees Cook                   2017-07-18 15:25:30 -0700 1235)  * seen by userspace since either the process is already taking a fatal
a9208e42ba99b (Kees Cook                   2017-07-18 15:25:30 -0700 1236)  * signal (via de_thread() or coredump), or will have SEGV raised
13c432b51449d (Eric W. Biederman           2020-03-19 17:16:12 -0500 1237)  * (after exec_mmap()) by search_binary_handler (see below).
a9208e42ba99b (Kees Cook                   2017-07-18 15:25:30 -0700 1238)  */
2388777a0a595 (Eric W. Biederman           2020-05-03 07:54:10 -0500 1239) int begin_new_exec(struct linux_binprm * bprm)
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1240) {
2ca7be7d55ad8 (Eric W. Biederman           2020-03-25 10:00:07 -0500 1241) 	struct task_struct *me = current;
221af7f87b974 (Linus Torvalds              2010-01-28 22:14:42 -0800 1242) 	int retval;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1243) 
56305aa9b6fab (Eric W. Biederman           2020-05-29 22:00:54 -0500 1244) 	/* Once we are committed compute the creds */
56305aa9b6fab (Eric W. Biederman           2020-05-29 22:00:54 -0500 1245) 	retval = bprm_creds_from_file(bprm);
56305aa9b6fab (Eric W. Biederman           2020-05-29 22:00:54 -0500 1246) 	if (retval)
56305aa9b6fab (Eric W. Biederman           2020-05-29 22:00:54 -0500 1247) 		return retval;
56305aa9b6fab (Eric W. Biederman           2020-05-29 22:00:54 -0500 1248) 
6834e0bb41bbe (Eric W. Biederman           2020-04-04 12:01:37 -0500 1249) 	/*
6834e0bb41bbe (Eric W. Biederman           2020-04-04 12:01:37 -0500 1250) 	 * Ensure all future errors are fatal.
6834e0bb41bbe (Eric W. Biederman           2020-04-04 12:01:37 -0500 1251) 	 */
6834e0bb41bbe (Eric W. Biederman           2020-04-04 12:01:37 -0500 1252) 	bprm->point_of_no_return = true;
6834e0bb41bbe (Eric W. Biederman           2020-04-04 12:01:37 -0500 1253) 
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1254) 	/*
0216915592454 (Eric W. Biederman           2020-03-25 10:00:21 -0500 1255) 	 * Make this the only thread in the thread group.
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1256) 	 */
2ca7be7d55ad8 (Eric W. Biederman           2020-03-25 10:00:07 -0500 1257) 	retval = de_thread(me);
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1258) 	if (retval)
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1259) 		goto out;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1260) 
9ee1206dcfb9d (Eric W. Biederman           2020-11-30 16:58:46 -0600 1261) 	/*
9ee1206dcfb9d (Eric W. Biederman           2020-11-30 16:58:46 -0600 1262) 	 * Cancel any io_uring activity across execve
9ee1206dcfb9d (Eric W. Biederman           2020-11-30 16:58:46 -0600 1263) 	 */
9ee1206dcfb9d (Eric W. Biederman           2020-11-30 16:58:46 -0600 1264) 	io_uring_task_cancel();
9ee1206dcfb9d (Eric W. Biederman           2020-11-30 16:58:46 -0600 1265) 
b6043501289eb (Eric W. Biederman           2020-11-20 17:14:18 -0600 1266) 	/* Ensure the files table is not shared. */
1f702603e7125 (Eric W. Biederman           2020-11-20 17:14:19 -0600 1267) 	retval = unshare_files();
b6043501289eb (Eric W. Biederman           2020-11-20 17:14:18 -0600 1268) 	if (retval)
b6043501289eb (Eric W. Biederman           2020-11-20 17:14:18 -0600 1269) 		goto out;
b6043501289eb (Eric W. Biederman           2020-11-20 17:14:18 -0600 1270) 
6e399cd144d85 (Davidlohr Bueso             2015-04-16 12:47:59 -0700 1271) 	/*
6e399cd144d85 (Davidlohr Bueso             2015-04-16 12:47:59 -0700 1272) 	 * Must be called _before_ exec_mmap() as bprm->mm is
6e399cd144d85 (Davidlohr Bueso             2015-04-16 12:47:59 -0700 1273) 	 * not visibile until then. This also enables the update
6e399cd144d85 (Davidlohr Bueso             2015-04-16 12:47:59 -0700 1274) 	 * to be lockless.
6e399cd144d85 (Davidlohr Bueso             2015-04-16 12:47:59 -0700 1275) 	 */
925d1c401fa6c (Matt Helsley                2008-04-29 01:01:36 -0700 1276) 	set_mm_exe_file(bprm->mm, bprm->file);
6e399cd144d85 (Davidlohr Bueso             2015-04-16 12:47:59 -0700 1277) 
b8a61c9e7b4a0 (Eric W. Biederman           2020-05-14 15:17:40 -0500 1278) 	/* If the binary is not readable then enforce mm->dumpable=0 */
f87d1c9559164 (Eric W. Biederman           2020-05-16 16:29:20 -0500 1279) 	would_dump(bprm, bprm->file);
b8a61c9e7b4a0 (Eric W. Biederman           2020-05-14 15:17:40 -0500 1280) 	if (bprm->have_execfd)
b8a61c9e7b4a0 (Eric W. Biederman           2020-05-14 15:17:40 -0500 1281) 		would_dump(bprm, bprm->executable);
f87d1c9559164 (Eric W. Biederman           2020-05-16 16:29:20 -0500 1282) 
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1283) 	/*
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1284) 	 * Release all of the old mmap stuff
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1285) 	 */
3c77f84572215 (Oleg Nesterov               2010-11-30 20:55:34 +0100 1286) 	acct_arg_size(bprm, 0);
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1287) 	retval = exec_mmap(bprm->mm);
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1288) 	if (retval)
fd8328be874f4 (Al Viro                     2008-04-22 05:11:59 -0400 1289) 		goto out;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1290) 
a9208e42ba99b (Kees Cook                   2017-07-18 15:25:30 -0700 1291) 	bprm->mm = NULL;
7ab02af428c2d (Linus Torvalds              2010-02-02 12:37:44 -0800 1292) 
ccf0fa6be0268 (Eric W. Biederman           2020-03-25 10:03:21 -0500 1293) #ifdef CONFIG_POSIX_TIMERS
ccf0fa6be0268 (Eric W. Biederman           2020-03-25 10:03:21 -0500 1294) 	exit_itimers(me->signal);
ccf0fa6be0268 (Eric W. Biederman           2020-03-25 10:03:21 -0500 1295) 	flush_itimer_signals();
ccf0fa6be0268 (Eric W. Biederman           2020-03-25 10:03:21 -0500 1296) #endif
ccf0fa6be0268 (Eric W. Biederman           2020-03-25 10:03:21 -0500 1297) 
ccf0fa6be0268 (Eric W. Biederman           2020-03-25 10:03:21 -0500 1298) 	/*
ccf0fa6be0268 (Eric W. Biederman           2020-03-25 10:03:21 -0500 1299) 	 * Make the signal table private.
ccf0fa6be0268 (Eric W. Biederman           2020-03-25 10:03:21 -0500 1300) 	 */
ccf0fa6be0268 (Eric W. Biederman           2020-03-25 10:03:21 -0500 1301) 	retval = unshare_sighand(me);
ccf0fa6be0268 (Eric W. Biederman           2020-03-25 10:03:21 -0500 1302) 	if (retval)
89826cce37542 (Eric W. Biederman           2020-04-02 18:04:54 -0500 1303) 		goto out_unlock;
ccf0fa6be0268 (Eric W. Biederman           2020-03-25 10:03:21 -0500 1304) 
fe81417596fa8 (Christoph Hellwig           2020-08-11 18:33:50 -0700 1305) 	/*
fe81417596fa8 (Christoph Hellwig           2020-08-11 18:33:50 -0700 1306) 	 * Ensure that the uaccess routines can actually operate on userspace
fe81417596fa8 (Christoph Hellwig           2020-08-11 18:33:50 -0700 1307) 	 * pointers:
fe81417596fa8 (Christoph Hellwig           2020-08-11 18:33:50 -0700 1308) 	 */
fe81417596fa8 (Christoph Hellwig           2020-08-11 18:33:50 -0700 1309) 	force_uaccess_begin();
fe81417596fa8 (Christoph Hellwig           2020-08-11 18:33:50 -0700 1310) 
2ca7be7d55ad8 (Eric W. Biederman           2020-03-25 10:00:07 -0500 1311) 	me->flags &= ~(PF_RANDOMIZE | PF_FORKNOEXEC | PF_KTHREAD |
b88fae644e5e3 (Zhang Yi                    2014-01-23 15:55:57 -0800 1312) 					PF_NOFREEZE | PF_NO_SETAFFINITY);
7ab02af428c2d (Linus Torvalds              2010-02-02 12:37:44 -0800 1313) 	flush_thread();
2ca7be7d55ad8 (Eric W. Biederman           2020-03-25 10:00:07 -0500 1314) 	me->personality &= ~bprm->per_clear;
7ab02af428c2d (Linus Torvalds              2010-02-02 12:37:44 -0800 1315) 
1446e1df9eb18 (Gabriel Krisman Bertazi     2020-11-27 14:32:34 -0500 1316) 	clear_syscall_work_syscall_user_dispatch(me);
1446e1df9eb18 (Gabriel Krisman Bertazi     2020-11-27 14:32:34 -0500 1317) 
613cc2b6f272c (Aleksa Sarai                2016-12-21 16:26:24 +1100 1318) 	/*
613cc2b6f272c (Aleksa Sarai                2016-12-21 16:26:24 +1100 1319) 	 * We have to apply CLOEXEC before we change whether the process is
613cc2b6f272c (Aleksa Sarai                2016-12-21 16:26:24 +1100 1320) 	 * dumpable (in setup_new_exec) to avoid a race with a process in userspace
613cc2b6f272c (Aleksa Sarai                2016-12-21 16:26:24 +1100 1321) 	 * trying to access the should-be-closed file descriptors of a process
613cc2b6f272c (Aleksa Sarai                2016-12-21 16:26:24 +1100 1322) 	 * undergoing exec(2).
613cc2b6f272c (Aleksa Sarai                2016-12-21 16:26:24 +1100 1323) 	 */
2ca7be7d55ad8 (Eric W. Biederman           2020-03-25 10:00:07 -0500 1324) 	do_close_on_exec(me->files);
f84df2a6f268d (Eric W. Biederman           2016-11-16 22:06:51 -0600 1325) 
64701dee4178e (Kees Cook                   2017-07-18 15:25:35 -0700 1326) 	if (bprm->secureexec) {
fe8993b3a05cb (Kees Cook                   2017-07-18 15:25:36 -0700 1327) 		/* Make sure parent cannot signal privileged process. */
7d503feba0c88 (Eric W. Biederman           2020-04-02 18:35:14 -0500 1328) 		me->pdeath_signal = 0;
fe8993b3a05cb (Kees Cook                   2017-07-18 15:25:36 -0700 1329) 
64701dee4178e (Kees Cook                   2017-07-18 15:25:35 -0700 1330) 		/*
64701dee4178e (Kees Cook                   2017-07-18 15:25:35 -0700 1331) 		 * For secureexec, reset the stack limit to sane default to
64701dee4178e (Kees Cook                   2017-07-18 15:25:35 -0700 1332) 		 * avoid bad behavior from the prior rlimits. This has to
64701dee4178e (Kees Cook                   2017-07-18 15:25:35 -0700 1333) 		 * happen before arch_pick_mmap_layout(), which examines
64701dee4178e (Kees Cook                   2017-07-18 15:25:35 -0700 1334) 		 * RLIMIT_STACK, but after the point of no return to avoid
779f4e1c6c7c6 (Kees Cook                   2017-12-12 11:28:38 -0800 1335) 		 * needing to clean up the change on failure.
64701dee4178e (Kees Cook                   2017-07-18 15:25:35 -0700 1336) 		 */
c31dbb146dd44 (Kees Cook                   2018-04-10 16:35:01 -0700 1337) 		if (bprm->rlim_stack.rlim_cur > _STK_LIM)
c31dbb146dd44 (Kees Cook                   2018-04-10 16:35:01 -0700 1338) 			bprm->rlim_stack.rlim_cur = _STK_LIM;
64701dee4178e (Kees Cook                   2017-07-18 15:25:35 -0700 1339) 	}
64701dee4178e (Kees Cook                   2017-07-18 15:25:35 -0700 1340) 
7d503feba0c88 (Eric W. Biederman           2020-04-02 18:35:14 -0500 1341) 	me->sas_ss_sp = me->sas_ss_size = 0;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1342) 
e816c201aed52 (Kees Cook                   2018-01-02 15:21:33 -0800 1343) 	/*
e816c201aed52 (Kees Cook                   2018-01-02 15:21:33 -0800 1344) 	 * Figure out dumpability. Note that this checking only of current
e816c201aed52 (Kees Cook                   2018-01-02 15:21:33 -0800 1345) 	 * is wrong, but userspace depends on it. This should be testing
e816c201aed52 (Kees Cook                   2018-01-02 15:21:33 -0800 1346) 	 * bprm->secureexec instead.
e816c201aed52 (Kees Cook                   2018-01-02 15:21:33 -0800 1347) 	 */
473d89639db0a (Kees Cook                   2017-07-18 15:25:34 -0700 1348) 	if (bprm->interp_flags & BINPRM_FLAGS_ENFORCE_NONDUMP ||
e816c201aed52 (Kees Cook                   2018-01-02 15:21:33 -0800 1349) 	    !(uid_eq(current_euid(), current_uid()) &&
e816c201aed52 (Kees Cook                   2018-01-02 15:21:33 -0800 1350) 	      gid_eq(current_egid(), current_gid())))
6c5d523826dc6 (Kawai, Hidehiro             2007-07-19 01:48:27 -0700 1351) 		set_dumpable(current->mm, suid_dumpable);
473d89639db0a (Kees Cook                   2017-07-18 15:25:34 -0700 1352) 	else
473d89639db0a (Kees Cook                   2017-07-18 15:25:34 -0700 1353) 		set_dumpable(current->mm, SUID_DUMP_USER);
d6e711448137c (Alan Cox                    2005-06-23 00:09:43 -0700 1354) 
e041e328c4b41 (Peter Zijlstra              2014-05-21 17:32:19 +0200 1355) 	perf_event_exec();
7d503feba0c88 (Eric W. Biederman           2020-04-02 18:35:14 -0500 1356) 	__set_task_comm(me, kbasename(bprm->filename), true);
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1357) 
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1358) 	/* An exec changes our domain. We are no longer part of the thread
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1359) 	   group */
7d503feba0c88 (Eric W. Biederman           2020-04-02 18:35:14 -0500 1360) 	WRITE_ONCE(me->self_exec_id, me->self_exec_id + 1);
7d503feba0c88 (Eric W. Biederman           2020-04-02 18:35:14 -0500 1361) 	flush_signal_handlers(me, 0);
96ecee29b0b56 (Eric W. Biederman           2020-05-03 06:48:17 -0500 1362) 
1199573d26016 (Alexey Gladkov              2021-04-22 14:27:09 +0200 1363) 	retval = set_cred_ucounts(bprm->cred);
1199573d26016 (Alexey Gladkov              2021-04-22 14:27:09 +0200 1364) 	if (retval < 0)
1199573d26016 (Alexey Gladkov              2021-04-22 14:27:09 +0200 1365) 		goto out_unlock;
1199573d26016 (Alexey Gladkov              2021-04-22 14:27:09 +0200 1366) 
96ecee29b0b56 (Eric W. Biederman           2020-05-03 06:48:17 -0500 1367) 	/*
96ecee29b0b56 (Eric W. Biederman           2020-05-03 06:48:17 -0500 1368) 	 * install the new credentials for this executable
96ecee29b0b56 (Eric W. Biederman           2020-05-03 06:48:17 -0500 1369) 	 */
96ecee29b0b56 (Eric W. Biederman           2020-05-03 06:48:17 -0500 1370) 	security_bprm_committing_creds(bprm);
96ecee29b0b56 (Eric W. Biederman           2020-05-03 06:48:17 -0500 1371) 
96ecee29b0b56 (Eric W. Biederman           2020-05-03 06:48:17 -0500 1372) 	commit_creds(bprm->cred);
96ecee29b0b56 (Eric W. Biederman           2020-05-03 06:48:17 -0500 1373) 	bprm->cred = NULL;
96ecee29b0b56 (Eric W. Biederman           2020-05-03 06:48:17 -0500 1374) 
96ecee29b0b56 (Eric W. Biederman           2020-05-03 06:48:17 -0500 1375) 	/*
96ecee29b0b56 (Eric W. Biederman           2020-05-03 06:48:17 -0500 1376) 	 * Disable monitoring for regular users
96ecee29b0b56 (Eric W. Biederman           2020-05-03 06:48:17 -0500 1377) 	 * when executing setuid binaries. Must
96ecee29b0b56 (Eric W. Biederman           2020-05-03 06:48:17 -0500 1378) 	 * wait until new credentials are committed
96ecee29b0b56 (Eric W. Biederman           2020-05-03 06:48:17 -0500 1379) 	 * by commit_creds() above
96ecee29b0b56 (Eric W. Biederman           2020-05-03 06:48:17 -0500 1380) 	 */
7d503feba0c88 (Eric W. Biederman           2020-04-02 18:35:14 -0500 1381) 	if (get_dumpable(me->mm) != SUID_DUMP_USER)
7d503feba0c88 (Eric W. Biederman           2020-04-02 18:35:14 -0500 1382) 		perf_event_exit_task(me);
96ecee29b0b56 (Eric W. Biederman           2020-05-03 06:48:17 -0500 1383) 	/*
96ecee29b0b56 (Eric W. Biederman           2020-05-03 06:48:17 -0500 1384) 	 * cred_guard_mutex must be held at least to this point to prevent
96ecee29b0b56 (Eric W. Biederman           2020-05-03 06:48:17 -0500 1385) 	 * ptrace_attach() from altering our determination of the task's
96ecee29b0b56 (Eric W. Biederman           2020-05-03 06:48:17 -0500 1386) 	 * credentials; any time after this it may be unlocked.
96ecee29b0b56 (Eric W. Biederman           2020-05-03 06:48:17 -0500 1387) 	 */
96ecee29b0b56 (Eric W. Biederman           2020-05-03 06:48:17 -0500 1388) 	security_bprm_committed_creds(bprm);
b8a61c9e7b4a0 (Eric W. Biederman           2020-05-14 15:17:40 -0500 1389) 
b8a61c9e7b4a0 (Eric W. Biederman           2020-05-14 15:17:40 -0500 1390) 	/* Pass the opened binary to the interpreter. */
b8a61c9e7b4a0 (Eric W. Biederman           2020-05-14 15:17:40 -0500 1391) 	if (bprm->have_execfd) {
b8a61c9e7b4a0 (Eric W. Biederman           2020-05-14 15:17:40 -0500 1392) 		retval = get_unused_fd_flags(0);
b8a61c9e7b4a0 (Eric W. Biederman           2020-05-14 15:17:40 -0500 1393) 		if (retval < 0)
b8a61c9e7b4a0 (Eric W. Biederman           2020-05-14 15:17:40 -0500 1394) 			goto out_unlock;
b8a61c9e7b4a0 (Eric W. Biederman           2020-05-14 15:17:40 -0500 1395) 		fd_install(retval, bprm->executable);
b8a61c9e7b4a0 (Eric W. Biederman           2020-05-14 15:17:40 -0500 1396) 		bprm->executable = NULL;
b8a61c9e7b4a0 (Eric W. Biederman           2020-05-14 15:17:40 -0500 1397) 		bprm->execfd = retval;
b8a61c9e7b4a0 (Eric W. Biederman           2020-05-14 15:17:40 -0500 1398) 	}
221af7f87b974 (Linus Torvalds              2010-01-28 22:14:42 -0800 1399) 	return 0;
221af7f87b974 (Linus Torvalds              2010-01-28 22:14:42 -0800 1400) 
df9e4d2c4a535 (Eric W. Biederman           2020-05-03 07:15:28 -0500 1401) out_unlock:
f7cfd871ae0c5 (Eric W. Biederman           2020-12-03 14:12:00 -0600 1402) 	up_write(&me->signal->exec_update_lock);
221af7f87b974 (Linus Torvalds              2010-01-28 22:14:42 -0800 1403) out:
221af7f87b974 (Linus Torvalds              2010-01-28 22:14:42 -0800 1404) 	return retval;
221af7f87b974 (Linus Torvalds              2010-01-28 22:14:42 -0800 1405) }
2388777a0a595 (Eric W. Biederman           2020-05-03 07:54:10 -0500 1406) EXPORT_SYMBOL(begin_new_exec);
221af7f87b974 (Linus Torvalds              2010-01-28 22:14:42 -0800 1407) 
1b5d783c94c32 (Al Viro                     2011-06-19 12:49:47 -0400 1408) void would_dump(struct linux_binprm *bprm, struct file *file)
1b5d783c94c32 (Al Viro                     2011-06-19 12:49:47 -0400 1409) {
f84df2a6f268d (Eric W. Biederman           2016-11-16 22:06:51 -0600 1410) 	struct inode *inode = file_inode(file);
435ac6214e00e (Christian Brauner           2021-01-21 14:19:41 +0100 1411) 	struct user_namespace *mnt_userns = file_mnt_user_ns(file);
435ac6214e00e (Christian Brauner           2021-01-21 14:19:41 +0100 1412) 	if (inode_permission(mnt_userns, inode, MAY_READ) < 0) {
f84df2a6f268d (Eric W. Biederman           2016-11-16 22:06:51 -0600 1413) 		struct user_namespace *old, *user_ns;
1b5d783c94c32 (Al Viro                     2011-06-19 12:49:47 -0400 1414) 		bprm->interp_flags |= BINPRM_FLAGS_ENFORCE_NONDUMP;
f84df2a6f268d (Eric W. Biederman           2016-11-16 22:06:51 -0600 1415) 
f84df2a6f268d (Eric W. Biederman           2016-11-16 22:06:51 -0600 1416) 		/* Ensure mm->user_ns contains the executable */
f84df2a6f268d (Eric W. Biederman           2016-11-16 22:06:51 -0600 1417) 		user_ns = old = bprm->mm->user_ns;
f84df2a6f268d (Eric W. Biederman           2016-11-16 22:06:51 -0600 1418) 		while ((user_ns != &init_user_ns) &&
435ac6214e00e (Christian Brauner           2021-01-21 14:19:41 +0100 1419) 		       !privileged_wrt_inode_uidgid(user_ns, mnt_userns, inode))
f84df2a6f268d (Eric W. Biederman           2016-11-16 22:06:51 -0600 1420) 			user_ns = user_ns->parent;
f84df2a6f268d (Eric W. Biederman           2016-11-16 22:06:51 -0600 1421) 
f84df2a6f268d (Eric W. Biederman           2016-11-16 22:06:51 -0600 1422) 		if (old != user_ns) {
f84df2a6f268d (Eric W. Biederman           2016-11-16 22:06:51 -0600 1423) 			bprm->mm->user_ns = get_user_ns(user_ns);
f84df2a6f268d (Eric W. Biederman           2016-11-16 22:06:51 -0600 1424) 			put_user_ns(old);
f84df2a6f268d (Eric W. Biederman           2016-11-16 22:06:51 -0600 1425) 		}
f84df2a6f268d (Eric W. Biederman           2016-11-16 22:06:51 -0600 1426) 	}
1b5d783c94c32 (Al Viro                     2011-06-19 12:49:47 -0400 1427) }
1b5d783c94c32 (Al Viro                     2011-06-19 12:49:47 -0400 1428) EXPORT_SYMBOL(would_dump);
1b5d783c94c32 (Al Viro                     2011-06-19 12:49:47 -0400 1429) 
221af7f87b974 (Linus Torvalds              2010-01-28 22:14:42 -0800 1430) void setup_new_exec(struct linux_binprm * bprm)
221af7f87b974 (Linus Torvalds              2010-01-28 22:14:42 -0800 1431) {
df9e4d2c4a535 (Eric W. Biederman           2020-05-03 07:15:28 -0500 1432) 	/* Setup things that can depend upon the personality */
df9e4d2c4a535 (Eric W. Biederman           2020-05-03 07:15:28 -0500 1433) 	struct task_struct *me = current;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1434) 
df9e4d2c4a535 (Eric W. Biederman           2020-05-03 07:15:28 -0500 1435) 	arch_pick_mmap_layout(me->mm, &bprm->rlim_stack);
d6e711448137c (Alan Cox                    2005-06-23 00:09:43 -0700 1436) 
e9ea1e7f53b85 (Kyle Huey                   2017-03-20 01:16:26 -0700 1437) 	arch_setup_new_exec();
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1438) 
0551fbd29e16f (Benjamin Herrenschmidt      2006-02-28 16:59:19 -0800 1439) 	/* Set the new mm task size. We have to do that late because it may
0551fbd29e16f (Benjamin Herrenschmidt      2006-02-28 16:59:19 -0800 1440) 	 * depend on TIF_32BIT which is only updated in flush_thread() on
0551fbd29e16f (Benjamin Herrenschmidt      2006-02-28 16:59:19 -0800 1441) 	 * some architectures like powerpc
0551fbd29e16f (Benjamin Herrenschmidt      2006-02-28 16:59:19 -0800 1442) 	 */
df9e4d2c4a535 (Eric W. Biederman           2020-05-03 07:15:28 -0500 1443) 	me->mm->task_size = TASK_SIZE;
f7cfd871ae0c5 (Eric W. Biederman           2020-12-03 14:12:00 -0600 1444) 	up_write(&me->signal->exec_update_lock);
7d503feba0c88 (Eric W. Biederman           2020-04-02 18:35:14 -0500 1445) 	mutex_unlock(&me->signal->cred_guard_mutex);
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1446) }
221af7f87b974 (Linus Torvalds              2010-01-28 22:14:42 -0800 1447) EXPORT_SYMBOL(setup_new_exec);
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1448) 
b83838313386f (Kees Cook                   2018-04-10 16:34:57 -0700 1449) /* Runs immediately before start_thread() takes over. */
b83838313386f (Kees Cook                   2018-04-10 16:34:57 -0700 1450) void finalize_exec(struct linux_binprm *bprm)
b83838313386f (Kees Cook                   2018-04-10 16:34:57 -0700 1451) {
c31dbb146dd44 (Kees Cook                   2018-04-10 16:35:01 -0700 1452) 	/* Store any stack rlimit changes before starting thread. */
c31dbb146dd44 (Kees Cook                   2018-04-10 16:35:01 -0700 1453) 	task_lock(current->group_leader);
c31dbb146dd44 (Kees Cook                   2018-04-10 16:35:01 -0700 1454) 	current->signal->rlim[RLIMIT_STACK] = bprm->rlim_stack;
c31dbb146dd44 (Kees Cook                   2018-04-10 16:35:01 -0700 1455) 	task_unlock(current->group_leader);
b83838313386f (Kees Cook                   2018-04-10 16:34:57 -0700 1456) }
b83838313386f (Kees Cook                   2018-04-10 16:34:57 -0700 1457) EXPORT_SYMBOL(finalize_exec);
b83838313386f (Kees Cook                   2018-04-10 16:34:57 -0700 1458) 
a2a8474c3fff8 (Oleg Nesterov               2009-09-05 11:17:13 -0700 1459) /*
a2a8474c3fff8 (Oleg Nesterov               2009-09-05 11:17:13 -0700 1460)  * Prepare credentials and lock ->cred_guard_mutex.
96ecee29b0b56 (Eric W. Biederman           2020-05-03 06:48:17 -0500 1461)  * setup_new_exec() commits the new creds and drops the lock.
3d742d4b6ebb3 (Randy Dunlap                2021-02-24 12:00:48 -0800 1462)  * Or, if exec fails before, free_bprm() should release ->cred
a2a8474c3fff8 (Oleg Nesterov               2009-09-05 11:17:13 -0700 1463)  * and unlock.
a2a8474c3fff8 (Oleg Nesterov               2009-09-05 11:17:13 -0700 1464)  */
4addd2640fcae (Chanho Min                  2018-12-10 16:49:54 +0900 1465) static int prepare_bprm_creds(struct linux_binprm *bprm)
a2a8474c3fff8 (Oleg Nesterov               2009-09-05 11:17:13 -0700 1466) {
9b1bf12d5d51b (KOSAKI Motohiro             2010-10-27 15:34:08 -0700 1467) 	if (mutex_lock_interruptible(&current->signal->cred_guard_mutex))
a2a8474c3fff8 (Oleg Nesterov               2009-09-05 11:17:13 -0700 1468) 		return -ERESTARTNOINTR;
a2a8474c3fff8 (Oleg Nesterov               2009-09-05 11:17:13 -0700 1469) 
a2a8474c3fff8 (Oleg Nesterov               2009-09-05 11:17:13 -0700 1470) 	bprm->cred = prepare_exec_creds();
a2a8474c3fff8 (Oleg Nesterov               2009-09-05 11:17:13 -0700 1471) 	if (likely(bprm->cred))
a2a8474c3fff8 (Oleg Nesterov               2009-09-05 11:17:13 -0700 1472) 		return 0;
a2a8474c3fff8 (Oleg Nesterov               2009-09-05 11:17:13 -0700 1473) 
9b1bf12d5d51b (KOSAKI Motohiro             2010-10-27 15:34:08 -0700 1474) 	mutex_unlock(&current->signal->cred_guard_mutex);
a2a8474c3fff8 (Oleg Nesterov               2009-09-05 11:17:13 -0700 1475) 	return -ENOMEM;
a2a8474c3fff8 (Oleg Nesterov               2009-09-05 11:17:13 -0700 1476) }
a2a8474c3fff8 (Oleg Nesterov               2009-09-05 11:17:13 -0700 1477) 
c4ad8f98bef77 (Linus Torvalds              2014-02-05 12:54:53 -0800 1478) static void free_bprm(struct linux_binprm *bprm)
a2a8474c3fff8 (Oleg Nesterov               2009-09-05 11:17:13 -0700 1479) {
f18ac551e5035 (Eric W. Biederman           2020-07-10 15:54:54 -0500 1480) 	if (bprm->mm) {
f18ac551e5035 (Eric W. Biederman           2020-07-10 15:54:54 -0500 1481) 		acct_arg_size(bprm, 0);
f18ac551e5035 (Eric W. Biederman           2020-07-10 15:54:54 -0500 1482) 		mmput(bprm->mm);
f18ac551e5035 (Eric W. Biederman           2020-07-10 15:54:54 -0500 1483) 	}
a2a8474c3fff8 (Oleg Nesterov               2009-09-05 11:17:13 -0700 1484) 	free_arg_pages(bprm);
a2a8474c3fff8 (Oleg Nesterov               2009-09-05 11:17:13 -0700 1485) 	if (bprm->cred) {
9b1bf12d5d51b (KOSAKI Motohiro             2010-10-27 15:34:08 -0700 1486) 		mutex_unlock(&current->signal->cred_guard_mutex);
a2a8474c3fff8 (Oleg Nesterov               2009-09-05 11:17:13 -0700 1487) 		abort_creds(bprm->cred);
a2a8474c3fff8 (Oleg Nesterov               2009-09-05 11:17:13 -0700 1488) 	}
63e46b95e9eae (Oleg Nesterov               2014-01-23 15:55:51 -0800 1489) 	if (bprm->file) {
63e46b95e9eae (Oleg Nesterov               2014-01-23 15:55:51 -0800 1490) 		allow_write_access(bprm->file);
63e46b95e9eae (Oleg Nesterov               2014-01-23 15:55:51 -0800 1491) 		fput(bprm->file);
63e46b95e9eae (Oleg Nesterov               2014-01-23 15:55:51 -0800 1492) 	}
b8a61c9e7b4a0 (Eric W. Biederman           2020-05-14 15:17:40 -0500 1493) 	if (bprm->executable)
b8a61c9e7b4a0 (Eric W. Biederman           2020-05-14 15:17:40 -0500 1494) 		fput(bprm->executable);
b66c598401753 (Kees Cook                   2012-12-20 15:05:16 -0800 1495) 	/* If a binfmt changed the interp, free it. */
b66c598401753 (Kees Cook                   2012-12-20 15:05:16 -0800 1496) 	if (bprm->interp != bprm->filename)
b66c598401753 (Kees Cook                   2012-12-20 15:05:16 -0800 1497) 		kfree(bprm->interp);
60d9ad1d1d7f1 (Eric W. Biederman           2020-07-11 08:16:15 -0500 1498) 	kfree(bprm->fdpath);
a2a8474c3fff8 (Oleg Nesterov               2009-09-05 11:17:13 -0700 1499) 	kfree(bprm);
a2a8474c3fff8 (Oleg Nesterov               2009-09-05 11:17:13 -0700 1500) }
a2a8474c3fff8 (Oleg Nesterov               2009-09-05 11:17:13 -0700 1501) 
60d9ad1d1d7f1 (Eric W. Biederman           2020-07-11 08:16:15 -0500 1502) static struct linux_binprm *alloc_bprm(int fd, struct filename *filename)
0a8f36eb48f64 (Eric W. Biederman           2020-07-10 15:39:45 -0500 1503) {
0a8f36eb48f64 (Eric W. Biederman           2020-07-10 15:39:45 -0500 1504) 	struct linux_binprm *bprm = kzalloc(sizeof(*bprm), GFP_KERNEL);
60d9ad1d1d7f1 (Eric W. Biederman           2020-07-11 08:16:15 -0500 1505) 	int retval = -ENOMEM;
0a8f36eb48f64 (Eric W. Biederman           2020-07-10 15:39:45 -0500 1506) 	if (!bprm)
60d9ad1d1d7f1 (Eric W. Biederman           2020-07-11 08:16:15 -0500 1507) 		goto out;
60d9ad1d1d7f1 (Eric W. Biederman           2020-07-11 08:16:15 -0500 1508) 
60d9ad1d1d7f1 (Eric W. Biederman           2020-07-11 08:16:15 -0500 1509) 	if (fd == AT_FDCWD || filename->name[0] == '/') {
60d9ad1d1d7f1 (Eric W. Biederman           2020-07-11 08:16:15 -0500 1510) 		bprm->filename = filename->name;
60d9ad1d1d7f1 (Eric W. Biederman           2020-07-11 08:16:15 -0500 1511) 	} else {
60d9ad1d1d7f1 (Eric W. Biederman           2020-07-11 08:16:15 -0500 1512) 		if (filename->name[0] == '\0')
60d9ad1d1d7f1 (Eric W. Biederman           2020-07-11 08:16:15 -0500 1513) 			bprm->fdpath = kasprintf(GFP_KERNEL, "/dev/fd/%d", fd);
60d9ad1d1d7f1 (Eric W. Biederman           2020-07-11 08:16:15 -0500 1514) 		else
60d9ad1d1d7f1 (Eric W. Biederman           2020-07-11 08:16:15 -0500 1515) 			bprm->fdpath = kasprintf(GFP_KERNEL, "/dev/fd/%d/%s",
60d9ad1d1d7f1 (Eric W. Biederman           2020-07-11 08:16:15 -0500 1516) 						  fd, filename->name);
60d9ad1d1d7f1 (Eric W. Biederman           2020-07-11 08:16:15 -0500 1517) 		if (!bprm->fdpath)
60d9ad1d1d7f1 (Eric W. Biederman           2020-07-11 08:16:15 -0500 1518) 			goto out_free;
60d9ad1d1d7f1 (Eric W. Biederman           2020-07-11 08:16:15 -0500 1519) 
60d9ad1d1d7f1 (Eric W. Biederman           2020-07-11 08:16:15 -0500 1520) 		bprm->filename = bprm->fdpath;
60d9ad1d1d7f1 (Eric W. Biederman           2020-07-11 08:16:15 -0500 1521) 	}
60d9ad1d1d7f1 (Eric W. Biederman           2020-07-11 08:16:15 -0500 1522) 	bprm->interp = bprm->filename;
f18ac551e5035 (Eric W. Biederman           2020-07-10 15:54:54 -0500 1523) 
f18ac551e5035 (Eric W. Biederman           2020-07-10 15:54:54 -0500 1524) 	retval = bprm_mm_init(bprm);
f18ac551e5035 (Eric W. Biederman           2020-07-10 15:54:54 -0500 1525) 	if (retval)
f18ac551e5035 (Eric W. Biederman           2020-07-10 15:54:54 -0500 1526) 		goto out_free;
0a8f36eb48f64 (Eric W. Biederman           2020-07-10 15:39:45 -0500 1527) 	return bprm;
60d9ad1d1d7f1 (Eric W. Biederman           2020-07-11 08:16:15 -0500 1528) 
60d9ad1d1d7f1 (Eric W. Biederman           2020-07-11 08:16:15 -0500 1529) out_free:
60d9ad1d1d7f1 (Eric W. Biederman           2020-07-11 08:16:15 -0500 1530) 	free_bprm(bprm);
60d9ad1d1d7f1 (Eric W. Biederman           2020-07-11 08:16:15 -0500 1531) out:
60d9ad1d1d7f1 (Eric W. Biederman           2020-07-11 08:16:15 -0500 1532) 	return ERR_PTR(retval);
0a8f36eb48f64 (Eric W. Biederman           2020-07-10 15:39:45 -0500 1533) }
0a8f36eb48f64 (Eric W. Biederman           2020-07-10 15:39:45 -0500 1534) 
c2315c187fa0d (Oleg Nesterov               2017-10-03 16:15:42 -0700 1535) int bprm_change_interp(const char *interp, struct linux_binprm *bprm)
b66c598401753 (Kees Cook                   2012-12-20 15:05:16 -0800 1536) {
b66c598401753 (Kees Cook                   2012-12-20 15:05:16 -0800 1537) 	/* If a binfmt changed the interp, free it first. */
b66c598401753 (Kees Cook                   2012-12-20 15:05:16 -0800 1538) 	if (bprm->interp != bprm->filename)
b66c598401753 (Kees Cook                   2012-12-20 15:05:16 -0800 1539) 		kfree(bprm->interp);
b66c598401753 (Kees Cook                   2012-12-20 15:05:16 -0800 1540) 	bprm->interp = kstrdup(interp, GFP_KERNEL);
b66c598401753 (Kees Cook                   2012-12-20 15:05:16 -0800 1541) 	if (!bprm->interp)
b66c598401753 (Kees Cook                   2012-12-20 15:05:16 -0800 1542) 		return -ENOMEM;
b66c598401753 (Kees Cook                   2012-12-20 15:05:16 -0800 1543) 	return 0;
b66c598401753 (Kees Cook                   2012-12-20 15:05:16 -0800 1544) }
b66c598401753 (Kees Cook                   2012-12-20 15:05:16 -0800 1545) EXPORT_SYMBOL(bprm_change_interp);
b66c598401753 (Kees Cook                   2012-12-20 15:05:16 -0800 1546) 
a6f76f23d297f (David Howells               2008-11-14 10:39:24 +1100 1547) /*
a6f76f23d297f (David Howells               2008-11-14 10:39:24 +1100 1548)  * determine how safe it is to execute the proposed program
9b1bf12d5d51b (KOSAKI Motohiro             2010-10-27 15:34:08 -0700 1549)  * - the caller must hold ->cred_guard_mutex to protect against
c2e1f2e30daa5 (Kees Cook                   2014-06-05 00:23:17 -0700 1550)  *   PTRACE_ATTACH or seccomp thread-sync
a6f76f23d297f (David Howells               2008-11-14 10:39:24 +1100 1551)  */
9e00cdb091b00 (Oleg Nesterov               2014-01-23 15:55:50 -0800 1552) static void check_unsafe_exec(struct linux_binprm *bprm)
a6f76f23d297f (David Howells               2008-11-14 10:39:24 +1100 1553) {
0bf2f3aec5474 (David Howells               2009-02-06 11:45:46 +0000 1554) 	struct task_struct *p = current, *t;
f1191b50ec11c (Al Viro                     2009-03-30 07:35:18 -0400 1555) 	unsigned n_fs;
a6f76f23d297f (David Howells               2008-11-14 10:39:24 +1100 1556) 
9227dd2a84a76 (Eric W. Biederman           2017-01-23 17:26:31 +1300 1557) 	if (p->ptrace)
9227dd2a84a76 (Eric W. Biederman           2017-01-23 17:26:31 +1300 1558) 		bprm->unsafe |= LSM_UNSAFE_PTRACE;
a6f76f23d297f (David Howells               2008-11-14 10:39:24 +1100 1559) 
259e5e6c75a91 (Andy Lutomirski             2012-04-12 16:47:50 -0500 1560) 	/*
259e5e6c75a91 (Andy Lutomirski             2012-04-12 16:47:50 -0500 1561) 	 * This isn't strictly necessary, but it makes it harder for LSMs to
259e5e6c75a91 (Andy Lutomirski             2012-04-12 16:47:50 -0500 1562) 	 * mess up.
259e5e6c75a91 (Andy Lutomirski             2012-04-12 16:47:50 -0500 1563) 	 */
1d4457f99928a (Kees Cook                   2014-05-21 15:23:46 -0700 1564) 	if (task_no_new_privs(current))
259e5e6c75a91 (Andy Lutomirski             2012-04-12 16:47:50 -0500 1565) 		bprm->unsafe |= LSM_UNSAFE_NO_NEW_PRIVS;
259e5e6c75a91 (Andy Lutomirski             2012-04-12 16:47:50 -0500 1566) 
83f62a2eacb1d (Oleg Nesterov               2014-01-23 15:55:49 -0800 1567) 	t = p;
0bf2f3aec5474 (David Howells               2009-02-06 11:45:46 +0000 1568) 	n_fs = 1;
2a4419b5b2a77 (Nicholas Piggin             2010-08-18 04:37:33 +1000 1569) 	spin_lock(&p->fs->lock);
437f7fdb607f3 (Oleg Nesterov               2009-04-24 01:02:45 +0200 1570) 	rcu_read_lock();
83f62a2eacb1d (Oleg Nesterov               2014-01-23 15:55:49 -0800 1571) 	while_each_thread(p, t) {
0bf2f3aec5474 (David Howells               2009-02-06 11:45:46 +0000 1572) 		if (t->fs == p->fs)
0bf2f3aec5474 (David Howells               2009-02-06 11:45:46 +0000 1573) 			n_fs++;
0bf2f3aec5474 (David Howells               2009-02-06 11:45:46 +0000 1574) 	}
437f7fdb607f3 (Oleg Nesterov               2009-04-24 01:02:45 +0200 1575) 	rcu_read_unlock();
0bf2f3aec5474 (David Howells               2009-02-06 11:45:46 +0000 1576) 
9e00cdb091b00 (Oleg Nesterov               2014-01-23 15:55:50 -0800 1577) 	if (p->fs->users > n_fs)
a6f76f23d297f (David Howells               2008-11-14 10:39:24 +1100 1578) 		bprm->unsafe |= LSM_UNSAFE_SHARE;
9e00cdb091b00 (Oleg Nesterov               2014-01-23 15:55:50 -0800 1579) 	else
9e00cdb091b00 (Oleg Nesterov               2014-01-23 15:55:50 -0800 1580) 		p->fs->in_exec = 1;
2a4419b5b2a77 (Nicholas Piggin             2010-08-18 04:37:33 +1000 1581) 	spin_unlock(&p->fs->lock);
a6f76f23d297f (David Howells               2008-11-14 10:39:24 +1100 1582) }
a6f76f23d297f (David Howells               2008-11-14 10:39:24 +1100 1583) 
56305aa9b6fab (Eric W. Biederman           2020-05-29 22:00:54 -0500 1584) static void bprm_fill_uid(struct linux_binprm *bprm, struct file *file)
8b01fc86b9f42 (Jann Horn                   2015-04-19 02:48:39 +0200 1585) {
56305aa9b6fab (Eric W. Biederman           2020-05-29 22:00:54 -0500 1586) 	/* Handle suid and sgid on files */
1ab29965b3059 (Christian Brauner           2021-01-21 14:19:42 +0100 1587) 	struct user_namespace *mnt_userns;
8b01fc86b9f42 (Jann Horn                   2015-04-19 02:48:39 +0200 1588) 	struct inode *inode;
8b01fc86b9f42 (Jann Horn                   2015-04-19 02:48:39 +0200 1589) 	unsigned int mode;
8b01fc86b9f42 (Jann Horn                   2015-04-19 02:48:39 +0200 1590) 	kuid_t uid;
8b01fc86b9f42 (Jann Horn                   2015-04-19 02:48:39 +0200 1591) 	kgid_t gid;
8b01fc86b9f42 (Jann Horn                   2015-04-19 02:48:39 +0200 1592) 
56305aa9b6fab (Eric W. Biederman           2020-05-29 22:00:54 -0500 1593) 	if (!mnt_may_suid(file->f_path.mnt))
8b01fc86b9f42 (Jann Horn                   2015-04-19 02:48:39 +0200 1594) 		return;
8b01fc86b9f42 (Jann Horn                   2015-04-19 02:48:39 +0200 1595) 
8b01fc86b9f42 (Jann Horn                   2015-04-19 02:48:39 +0200 1596) 	if (task_no_new_privs(current))
8b01fc86b9f42 (Jann Horn                   2015-04-19 02:48:39 +0200 1597) 		return;
8b01fc86b9f42 (Jann Horn                   2015-04-19 02:48:39 +0200 1598) 
56305aa9b6fab (Eric W. Biederman           2020-05-29 22:00:54 -0500 1599) 	inode = file->f_path.dentry->d_inode;
8b01fc86b9f42 (Jann Horn                   2015-04-19 02:48:39 +0200 1600) 	mode = READ_ONCE(inode->i_mode);
8b01fc86b9f42 (Jann Horn                   2015-04-19 02:48:39 +0200 1601) 	if (!(mode & (S_ISUID|S_ISGID)))
8b01fc86b9f42 (Jann Horn                   2015-04-19 02:48:39 +0200 1602) 		return;
8b01fc86b9f42 (Jann Horn                   2015-04-19 02:48:39 +0200 1603) 
1ab29965b3059 (Christian Brauner           2021-01-21 14:19:42 +0100 1604) 	mnt_userns = file_mnt_user_ns(file);
1ab29965b3059 (Christian Brauner           2021-01-21 14:19:42 +0100 1605) 
8b01fc86b9f42 (Jann Horn                   2015-04-19 02:48:39 +0200 1606) 	/* Be careful if suid/sgid is set */
5955102c9984f (Al Viro                     2016-01-22 15:40:57 -0500 1607) 	inode_lock(inode);
8b01fc86b9f42 (Jann Horn                   2015-04-19 02:48:39 +0200 1608) 
8b01fc86b9f42 (Jann Horn                   2015-04-19 02:48:39 +0200 1609) 	/* reload atomically mode/uid/gid now that lock held */
8b01fc86b9f42 (Jann Horn                   2015-04-19 02:48:39 +0200 1610) 	mode = inode->i_mode;
1ab29965b3059 (Christian Brauner           2021-01-21 14:19:42 +0100 1611) 	uid = i_uid_into_mnt(mnt_userns, inode);
1ab29965b3059 (Christian Brauner           2021-01-21 14:19:42 +0100 1612) 	gid = i_gid_into_mnt(mnt_userns, inode);
5955102c9984f (Al Viro                     2016-01-22 15:40:57 -0500 1613) 	inode_unlock(inode);
8b01fc86b9f42 (Jann Horn                   2015-04-19 02:48:39 +0200 1614) 
8b01fc86b9f42 (Jann Horn                   2015-04-19 02:48:39 +0200 1615) 	/* We ignore suid/sgid if there are no mappings for them in the ns */
8b01fc86b9f42 (Jann Horn                   2015-04-19 02:48:39 +0200 1616) 	if (!kuid_has_mapping(bprm->cred->user_ns, uid) ||
8b01fc86b9f42 (Jann Horn                   2015-04-19 02:48:39 +0200 1617) 		 !kgid_has_mapping(bprm->cred->user_ns, gid))
8b01fc86b9f42 (Jann Horn                   2015-04-19 02:48:39 +0200 1618) 		return;
8b01fc86b9f42 (Jann Horn                   2015-04-19 02:48:39 +0200 1619) 
8b01fc86b9f42 (Jann Horn                   2015-04-19 02:48:39 +0200 1620) 	if (mode & S_ISUID) {
8b01fc86b9f42 (Jann Horn                   2015-04-19 02:48:39 +0200 1621) 		bprm->per_clear |= PER_CLEAR_ON_SETID;
8b01fc86b9f42 (Jann Horn                   2015-04-19 02:48:39 +0200 1622) 		bprm->cred->euid = uid;
8b01fc86b9f42 (Jann Horn                   2015-04-19 02:48:39 +0200 1623) 	}
8b01fc86b9f42 (Jann Horn                   2015-04-19 02:48:39 +0200 1624) 
8b01fc86b9f42 (Jann Horn                   2015-04-19 02:48:39 +0200 1625) 	if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
8b01fc86b9f42 (Jann Horn                   2015-04-19 02:48:39 +0200 1626) 		bprm->per_clear |= PER_CLEAR_ON_SETID;
8b01fc86b9f42 (Jann Horn                   2015-04-19 02:48:39 +0200 1627) 		bprm->cred->egid = gid;
8b01fc86b9f42 (Jann Horn                   2015-04-19 02:48:39 +0200 1628) 	}
8b01fc86b9f42 (Jann Horn                   2015-04-19 02:48:39 +0200 1629) }
8b01fc86b9f42 (Jann Horn                   2015-04-19 02:48:39 +0200 1630) 
56305aa9b6fab (Eric W. Biederman           2020-05-29 22:00:54 -0500 1631) /*
56305aa9b6fab (Eric W. Biederman           2020-05-29 22:00:54 -0500 1632)  * Compute brpm->cred based upon the final binary.
56305aa9b6fab (Eric W. Biederman           2020-05-29 22:00:54 -0500 1633)  */
56305aa9b6fab (Eric W. Biederman           2020-05-29 22:00:54 -0500 1634) static int bprm_creds_from_file(struct linux_binprm *bprm)
56305aa9b6fab (Eric W. Biederman           2020-05-29 22:00:54 -0500 1635) {
56305aa9b6fab (Eric W. Biederman           2020-05-29 22:00:54 -0500 1636) 	/* Compute creds based on which file? */
56305aa9b6fab (Eric W. Biederman           2020-05-29 22:00:54 -0500 1637) 	struct file *file = bprm->execfd_creds ? bprm->executable : bprm->file;
56305aa9b6fab (Eric W. Biederman           2020-05-29 22:00:54 -0500 1638) 
56305aa9b6fab (Eric W. Biederman           2020-05-29 22:00:54 -0500 1639) 	bprm_fill_uid(bprm, file);
56305aa9b6fab (Eric W. Biederman           2020-05-29 22:00:54 -0500 1640) 	return security_bprm_creds_from_file(bprm, file);
56305aa9b6fab (Eric W. Biederman           2020-05-29 22:00:54 -0500 1641) }
56305aa9b6fab (Eric W. Biederman           2020-05-29 22:00:54 -0500 1642) 
9e00cdb091b00 (Oleg Nesterov               2014-01-23 15:55:50 -0800 1643) /*
9e00cdb091b00 (Oleg Nesterov               2014-01-23 15:55:50 -0800 1644)  * Fill the binprm structure from the inode.
56305aa9b6fab (Eric W. Biederman           2020-05-29 22:00:54 -0500 1645)  * Read the first BINPRM_BUF_SIZE bytes
a6f76f23d297f (David Howells               2008-11-14 10:39:24 +1100 1646)  *
a6f76f23d297f (David Howells               2008-11-14 10:39:24 +1100 1647)  * This may be called multiple times for binary chains (scripts for example).
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1648)  */
8b72ca9004ed3 (Eric W. Biederman           2020-05-13 22:25:20 -0500 1649) static int prepare_binprm(struct linux_binprm *bprm)
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1650) {
bdd1d2d3d251c (Christoph Hellwig           2017-09-01 17:39:13 +0200 1651) 	loff_t pos = 0;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1652) 
a6f76f23d297f (David Howells               2008-11-14 10:39:24 +1100 1653) 	memset(bprm->buf, 0, BINPRM_BUF_SIZE);
bdd1d2d3d251c (Christoph Hellwig           2017-09-01 17:39:13 +0200 1654) 	return kernel_read(bprm->file, bprm->buf, BINPRM_BUF_SIZE, &pos);
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1655) }
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1656) 
4fc75ff4816c3 (Nicholas Piggin             2007-05-08 00:25:16 -0700 1657) /*
4fc75ff4816c3 (Nicholas Piggin             2007-05-08 00:25:16 -0700 1658)  * Arguments are '\0' separated strings found at the location bprm->p
4fc75ff4816c3 (Nicholas Piggin             2007-05-08 00:25:16 -0700 1659)  * points to; chop off the first by relocating brpm->p to right after
4fc75ff4816c3 (Nicholas Piggin             2007-05-08 00:25:16 -0700 1660)  * the first '\0' encountered.
4fc75ff4816c3 (Nicholas Piggin             2007-05-08 00:25:16 -0700 1661)  */
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700 1662) int remove_arg_zero(struct linux_binprm *bprm)
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1663) {
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700 1664) 	int ret = 0;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700 1665) 	unsigned long offset;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700 1666) 	char *kaddr;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700 1667) 	struct page *page;
4fc75ff4816c3 (Nicholas Piggin             2007-05-08 00:25:16 -0700 1668) 
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700 1669) 	if (!bprm->argc)
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700 1670) 		return 0;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1671) 
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700 1672) 	do {
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700 1673) 		offset = bprm->p & ~PAGE_MASK;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700 1674) 		page = get_arg_page(bprm, bprm->p, 0);
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700 1675) 		if (!page) {
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700 1676) 			ret = -EFAULT;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700 1677) 			goto out;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700 1678) 		}
e8e3c3d66fd9d (Cong Wang                   2011-11-25 23:14:27 +0800 1679) 		kaddr = kmap_atomic(page);
4fc75ff4816c3 (Nicholas Piggin             2007-05-08 00:25:16 -0700 1680) 
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700 1681) 		for (; offset < PAGE_SIZE && kaddr[offset];
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700 1682) 				offset++, bprm->p++)
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700 1683) 			;
4fc75ff4816c3 (Nicholas Piggin             2007-05-08 00:25:16 -0700 1684) 
e8e3c3d66fd9d (Cong Wang                   2011-11-25 23:14:27 +0800 1685) 		kunmap_atomic(kaddr);
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700 1686) 		put_arg_page(page);
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700 1687) 	} while (offset == PAGE_SIZE);
4fc75ff4816c3 (Nicholas Piggin             2007-05-08 00:25:16 -0700 1688) 
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700 1689) 	bprm->p++;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700 1690) 	bprm->argc--;
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700 1691) 	ret = 0;
4fc75ff4816c3 (Nicholas Piggin             2007-05-08 00:25:16 -0700 1692) 
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700 1693) out:
b6a2fea39318e (Ollie Wild                  2007-07-19 01:48:16 -0700 1694) 	return ret;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1695) }
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1696) EXPORT_SYMBOL(remove_arg_zero);
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1697) 
cb7b6b1cbc20a (Oleg Nesterov               2013-09-11 14:24:44 -0700 1698) #define printable(c) (((c)=='\t') || ((c)=='\n') || (0x20<=(c) && (c)<=0x7e))
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1699) /*
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1700)  * cycle the list of binary formats handler, until one recognizes the image
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1701)  */
bc2bf338d54b7 (Eric W. Biederman           2020-05-18 18:43:20 -0500 1702) static int search_binary_handler(struct linux_binprm *bprm)
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1703) {
cb7b6b1cbc20a (Oleg Nesterov               2013-09-11 14:24:44 -0700 1704) 	bool need_retry = IS_ENABLED(CONFIG_MODULES);
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1705) 	struct linux_binfmt *fmt;
cb7b6b1cbc20a (Oleg Nesterov               2013-09-11 14:24:44 -0700 1706) 	int retval;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1707) 
8b72ca9004ed3 (Eric W. Biederman           2020-05-13 22:25:20 -0500 1708) 	retval = prepare_binprm(bprm);
8b72ca9004ed3 (Eric W. Biederman           2020-05-13 22:25:20 -0500 1709) 	if (retval < 0)
8b72ca9004ed3 (Eric W. Biederman           2020-05-13 22:25:20 -0500 1710) 		return retval;
d740269867021 (Kees Cook                   2012-12-17 16:03:20 -0800 1711) 
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1712) 	retval = security_bprm_check(bprm);
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1713) 	if (retval)
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1714) 		return retval;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1715) 
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1716) 	retval = -ENOENT;
cb7b6b1cbc20a (Oleg Nesterov               2013-09-11 14:24:44 -0700 1717)  retry:
cb7b6b1cbc20a (Oleg Nesterov               2013-09-11 14:24:44 -0700 1718) 	read_lock(&binfmt_lock);
cb7b6b1cbc20a (Oleg Nesterov               2013-09-11 14:24:44 -0700 1719) 	list_for_each_entry(fmt, &formats, lh) {
cb7b6b1cbc20a (Oleg Nesterov               2013-09-11 14:24:44 -0700 1720) 		if (!try_module_get(fmt->module))
cb7b6b1cbc20a (Oleg Nesterov               2013-09-11 14:24:44 -0700 1721) 			continue;
cb7b6b1cbc20a (Oleg Nesterov               2013-09-11 14:24:44 -0700 1722) 		read_unlock(&binfmt_lock);
d53ddd0181d1c (Alexey Dobriyan             2019-05-14 15:44:37 -0700 1723) 
cb7b6b1cbc20a (Oleg Nesterov               2013-09-11 14:24:44 -0700 1724) 		retval = fmt->load_binary(bprm);
d53ddd0181d1c (Alexey Dobriyan             2019-05-14 15:44:37 -0700 1725) 
19d860a140bea (Al Viro                     2014-05-04 20:11:36 -0400 1726) 		read_lock(&binfmt_lock);
19d860a140bea (Al Viro                     2014-05-04 20:11:36 -0400 1727) 		put_binfmt(fmt);
bc2bf338d54b7 (Eric W. Biederman           2020-05-18 18:43:20 -0500 1728) 		if (bprm->point_of_no_return || (retval != -ENOEXEC)) {
19d860a140bea (Al Viro                     2014-05-04 20:11:36 -0400 1729) 			read_unlock(&binfmt_lock);
cb7b6b1cbc20a (Oleg Nesterov               2013-09-11 14:24:44 -0700 1730) 			return retval;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1731) 		}
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1732) 	}
cb7b6b1cbc20a (Oleg Nesterov               2013-09-11 14:24:44 -0700 1733) 	read_unlock(&binfmt_lock);
cb7b6b1cbc20a (Oleg Nesterov               2013-09-11 14:24:44 -0700 1734) 
19d860a140bea (Al Viro                     2014-05-04 20:11:36 -0400 1735) 	if (need_retry) {
cb7b6b1cbc20a (Oleg Nesterov               2013-09-11 14:24:44 -0700 1736) 		if (printable(bprm->buf[0]) && printable(bprm->buf[1]) &&
cb7b6b1cbc20a (Oleg Nesterov               2013-09-11 14:24:44 -0700 1737) 		    printable(bprm->buf[2]) && printable(bprm->buf[3]))
cb7b6b1cbc20a (Oleg Nesterov               2013-09-11 14:24:44 -0700 1738) 			return retval;
4e0621a07ea58 (Oleg Nesterov               2013-09-11 14:24:45 -0700 1739) 		if (request_module("binfmt-%04x", *(ushort *)(bprm->buf + 2)) < 0)
4e0621a07ea58 (Oleg Nesterov               2013-09-11 14:24:45 -0700 1740) 			return retval;
cb7b6b1cbc20a (Oleg Nesterov               2013-09-11 14:24:44 -0700 1741) 		need_retry = false;
cb7b6b1cbc20a (Oleg Nesterov               2013-09-11 14:24:44 -0700 1742) 		goto retry;
cb7b6b1cbc20a (Oleg Nesterov               2013-09-11 14:24:44 -0700 1743) 	}
cb7b6b1cbc20a (Oleg Nesterov               2013-09-11 14:24:44 -0700 1744) 
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1745) 	return retval;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1746) }
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1747) 
5d1baf3b63bfc (Oleg Nesterov               2013-09-11 14:24:38 -0700 1748) static int exec_binprm(struct linux_binprm *bprm)
5d1baf3b63bfc (Oleg Nesterov               2013-09-11 14:24:38 -0700 1749) {
5d1baf3b63bfc (Oleg Nesterov               2013-09-11 14:24:38 -0700 1750) 	pid_t old_pid, old_vpid;
bc2bf338d54b7 (Eric W. Biederman           2020-05-18 18:43:20 -0500 1751) 	int ret, depth;
5d1baf3b63bfc (Oleg Nesterov               2013-09-11 14:24:38 -0700 1752) 
5d1baf3b63bfc (Oleg Nesterov               2013-09-11 14:24:38 -0700 1753) 	/* Need to fetch pid before load_binary changes it */
5d1baf3b63bfc (Oleg Nesterov               2013-09-11 14:24:38 -0700 1754) 	old_pid = current->pid;
5d1baf3b63bfc (Oleg Nesterov               2013-09-11 14:24:38 -0700 1755) 	rcu_read_lock();
5d1baf3b63bfc (Oleg Nesterov               2013-09-11 14:24:38 -0700 1756) 	old_vpid = task_pid_nr_ns(current, task_active_pid_ns(current->parent));
5d1baf3b63bfc (Oleg Nesterov               2013-09-11 14:24:38 -0700 1757) 	rcu_read_unlock();
5d1baf3b63bfc (Oleg Nesterov               2013-09-11 14:24:38 -0700 1758) 
bc2bf338d54b7 (Eric W. Biederman           2020-05-18 18:43:20 -0500 1759) 	/* This allows 4 levels of binfmt rewrites before failing hard. */
bc2bf338d54b7 (Eric W. Biederman           2020-05-18 18:43:20 -0500 1760) 	for (depth = 0;; depth++) {
bc2bf338d54b7 (Eric W. Biederman           2020-05-18 18:43:20 -0500 1761) 		struct file *exec;
bc2bf338d54b7 (Eric W. Biederman           2020-05-18 18:43:20 -0500 1762) 		if (depth > 5)
bc2bf338d54b7 (Eric W. Biederman           2020-05-18 18:43:20 -0500 1763) 			return -ELOOP;
bc2bf338d54b7 (Eric W. Biederman           2020-05-18 18:43:20 -0500 1764) 
bc2bf338d54b7 (Eric W. Biederman           2020-05-18 18:43:20 -0500 1765) 		ret = search_binary_handler(bprm);
bc2bf338d54b7 (Eric W. Biederman           2020-05-18 18:43:20 -0500 1766) 		if (ret < 0)
bc2bf338d54b7 (Eric W. Biederman           2020-05-18 18:43:20 -0500 1767) 			return ret;
bc2bf338d54b7 (Eric W. Biederman           2020-05-18 18:43:20 -0500 1768) 		if (!bprm->interpreter)
bc2bf338d54b7 (Eric W. Biederman           2020-05-18 18:43:20 -0500 1769) 			break;
bc2bf338d54b7 (Eric W. Biederman           2020-05-18 18:43:20 -0500 1770) 
bc2bf338d54b7 (Eric W. Biederman           2020-05-18 18:43:20 -0500 1771) 		exec = bprm->file;
bc2bf338d54b7 (Eric W. Biederman           2020-05-18 18:43:20 -0500 1772) 		bprm->file = bprm->interpreter;
bc2bf338d54b7 (Eric W. Biederman           2020-05-18 18:43:20 -0500 1773) 		bprm->interpreter = NULL;
bc2bf338d54b7 (Eric W. Biederman           2020-05-18 18:43:20 -0500 1774) 
bc2bf338d54b7 (Eric W. Biederman           2020-05-18 18:43:20 -0500 1775) 		allow_write_access(exec);
bc2bf338d54b7 (Eric W. Biederman           2020-05-18 18:43:20 -0500 1776) 		if (unlikely(bprm->have_execfd)) {
bc2bf338d54b7 (Eric W. Biederman           2020-05-18 18:43:20 -0500 1777) 			if (bprm->executable) {
bc2bf338d54b7 (Eric W. Biederman           2020-05-18 18:43:20 -0500 1778) 				fput(exec);
bc2bf338d54b7 (Eric W. Biederman           2020-05-18 18:43:20 -0500 1779) 				return -ENOEXEC;
bc2bf338d54b7 (Eric W. Biederman           2020-05-18 18:43:20 -0500 1780) 			}
bc2bf338d54b7 (Eric W. Biederman           2020-05-18 18:43:20 -0500 1781) 			bprm->executable = exec;
bc2bf338d54b7 (Eric W. Biederman           2020-05-18 18:43:20 -0500 1782) 		} else
bc2bf338d54b7 (Eric W. Biederman           2020-05-18 18:43:20 -0500 1783) 			fput(exec);
5d1baf3b63bfc (Oleg Nesterov               2013-09-11 14:24:38 -0700 1784) 	}
5d1baf3b63bfc (Oleg Nesterov               2013-09-11 14:24:38 -0700 1785) 
bc2bf338d54b7 (Eric W. Biederman           2020-05-18 18:43:20 -0500 1786) 	audit_bprm(bprm);
bc2bf338d54b7 (Eric W. Biederman           2020-05-18 18:43:20 -0500 1787) 	trace_sched_process_exec(current, old_pid, bprm);
bc2bf338d54b7 (Eric W. Biederman           2020-05-18 18:43:20 -0500 1788) 	ptrace_event(PTRACE_EVENT_EXEC, old_vpid);
bc2bf338d54b7 (Eric W. Biederman           2020-05-18 18:43:20 -0500 1789) 	proc_exec_connector(current);
bc2bf338d54b7 (Eric W. Biederman           2020-05-18 18:43:20 -0500 1790) 	return 0;
5d1baf3b63bfc (Oleg Nesterov               2013-09-11 14:24:38 -0700 1791) }
5d1baf3b63bfc (Oleg Nesterov               2013-09-11 14:24:38 -0700 1792) 
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1793) /*
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1794)  * sys_execve() executes a new program.
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1795)  */
0c9cdff054aec (Eric W. Biederman           2020-07-12 07:17:50 -0500 1796) static int bprm_execve(struct linux_binprm *bprm,
0c9cdff054aec (Eric W. Biederman           2020-07-12 07:17:50 -0500 1797) 		       int fd, struct filename *filename, int flags)
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1798) {
25cf336de51b5 (Eric W. Biederman           2020-06-25 13:56:40 -0500 1799) 	struct file *file;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1800) 	int retval;
0f2122045b946 (Jens Axboe                  2020-09-13 13:09:39 -0600 1801) 
a2a8474c3fff8 (Oleg Nesterov               2009-09-05 11:17:13 -0700 1802) 	retval = prepare_bprm_creds(bprm);
a2a8474c3fff8 (Oleg Nesterov               2009-09-05 11:17:13 -0700 1803) 	if (retval)
b6043501289eb (Eric W. Biederman           2020-11-20 17:14:18 -0600 1804) 		return retval;
498052bba55ec (Al Viro                     2009-03-30 07:20:30 -0400 1805) 
9e00cdb091b00 (Oleg Nesterov               2014-01-23 15:55:50 -0800 1806) 	check_unsafe_exec(bprm);
a2a8474c3fff8 (Oleg Nesterov               2009-09-05 11:17:13 -0700 1807) 	current->in_execve = 1;
a6f76f23d297f (David Howells               2008-11-14 10:39:24 +1100 1808) 
25cf336de51b5 (Eric W. Biederman           2020-06-25 13:56:40 -0500 1809) 	file = do_open_execat(fd, filename, flags);
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1810) 	retval = PTR_ERR(file);
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1811) 	if (IS_ERR(file))
498052bba55ec (Al Viro                     2009-03-30 07:20:30 -0400 1812) 		goto out_unmark;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1813) 
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1814) 	sched_exec();
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1815) 
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1816) 	bprm->file = file;
60d9ad1d1d7f1 (Eric W. Biederman           2020-07-11 08:16:15 -0500 1817) 	/*
60d9ad1d1d7f1 (Eric W. Biederman           2020-07-11 08:16:15 -0500 1818) 	 * Record that a name derived from an O_CLOEXEC fd will be
b6043501289eb (Eric W. Biederman           2020-11-20 17:14:18 -0600 1819) 	 * inaccessible after exec.  This allows the code in exec to
b6043501289eb (Eric W. Biederman           2020-11-20 17:14:18 -0600 1820) 	 * choose to fail when the executable is not mmaped into the
b6043501289eb (Eric W. Biederman           2020-11-20 17:14:18 -0600 1821) 	 * interpreter and an open file descriptor is not passed to
b6043501289eb (Eric W. Biederman           2020-11-20 17:14:18 -0600 1822) 	 * the interpreter.  This makes for a better user experience
b6043501289eb (Eric W. Biederman           2020-11-20 17:14:18 -0600 1823) 	 * than having the interpreter start and then immediately fail
b6043501289eb (Eric W. Biederman           2020-11-20 17:14:18 -0600 1824) 	 * when it finds the executable is inaccessible.
60d9ad1d1d7f1 (Eric W. Biederman           2020-07-11 08:16:15 -0500 1825) 	 */
878f12dbb8f51 (Eric W. Biederman           2020-12-09 15:42:57 -0600 1826) 	if (bprm->fdpath && get_close_on_exec(fd))
60d9ad1d1d7f1 (Eric W. Biederman           2020-07-11 08:16:15 -0500 1827) 		bprm->interp_flags |= BINPRM_FLAGS_PATH_INACCESSIBLE;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1828) 
b8bff599261c9 (Eric W. Biederman           2020-03-22 15:46:24 -0500 1829) 	/* Set the unchanging part of bprm->cred */
b8bff599261c9 (Eric W. Biederman           2020-03-22 15:46:24 -0500 1830) 	retval = security_bprm_creds_for_exec(bprm);
b8bff599261c9 (Eric W. Biederman           2020-03-22 15:46:24 -0500 1831) 	if (retval)
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1832) 		goto out;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1833) 
5d1baf3b63bfc (Oleg Nesterov               2013-09-11 14:24:38 -0700 1834) 	retval = exec_binprm(bprm);
a6f76f23d297f (David Howells               2008-11-14 10:39:24 +1100 1835) 	if (retval < 0)
a6f76f23d297f (David Howells               2008-11-14 10:39:24 +1100 1836) 		goto out;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1837) 
a6f76f23d297f (David Howells               2008-11-14 10:39:24 +1100 1838) 	/* execve succeeded */
498052bba55ec (Al Viro                     2009-03-30 07:20:30 -0400 1839) 	current->fs->in_exec = 0;
f9ce1f1cda8b7 (Kentaro Takeda              2009-02-05 17:18:11 +0900 1840) 	current->in_execve = 0;
d7822b1e24f2d (Mathieu Desnoyers           2018-06-02 08:43:54 -0400 1841) 	rseq_execve(current);
a6f76f23d297f (David Howells               2008-11-14 10:39:24 +1100 1842) 	acct_update_integrals(current);
16d51a590a8ce (Jann Horn                   2019-07-16 17:20:45 +0200 1843) 	task_numa_free(current, false);
a6f76f23d297f (David Howells               2008-11-14 10:39:24 +1100 1844) 	return retval;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1845) 
a6f76f23d297f (David Howells               2008-11-14 10:39:24 +1100 1846) out:
8890b29341f30 (Eric W. Biederman           2020-04-04 09:42:56 -0500 1847) 	/*
3d742d4b6ebb3 (Randy Dunlap                2021-02-24 12:00:48 -0800 1848) 	 * If past the point of no return ensure the code never
8890b29341f30 (Eric W. Biederman           2020-04-04 09:42:56 -0500 1849) 	 * returns to the userspace process.  Use an existing fatal
8890b29341f30 (Eric W. Biederman           2020-04-04 09:42:56 -0500 1850) 	 * signal if present otherwise terminate the process with
8890b29341f30 (Eric W. Biederman           2020-04-04 09:42:56 -0500 1851) 	 * SIGSEGV.
8890b29341f30 (Eric W. Biederman           2020-04-04 09:42:56 -0500 1852) 	 */
8890b29341f30 (Eric W. Biederman           2020-04-04 09:42:56 -0500 1853) 	if (bprm->point_of_no_return && !fatal_signal_pending(current))
8890b29341f30 (Eric W. Biederman           2020-04-04 09:42:56 -0500 1854) 		force_sigsegv(SIGSEGV);
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1855) 
498052bba55ec (Al Viro                     2009-03-30 07:20:30 -0400 1856) out_unmark:
9e00cdb091b00 (Oleg Nesterov               2014-01-23 15:55:50 -0800 1857) 	current->fs->in_exec = 0;
f9ce1f1cda8b7 (Kentaro Takeda              2009-02-05 17:18:11 +0900 1858) 	current->in_execve = 0;
a6f76f23d297f (David Howells               2008-11-14 10:39:24 +1100 1859) 
0c9cdff054aec (Eric W. Biederman           2020-07-12 07:17:50 -0500 1860) 	return retval;
0c9cdff054aec (Eric W. Biederman           2020-07-12 07:17:50 -0500 1861) }
0c9cdff054aec (Eric W. Biederman           2020-07-12 07:17:50 -0500 1862) 
0c9cdff054aec (Eric W. Biederman           2020-07-12 07:17:50 -0500 1863) static int do_execveat_common(int fd, struct filename *filename,
0c9cdff054aec (Eric W. Biederman           2020-07-12 07:17:50 -0500 1864) 			      struct user_arg_ptr argv,
0c9cdff054aec (Eric W. Biederman           2020-07-12 07:17:50 -0500 1865) 			      struct user_arg_ptr envp,
0c9cdff054aec (Eric W. Biederman           2020-07-12 07:17:50 -0500 1866) 			      int flags)
0c9cdff054aec (Eric W. Biederman           2020-07-12 07:17:50 -0500 1867) {
0c9cdff054aec (Eric W. Biederman           2020-07-12 07:17:50 -0500 1868) 	struct linux_binprm *bprm;
0c9cdff054aec (Eric W. Biederman           2020-07-12 07:17:50 -0500 1869) 	int retval;
0c9cdff054aec (Eric W. Biederman           2020-07-12 07:17:50 -0500 1870) 
0c9cdff054aec (Eric W. Biederman           2020-07-12 07:17:50 -0500 1871) 	if (IS_ERR(filename))
0c9cdff054aec (Eric W. Biederman           2020-07-12 07:17:50 -0500 1872) 		return PTR_ERR(filename);
0c9cdff054aec (Eric W. Biederman           2020-07-12 07:17:50 -0500 1873) 
0c9cdff054aec (Eric W. Biederman           2020-07-12 07:17:50 -0500 1874) 	/*
0c9cdff054aec (Eric W. Biederman           2020-07-12 07:17:50 -0500 1875) 	 * We move the actual failure in case of RLIMIT_NPROC excess from
0c9cdff054aec (Eric W. Biederman           2020-07-12 07:17:50 -0500 1876) 	 * set*uid() to execve() because too many poorly written programs
0c9cdff054aec (Eric W. Biederman           2020-07-12 07:17:50 -0500 1877) 	 * don't check setuid() return code.  Here we additionally recheck
0c9cdff054aec (Eric W. Biederman           2020-07-12 07:17:50 -0500 1878) 	 * whether NPROC limit is still exceeded.
0c9cdff054aec (Eric W. Biederman           2020-07-12 07:17:50 -0500 1879) 	 */
0c9cdff054aec (Eric W. Biederman           2020-07-12 07:17:50 -0500 1880) 	if ((current->flags & PF_NPROC_EXCEEDED) &&
0c9cdff054aec (Eric W. Biederman           2020-07-12 07:17:50 -0500 1881) 	    atomic_read(&current_user()->processes) > rlimit(RLIMIT_NPROC)) {
0c9cdff054aec (Eric W. Biederman           2020-07-12 07:17:50 -0500 1882) 		retval = -EAGAIN;
0c9cdff054aec (Eric W. Biederman           2020-07-12 07:17:50 -0500 1883) 		goto out_ret;
0c9cdff054aec (Eric W. Biederman           2020-07-12 07:17:50 -0500 1884) 	}
0c9cdff054aec (Eric W. Biederman           2020-07-12 07:17:50 -0500 1885) 
0c9cdff054aec (Eric W. Biederman           2020-07-12 07:17:50 -0500 1886) 	/* We're below the limit (still or again), so we don't want to make
0c9cdff054aec (Eric W. Biederman           2020-07-12 07:17:50 -0500 1887) 	 * further execve() calls fail. */
0c9cdff054aec (Eric W. Biederman           2020-07-12 07:17:50 -0500 1888) 	current->flags &= ~PF_NPROC_EXCEEDED;
0c9cdff054aec (Eric W. Biederman           2020-07-12 07:17:50 -0500 1889) 
0c9cdff054aec (Eric W. Biederman           2020-07-12 07:17:50 -0500 1890) 	bprm = alloc_bprm(fd, filename);
0c9cdff054aec (Eric W. Biederman           2020-07-12 07:17:50 -0500 1891) 	if (IS_ERR(bprm)) {
0c9cdff054aec (Eric W. Biederman           2020-07-12 07:17:50 -0500 1892) 		retval = PTR_ERR(bprm);
0c9cdff054aec (Eric W. Biederman           2020-07-12 07:17:50 -0500 1893) 		goto out_ret;
0c9cdff054aec (Eric W. Biederman           2020-07-12 07:17:50 -0500 1894) 	}
0c9cdff054aec (Eric W. Biederman           2020-07-12 07:17:50 -0500 1895) 
d8b9cd549ecf0 (Eric W. Biederman           2020-07-12 08:23:54 -0500 1896) 	retval = count(argv, MAX_ARG_STRINGS);
d8b9cd549ecf0 (Eric W. Biederman           2020-07-12 08:23:54 -0500 1897) 	if (retval < 0)
d8b9cd549ecf0 (Eric W. Biederman           2020-07-12 08:23:54 -0500 1898) 		goto out_free;
d8b9cd549ecf0 (Eric W. Biederman           2020-07-12 08:23:54 -0500 1899) 	bprm->argc = retval;
d8b9cd549ecf0 (Eric W. Biederman           2020-07-12 08:23:54 -0500 1900) 
d8b9cd549ecf0 (Eric W. Biederman           2020-07-12 08:23:54 -0500 1901) 	retval = count(envp, MAX_ARG_STRINGS);
d8b9cd549ecf0 (Eric W. Biederman           2020-07-12 08:23:54 -0500 1902) 	if (retval < 0)
d8b9cd549ecf0 (Eric W. Biederman           2020-07-12 08:23:54 -0500 1903) 		goto out_free;
d8b9cd549ecf0 (Eric W. Biederman           2020-07-12 08:23:54 -0500 1904) 	bprm->envc = retval;
d8b9cd549ecf0 (Eric W. Biederman           2020-07-12 08:23:54 -0500 1905) 
d8b9cd549ecf0 (Eric W. Biederman           2020-07-12 08:23:54 -0500 1906) 	retval = bprm_stack_limits(bprm);
0c9cdff054aec (Eric W. Biederman           2020-07-12 07:17:50 -0500 1907) 	if (retval < 0)
0c9cdff054aec (Eric W. Biederman           2020-07-12 07:17:50 -0500 1908) 		goto out_free;
0c9cdff054aec (Eric W. Biederman           2020-07-12 07:17:50 -0500 1909) 
0c9cdff054aec (Eric W. Biederman           2020-07-12 07:17:50 -0500 1910) 	retval = copy_string_kernel(bprm->filename, bprm);
0c9cdff054aec (Eric W. Biederman           2020-07-12 07:17:50 -0500 1911) 	if (retval < 0)
0c9cdff054aec (Eric W. Biederman           2020-07-12 07:17:50 -0500 1912) 		goto out_free;
0c9cdff054aec (Eric W. Biederman           2020-07-12 07:17:50 -0500 1913) 	bprm->exec = bprm->p;
0c9cdff054aec (Eric W. Biederman           2020-07-12 07:17:50 -0500 1914) 
0c9cdff054aec (Eric W. Biederman           2020-07-12 07:17:50 -0500 1915) 	retval = copy_strings(bprm->envc, envp, bprm);
0c9cdff054aec (Eric W. Biederman           2020-07-12 07:17:50 -0500 1916) 	if (retval < 0)
0c9cdff054aec (Eric W. Biederman           2020-07-12 07:17:50 -0500 1917) 		goto out_free;
0c9cdff054aec (Eric W. Biederman           2020-07-12 07:17:50 -0500 1918) 
0c9cdff054aec (Eric W. Biederman           2020-07-12 07:17:50 -0500 1919) 	retval = copy_strings(bprm->argc, argv, bprm);
0c9cdff054aec (Eric W. Biederman           2020-07-12 07:17:50 -0500 1920) 	if (retval < 0)
0c9cdff054aec (Eric W. Biederman           2020-07-12 07:17:50 -0500 1921) 		goto out_free;
0c9cdff054aec (Eric W. Biederman           2020-07-12 07:17:50 -0500 1922) 
0c9cdff054aec (Eric W. Biederman           2020-07-12 07:17:50 -0500 1923) 	retval = bprm_execve(bprm, fd, filename, flags);
a6f76f23d297f (David Howells               2008-11-14 10:39:24 +1100 1924) out_free:
08a6fac1c6323 (Al Viro                     2008-05-10 16:38:25 -0400 1925) 	free_bprm(bprm);
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1926) 
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1927) out_ret:
25cf336de51b5 (Eric W. Biederman           2020-06-25 13:56:40 -0500 1928) 	putname(filename);
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1929) 	return retval;
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1930) }
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 1931) 
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500 1932) int kernel_execve(const char *kernel_filename,
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500 1933) 		  const char *const *argv, const char *const *envp)
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500 1934) {
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500 1935) 	struct filename *filename;
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500 1936) 	struct linux_binprm *bprm;
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500 1937) 	int fd = AT_FDCWD;
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500 1938) 	int retval;
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500 1939) 
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500 1940) 	filename = getname_kernel(kernel_filename);
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500 1941) 	if (IS_ERR(filename))
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500 1942) 		return PTR_ERR(filename);
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500 1943) 
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500 1944) 	bprm = alloc_bprm(fd, filename);
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500 1945) 	if (IS_ERR(bprm)) {
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500 1946) 		retval = PTR_ERR(bprm);
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500 1947) 		goto out_ret;
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500 1948) 	}
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500 1949) 
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500 1950) 	retval = count_strings_kernel(argv);
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500 1951) 	if (retval < 0)
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500 1952) 		goto out_free;
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500 1953) 	bprm->argc = retval;
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500 1954) 
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500 1955) 	retval = count_strings_kernel(envp);
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500 1956) 	if (retval < 0)
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500 1957) 		goto out_free;
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500 1958) 	bprm->envc = retval;
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500 1959) 
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500 1960) 	retval = bprm_stack_limits(bprm);
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500 1961) 	if (retval < 0)
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500 1962) 		goto out_free;
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500 1963) 
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500 1964) 	retval = copy_string_kernel(bprm->filename, bprm);
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500 1965) 	if (retval < 0)
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500 1966) 		goto out_free;
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500 1967) 	bprm->exec = bprm->p;
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500 1968) 
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500 1969) 	retval = copy_strings_kernel(bprm->envc, envp, bprm);
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500 1970) 	if (retval < 0)
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500 1971) 		goto out_free;
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500 1972) 
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500 1973) 	retval = copy_strings_kernel(bprm->argc, argv, bprm);
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500 1974) 	if (retval < 0)
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500 1975) 		goto out_free;
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500 1976) 
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500 1977) 	retval = bprm_execve(bprm, fd, filename, 0);
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500 1978) out_free:
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500 1979) 	free_bprm(bprm);
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500 1980) out_ret:
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500 1981) 	putname(filename);
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500 1982) 	return retval;
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500 1983) }
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500 1984) 
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500 1985) static int do_execve(struct filename *filename,
ba2d01629d0d1 (Oleg Nesterov               2011-03-06 18:02:37 +0100 1986) 	const char __user *const __user *__argv,
da3d4c5fa5623 (Al Viro                     2012-10-20 21:49:33 -0400 1987) 	const char __user *const __user *__envp)
ba2d01629d0d1 (Oleg Nesterov               2011-03-06 18:02:37 +0100 1988) {
0e028465d18b7 (Oleg Nesterov               2011-03-06 18:02:54 +0100 1989) 	struct user_arg_ptr argv = { .ptr.native = __argv };
0e028465d18b7 (Oleg Nesterov               2011-03-06 18:02:54 +0100 1990) 	struct user_arg_ptr envp = { .ptr.native = __envp };
51f39a1f0cea1 (David Drysdale              2014-12-12 16:57:29 -0800 1991) 	return do_execveat_common(AT_FDCWD, filename, argv, envp, 0);
51f39a1f0cea1 (David Drysdale              2014-12-12 16:57:29 -0800 1992) }
51f39a1f0cea1 (David Drysdale              2014-12-12 16:57:29 -0800 1993) 
be619f7f063a4 (Eric W. Biederman           2020-07-13 12:06:48 -0500 1994) static int do_execveat(int fd, struct filename *filename,
51f39a1f0cea1 (David Drysdale              2014-12-12 16:57:29 -0800 1995) 		const char __user *const __user *__argv,
51f39a1f0cea1 (David Drysdale              2014-12-12 16:57:29 -0800 1996) 		const char __user *const __user *__envp,
51f39a1f0cea1 (David Drysdale              2014-12-12 16:57:29 -0800 1997) 		int flags)
51f39a1f0cea1 (David Drysdale              2014-12-12 16:57:29 -0800 1998) {
51f39a1f0cea1 (David Drysdale              2014-12-12 16:57:29 -0800 1999) 	struct user_arg_ptr argv = { .ptr.native = __argv };
51f39a1f0cea1 (David Drysdale              2014-12-12 16:57:29 -0800 2000) 	struct user_arg_ptr envp = { .ptr.native = __envp };
51f39a1f0cea1 (David Drysdale              2014-12-12 16:57:29 -0800 2001) 
51f39a1f0cea1 (David Drysdale              2014-12-12 16:57:29 -0800 2002) 	return do_execveat_common(fd, filename, argv, envp, flags);
0e028465d18b7 (Oleg Nesterov               2011-03-06 18:02:54 +0100 2003) }
0e028465d18b7 (Oleg Nesterov               2011-03-06 18:02:54 +0100 2004) 
0e028465d18b7 (Oleg Nesterov               2011-03-06 18:02:54 +0100 2005) #ifdef CONFIG_COMPAT
c4ad8f98bef77 (Linus Torvalds              2014-02-05 12:54:53 -0800 2006) static int compat_do_execve(struct filename *filename,
38b983b3461e7 (Al Viro                     2012-09-30 13:38:55 -0400 2007) 	const compat_uptr_t __user *__argv,
d03d26e58fde2 (Al Viro                     2012-10-20 21:46:25 -0400 2008) 	const compat_uptr_t __user *__envp)
0e028465d18b7 (Oleg Nesterov               2011-03-06 18:02:54 +0100 2009) {
0e028465d18b7 (Oleg Nesterov               2011-03-06 18:02:54 +0100 2010) 	struct user_arg_ptr argv = {
0e028465d18b7 (Oleg Nesterov               2011-03-06 18:02:54 +0100 2011) 		.is_compat = true,
0e028465d18b7 (Oleg Nesterov               2011-03-06 18:02:54 +0100 2012) 		.ptr.compat = __argv,
0e028465d18b7 (Oleg Nesterov               2011-03-06 18:02:54 +0100 2013) 	};
0e028465d18b7 (Oleg Nesterov               2011-03-06 18:02:54 +0100 2014) 	struct user_arg_ptr envp = {
0e028465d18b7 (Oleg Nesterov               2011-03-06 18:02:54 +0100 2015) 		.is_compat = true,
0e028465d18b7 (Oleg Nesterov               2011-03-06 18:02:54 +0100 2016) 		.ptr.compat = __envp,
0e028465d18b7 (Oleg Nesterov               2011-03-06 18:02:54 +0100 2017) 	};
51f39a1f0cea1 (David Drysdale              2014-12-12 16:57:29 -0800 2018) 	return do_execveat_common(AT_FDCWD, filename, argv, envp, 0);
51f39a1f0cea1 (David Drysdale              2014-12-12 16:57:29 -0800 2019) }
51f39a1f0cea1 (David Drysdale              2014-12-12 16:57:29 -0800 2020) 
51f39a1f0cea1 (David Drysdale              2014-12-12 16:57:29 -0800 2021) static int compat_do_execveat(int fd, struct filename *filename,
51f39a1f0cea1 (David Drysdale              2014-12-12 16:57:29 -0800 2022) 			      const compat_uptr_t __user *__argv,
51f39a1f0cea1 (David Drysdale              2014-12-12 16:57:29 -0800 2023) 			      const compat_uptr_t __user *__envp,
51f39a1f0cea1 (David Drysdale              2014-12-12 16:57:29 -0800 2024) 			      int flags)
51f39a1f0cea1 (David Drysdale              2014-12-12 16:57:29 -0800 2025) {
51f39a1f0cea1 (David Drysdale              2014-12-12 16:57:29 -0800 2026) 	struct user_arg_ptr argv = {
51f39a1f0cea1 (David Drysdale              2014-12-12 16:57:29 -0800 2027) 		.is_compat = true,
51f39a1f0cea1 (David Drysdale              2014-12-12 16:57:29 -0800 2028) 		.ptr.compat = __argv,
51f39a1f0cea1 (David Drysdale              2014-12-12 16:57:29 -0800 2029) 	};
51f39a1f0cea1 (David Drysdale              2014-12-12 16:57:29 -0800 2030) 	struct user_arg_ptr envp = {
51f39a1f0cea1 (David Drysdale              2014-12-12 16:57:29 -0800 2031) 		.is_compat = true,
51f39a1f0cea1 (David Drysdale              2014-12-12 16:57:29 -0800 2032) 		.ptr.compat = __envp,
51f39a1f0cea1 (David Drysdale              2014-12-12 16:57:29 -0800 2033) 	};
51f39a1f0cea1 (David Drysdale              2014-12-12 16:57:29 -0800 2034) 	return do_execveat_common(fd, filename, argv, envp, flags);
ba2d01629d0d1 (Oleg Nesterov               2011-03-06 18:02:37 +0100 2035) }
0e028465d18b7 (Oleg Nesterov               2011-03-06 18:02:54 +0100 2036) #endif
ba2d01629d0d1 (Oleg Nesterov               2011-03-06 18:02:37 +0100 2037) 
964ee7df90d79 (Oleg Nesterov               2009-09-23 15:56:59 -0700 2038) void set_binfmt(struct linux_binfmt *new)
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 2039) {
801460d0cf5c5 (Hiroshi Shimamoto           2009-09-23 15:57:41 -0700 2040) 	struct mm_struct *mm = current->mm;
801460d0cf5c5 (Hiroshi Shimamoto           2009-09-23 15:57:41 -0700 2041) 
801460d0cf5c5 (Hiroshi Shimamoto           2009-09-23 15:57:41 -0700 2042) 	if (mm->binfmt)
801460d0cf5c5 (Hiroshi Shimamoto           2009-09-23 15:57:41 -0700 2043) 		module_put(mm->binfmt->module);
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 2044) 
801460d0cf5c5 (Hiroshi Shimamoto           2009-09-23 15:57:41 -0700 2045) 	mm->binfmt = new;
964ee7df90d79 (Oleg Nesterov               2009-09-23 15:56:59 -0700 2046) 	if (new)
964ee7df90d79 (Oleg Nesterov               2009-09-23 15:56:59 -0700 2047) 		__module_get(new->module);
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 2048) }
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 2049) EXPORT_SYMBOL(set_binfmt);
^1da177e4c3f4 (Linus Torvalds              2005-04-16 15:20:36 -0700 2050) 
6c5d523826dc6 (Kawai, Hidehiro             2007-07-19 01:48:27 -0700 2051) /*
7288e1187ba93 (Oleg Nesterov               2014-01-23 15:55:32 -0800 2052)  * set_dumpable stores three-value SUID_DUMP_* into mm->flags.
6c5d523826dc6 (Kawai, Hidehiro             2007-07-19 01:48:27 -0700 2053)  */
6c5d523826dc6 (Kawai, Hidehiro             2007-07-19 01:48:27 -0700 2054) void set_dumpable(struct mm_struct *mm, int value)
6c5d523826dc6 (Kawai, Hidehiro             2007-07-19 01:48:27 -0700 2055) {
7288e1187ba93 (Oleg Nesterov               2014-01-23 15:55:32 -0800 2056) 	if (WARN_ON((unsigned)value > SUID_DUMP_ROOT))
7288e1187ba93 (Oleg Nesterov               2014-01-23 15:55:32 -0800 2057) 		return;
7288e1187ba93 (Oleg Nesterov               2014-01-23 15:55:32 -0800 2058) 
26e152252e929 (Vineet Gupta                2019-03-07 16:29:23 -0800 2059) 	set_mask_bits(&mm->flags, MMF_DUMPABLE_MASK, value);
6c5d523826dc6 (Kawai, Hidehiro             2007-07-19 01:48:27 -0700 2060) }
6c5d523826dc6 (Kawai, Hidehiro             2007-07-19 01:48:27 -0700 2061) 
38b983b3461e7 (Al Viro                     2012-09-30 13:38:55 -0400 2062) SYSCALL_DEFINE3(execve,
38b983b3461e7 (Al Viro                     2012-09-30 13:38:55 -0400 2063) 		const char __user *, filename,
38b983b3461e7 (Al Viro                     2012-09-30 13:38:55 -0400 2064) 		const char __user *const __user *, argv,
38b983b3461e7 (Al Viro                     2012-09-30 13:38:55 -0400 2065) 		const char __user *const __user *, envp)
38b983b3461e7 (Al Viro                     2012-09-30 13:38:55 -0400 2066) {
c4ad8f98bef77 (Linus Torvalds              2014-02-05 12:54:53 -0800 2067) 	return do_execve(getname(filename), argv, envp);
38b983b3461e7 (Al Viro                     2012-09-30 13:38:55 -0400 2068) }
51f39a1f0cea1 (David Drysdale              2014-12-12 16:57:29 -0800 2069) 
51f39a1f0cea1 (David Drysdale              2014-12-12 16:57:29 -0800 2070) SYSCALL_DEFINE5(execveat,
51f39a1f0cea1 (David Drysdale              2014-12-12 16:57:29 -0800 2071) 		int, fd, const char __user *, filename,
51f39a1f0cea1 (David Drysdale              2014-12-12 16:57:29 -0800 2072) 		const char __user *const __user *, argv,
51f39a1f0cea1 (David Drysdale              2014-12-12 16:57:29 -0800 2073) 		const char __user *const __user *, envp,
51f39a1f0cea1 (David Drysdale              2014-12-12 16:57:29 -0800 2074) 		int, flags)
51f39a1f0cea1 (David Drysdale              2014-12-12 16:57:29 -0800 2075) {
51f39a1f0cea1 (David Drysdale              2014-12-12 16:57:29 -0800 2076) 	int lookup_flags = (flags & AT_EMPTY_PATH) ? LOOKUP_EMPTY : 0;
51f39a1f0cea1 (David Drysdale              2014-12-12 16:57:29 -0800 2077) 
51f39a1f0cea1 (David Drysdale              2014-12-12 16:57:29 -0800 2078) 	return do_execveat(fd,
51f39a1f0cea1 (David Drysdale              2014-12-12 16:57:29 -0800 2079) 			   getname_flags(filename, lookup_flags, NULL),
51f39a1f0cea1 (David Drysdale              2014-12-12 16:57:29 -0800 2080) 			   argv, envp, flags);
51f39a1f0cea1 (David Drysdale              2014-12-12 16:57:29 -0800 2081) }
51f39a1f0cea1 (David Drysdale              2014-12-12 16:57:29 -0800 2082) 
38b983b3461e7 (Al Viro                     2012-09-30 13:38:55 -0400 2083) #ifdef CONFIG_COMPAT
625b1d7e812d5 (Heiko Carstens              2014-03-04 10:53:50 +0100 2084) COMPAT_SYSCALL_DEFINE3(execve, const char __user *, filename,
625b1d7e812d5 (Heiko Carstens              2014-03-04 10:53:50 +0100 2085) 	const compat_uptr_t __user *, argv,
625b1d7e812d5 (Heiko Carstens              2014-03-04 10:53:50 +0100 2086) 	const compat_uptr_t __user *, envp)
38b983b3461e7 (Al Viro                     2012-09-30 13:38:55 -0400 2087) {
c4ad8f98bef77 (Linus Torvalds              2014-02-05 12:54:53 -0800 2088) 	return compat_do_execve(getname(filename), argv, envp);
38b983b3461e7 (Al Viro                     2012-09-30 13:38:55 -0400 2089) }
51f39a1f0cea1 (David Drysdale              2014-12-12 16:57:29 -0800 2090) 
51f39a1f0cea1 (David Drysdale              2014-12-12 16:57:29 -0800 2091) COMPAT_SYSCALL_DEFINE5(execveat, int, fd,
51f39a1f0cea1 (David Drysdale              2014-12-12 16:57:29 -0800 2092) 		       const char __user *, filename,
51f39a1f0cea1 (David Drysdale              2014-12-12 16:57:29 -0800 2093) 		       const compat_uptr_t __user *, argv,
51f39a1f0cea1 (David Drysdale              2014-12-12 16:57:29 -0800 2094) 		       const compat_uptr_t __user *, envp,
51f39a1f0cea1 (David Drysdale              2014-12-12 16:57:29 -0800 2095) 		       int,  flags)
51f39a1f0cea1 (David Drysdale              2014-12-12 16:57:29 -0800 2096) {
51f39a1f0cea1 (David Drysdale              2014-12-12 16:57:29 -0800 2097) 	int lookup_flags = (flags & AT_EMPTY_PATH) ? LOOKUP_EMPTY : 0;
51f39a1f0cea1 (David Drysdale              2014-12-12 16:57:29 -0800 2098) 
51f39a1f0cea1 (David Drysdale              2014-12-12 16:57:29 -0800 2099) 	return compat_do_execveat(fd,
51f39a1f0cea1 (David Drysdale              2014-12-12 16:57:29 -0800 2100) 				  getname_flags(filename, lookup_flags, NULL),
51f39a1f0cea1 (David Drysdale              2014-12-12 16:57:29 -0800 2101) 				  argv, envp, flags);
51f39a1f0cea1 (David Drysdale              2014-12-12 16:57:29 -0800 2102) }
38b983b3461e7 (Al Viro                     2012-09-30 13:38:55 -0400 2103) #endif