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(¤t->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(¤t->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(¤t->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(¤t_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