1457c8996SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds * linux/fs/exec.c
41da177e4SLinus Torvalds *
51da177e4SLinus Torvalds * Copyright (C) 1991, 1992 Linus Torvalds
61da177e4SLinus Torvalds */
71da177e4SLinus Torvalds
81da177e4SLinus Torvalds /*
91da177e4SLinus Torvalds * #!-checking implemented by tytso.
101da177e4SLinus Torvalds */
111da177e4SLinus Torvalds /*
121da177e4SLinus Torvalds * Demand-loading implemented 01.12.91 - no need to read anything but
131da177e4SLinus Torvalds * the header into memory. The inode of the executable is put into
141da177e4SLinus Torvalds * "current->executable", and page faults do the actual loading. Clean.
151da177e4SLinus Torvalds *
161da177e4SLinus Torvalds * Once more I can proudly say that linux stood up to being changed: it
171da177e4SLinus Torvalds * was less than 2 hours work to get demand-loading completely implemented.
181da177e4SLinus Torvalds *
191da177e4SLinus Torvalds * Demand loading changed July 1993 by Eric Youngdale. Use mmap instead,
201da177e4SLinus Torvalds * current->executable is only used by the procfs. This allows a dispatch
211da177e4SLinus Torvalds * table to check for several different types of binary formats. We keep
221da177e4SLinus Torvalds * trying until we recognize the file or we run out of supported binary
231da177e4SLinus Torvalds * formats.
241da177e4SLinus Torvalds */
251da177e4SLinus Torvalds
26b89999d0SScott Branden #include <linux/kernel_read_file.h>
271da177e4SLinus Torvalds #include <linux/slab.h>
281da177e4SLinus Torvalds #include <linux/file.h>
299f3acc31SAl Viro #include <linux/fdtable.h>
30ba92a43dSHugh Dickins #include <linux/mm.h>
311da177e4SLinus Torvalds #include <linux/stat.h>
321da177e4SLinus Torvalds #include <linux/fcntl.h>
33ba92a43dSHugh Dickins #include <linux/swap.h>
3474aadce9SNeil Horman #include <linux/string.h>
351da177e4SLinus Torvalds #include <linux/init.h>
366e84f315SIngo Molnar #include <linux/sched/mm.h>
37f7ccbae4SIngo Molnar #include <linux/sched/coredump.h>
383f07c014SIngo Molnar #include <linux/sched/signal.h>
396a3827d7SIngo Molnar #include <linux/sched/numa_balancing.h>
4029930025SIngo Molnar #include <linux/sched/task.h>
41ca5b172bSHugh Dickins #include <linux/pagemap.h>
42cdd6c482SIngo Molnar #include <linux/perf_event.h>
431da177e4SLinus Torvalds #include <linux/highmem.h>
441da177e4SLinus Torvalds #include <linux/spinlock.h>
451da177e4SLinus Torvalds #include <linux/key.h>
461da177e4SLinus Torvalds #include <linux/personality.h>
471da177e4SLinus Torvalds #include <linux/binfmts.h>
481da177e4SLinus Torvalds #include <linux/utsname.h>
4984d73786SSukadev Bhattiprolu #include <linux/pid_namespace.h>
501da177e4SLinus Torvalds #include <linux/module.h>
511da177e4SLinus Torvalds #include <linux/namei.h>
521da177e4SLinus Torvalds #include <linux/mount.h>
531da177e4SLinus Torvalds #include <linux/security.h>
541da177e4SLinus Torvalds #include <linux/syscalls.h>
558f0ab514SJay Lan #include <linux/tsacct_kern.h>
569f46080cSMatt Helsley #include <linux/cn_proc.h>
57473ae30bSAl Viro #include <linux/audit.h>
585f4123beSJohannes Berg #include <linux/kmod.h>
596110e3abSEric Paris #include <linux/fsnotify.h>
605ad4e53bSAl Viro #include <linux/fs_struct.h>
613d5992d2SYing Han #include <linux/oom.h>
620e028465SOleg Nesterov #include <linux/compat.h>
63b44a7dfcSMimi Zohar #include <linux/vmalloc.h>
640f212204SJens Axboe #include <linux/io_uring.h>
651446e1dfSGabriel Krisman Bertazi #include <linux/syscall_user_dispatch.h>
6666ad3986SLuis Chamberlain #include <linux/coredump.h>
672b5f9dadSAndrei Vagin #include <linux/time_namespace.h>
68fd593511SBeau Belgrave #include <linux/user_events.h>
691da177e4SLinus Torvalds
707c0f6ba6SLinus Torvalds #include <linux/uaccess.h>
711da177e4SLinus Torvalds #include <asm/mmu_context.h>
72b6a2fea3SOllie Wild #include <asm/tlb.h>
7343d2b113SKAMEZAWA Hiroyuki
7443d2b113SKAMEZAWA Hiroyuki #include <trace/events/task.h>
75a6f76f23SDavid Howells #include "internal.h"
761da177e4SLinus Torvalds
774ff16c25SDavid Smith #include <trace/events/sched.h>
784ff16c25SDavid Smith
7956305aa9SEric W. Biederman static int bprm_creds_from_file(struct linux_binprm *bprm);
8056305aa9SEric W. Biederman
81d6e71144SAlan Cox int suid_dumpable = 0;
82d6e71144SAlan Cox
83e4dc1b14SAlexey Dobriyan static LIST_HEAD(formats);
841da177e4SLinus Torvalds static DEFINE_RWLOCK(binfmt_lock);
851da177e4SLinus Torvalds
__register_binfmt(struct linux_binfmt * fmt,int insert)868fc3dc5aSAl Viro void __register_binfmt(struct linux_binfmt * fmt, int insert)
871da177e4SLinus Torvalds {
881da177e4SLinus Torvalds write_lock(&binfmt_lock);
8974641f58SIvan Kokshaysky insert ? list_add(&fmt->lh, &formats) :
9074641f58SIvan Kokshaysky list_add_tail(&fmt->lh, &formats);
911da177e4SLinus Torvalds write_unlock(&binfmt_lock);
921da177e4SLinus Torvalds }
931da177e4SLinus Torvalds
9474641f58SIvan Kokshaysky EXPORT_SYMBOL(__register_binfmt);
951da177e4SLinus Torvalds
unregister_binfmt(struct linux_binfmt * fmt)96f6b450d4SAlexey Dobriyan void unregister_binfmt(struct linux_binfmt * fmt)
971da177e4SLinus Torvalds {
981da177e4SLinus Torvalds write_lock(&binfmt_lock);
99e4dc1b14SAlexey Dobriyan list_del(&fmt->lh);
1001da177e4SLinus Torvalds write_unlock(&binfmt_lock);
1011da177e4SLinus Torvalds }
1021da177e4SLinus Torvalds
1031da177e4SLinus Torvalds EXPORT_SYMBOL(unregister_binfmt);
1041da177e4SLinus Torvalds
put_binfmt(struct linux_binfmt * fmt)1051da177e4SLinus Torvalds static inline void put_binfmt(struct linux_binfmt * fmt)
1061da177e4SLinus Torvalds {
1071da177e4SLinus Torvalds module_put(fmt->module);
1081da177e4SLinus Torvalds }
1091da177e4SLinus Torvalds
path_noexec(const struct path * path)11090f8572bSEric W. Biederman bool path_noexec(const struct path *path)
11190f8572bSEric W. Biederman {
11290f8572bSEric W. Biederman return (path->mnt->mnt_flags & MNT_NOEXEC) ||
11390f8572bSEric W. Biederman (path->mnt->mnt_sb->s_iflags & SB_I_NOEXEC);
11490f8572bSEric W. Biederman }
11590f8572bSEric W. Biederman
11669369a70SJosh Triplett #ifdef CONFIG_USELIB
1171da177e4SLinus Torvalds /*
1181da177e4SLinus Torvalds * Note that a shared library must be both readable and executable due to
1191da177e4SLinus Torvalds * security reasons.
1201da177e4SLinus Torvalds *
121b452722eSTom Rix * Also note that we take the address to load from the file itself.
1221da177e4SLinus Torvalds */
SYSCALL_DEFINE1(uselib,const char __user *,library)1231e7bfb21SHeiko Carstens SYSCALL_DEFINE1(uselib, const char __user *, library)
1241da177e4SLinus Torvalds {
12572c2d531SAl Viro struct linux_binfmt *fmt;
1261da177e4SLinus Torvalds struct file *file;
12791a27b2aSJeff Layton struct filename *tmp = getname(library);
128964bd183SAl Viro int error = PTR_ERR(tmp);
12947c805dcSAl Viro static const struct open_flags uselib_flags = {
13047c805dcSAl Viro .open_flag = O_LARGEFILE | O_RDONLY | __FMODE_EXEC,
13162fb4a15SAl Viro .acc_mode = MAY_READ | MAY_EXEC,
132f9652e10SAl Viro .intent = LOOKUP_OPEN,
133f9652e10SAl Viro .lookup_flags = LOOKUP_FOLLOW,
13447c805dcSAl Viro };
1351da177e4SLinus Torvalds
1366e8341a1SAl Viro if (IS_ERR(tmp))
1371da177e4SLinus Torvalds goto out;
1381da177e4SLinus Torvalds
139f9652e10SAl Viro file = do_filp_open(AT_FDCWD, tmp, &uselib_flags);
1406e8341a1SAl Viro putname(tmp);
1411da177e4SLinus Torvalds error = PTR_ERR(file);
1421da177e4SLinus Torvalds if (IS_ERR(file))
1431da177e4SLinus Torvalds goto out;
1441da177e4SLinus Torvalds
145633fb6acSKees Cook /*
1460d16f53cSMateusz Guzik * Check do_open_execat() for an explanation.
147633fb6acSKees Cook */
148db19c91cSKees Cook error = -EACCES;
1490d16f53cSMateusz Guzik if (WARN_ON_ONCE(!S_ISREG(file_inode(file)->i_mode)) ||
1500d16f53cSMateusz Guzik path_noexec(&file->f_path))
1516e8341a1SAl Viro goto exit;
1526e8341a1SAl Viro
1531da177e4SLinus Torvalds error = -ENOEXEC;
1541da177e4SLinus Torvalds
1551da177e4SLinus Torvalds read_lock(&binfmt_lock);
156e4dc1b14SAlexey Dobriyan list_for_each_entry(fmt, &formats, lh) {
1571da177e4SLinus Torvalds if (!fmt->load_shlib)
1581da177e4SLinus Torvalds continue;
1591da177e4SLinus Torvalds if (!try_module_get(fmt->module))
1601da177e4SLinus Torvalds continue;
1611da177e4SLinus Torvalds read_unlock(&binfmt_lock);
1621da177e4SLinus Torvalds error = fmt->load_shlib(file);
1631da177e4SLinus Torvalds read_lock(&binfmt_lock);
1641da177e4SLinus Torvalds put_binfmt(fmt);
1651da177e4SLinus Torvalds if (error != -ENOEXEC)
1661da177e4SLinus Torvalds break;
1671da177e4SLinus Torvalds }
1681da177e4SLinus Torvalds read_unlock(&binfmt_lock);
1696e8341a1SAl Viro exit:
1701da177e4SLinus Torvalds fput(file);
1711da177e4SLinus Torvalds out:
1721da177e4SLinus Torvalds return error;
1731da177e4SLinus Torvalds }
17469369a70SJosh Triplett #endif /* #ifdef CONFIG_USELIB */
1751da177e4SLinus Torvalds
176b6a2fea3SOllie Wild #ifdef CONFIG_MMU
177ae6b585eSOleg Nesterov /*
178ae6b585eSOleg Nesterov * The nascent bprm->mm is not visible until exec_mmap() but it can
179ae6b585eSOleg Nesterov * use a lot of memory, account these pages in current->mm temporary
180ae6b585eSOleg Nesterov * for oom_badness()->get_mm_rss(). Once exec succeeds or fails, we
181ae6b585eSOleg Nesterov * change the counter back via acct_arg_size(0).
182ae6b585eSOleg Nesterov */
acct_arg_size(struct linux_binprm * bprm,unsigned long pages)1830e028465SOleg Nesterov static void acct_arg_size(struct linux_binprm *bprm, unsigned long pages)
1843c77f845SOleg Nesterov {
1853c77f845SOleg Nesterov struct mm_struct *mm = current->mm;
1863c77f845SOleg Nesterov long diff = (long)(pages - bprm->vma_pages);
1873c77f845SOleg Nesterov
1883c77f845SOleg Nesterov if (!mm || !diff)
1893c77f845SOleg Nesterov return;
1903c77f845SOleg Nesterov
1913c77f845SOleg Nesterov bprm->vma_pages = pages;
1923c77f845SOleg Nesterov add_mm_counter(mm, MM_ANONPAGES, diff);
1933c77f845SOleg Nesterov }
1943c77f845SOleg Nesterov
get_arg_page(struct linux_binprm * bprm,unsigned long pos,int write)1950e028465SOleg Nesterov static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos,
196b6a2fea3SOllie Wild int write)
197b6a2fea3SOllie Wild {
198b6a2fea3SOllie Wild struct page *page;
199f313c51dSLinus Torvalds struct vm_area_struct *vma = bprm->vma;
200f313c51dSLinus Torvalds struct mm_struct *mm = bprm->mm;
201b6a2fea3SOllie Wild int ret;
202b6a2fea3SOllie Wild
203f313c51dSLinus Torvalds /*
204f313c51dSLinus Torvalds * Avoid relying on expanding the stack down in GUP (which
205f313c51dSLinus Torvalds * does not work for STACK_GROWSUP anyway), and just do it
206f313c51dSLinus Torvalds * by hand ahead of time.
207f313c51dSLinus Torvalds */
208f313c51dSLinus Torvalds if (write && pos < vma->vm_start) {
209f313c51dSLinus Torvalds mmap_write_lock(mm);
2108d7071afSLinus Torvalds ret = expand_downwards(vma, pos);
211f313c51dSLinus Torvalds if (unlikely(ret < 0)) {
212f313c51dSLinus Torvalds mmap_write_unlock(mm);
213b6a2fea3SOllie Wild return NULL;
214b6a2fea3SOllie Wild }
215f313c51dSLinus Torvalds mmap_write_downgrade(mm);
216f313c51dSLinus Torvalds } else
217f313c51dSLinus Torvalds mmap_read_lock(mm);
2189beae1eaSLorenzo Stoakes
2191e987790SDave Hansen /*
2201e987790SDave Hansen * We are doing an exec(). 'current' is the process
221f313c51dSLinus Torvalds * doing the exec and 'mm' is the new process's mm.
2221e987790SDave Hansen */
223f313c51dSLinus Torvalds ret = get_user_pages_remote(mm, pos, 1,
224f313c51dSLinus Torvalds write ? FOLL_WRITE : 0,
225ca5e8632SLorenzo Stoakes &page, NULL);
226f313c51dSLinus Torvalds mmap_read_unlock(mm);
227b6a2fea3SOllie Wild if (ret <= 0)
228b6a2fea3SOllie Wild return NULL;
229b6a2fea3SOllie Wild
230655c16a8SOleg Nesterov if (write)
231f313c51dSLinus Torvalds acct_arg_size(bprm, vma_pages(vma));
232b6a2fea3SOllie Wild
233b6a2fea3SOllie Wild return page;
234b6a2fea3SOllie Wild }
235b6a2fea3SOllie Wild
put_arg_page(struct page * page)236b6a2fea3SOllie Wild static void put_arg_page(struct page *page)
237b6a2fea3SOllie Wild {
238b6a2fea3SOllie Wild put_page(page);
239b6a2fea3SOllie Wild }
240b6a2fea3SOllie Wild
free_arg_pages(struct linux_binprm * bprm)241b6a2fea3SOllie Wild static void free_arg_pages(struct linux_binprm *bprm)
242b6a2fea3SOllie Wild {
243b6a2fea3SOllie Wild }
244b6a2fea3SOllie Wild
flush_arg_page(struct linux_binprm * bprm,unsigned long pos,struct page * page)245b6a2fea3SOllie Wild static void flush_arg_page(struct linux_binprm *bprm, unsigned long pos,
246b6a2fea3SOllie Wild struct page *page)
247b6a2fea3SOllie Wild {
248b6a2fea3SOllie Wild flush_cache_page(bprm->vma, pos, page_to_pfn(page));
249b6a2fea3SOllie Wild }
250b6a2fea3SOllie Wild
__bprm_mm_init(struct linux_binprm * bprm)251b6a2fea3SOllie Wild static int __bprm_mm_init(struct linux_binprm *bprm)
252b6a2fea3SOllie Wild {
253eaccbfa5SLuiz Fernando N. Capitulino int err;
254b6a2fea3SOllie Wild struct vm_area_struct *vma = NULL;
255b6a2fea3SOllie Wild struct mm_struct *mm = bprm->mm;
256b6a2fea3SOllie Wild
257490fc053SLinus Torvalds bprm->vma = vma = vm_area_alloc(mm);
258b6a2fea3SOllie Wild if (!vma)
259eaccbfa5SLuiz Fernando N. Capitulino return -ENOMEM;
260bfd40eafSKirill A. Shutemov vma_set_anonymous(vma);
261b6a2fea3SOllie Wild
262d8ed45c5SMichel Lespinasse if (mmap_write_lock_killable(mm)) {
263f268dfe9SMichal Hocko err = -EINTR;
264f268dfe9SMichal Hocko goto err_free;
265f268dfe9SMichal Hocko }
266b6a2fea3SOllie Wild
267b6a2fea3SOllie Wild /*
268b6a2fea3SOllie Wild * Place the stack at the largest stack address the architecture
269b6a2fea3SOllie Wild * supports. Later, we'll move this to an appropriate place. We don't
270b6a2fea3SOllie Wild * use STACK_TOP because that can depend on attributes which aren't
271b6a2fea3SOllie Wild * configured yet.
272b6a2fea3SOllie Wild */
273aacb3d17SMichal Hocko BUILD_BUG_ON(VM_STACK_FLAGS & VM_STACK_INCOMPLETE_SETUP);
274b6a2fea3SOllie Wild vma->vm_end = STACK_TOP_MAX;
275b6a2fea3SOllie Wild vma->vm_start = vma->vm_end - PAGE_SIZE;
2761c71222eSSuren Baghdasaryan vm_flags_init(vma, VM_SOFTDIRTY | VM_STACK_FLAGS | VM_STACK_INCOMPLETE_SETUP);
2773ed75eb8SColy Li vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
278462e635eSTavis Ormandy
279b6a2fea3SOllie Wild err = insert_vm_struct(mm, vma);
280eaccbfa5SLuiz Fernando N. Capitulino if (err)
281b6a2fea3SOllie Wild goto err;
282b6a2fea3SOllie Wild
283b6a2fea3SOllie Wild mm->stack_vm = mm->total_vm = 1;
284d8ed45c5SMichel Lespinasse mmap_write_unlock(mm);
285b6a2fea3SOllie Wild bprm->p = vma->vm_end - sizeof(void *);
286b6a2fea3SOllie Wild return 0;
287b6a2fea3SOllie Wild err:
288d8ed45c5SMichel Lespinasse mmap_write_unlock(mm);
289f268dfe9SMichal Hocko err_free:
290b6a2fea3SOllie Wild bprm->vma = NULL;
2913928d4f5SLinus Torvalds vm_area_free(vma);
292b6a2fea3SOllie Wild return err;
293b6a2fea3SOllie Wild }
294b6a2fea3SOllie Wild
valid_arg_len(struct linux_binprm * bprm,long len)295b6a2fea3SOllie Wild static bool valid_arg_len(struct linux_binprm *bprm, long len)
296b6a2fea3SOllie Wild {
297b6a2fea3SOllie Wild return len <= MAX_ARG_STRLEN;
298b6a2fea3SOllie Wild }
299b6a2fea3SOllie Wild
300b6a2fea3SOllie Wild #else
301b6a2fea3SOllie Wild
acct_arg_size(struct linux_binprm * bprm,unsigned long pages)3020e028465SOleg Nesterov static inline void acct_arg_size(struct linux_binprm *bprm, unsigned long pages)
3033c77f845SOleg Nesterov {
3043c77f845SOleg Nesterov }
3053c77f845SOleg Nesterov
get_arg_page(struct linux_binprm * bprm,unsigned long pos,int write)3060e028465SOleg Nesterov static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos,
307b6a2fea3SOllie Wild int write)
308b6a2fea3SOllie Wild {
309b6a2fea3SOllie Wild struct page *page;
310b6a2fea3SOllie Wild
311b6a2fea3SOllie Wild page = bprm->page[pos / PAGE_SIZE];
312b6a2fea3SOllie Wild if (!page && write) {
313b6a2fea3SOllie Wild page = alloc_page(GFP_HIGHUSER|__GFP_ZERO);
314b6a2fea3SOllie Wild if (!page)
315b6a2fea3SOllie Wild return NULL;
316b6a2fea3SOllie Wild bprm->page[pos / PAGE_SIZE] = page;
317b6a2fea3SOllie Wild }
318b6a2fea3SOllie Wild
319b6a2fea3SOllie Wild return page;
320b6a2fea3SOllie Wild }
321b6a2fea3SOllie Wild
put_arg_page(struct page * page)322b6a2fea3SOllie Wild static void put_arg_page(struct page *page)
323b6a2fea3SOllie Wild {
324b6a2fea3SOllie Wild }
325b6a2fea3SOllie Wild
free_arg_page(struct linux_binprm * bprm,int i)326b6a2fea3SOllie Wild static void free_arg_page(struct linux_binprm *bprm, int i)
327b6a2fea3SOllie Wild {
328b6a2fea3SOllie Wild if (bprm->page[i]) {
329b6a2fea3SOllie Wild __free_page(bprm->page[i]);
330b6a2fea3SOllie Wild bprm->page[i] = NULL;
331b6a2fea3SOllie Wild }
332b6a2fea3SOllie Wild }
333b6a2fea3SOllie Wild
free_arg_pages(struct linux_binprm * bprm)334b6a2fea3SOllie Wild static void free_arg_pages(struct linux_binprm *bprm)
335b6a2fea3SOllie Wild {
336b6a2fea3SOllie Wild int i;
337b6a2fea3SOllie Wild
338b6a2fea3SOllie Wild for (i = 0; i < MAX_ARG_PAGES; i++)
339b6a2fea3SOllie Wild free_arg_page(bprm, i);
340b6a2fea3SOllie Wild }
341b6a2fea3SOllie Wild
flush_arg_page(struct linux_binprm * bprm,unsigned long pos,struct page * page)342b6a2fea3SOllie Wild static void flush_arg_page(struct linux_binprm *bprm, unsigned long pos,
343b6a2fea3SOllie Wild struct page *page)
344b6a2fea3SOllie Wild {
345b6a2fea3SOllie Wild }
346b6a2fea3SOllie Wild
__bprm_mm_init(struct linux_binprm * bprm)347b6a2fea3SOllie Wild static int __bprm_mm_init(struct linux_binprm *bprm)
348b6a2fea3SOllie Wild {
349b6a2fea3SOllie Wild bprm->p = PAGE_SIZE * MAX_ARG_PAGES - sizeof(void *);
350b6a2fea3SOllie Wild return 0;
351b6a2fea3SOllie Wild }
352b6a2fea3SOllie Wild
valid_arg_len(struct linux_binprm * bprm,long len)353b6a2fea3SOllie Wild static bool valid_arg_len(struct linux_binprm *bprm, long len)
354b6a2fea3SOllie Wild {
355b6a2fea3SOllie Wild return len <= bprm->p;
356b6a2fea3SOllie Wild }
357b6a2fea3SOllie Wild
358b6a2fea3SOllie Wild #endif /* CONFIG_MMU */
359b6a2fea3SOllie Wild
360b6a2fea3SOllie Wild /*
361b6a2fea3SOllie Wild * Create a new mm_struct and populate it with a temporary stack
362b6a2fea3SOllie Wild * vm_area_struct. We don't have enough context at this point to set the stack
363b6a2fea3SOllie Wild * flags, permissions, and offset, so we use temporary values. We'll update
364b6a2fea3SOllie Wild * them later in setup_arg_pages().
365b6a2fea3SOllie Wild */
bprm_mm_init(struct linux_binprm * bprm)3669cc64ceaSYuanhan Liu static int bprm_mm_init(struct linux_binprm *bprm)
367b6a2fea3SOllie Wild {
368b6a2fea3SOllie Wild int err;
369b6a2fea3SOllie Wild struct mm_struct *mm = NULL;
370b6a2fea3SOllie Wild
371b6a2fea3SOllie Wild bprm->mm = mm = mm_alloc();
372b6a2fea3SOllie Wild err = -ENOMEM;
373b6a2fea3SOllie Wild if (!mm)
374b6a2fea3SOllie Wild goto err;
375b6a2fea3SOllie Wild
376c31dbb14SKees Cook /* Save current stack limit for all calculations made during exec. */
377c31dbb14SKees Cook task_lock(current->group_leader);
378c31dbb14SKees Cook bprm->rlim_stack = current->signal->rlim[RLIMIT_STACK];
379c31dbb14SKees Cook task_unlock(current->group_leader);
380c31dbb14SKees Cook
381b6a2fea3SOllie Wild err = __bprm_mm_init(bprm);
382b6a2fea3SOllie Wild if (err)
383b6a2fea3SOllie Wild goto err;
384b6a2fea3SOllie Wild
385b6a2fea3SOllie Wild return 0;
386b6a2fea3SOllie Wild
387b6a2fea3SOllie Wild err:
388b6a2fea3SOllie Wild if (mm) {
389b6a2fea3SOllie Wild bprm->mm = NULL;
390b6a2fea3SOllie Wild mmdrop(mm);
391b6a2fea3SOllie Wild }
392b6a2fea3SOllie Wild
393b6a2fea3SOllie Wild return err;
394b6a2fea3SOllie Wild }
395b6a2fea3SOllie Wild
396ba2d0162SOleg Nesterov struct user_arg_ptr {
3970e028465SOleg Nesterov #ifdef CONFIG_COMPAT
3980e028465SOleg Nesterov bool is_compat;
3990e028465SOleg Nesterov #endif
4000e028465SOleg Nesterov union {
401ba2d0162SOleg Nesterov const char __user *const __user *native;
4020e028465SOleg Nesterov #ifdef CONFIG_COMPAT
40338b983b3SAl Viro const compat_uptr_t __user *compat;
4040e028465SOleg Nesterov #endif
4050e028465SOleg Nesterov } ptr;
406ba2d0162SOleg Nesterov };
407ba2d0162SOleg Nesterov
get_user_arg_ptr(struct user_arg_ptr argv,int nr)408ba2d0162SOleg Nesterov static const char __user *get_user_arg_ptr(struct user_arg_ptr argv, int nr)
4091d1dbf81SOleg Nesterov {
4100e028465SOleg Nesterov const char __user *native;
4111d1dbf81SOleg Nesterov
4120e028465SOleg Nesterov #ifdef CONFIG_COMPAT
4130e028465SOleg Nesterov if (unlikely(argv.is_compat)) {
4140e028465SOleg Nesterov compat_uptr_t compat;
4150e028465SOleg Nesterov
4160e028465SOleg Nesterov if (get_user(compat, argv.ptr.compat + nr))
4171d1dbf81SOleg Nesterov return ERR_PTR(-EFAULT);
4181d1dbf81SOleg Nesterov
4190e028465SOleg Nesterov return compat_ptr(compat);
4200e028465SOleg Nesterov }
4210e028465SOleg Nesterov #endif
4220e028465SOleg Nesterov
4230e028465SOleg Nesterov if (get_user(native, argv.ptr.native + nr))
4240e028465SOleg Nesterov return ERR_PTR(-EFAULT);
4250e028465SOleg Nesterov
4260e028465SOleg Nesterov return native;
4271d1dbf81SOleg Nesterov }
4281d1dbf81SOleg Nesterov
4291da177e4SLinus Torvalds /*
4301da177e4SLinus Torvalds * count() counts the number of strings in array ARGV.
4311da177e4SLinus Torvalds */
count(struct user_arg_ptr argv,int max)432ba2d0162SOleg Nesterov static int count(struct user_arg_ptr argv, int max)
4331da177e4SLinus Torvalds {
4341da177e4SLinus Torvalds int i = 0;
4351da177e4SLinus Torvalds
4360e028465SOleg Nesterov if (argv.ptr.native != NULL) {
4371da177e4SLinus Torvalds for (;;) {
4381d1dbf81SOleg Nesterov const char __user *p = get_user_arg_ptr(argv, i);
4391da177e4SLinus Torvalds
4401da177e4SLinus Torvalds if (!p)
4411da177e4SLinus Torvalds break;
4421d1dbf81SOleg Nesterov
4431d1dbf81SOleg Nesterov if (IS_ERR(p))
4441d1dbf81SOleg Nesterov return -EFAULT;
4451d1dbf81SOleg Nesterov
4466d92d4f6SXi Wang if (i >= max)
4471da177e4SLinus Torvalds return -E2BIG;
4486d92d4f6SXi Wang ++i;
4499aea5a65SRoland McGrath
4509aea5a65SRoland McGrath if (fatal_signal_pending(current))
4519aea5a65SRoland McGrath return -ERESTARTNOHAND;
4521da177e4SLinus Torvalds cond_resched();
4531da177e4SLinus Torvalds }
4541da177e4SLinus Torvalds }
4551da177e4SLinus Torvalds return i;
4561da177e4SLinus Torvalds }
4571da177e4SLinus Torvalds
count_strings_kernel(const char * const * argv)458be619f7fSEric W. Biederman static int count_strings_kernel(const char *const *argv)
459be619f7fSEric W. Biederman {
460be619f7fSEric W. Biederman int i;
461be619f7fSEric W. Biederman
462be619f7fSEric W. Biederman if (!argv)
463be619f7fSEric W. Biederman return 0;
464be619f7fSEric W. Biederman
465be619f7fSEric W. Biederman for (i = 0; argv[i]; ++i) {
466be619f7fSEric W. Biederman if (i >= MAX_ARG_STRINGS)
467be619f7fSEric W. Biederman return -E2BIG;
468be619f7fSEric W. Biederman if (fatal_signal_pending(current))
469be619f7fSEric W. Biederman return -ERESTARTNOHAND;
470be619f7fSEric W. Biederman cond_resched();
471be619f7fSEric W. Biederman }
472be619f7fSEric W. Biederman return i;
473be619f7fSEric W. Biederman }
474be619f7fSEric W. Biederman
bprm_stack_limits(struct linux_binprm * bprm)475d8b9cd54SEric W. Biederman static int bprm_stack_limits(struct linux_binprm *bprm)
476655c16a8SOleg Nesterov {
477655c16a8SOleg Nesterov unsigned long limit, ptr_size;
478655c16a8SOleg Nesterov
479655c16a8SOleg Nesterov /*
480655c16a8SOleg Nesterov * Limit to 1/4 of the max stack size or 3/4 of _STK_LIM
481655c16a8SOleg Nesterov * (whichever is smaller) for the argv+env strings.
482655c16a8SOleg Nesterov * This ensures that:
483655c16a8SOleg Nesterov * - the remaining binfmt code will not run out of stack space,
484655c16a8SOleg Nesterov * - the program will have a reasonable amount of stack left
485655c16a8SOleg Nesterov * to work from.
486655c16a8SOleg Nesterov */
487655c16a8SOleg Nesterov limit = _STK_LIM / 4 * 3;
488655c16a8SOleg Nesterov limit = min(limit, bprm->rlim_stack.rlim_cur / 4);
489655c16a8SOleg Nesterov /*
490655c16a8SOleg Nesterov * We've historically supported up to 32 pages (ARG_MAX)
491655c16a8SOleg Nesterov * of argument strings even with small stacks
492655c16a8SOleg Nesterov */
493655c16a8SOleg Nesterov limit = max_t(unsigned long, limit, ARG_MAX);
494655c16a8SOleg Nesterov /*
495655c16a8SOleg Nesterov * We must account for the size of all the argv and envp pointers to
496655c16a8SOleg Nesterov * the argv and envp strings, since they will also take up space in
497655c16a8SOleg Nesterov * the stack. They aren't stored until much later when we can't
498655c16a8SOleg Nesterov * signal to the parent that the child has run out of stack space.
499655c16a8SOleg Nesterov * Instead, calculate it here so it's possible to fail gracefully.
500dcd46d89SKees Cook *
501dcd46d89SKees Cook * In the case of argc = 0, make sure there is space for adding a
502dcd46d89SKees Cook * empty string (which will bump argc to 1), to ensure confused
503dcd46d89SKees Cook * userspace programs don't start processing from argv[1], thinking
504dcd46d89SKees Cook * argc can never be 0, to keep them from walking envp by accident.
505dcd46d89SKees Cook * See do_execveat_common().
506655c16a8SOleg Nesterov */
507dcd46d89SKees Cook ptr_size = (max(bprm->argc, 1) + bprm->envc) * sizeof(void *);
508655c16a8SOleg Nesterov if (limit <= ptr_size)
509655c16a8SOleg Nesterov return -E2BIG;
510655c16a8SOleg Nesterov limit -= ptr_size;
511655c16a8SOleg Nesterov
512655c16a8SOleg Nesterov bprm->argmin = bprm->p - limit;
513655c16a8SOleg Nesterov return 0;
514655c16a8SOleg Nesterov }
515655c16a8SOleg Nesterov
5161da177e4SLinus Torvalds /*
517b6a2fea3SOllie Wild * 'copy_strings()' copies argument/environment strings from the old
518b6a2fea3SOllie Wild * processes's memory to the new process's stack. The call to get_user_pages()
519b6a2fea3SOllie Wild * ensures the destination page is created and not swapped out.
5201da177e4SLinus Torvalds */
copy_strings(int argc,struct user_arg_ptr argv,struct linux_binprm * bprm)521ba2d0162SOleg Nesterov static int copy_strings(int argc, struct user_arg_ptr argv,
52275c96f85SAdrian Bunk struct linux_binprm *bprm)
5231da177e4SLinus Torvalds {
5241da177e4SLinus Torvalds struct page *kmapped_page = NULL;
5251da177e4SLinus Torvalds char *kaddr = NULL;
526b6a2fea3SOllie Wild unsigned long kpos = 0;
5271da177e4SLinus Torvalds int ret;
5281da177e4SLinus Torvalds
5291da177e4SLinus Torvalds while (argc-- > 0) {
530d7627467SDavid Howells const char __user *str;
5311da177e4SLinus Torvalds int len;
5321da177e4SLinus Torvalds unsigned long pos;
5331da177e4SLinus Torvalds
5341da177e4SLinus Torvalds ret = -EFAULT;
5351d1dbf81SOleg Nesterov str = get_user_arg_ptr(argv, argc);
5361d1dbf81SOleg Nesterov if (IS_ERR(str))
5371da177e4SLinus Torvalds goto out;
5381da177e4SLinus Torvalds
5391d1dbf81SOleg Nesterov len = strnlen_user(str, MAX_ARG_STRLEN);
5401d1dbf81SOleg Nesterov if (!len)
5411da177e4SLinus Torvalds goto out;
5421d1dbf81SOleg Nesterov
5431d1dbf81SOleg Nesterov ret = -E2BIG;
5441d1dbf81SOleg Nesterov if (!valid_arg_len(bprm, len))
5451d1dbf81SOleg Nesterov goto out;
5461da177e4SLinus Torvalds
547b452722eSTom Rix /* We're going to work our way backwards. */
5481da177e4SLinus Torvalds pos = bprm->p;
549b6a2fea3SOllie Wild str += len;
550b6a2fea3SOllie Wild bprm->p -= len;
551655c16a8SOleg Nesterov #ifdef CONFIG_MMU
552655c16a8SOleg Nesterov if (bprm->p < bprm->argmin)
553655c16a8SOleg Nesterov goto out;
554655c16a8SOleg Nesterov #endif
5551da177e4SLinus Torvalds
5561da177e4SLinus Torvalds while (len > 0) {
5571da177e4SLinus Torvalds int offset, bytes_to_copy;
5581da177e4SLinus Torvalds
5599aea5a65SRoland McGrath if (fatal_signal_pending(current)) {
5609aea5a65SRoland McGrath ret = -ERESTARTNOHAND;
5619aea5a65SRoland McGrath goto out;
5629aea5a65SRoland McGrath }
5637993bc1fSRoland McGrath cond_resched();
5647993bc1fSRoland McGrath
5651da177e4SLinus Torvalds offset = pos % PAGE_SIZE;
566b6a2fea3SOllie Wild if (offset == 0)
567b6a2fea3SOllie Wild offset = PAGE_SIZE;
568b6a2fea3SOllie Wild
569b6a2fea3SOllie Wild bytes_to_copy = offset;
570b6a2fea3SOllie Wild if (bytes_to_copy > len)
571b6a2fea3SOllie Wild bytes_to_copy = len;
572b6a2fea3SOllie Wild
573b6a2fea3SOllie Wild offset -= bytes_to_copy;
574b6a2fea3SOllie Wild pos -= bytes_to_copy;
575b6a2fea3SOllie Wild str -= bytes_to_copy;
576b6a2fea3SOllie Wild len -= bytes_to_copy;
577b6a2fea3SOllie Wild
578b6a2fea3SOllie Wild if (!kmapped_page || kpos != (pos & PAGE_MASK)) {
579b6a2fea3SOllie Wild struct page *page;
580b6a2fea3SOllie Wild
581b6a2fea3SOllie Wild page = get_arg_page(bprm, pos, 1);
5821da177e4SLinus Torvalds if (!page) {
583b6a2fea3SOllie Wild ret = -E2BIG;
5841da177e4SLinus Torvalds goto out;
5851da177e4SLinus Torvalds }
5861da177e4SLinus Torvalds
587b6a2fea3SOllie Wild if (kmapped_page) {
588f358afc5SChristoph Hellwig flush_dcache_page(kmapped_page);
5893a608cfeSFabio M. De Francesco kunmap_local(kaddr);
590b6a2fea3SOllie Wild put_arg_page(kmapped_page);
591b6a2fea3SOllie Wild }
5921da177e4SLinus Torvalds kmapped_page = page;
5933a608cfeSFabio M. De Francesco kaddr = kmap_local_page(kmapped_page);
594b6a2fea3SOllie Wild kpos = pos & PAGE_MASK;
595b6a2fea3SOllie Wild flush_arg_page(bprm, kpos, kmapped_page);
5961da177e4SLinus Torvalds }
597b6a2fea3SOllie Wild if (copy_from_user(kaddr+offset, str, bytes_to_copy)) {
5981da177e4SLinus Torvalds ret = -EFAULT;
5991da177e4SLinus Torvalds goto out;
6001da177e4SLinus Torvalds }
6011da177e4SLinus Torvalds }
6021da177e4SLinus Torvalds }
6031da177e4SLinus Torvalds ret = 0;
6041da177e4SLinus Torvalds out:
605b6a2fea3SOllie Wild if (kmapped_page) {
606f358afc5SChristoph Hellwig flush_dcache_page(kmapped_page);
6073a608cfeSFabio M. De Francesco kunmap_local(kaddr);
608b6a2fea3SOllie Wild put_arg_page(kmapped_page);
609b6a2fea3SOllie Wild }
6101da177e4SLinus Torvalds return ret;
6111da177e4SLinus Torvalds }
6121da177e4SLinus Torvalds
6131da177e4SLinus Torvalds /*
614986db2d1SChristoph Hellwig * Copy and argument/environment string from the kernel to the processes stack.
6151da177e4SLinus Torvalds */
copy_string_kernel(const char * arg,struct linux_binprm * bprm)616986db2d1SChristoph Hellwig int copy_string_kernel(const char *arg, struct linux_binprm *bprm)
6171da177e4SLinus Torvalds {
618762a3af6SChristoph Hellwig int len = strnlen(arg, MAX_ARG_STRLEN) + 1 /* terminating NUL */;
619762a3af6SChristoph Hellwig unsigned long pos = bprm->p;
620ba2d0162SOleg Nesterov
621762a3af6SChristoph Hellwig if (len == 0)
622762a3af6SChristoph Hellwig return -EFAULT;
623762a3af6SChristoph Hellwig if (!valid_arg_len(bprm, len))
624762a3af6SChristoph Hellwig return -E2BIG;
625ba2d0162SOleg Nesterov
626762a3af6SChristoph Hellwig /* We're going to work our way backwards. */
627762a3af6SChristoph Hellwig arg += len;
628762a3af6SChristoph Hellwig bprm->p -= len;
629762a3af6SChristoph Hellwig if (IS_ENABLED(CONFIG_MMU) && bprm->p < bprm->argmin)
630762a3af6SChristoph Hellwig return -E2BIG;
631762a3af6SChristoph Hellwig
632762a3af6SChristoph Hellwig while (len > 0) {
633762a3af6SChristoph Hellwig unsigned int bytes_to_copy = min_t(unsigned int, len,
634762a3af6SChristoph Hellwig min_not_zero(offset_in_page(pos), PAGE_SIZE));
635762a3af6SChristoph Hellwig struct page *page;
636762a3af6SChristoph Hellwig
637762a3af6SChristoph Hellwig pos -= bytes_to_copy;
638762a3af6SChristoph Hellwig arg -= bytes_to_copy;
639762a3af6SChristoph Hellwig len -= bytes_to_copy;
640762a3af6SChristoph Hellwig
641762a3af6SChristoph Hellwig page = get_arg_page(bprm, pos, 1);
642762a3af6SChristoph Hellwig if (!page)
643762a3af6SChristoph Hellwig return -E2BIG;
644762a3af6SChristoph Hellwig flush_arg_page(bprm, pos & PAGE_MASK, page);
645c6e8e36cSFabio M. De Francesco memcpy_to_page(page, offset_in_page(pos), arg, bytes_to_copy);
646762a3af6SChristoph Hellwig put_arg_page(page);
6471da177e4SLinus Torvalds }
648762a3af6SChristoph Hellwig
649762a3af6SChristoph Hellwig return 0;
6501da177e4SLinus Torvalds }
651986db2d1SChristoph Hellwig EXPORT_SYMBOL(copy_string_kernel);
6521da177e4SLinus Torvalds
copy_strings_kernel(int argc,const char * const * argv,struct linux_binprm * bprm)653be619f7fSEric W. Biederman static int copy_strings_kernel(int argc, const char *const *argv,
654be619f7fSEric W. Biederman struct linux_binprm *bprm)
655be619f7fSEric W. Biederman {
656be619f7fSEric W. Biederman while (argc-- > 0) {
657be619f7fSEric W. Biederman int ret = copy_string_kernel(argv[argc], bprm);
658be619f7fSEric W. Biederman if (ret < 0)
659be619f7fSEric W. Biederman return ret;
660be619f7fSEric W. Biederman if (fatal_signal_pending(current))
661be619f7fSEric W. Biederman return -ERESTARTNOHAND;
662be619f7fSEric W. Biederman cond_resched();
663be619f7fSEric W. Biederman }
664be619f7fSEric W. Biederman return 0;
665be619f7fSEric W. Biederman }
666be619f7fSEric W. Biederman
6671da177e4SLinus Torvalds #ifdef CONFIG_MMU
668b6a2fea3SOllie Wild
6691da177e4SLinus Torvalds /*
670b6a2fea3SOllie Wild * During bprm_mm_init(), we create a temporary stack at STACK_TOP_MAX. Once
671b6a2fea3SOllie Wild * the binfmt code determines where the new stack should reside, we shift it to
672b6a2fea3SOllie Wild * its final location. The process proceeds as follows:
6731da177e4SLinus Torvalds *
674b6a2fea3SOllie Wild * 1) Use shift to calculate the new vma endpoints.
675b6a2fea3SOllie Wild * 2) Extend vma to cover both the old and new ranges. This ensures the
676b6a2fea3SOllie Wild * arguments passed to subsequent functions are consistent.
677b6a2fea3SOllie Wild * 3) Move vma's page tables to the new range.
678b6a2fea3SOllie Wild * 4) Free up any cleared pgd range.
679b6a2fea3SOllie Wild * 5) Shrink the vma to cover only the new range.
6801da177e4SLinus Torvalds */
shift_arg_pages(struct vm_area_struct * vma,unsigned long shift)681b6a2fea3SOllie Wild static int shift_arg_pages(struct vm_area_struct *vma, unsigned long shift)
6821da177e4SLinus Torvalds {
6831da177e4SLinus Torvalds struct mm_struct *mm = vma->vm_mm;
684b6a2fea3SOllie Wild unsigned long old_start = vma->vm_start;
685b6a2fea3SOllie Wild unsigned long old_end = vma->vm_end;
686b6a2fea3SOllie Wild unsigned long length = old_end - old_start;
687b6a2fea3SOllie Wild unsigned long new_start = old_start - shift;
688b6a2fea3SOllie Wild unsigned long new_end = old_end - shift;
68919066e58SMatthew Wilcox (Oracle) VMA_ITERATOR(vmi, mm, new_start);
69019066e58SMatthew Wilcox (Oracle) struct vm_area_struct *next;
691d16dfc55SPeter Zijlstra struct mmu_gather tlb;
6921da177e4SLinus Torvalds
693b6a2fea3SOllie Wild BUG_ON(new_start > new_end);
6941da177e4SLinus Torvalds
695b6a2fea3SOllie Wild /*
696b6a2fea3SOllie Wild * ensure there are no vmas between where we want to go
697b6a2fea3SOllie Wild * and where we are
6981da177e4SLinus Torvalds */
69919066e58SMatthew Wilcox (Oracle) if (vma != vma_next(&vmi))
700b6a2fea3SOllie Wild return -EFAULT;
7011da177e4SLinus Torvalds
702b5df0922SLiam R. Howlett vma_iter_prev_range(&vmi);
703b6a2fea3SOllie Wild /*
704b6a2fea3SOllie Wild * cover the whole range: [new_start, old_end)
705b6a2fea3SOllie Wild */
706cf51e86dSLiam R. Howlett if (vma_expand(&vmi, vma, new_start, old_end, vma->vm_pgoff, NULL))
7075beb4930SRik van Riel return -ENOMEM;
7081da177e4SLinus Torvalds
709b6a2fea3SOllie Wild /*
710b6a2fea3SOllie Wild * move the page tables downwards, on failure we rely on
711b6a2fea3SOllie Wild * process cleanup to remove whatever mess we made.
712b6a2fea3SOllie Wild */
713b6a2fea3SOllie Wild if (length != move_page_tables(vma, old_start,
71438a76013SMichel Lespinasse vma, new_start, length, false))
7151da177e4SLinus Torvalds return -ENOMEM;
7161da177e4SLinus Torvalds
717b6a2fea3SOllie Wild lru_add_drain();
718a72afd87SWill Deacon tlb_gather_mmu(&tlb, mm);
71919066e58SMatthew Wilcox (Oracle) next = vma_next(&vmi);
720b6a2fea3SOllie Wild if (new_end > old_start) {
721b6a2fea3SOllie Wild /*
722b6a2fea3SOllie Wild * when the old and new regions overlap clear from new_end.
723b6a2fea3SOllie Wild */
724d16dfc55SPeter Zijlstra free_pgd_range(&tlb, new_end, old_end, new_end,
72519066e58SMatthew Wilcox (Oracle) next ? next->vm_start : USER_PGTABLES_CEILING);
726b6a2fea3SOllie Wild } else {
727b6a2fea3SOllie Wild /*
728b6a2fea3SOllie Wild * otherwise, clean from old_start; this is done to not touch
729b6a2fea3SOllie Wild * the address space in [new_end, old_start) some architectures
730b6a2fea3SOllie Wild * have constraints on va-space that make this illegal (IA64) -
731b6a2fea3SOllie Wild * for the others its just a little faster.
732b6a2fea3SOllie Wild */
733d16dfc55SPeter Zijlstra free_pgd_range(&tlb, old_start, old_end, new_end,
73419066e58SMatthew Wilcox (Oracle) next ? next->vm_start : USER_PGTABLES_CEILING);
7351da177e4SLinus Torvalds }
736ae8eba8bSWill Deacon tlb_finish_mmu(&tlb);
7371da177e4SLinus Torvalds
738b373037fSLiam R. Howlett vma_prev(&vmi);
739b373037fSLiam R. Howlett /* Shrink the vma to just the new range */
740cf51e86dSLiam R. Howlett return vma_shrink(&vmi, vma, new_start, new_end, vma->vm_pgoff);
7411da177e4SLinus Torvalds }
7421da177e4SLinus Torvalds
743b6a2fea3SOllie Wild /*
744b6a2fea3SOllie Wild * Finalizes the stack vm_area_struct. The flags and permissions are updated,
745b6a2fea3SOllie Wild * the stack is optionally relocated, and some extra space is added.
746b6a2fea3SOllie Wild */
setup_arg_pages(struct linux_binprm * bprm,unsigned long stack_top,int executable_stack)747b6a2fea3SOllie Wild int setup_arg_pages(struct linux_binprm *bprm,
748b6a2fea3SOllie Wild unsigned long stack_top,
749b6a2fea3SOllie Wild int executable_stack)
7501da177e4SLinus Torvalds {
751b6a2fea3SOllie Wild unsigned long ret;
752b6a2fea3SOllie Wild unsigned long stack_shift;
753b6a2fea3SOllie Wild struct mm_struct *mm = current->mm;
754b6a2fea3SOllie Wild struct vm_area_struct *vma = bprm->vma;
755b6a2fea3SOllie Wild struct vm_area_struct *prev = NULL;
756b6a2fea3SOllie Wild unsigned long vm_flags;
757b6a2fea3SOllie Wild unsigned long stack_base;
758803bf5ecSMichael Neuling unsigned long stack_size;
759803bf5ecSMichael Neuling unsigned long stack_expand;
760803bf5ecSMichael Neuling unsigned long rlim_stack;
7614a18419fSNadav Amit struct mmu_gather tlb;
7622286a691SLiam R. Howlett struct vma_iterator vmi;
7631da177e4SLinus Torvalds
764b6a2fea3SOllie Wild #ifdef CONFIG_STACK_GROWSUP
765d71f290bSJames Hogan /* Limit stack size */
766c31dbb14SKees Cook stack_base = bprm->rlim_stack.rlim_max;
76722ee3ea5SHelge Deller
76822ee3ea5SHelge Deller stack_base = calc_max_stack_size(stack_base);
769b6a2fea3SOllie Wild
770d045c77cSHelge Deller /* Add space for stack randomization. */
771a17dfde5SHelge Deller if (current->flags & PF_RANDOMIZE)
772d045c77cSHelge Deller stack_base += (STACK_RND_MASK << PAGE_SHIFT);
773d045c77cSHelge Deller
774b6a2fea3SOllie Wild /* Make sure we didn't let the argument array grow too large. */
775b6a2fea3SOllie Wild if (vma->vm_end - vma->vm_start > stack_base)
776b6a2fea3SOllie Wild return -ENOMEM;
777b6a2fea3SOllie Wild
778b6a2fea3SOllie Wild stack_base = PAGE_ALIGN(stack_top - stack_base);
779b6a2fea3SOllie Wild
780b6a2fea3SOllie Wild stack_shift = vma->vm_start - stack_base;
781b6a2fea3SOllie Wild mm->arg_start = bprm->p - stack_shift;
782b6a2fea3SOllie Wild bprm->p = vma->vm_end - stack_shift;
783b6a2fea3SOllie Wild #else
784b6a2fea3SOllie Wild stack_top = arch_align_stack(stack_top);
785b6a2fea3SOllie Wild stack_top = PAGE_ALIGN(stack_top);
7861b528181SRoland McGrath
7871b528181SRoland McGrath if (unlikely(stack_top < mmap_min_addr) ||
7881b528181SRoland McGrath unlikely(vma->vm_end - vma->vm_start >= stack_top - mmap_min_addr))
7891b528181SRoland McGrath return -ENOMEM;
7901b528181SRoland McGrath
791b6a2fea3SOllie Wild stack_shift = vma->vm_end - stack_top;
792b6a2fea3SOllie Wild
793b6a2fea3SOllie Wild bprm->p -= stack_shift;
794b6a2fea3SOllie Wild mm->arg_start = bprm->p;
795b6a2fea3SOllie Wild #endif
796b6a2fea3SOllie Wild
797b6a2fea3SOllie Wild if (bprm->loader)
798b6a2fea3SOllie Wild bprm->loader -= stack_shift;
799b6a2fea3SOllie Wild bprm->exec -= stack_shift;
800b6a2fea3SOllie Wild
801d8ed45c5SMichel Lespinasse if (mmap_write_lock_killable(mm))
802f268dfe9SMichal Hocko return -EINTR;
803f268dfe9SMichal Hocko
80496a8e13eSHugh Dickins vm_flags = VM_STACK_FLAGS;
805b6a2fea3SOllie Wild
806b6a2fea3SOllie Wild /*
807b6a2fea3SOllie Wild * Adjust stack execute permissions; explicitly enable for
808b6a2fea3SOllie Wild * EXSTACK_ENABLE_X, disable for EXSTACK_DISABLE_X and leave alone
809b6a2fea3SOllie Wild * (arch default) otherwise.
810b6a2fea3SOllie Wild */
811b6a2fea3SOllie Wild if (unlikely(executable_stack == EXSTACK_ENABLE_X))
812b6a2fea3SOllie Wild vm_flags |= VM_EXEC;
813b6a2fea3SOllie Wild else if (executable_stack == EXSTACK_DISABLE_X)
814b6a2fea3SOllie Wild vm_flags &= ~VM_EXEC;
815b6a2fea3SOllie Wild vm_flags |= mm->def_flags;
816a8bef8ffSMel Gorman vm_flags |= VM_STACK_INCOMPLETE_SETUP;
817b6a2fea3SOllie Wild
8182286a691SLiam R. Howlett vma_iter_init(&vmi, mm, vma->vm_start);
8192286a691SLiam R. Howlett
8204a18419fSNadav Amit tlb_gather_mmu(&tlb, mm);
8212286a691SLiam R. Howlett ret = mprotect_fixup(&vmi, &tlb, vma, &prev, vma->vm_start, vma->vm_end,
822b6a2fea3SOllie Wild vm_flags);
8234a18419fSNadav Amit tlb_finish_mmu(&tlb);
8244a18419fSNadav Amit
825b6a2fea3SOllie Wild if (ret)
826b6a2fea3SOllie Wild goto out_unlock;
827b6a2fea3SOllie Wild BUG_ON(prev != vma);
828b6a2fea3SOllie Wild
82947a2ebb7SAlexey Dobriyan if (unlikely(vm_flags & VM_EXEC)) {
83047a2ebb7SAlexey Dobriyan pr_warn_once("process '%pD4' started with executable stack\n",
83147a2ebb7SAlexey Dobriyan bprm->file);
83247a2ebb7SAlexey Dobriyan }
83347a2ebb7SAlexey Dobriyan
834b6a2fea3SOllie Wild /* Move stack pages down in memory. */
835b6a2fea3SOllie Wild if (stack_shift) {
836b6a2fea3SOllie Wild ret = shift_arg_pages(vma, stack_shift);
837fc63cf23SAnton Blanchard if (ret)
838fc63cf23SAnton Blanchard goto out_unlock;
8391da177e4SLinus Torvalds }
8401da177e4SLinus Torvalds
841a8bef8ffSMel Gorman /* mprotect_fixup is overkill to remove the temporary stack flags */
8421c71222eSSuren Baghdasaryan vm_flags_clear(vma, VM_STACK_INCOMPLETE_SETUP);
843a8bef8ffSMel Gorman
8445ef097ddSMichael Neuling stack_expand = 131072UL; /* randomly 32*4k (or 2*64k) pages */
845803bf5ecSMichael Neuling stack_size = vma->vm_end - vma->vm_start;
846803bf5ecSMichael Neuling /*
847803bf5ecSMichael Neuling * Align this down to a page boundary as expand_stack
848803bf5ecSMichael Neuling * will align it up.
849803bf5ecSMichael Neuling */
850c31dbb14SKees Cook rlim_stack = bprm->rlim_stack.rlim_cur & PAGE_MASK;
851bfb4a2b9SRolf Eike Beer
852bfb4a2b9SRolf Eike Beer stack_expand = min(rlim_stack, stack_size + stack_expand);
853bfb4a2b9SRolf Eike Beer
854b6a2fea3SOllie Wild #ifdef CONFIG_STACK_GROWSUP
855bfb4a2b9SRolf Eike Beer stack_base = vma->vm_start + stack_expand;
856b6a2fea3SOllie Wild #else
857bfb4a2b9SRolf Eike Beer stack_base = vma->vm_end - stack_expand;
858b6a2fea3SOllie Wild #endif
8593af9e859SEric B Munson current->mm->start_stack = bprm->p;
8608d7071afSLinus Torvalds ret = expand_stack_locked(vma, stack_base);
861b6a2fea3SOllie Wild if (ret)
862b6a2fea3SOllie Wild ret = -EFAULT;
863b6a2fea3SOllie Wild
864b6a2fea3SOllie Wild out_unlock:
865d8ed45c5SMichel Lespinasse mmap_write_unlock(mm);
866fc63cf23SAnton Blanchard return ret;
867b6a2fea3SOllie Wild }
868b6a2fea3SOllie Wild EXPORT_SYMBOL(setup_arg_pages);
869b6a2fea3SOllie Wild
8707e7ec6a9SNicolas Pitre #else
8717e7ec6a9SNicolas Pitre
8727e7ec6a9SNicolas Pitre /*
8737e7ec6a9SNicolas Pitre * Transfer the program arguments and environment from the holding pages
8747e7ec6a9SNicolas Pitre * onto the stack. The provided stack pointer is adjusted accordingly.
8757e7ec6a9SNicolas Pitre */
transfer_args_to_stack(struct linux_binprm * bprm,unsigned long * sp_location)8767e7ec6a9SNicolas Pitre int transfer_args_to_stack(struct linux_binprm *bprm,
8777e7ec6a9SNicolas Pitre unsigned long *sp_location)
8787e7ec6a9SNicolas Pitre {
8797e7ec6a9SNicolas Pitre unsigned long index, stop, sp;
8807e7ec6a9SNicolas Pitre int ret = 0;
8817e7ec6a9SNicolas Pitre
8827e7ec6a9SNicolas Pitre stop = bprm->p >> PAGE_SHIFT;
8837e7ec6a9SNicolas Pitre sp = *sp_location;
8847e7ec6a9SNicolas Pitre
8857e7ec6a9SNicolas Pitre for (index = MAX_ARG_PAGES - 1; index >= stop; index--) {
8867e7ec6a9SNicolas Pitre unsigned int offset = index == stop ? bprm->p & ~PAGE_MASK : 0;
8873a608cfeSFabio M. De Francesco char *src = kmap_local_page(bprm->page[index]) + offset;
8887e7ec6a9SNicolas Pitre sp -= PAGE_SIZE - offset;
8897e7ec6a9SNicolas Pitre if (copy_to_user((void *) sp, src, PAGE_SIZE - offset) != 0)
8907e7ec6a9SNicolas Pitre ret = -EFAULT;
8913a608cfeSFabio M. De Francesco kunmap_local(src);
8927e7ec6a9SNicolas Pitre if (ret)
8937e7ec6a9SNicolas Pitre goto out;
8947e7ec6a9SNicolas Pitre }
8957e7ec6a9SNicolas Pitre
896c3639d87SMax Filippov bprm->exec += *sp_location - MAX_ARG_PAGES * PAGE_SIZE;
8977e7ec6a9SNicolas Pitre *sp_location = sp;
8987e7ec6a9SNicolas Pitre
8997e7ec6a9SNicolas Pitre out:
9007e7ec6a9SNicolas Pitre return ret;
9017e7ec6a9SNicolas Pitre }
9027e7ec6a9SNicolas Pitre EXPORT_SYMBOL(transfer_args_to_stack);
9037e7ec6a9SNicolas Pitre
9041da177e4SLinus Torvalds #endif /* CONFIG_MMU */
9051da177e4SLinus Torvalds
do_open_execat(int fd,struct filename * name,int flags)90651f39a1fSDavid Drysdale static struct file *do_open_execat(int fd, struct filename *name, int flags)
9071da177e4SLinus Torvalds {
9081da177e4SLinus Torvalds struct file *file;
909e56b6a5dSChristoph Hellwig int err;
91051f39a1fSDavid Drysdale struct open_flags open_exec_flags = {
91147c805dcSAl Viro .open_flag = O_LARGEFILE | O_RDONLY | __FMODE_EXEC,
91262fb4a15SAl Viro .acc_mode = MAY_EXEC,
913f9652e10SAl Viro .intent = LOOKUP_OPEN,
914f9652e10SAl Viro .lookup_flags = LOOKUP_FOLLOW,
91547c805dcSAl Viro };
9161da177e4SLinus Torvalds
91751f39a1fSDavid Drysdale if ((flags & ~(AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH)) != 0)
91851f39a1fSDavid Drysdale return ERR_PTR(-EINVAL);
91951f39a1fSDavid Drysdale if (flags & AT_SYMLINK_NOFOLLOW)
92051f39a1fSDavid Drysdale open_exec_flags.lookup_flags &= ~LOOKUP_FOLLOW;
92151f39a1fSDavid Drysdale if (flags & AT_EMPTY_PATH)
92251f39a1fSDavid Drysdale open_exec_flags.lookup_flags |= LOOKUP_EMPTY;
92351f39a1fSDavid Drysdale
92451f39a1fSDavid Drysdale file = do_filp_open(fd, name, &open_exec_flags);
9256e8341a1SAl Viro if (IS_ERR(file))
9260d16f53cSMateusz Guzik return file;
9271da177e4SLinus Torvalds
928633fb6acSKees Cook /*
9290d16f53cSMateusz Guzik * In the past the regular type check was here. It moved to may_open() in
9300d16f53cSMateusz Guzik * 633fb6ac3980 ("exec: move S_ISREG() check earlier"). Since then it is
9310d16f53cSMateusz Guzik * an invariant that all non-regular files error out before we get here.
932633fb6acSKees Cook */
933e56b6a5dSChristoph Hellwig err = -EACCES;
9340d16f53cSMateusz Guzik if (WARN_ON_ONCE(!S_ISREG(file_inode(file)->i_mode)) ||
9350d16f53cSMateusz Guzik path_noexec(&file->f_path))
9366e8341a1SAl Viro goto exit;
937e56b6a5dSChristoph Hellwig
9381da177e4SLinus Torvalds err = deny_write_access(file);
9396e8341a1SAl Viro if (err)
9406e8341a1SAl Viro goto exit;
9411da177e4SLinus Torvalds
942e56b6a5dSChristoph Hellwig return file;
943e56b6a5dSChristoph Hellwig
9446e8341a1SAl Viro exit:
9456e8341a1SAl Viro fput(file);
946e56b6a5dSChristoph Hellwig return ERR_PTR(err);
947e56b6a5dSChristoph Hellwig }
948c4ad8f98SLinus Torvalds
open_exec(const char * name)949c4ad8f98SLinus Torvalds struct file *open_exec(const char *name)
950c4ad8f98SLinus Torvalds {
95151689104SPaul Moore struct filename *filename = getname_kernel(name);
95251689104SPaul Moore struct file *f = ERR_CAST(filename);
95351689104SPaul Moore
95451689104SPaul Moore if (!IS_ERR(filename)) {
95551689104SPaul Moore f = do_open_execat(AT_FDCWD, filename, 0);
95651689104SPaul Moore putname(filename);
95751689104SPaul Moore }
95851689104SPaul Moore return f;
959c4ad8f98SLinus Torvalds }
9601da177e4SLinus Torvalds EXPORT_SYMBOL(open_exec);
9611da177e4SLinus Torvalds
962987f20a9SEric W. Biederman #if defined(CONFIG_BINFMT_FLAT) || defined(CONFIG_BINFMT_ELF_FDPIC)
read_code(struct file * file,unsigned long addr,loff_t pos,size_t len)9633dc20cb2SAl Viro ssize_t read_code(struct file *file, unsigned long addr, loff_t pos, size_t len)
9643dc20cb2SAl Viro {
965ec695579SAl Viro ssize_t res = vfs_read(file, (void __user *)addr, len, &pos);
9663dc20cb2SAl Viro if (res > 0)
967bce2b68bSChristoph Hellwig flush_icache_user_range(addr, addr + len);
9683dc20cb2SAl Viro return res;
9693dc20cb2SAl Viro }
9703dc20cb2SAl Viro EXPORT_SYMBOL(read_code);
97148304f79SChristoph Hellwig #endif
9723dc20cb2SAl Viro
973eea96732SEric W. Biederman /*
974eea96732SEric W. Biederman * Maps the mm_struct mm into the current task struct.
975f7cfd871SEric W. Biederman * On success, this function returns with exec_update_lock
976f7cfd871SEric W. Biederman * held for writing.
977eea96732SEric W. Biederman */
exec_mmap(struct mm_struct * mm)9781da177e4SLinus Torvalds static int exec_mmap(struct mm_struct *mm)
9791da177e4SLinus Torvalds {
9801da177e4SLinus Torvalds struct task_struct *tsk;
9811da177e4SLinus Torvalds struct mm_struct *old_mm, *active_mm;
982eea96732SEric W. Biederman int ret;
9831da177e4SLinus Torvalds
9841da177e4SLinus Torvalds /* Notify parent that we're no longer interested in the old VM */
9851da177e4SLinus Torvalds tsk = current;
9861da177e4SLinus Torvalds old_mm = current->mm;
9874610ba7aSThomas Gleixner exec_mm_release(tsk, old_mm);
988a28bf136SEric W. Biederman if (old_mm)
989a28bf136SEric W. Biederman sync_mm_rss(old_mm);
9901da177e4SLinus Torvalds
991f7cfd871SEric W. Biederman ret = down_write_killable(&tsk->signal->exec_update_lock);
992eea96732SEric W. Biederman if (ret)
993eea96732SEric W. Biederman return ret;
994eea96732SEric W. Biederman
9951da177e4SLinus Torvalds if (old_mm) {
9961da177e4SLinus Torvalds /*
9977e3c4fb7SEric W. Biederman * If there is a pending fatal signal perhaps a signal
9987e3c4fb7SEric W. Biederman * whose default action is to create a coredump get
9997e3c4fb7SEric W. Biederman * out and die instead of going through with the exec.
10001da177e4SLinus Torvalds */
10017e3c4fb7SEric W. Biederman ret = mmap_read_lock_killable(old_mm);
10027e3c4fb7SEric W. Biederman if (ret) {
1003f7cfd871SEric W. Biederman up_write(&tsk->signal->exec_update_lock);
10047e3c4fb7SEric W. Biederman return ret;
10051da177e4SLinus Torvalds }
10061da177e4SLinus Torvalds }
1007eea96732SEric W. Biederman
10081da177e4SLinus Torvalds task_lock(tsk);
1009227a4aadSMathieu Desnoyers membarrier_exec_mmap(mm);
1010d53c3dfbSNicholas Piggin
1011d53c3dfbSNicholas Piggin local_irq_disable();
1012d53c3dfbSNicholas Piggin active_mm = tsk->active_mm;
10131da177e4SLinus Torvalds tsk->active_mm = mm;
1014d53c3dfbSNicholas Piggin tsk->mm = mm;
1015af7f588dSMathieu Desnoyers mm_init_cid(mm);
1016d53c3dfbSNicholas Piggin /*
1017d53c3dfbSNicholas Piggin * This prevents preemption while active_mm is being loaded and
1018d53c3dfbSNicholas Piggin * it and mm are being updated, which could cause problems for
1019d53c3dfbSNicholas Piggin * lazy tlb mm refcounting when these are updated by context
1020d53c3dfbSNicholas Piggin * switches. Not all architectures can handle irqs off over
1021d53c3dfbSNicholas Piggin * activate_mm yet.
1022d53c3dfbSNicholas Piggin */
1023d53c3dfbSNicholas Piggin if (!IS_ENABLED(CONFIG_ARCH_WANT_IRQS_OFF_ACTIVATE_MM))
1024d53c3dfbSNicholas Piggin local_irq_enable();
10251da177e4SLinus Torvalds activate_mm(active_mm, mm);
1026d53c3dfbSNicholas Piggin if (IS_ENABLED(CONFIG_ARCH_WANT_IRQS_OFF_ACTIVATE_MM))
1027d53c3dfbSNicholas Piggin local_irq_enable();
1028dda1c41aSSebastian Andrzej Siewior lru_gen_add_mm(mm);
10291da177e4SLinus Torvalds task_unlock(tsk);
1030bd74fdaeSYu Zhao lru_gen_use_mm(mm);
10311da177e4SLinus Torvalds if (old_mm) {
1032d8ed45c5SMichel Lespinasse mmap_read_unlock(old_mm);
10337dddb12cSEric Sesterhenn BUG_ON(active_mm != old_mm);
1034701085b2SOleg Nesterov setmax_mm_hiwater_rss(&tsk->signal->maxrss, old_mm);
103531a78f23SBalbir Singh mm_update_next_owner(old_mm);
10361da177e4SLinus Torvalds mmput(old_mm);
10371da177e4SLinus Torvalds return 0;
10381da177e4SLinus Torvalds }
1039aa464ba9SNicholas Piggin mmdrop_lazy_tlb(active_mm);
10401da177e4SLinus Torvalds return 0;
10411da177e4SLinus Torvalds }
10421da177e4SLinus Torvalds
de_thread(struct task_struct * tsk)1043858119e1SArjan van de Ven static int de_thread(struct task_struct *tsk)
10441da177e4SLinus Torvalds {
10451da177e4SLinus Torvalds struct signal_struct *sig = tsk->signal;
1046b2c903b8SOleg Nesterov struct sighand_struct *oldsighand = tsk->sighand;
10471da177e4SLinus Torvalds spinlock_t *lock = &oldsighand->siglock;
10481da177e4SLinus Torvalds
1049aafe6c2aSEric W. Biederman if (thread_group_empty(tsk))
10501da177e4SLinus Torvalds goto no_thread_group;
10511da177e4SLinus Torvalds
10521da177e4SLinus Torvalds /*
10531da177e4SLinus Torvalds * Kill all other threads in the thread group.
10541da177e4SLinus Torvalds */
10551da177e4SLinus Torvalds spin_lock_irq(lock);
105649697335SEric W. Biederman if ((sig->flags & SIGNAL_GROUP_EXIT) || sig->group_exec_task) {
10571da177e4SLinus Torvalds /*
10581da177e4SLinus Torvalds * Another group action in progress, just
10591da177e4SLinus Torvalds * return so that the signal is processed.
10601da177e4SLinus Torvalds */
10611da177e4SLinus Torvalds spin_unlock_irq(lock);
10621da177e4SLinus Torvalds return -EAGAIN;
10631da177e4SLinus Torvalds }
10641da177e4SLinus Torvalds
106560700e38SEric W. Biederman sig->group_exec_task = tsk;
1066d344193aSOleg Nesterov sig->notify_count = zap_other_threads(tsk);
1067d344193aSOleg Nesterov if (!thread_group_leader(tsk))
1068d344193aSOleg Nesterov sig->notify_count--;
1069d344193aSOleg Nesterov
1070d344193aSOleg Nesterov while (sig->notify_count) {
1071d5bbd43dSOleg Nesterov __set_current_state(TASK_KILLABLE);
10721da177e4SLinus Torvalds spin_unlock_irq(lock);
1073a72173ecSRafael J. Wysocki schedule();
107408d405c8SDavidlohr Bueso if (__fatal_signal_pending(tsk))
1075d5bbd43dSOleg Nesterov goto killed;
10761da177e4SLinus Torvalds spin_lock_irq(lock);
10771da177e4SLinus Torvalds }
10781da177e4SLinus Torvalds spin_unlock_irq(lock);
10791da177e4SLinus Torvalds
10801da177e4SLinus Torvalds /*
10811da177e4SLinus Torvalds * At this point all other threads have exited, all we have to
10821da177e4SLinus Torvalds * do is to wait for the thread group leader to become inactive,
10831da177e4SLinus Torvalds * and to assume its PID:
10841da177e4SLinus Torvalds */
1085aafe6c2aSEric W. Biederman if (!thread_group_leader(tsk)) {
10868187926bSOleg Nesterov struct task_struct *leader = tsk->group_leader;
10876db840faSOleg Nesterov
10886db840faSOleg Nesterov for (;;) {
1089780de9ddSIngo Molnar cgroup_threadgroup_change_begin(tsk);
10906db840faSOleg Nesterov write_lock_irq(&tasklist_lock);
1091dfcce791SKirill Tkhai /*
1092dfcce791SKirill Tkhai * Do this under tasklist_lock to ensure that
109360700e38SEric W. Biederman * exit_notify() can't miss ->group_exec_task
1094dfcce791SKirill Tkhai */
1095dfcce791SKirill Tkhai sig->notify_count = -1;
10966db840faSOleg Nesterov if (likely(leader->exit_state))
10976db840faSOleg Nesterov break;
1098d5bbd43dSOleg Nesterov __set_current_state(TASK_KILLABLE);
10996db840faSOleg Nesterov write_unlock_irq(&tasklist_lock);
1100780de9ddSIngo Molnar cgroup_threadgroup_change_end(tsk);
1101a72173ecSRafael J. Wysocki schedule();
110208d405c8SDavidlohr Bueso if (__fatal_signal_pending(tsk))
1103d5bbd43dSOleg Nesterov goto killed;
11046db840faSOleg Nesterov }
11051da177e4SLinus Torvalds
1106f5e90281SRoland McGrath /*
1107f5e90281SRoland McGrath * The only record we have of the real-time age of a
1108f5e90281SRoland McGrath * process, regardless of execs it's done, is start_time.
1109f5e90281SRoland McGrath * All the past CPU time is accumulated in signal_struct
1110f5e90281SRoland McGrath * from sister threads now dead. But in this non-leader
1111f5e90281SRoland McGrath * exec, nothing survives from the original leader thread,
1112f5e90281SRoland McGrath * whose birth marks the true age of this process now.
1113f5e90281SRoland McGrath * When we take on its identity by switching to its PID, we
1114f5e90281SRoland McGrath * also take its birthdate (always earlier than our own).
1115f5e90281SRoland McGrath */
1116aafe6c2aSEric W. Biederman tsk->start_time = leader->start_time;
1117cf25e24dSPeter Zijlstra tsk->start_boottime = leader->start_boottime;
1118f5e90281SRoland McGrath
1119bac0abd6SPavel Emelyanov BUG_ON(!same_thread_group(leader, tsk));
11201da177e4SLinus Torvalds /*
11211da177e4SLinus Torvalds * An exec() starts a new thread group with the
11221da177e4SLinus Torvalds * TGID of the previous thread group. Rehash the
11231da177e4SLinus Torvalds * two threads with a switched PID, and release
11241da177e4SLinus Torvalds * the former thread group leader:
11251da177e4SLinus Torvalds */
1126d73d6529SEric W. Biederman
1127d73d6529SEric W. Biederman /* Become a process group leader with the old leader's pid.
1128c18258c6SEric W. Biederman * The old leader becomes a thread of the this thread group.
1129d73d6529SEric W. Biederman */
11306b03d130SEric W. Biederman exchange_tids(tsk, leader);
11316883f81aSEric W. Biederman transfer_pid(leader, tsk, PIDTYPE_TGID);
1132aafe6c2aSEric W. Biederman transfer_pid(leader, tsk, PIDTYPE_PGID);
1133aafe6c2aSEric W. Biederman transfer_pid(leader, tsk, PIDTYPE_SID);
11349cd80bbbSOleg Nesterov
1135aafe6c2aSEric W. Biederman list_replace_rcu(&leader->tasks, &tsk->tasks);
11369cd80bbbSOleg Nesterov list_replace_init(&leader->sibling, &tsk->sibling);
11371da177e4SLinus Torvalds
1138aafe6c2aSEric W. Biederman tsk->group_leader = tsk;
1139aafe6c2aSEric W. Biederman leader->group_leader = tsk;
1140de12a787SEric W. Biederman
1141aafe6c2aSEric W. Biederman tsk->exit_signal = SIGCHLD;
1142087806b1SOleg Nesterov leader->exit_signal = -1;
1143962b564cSOleg Nesterov
1144962b564cSOleg Nesterov BUG_ON(leader->exit_state != EXIT_ZOMBIE);
1145962b564cSOleg Nesterov leader->exit_state = EXIT_DEAD;
1146eac1b5e5SOleg Nesterov
1147eac1b5e5SOleg Nesterov /*
1148eac1b5e5SOleg Nesterov * We are going to release_task()->ptrace_unlink() silently,
1149eac1b5e5SOleg Nesterov * the tracer can sleep in do_wait(). EXIT_DEAD guarantees
11505036793dSZhang Jiaming * the tracer won't block again waiting for this thread.
1151eac1b5e5SOleg Nesterov */
1152eac1b5e5SOleg Nesterov if (unlikely(leader->ptrace))
1153eac1b5e5SOleg Nesterov __wake_up_parent(leader, leader->parent);
11541da177e4SLinus Torvalds write_unlock_irq(&tasklist_lock);
1155780de9ddSIngo Molnar cgroup_threadgroup_change_end(tsk);
11568187926bSOleg Nesterov
11578187926bSOleg Nesterov release_task(leader);
11581da177e4SLinus Torvalds }
11591da177e4SLinus Torvalds
116060700e38SEric W. Biederman sig->group_exec_task = NULL;
11616db840faSOleg Nesterov sig->notify_count = 0;
11621da177e4SLinus Torvalds
11631da177e4SLinus Torvalds no_thread_group:
1164e6368253SOleg Nesterov /* we have changed execution domain */
1165e6368253SOleg Nesterov tsk->exit_signal = SIGCHLD;
1166e6368253SOleg Nesterov
116702169155SEric W. Biederman BUG_ON(!thread_group_leader(tsk));
116802169155SEric W. Biederman return 0;
116902169155SEric W. Biederman
117002169155SEric W. Biederman killed:
117102169155SEric W. Biederman /* protects against exit_notify() and __exit_signal() */
117202169155SEric W. Biederman read_lock(&tasklist_lock);
117360700e38SEric W. Biederman sig->group_exec_task = NULL;
117402169155SEric W. Biederman sig->notify_count = 0;
117502169155SEric W. Biederman read_unlock(&tasklist_lock);
117602169155SEric W. Biederman return -EAGAIN;
117702169155SEric W. Biederman }
117802169155SEric W. Biederman
117902169155SEric W. Biederman
11807a60ef48SEric W. Biederman /*
11817a60ef48SEric W. Biederman * This function makes sure the current process has its own signal table,
11827a60ef48SEric W. Biederman * so that flush_signal_handlers can later reset the handlers without
11837a60ef48SEric W. Biederman * disturbing other processes. (Other processes might share the signal
11847a60ef48SEric W. Biederman * table via the CLONE_SIGHAND option to clone().)
11857a60ef48SEric W. Biederman */
unshare_sighand(struct task_struct * me)118602169155SEric W. Biederman static int unshare_sighand(struct task_struct *me)
118702169155SEric W. Biederman {
118802169155SEric W. Biederman struct sighand_struct *oldsighand = me->sighand;
1189329f7dbaSOleg Nesterov
1190d036bda7SElena Reshetova if (refcount_read(&oldsighand->count) != 1) {
1191b2c903b8SOleg Nesterov struct sighand_struct *newsighand;
11921da177e4SLinus Torvalds /*
1193b2c903b8SOleg Nesterov * This ->sighand is shared with the CLONE_SIGHAND
1194b2c903b8SOleg Nesterov * but not CLONE_THREAD task, switch to the new one.
11951da177e4SLinus Torvalds */
1196b2c903b8SOleg Nesterov newsighand = kmem_cache_alloc(sighand_cachep, GFP_KERNEL);
1197b2c903b8SOleg Nesterov if (!newsighand)
1198b2c903b8SOleg Nesterov return -ENOMEM;
1199b2c903b8SOleg Nesterov
1200d036bda7SElena Reshetova refcount_set(&newsighand->count, 1);
12011da177e4SLinus Torvalds
12021da177e4SLinus Torvalds write_lock_irq(&tasklist_lock);
12031da177e4SLinus Torvalds spin_lock(&oldsighand->siglock);
12045bf2fedcSBernd Edlinger memcpy(newsighand->action, oldsighand->action,
12055bf2fedcSBernd Edlinger sizeof(newsighand->action));
120602169155SEric W. Biederman rcu_assign_pointer(me->sighand, newsighand);
12071da177e4SLinus Torvalds spin_unlock(&oldsighand->siglock);
12081da177e4SLinus Torvalds write_unlock_irq(&tasklist_lock);
12091da177e4SLinus Torvalds
1210fba2afaaSDavide Libenzi __cleanup_sighand(oldsighand);
12111da177e4SLinus Torvalds }
12121da177e4SLinus Torvalds return 0;
12131da177e4SLinus Torvalds }
12141da177e4SLinus Torvalds
__get_task_comm(char * buf,size_t buf_size,struct task_struct * tsk)12153756f640SArnd Bergmann char *__get_task_comm(char *buf, size_t buf_size, struct task_struct *tsk)
12161da177e4SLinus Torvalds {
12171da177e4SLinus Torvalds task_lock(tsk);
1218503471acSYafang Shao /* Always NUL terminated and zero-padded */
1219503471acSYafang Shao strscpy_pad(buf, tsk->comm, buf_size);
12201da177e4SLinus Torvalds task_unlock(tsk);
122159714d65SAndrew Morton return buf;
12221da177e4SLinus Torvalds }
12233756f640SArnd Bergmann EXPORT_SYMBOL_GPL(__get_task_comm);
12241da177e4SLinus Torvalds
12256a6d27deSAl Viro /*
12266a6d27deSAl Viro * These functions flushes out all traces of the currently running executable
12276a6d27deSAl Viro * so that a new one can be started
12286a6d27deSAl Viro */
12296a6d27deSAl Viro
__set_task_comm(struct task_struct * tsk,const char * buf,bool exec)123082b89778SAdrian Hunter void __set_task_comm(struct task_struct *tsk, const char *buf, bool exec)
12311da177e4SLinus Torvalds {
12321da177e4SLinus Torvalds task_lock(tsk);
123343d2b113SKAMEZAWA Hiroyuki trace_task_rename(tsk, buf);
123406c5088aSYafang Shao strscpy_pad(tsk->comm, buf, sizeof(tsk->comm));
12351da177e4SLinus Torvalds task_unlock(tsk);
123682b89778SAdrian Hunter perf_event_comm(tsk, exec);
12371da177e4SLinus Torvalds }
12381da177e4SLinus Torvalds
1239a9208e42SKees Cook /*
1240a9208e42SKees Cook * Calling this is the point of no return. None of the failures will be
1241a9208e42SKees Cook * seen by userspace since either the process is already taking a fatal
1242a9208e42SKees Cook * signal (via de_thread() or coredump), or will have SEGV raised
124313c432b5SEric W. Biederman * (after exec_mmap()) by search_binary_handler (see below).
1244a9208e42SKees Cook */
begin_new_exec(struct linux_binprm * bprm)12452388777aSEric W. Biederman int begin_new_exec(struct linux_binprm * bprm)
12461da177e4SLinus Torvalds {
12472ca7be7dSEric W. Biederman struct task_struct *me = current;
1248221af7f8SLinus Torvalds int retval;
12491da177e4SLinus Torvalds
125056305aa9SEric W. Biederman /* Once we are committed compute the creds */
125156305aa9SEric W. Biederman retval = bprm_creds_from_file(bprm);
125256305aa9SEric W. Biederman if (retval)
125356305aa9SEric W. Biederman return retval;
125456305aa9SEric W. Biederman
12551da177e4SLinus Torvalds /*
12566834e0bbSEric W. Biederman * Ensure all future errors are fatal.
12576834e0bbSEric W. Biederman */
12586834e0bbSEric W. Biederman bprm->point_of_no_return = true;
12596834e0bbSEric W. Biederman
12601da177e4SLinus Torvalds /*
126102169155SEric W. Biederman * Make this the only thread in the thread group.
12621da177e4SLinus Torvalds */
12632ca7be7dSEric W. Biederman retval = de_thread(me);
12641da177e4SLinus Torvalds if (retval)
12651da177e4SLinus Torvalds goto out;
12661da177e4SLinus Torvalds
12676e399cd1SDavidlohr Bueso /*
12689ee1206dSEric W. Biederman * Cancel any io_uring activity across execve
12699ee1206dSEric W. Biederman */
12709ee1206dSEric W. Biederman io_uring_task_cancel();
12719ee1206dSEric W. Biederman
1272b6043501SEric W. Biederman /* Ensure the files table is not shared. */
12731f702603SEric W. Biederman retval = unshare_files();
1274b6043501SEric W. Biederman if (retval)
1275b6043501SEric W. Biederman goto out;
1276b6043501SEric W. Biederman
12776e399cd1SDavidlohr Bueso /*
12786e399cd1SDavidlohr Bueso * Must be called _before_ exec_mmap() as bprm->mm is
1279a7031f14SMateusz Guzik * not visible until then. Doing it here also ensures
1280a7031f14SMateusz Guzik * we don't race against replace_mm_exe_file().
12816e399cd1SDavidlohr Bueso */
1282fe69d560SDavid Hildenbrand retval = set_mm_exe_file(bprm->mm, bprm->file);
1283fe69d560SDavid Hildenbrand if (retval)
1284fe69d560SDavid Hildenbrand goto out;
12856e399cd1SDavidlohr Bueso
1286b8a61c9eSEric W. Biederman /* If the binary is not readable then enforce mm->dumpable=0 */
1287f87d1c95SEric W. Biederman would_dump(bprm, bprm->file);
1288b8a61c9eSEric W. Biederman if (bprm->have_execfd)
1289b8a61c9eSEric W. Biederman would_dump(bprm, bprm->executable);
1290f87d1c95SEric W. Biederman
12911da177e4SLinus Torvalds /*
12921da177e4SLinus Torvalds * Release all of the old mmap stuff
12931da177e4SLinus Torvalds */
12943c77f845SOleg Nesterov acct_arg_size(bprm, 0);
12951da177e4SLinus Torvalds retval = exec_mmap(bprm->mm);
12961da177e4SLinus Torvalds if (retval)
1297fd8328beSAl Viro goto out;
12981da177e4SLinus Torvalds
1299a9208e42SKees Cook bprm->mm = NULL;
13007ab02af4SLinus Torvalds
13012b5f9dadSAndrei Vagin retval = exec_task_namespaces();
13022b5f9dadSAndrei Vagin if (retval)
13032b5f9dadSAndrei Vagin goto out_unlock;
13042b5f9dadSAndrei Vagin
1305ccf0fa6bSEric W. Biederman #ifdef CONFIG_POSIX_TIMERS
1306e362359aSThadeu Lima de Souza Cascardo spin_lock_irq(&me->sighand->siglock);
1307e362359aSThadeu Lima de Souza Cascardo posix_cpu_timers_exit(me);
1308e362359aSThadeu Lima de Souza Cascardo spin_unlock_irq(&me->sighand->siglock);
1309d5b36a4dSOleg Nesterov exit_itimers(me);
1310ccf0fa6bSEric W. Biederman flush_itimer_signals();
1311ccf0fa6bSEric W. Biederman #endif
1312ccf0fa6bSEric W. Biederman
1313ccf0fa6bSEric W. Biederman /*
1314ccf0fa6bSEric W. Biederman * Make the signal table private.
1315ccf0fa6bSEric W. Biederman */
1316ccf0fa6bSEric W. Biederman retval = unshare_sighand(me);
1317ccf0fa6bSEric W. Biederman if (retval)
131889826cceSEric W. Biederman goto out_unlock;
1319ccf0fa6bSEric W. Biederman
13201b2552cbSEric W. Biederman me->flags &= ~(PF_RANDOMIZE | PF_FORKNOEXEC |
1321b88fae64SZhang Yi PF_NOFREEZE | PF_NO_SETAFFINITY);
13227ab02af4SLinus Torvalds flush_thread();
13232ca7be7dSEric W. Biederman me->personality &= ~bprm->per_clear;
13247ab02af4SLinus Torvalds
13251446e1dfSGabriel Krisman Bertazi clear_syscall_work_syscall_user_dispatch(me);
13261446e1dfSGabriel Krisman Bertazi
1327613cc2b6SAleksa Sarai /*
1328613cc2b6SAleksa Sarai * We have to apply CLOEXEC before we change whether the process is
1329613cc2b6SAleksa Sarai * dumpable (in setup_new_exec) to avoid a race with a process in userspace
1330613cc2b6SAleksa Sarai * trying to access the should-be-closed file descriptors of a process
1331613cc2b6SAleksa Sarai * undergoing exec(2).
1332613cc2b6SAleksa Sarai */
13332ca7be7dSEric W. Biederman do_close_on_exec(me->files);
1334df9e4d2cSEric W. Biederman
1335df9e4d2cSEric W. Biederman if (bprm->secureexec) {
1336df9e4d2cSEric W. Biederman /* Make sure parent cannot signal privileged process. */
1337df9e4d2cSEric W. Biederman me->pdeath_signal = 0;
1338df9e4d2cSEric W. Biederman
1339df9e4d2cSEric W. Biederman /*
1340df9e4d2cSEric W. Biederman * For secureexec, reset the stack limit to sane default to
1341df9e4d2cSEric W. Biederman * avoid bad behavior from the prior rlimits. This has to
1342df9e4d2cSEric W. Biederman * happen before arch_pick_mmap_layout(), which examines
1343df9e4d2cSEric W. Biederman * RLIMIT_STACK, but after the point of no return to avoid
1344df9e4d2cSEric W. Biederman * needing to clean up the change on failure.
1345df9e4d2cSEric W. Biederman */
1346df9e4d2cSEric W. Biederman if (bprm->rlim_stack.rlim_cur > _STK_LIM)
1347df9e4d2cSEric W. Biederman bprm->rlim_stack.rlim_cur = _STK_LIM;
1348df9e4d2cSEric W. Biederman }
1349df9e4d2cSEric W. Biederman
1350df9e4d2cSEric W. Biederman me->sas_ss_sp = me->sas_ss_size = 0;
1351df9e4d2cSEric W. Biederman
1352df9e4d2cSEric W. Biederman /*
1353df9e4d2cSEric W. Biederman * Figure out dumpability. Note that this checking only of current
1354df9e4d2cSEric W. Biederman * is wrong, but userspace depends on it. This should be testing
1355df9e4d2cSEric W. Biederman * bprm->secureexec instead.
1356df9e4d2cSEric W. Biederman */
1357df9e4d2cSEric W. Biederman if (bprm->interp_flags & BINPRM_FLAGS_ENFORCE_NONDUMP ||
1358df9e4d2cSEric W. Biederman !(uid_eq(current_euid(), current_uid()) &&
1359df9e4d2cSEric W. Biederman gid_eq(current_egid(), current_gid())))
1360df9e4d2cSEric W. Biederman set_dumpable(current->mm, suid_dumpable);
1361df9e4d2cSEric W. Biederman else
1362df9e4d2cSEric W. Biederman set_dumpable(current->mm, SUID_DUMP_USER);
1363df9e4d2cSEric W. Biederman
1364df9e4d2cSEric W. Biederman perf_event_exec();
1365*dc5da273SKees Cook
1366*dc5da273SKees Cook /*
1367*dc5da273SKees Cook * If the original filename was empty, alloc_bprm() made up a path
1368*dc5da273SKees Cook * that will probably not be useful to admins running ps or similar.
1369*dc5da273SKees Cook * Let's fix it up to be something reasonable.
1370*dc5da273SKees Cook */
1371*dc5da273SKees Cook if (bprm->comm_from_dentry) {
1372*dc5da273SKees Cook /*
1373*dc5da273SKees Cook * Hold RCU lock to keep the name from being freed behind our back.
1374*dc5da273SKees Cook * Use acquire semantics to make sure the terminating NUL from
1375*dc5da273SKees Cook * __d_alloc() is seen.
1376*dc5da273SKees Cook *
1377*dc5da273SKees Cook * Note, we're deliberately sloppy here. We don't need to care about
1378*dc5da273SKees Cook * detecting a concurrent rename and just want a terminated name.
1379*dc5da273SKees Cook */
1380*dc5da273SKees Cook rcu_read_lock();
1381*dc5da273SKees Cook __set_task_comm(me, smp_load_acquire(&bprm->file->f_path.dentry->d_name.name),
1382*dc5da273SKees Cook true);
1383*dc5da273SKees Cook rcu_read_unlock();
1384*dc5da273SKees Cook } else {
1385df9e4d2cSEric W. Biederman __set_task_comm(me, kbasename(bprm->filename), true);
1386*dc5da273SKees Cook }
1387df9e4d2cSEric W. Biederman
1388df9e4d2cSEric W. Biederman /* An exec changes our domain. We are no longer part of the thread
1389df9e4d2cSEric W. Biederman group */
1390df9e4d2cSEric W. Biederman WRITE_ONCE(me->self_exec_id, me->self_exec_id + 1);
1391df9e4d2cSEric W. Biederman flush_signal_handlers(me, 0);
1392df9e4d2cSEric W. Biederman
1393905ae01cSAlexey Gladkov retval = set_cred_ucounts(bprm->cred);
1394905ae01cSAlexey Gladkov if (retval < 0)
1395905ae01cSAlexey Gladkov goto out_unlock;
1396905ae01cSAlexey Gladkov
1397df9e4d2cSEric W. Biederman /*
1398df9e4d2cSEric W. Biederman * install the new credentials for this executable
1399df9e4d2cSEric W. Biederman */
1400df9e4d2cSEric W. Biederman security_bprm_committing_creds(bprm);
1401df9e4d2cSEric W. Biederman
1402df9e4d2cSEric W. Biederman commit_creds(bprm->cred);
1403df9e4d2cSEric W. Biederman bprm->cred = NULL;
1404df9e4d2cSEric W. Biederman
1405df9e4d2cSEric W. Biederman /*
1406df9e4d2cSEric W. Biederman * Disable monitoring for regular users
1407df9e4d2cSEric W. Biederman * when executing setuid binaries. Must
1408df9e4d2cSEric W. Biederman * wait until new credentials are committed
1409df9e4d2cSEric W. Biederman * by commit_creds() above
1410df9e4d2cSEric W. Biederman */
1411df9e4d2cSEric W. Biederman if (get_dumpable(me->mm) != SUID_DUMP_USER)
1412df9e4d2cSEric W. Biederman perf_event_exit_task(me);
1413df9e4d2cSEric W. Biederman /*
1414df9e4d2cSEric W. Biederman * cred_guard_mutex must be held at least to this point to prevent
1415df9e4d2cSEric W. Biederman * ptrace_attach() from altering our determination of the task's
1416df9e4d2cSEric W. Biederman * credentials; any time after this it may be unlocked.
1417df9e4d2cSEric W. Biederman */
1418df9e4d2cSEric W. Biederman security_bprm_committed_creds(bprm);
1419b8a61c9eSEric W. Biederman
1420b8a61c9eSEric W. Biederman /* Pass the opened binary to the interpreter. */
1421b8a61c9eSEric W. Biederman if (bprm->have_execfd) {
1422b8a61c9eSEric W. Biederman retval = get_unused_fd_flags(0);
1423b8a61c9eSEric W. Biederman if (retval < 0)
1424b8a61c9eSEric W. Biederman goto out_unlock;
1425b8a61c9eSEric W. Biederman fd_install(retval, bprm->executable);
1426b8a61c9eSEric W. Biederman bprm->executable = NULL;
1427b8a61c9eSEric W. Biederman bprm->execfd = retval;
1428b8a61c9eSEric W. Biederman }
1429221af7f8SLinus Torvalds return 0;
1430221af7f8SLinus Torvalds
143189826cceSEric W. Biederman out_unlock:
1432f7cfd871SEric W. Biederman up_write(&me->signal->exec_update_lock);
1433841460c1SBernd Edlinger if (!bprm->cred)
1434841460c1SBernd Edlinger mutex_unlock(&me->signal->cred_guard_mutex);
1435841460c1SBernd Edlinger
1436221af7f8SLinus Torvalds out:
1437221af7f8SLinus Torvalds return retval;
1438221af7f8SLinus Torvalds }
14392388777aSEric W. Biederman EXPORT_SYMBOL(begin_new_exec);
1440221af7f8SLinus Torvalds
would_dump(struct linux_binprm * bprm,struct file * file)14411b5d783cSAl Viro void would_dump(struct linux_binprm *bprm, struct file *file)
14421b5d783cSAl Viro {
1443f84df2a6SEric W. Biederman struct inode *inode = file_inode(file);
14444609e1f1SChristian Brauner struct mnt_idmap *idmap = file_mnt_idmap(file);
14454609e1f1SChristian Brauner if (inode_permission(idmap, inode, MAY_READ) < 0) {
1446f84df2a6SEric W. Biederman struct user_namespace *old, *user_ns;
14471b5d783cSAl Viro bprm->interp_flags |= BINPRM_FLAGS_ENFORCE_NONDUMP;
1448f84df2a6SEric W. Biederman
1449f84df2a6SEric W. Biederman /* Ensure mm->user_ns contains the executable */
1450f84df2a6SEric W. Biederman user_ns = old = bprm->mm->user_ns;
1451f84df2a6SEric W. Biederman while ((user_ns != &init_user_ns) &&
14529452e93eSChristian Brauner !privileged_wrt_inode_uidgid(user_ns, idmap, inode))
1453f84df2a6SEric W. Biederman user_ns = user_ns->parent;
1454f84df2a6SEric W. Biederman
1455f84df2a6SEric W. Biederman if (old != user_ns) {
1456f84df2a6SEric W. Biederman bprm->mm->user_ns = get_user_ns(user_ns);
1457f84df2a6SEric W. Biederman put_user_ns(old);
1458f84df2a6SEric W. Biederman }
1459f84df2a6SEric W. Biederman }
14601b5d783cSAl Viro }
14611b5d783cSAl Viro EXPORT_SYMBOL(would_dump);
14621b5d783cSAl Viro
setup_new_exec(struct linux_binprm * bprm)1463221af7f8SLinus Torvalds void setup_new_exec(struct linux_binprm * bprm)
1464221af7f8SLinus Torvalds {
1465df9e4d2cSEric W. Biederman /* Setup things that can depend upon the personality */
14667d503febSEric W. Biederman struct task_struct *me = current;
146746d98eb4SKees Cook
14687d503febSEric W. Biederman arch_pick_mmap_layout(me->mm, &bprm->rlim_stack);
1469d6e71144SAlan Cox
1470e9ea1e7fSKyle Huey arch_setup_new_exec();
14711da177e4SLinus Torvalds
14720551fbd2SBenjamin Herrenschmidt /* Set the new mm task size. We have to do that late because it may
14730551fbd2SBenjamin Herrenschmidt * depend on TIF_32BIT which is only updated in flush_thread() on
14740551fbd2SBenjamin Herrenschmidt * some architectures like powerpc
14750551fbd2SBenjamin Herrenschmidt */
14767d503febSEric W. Biederman me->mm->task_size = TASK_SIZE;
1477f7cfd871SEric W. Biederman up_write(&me->signal->exec_update_lock);
14787d503febSEric W. Biederman mutex_unlock(&me->signal->cred_guard_mutex);
14791da177e4SLinus Torvalds }
1480221af7f8SLinus Torvalds EXPORT_SYMBOL(setup_new_exec);
14811da177e4SLinus Torvalds
1482b8383831SKees Cook /* Runs immediately before start_thread() takes over. */
finalize_exec(struct linux_binprm * bprm)1483b8383831SKees Cook void finalize_exec(struct linux_binprm *bprm)
1484b8383831SKees Cook {
1485c31dbb14SKees Cook /* Store any stack rlimit changes before starting thread. */
1486c31dbb14SKees Cook task_lock(current->group_leader);
1487c31dbb14SKees Cook current->signal->rlim[RLIMIT_STACK] = bprm->rlim_stack;
1488c31dbb14SKees Cook task_unlock(current->group_leader);
1489b8383831SKees Cook }
1490b8383831SKees Cook EXPORT_SYMBOL(finalize_exec);
1491b8383831SKees Cook
14921da177e4SLinus Torvalds /*
1493a2a8474cSOleg Nesterov * Prepare credentials and lock ->cred_guard_mutex.
149496ecee29SEric W. Biederman * setup_new_exec() commits the new creds and drops the lock.
14953d742d4bSRandy Dunlap * Or, if exec fails before, free_bprm() should release ->cred
1496a2a8474cSOleg Nesterov * and unlock.
1497a2a8474cSOleg Nesterov */
prepare_bprm_creds(struct linux_binprm * bprm)14984addd264SChanho Min static int prepare_bprm_creds(struct linux_binprm *bprm)
1499a2a8474cSOleg Nesterov {
15009b1bf12dSKOSAKI Motohiro if (mutex_lock_interruptible(¤t->signal->cred_guard_mutex))
1501a2a8474cSOleg Nesterov return -ERESTARTNOINTR;
1502a2a8474cSOleg Nesterov
1503a2a8474cSOleg Nesterov bprm->cred = prepare_exec_creds();
1504a2a8474cSOleg Nesterov if (likely(bprm->cred))
1505a2a8474cSOleg Nesterov return 0;
1506a2a8474cSOleg Nesterov
15079b1bf12dSKOSAKI Motohiro mutex_unlock(¤t->signal->cred_guard_mutex);
1508a2a8474cSOleg Nesterov return -ENOMEM;
1509a2a8474cSOleg Nesterov }
1510a2a8474cSOleg Nesterov
free_bprm(struct linux_binprm * bprm)1511c4ad8f98SLinus Torvalds static void free_bprm(struct linux_binprm *bprm)
1512a2a8474cSOleg Nesterov {
1513f18ac551SEric W. Biederman if (bprm->mm) {
1514f18ac551SEric W. Biederman acct_arg_size(bprm, 0);
1515f18ac551SEric W. Biederman mmput(bprm->mm);
1516f18ac551SEric W. Biederman }
1517a2a8474cSOleg Nesterov free_arg_pages(bprm);
1518a2a8474cSOleg Nesterov if (bprm->cred) {
15199b1bf12dSKOSAKI Motohiro mutex_unlock(¤t->signal->cred_guard_mutex);
1520a2a8474cSOleg Nesterov abort_creds(bprm->cred);
1521a2a8474cSOleg Nesterov }
152263e46b95SOleg Nesterov if (bprm->file) {
152363e46b95SOleg Nesterov allow_write_access(bprm->file);
152463e46b95SOleg Nesterov fput(bprm->file);
152563e46b95SOleg Nesterov }
1526b8a61c9eSEric W. Biederman if (bprm->executable)
1527b8a61c9eSEric W. Biederman fput(bprm->executable);
1528b66c5984SKees Cook /* If a binfmt changed the interp, free it. */
1529b66c5984SKees Cook if (bprm->interp != bprm->filename)
1530b66c5984SKees Cook kfree(bprm->interp);
153160d9ad1dSEric W. Biederman kfree(bprm->fdpath);
1532a2a8474cSOleg Nesterov kfree(bprm);
1533a2a8474cSOleg Nesterov }
1534a2a8474cSOleg Nesterov
alloc_bprm(int fd,struct filename * filename)153560d9ad1dSEric W. Biederman static struct linux_binprm *alloc_bprm(int fd, struct filename *filename)
15360a8f36ebSEric W. Biederman {
15370a8f36ebSEric W. Biederman struct linux_binprm *bprm = kzalloc(sizeof(*bprm), GFP_KERNEL);
153860d9ad1dSEric W. Biederman int retval = -ENOMEM;
15390a8f36ebSEric W. Biederman if (!bprm)
154060d9ad1dSEric W. Biederman goto out;
154160d9ad1dSEric W. Biederman
154260d9ad1dSEric W. Biederman if (fd == AT_FDCWD || filename->name[0] == '/') {
154360d9ad1dSEric W. Biederman bprm->filename = filename->name;
154460d9ad1dSEric W. Biederman } else {
1545*dc5da273SKees Cook if (filename->name[0] == '\0') {
154660d9ad1dSEric W. Biederman bprm->fdpath = kasprintf(GFP_KERNEL, "/dev/fd/%d", fd);
1547*dc5da273SKees Cook bprm->comm_from_dentry = 1;
1548*dc5da273SKees Cook } else {
154960d9ad1dSEric W. Biederman bprm->fdpath = kasprintf(GFP_KERNEL, "/dev/fd/%d/%s",
155060d9ad1dSEric W. Biederman fd, filename->name);
1551*dc5da273SKees Cook }
155260d9ad1dSEric W. Biederman if (!bprm->fdpath)
155360d9ad1dSEric W. Biederman goto out_free;
155460d9ad1dSEric W. Biederman
155560d9ad1dSEric W. Biederman bprm->filename = bprm->fdpath;
155660d9ad1dSEric W. Biederman }
155760d9ad1dSEric W. Biederman bprm->interp = bprm->filename;
1558f18ac551SEric W. Biederman
1559f18ac551SEric W. Biederman retval = bprm_mm_init(bprm);
1560f18ac551SEric W. Biederman if (retval)
1561f18ac551SEric W. Biederman goto out_free;
15620a8f36ebSEric W. Biederman return bprm;
156360d9ad1dSEric W. Biederman
156460d9ad1dSEric W. Biederman out_free:
156560d9ad1dSEric W. Biederman free_bprm(bprm);
156660d9ad1dSEric W. Biederman out:
156760d9ad1dSEric W. Biederman return ERR_PTR(retval);
15680a8f36ebSEric W. Biederman }
15690a8f36ebSEric W. Biederman
bprm_change_interp(const char * interp,struct linux_binprm * bprm)1570c2315c18SOleg Nesterov int bprm_change_interp(const char *interp, struct linux_binprm *bprm)
1571b66c5984SKees Cook {
1572b66c5984SKees Cook /* If a binfmt changed the interp, free it first. */
1573b66c5984SKees Cook if (bprm->interp != bprm->filename)
1574b66c5984SKees Cook kfree(bprm->interp);
1575b66c5984SKees Cook bprm->interp = kstrdup(interp, GFP_KERNEL);
1576b66c5984SKees Cook if (!bprm->interp)
1577b66c5984SKees Cook return -ENOMEM;
1578b66c5984SKees Cook return 0;
1579b66c5984SKees Cook }
1580b66c5984SKees Cook EXPORT_SYMBOL(bprm_change_interp);
1581b66c5984SKees Cook
1582a2a8474cSOleg Nesterov /*
1583a6f76f23SDavid Howells * determine how safe it is to execute the proposed program
15849b1bf12dSKOSAKI Motohiro * - the caller must hold ->cred_guard_mutex to protect against
1585c2e1f2e3SKees Cook * PTRACE_ATTACH or seccomp thread-sync
1586a6f76f23SDavid Howells */
check_unsafe_exec(struct linux_binprm * bprm)15879e00cdb0SOleg Nesterov static void check_unsafe_exec(struct linux_binprm *bprm)
1588a6f76f23SDavid Howells {
15890bf2f3aeSDavid Howells struct task_struct *p = current, *t;
1590f1191b50SAl Viro unsigned n_fs;
1591a6f76f23SDavid Howells
15929227dd2aSEric W. Biederman if (p->ptrace)
15934b9d33e6STejun Heo bprm->unsafe |= LSM_UNSAFE_PTRACE;
1594a6f76f23SDavid Howells
1595259e5e6cSAndy Lutomirski /*
1596259e5e6cSAndy Lutomirski * This isn't strictly necessary, but it makes it harder for LSMs to
1597259e5e6cSAndy Lutomirski * mess up.
1598259e5e6cSAndy Lutomirski */
15991d4457f9SKees Cook if (task_no_new_privs(current))
1600259e5e6cSAndy Lutomirski bprm->unsafe |= LSM_UNSAFE_NO_NEW_PRIVS;
1601259e5e6cSAndy Lutomirski
1602275498a9SKees Cook /*
1603275498a9SKees Cook * If another task is sharing our fs, we cannot safely
1604275498a9SKees Cook * suid exec because the differently privileged task
1605275498a9SKees Cook * will be able to manipulate the current directory, etc.
1606275498a9SKees Cook * It would be nice to force an unshare instead...
1607275498a9SKees Cook */
160883f62a2eSOleg Nesterov t = p;
16090bf2f3aeSDavid Howells n_fs = 1;
16102a4419b5SNick Piggin spin_lock(&p->fs->lock);
1611437f7fdbSOleg Nesterov rcu_read_lock();
161283f62a2eSOleg Nesterov while_each_thread(p, t) {
16130bf2f3aeSDavid Howells if (t->fs == p->fs)
16140bf2f3aeSDavid Howells n_fs++;
16150bf2f3aeSDavid Howells }
1616437f7fdbSOleg Nesterov rcu_read_unlock();
16170bf2f3aeSDavid Howells
16189e00cdb0SOleg Nesterov if (p->fs->users > n_fs)
1619a6f76f23SDavid Howells bprm->unsafe |= LSM_UNSAFE_SHARE;
16209e00cdb0SOleg Nesterov else
1621498052bbSAl Viro p->fs->in_exec = 1;
16222a4419b5SNick Piggin spin_unlock(&p->fs->lock);
1623a6f76f23SDavid Howells }
1624a6f76f23SDavid Howells
bprm_fill_uid(struct linux_binprm * bprm,struct file * file)162556305aa9SEric W. Biederman static void bprm_fill_uid(struct linux_binprm *bprm, struct file *file)
16268b01fc86SJann Horn {
162756305aa9SEric W. Biederman /* Handle suid and sgid on files */
1628e67fe633SChristian Brauner struct mnt_idmap *idmap;
1629e6ae4381SAl Viro struct inode *inode = file_inode(file);
16308b01fc86SJann Horn unsigned int mode;
1631a2bd096fSChristian Brauner vfsuid_t vfsuid;
1632a2bd096fSChristian Brauner vfsgid_t vfsgid;
1633d2a2a471SKees Cook int err;
16348b01fc86SJann Horn
163556305aa9SEric W. Biederman if (!mnt_may_suid(file->f_path.mnt))
16368b01fc86SJann Horn return;
16378b01fc86SJann Horn
16388b01fc86SJann Horn if (task_no_new_privs(current))
16398b01fc86SJann Horn return;
16408b01fc86SJann Horn
16418b01fc86SJann Horn mode = READ_ONCE(inode->i_mode);
16428b01fc86SJann Horn if (!(mode & (S_ISUID|S_ISGID)))
16438b01fc86SJann Horn return;
16448b01fc86SJann Horn
1645e67fe633SChristian Brauner idmap = file_mnt_idmap(file);
16461ab29965SChristian Brauner
16478b01fc86SJann Horn /* Be careful if suid/sgid is set */
16485955102cSAl Viro inode_lock(inode);
16498b01fc86SJann Horn
1650d2a2a471SKees Cook /* Atomically reload and check mode/uid/gid now that lock held. */
16518b01fc86SJann Horn mode = inode->i_mode;
1652e67fe633SChristian Brauner vfsuid = i_uid_into_vfsuid(idmap, inode);
1653e67fe633SChristian Brauner vfsgid = i_gid_into_vfsgid(idmap, inode);
1654d2a2a471SKees Cook err = inode_permission(idmap, inode, MAY_EXEC);
16555955102cSAl Viro inode_unlock(inode);
16568b01fc86SJann Horn
1657d2a2a471SKees Cook /* Did the exec bit vanish out from under us? Give up. */
1658d2a2a471SKees Cook if (err)
1659d2a2a471SKees Cook return;
1660d2a2a471SKees Cook
16618b01fc86SJann Horn /* We ignore suid/sgid if there are no mappings for them in the ns */
1662a2bd096fSChristian Brauner if (!vfsuid_has_mapping(bprm->cred->user_ns, vfsuid) ||
1663a2bd096fSChristian Brauner !vfsgid_has_mapping(bprm->cred->user_ns, vfsgid))
16648b01fc86SJann Horn return;
16658b01fc86SJann Horn
16668b01fc86SJann Horn if (mode & S_ISUID) {
16678b01fc86SJann Horn bprm->per_clear |= PER_CLEAR_ON_SETID;
1668a2bd096fSChristian Brauner bprm->cred->euid = vfsuid_into_kuid(vfsuid);
16698b01fc86SJann Horn }
16708b01fc86SJann Horn
16718b01fc86SJann Horn if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
16728b01fc86SJann Horn bprm->per_clear |= PER_CLEAR_ON_SETID;
1673a2bd096fSChristian Brauner bprm->cred->egid = vfsgid_into_kgid(vfsgid);
16748b01fc86SJann Horn }
16758b01fc86SJann Horn }
16768b01fc86SJann Horn
1677a6f76f23SDavid Howells /*
167856305aa9SEric W. Biederman * Compute brpm->cred based upon the final binary.
167956305aa9SEric W. Biederman */
bprm_creds_from_file(struct linux_binprm * bprm)168056305aa9SEric W. Biederman static int bprm_creds_from_file(struct linux_binprm *bprm)
168156305aa9SEric W. Biederman {
168256305aa9SEric W. Biederman /* Compute creds based on which file? */
168356305aa9SEric W. Biederman struct file *file = bprm->execfd_creds ? bprm->executable : bprm->file;
168456305aa9SEric W. Biederman
168556305aa9SEric W. Biederman bprm_fill_uid(bprm, file);
168656305aa9SEric W. Biederman return security_bprm_creds_from_file(bprm, file);
168756305aa9SEric W. Biederman }
168856305aa9SEric W. Biederman
168956305aa9SEric W. Biederman /*
16901da177e4SLinus Torvalds * Fill the binprm structure from the inode.
169156305aa9SEric W. Biederman * Read the first BINPRM_BUF_SIZE bytes
1692a6f76f23SDavid Howells *
1693a6f76f23SDavid Howells * This may be called multiple times for binary chains (scripts for example).
16941da177e4SLinus Torvalds */
prepare_binprm(struct linux_binprm * bprm)16958b72ca90SEric W. Biederman static int prepare_binprm(struct linux_binprm *bprm)
16961da177e4SLinus Torvalds {
1697bdd1d2d3SChristoph Hellwig loff_t pos = 0;
16981da177e4SLinus Torvalds
16991da177e4SLinus Torvalds memset(bprm->buf, 0, BINPRM_BUF_SIZE);
1700bdd1d2d3SChristoph Hellwig return kernel_read(bprm->file, bprm->buf, BINPRM_BUF_SIZE, &pos);
17011da177e4SLinus Torvalds }
17021da177e4SLinus Torvalds
17034fc75ff4SNick Piggin /*
17044fc75ff4SNick Piggin * Arguments are '\0' separated strings found at the location bprm->p
17054fc75ff4SNick Piggin * points to; chop off the first by relocating brpm->p to right after
17064fc75ff4SNick Piggin * the first '\0' encountered.
17074fc75ff4SNick Piggin */
remove_arg_zero(struct linux_binprm * bprm)1708b6a2fea3SOllie Wild int remove_arg_zero(struct linux_binprm *bprm)
17091da177e4SLinus Torvalds {
1710b6a2fea3SOllie Wild int ret = 0;
17111da177e4SLinus Torvalds unsigned long offset;
17121da177e4SLinus Torvalds char *kaddr;
17131da177e4SLinus Torvalds struct page *page;
17141da177e4SLinus Torvalds
1715b6a2fea3SOllie Wild if (!bprm->argc)
1716b6a2fea3SOllie Wild return 0;
17171da177e4SLinus Torvalds
1718b6a2fea3SOllie Wild do {
1719b6a2fea3SOllie Wild offset = bprm->p & ~PAGE_MASK;
1720b6a2fea3SOllie Wild page = get_arg_page(bprm, bprm->p, 0);
1721b6a2fea3SOllie Wild if (!page) {
1722b6a2fea3SOllie Wild ret = -EFAULT;
1723b6a2fea3SOllie Wild goto out;
1724b6a2fea3SOllie Wild }
17253a608cfeSFabio M. De Francesco kaddr = kmap_local_page(page);
17264fc75ff4SNick Piggin
1727b6a2fea3SOllie Wild for (; offset < PAGE_SIZE && kaddr[offset];
1728b6a2fea3SOllie Wild offset++, bprm->p++)
1729b6a2fea3SOllie Wild ;
17304fc75ff4SNick Piggin
17313a608cfeSFabio M. De Francesco kunmap_local(kaddr);
1732b6a2fea3SOllie Wild put_arg_page(page);
1733b6a2fea3SOllie Wild } while (offset == PAGE_SIZE);
17344fc75ff4SNick Piggin
1735b6a2fea3SOllie Wild bprm->p++;
17361da177e4SLinus Torvalds bprm->argc--;
1737b6a2fea3SOllie Wild ret = 0;
1738b6a2fea3SOllie Wild
1739b6a2fea3SOllie Wild out:
1740b6a2fea3SOllie Wild return ret;
17411da177e4SLinus Torvalds }
17421da177e4SLinus Torvalds EXPORT_SYMBOL(remove_arg_zero);
17431da177e4SLinus Torvalds
1744cb7b6b1cSOleg Nesterov #define printable(c) (((c)=='\t') || ((c)=='\n') || (0x20<=(c) && (c)<=0x7e))
17451da177e4SLinus Torvalds /*
17461da177e4SLinus Torvalds * cycle the list of binary formats handler, until one recognizes the image
17471da177e4SLinus Torvalds */
search_binary_handler(struct linux_binprm * bprm)1748bc2bf338SEric W. Biederman static int search_binary_handler(struct linux_binprm *bprm)
17491da177e4SLinus Torvalds {
1750cb7b6b1cSOleg Nesterov bool need_retry = IS_ENABLED(CONFIG_MODULES);
17511da177e4SLinus Torvalds struct linux_binfmt *fmt;
1752cb7b6b1cSOleg Nesterov int retval;
17531da177e4SLinus Torvalds
17548b72ca90SEric W. Biederman retval = prepare_binprm(bprm);
17558b72ca90SEric W. Biederman if (retval < 0)
17568b72ca90SEric W. Biederman return retval;
1757d7402698SKees Cook
17581da177e4SLinus Torvalds retval = security_bprm_check(bprm);
17591da177e4SLinus Torvalds if (retval)
17601da177e4SLinus Torvalds return retval;
17611da177e4SLinus Torvalds
17621da177e4SLinus Torvalds retval = -ENOENT;
1763cb7b6b1cSOleg Nesterov retry:
17641da177e4SLinus Torvalds read_lock(&binfmt_lock);
1765e4dc1b14SAlexey Dobriyan list_for_each_entry(fmt, &formats, lh) {
17661da177e4SLinus Torvalds if (!try_module_get(fmt->module))
17671da177e4SLinus Torvalds continue;
17681da177e4SLinus Torvalds read_unlock(&binfmt_lock);
1769d53ddd01SAlexey Dobriyan
177092eaa565SOleg Nesterov retval = fmt->load_binary(bprm);
1771d53ddd01SAlexey Dobriyan
17721da177e4SLinus Torvalds read_lock(&binfmt_lock);
17731da177e4SLinus Torvalds put_binfmt(fmt);
1774bc2bf338SEric W. Biederman if (bprm->point_of_no_return || (retval != -ENOEXEC)) {
177519d860a1SAl Viro read_unlock(&binfmt_lock);
177619d860a1SAl Viro return retval;
177719d860a1SAl Viro }
17781da177e4SLinus Torvalds }
17791da177e4SLinus Torvalds read_unlock(&binfmt_lock);
1780cb7b6b1cSOleg Nesterov
178119d860a1SAl Viro if (need_retry) {
1782cb7b6b1cSOleg Nesterov if (printable(bprm->buf[0]) && printable(bprm->buf[1]) &&
1783cb7b6b1cSOleg Nesterov printable(bprm->buf[2]) && printable(bprm->buf[3]))
1784cb7b6b1cSOleg Nesterov return retval;
17854e0621a0SOleg Nesterov if (request_module("binfmt-%04x", *(ushort *)(bprm->buf + 2)) < 0)
17864e0621a0SOleg Nesterov return retval;
1787cb7b6b1cSOleg Nesterov need_retry = false;
1788cb7b6b1cSOleg Nesterov goto retry;
17891da177e4SLinus Torvalds }
1790cb7b6b1cSOleg Nesterov
17911da177e4SLinus Torvalds return retval;
17921da177e4SLinus Torvalds }
17931da177e4SLinus Torvalds
1794275498a9SKees Cook /* binfmt handlers will call back into begin_new_exec() on success. */
exec_binprm(struct linux_binprm * bprm)17955d1baf3bSOleg Nesterov static int exec_binprm(struct linux_binprm *bprm)
17965d1baf3bSOleg Nesterov {
17975d1baf3bSOleg Nesterov pid_t old_pid, old_vpid;
1798bc2bf338SEric W. Biederman int ret, depth;
17995d1baf3bSOleg Nesterov
18005d1baf3bSOleg Nesterov /* Need to fetch pid before load_binary changes it */
18015d1baf3bSOleg Nesterov old_pid = current->pid;
18025d1baf3bSOleg Nesterov rcu_read_lock();
18035d1baf3bSOleg Nesterov old_vpid = task_pid_nr_ns(current, task_active_pid_ns(current->parent));
18045d1baf3bSOleg Nesterov rcu_read_unlock();
18055d1baf3bSOleg Nesterov
1806bc2bf338SEric W. Biederman /* This allows 4 levels of binfmt rewrites before failing hard. */
1807bc2bf338SEric W. Biederman for (depth = 0;; depth++) {
1808bc2bf338SEric W. Biederman struct file *exec;
1809bc2bf338SEric W. Biederman if (depth > 5)
1810bc2bf338SEric W. Biederman return -ELOOP;
1811bc2bf338SEric W. Biederman
18125d1baf3bSOleg Nesterov ret = search_binary_handler(bprm);
1813bc2bf338SEric W. Biederman if (ret < 0)
1814bc2bf338SEric W. Biederman return ret;
1815bc2bf338SEric W. Biederman if (!bprm->interpreter)
1816bc2bf338SEric W. Biederman break;
1817bc2bf338SEric W. Biederman
1818bc2bf338SEric W. Biederman exec = bprm->file;
1819bc2bf338SEric W. Biederman bprm->file = bprm->interpreter;
1820bc2bf338SEric W. Biederman bprm->interpreter = NULL;
1821bc2bf338SEric W. Biederman
1822bc2bf338SEric W. Biederman allow_write_access(exec);
1823bc2bf338SEric W. Biederman if (unlikely(bprm->have_execfd)) {
1824bc2bf338SEric W. Biederman if (bprm->executable) {
1825bc2bf338SEric W. Biederman fput(exec);
1826bc2bf338SEric W. Biederman return -ENOEXEC;
1827bc2bf338SEric W. Biederman }
1828bc2bf338SEric W. Biederman bprm->executable = exec;
1829bc2bf338SEric W. Biederman } else
1830bc2bf338SEric W. Biederman fput(exec);
1831bc2bf338SEric W. Biederman }
1832bc2bf338SEric W. Biederman
18339410d228SRichard Guy Briggs audit_bprm(bprm);
18345d1baf3bSOleg Nesterov trace_sched_process_exec(current, old_pid, bprm);
18355d1baf3bSOleg Nesterov ptrace_event(PTRACE_EVENT_EXEC, old_vpid);
18369beb266fSOleg Nesterov proc_exec_connector(current);
1837bc2bf338SEric W. Biederman return 0;
18385d1baf3bSOleg Nesterov }
18395d1baf3bSOleg Nesterov
18401da177e4SLinus Torvalds /*
18411da177e4SLinus Torvalds * sys_execve() executes a new program.
18421da177e4SLinus Torvalds */
bprm_execve(struct linux_binprm * bprm,int fd,struct filename * filename,int flags)18430c9cdff0SEric W. Biederman static int bprm_execve(struct linux_binprm *bprm,
18440c9cdff0SEric W. Biederman int fd, struct filename *filename, int flags)
18450c9cdff0SEric W. Biederman {
18460c9cdff0SEric W. Biederman struct file *file;
18470c9cdff0SEric W. Biederman int retval;
18480c9cdff0SEric W. Biederman
18490c9cdff0SEric W. Biederman retval = prepare_bprm_creds(bprm);
18500c9cdff0SEric W. Biederman if (retval)
1851b6043501SEric W. Biederman return retval;
18520c9cdff0SEric W. Biederman
1853275498a9SKees Cook /*
1854275498a9SKees Cook * Check for unsafe execution states before exec_binprm(), which
1855275498a9SKees Cook * will call back into begin_new_exec(), into bprm_creds_from_file(),
1856275498a9SKees Cook * where setuid-ness is evaluated.
1857275498a9SKees Cook */
18580c9cdff0SEric W. Biederman check_unsafe_exec(bprm);
18590c9cdff0SEric W. Biederman current->in_execve = 1;
1860af7f588dSMathieu Desnoyers sched_mm_cid_before_execve(current);
18610c9cdff0SEric W. Biederman
18620c9cdff0SEric W. Biederman file = do_open_execat(fd, filename, flags);
18630c9cdff0SEric W. Biederman retval = PTR_ERR(file);
18640c9cdff0SEric W. Biederman if (IS_ERR(file))
18650c9cdff0SEric W. Biederman goto out_unmark;
18660c9cdff0SEric W. Biederman
18670c9cdff0SEric W. Biederman sched_exec();
18680c9cdff0SEric W. Biederman
18690c9cdff0SEric W. Biederman bprm->file = file;
18700c9cdff0SEric W. Biederman /*
18710c9cdff0SEric W. Biederman * Record that a name derived from an O_CLOEXEC fd will be
1872b6043501SEric W. Biederman * inaccessible after exec. This allows the code in exec to
1873b6043501SEric W. Biederman * choose to fail when the executable is not mmaped into the
1874b6043501SEric W. Biederman * interpreter and an open file descriptor is not passed to
1875b6043501SEric W. Biederman * the interpreter. This makes for a better user experience
1876b6043501SEric W. Biederman * than having the interpreter start and then immediately fail
1877b6043501SEric W. Biederman * when it finds the executable is inaccessible.
18780c9cdff0SEric W. Biederman */
1879878f12dbSEric W. Biederman if (bprm->fdpath && get_close_on_exec(fd))
18800c9cdff0SEric W. Biederman bprm->interp_flags |= BINPRM_FLAGS_PATH_INACCESSIBLE;
18810c9cdff0SEric W. Biederman
18820c9cdff0SEric W. Biederman /* Set the unchanging part of bprm->cred */
18830c9cdff0SEric W. Biederman retval = security_bprm_creds_for_exec(bprm);
18840c9cdff0SEric W. Biederman if (retval)
18850c9cdff0SEric W. Biederman goto out;
18860c9cdff0SEric W. Biederman
18870c9cdff0SEric W. Biederman retval = exec_binprm(bprm);
18880c9cdff0SEric W. Biederman if (retval < 0)
18890c9cdff0SEric W. Biederman goto out;
18900c9cdff0SEric W. Biederman
1891af7f588dSMathieu Desnoyers sched_mm_cid_after_execve(current);
18920c9cdff0SEric W. Biederman /* execve succeeded */
18930c9cdff0SEric W. Biederman current->fs->in_exec = 0;
18940c9cdff0SEric W. Biederman current->in_execve = 0;
18950c9cdff0SEric W. Biederman rseq_execve(current);
1896fd593511SBeau Belgrave user_events_execve(current);
18970c9cdff0SEric W. Biederman acct_update_integrals(current);
18980c9cdff0SEric W. Biederman task_numa_free(current, false);
18990c9cdff0SEric W. Biederman return retval;
19000c9cdff0SEric W. Biederman
19010c9cdff0SEric W. Biederman out:
19020c9cdff0SEric W. Biederman /*
19033d742d4bSRandy Dunlap * If past the point of no return ensure the code never
19040c9cdff0SEric W. Biederman * returns to the userspace process. Use an existing fatal
19050c9cdff0SEric W. Biederman * signal if present otherwise terminate the process with
19060c9cdff0SEric W. Biederman * SIGSEGV.
19070c9cdff0SEric W. Biederman */
19080c9cdff0SEric W. Biederman if (bprm->point_of_no_return && !fatal_signal_pending(current))
1909e21294a7SEric W. Biederman force_fatal_sig(SIGSEGV);
19100c9cdff0SEric W. Biederman
19110c9cdff0SEric W. Biederman out_unmark:
1912af7f588dSMathieu Desnoyers sched_mm_cid_after_execve(current);
19130c9cdff0SEric W. Biederman current->fs->in_exec = 0;
19140c9cdff0SEric W. Biederman current->in_execve = 0;
19150c9cdff0SEric W. Biederman
19160c9cdff0SEric W. Biederman return retval;
19170c9cdff0SEric W. Biederman }
19180c9cdff0SEric W. Biederman
do_execveat_common(int fd,struct filename * filename,struct user_arg_ptr argv,struct user_arg_ptr envp,int flags)191925cf336dSEric W. Biederman static int do_execveat_common(int fd, struct filename *filename,
1920ba2d0162SOleg Nesterov struct user_arg_ptr argv,
192151f39a1fSDavid Drysdale struct user_arg_ptr envp,
192225cf336dSEric W. Biederman int flags)
19231da177e4SLinus Torvalds {
19241da177e4SLinus Torvalds struct linux_binprm *bprm;
19251da177e4SLinus Torvalds int retval;
192672fa5997SVasiliy Kulikov
1927c4ad8f98SLinus Torvalds if (IS_ERR(filename))
1928c4ad8f98SLinus Torvalds return PTR_ERR(filename);
1929c4ad8f98SLinus Torvalds
193072fa5997SVasiliy Kulikov /*
193172fa5997SVasiliy Kulikov * We move the actual failure in case of RLIMIT_NPROC excess from
193272fa5997SVasiliy Kulikov * set*uid() to execve() because too many poorly written programs
193372fa5997SVasiliy Kulikov * don't check setuid() return code. Here we additionally recheck
193472fa5997SVasiliy Kulikov * whether NPROC limit is still exceeded.
193572fa5997SVasiliy Kulikov */
193672fa5997SVasiliy Kulikov if ((current->flags & PF_NPROC_EXCEEDED) &&
1937de399236SAlexey Gladkov is_rlimit_overlimit(current_ucounts(), UCOUNT_RLIMIT_NPROC, rlimit(RLIMIT_NPROC))) {
193872fa5997SVasiliy Kulikov retval = -EAGAIN;
193972fa5997SVasiliy Kulikov goto out_ret;
194072fa5997SVasiliy Kulikov }
194172fa5997SVasiliy Kulikov
194272fa5997SVasiliy Kulikov /* We're below the limit (still or again), so we don't want to make
194372fa5997SVasiliy Kulikov * further execve() calls fail. */
194472fa5997SVasiliy Kulikov current->flags &= ~PF_NPROC_EXCEEDED;
19451da177e4SLinus Torvalds
194660d9ad1dSEric W. Biederman bprm = alloc_bprm(fd, filename);
19470a8f36ebSEric W. Biederman if (IS_ERR(bprm)) {
19480a8f36ebSEric W. Biederman retval = PTR_ERR(bprm);
19490a8f36ebSEric W. Biederman goto out_ret;
19500a8f36ebSEric W. Biederman }
19510a8f36ebSEric W. Biederman
1952d8b9cd54SEric W. Biederman retval = count(argv, MAX_ARG_STRINGS);
1953dcd46d89SKees Cook if (retval == 0)
1954dcd46d89SKees Cook pr_warn_once("process '%s' launched '%s' with NULL argv: empty string added\n",
1955dcd46d89SKees Cook current->comm, bprm->filename);
1956d8b9cd54SEric W. Biederman if (retval < 0)
1957d8b9cd54SEric W. Biederman goto out_free;
1958d8b9cd54SEric W. Biederman bprm->argc = retval;
1959d8b9cd54SEric W. Biederman
1960d8b9cd54SEric W. Biederman retval = count(envp, MAX_ARG_STRINGS);
1961d8b9cd54SEric W. Biederman if (retval < 0)
1962d8b9cd54SEric W. Biederman goto out_free;
1963d8b9cd54SEric W. Biederman bprm->envc = retval;
1964d8b9cd54SEric W. Biederman
1965d8b9cd54SEric W. Biederman retval = bprm_stack_limits(bprm);
1966655c16a8SOleg Nesterov if (retval < 0)
19670c9cdff0SEric W. Biederman goto out_free;
19681da177e4SLinus Torvalds
1969986db2d1SChristoph Hellwig retval = copy_string_kernel(bprm->filename, bprm);
19701da177e4SLinus Torvalds if (retval < 0)
19710c9cdff0SEric W. Biederman goto out_free;
19721da177e4SLinus Torvalds bprm->exec = bprm->p;
19730c9cdff0SEric W. Biederman
19741da177e4SLinus Torvalds retval = copy_strings(bprm->envc, envp, bprm);
19751da177e4SLinus Torvalds if (retval < 0)
19760c9cdff0SEric W. Biederman goto out_free;
19771da177e4SLinus Torvalds
19781da177e4SLinus Torvalds retval = copy_strings(bprm->argc, argv, bprm);
19791da177e4SLinus Torvalds if (retval < 0)
19800c9cdff0SEric W. Biederman goto out_free;
19811da177e4SLinus Torvalds
1982dcd46d89SKees Cook /*
1983dcd46d89SKees Cook * When argv is empty, add an empty string ("") as argv[0] to
1984dcd46d89SKees Cook * ensure confused userspace programs that start processing
1985dcd46d89SKees Cook * from argv[1] won't end up walking envp. See also
1986dcd46d89SKees Cook * bprm_stack_limits().
1987dcd46d89SKees Cook */
1988dcd46d89SKees Cook if (bprm->argc == 0) {
1989dcd46d89SKees Cook retval = copy_string_kernel("", bprm);
1990dcd46d89SKees Cook if (retval < 0)
1991dcd46d89SKees Cook goto out_free;
1992dcd46d89SKees Cook bprm->argc = 1;
1993dcd46d89SKees Cook }
1994dcd46d89SKees Cook
19950c9cdff0SEric W. Biederman retval = bprm_execve(bprm, fd, filename, flags);
1996a6f76f23SDavid Howells out_free:
199708a6fac1SAl Viro free_bprm(bprm);
19981da177e4SLinus Torvalds
19991da177e4SLinus Torvalds out_ret:
2000c4ad8f98SLinus Torvalds putname(filename);
20011da177e4SLinus Torvalds return retval;
20021da177e4SLinus Torvalds }
20031da177e4SLinus Torvalds
kernel_execve(const char * kernel_filename,const char * const * argv,const char * const * envp)2004be619f7fSEric W. Biederman int kernel_execve(const char *kernel_filename,
2005be619f7fSEric W. Biederman const char *const *argv, const char *const *envp)
2006be619f7fSEric W. Biederman {
2007be619f7fSEric W. Biederman struct filename *filename;
2008be619f7fSEric W. Biederman struct linux_binprm *bprm;
2009be619f7fSEric W. Biederman int fd = AT_FDCWD;
2010be619f7fSEric W. Biederman int retval;
2011be619f7fSEric W. Biederman
20121b2552cbSEric W. Biederman /* It is non-sense for kernel threads to call execve */
20131b2552cbSEric W. Biederman if (WARN_ON_ONCE(current->flags & PF_KTHREAD))
2014343f4c49SEric W. Biederman return -EINVAL;
2015343f4c49SEric W. Biederman
2016be619f7fSEric W. Biederman filename = getname_kernel(kernel_filename);
2017be619f7fSEric W. Biederman if (IS_ERR(filename))
2018be619f7fSEric W. Biederman return PTR_ERR(filename);
2019be619f7fSEric W. Biederman
2020be619f7fSEric W. Biederman bprm = alloc_bprm(fd, filename);
2021be619f7fSEric W. Biederman if (IS_ERR(bprm)) {
2022be619f7fSEric W. Biederman retval = PTR_ERR(bprm);
2023be619f7fSEric W. Biederman goto out_ret;
2024be619f7fSEric W. Biederman }
2025be619f7fSEric W. Biederman
2026be619f7fSEric W. Biederman retval = count_strings_kernel(argv);
2027dcd46d89SKees Cook if (WARN_ON_ONCE(retval == 0))
2028dcd46d89SKees Cook retval = -EINVAL;
2029be619f7fSEric W. Biederman if (retval < 0)
2030be619f7fSEric W. Biederman goto out_free;
2031be619f7fSEric W. Biederman bprm->argc = retval;
2032be619f7fSEric W. Biederman
2033be619f7fSEric W. Biederman retval = count_strings_kernel(envp);
2034be619f7fSEric W. Biederman if (retval < 0)
2035be619f7fSEric W. Biederman goto out_free;
2036be619f7fSEric W. Biederman bprm->envc = retval;
2037be619f7fSEric W. Biederman
2038be619f7fSEric W. Biederman retval = bprm_stack_limits(bprm);
2039be619f7fSEric W. Biederman if (retval < 0)
2040be619f7fSEric W. Biederman goto out_free;
2041be619f7fSEric W. Biederman
2042be619f7fSEric W. Biederman retval = copy_string_kernel(bprm->filename, bprm);
2043be619f7fSEric W. Biederman if (retval < 0)
2044be619f7fSEric W. Biederman goto out_free;
2045be619f7fSEric W. Biederman bprm->exec = bprm->p;
2046be619f7fSEric W. Biederman
2047be619f7fSEric W. Biederman retval = copy_strings_kernel(bprm->envc, envp, bprm);
2048be619f7fSEric W. Biederman if (retval < 0)
2049be619f7fSEric W. Biederman goto out_free;
2050be619f7fSEric W. Biederman
2051be619f7fSEric W. Biederman retval = copy_strings_kernel(bprm->argc, argv, bprm);
2052be619f7fSEric W. Biederman if (retval < 0)
2053be619f7fSEric W. Biederman goto out_free;
2054be619f7fSEric W. Biederman
2055be619f7fSEric W. Biederman retval = bprm_execve(bprm, fd, filename, 0);
2056be619f7fSEric W. Biederman out_free:
2057be619f7fSEric W. Biederman free_bprm(bprm);
2058be619f7fSEric W. Biederman out_ret:
2059be619f7fSEric W. Biederman putname(filename);
2060be619f7fSEric W. Biederman return retval;
2061be619f7fSEric W. Biederman }
2062be619f7fSEric W. Biederman
do_execve(struct filename * filename,const char __user * const __user * __argv,const char __user * const __user * __envp)2063be619f7fSEric W. Biederman static int do_execve(struct filename *filename,
2064ba2d0162SOleg Nesterov const char __user *const __user *__argv,
2065da3d4c5fSAl Viro const char __user *const __user *__envp)
2066ba2d0162SOleg Nesterov {
20670e028465SOleg Nesterov struct user_arg_ptr argv = { .ptr.native = __argv };
20680e028465SOleg Nesterov struct user_arg_ptr envp = { .ptr.native = __envp };
206951f39a1fSDavid Drysdale return do_execveat_common(AT_FDCWD, filename, argv, envp, 0);
207051f39a1fSDavid Drysdale }
207151f39a1fSDavid Drysdale
do_execveat(int fd,struct filename * filename,const char __user * const __user * __argv,const char __user * const __user * __envp,int flags)2072be619f7fSEric W. Biederman static int do_execveat(int fd, struct filename *filename,
207351f39a1fSDavid Drysdale const char __user *const __user *__argv,
207451f39a1fSDavid Drysdale const char __user *const __user *__envp,
207551f39a1fSDavid Drysdale int flags)
207651f39a1fSDavid Drysdale {
207751f39a1fSDavid Drysdale struct user_arg_ptr argv = { .ptr.native = __argv };
207851f39a1fSDavid Drysdale struct user_arg_ptr envp = { .ptr.native = __envp };
207951f39a1fSDavid Drysdale
208051f39a1fSDavid Drysdale return do_execveat_common(fd, filename, argv, envp, flags);
2081ba2d0162SOleg Nesterov }
2082ba2d0162SOleg Nesterov
20830e028465SOleg Nesterov #ifdef CONFIG_COMPAT
compat_do_execve(struct filename * filename,const compat_uptr_t __user * __argv,const compat_uptr_t __user * __envp)2084c4ad8f98SLinus Torvalds static int compat_do_execve(struct filename *filename,
208538b983b3SAl Viro const compat_uptr_t __user *__argv,
2086d03d26e5SAl Viro const compat_uptr_t __user *__envp)
20870e028465SOleg Nesterov {
20880e028465SOleg Nesterov struct user_arg_ptr argv = {
20890e028465SOleg Nesterov .is_compat = true,
20900e028465SOleg Nesterov .ptr.compat = __argv,
20910e028465SOleg Nesterov };
20920e028465SOleg Nesterov struct user_arg_ptr envp = {
20930e028465SOleg Nesterov .is_compat = true,
20940e028465SOleg Nesterov .ptr.compat = __envp,
20950e028465SOleg Nesterov };
209651f39a1fSDavid Drysdale return do_execveat_common(AT_FDCWD, filename, argv, envp, 0);
209751f39a1fSDavid Drysdale }
209851f39a1fSDavid Drysdale
compat_do_execveat(int fd,struct filename * filename,const compat_uptr_t __user * __argv,const compat_uptr_t __user * __envp,int flags)209951f39a1fSDavid Drysdale static int compat_do_execveat(int fd, struct filename *filename,
210051f39a1fSDavid Drysdale const compat_uptr_t __user *__argv,
210151f39a1fSDavid Drysdale const compat_uptr_t __user *__envp,
210251f39a1fSDavid Drysdale int flags)
210351f39a1fSDavid Drysdale {
210451f39a1fSDavid Drysdale struct user_arg_ptr argv = {
210551f39a1fSDavid Drysdale .is_compat = true,
210651f39a1fSDavid Drysdale .ptr.compat = __argv,
210751f39a1fSDavid Drysdale };
210851f39a1fSDavid Drysdale struct user_arg_ptr envp = {
210951f39a1fSDavid Drysdale .is_compat = true,
211051f39a1fSDavid Drysdale .ptr.compat = __envp,
211151f39a1fSDavid Drysdale };
211251f39a1fSDavid Drysdale return do_execveat_common(fd, filename, argv, envp, flags);
21130e028465SOleg Nesterov }
21140e028465SOleg Nesterov #endif
21150e028465SOleg Nesterov
set_binfmt(struct linux_binfmt * new)2116964ee7dfSOleg Nesterov void set_binfmt(struct linux_binfmt *new)
21171da177e4SLinus Torvalds {
2118801460d0SHiroshi Shimamoto struct mm_struct *mm = current->mm;
21191da177e4SLinus Torvalds
2120801460d0SHiroshi Shimamoto if (mm->binfmt)
2121801460d0SHiroshi Shimamoto module_put(mm->binfmt->module);
2122801460d0SHiroshi Shimamoto
2123801460d0SHiroshi Shimamoto mm->binfmt = new;
2124964ee7dfSOleg Nesterov if (new)
2125964ee7dfSOleg Nesterov __module_get(new->module);
21261da177e4SLinus Torvalds }
21271da177e4SLinus Torvalds EXPORT_SYMBOL(set_binfmt);
21281da177e4SLinus Torvalds
21296c5d5238SKawai, Hidehiro /*
21307288e118SOleg Nesterov * set_dumpable stores three-value SUID_DUMP_* into mm->flags.
21316c5d5238SKawai, Hidehiro */
set_dumpable(struct mm_struct * mm,int value)21326c5d5238SKawai, Hidehiro void set_dumpable(struct mm_struct *mm, int value)
21336c5d5238SKawai, Hidehiro {
21347288e118SOleg Nesterov if (WARN_ON((unsigned)value > SUID_DUMP_ROOT))
21357288e118SOleg Nesterov return;
21367288e118SOleg Nesterov
213726e15225SVineet Gupta set_mask_bits(&mm->flags, MMF_DUMPABLE_MASK, value);
21386c5d5238SKawai, Hidehiro }
21396c5d5238SKawai, Hidehiro
SYSCALL_DEFINE3(execve,const char __user *,filename,const char __user * const __user *,argv,const char __user * const __user *,envp)214038b983b3SAl Viro SYSCALL_DEFINE3(execve,
214138b983b3SAl Viro const char __user *, filename,
214238b983b3SAl Viro const char __user *const __user *, argv,
214338b983b3SAl Viro const char __user *const __user *, envp)
214438b983b3SAl Viro {
2145c4ad8f98SLinus Torvalds return do_execve(getname(filename), argv, envp);
214638b983b3SAl Viro }
214751f39a1fSDavid Drysdale
SYSCALL_DEFINE5(execveat,int,fd,const char __user *,filename,const char __user * const __user *,argv,const char __user * const __user *,envp,int,flags)214851f39a1fSDavid Drysdale SYSCALL_DEFINE5(execveat,
214951f39a1fSDavid Drysdale int, fd, const char __user *, filename,
215051f39a1fSDavid Drysdale const char __user *const __user *, argv,
215151f39a1fSDavid Drysdale const char __user *const __user *, envp,
215251f39a1fSDavid Drysdale int, flags)
215351f39a1fSDavid Drysdale {
215451f39a1fSDavid Drysdale return do_execveat(fd,
21558228e2c3SDmitry Kadashev getname_uflags(filename, flags),
215651f39a1fSDavid Drysdale argv, envp, flags);
215751f39a1fSDavid Drysdale }
215851f39a1fSDavid Drysdale
215938b983b3SAl Viro #ifdef CONFIG_COMPAT
COMPAT_SYSCALL_DEFINE3(execve,const char __user *,filename,const compat_uptr_t __user *,argv,const compat_uptr_t __user *,envp)2160625b1d7eSHeiko Carstens COMPAT_SYSCALL_DEFINE3(execve, const char __user *, filename,
2161625b1d7eSHeiko Carstens const compat_uptr_t __user *, argv,
2162625b1d7eSHeiko Carstens const compat_uptr_t __user *, envp)
216338b983b3SAl Viro {
2164c4ad8f98SLinus Torvalds return compat_do_execve(getname(filename), argv, envp);
216538b983b3SAl Viro }
216651f39a1fSDavid Drysdale
COMPAT_SYSCALL_DEFINE5(execveat,int,fd,const char __user *,filename,const compat_uptr_t __user *,argv,const compat_uptr_t __user *,envp,int,flags)216751f39a1fSDavid Drysdale COMPAT_SYSCALL_DEFINE5(execveat, int, fd,
216851f39a1fSDavid Drysdale const char __user *, filename,
216951f39a1fSDavid Drysdale const compat_uptr_t __user *, argv,
217051f39a1fSDavid Drysdale const compat_uptr_t __user *, envp,
217151f39a1fSDavid Drysdale int, flags)
217251f39a1fSDavid Drysdale {
217351f39a1fSDavid Drysdale return compat_do_execveat(fd,
21748228e2c3SDmitry Kadashev getname_uflags(filename, flags),
217551f39a1fSDavid Drysdale argv, envp, flags);
217651f39a1fSDavid Drysdale }
217738b983b3SAl Viro #endif
217866ad3986SLuis Chamberlain
217966ad3986SLuis Chamberlain #ifdef CONFIG_SYSCTL
218066ad3986SLuis Chamberlain
proc_dointvec_minmax_coredump(struct ctl_table * table,int write,void * buffer,size_t * lenp,loff_t * ppos)218166ad3986SLuis Chamberlain static int proc_dointvec_minmax_coredump(struct ctl_table *table, int write,
218266ad3986SLuis Chamberlain void *buffer, size_t *lenp, loff_t *ppos)
218366ad3986SLuis Chamberlain {
218466ad3986SLuis Chamberlain int error = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
218566ad3986SLuis Chamberlain
218666ad3986SLuis Chamberlain if (!error)
218766ad3986SLuis Chamberlain validate_coredump_safety();
218866ad3986SLuis Chamberlain return error;
218966ad3986SLuis Chamberlain }
219066ad3986SLuis Chamberlain
219166ad3986SLuis Chamberlain static struct ctl_table fs_exec_sysctls[] = {
219266ad3986SLuis Chamberlain {
219366ad3986SLuis Chamberlain .procname = "suid_dumpable",
219466ad3986SLuis Chamberlain .data = &suid_dumpable,
219566ad3986SLuis Chamberlain .maxlen = sizeof(int),
219666ad3986SLuis Chamberlain .mode = 0644,
219766ad3986SLuis Chamberlain .proc_handler = proc_dointvec_minmax_coredump,
219866ad3986SLuis Chamberlain .extra1 = SYSCTL_ZERO,
219966ad3986SLuis Chamberlain .extra2 = SYSCTL_TWO,
220066ad3986SLuis Chamberlain },
220166ad3986SLuis Chamberlain { }
220266ad3986SLuis Chamberlain };
220366ad3986SLuis Chamberlain
init_fs_exec_sysctls(void)220466ad3986SLuis Chamberlain static int __init init_fs_exec_sysctls(void)
220566ad3986SLuis Chamberlain {
220666ad3986SLuis Chamberlain register_sysctl_init("fs", fs_exec_sysctls);
220766ad3986SLuis Chamberlain return 0;
220866ad3986SLuis Chamberlain }
220966ad3986SLuis Chamberlain
221066ad3986SLuis Chamberlain fs_initcall(init_fs_exec_sysctls);
221166ad3986SLuis Chamberlain #endif /* CONFIG_SYSCTL */
2212