162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * linux/fs/exec.c 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 1991, 1992 Linus Torvalds 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci/* 962306a36Sopenharmony_ci * #!-checking implemented by tytso. 1062306a36Sopenharmony_ci */ 1162306a36Sopenharmony_ci/* 1262306a36Sopenharmony_ci * Demand-loading implemented 01.12.91 - no need to read anything but 1362306a36Sopenharmony_ci * the header into memory. The inode of the executable is put into 1462306a36Sopenharmony_ci * "current->executable", and page faults do the actual loading. Clean. 1562306a36Sopenharmony_ci * 1662306a36Sopenharmony_ci * Once more I can proudly say that linux stood up to being changed: it 1762306a36Sopenharmony_ci * was less than 2 hours work to get demand-loading completely implemented. 1862306a36Sopenharmony_ci * 1962306a36Sopenharmony_ci * Demand loading changed July 1993 by Eric Youngdale. Use mmap instead, 2062306a36Sopenharmony_ci * current->executable is only used by the procfs. This allows a dispatch 2162306a36Sopenharmony_ci * table to check for several different types of binary formats. We keep 2262306a36Sopenharmony_ci * trying until we recognize the file or we run out of supported binary 2362306a36Sopenharmony_ci * formats. 2462306a36Sopenharmony_ci */ 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci#include <linux/kernel_read_file.h> 2762306a36Sopenharmony_ci#include <linux/slab.h> 2862306a36Sopenharmony_ci#include <linux/file.h> 2962306a36Sopenharmony_ci#include <linux/fdtable.h> 3062306a36Sopenharmony_ci#include <linux/mm.h> 3162306a36Sopenharmony_ci#include <linux/stat.h> 3262306a36Sopenharmony_ci#include <linux/fcntl.h> 3362306a36Sopenharmony_ci#include <linux/swap.h> 3462306a36Sopenharmony_ci#include <linux/string.h> 3562306a36Sopenharmony_ci#include <linux/init.h> 3662306a36Sopenharmony_ci#include <linux/sched/mm.h> 3762306a36Sopenharmony_ci#include <linux/sched/coredump.h> 3862306a36Sopenharmony_ci#include <linux/sched/signal.h> 3962306a36Sopenharmony_ci#include <linux/sched/numa_balancing.h> 4062306a36Sopenharmony_ci#include <linux/sched/task.h> 4162306a36Sopenharmony_ci#include <linux/pagemap.h> 4262306a36Sopenharmony_ci#include <linux/perf_event.h> 4362306a36Sopenharmony_ci#include <linux/highmem.h> 4462306a36Sopenharmony_ci#include <linux/spinlock.h> 4562306a36Sopenharmony_ci#include <linux/key.h> 4662306a36Sopenharmony_ci#include <linux/personality.h> 4762306a36Sopenharmony_ci#include <linux/binfmts.h> 4862306a36Sopenharmony_ci#include <linux/utsname.h> 4962306a36Sopenharmony_ci#include <linux/pid_namespace.h> 5062306a36Sopenharmony_ci#include <linux/module.h> 5162306a36Sopenharmony_ci#include <linux/namei.h> 5262306a36Sopenharmony_ci#include <linux/mount.h> 5362306a36Sopenharmony_ci#include <linux/security.h> 5462306a36Sopenharmony_ci#include <linux/syscalls.h> 5562306a36Sopenharmony_ci#include <linux/tsacct_kern.h> 5662306a36Sopenharmony_ci#include <linux/cn_proc.h> 5762306a36Sopenharmony_ci#include <linux/audit.h> 5862306a36Sopenharmony_ci#include <linux/kmod.h> 5962306a36Sopenharmony_ci#include <linux/fsnotify.h> 6062306a36Sopenharmony_ci#include <linux/fs_struct.h> 6162306a36Sopenharmony_ci#include <linux/oom.h> 6262306a36Sopenharmony_ci#include <linux/compat.h> 6362306a36Sopenharmony_ci#include <linux/vmalloc.h> 6462306a36Sopenharmony_ci#include <linux/io_uring.h> 6562306a36Sopenharmony_ci#include <linux/syscall_user_dispatch.h> 6662306a36Sopenharmony_ci#include <linux/coredump.h> 6762306a36Sopenharmony_ci#include <linux/time_namespace.h> 6862306a36Sopenharmony_ci#include <linux/user_events.h> 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci#include <linux/uaccess.h> 7162306a36Sopenharmony_ci#include <asm/mmu_context.h> 7262306a36Sopenharmony_ci#include <asm/tlb.h> 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci#include <trace/events/task.h> 7562306a36Sopenharmony_ci#include "internal.h" 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci#include <trace/events/sched.h> 7862306a36Sopenharmony_ci#include <linux/hck/lite_hck_ced.h> 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_cistatic int bprm_creds_from_file(struct linux_binprm *bprm); 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ciint suid_dumpable = 0; 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_cistatic LIST_HEAD(formats); 8562306a36Sopenharmony_cistatic DEFINE_RWLOCK(binfmt_lock); 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_civoid __register_binfmt(struct linux_binfmt * fmt, int insert) 8862306a36Sopenharmony_ci{ 8962306a36Sopenharmony_ci write_lock(&binfmt_lock); 9062306a36Sopenharmony_ci insert ? list_add(&fmt->lh, &formats) : 9162306a36Sopenharmony_ci list_add_tail(&fmt->lh, &formats); 9262306a36Sopenharmony_ci write_unlock(&binfmt_lock); 9362306a36Sopenharmony_ci} 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ciEXPORT_SYMBOL(__register_binfmt); 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_civoid unregister_binfmt(struct linux_binfmt * fmt) 9862306a36Sopenharmony_ci{ 9962306a36Sopenharmony_ci write_lock(&binfmt_lock); 10062306a36Sopenharmony_ci list_del(&fmt->lh); 10162306a36Sopenharmony_ci write_unlock(&binfmt_lock); 10262306a36Sopenharmony_ci} 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ciEXPORT_SYMBOL(unregister_binfmt); 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_cistatic inline void put_binfmt(struct linux_binfmt * fmt) 10762306a36Sopenharmony_ci{ 10862306a36Sopenharmony_ci module_put(fmt->module); 10962306a36Sopenharmony_ci} 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_cibool path_noexec(const struct path *path) 11262306a36Sopenharmony_ci{ 11362306a36Sopenharmony_ci return (path->mnt->mnt_flags & MNT_NOEXEC) || 11462306a36Sopenharmony_ci (path->mnt->mnt_sb->s_iflags & SB_I_NOEXEC); 11562306a36Sopenharmony_ci} 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci#ifdef CONFIG_USELIB 11862306a36Sopenharmony_ci/* 11962306a36Sopenharmony_ci * Note that a shared library must be both readable and executable due to 12062306a36Sopenharmony_ci * security reasons. 12162306a36Sopenharmony_ci * 12262306a36Sopenharmony_ci * Also note that we take the address to load from the file itself. 12362306a36Sopenharmony_ci */ 12462306a36Sopenharmony_ciSYSCALL_DEFINE1(uselib, const char __user *, library) 12562306a36Sopenharmony_ci{ 12662306a36Sopenharmony_ci struct linux_binfmt *fmt; 12762306a36Sopenharmony_ci struct file *file; 12862306a36Sopenharmony_ci struct filename *tmp = getname(library); 12962306a36Sopenharmony_ci int error = PTR_ERR(tmp); 13062306a36Sopenharmony_ci static const struct open_flags uselib_flags = { 13162306a36Sopenharmony_ci .open_flag = O_LARGEFILE | O_RDONLY | __FMODE_EXEC, 13262306a36Sopenharmony_ci .acc_mode = MAY_READ | MAY_EXEC, 13362306a36Sopenharmony_ci .intent = LOOKUP_OPEN, 13462306a36Sopenharmony_ci .lookup_flags = LOOKUP_FOLLOW, 13562306a36Sopenharmony_ci }; 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci if (IS_ERR(tmp)) 13862306a36Sopenharmony_ci goto out; 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci file = do_filp_open(AT_FDCWD, tmp, &uselib_flags); 14162306a36Sopenharmony_ci putname(tmp); 14262306a36Sopenharmony_ci error = PTR_ERR(file); 14362306a36Sopenharmony_ci if (IS_ERR(file)) 14462306a36Sopenharmony_ci goto out; 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci /* 14762306a36Sopenharmony_ci * may_open() has already checked for this, so it should be 14862306a36Sopenharmony_ci * impossible to trip now. But we need to be extra cautious 14962306a36Sopenharmony_ci * and check again at the very end too. 15062306a36Sopenharmony_ci */ 15162306a36Sopenharmony_ci error = -EACCES; 15262306a36Sopenharmony_ci if (WARN_ON_ONCE(!S_ISREG(file_inode(file)->i_mode) || 15362306a36Sopenharmony_ci path_noexec(&file->f_path))) 15462306a36Sopenharmony_ci goto exit; 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci error = -ENOEXEC; 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci read_lock(&binfmt_lock); 15962306a36Sopenharmony_ci list_for_each_entry(fmt, &formats, lh) { 16062306a36Sopenharmony_ci if (!fmt->load_shlib) 16162306a36Sopenharmony_ci continue; 16262306a36Sopenharmony_ci if (!try_module_get(fmt->module)) 16362306a36Sopenharmony_ci continue; 16462306a36Sopenharmony_ci read_unlock(&binfmt_lock); 16562306a36Sopenharmony_ci error = fmt->load_shlib(file); 16662306a36Sopenharmony_ci read_lock(&binfmt_lock); 16762306a36Sopenharmony_ci put_binfmt(fmt); 16862306a36Sopenharmony_ci if (error != -ENOEXEC) 16962306a36Sopenharmony_ci break; 17062306a36Sopenharmony_ci } 17162306a36Sopenharmony_ci read_unlock(&binfmt_lock); 17262306a36Sopenharmony_ciexit: 17362306a36Sopenharmony_ci fput(file); 17462306a36Sopenharmony_ciout: 17562306a36Sopenharmony_ci return error; 17662306a36Sopenharmony_ci} 17762306a36Sopenharmony_ci#endif /* #ifdef CONFIG_USELIB */ 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci#ifdef CONFIG_MMU 18062306a36Sopenharmony_ci/* 18162306a36Sopenharmony_ci * The nascent bprm->mm is not visible until exec_mmap() but it can 18262306a36Sopenharmony_ci * use a lot of memory, account these pages in current->mm temporary 18362306a36Sopenharmony_ci * for oom_badness()->get_mm_rss(). Once exec succeeds or fails, we 18462306a36Sopenharmony_ci * change the counter back via acct_arg_size(0). 18562306a36Sopenharmony_ci */ 18662306a36Sopenharmony_cistatic void acct_arg_size(struct linux_binprm *bprm, unsigned long pages) 18762306a36Sopenharmony_ci{ 18862306a36Sopenharmony_ci struct mm_struct *mm = current->mm; 18962306a36Sopenharmony_ci long diff = (long)(pages - bprm->vma_pages); 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci if (!mm || !diff) 19262306a36Sopenharmony_ci return; 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_ci bprm->vma_pages = pages; 19562306a36Sopenharmony_ci add_mm_counter(mm, MM_ANONPAGES, diff); 19662306a36Sopenharmony_ci} 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_cistatic struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos, 19962306a36Sopenharmony_ci int write) 20062306a36Sopenharmony_ci{ 20162306a36Sopenharmony_ci struct page *page; 20262306a36Sopenharmony_ci struct vm_area_struct *vma = bprm->vma; 20362306a36Sopenharmony_ci struct mm_struct *mm = bprm->mm; 20462306a36Sopenharmony_ci int ret; 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci /* 20762306a36Sopenharmony_ci * Avoid relying on expanding the stack down in GUP (which 20862306a36Sopenharmony_ci * does not work for STACK_GROWSUP anyway), and just do it 20962306a36Sopenharmony_ci * by hand ahead of time. 21062306a36Sopenharmony_ci */ 21162306a36Sopenharmony_ci if (write && pos < vma->vm_start) { 21262306a36Sopenharmony_ci mmap_write_lock(mm); 21362306a36Sopenharmony_ci ret = expand_downwards(vma, pos); 21462306a36Sopenharmony_ci if (unlikely(ret < 0)) { 21562306a36Sopenharmony_ci mmap_write_unlock(mm); 21662306a36Sopenharmony_ci return NULL; 21762306a36Sopenharmony_ci } 21862306a36Sopenharmony_ci mmap_write_downgrade(mm); 21962306a36Sopenharmony_ci } else 22062306a36Sopenharmony_ci mmap_read_lock(mm); 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci /* 22362306a36Sopenharmony_ci * We are doing an exec(). 'current' is the process 22462306a36Sopenharmony_ci * doing the exec and 'mm' is the new process's mm. 22562306a36Sopenharmony_ci */ 22662306a36Sopenharmony_ci ret = get_user_pages_remote(mm, pos, 1, 22762306a36Sopenharmony_ci write ? FOLL_WRITE : 0, 22862306a36Sopenharmony_ci &page, NULL); 22962306a36Sopenharmony_ci mmap_read_unlock(mm); 23062306a36Sopenharmony_ci if (ret <= 0) 23162306a36Sopenharmony_ci return NULL; 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci if (write) 23462306a36Sopenharmony_ci acct_arg_size(bprm, vma_pages(vma)); 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci return page; 23762306a36Sopenharmony_ci} 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_cistatic void put_arg_page(struct page *page) 24062306a36Sopenharmony_ci{ 24162306a36Sopenharmony_ci put_page(page); 24262306a36Sopenharmony_ci} 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_cistatic void free_arg_pages(struct linux_binprm *bprm) 24562306a36Sopenharmony_ci{ 24662306a36Sopenharmony_ci} 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_cistatic void flush_arg_page(struct linux_binprm *bprm, unsigned long pos, 24962306a36Sopenharmony_ci struct page *page) 25062306a36Sopenharmony_ci{ 25162306a36Sopenharmony_ci flush_cache_page(bprm->vma, pos, page_to_pfn(page)); 25262306a36Sopenharmony_ci} 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_cistatic int __bprm_mm_init(struct linux_binprm *bprm) 25562306a36Sopenharmony_ci{ 25662306a36Sopenharmony_ci int err; 25762306a36Sopenharmony_ci struct vm_area_struct *vma = NULL; 25862306a36Sopenharmony_ci struct mm_struct *mm = bprm->mm; 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_ci bprm->vma = vma = vm_area_alloc(mm); 26162306a36Sopenharmony_ci if (!vma) 26262306a36Sopenharmony_ci return -ENOMEM; 26362306a36Sopenharmony_ci vma_set_anonymous(vma); 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ci if (mmap_write_lock_killable(mm)) { 26662306a36Sopenharmony_ci err = -EINTR; 26762306a36Sopenharmony_ci goto err_free; 26862306a36Sopenharmony_ci } 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_ci /* 27162306a36Sopenharmony_ci * Place the stack at the largest stack address the architecture 27262306a36Sopenharmony_ci * supports. Later, we'll move this to an appropriate place. We don't 27362306a36Sopenharmony_ci * use STACK_TOP because that can depend on attributes which aren't 27462306a36Sopenharmony_ci * configured yet. 27562306a36Sopenharmony_ci */ 27662306a36Sopenharmony_ci BUILD_BUG_ON(VM_STACK_FLAGS & VM_STACK_INCOMPLETE_SETUP); 27762306a36Sopenharmony_ci vma->vm_end = STACK_TOP_MAX; 27862306a36Sopenharmony_ci vma->vm_start = vma->vm_end - PAGE_SIZE; 27962306a36Sopenharmony_ci vm_flags_init(vma, VM_SOFTDIRTY | VM_STACK_FLAGS | VM_STACK_INCOMPLETE_SETUP); 28062306a36Sopenharmony_ci vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_ci err = insert_vm_struct(mm, vma); 28362306a36Sopenharmony_ci if (err) 28462306a36Sopenharmony_ci goto err; 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_ci mm->stack_vm = mm->total_vm = 1; 28762306a36Sopenharmony_ci mmap_write_unlock(mm); 28862306a36Sopenharmony_ci bprm->p = vma->vm_end - sizeof(void *); 28962306a36Sopenharmony_ci return 0; 29062306a36Sopenharmony_cierr: 29162306a36Sopenharmony_ci mmap_write_unlock(mm); 29262306a36Sopenharmony_cierr_free: 29362306a36Sopenharmony_ci bprm->vma = NULL; 29462306a36Sopenharmony_ci vm_area_free(vma); 29562306a36Sopenharmony_ci return err; 29662306a36Sopenharmony_ci} 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_cistatic bool valid_arg_len(struct linux_binprm *bprm, long len) 29962306a36Sopenharmony_ci{ 30062306a36Sopenharmony_ci return len <= MAX_ARG_STRLEN; 30162306a36Sopenharmony_ci} 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci#else 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_cistatic inline void acct_arg_size(struct linux_binprm *bprm, unsigned long pages) 30662306a36Sopenharmony_ci{ 30762306a36Sopenharmony_ci} 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_cistatic struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos, 31062306a36Sopenharmony_ci int write) 31162306a36Sopenharmony_ci{ 31262306a36Sopenharmony_ci struct page *page; 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_ci page = bprm->page[pos / PAGE_SIZE]; 31562306a36Sopenharmony_ci if (!page && write) { 31662306a36Sopenharmony_ci page = alloc_page(GFP_HIGHUSER|__GFP_ZERO); 31762306a36Sopenharmony_ci if (!page) 31862306a36Sopenharmony_ci return NULL; 31962306a36Sopenharmony_ci bprm->page[pos / PAGE_SIZE] = page; 32062306a36Sopenharmony_ci } 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ci return page; 32362306a36Sopenharmony_ci} 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_cistatic void put_arg_page(struct page *page) 32662306a36Sopenharmony_ci{ 32762306a36Sopenharmony_ci} 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_cistatic void free_arg_page(struct linux_binprm *bprm, int i) 33062306a36Sopenharmony_ci{ 33162306a36Sopenharmony_ci if (bprm->page[i]) { 33262306a36Sopenharmony_ci __free_page(bprm->page[i]); 33362306a36Sopenharmony_ci bprm->page[i] = NULL; 33462306a36Sopenharmony_ci } 33562306a36Sopenharmony_ci} 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_cistatic void free_arg_pages(struct linux_binprm *bprm) 33862306a36Sopenharmony_ci{ 33962306a36Sopenharmony_ci int i; 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci for (i = 0; i < MAX_ARG_PAGES; i++) 34262306a36Sopenharmony_ci free_arg_page(bprm, i); 34362306a36Sopenharmony_ci} 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_cistatic void flush_arg_page(struct linux_binprm *bprm, unsigned long pos, 34662306a36Sopenharmony_ci struct page *page) 34762306a36Sopenharmony_ci{ 34862306a36Sopenharmony_ci} 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_cistatic int __bprm_mm_init(struct linux_binprm *bprm) 35162306a36Sopenharmony_ci{ 35262306a36Sopenharmony_ci bprm->p = PAGE_SIZE * MAX_ARG_PAGES - sizeof(void *); 35362306a36Sopenharmony_ci return 0; 35462306a36Sopenharmony_ci} 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_cistatic bool valid_arg_len(struct linux_binprm *bprm, long len) 35762306a36Sopenharmony_ci{ 35862306a36Sopenharmony_ci return len <= bprm->p; 35962306a36Sopenharmony_ci} 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci#endif /* CONFIG_MMU */ 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_ci/* 36462306a36Sopenharmony_ci * Create a new mm_struct and populate it with a temporary stack 36562306a36Sopenharmony_ci * vm_area_struct. We don't have enough context at this point to set the stack 36662306a36Sopenharmony_ci * flags, permissions, and offset, so we use temporary values. We'll update 36762306a36Sopenharmony_ci * them later in setup_arg_pages(). 36862306a36Sopenharmony_ci */ 36962306a36Sopenharmony_cistatic int bprm_mm_init(struct linux_binprm *bprm) 37062306a36Sopenharmony_ci{ 37162306a36Sopenharmony_ci int err; 37262306a36Sopenharmony_ci struct mm_struct *mm = NULL; 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_ci bprm->mm = mm = mm_alloc(); 37562306a36Sopenharmony_ci err = -ENOMEM; 37662306a36Sopenharmony_ci if (!mm) 37762306a36Sopenharmony_ci goto err; 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ci /* Save current stack limit for all calculations made during exec. */ 38062306a36Sopenharmony_ci task_lock(current->group_leader); 38162306a36Sopenharmony_ci bprm->rlim_stack = current->signal->rlim[RLIMIT_STACK]; 38262306a36Sopenharmony_ci task_unlock(current->group_leader); 38362306a36Sopenharmony_ci 38462306a36Sopenharmony_ci err = __bprm_mm_init(bprm); 38562306a36Sopenharmony_ci if (err) 38662306a36Sopenharmony_ci goto err; 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_ci return 0; 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_cierr: 39162306a36Sopenharmony_ci if (mm) { 39262306a36Sopenharmony_ci bprm->mm = NULL; 39362306a36Sopenharmony_ci mmdrop(mm); 39462306a36Sopenharmony_ci } 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_ci return err; 39762306a36Sopenharmony_ci} 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_cistruct user_arg_ptr { 40062306a36Sopenharmony_ci#ifdef CONFIG_COMPAT 40162306a36Sopenharmony_ci bool is_compat; 40262306a36Sopenharmony_ci#endif 40362306a36Sopenharmony_ci union { 40462306a36Sopenharmony_ci const char __user *const __user *native; 40562306a36Sopenharmony_ci#ifdef CONFIG_COMPAT 40662306a36Sopenharmony_ci const compat_uptr_t __user *compat; 40762306a36Sopenharmony_ci#endif 40862306a36Sopenharmony_ci } ptr; 40962306a36Sopenharmony_ci}; 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_cistatic const char __user *get_user_arg_ptr(struct user_arg_ptr argv, int nr) 41262306a36Sopenharmony_ci{ 41362306a36Sopenharmony_ci const char __user *native; 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_ci#ifdef CONFIG_COMPAT 41662306a36Sopenharmony_ci if (unlikely(argv.is_compat)) { 41762306a36Sopenharmony_ci compat_uptr_t compat; 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_ci if (get_user(compat, argv.ptr.compat + nr)) 42062306a36Sopenharmony_ci return ERR_PTR(-EFAULT); 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_ci return compat_ptr(compat); 42362306a36Sopenharmony_ci } 42462306a36Sopenharmony_ci#endif 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_ci if (get_user(native, argv.ptr.native + nr)) 42762306a36Sopenharmony_ci return ERR_PTR(-EFAULT); 42862306a36Sopenharmony_ci 42962306a36Sopenharmony_ci return native; 43062306a36Sopenharmony_ci} 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_ci/* 43362306a36Sopenharmony_ci * count() counts the number of strings in array ARGV. 43462306a36Sopenharmony_ci */ 43562306a36Sopenharmony_cistatic int count(struct user_arg_ptr argv, int max) 43662306a36Sopenharmony_ci{ 43762306a36Sopenharmony_ci int i = 0; 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_ci if (argv.ptr.native != NULL) { 44062306a36Sopenharmony_ci for (;;) { 44162306a36Sopenharmony_ci const char __user *p = get_user_arg_ptr(argv, i); 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_ci if (!p) 44462306a36Sopenharmony_ci break; 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_ci if (IS_ERR(p)) 44762306a36Sopenharmony_ci return -EFAULT; 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_ci if (i >= max) 45062306a36Sopenharmony_ci return -E2BIG; 45162306a36Sopenharmony_ci ++i; 45262306a36Sopenharmony_ci 45362306a36Sopenharmony_ci if (fatal_signal_pending(current)) 45462306a36Sopenharmony_ci return -ERESTARTNOHAND; 45562306a36Sopenharmony_ci cond_resched(); 45662306a36Sopenharmony_ci } 45762306a36Sopenharmony_ci } 45862306a36Sopenharmony_ci return i; 45962306a36Sopenharmony_ci} 46062306a36Sopenharmony_ci 46162306a36Sopenharmony_cistatic int count_strings_kernel(const char *const *argv) 46262306a36Sopenharmony_ci{ 46362306a36Sopenharmony_ci int i; 46462306a36Sopenharmony_ci 46562306a36Sopenharmony_ci if (!argv) 46662306a36Sopenharmony_ci return 0; 46762306a36Sopenharmony_ci 46862306a36Sopenharmony_ci for (i = 0; argv[i]; ++i) { 46962306a36Sopenharmony_ci if (i >= MAX_ARG_STRINGS) 47062306a36Sopenharmony_ci return -E2BIG; 47162306a36Sopenharmony_ci if (fatal_signal_pending(current)) 47262306a36Sopenharmony_ci return -ERESTARTNOHAND; 47362306a36Sopenharmony_ci cond_resched(); 47462306a36Sopenharmony_ci } 47562306a36Sopenharmony_ci return i; 47662306a36Sopenharmony_ci} 47762306a36Sopenharmony_ci 47862306a36Sopenharmony_cistatic int bprm_stack_limits(struct linux_binprm *bprm) 47962306a36Sopenharmony_ci{ 48062306a36Sopenharmony_ci unsigned long limit, ptr_size; 48162306a36Sopenharmony_ci 48262306a36Sopenharmony_ci /* 48362306a36Sopenharmony_ci * Limit to 1/4 of the max stack size or 3/4 of _STK_LIM 48462306a36Sopenharmony_ci * (whichever is smaller) for the argv+env strings. 48562306a36Sopenharmony_ci * This ensures that: 48662306a36Sopenharmony_ci * - the remaining binfmt code will not run out of stack space, 48762306a36Sopenharmony_ci * - the program will have a reasonable amount of stack left 48862306a36Sopenharmony_ci * to work from. 48962306a36Sopenharmony_ci */ 49062306a36Sopenharmony_ci limit = _STK_LIM / 4 * 3; 49162306a36Sopenharmony_ci limit = min(limit, bprm->rlim_stack.rlim_cur / 4); 49262306a36Sopenharmony_ci /* 49362306a36Sopenharmony_ci * We've historically supported up to 32 pages (ARG_MAX) 49462306a36Sopenharmony_ci * of argument strings even with small stacks 49562306a36Sopenharmony_ci */ 49662306a36Sopenharmony_ci limit = max_t(unsigned long, limit, ARG_MAX); 49762306a36Sopenharmony_ci /* 49862306a36Sopenharmony_ci * We must account for the size of all the argv and envp pointers to 49962306a36Sopenharmony_ci * the argv and envp strings, since they will also take up space in 50062306a36Sopenharmony_ci * the stack. They aren't stored until much later when we can't 50162306a36Sopenharmony_ci * signal to the parent that the child has run out of stack space. 50262306a36Sopenharmony_ci * Instead, calculate it here so it's possible to fail gracefully. 50362306a36Sopenharmony_ci * 50462306a36Sopenharmony_ci * In the case of argc = 0, make sure there is space for adding a 50562306a36Sopenharmony_ci * empty string (which will bump argc to 1), to ensure confused 50662306a36Sopenharmony_ci * userspace programs don't start processing from argv[1], thinking 50762306a36Sopenharmony_ci * argc can never be 0, to keep them from walking envp by accident. 50862306a36Sopenharmony_ci * See do_execveat_common(). 50962306a36Sopenharmony_ci */ 51062306a36Sopenharmony_ci ptr_size = (max(bprm->argc, 1) + bprm->envc) * sizeof(void *); 51162306a36Sopenharmony_ci if (limit <= ptr_size) 51262306a36Sopenharmony_ci return -E2BIG; 51362306a36Sopenharmony_ci limit -= ptr_size; 51462306a36Sopenharmony_ci 51562306a36Sopenharmony_ci bprm->argmin = bprm->p - limit; 51662306a36Sopenharmony_ci return 0; 51762306a36Sopenharmony_ci} 51862306a36Sopenharmony_ci 51962306a36Sopenharmony_ci/* 52062306a36Sopenharmony_ci * 'copy_strings()' copies argument/environment strings from the old 52162306a36Sopenharmony_ci * processes's memory to the new process's stack. The call to get_user_pages() 52262306a36Sopenharmony_ci * ensures the destination page is created and not swapped out. 52362306a36Sopenharmony_ci */ 52462306a36Sopenharmony_cistatic int copy_strings(int argc, struct user_arg_ptr argv, 52562306a36Sopenharmony_ci struct linux_binprm *bprm) 52662306a36Sopenharmony_ci{ 52762306a36Sopenharmony_ci struct page *kmapped_page = NULL; 52862306a36Sopenharmony_ci char *kaddr = NULL; 52962306a36Sopenharmony_ci unsigned long kpos = 0; 53062306a36Sopenharmony_ci int ret; 53162306a36Sopenharmony_ci 53262306a36Sopenharmony_ci while (argc-- > 0) { 53362306a36Sopenharmony_ci const char __user *str; 53462306a36Sopenharmony_ci int len; 53562306a36Sopenharmony_ci unsigned long pos; 53662306a36Sopenharmony_ci 53762306a36Sopenharmony_ci ret = -EFAULT; 53862306a36Sopenharmony_ci str = get_user_arg_ptr(argv, argc); 53962306a36Sopenharmony_ci if (IS_ERR(str)) 54062306a36Sopenharmony_ci goto out; 54162306a36Sopenharmony_ci 54262306a36Sopenharmony_ci len = strnlen_user(str, MAX_ARG_STRLEN); 54362306a36Sopenharmony_ci if (!len) 54462306a36Sopenharmony_ci goto out; 54562306a36Sopenharmony_ci 54662306a36Sopenharmony_ci ret = -E2BIG; 54762306a36Sopenharmony_ci if (!valid_arg_len(bprm, len)) 54862306a36Sopenharmony_ci goto out; 54962306a36Sopenharmony_ci 55062306a36Sopenharmony_ci /* We're going to work our way backwards. */ 55162306a36Sopenharmony_ci pos = bprm->p; 55262306a36Sopenharmony_ci str += len; 55362306a36Sopenharmony_ci bprm->p -= len; 55462306a36Sopenharmony_ci#ifdef CONFIG_MMU 55562306a36Sopenharmony_ci if (bprm->p < bprm->argmin) 55662306a36Sopenharmony_ci goto out; 55762306a36Sopenharmony_ci#endif 55862306a36Sopenharmony_ci 55962306a36Sopenharmony_ci while (len > 0) { 56062306a36Sopenharmony_ci int offset, bytes_to_copy; 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_ci if (fatal_signal_pending(current)) { 56362306a36Sopenharmony_ci ret = -ERESTARTNOHAND; 56462306a36Sopenharmony_ci goto out; 56562306a36Sopenharmony_ci } 56662306a36Sopenharmony_ci cond_resched(); 56762306a36Sopenharmony_ci 56862306a36Sopenharmony_ci offset = pos % PAGE_SIZE; 56962306a36Sopenharmony_ci if (offset == 0) 57062306a36Sopenharmony_ci offset = PAGE_SIZE; 57162306a36Sopenharmony_ci 57262306a36Sopenharmony_ci bytes_to_copy = offset; 57362306a36Sopenharmony_ci if (bytes_to_copy > len) 57462306a36Sopenharmony_ci bytes_to_copy = len; 57562306a36Sopenharmony_ci 57662306a36Sopenharmony_ci offset -= bytes_to_copy; 57762306a36Sopenharmony_ci pos -= bytes_to_copy; 57862306a36Sopenharmony_ci str -= bytes_to_copy; 57962306a36Sopenharmony_ci len -= bytes_to_copy; 58062306a36Sopenharmony_ci 58162306a36Sopenharmony_ci if (!kmapped_page || kpos != (pos & PAGE_MASK)) { 58262306a36Sopenharmony_ci struct page *page; 58362306a36Sopenharmony_ci 58462306a36Sopenharmony_ci page = get_arg_page(bprm, pos, 1); 58562306a36Sopenharmony_ci if (!page) { 58662306a36Sopenharmony_ci ret = -E2BIG; 58762306a36Sopenharmony_ci goto out; 58862306a36Sopenharmony_ci } 58962306a36Sopenharmony_ci 59062306a36Sopenharmony_ci if (kmapped_page) { 59162306a36Sopenharmony_ci flush_dcache_page(kmapped_page); 59262306a36Sopenharmony_ci kunmap_local(kaddr); 59362306a36Sopenharmony_ci put_arg_page(kmapped_page); 59462306a36Sopenharmony_ci } 59562306a36Sopenharmony_ci kmapped_page = page; 59662306a36Sopenharmony_ci kaddr = kmap_local_page(kmapped_page); 59762306a36Sopenharmony_ci kpos = pos & PAGE_MASK; 59862306a36Sopenharmony_ci flush_arg_page(bprm, kpos, kmapped_page); 59962306a36Sopenharmony_ci } 60062306a36Sopenharmony_ci if (copy_from_user(kaddr+offset, str, bytes_to_copy)) { 60162306a36Sopenharmony_ci ret = -EFAULT; 60262306a36Sopenharmony_ci goto out; 60362306a36Sopenharmony_ci } 60462306a36Sopenharmony_ci } 60562306a36Sopenharmony_ci } 60662306a36Sopenharmony_ci ret = 0; 60762306a36Sopenharmony_ciout: 60862306a36Sopenharmony_ci if (kmapped_page) { 60962306a36Sopenharmony_ci flush_dcache_page(kmapped_page); 61062306a36Sopenharmony_ci kunmap_local(kaddr); 61162306a36Sopenharmony_ci put_arg_page(kmapped_page); 61262306a36Sopenharmony_ci } 61362306a36Sopenharmony_ci return ret; 61462306a36Sopenharmony_ci} 61562306a36Sopenharmony_ci 61662306a36Sopenharmony_ci/* 61762306a36Sopenharmony_ci * Copy and argument/environment string from the kernel to the processes stack. 61862306a36Sopenharmony_ci */ 61962306a36Sopenharmony_ciint copy_string_kernel(const char *arg, struct linux_binprm *bprm) 62062306a36Sopenharmony_ci{ 62162306a36Sopenharmony_ci int len = strnlen(arg, MAX_ARG_STRLEN) + 1 /* terminating NUL */; 62262306a36Sopenharmony_ci unsigned long pos = bprm->p; 62362306a36Sopenharmony_ci 62462306a36Sopenharmony_ci if (len == 0) 62562306a36Sopenharmony_ci return -EFAULT; 62662306a36Sopenharmony_ci if (!valid_arg_len(bprm, len)) 62762306a36Sopenharmony_ci return -E2BIG; 62862306a36Sopenharmony_ci 62962306a36Sopenharmony_ci /* We're going to work our way backwards. */ 63062306a36Sopenharmony_ci arg += len; 63162306a36Sopenharmony_ci bprm->p -= len; 63262306a36Sopenharmony_ci if (IS_ENABLED(CONFIG_MMU) && bprm->p < bprm->argmin) 63362306a36Sopenharmony_ci return -E2BIG; 63462306a36Sopenharmony_ci 63562306a36Sopenharmony_ci while (len > 0) { 63662306a36Sopenharmony_ci unsigned int bytes_to_copy = min_t(unsigned int, len, 63762306a36Sopenharmony_ci min_not_zero(offset_in_page(pos), PAGE_SIZE)); 63862306a36Sopenharmony_ci struct page *page; 63962306a36Sopenharmony_ci 64062306a36Sopenharmony_ci pos -= bytes_to_copy; 64162306a36Sopenharmony_ci arg -= bytes_to_copy; 64262306a36Sopenharmony_ci len -= bytes_to_copy; 64362306a36Sopenharmony_ci 64462306a36Sopenharmony_ci page = get_arg_page(bprm, pos, 1); 64562306a36Sopenharmony_ci if (!page) 64662306a36Sopenharmony_ci return -E2BIG; 64762306a36Sopenharmony_ci flush_arg_page(bprm, pos & PAGE_MASK, page); 64862306a36Sopenharmony_ci memcpy_to_page(page, offset_in_page(pos), arg, bytes_to_copy); 64962306a36Sopenharmony_ci put_arg_page(page); 65062306a36Sopenharmony_ci } 65162306a36Sopenharmony_ci 65262306a36Sopenharmony_ci return 0; 65362306a36Sopenharmony_ci} 65462306a36Sopenharmony_ciEXPORT_SYMBOL(copy_string_kernel); 65562306a36Sopenharmony_ci 65662306a36Sopenharmony_cistatic int copy_strings_kernel(int argc, const char *const *argv, 65762306a36Sopenharmony_ci struct linux_binprm *bprm) 65862306a36Sopenharmony_ci{ 65962306a36Sopenharmony_ci while (argc-- > 0) { 66062306a36Sopenharmony_ci int ret = copy_string_kernel(argv[argc], bprm); 66162306a36Sopenharmony_ci if (ret < 0) 66262306a36Sopenharmony_ci return ret; 66362306a36Sopenharmony_ci if (fatal_signal_pending(current)) 66462306a36Sopenharmony_ci return -ERESTARTNOHAND; 66562306a36Sopenharmony_ci cond_resched(); 66662306a36Sopenharmony_ci } 66762306a36Sopenharmony_ci return 0; 66862306a36Sopenharmony_ci} 66962306a36Sopenharmony_ci 67062306a36Sopenharmony_ci#ifdef CONFIG_MMU 67162306a36Sopenharmony_ci 67262306a36Sopenharmony_ci/* 67362306a36Sopenharmony_ci * During bprm_mm_init(), we create a temporary stack at STACK_TOP_MAX. Once 67462306a36Sopenharmony_ci * the binfmt code determines where the new stack should reside, we shift it to 67562306a36Sopenharmony_ci * its final location. The process proceeds as follows: 67662306a36Sopenharmony_ci * 67762306a36Sopenharmony_ci * 1) Use shift to calculate the new vma endpoints. 67862306a36Sopenharmony_ci * 2) Extend vma to cover both the old and new ranges. This ensures the 67962306a36Sopenharmony_ci * arguments passed to subsequent functions are consistent. 68062306a36Sopenharmony_ci * 3) Move vma's page tables to the new range. 68162306a36Sopenharmony_ci * 4) Free up any cleared pgd range. 68262306a36Sopenharmony_ci * 5) Shrink the vma to cover only the new range. 68362306a36Sopenharmony_ci */ 68462306a36Sopenharmony_cistatic int shift_arg_pages(struct vm_area_struct *vma, unsigned long shift) 68562306a36Sopenharmony_ci{ 68662306a36Sopenharmony_ci struct mm_struct *mm = vma->vm_mm; 68762306a36Sopenharmony_ci unsigned long old_start = vma->vm_start; 68862306a36Sopenharmony_ci unsigned long old_end = vma->vm_end; 68962306a36Sopenharmony_ci unsigned long length = old_end - old_start; 69062306a36Sopenharmony_ci unsigned long new_start = old_start - shift; 69162306a36Sopenharmony_ci unsigned long new_end = old_end - shift; 69262306a36Sopenharmony_ci VMA_ITERATOR(vmi, mm, new_start); 69362306a36Sopenharmony_ci struct vm_area_struct *next; 69462306a36Sopenharmony_ci struct mmu_gather tlb; 69562306a36Sopenharmony_ci 69662306a36Sopenharmony_ci BUG_ON(new_start > new_end); 69762306a36Sopenharmony_ci 69862306a36Sopenharmony_ci /* 69962306a36Sopenharmony_ci * ensure there are no vmas between where we want to go 70062306a36Sopenharmony_ci * and where we are 70162306a36Sopenharmony_ci */ 70262306a36Sopenharmony_ci if (vma != vma_next(&vmi)) 70362306a36Sopenharmony_ci return -EFAULT; 70462306a36Sopenharmony_ci 70562306a36Sopenharmony_ci vma_iter_prev_range(&vmi); 70662306a36Sopenharmony_ci /* 70762306a36Sopenharmony_ci * cover the whole range: [new_start, old_end) 70862306a36Sopenharmony_ci */ 70962306a36Sopenharmony_ci if (vma_expand(&vmi, vma, new_start, old_end, vma->vm_pgoff, NULL)) 71062306a36Sopenharmony_ci return -ENOMEM; 71162306a36Sopenharmony_ci 71262306a36Sopenharmony_ci /* 71362306a36Sopenharmony_ci * move the page tables downwards, on failure we rely on 71462306a36Sopenharmony_ci * process cleanup to remove whatever mess we made. 71562306a36Sopenharmony_ci */ 71662306a36Sopenharmony_ci if (length != move_page_tables(vma, old_start, 71762306a36Sopenharmony_ci vma, new_start, length, false)) 71862306a36Sopenharmony_ci return -ENOMEM; 71962306a36Sopenharmony_ci 72062306a36Sopenharmony_ci lru_add_drain(); 72162306a36Sopenharmony_ci tlb_gather_mmu(&tlb, mm); 72262306a36Sopenharmony_ci next = vma_next(&vmi); 72362306a36Sopenharmony_ci if (new_end > old_start) { 72462306a36Sopenharmony_ci /* 72562306a36Sopenharmony_ci * when the old and new regions overlap clear from new_end. 72662306a36Sopenharmony_ci */ 72762306a36Sopenharmony_ci free_pgd_range(&tlb, new_end, old_end, new_end, 72862306a36Sopenharmony_ci next ? next->vm_start : USER_PGTABLES_CEILING); 72962306a36Sopenharmony_ci } else { 73062306a36Sopenharmony_ci /* 73162306a36Sopenharmony_ci * otherwise, clean from old_start; this is done to not touch 73262306a36Sopenharmony_ci * the address space in [new_end, old_start) some architectures 73362306a36Sopenharmony_ci * have constraints on va-space that make this illegal (IA64) - 73462306a36Sopenharmony_ci * for the others its just a little faster. 73562306a36Sopenharmony_ci */ 73662306a36Sopenharmony_ci free_pgd_range(&tlb, old_start, old_end, new_end, 73762306a36Sopenharmony_ci next ? next->vm_start : USER_PGTABLES_CEILING); 73862306a36Sopenharmony_ci } 73962306a36Sopenharmony_ci tlb_finish_mmu(&tlb); 74062306a36Sopenharmony_ci 74162306a36Sopenharmony_ci vma_prev(&vmi); 74262306a36Sopenharmony_ci /* Shrink the vma to just the new range */ 74362306a36Sopenharmony_ci return vma_shrink(&vmi, vma, new_start, new_end, vma->vm_pgoff); 74462306a36Sopenharmony_ci} 74562306a36Sopenharmony_ci 74662306a36Sopenharmony_ci/* 74762306a36Sopenharmony_ci * Finalizes the stack vm_area_struct. The flags and permissions are updated, 74862306a36Sopenharmony_ci * the stack is optionally relocated, and some extra space is added. 74962306a36Sopenharmony_ci */ 75062306a36Sopenharmony_ciint setup_arg_pages(struct linux_binprm *bprm, 75162306a36Sopenharmony_ci unsigned long stack_top, 75262306a36Sopenharmony_ci int executable_stack) 75362306a36Sopenharmony_ci{ 75462306a36Sopenharmony_ci unsigned long ret; 75562306a36Sopenharmony_ci unsigned long stack_shift; 75662306a36Sopenharmony_ci struct mm_struct *mm = current->mm; 75762306a36Sopenharmony_ci struct vm_area_struct *vma = bprm->vma; 75862306a36Sopenharmony_ci struct vm_area_struct *prev = NULL; 75962306a36Sopenharmony_ci unsigned long vm_flags; 76062306a36Sopenharmony_ci unsigned long stack_base; 76162306a36Sopenharmony_ci unsigned long stack_size; 76262306a36Sopenharmony_ci unsigned long stack_expand; 76362306a36Sopenharmony_ci unsigned long rlim_stack; 76462306a36Sopenharmony_ci struct mmu_gather tlb; 76562306a36Sopenharmony_ci struct vma_iterator vmi; 76662306a36Sopenharmony_ci 76762306a36Sopenharmony_ci#ifdef CONFIG_STACK_GROWSUP 76862306a36Sopenharmony_ci /* Limit stack size */ 76962306a36Sopenharmony_ci stack_base = bprm->rlim_stack.rlim_max; 77062306a36Sopenharmony_ci 77162306a36Sopenharmony_ci stack_base = calc_max_stack_size(stack_base); 77262306a36Sopenharmony_ci 77362306a36Sopenharmony_ci /* Add space for stack randomization. */ 77462306a36Sopenharmony_ci stack_base += (STACK_RND_MASK << PAGE_SHIFT); 77562306a36Sopenharmony_ci 77662306a36Sopenharmony_ci /* Make sure we didn't let the argument array grow too large. */ 77762306a36Sopenharmony_ci if (vma->vm_end - vma->vm_start > stack_base) 77862306a36Sopenharmony_ci return -ENOMEM; 77962306a36Sopenharmony_ci 78062306a36Sopenharmony_ci stack_base = PAGE_ALIGN(stack_top - stack_base); 78162306a36Sopenharmony_ci 78262306a36Sopenharmony_ci stack_shift = vma->vm_start - stack_base; 78362306a36Sopenharmony_ci mm->arg_start = bprm->p - stack_shift; 78462306a36Sopenharmony_ci bprm->p = vma->vm_end - stack_shift; 78562306a36Sopenharmony_ci#else 78662306a36Sopenharmony_ci stack_top = arch_align_stack(stack_top); 78762306a36Sopenharmony_ci stack_top = PAGE_ALIGN(stack_top); 78862306a36Sopenharmony_ci 78962306a36Sopenharmony_ci if (unlikely(stack_top < mmap_min_addr) || 79062306a36Sopenharmony_ci unlikely(vma->vm_end - vma->vm_start >= stack_top - mmap_min_addr)) 79162306a36Sopenharmony_ci return -ENOMEM; 79262306a36Sopenharmony_ci 79362306a36Sopenharmony_ci stack_shift = vma->vm_end - stack_top; 79462306a36Sopenharmony_ci 79562306a36Sopenharmony_ci bprm->p -= stack_shift; 79662306a36Sopenharmony_ci mm->arg_start = bprm->p; 79762306a36Sopenharmony_ci#endif 79862306a36Sopenharmony_ci 79962306a36Sopenharmony_ci if (bprm->loader) 80062306a36Sopenharmony_ci bprm->loader -= stack_shift; 80162306a36Sopenharmony_ci bprm->exec -= stack_shift; 80262306a36Sopenharmony_ci 80362306a36Sopenharmony_ci if (mmap_write_lock_killable(mm)) 80462306a36Sopenharmony_ci return -EINTR; 80562306a36Sopenharmony_ci 80662306a36Sopenharmony_ci vm_flags = VM_STACK_FLAGS; 80762306a36Sopenharmony_ci 80862306a36Sopenharmony_ci /* 80962306a36Sopenharmony_ci * Adjust stack execute permissions; explicitly enable for 81062306a36Sopenharmony_ci * EXSTACK_ENABLE_X, disable for EXSTACK_DISABLE_X and leave alone 81162306a36Sopenharmony_ci * (arch default) otherwise. 81262306a36Sopenharmony_ci */ 81362306a36Sopenharmony_ci if (unlikely(executable_stack == EXSTACK_ENABLE_X)) 81462306a36Sopenharmony_ci vm_flags |= VM_EXEC; 81562306a36Sopenharmony_ci else if (executable_stack == EXSTACK_DISABLE_X) 81662306a36Sopenharmony_ci vm_flags &= ~VM_EXEC; 81762306a36Sopenharmony_ci vm_flags |= mm->def_flags; 81862306a36Sopenharmony_ci vm_flags |= VM_STACK_INCOMPLETE_SETUP; 81962306a36Sopenharmony_ci 82062306a36Sopenharmony_ci vma_iter_init(&vmi, mm, vma->vm_start); 82162306a36Sopenharmony_ci 82262306a36Sopenharmony_ci tlb_gather_mmu(&tlb, mm); 82362306a36Sopenharmony_ci ret = mprotect_fixup(&vmi, &tlb, vma, &prev, vma->vm_start, vma->vm_end, 82462306a36Sopenharmony_ci vm_flags); 82562306a36Sopenharmony_ci tlb_finish_mmu(&tlb); 82662306a36Sopenharmony_ci 82762306a36Sopenharmony_ci if (ret) 82862306a36Sopenharmony_ci goto out_unlock; 82962306a36Sopenharmony_ci BUG_ON(prev != vma); 83062306a36Sopenharmony_ci 83162306a36Sopenharmony_ci if (unlikely(vm_flags & VM_EXEC)) { 83262306a36Sopenharmony_ci pr_warn_once("process '%pD4' started with executable stack\n", 83362306a36Sopenharmony_ci bprm->file); 83462306a36Sopenharmony_ci } 83562306a36Sopenharmony_ci 83662306a36Sopenharmony_ci /* Move stack pages down in memory. */ 83762306a36Sopenharmony_ci if (stack_shift) { 83862306a36Sopenharmony_ci ret = shift_arg_pages(vma, stack_shift); 83962306a36Sopenharmony_ci if (ret) 84062306a36Sopenharmony_ci goto out_unlock; 84162306a36Sopenharmony_ci } 84262306a36Sopenharmony_ci 84362306a36Sopenharmony_ci /* mprotect_fixup is overkill to remove the temporary stack flags */ 84462306a36Sopenharmony_ci vm_flags_clear(vma, VM_STACK_INCOMPLETE_SETUP); 84562306a36Sopenharmony_ci 84662306a36Sopenharmony_ci stack_expand = 131072UL; /* randomly 32*4k (or 2*64k) pages */ 84762306a36Sopenharmony_ci stack_size = vma->vm_end - vma->vm_start; 84862306a36Sopenharmony_ci /* 84962306a36Sopenharmony_ci * Align this down to a page boundary as expand_stack 85062306a36Sopenharmony_ci * will align it up. 85162306a36Sopenharmony_ci */ 85262306a36Sopenharmony_ci rlim_stack = bprm->rlim_stack.rlim_cur & PAGE_MASK; 85362306a36Sopenharmony_ci 85462306a36Sopenharmony_ci stack_expand = min(rlim_stack, stack_size + stack_expand); 85562306a36Sopenharmony_ci 85662306a36Sopenharmony_ci#ifdef CONFIG_STACK_GROWSUP 85762306a36Sopenharmony_ci stack_base = vma->vm_start + stack_expand; 85862306a36Sopenharmony_ci#else 85962306a36Sopenharmony_ci stack_base = vma->vm_end - stack_expand; 86062306a36Sopenharmony_ci#endif 86162306a36Sopenharmony_ci current->mm->start_stack = bprm->p; 86262306a36Sopenharmony_ci ret = expand_stack_locked(vma, stack_base); 86362306a36Sopenharmony_ci if (ret) 86462306a36Sopenharmony_ci ret = -EFAULT; 86562306a36Sopenharmony_ci 86662306a36Sopenharmony_ciout_unlock: 86762306a36Sopenharmony_ci mmap_write_unlock(mm); 86862306a36Sopenharmony_ci return ret; 86962306a36Sopenharmony_ci} 87062306a36Sopenharmony_ciEXPORT_SYMBOL(setup_arg_pages); 87162306a36Sopenharmony_ci 87262306a36Sopenharmony_ci#else 87362306a36Sopenharmony_ci 87462306a36Sopenharmony_ci/* 87562306a36Sopenharmony_ci * Transfer the program arguments and environment from the holding pages 87662306a36Sopenharmony_ci * onto the stack. The provided stack pointer is adjusted accordingly. 87762306a36Sopenharmony_ci */ 87862306a36Sopenharmony_ciint transfer_args_to_stack(struct linux_binprm *bprm, 87962306a36Sopenharmony_ci unsigned long *sp_location) 88062306a36Sopenharmony_ci{ 88162306a36Sopenharmony_ci unsigned long index, stop, sp; 88262306a36Sopenharmony_ci int ret = 0; 88362306a36Sopenharmony_ci 88462306a36Sopenharmony_ci stop = bprm->p >> PAGE_SHIFT; 88562306a36Sopenharmony_ci sp = *sp_location; 88662306a36Sopenharmony_ci 88762306a36Sopenharmony_ci for (index = MAX_ARG_PAGES - 1; index >= stop; index--) { 88862306a36Sopenharmony_ci unsigned int offset = index == stop ? bprm->p & ~PAGE_MASK : 0; 88962306a36Sopenharmony_ci char *src = kmap_local_page(bprm->page[index]) + offset; 89062306a36Sopenharmony_ci sp -= PAGE_SIZE - offset; 89162306a36Sopenharmony_ci if (copy_to_user((void *) sp, src, PAGE_SIZE - offset) != 0) 89262306a36Sopenharmony_ci ret = -EFAULT; 89362306a36Sopenharmony_ci kunmap_local(src); 89462306a36Sopenharmony_ci if (ret) 89562306a36Sopenharmony_ci goto out; 89662306a36Sopenharmony_ci } 89762306a36Sopenharmony_ci 89862306a36Sopenharmony_ci *sp_location = sp; 89962306a36Sopenharmony_ci 90062306a36Sopenharmony_ciout: 90162306a36Sopenharmony_ci return ret; 90262306a36Sopenharmony_ci} 90362306a36Sopenharmony_ciEXPORT_SYMBOL(transfer_args_to_stack); 90462306a36Sopenharmony_ci 90562306a36Sopenharmony_ci#endif /* CONFIG_MMU */ 90662306a36Sopenharmony_ci 90762306a36Sopenharmony_cistatic struct file *do_open_execat(int fd, struct filename *name, int flags) 90862306a36Sopenharmony_ci{ 90962306a36Sopenharmony_ci struct file *file; 91062306a36Sopenharmony_ci int err; 91162306a36Sopenharmony_ci struct open_flags open_exec_flags = { 91262306a36Sopenharmony_ci .open_flag = O_LARGEFILE | O_RDONLY | __FMODE_EXEC, 91362306a36Sopenharmony_ci .acc_mode = MAY_EXEC, 91462306a36Sopenharmony_ci .intent = LOOKUP_OPEN, 91562306a36Sopenharmony_ci .lookup_flags = LOOKUP_FOLLOW, 91662306a36Sopenharmony_ci }; 91762306a36Sopenharmony_ci 91862306a36Sopenharmony_ci if ((flags & ~(AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH)) != 0) 91962306a36Sopenharmony_ci return ERR_PTR(-EINVAL); 92062306a36Sopenharmony_ci if (flags & AT_SYMLINK_NOFOLLOW) 92162306a36Sopenharmony_ci open_exec_flags.lookup_flags &= ~LOOKUP_FOLLOW; 92262306a36Sopenharmony_ci if (flags & AT_EMPTY_PATH) 92362306a36Sopenharmony_ci open_exec_flags.lookup_flags |= LOOKUP_EMPTY; 92462306a36Sopenharmony_ci 92562306a36Sopenharmony_ci file = do_filp_open(fd, name, &open_exec_flags); 92662306a36Sopenharmony_ci if (IS_ERR(file)) 92762306a36Sopenharmony_ci goto out; 92862306a36Sopenharmony_ci 92962306a36Sopenharmony_ci /* 93062306a36Sopenharmony_ci * may_open() has already checked for this, so it should be 93162306a36Sopenharmony_ci * impossible to trip now. But we need to be extra cautious 93262306a36Sopenharmony_ci * and check again at the very end too. 93362306a36Sopenharmony_ci */ 93462306a36Sopenharmony_ci err = -EACCES; 93562306a36Sopenharmony_ci if (WARN_ON_ONCE(!S_ISREG(file_inode(file)->i_mode) || 93662306a36Sopenharmony_ci path_noexec(&file->f_path))) 93762306a36Sopenharmony_ci goto exit; 93862306a36Sopenharmony_ci 93962306a36Sopenharmony_ci err = deny_write_access(file); 94062306a36Sopenharmony_ci if (err) 94162306a36Sopenharmony_ci goto exit; 94262306a36Sopenharmony_ci 94362306a36Sopenharmony_ciout: 94462306a36Sopenharmony_ci return file; 94562306a36Sopenharmony_ci 94662306a36Sopenharmony_ciexit: 94762306a36Sopenharmony_ci fput(file); 94862306a36Sopenharmony_ci return ERR_PTR(err); 94962306a36Sopenharmony_ci} 95062306a36Sopenharmony_ci 95162306a36Sopenharmony_cistruct file *open_exec(const char *name) 95262306a36Sopenharmony_ci{ 95362306a36Sopenharmony_ci struct filename *filename = getname_kernel(name); 95462306a36Sopenharmony_ci struct file *f = ERR_CAST(filename); 95562306a36Sopenharmony_ci 95662306a36Sopenharmony_ci if (!IS_ERR(filename)) { 95762306a36Sopenharmony_ci f = do_open_execat(AT_FDCWD, filename, 0); 95862306a36Sopenharmony_ci putname(filename); 95962306a36Sopenharmony_ci } 96062306a36Sopenharmony_ci return f; 96162306a36Sopenharmony_ci} 96262306a36Sopenharmony_ciEXPORT_SYMBOL(open_exec); 96362306a36Sopenharmony_ci 96462306a36Sopenharmony_ci#if defined(CONFIG_BINFMT_FLAT) || defined(CONFIG_BINFMT_ELF_FDPIC) 96562306a36Sopenharmony_cissize_t read_code(struct file *file, unsigned long addr, loff_t pos, size_t len) 96662306a36Sopenharmony_ci{ 96762306a36Sopenharmony_ci ssize_t res = vfs_read(file, (void __user *)addr, len, &pos); 96862306a36Sopenharmony_ci if (res > 0) 96962306a36Sopenharmony_ci flush_icache_user_range(addr, addr + len); 97062306a36Sopenharmony_ci return res; 97162306a36Sopenharmony_ci} 97262306a36Sopenharmony_ciEXPORT_SYMBOL(read_code); 97362306a36Sopenharmony_ci#endif 97462306a36Sopenharmony_ci 97562306a36Sopenharmony_ci/* 97662306a36Sopenharmony_ci * Maps the mm_struct mm into the current task struct. 97762306a36Sopenharmony_ci * On success, this function returns with exec_update_lock 97862306a36Sopenharmony_ci * held for writing. 97962306a36Sopenharmony_ci */ 98062306a36Sopenharmony_cistatic int exec_mmap(struct mm_struct *mm) 98162306a36Sopenharmony_ci{ 98262306a36Sopenharmony_ci struct task_struct *tsk; 98362306a36Sopenharmony_ci struct mm_struct *old_mm, *active_mm; 98462306a36Sopenharmony_ci int ret; 98562306a36Sopenharmony_ci 98662306a36Sopenharmony_ci /* Notify parent that we're no longer interested in the old VM */ 98762306a36Sopenharmony_ci tsk = current; 98862306a36Sopenharmony_ci old_mm = current->mm; 98962306a36Sopenharmony_ci exec_mm_release(tsk, old_mm); 99062306a36Sopenharmony_ci if (old_mm) 99162306a36Sopenharmony_ci sync_mm_rss(old_mm); 99262306a36Sopenharmony_ci 99362306a36Sopenharmony_ci ret = down_write_killable(&tsk->signal->exec_update_lock); 99462306a36Sopenharmony_ci if (ret) 99562306a36Sopenharmony_ci return ret; 99662306a36Sopenharmony_ci 99762306a36Sopenharmony_ci if (old_mm) { 99862306a36Sopenharmony_ci /* 99962306a36Sopenharmony_ci * If there is a pending fatal signal perhaps a signal 100062306a36Sopenharmony_ci * whose default action is to create a coredump get 100162306a36Sopenharmony_ci * out and die instead of going through with the exec. 100262306a36Sopenharmony_ci */ 100362306a36Sopenharmony_ci ret = mmap_read_lock_killable(old_mm); 100462306a36Sopenharmony_ci if (ret) { 100562306a36Sopenharmony_ci up_write(&tsk->signal->exec_update_lock); 100662306a36Sopenharmony_ci return ret; 100762306a36Sopenharmony_ci } 100862306a36Sopenharmony_ci } 100962306a36Sopenharmony_ci 101062306a36Sopenharmony_ci task_lock(tsk); 101162306a36Sopenharmony_ci membarrier_exec_mmap(mm); 101262306a36Sopenharmony_ci 101362306a36Sopenharmony_ci local_irq_disable(); 101462306a36Sopenharmony_ci active_mm = tsk->active_mm; 101562306a36Sopenharmony_ci tsk->active_mm = mm; 101662306a36Sopenharmony_ci tsk->mm = mm; 101762306a36Sopenharmony_ci mm_init_cid(mm); 101862306a36Sopenharmony_ci /* 101962306a36Sopenharmony_ci * This prevents preemption while active_mm is being loaded and 102062306a36Sopenharmony_ci * it and mm are being updated, which could cause problems for 102162306a36Sopenharmony_ci * lazy tlb mm refcounting when these are updated by context 102262306a36Sopenharmony_ci * switches. Not all architectures can handle irqs off over 102362306a36Sopenharmony_ci * activate_mm yet. 102462306a36Sopenharmony_ci */ 102562306a36Sopenharmony_ci if (!IS_ENABLED(CONFIG_ARCH_WANT_IRQS_OFF_ACTIVATE_MM)) 102662306a36Sopenharmony_ci local_irq_enable(); 102762306a36Sopenharmony_ci activate_mm(active_mm, mm); 102862306a36Sopenharmony_ci if (IS_ENABLED(CONFIG_ARCH_WANT_IRQS_OFF_ACTIVATE_MM)) 102962306a36Sopenharmony_ci local_irq_enable(); 103062306a36Sopenharmony_ci lru_gen_add_mm(mm); 103162306a36Sopenharmony_ci task_unlock(tsk); 103262306a36Sopenharmony_ci lru_gen_use_mm(mm); 103362306a36Sopenharmony_ci if (old_mm) { 103462306a36Sopenharmony_ci mmap_read_unlock(old_mm); 103562306a36Sopenharmony_ci BUG_ON(active_mm != old_mm); 103662306a36Sopenharmony_ci setmax_mm_hiwater_rss(&tsk->signal->maxrss, old_mm); 103762306a36Sopenharmony_ci mm_update_next_owner(old_mm); 103862306a36Sopenharmony_ci mmput(old_mm); 103962306a36Sopenharmony_ci return 0; 104062306a36Sopenharmony_ci } 104162306a36Sopenharmony_ci mmdrop_lazy_tlb(active_mm); 104262306a36Sopenharmony_ci return 0; 104362306a36Sopenharmony_ci} 104462306a36Sopenharmony_ci 104562306a36Sopenharmony_cistatic int de_thread(struct task_struct *tsk) 104662306a36Sopenharmony_ci{ 104762306a36Sopenharmony_ci struct signal_struct *sig = tsk->signal; 104862306a36Sopenharmony_ci struct sighand_struct *oldsighand = tsk->sighand; 104962306a36Sopenharmony_ci spinlock_t *lock = &oldsighand->siglock; 105062306a36Sopenharmony_ci 105162306a36Sopenharmony_ci if (thread_group_empty(tsk)) 105262306a36Sopenharmony_ci goto no_thread_group; 105362306a36Sopenharmony_ci 105462306a36Sopenharmony_ci /* 105562306a36Sopenharmony_ci * Kill all other threads in the thread group. 105662306a36Sopenharmony_ci */ 105762306a36Sopenharmony_ci spin_lock_irq(lock); 105862306a36Sopenharmony_ci if ((sig->flags & SIGNAL_GROUP_EXIT) || sig->group_exec_task) { 105962306a36Sopenharmony_ci /* 106062306a36Sopenharmony_ci * Another group action in progress, just 106162306a36Sopenharmony_ci * return so that the signal is processed. 106262306a36Sopenharmony_ci */ 106362306a36Sopenharmony_ci spin_unlock_irq(lock); 106462306a36Sopenharmony_ci return -EAGAIN; 106562306a36Sopenharmony_ci } 106662306a36Sopenharmony_ci 106762306a36Sopenharmony_ci sig->group_exec_task = tsk; 106862306a36Sopenharmony_ci sig->notify_count = zap_other_threads(tsk); 106962306a36Sopenharmony_ci if (!thread_group_leader(tsk)) 107062306a36Sopenharmony_ci sig->notify_count--; 107162306a36Sopenharmony_ci 107262306a36Sopenharmony_ci while (sig->notify_count) { 107362306a36Sopenharmony_ci __set_current_state(TASK_KILLABLE); 107462306a36Sopenharmony_ci spin_unlock_irq(lock); 107562306a36Sopenharmony_ci schedule(); 107662306a36Sopenharmony_ci if (__fatal_signal_pending(tsk)) 107762306a36Sopenharmony_ci goto killed; 107862306a36Sopenharmony_ci spin_lock_irq(lock); 107962306a36Sopenharmony_ci } 108062306a36Sopenharmony_ci spin_unlock_irq(lock); 108162306a36Sopenharmony_ci 108262306a36Sopenharmony_ci /* 108362306a36Sopenharmony_ci * At this point all other threads have exited, all we have to 108462306a36Sopenharmony_ci * do is to wait for the thread group leader to become inactive, 108562306a36Sopenharmony_ci * and to assume its PID: 108662306a36Sopenharmony_ci */ 108762306a36Sopenharmony_ci if (!thread_group_leader(tsk)) { 108862306a36Sopenharmony_ci struct task_struct *leader = tsk->group_leader; 108962306a36Sopenharmony_ci 109062306a36Sopenharmony_ci for (;;) { 109162306a36Sopenharmony_ci cgroup_threadgroup_change_begin(tsk); 109262306a36Sopenharmony_ci write_lock_irq(&tasklist_lock); 109362306a36Sopenharmony_ci /* 109462306a36Sopenharmony_ci * Do this under tasklist_lock to ensure that 109562306a36Sopenharmony_ci * exit_notify() can't miss ->group_exec_task 109662306a36Sopenharmony_ci */ 109762306a36Sopenharmony_ci sig->notify_count = -1; 109862306a36Sopenharmony_ci if (likely(leader->exit_state)) 109962306a36Sopenharmony_ci break; 110062306a36Sopenharmony_ci __set_current_state(TASK_KILLABLE); 110162306a36Sopenharmony_ci write_unlock_irq(&tasklist_lock); 110262306a36Sopenharmony_ci cgroup_threadgroup_change_end(tsk); 110362306a36Sopenharmony_ci schedule(); 110462306a36Sopenharmony_ci if (__fatal_signal_pending(tsk)) 110562306a36Sopenharmony_ci goto killed; 110662306a36Sopenharmony_ci } 110762306a36Sopenharmony_ci 110862306a36Sopenharmony_ci /* 110962306a36Sopenharmony_ci * The only record we have of the real-time age of a 111062306a36Sopenharmony_ci * process, regardless of execs it's done, is start_time. 111162306a36Sopenharmony_ci * All the past CPU time is accumulated in signal_struct 111262306a36Sopenharmony_ci * from sister threads now dead. But in this non-leader 111362306a36Sopenharmony_ci * exec, nothing survives from the original leader thread, 111462306a36Sopenharmony_ci * whose birth marks the true age of this process now. 111562306a36Sopenharmony_ci * When we take on its identity by switching to its PID, we 111662306a36Sopenharmony_ci * also take its birthdate (always earlier than our own). 111762306a36Sopenharmony_ci */ 111862306a36Sopenharmony_ci tsk->start_time = leader->start_time; 111962306a36Sopenharmony_ci tsk->start_boottime = leader->start_boottime; 112062306a36Sopenharmony_ci 112162306a36Sopenharmony_ci BUG_ON(!same_thread_group(leader, tsk)); 112262306a36Sopenharmony_ci /* 112362306a36Sopenharmony_ci * An exec() starts a new thread group with the 112462306a36Sopenharmony_ci * TGID of the previous thread group. Rehash the 112562306a36Sopenharmony_ci * two threads with a switched PID, and release 112662306a36Sopenharmony_ci * the former thread group leader: 112762306a36Sopenharmony_ci */ 112862306a36Sopenharmony_ci 112962306a36Sopenharmony_ci /* Become a process group leader with the old leader's pid. 113062306a36Sopenharmony_ci * The old leader becomes a thread of the this thread group. 113162306a36Sopenharmony_ci */ 113262306a36Sopenharmony_ci exchange_tids(tsk, leader); 113362306a36Sopenharmony_ci transfer_pid(leader, tsk, PIDTYPE_TGID); 113462306a36Sopenharmony_ci transfer_pid(leader, tsk, PIDTYPE_PGID); 113562306a36Sopenharmony_ci transfer_pid(leader, tsk, PIDTYPE_SID); 113662306a36Sopenharmony_ci 113762306a36Sopenharmony_ci list_replace_rcu(&leader->tasks, &tsk->tasks); 113862306a36Sopenharmony_ci list_replace_init(&leader->sibling, &tsk->sibling); 113962306a36Sopenharmony_ci 114062306a36Sopenharmony_ci tsk->group_leader = tsk; 114162306a36Sopenharmony_ci leader->group_leader = tsk; 114262306a36Sopenharmony_ci 114362306a36Sopenharmony_ci tsk->exit_signal = SIGCHLD; 114462306a36Sopenharmony_ci leader->exit_signal = -1; 114562306a36Sopenharmony_ci 114662306a36Sopenharmony_ci BUG_ON(leader->exit_state != EXIT_ZOMBIE); 114762306a36Sopenharmony_ci leader->exit_state = EXIT_DEAD; 114862306a36Sopenharmony_ci 114962306a36Sopenharmony_ci /* 115062306a36Sopenharmony_ci * We are going to release_task()->ptrace_unlink() silently, 115162306a36Sopenharmony_ci * the tracer can sleep in do_wait(). EXIT_DEAD guarantees 115262306a36Sopenharmony_ci * the tracer won't block again waiting for this thread. 115362306a36Sopenharmony_ci */ 115462306a36Sopenharmony_ci if (unlikely(leader->ptrace)) 115562306a36Sopenharmony_ci __wake_up_parent(leader, leader->parent); 115662306a36Sopenharmony_ci write_unlock_irq(&tasklist_lock); 115762306a36Sopenharmony_ci cgroup_threadgroup_change_end(tsk); 115862306a36Sopenharmony_ci 115962306a36Sopenharmony_ci release_task(leader); 116062306a36Sopenharmony_ci } 116162306a36Sopenharmony_ci 116262306a36Sopenharmony_ci sig->group_exec_task = NULL; 116362306a36Sopenharmony_ci sig->notify_count = 0; 116462306a36Sopenharmony_ci 116562306a36Sopenharmony_cino_thread_group: 116662306a36Sopenharmony_ci /* we have changed execution domain */ 116762306a36Sopenharmony_ci tsk->exit_signal = SIGCHLD; 116862306a36Sopenharmony_ci 116962306a36Sopenharmony_ci BUG_ON(!thread_group_leader(tsk)); 117062306a36Sopenharmony_ci return 0; 117162306a36Sopenharmony_ci 117262306a36Sopenharmony_cikilled: 117362306a36Sopenharmony_ci /* protects against exit_notify() and __exit_signal() */ 117462306a36Sopenharmony_ci read_lock(&tasklist_lock); 117562306a36Sopenharmony_ci sig->group_exec_task = NULL; 117662306a36Sopenharmony_ci sig->notify_count = 0; 117762306a36Sopenharmony_ci read_unlock(&tasklist_lock); 117862306a36Sopenharmony_ci return -EAGAIN; 117962306a36Sopenharmony_ci} 118062306a36Sopenharmony_ci 118162306a36Sopenharmony_ci 118262306a36Sopenharmony_ci/* 118362306a36Sopenharmony_ci * This function makes sure the current process has its own signal table, 118462306a36Sopenharmony_ci * so that flush_signal_handlers can later reset the handlers without 118562306a36Sopenharmony_ci * disturbing other processes. (Other processes might share the signal 118662306a36Sopenharmony_ci * table via the CLONE_SIGHAND option to clone().) 118762306a36Sopenharmony_ci */ 118862306a36Sopenharmony_cistatic int unshare_sighand(struct task_struct *me) 118962306a36Sopenharmony_ci{ 119062306a36Sopenharmony_ci struct sighand_struct *oldsighand = me->sighand; 119162306a36Sopenharmony_ci 119262306a36Sopenharmony_ci if (refcount_read(&oldsighand->count) != 1) { 119362306a36Sopenharmony_ci struct sighand_struct *newsighand; 119462306a36Sopenharmony_ci /* 119562306a36Sopenharmony_ci * This ->sighand is shared with the CLONE_SIGHAND 119662306a36Sopenharmony_ci * but not CLONE_THREAD task, switch to the new one. 119762306a36Sopenharmony_ci */ 119862306a36Sopenharmony_ci newsighand = kmem_cache_alloc(sighand_cachep, GFP_KERNEL); 119962306a36Sopenharmony_ci if (!newsighand) 120062306a36Sopenharmony_ci return -ENOMEM; 120162306a36Sopenharmony_ci 120262306a36Sopenharmony_ci refcount_set(&newsighand->count, 1); 120362306a36Sopenharmony_ci 120462306a36Sopenharmony_ci write_lock_irq(&tasklist_lock); 120562306a36Sopenharmony_ci spin_lock(&oldsighand->siglock); 120662306a36Sopenharmony_ci memcpy(newsighand->action, oldsighand->action, 120762306a36Sopenharmony_ci sizeof(newsighand->action)); 120862306a36Sopenharmony_ci rcu_assign_pointer(me->sighand, newsighand); 120962306a36Sopenharmony_ci spin_unlock(&oldsighand->siglock); 121062306a36Sopenharmony_ci write_unlock_irq(&tasklist_lock); 121162306a36Sopenharmony_ci 121262306a36Sopenharmony_ci __cleanup_sighand(oldsighand); 121362306a36Sopenharmony_ci } 121462306a36Sopenharmony_ci return 0; 121562306a36Sopenharmony_ci} 121662306a36Sopenharmony_ci 121762306a36Sopenharmony_cichar *__get_task_comm(char *buf, size_t buf_size, struct task_struct *tsk) 121862306a36Sopenharmony_ci{ 121962306a36Sopenharmony_ci task_lock(tsk); 122062306a36Sopenharmony_ci /* Always NUL terminated and zero-padded */ 122162306a36Sopenharmony_ci strscpy_pad(buf, tsk->comm, buf_size); 122262306a36Sopenharmony_ci task_unlock(tsk); 122362306a36Sopenharmony_ci return buf; 122462306a36Sopenharmony_ci} 122562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(__get_task_comm); 122662306a36Sopenharmony_ci 122762306a36Sopenharmony_ci/* 122862306a36Sopenharmony_ci * These functions flushes out all traces of the currently running executable 122962306a36Sopenharmony_ci * so that a new one can be started 123062306a36Sopenharmony_ci */ 123162306a36Sopenharmony_ci 123262306a36Sopenharmony_civoid __set_task_comm(struct task_struct *tsk, const char *buf, bool exec) 123362306a36Sopenharmony_ci{ 123462306a36Sopenharmony_ci task_lock(tsk); 123562306a36Sopenharmony_ci trace_task_rename(tsk, buf); 123662306a36Sopenharmony_ci strscpy_pad(tsk->comm, buf, sizeof(tsk->comm)); 123762306a36Sopenharmony_ci task_unlock(tsk); 123862306a36Sopenharmony_ci perf_event_comm(tsk, exec); 123962306a36Sopenharmony_ci} 124062306a36Sopenharmony_ci 124162306a36Sopenharmony_ci/* 124262306a36Sopenharmony_ci * Calling this is the point of no return. None of the failures will be 124362306a36Sopenharmony_ci * seen by userspace since either the process is already taking a fatal 124462306a36Sopenharmony_ci * signal (via de_thread() or coredump), or will have SEGV raised 124562306a36Sopenharmony_ci * (after exec_mmap()) by search_binary_handler (see below). 124662306a36Sopenharmony_ci */ 124762306a36Sopenharmony_ciint begin_new_exec(struct linux_binprm * bprm) 124862306a36Sopenharmony_ci{ 124962306a36Sopenharmony_ci struct task_struct *me = current; 125062306a36Sopenharmony_ci int retval; 125162306a36Sopenharmony_ci 125262306a36Sopenharmony_ci /* Once we are committed compute the creds */ 125362306a36Sopenharmony_ci retval = bprm_creds_from_file(bprm); 125462306a36Sopenharmony_ci if (retval) 125562306a36Sopenharmony_ci return retval; 125662306a36Sopenharmony_ci 125762306a36Sopenharmony_ci /* 125862306a36Sopenharmony_ci * Ensure all future errors are fatal. 125962306a36Sopenharmony_ci */ 126062306a36Sopenharmony_ci bprm->point_of_no_return = true; 126162306a36Sopenharmony_ci 126262306a36Sopenharmony_ci /* 126362306a36Sopenharmony_ci * Make this the only thread in the thread group. 126462306a36Sopenharmony_ci */ 126562306a36Sopenharmony_ci retval = de_thread(me); 126662306a36Sopenharmony_ci if (retval) 126762306a36Sopenharmony_ci goto out; 126862306a36Sopenharmony_ci 126962306a36Sopenharmony_ci /* 127062306a36Sopenharmony_ci * Cancel any io_uring activity across execve 127162306a36Sopenharmony_ci */ 127262306a36Sopenharmony_ci io_uring_task_cancel(); 127362306a36Sopenharmony_ci 127462306a36Sopenharmony_ci /* Ensure the files table is not shared. */ 127562306a36Sopenharmony_ci retval = unshare_files(); 127662306a36Sopenharmony_ci if (retval) 127762306a36Sopenharmony_ci goto out; 127862306a36Sopenharmony_ci 127962306a36Sopenharmony_ci /* 128062306a36Sopenharmony_ci * Must be called _before_ exec_mmap() as bprm->mm is 128162306a36Sopenharmony_ci * not visible until then. Doing it here also ensures 128262306a36Sopenharmony_ci * we don't race against replace_mm_exe_file(). 128362306a36Sopenharmony_ci */ 128462306a36Sopenharmony_ci retval = set_mm_exe_file(bprm->mm, bprm->file); 128562306a36Sopenharmony_ci if (retval) 128662306a36Sopenharmony_ci goto out; 128762306a36Sopenharmony_ci 128862306a36Sopenharmony_ci /* If the binary is not readable then enforce mm->dumpable=0 */ 128962306a36Sopenharmony_ci would_dump(bprm, bprm->file); 129062306a36Sopenharmony_ci if (bprm->have_execfd) 129162306a36Sopenharmony_ci would_dump(bprm, bprm->executable); 129262306a36Sopenharmony_ci 129362306a36Sopenharmony_ci /* 129462306a36Sopenharmony_ci * Release all of the old mmap stuff 129562306a36Sopenharmony_ci */ 129662306a36Sopenharmony_ci acct_arg_size(bprm, 0); 129762306a36Sopenharmony_ci retval = exec_mmap(bprm->mm); 129862306a36Sopenharmony_ci if (retval) 129962306a36Sopenharmony_ci goto out; 130062306a36Sopenharmony_ci 130162306a36Sopenharmony_ci bprm->mm = NULL; 130262306a36Sopenharmony_ci 130362306a36Sopenharmony_ci retval = exec_task_namespaces(); 130462306a36Sopenharmony_ci if (retval) 130562306a36Sopenharmony_ci goto out_unlock; 130662306a36Sopenharmony_ci 130762306a36Sopenharmony_ci#ifdef CONFIG_POSIX_TIMERS 130862306a36Sopenharmony_ci spin_lock_irq(&me->sighand->siglock); 130962306a36Sopenharmony_ci posix_cpu_timers_exit(me); 131062306a36Sopenharmony_ci spin_unlock_irq(&me->sighand->siglock); 131162306a36Sopenharmony_ci exit_itimers(me); 131262306a36Sopenharmony_ci flush_itimer_signals(); 131362306a36Sopenharmony_ci#endif 131462306a36Sopenharmony_ci 131562306a36Sopenharmony_ci /* 131662306a36Sopenharmony_ci * Make the signal table private. 131762306a36Sopenharmony_ci */ 131862306a36Sopenharmony_ci retval = unshare_sighand(me); 131962306a36Sopenharmony_ci if (retval) 132062306a36Sopenharmony_ci goto out_unlock; 132162306a36Sopenharmony_ci 132262306a36Sopenharmony_ci me->flags &= ~(PF_RANDOMIZE | PF_FORKNOEXEC | 132362306a36Sopenharmony_ci PF_NOFREEZE | PF_NO_SETAFFINITY); 132462306a36Sopenharmony_ci flush_thread(); 132562306a36Sopenharmony_ci me->personality &= ~bprm->per_clear; 132662306a36Sopenharmony_ci 132762306a36Sopenharmony_ci clear_syscall_work_syscall_user_dispatch(me); 132862306a36Sopenharmony_ci 132962306a36Sopenharmony_ci /* 133062306a36Sopenharmony_ci * We have to apply CLOEXEC before we change whether the process is 133162306a36Sopenharmony_ci * dumpable (in setup_new_exec) to avoid a race with a process in userspace 133262306a36Sopenharmony_ci * trying to access the should-be-closed file descriptors of a process 133362306a36Sopenharmony_ci * undergoing exec(2). 133462306a36Sopenharmony_ci */ 133562306a36Sopenharmony_ci do_close_on_exec(me->files); 133662306a36Sopenharmony_ci 133762306a36Sopenharmony_ci if (bprm->secureexec) { 133862306a36Sopenharmony_ci /* Make sure parent cannot signal privileged process. */ 133962306a36Sopenharmony_ci me->pdeath_signal = 0; 134062306a36Sopenharmony_ci 134162306a36Sopenharmony_ci /* 134262306a36Sopenharmony_ci * For secureexec, reset the stack limit to sane default to 134362306a36Sopenharmony_ci * avoid bad behavior from the prior rlimits. This has to 134462306a36Sopenharmony_ci * happen before arch_pick_mmap_layout(), which examines 134562306a36Sopenharmony_ci * RLIMIT_STACK, but after the point of no return to avoid 134662306a36Sopenharmony_ci * needing to clean up the change on failure. 134762306a36Sopenharmony_ci */ 134862306a36Sopenharmony_ci if (bprm->rlim_stack.rlim_cur > _STK_LIM) 134962306a36Sopenharmony_ci bprm->rlim_stack.rlim_cur = _STK_LIM; 135062306a36Sopenharmony_ci } 135162306a36Sopenharmony_ci 135262306a36Sopenharmony_ci me->sas_ss_sp = me->sas_ss_size = 0; 135362306a36Sopenharmony_ci 135462306a36Sopenharmony_ci /* 135562306a36Sopenharmony_ci * Figure out dumpability. Note that this checking only of current 135662306a36Sopenharmony_ci * is wrong, but userspace depends on it. This should be testing 135762306a36Sopenharmony_ci * bprm->secureexec instead. 135862306a36Sopenharmony_ci */ 135962306a36Sopenharmony_ci if (bprm->interp_flags & BINPRM_FLAGS_ENFORCE_NONDUMP || 136062306a36Sopenharmony_ci !(uid_eq(current_euid(), current_uid()) && 136162306a36Sopenharmony_ci gid_eq(current_egid(), current_gid()))) 136262306a36Sopenharmony_ci set_dumpable(current->mm, suid_dumpable); 136362306a36Sopenharmony_ci else 136462306a36Sopenharmony_ci set_dumpable(current->mm, SUID_DUMP_USER); 136562306a36Sopenharmony_ci 136662306a36Sopenharmony_ci perf_event_exec(); 136762306a36Sopenharmony_ci __set_task_comm(me, kbasename(bprm->filename), true); 136862306a36Sopenharmony_ci 136962306a36Sopenharmony_ci /* An exec changes our domain. We are no longer part of the thread 137062306a36Sopenharmony_ci group */ 137162306a36Sopenharmony_ci WRITE_ONCE(me->self_exec_id, me->self_exec_id + 1); 137262306a36Sopenharmony_ci flush_signal_handlers(me, 0); 137362306a36Sopenharmony_ci 137462306a36Sopenharmony_ci retval = set_cred_ucounts(bprm->cred); 137562306a36Sopenharmony_ci if (retval < 0) 137662306a36Sopenharmony_ci goto out_unlock; 137762306a36Sopenharmony_ci 137862306a36Sopenharmony_ci /* 137962306a36Sopenharmony_ci * install the new credentials for this executable 138062306a36Sopenharmony_ci */ 138162306a36Sopenharmony_ci security_bprm_committing_creds(bprm); 138262306a36Sopenharmony_ci 138362306a36Sopenharmony_ci commit_creds(bprm->cred); 138462306a36Sopenharmony_ci bprm->cred = NULL; 138562306a36Sopenharmony_ci 138662306a36Sopenharmony_ci /* 138762306a36Sopenharmony_ci * Disable monitoring for regular users 138862306a36Sopenharmony_ci * when executing setuid binaries. Must 138962306a36Sopenharmony_ci * wait until new credentials are committed 139062306a36Sopenharmony_ci * by commit_creds() above 139162306a36Sopenharmony_ci */ 139262306a36Sopenharmony_ci if (get_dumpable(me->mm) != SUID_DUMP_USER) 139362306a36Sopenharmony_ci perf_event_exit_task(me); 139462306a36Sopenharmony_ci /* 139562306a36Sopenharmony_ci * cred_guard_mutex must be held at least to this point to prevent 139662306a36Sopenharmony_ci * ptrace_attach() from altering our determination of the task's 139762306a36Sopenharmony_ci * credentials; any time after this it may be unlocked. 139862306a36Sopenharmony_ci */ 139962306a36Sopenharmony_ci security_bprm_committed_creds(bprm); 140062306a36Sopenharmony_ci 140162306a36Sopenharmony_ci /* Pass the opened binary to the interpreter. */ 140262306a36Sopenharmony_ci if (bprm->have_execfd) { 140362306a36Sopenharmony_ci retval = get_unused_fd_flags(0); 140462306a36Sopenharmony_ci if (retval < 0) 140562306a36Sopenharmony_ci goto out_unlock; 140662306a36Sopenharmony_ci fd_install(retval, bprm->executable); 140762306a36Sopenharmony_ci bprm->executable = NULL; 140862306a36Sopenharmony_ci bprm->execfd = retval; 140962306a36Sopenharmony_ci } 141062306a36Sopenharmony_ci return 0; 141162306a36Sopenharmony_ci 141262306a36Sopenharmony_ciout_unlock: 141362306a36Sopenharmony_ci up_write(&me->signal->exec_update_lock); 141462306a36Sopenharmony_ci if (!bprm->cred) 141562306a36Sopenharmony_ci mutex_unlock(&me->signal->cred_guard_mutex); 141662306a36Sopenharmony_ci 141762306a36Sopenharmony_ciout: 141862306a36Sopenharmony_ci return retval; 141962306a36Sopenharmony_ci} 142062306a36Sopenharmony_ciEXPORT_SYMBOL(begin_new_exec); 142162306a36Sopenharmony_ci 142262306a36Sopenharmony_civoid would_dump(struct linux_binprm *bprm, struct file *file) 142362306a36Sopenharmony_ci{ 142462306a36Sopenharmony_ci struct inode *inode = file_inode(file); 142562306a36Sopenharmony_ci struct mnt_idmap *idmap = file_mnt_idmap(file); 142662306a36Sopenharmony_ci if (inode_permission(idmap, inode, MAY_READ) < 0) { 142762306a36Sopenharmony_ci struct user_namespace *old, *user_ns; 142862306a36Sopenharmony_ci bprm->interp_flags |= BINPRM_FLAGS_ENFORCE_NONDUMP; 142962306a36Sopenharmony_ci 143062306a36Sopenharmony_ci /* Ensure mm->user_ns contains the executable */ 143162306a36Sopenharmony_ci user_ns = old = bprm->mm->user_ns; 143262306a36Sopenharmony_ci while ((user_ns != &init_user_ns) && 143362306a36Sopenharmony_ci !privileged_wrt_inode_uidgid(user_ns, idmap, inode)) 143462306a36Sopenharmony_ci user_ns = user_ns->parent; 143562306a36Sopenharmony_ci 143662306a36Sopenharmony_ci if (old != user_ns) { 143762306a36Sopenharmony_ci bprm->mm->user_ns = get_user_ns(user_ns); 143862306a36Sopenharmony_ci put_user_ns(old); 143962306a36Sopenharmony_ci } 144062306a36Sopenharmony_ci } 144162306a36Sopenharmony_ci} 144262306a36Sopenharmony_ciEXPORT_SYMBOL(would_dump); 144362306a36Sopenharmony_ci 144462306a36Sopenharmony_civoid setup_new_exec(struct linux_binprm * bprm) 144562306a36Sopenharmony_ci{ 144662306a36Sopenharmony_ci /* Setup things that can depend upon the personality */ 144762306a36Sopenharmony_ci struct task_struct *me = current; 144862306a36Sopenharmony_ci 144962306a36Sopenharmony_ci arch_pick_mmap_layout(me->mm, &bprm->rlim_stack); 145062306a36Sopenharmony_ci 145162306a36Sopenharmony_ci arch_setup_new_exec(); 145262306a36Sopenharmony_ci 145362306a36Sopenharmony_ci /* Set the new mm task size. We have to do that late because it may 145462306a36Sopenharmony_ci * depend on TIF_32BIT which is only updated in flush_thread() on 145562306a36Sopenharmony_ci * some architectures like powerpc 145662306a36Sopenharmony_ci */ 145762306a36Sopenharmony_ci me->mm->task_size = TASK_SIZE; 145862306a36Sopenharmony_ci up_write(&me->signal->exec_update_lock); 145962306a36Sopenharmony_ci mutex_unlock(&me->signal->cred_guard_mutex); 146062306a36Sopenharmony_ci} 146162306a36Sopenharmony_ciEXPORT_SYMBOL(setup_new_exec); 146262306a36Sopenharmony_ci 146362306a36Sopenharmony_ci/* Runs immediately before start_thread() takes over. */ 146462306a36Sopenharmony_civoid finalize_exec(struct linux_binprm *bprm) 146562306a36Sopenharmony_ci{ 146662306a36Sopenharmony_ci /* Store any stack rlimit changes before starting thread. */ 146762306a36Sopenharmony_ci task_lock(current->group_leader); 146862306a36Sopenharmony_ci current->signal->rlim[RLIMIT_STACK] = bprm->rlim_stack; 146962306a36Sopenharmony_ci task_unlock(current->group_leader); 147062306a36Sopenharmony_ci} 147162306a36Sopenharmony_ciEXPORT_SYMBOL(finalize_exec); 147262306a36Sopenharmony_ci 147362306a36Sopenharmony_ci/* 147462306a36Sopenharmony_ci * Prepare credentials and lock ->cred_guard_mutex. 147562306a36Sopenharmony_ci * setup_new_exec() commits the new creds and drops the lock. 147662306a36Sopenharmony_ci * Or, if exec fails before, free_bprm() should release ->cred 147762306a36Sopenharmony_ci * and unlock. 147862306a36Sopenharmony_ci */ 147962306a36Sopenharmony_cistatic int prepare_bprm_creds(struct linux_binprm *bprm) 148062306a36Sopenharmony_ci{ 148162306a36Sopenharmony_ci if (mutex_lock_interruptible(¤t->signal->cred_guard_mutex)) 148262306a36Sopenharmony_ci return -ERESTARTNOINTR; 148362306a36Sopenharmony_ci 148462306a36Sopenharmony_ci bprm->cred = prepare_exec_creds(); 148562306a36Sopenharmony_ci if (likely(bprm->cred)) 148662306a36Sopenharmony_ci return 0; 148762306a36Sopenharmony_ci 148862306a36Sopenharmony_ci mutex_unlock(¤t->signal->cred_guard_mutex); 148962306a36Sopenharmony_ci return -ENOMEM; 149062306a36Sopenharmony_ci} 149162306a36Sopenharmony_ci 149262306a36Sopenharmony_cistatic void free_bprm(struct linux_binprm *bprm) 149362306a36Sopenharmony_ci{ 149462306a36Sopenharmony_ci if (bprm->mm) { 149562306a36Sopenharmony_ci acct_arg_size(bprm, 0); 149662306a36Sopenharmony_ci mmput(bprm->mm); 149762306a36Sopenharmony_ci } 149862306a36Sopenharmony_ci free_arg_pages(bprm); 149962306a36Sopenharmony_ci if (bprm->cred) { 150062306a36Sopenharmony_ci mutex_unlock(¤t->signal->cred_guard_mutex); 150162306a36Sopenharmony_ci abort_creds(bprm->cred); 150262306a36Sopenharmony_ci } 150362306a36Sopenharmony_ci if (bprm->file) { 150462306a36Sopenharmony_ci allow_write_access(bprm->file); 150562306a36Sopenharmony_ci fput(bprm->file); 150662306a36Sopenharmony_ci } 150762306a36Sopenharmony_ci if (bprm->executable) 150862306a36Sopenharmony_ci fput(bprm->executable); 150962306a36Sopenharmony_ci /* If a binfmt changed the interp, free it. */ 151062306a36Sopenharmony_ci if (bprm->interp != bprm->filename) 151162306a36Sopenharmony_ci kfree(bprm->interp); 151262306a36Sopenharmony_ci kfree(bprm->fdpath); 151362306a36Sopenharmony_ci kfree(bprm); 151462306a36Sopenharmony_ci} 151562306a36Sopenharmony_ci 151662306a36Sopenharmony_cistatic struct linux_binprm *alloc_bprm(int fd, struct filename *filename) 151762306a36Sopenharmony_ci{ 151862306a36Sopenharmony_ci struct linux_binprm *bprm = kzalloc(sizeof(*bprm), GFP_KERNEL); 151962306a36Sopenharmony_ci int retval = -ENOMEM; 152062306a36Sopenharmony_ci if (!bprm) 152162306a36Sopenharmony_ci goto out; 152262306a36Sopenharmony_ci 152362306a36Sopenharmony_ci if (fd == AT_FDCWD || filename->name[0] == '/') { 152462306a36Sopenharmony_ci bprm->filename = filename->name; 152562306a36Sopenharmony_ci } else { 152662306a36Sopenharmony_ci if (filename->name[0] == '\0') 152762306a36Sopenharmony_ci bprm->fdpath = kasprintf(GFP_KERNEL, "/dev/fd/%d", fd); 152862306a36Sopenharmony_ci else 152962306a36Sopenharmony_ci bprm->fdpath = kasprintf(GFP_KERNEL, "/dev/fd/%d/%s", 153062306a36Sopenharmony_ci fd, filename->name); 153162306a36Sopenharmony_ci if (!bprm->fdpath) 153262306a36Sopenharmony_ci goto out_free; 153362306a36Sopenharmony_ci 153462306a36Sopenharmony_ci bprm->filename = bprm->fdpath; 153562306a36Sopenharmony_ci } 153662306a36Sopenharmony_ci bprm->interp = bprm->filename; 153762306a36Sopenharmony_ci 153862306a36Sopenharmony_ci retval = bprm_mm_init(bprm); 153962306a36Sopenharmony_ci if (retval) 154062306a36Sopenharmony_ci goto out_free; 154162306a36Sopenharmony_ci return bprm; 154262306a36Sopenharmony_ci 154362306a36Sopenharmony_ciout_free: 154462306a36Sopenharmony_ci free_bprm(bprm); 154562306a36Sopenharmony_ciout: 154662306a36Sopenharmony_ci return ERR_PTR(retval); 154762306a36Sopenharmony_ci} 154862306a36Sopenharmony_ci 154962306a36Sopenharmony_ciint bprm_change_interp(const char *interp, struct linux_binprm *bprm) 155062306a36Sopenharmony_ci{ 155162306a36Sopenharmony_ci /* If a binfmt changed the interp, free it first. */ 155262306a36Sopenharmony_ci if (bprm->interp != bprm->filename) 155362306a36Sopenharmony_ci kfree(bprm->interp); 155462306a36Sopenharmony_ci bprm->interp = kstrdup(interp, GFP_KERNEL); 155562306a36Sopenharmony_ci if (!bprm->interp) 155662306a36Sopenharmony_ci return -ENOMEM; 155762306a36Sopenharmony_ci return 0; 155862306a36Sopenharmony_ci} 155962306a36Sopenharmony_ciEXPORT_SYMBOL(bprm_change_interp); 156062306a36Sopenharmony_ci 156162306a36Sopenharmony_ci/* 156262306a36Sopenharmony_ci * determine how safe it is to execute the proposed program 156362306a36Sopenharmony_ci * - the caller must hold ->cred_guard_mutex to protect against 156462306a36Sopenharmony_ci * PTRACE_ATTACH or seccomp thread-sync 156562306a36Sopenharmony_ci */ 156662306a36Sopenharmony_cistatic void check_unsafe_exec(struct linux_binprm *bprm) 156762306a36Sopenharmony_ci{ 156862306a36Sopenharmony_ci struct task_struct *p = current, *t; 156962306a36Sopenharmony_ci unsigned n_fs; 157062306a36Sopenharmony_ci 157162306a36Sopenharmony_ci if (p->ptrace) 157262306a36Sopenharmony_ci bprm->unsafe |= LSM_UNSAFE_PTRACE; 157362306a36Sopenharmony_ci 157462306a36Sopenharmony_ci /* 157562306a36Sopenharmony_ci * This isn't strictly necessary, but it makes it harder for LSMs to 157662306a36Sopenharmony_ci * mess up. 157762306a36Sopenharmony_ci */ 157862306a36Sopenharmony_ci if (task_no_new_privs(current)) 157962306a36Sopenharmony_ci bprm->unsafe |= LSM_UNSAFE_NO_NEW_PRIVS; 158062306a36Sopenharmony_ci 158162306a36Sopenharmony_ci /* 158262306a36Sopenharmony_ci * If another task is sharing our fs, we cannot safely 158362306a36Sopenharmony_ci * suid exec because the differently privileged task 158462306a36Sopenharmony_ci * will be able to manipulate the current directory, etc. 158562306a36Sopenharmony_ci * It would be nice to force an unshare instead... 158662306a36Sopenharmony_ci */ 158762306a36Sopenharmony_ci t = p; 158862306a36Sopenharmony_ci n_fs = 1; 158962306a36Sopenharmony_ci spin_lock(&p->fs->lock); 159062306a36Sopenharmony_ci rcu_read_lock(); 159162306a36Sopenharmony_ci while_each_thread(p, t) { 159262306a36Sopenharmony_ci if (t->fs == p->fs) 159362306a36Sopenharmony_ci n_fs++; 159462306a36Sopenharmony_ci } 159562306a36Sopenharmony_ci rcu_read_unlock(); 159662306a36Sopenharmony_ci 159762306a36Sopenharmony_ci if (p->fs->users > n_fs) 159862306a36Sopenharmony_ci bprm->unsafe |= LSM_UNSAFE_SHARE; 159962306a36Sopenharmony_ci else 160062306a36Sopenharmony_ci p->fs->in_exec = 1; 160162306a36Sopenharmony_ci spin_unlock(&p->fs->lock); 160262306a36Sopenharmony_ci} 160362306a36Sopenharmony_ci 160462306a36Sopenharmony_cistatic void bprm_fill_uid(struct linux_binprm *bprm, struct file *file) 160562306a36Sopenharmony_ci{ 160662306a36Sopenharmony_ci /* Handle suid and sgid on files */ 160762306a36Sopenharmony_ci struct mnt_idmap *idmap; 160862306a36Sopenharmony_ci struct inode *inode = file_inode(file); 160962306a36Sopenharmony_ci unsigned int mode; 161062306a36Sopenharmony_ci vfsuid_t vfsuid; 161162306a36Sopenharmony_ci vfsgid_t vfsgid; 161262306a36Sopenharmony_ci 161362306a36Sopenharmony_ci if (!mnt_may_suid(file->f_path.mnt)) 161462306a36Sopenharmony_ci return; 161562306a36Sopenharmony_ci 161662306a36Sopenharmony_ci if (task_no_new_privs(current)) 161762306a36Sopenharmony_ci return; 161862306a36Sopenharmony_ci 161962306a36Sopenharmony_ci mode = READ_ONCE(inode->i_mode); 162062306a36Sopenharmony_ci if (!(mode & (S_ISUID|S_ISGID))) 162162306a36Sopenharmony_ci return; 162262306a36Sopenharmony_ci 162362306a36Sopenharmony_ci idmap = file_mnt_idmap(file); 162462306a36Sopenharmony_ci 162562306a36Sopenharmony_ci /* Be careful if suid/sgid is set */ 162662306a36Sopenharmony_ci inode_lock(inode); 162762306a36Sopenharmony_ci 162862306a36Sopenharmony_ci /* reload atomically mode/uid/gid now that lock held */ 162962306a36Sopenharmony_ci mode = inode->i_mode; 163062306a36Sopenharmony_ci vfsuid = i_uid_into_vfsuid(idmap, inode); 163162306a36Sopenharmony_ci vfsgid = i_gid_into_vfsgid(idmap, inode); 163262306a36Sopenharmony_ci inode_unlock(inode); 163362306a36Sopenharmony_ci 163462306a36Sopenharmony_ci /* We ignore suid/sgid if there are no mappings for them in the ns */ 163562306a36Sopenharmony_ci if (!vfsuid_has_mapping(bprm->cred->user_ns, vfsuid) || 163662306a36Sopenharmony_ci !vfsgid_has_mapping(bprm->cred->user_ns, vfsgid)) 163762306a36Sopenharmony_ci return; 163862306a36Sopenharmony_ci 163962306a36Sopenharmony_ci if (mode & S_ISUID) { 164062306a36Sopenharmony_ci bprm->per_clear |= PER_CLEAR_ON_SETID; 164162306a36Sopenharmony_ci bprm->cred->euid = vfsuid_into_kuid(vfsuid); 164262306a36Sopenharmony_ci } 164362306a36Sopenharmony_ci 164462306a36Sopenharmony_ci if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) { 164562306a36Sopenharmony_ci bprm->per_clear |= PER_CLEAR_ON_SETID; 164662306a36Sopenharmony_ci bprm->cred->egid = vfsgid_into_kgid(vfsgid); 164762306a36Sopenharmony_ci } 164862306a36Sopenharmony_ci} 164962306a36Sopenharmony_ci 165062306a36Sopenharmony_ci/* 165162306a36Sopenharmony_ci * Compute brpm->cred based upon the final binary. 165262306a36Sopenharmony_ci */ 165362306a36Sopenharmony_cistatic int bprm_creds_from_file(struct linux_binprm *bprm) 165462306a36Sopenharmony_ci{ 165562306a36Sopenharmony_ci /* Compute creds based on which file? */ 165662306a36Sopenharmony_ci struct file *file = bprm->execfd_creds ? bprm->executable : bprm->file; 165762306a36Sopenharmony_ci 165862306a36Sopenharmony_ci bprm_fill_uid(bprm, file); 165962306a36Sopenharmony_ci return security_bprm_creds_from_file(bprm, file); 166062306a36Sopenharmony_ci} 166162306a36Sopenharmony_ci 166262306a36Sopenharmony_ci/* 166362306a36Sopenharmony_ci * Fill the binprm structure from the inode. 166462306a36Sopenharmony_ci * Read the first BINPRM_BUF_SIZE bytes 166562306a36Sopenharmony_ci * 166662306a36Sopenharmony_ci * This may be called multiple times for binary chains (scripts for example). 166762306a36Sopenharmony_ci */ 166862306a36Sopenharmony_cistatic int prepare_binprm(struct linux_binprm *bprm) 166962306a36Sopenharmony_ci{ 167062306a36Sopenharmony_ci loff_t pos = 0; 167162306a36Sopenharmony_ci 167262306a36Sopenharmony_ci memset(bprm->buf, 0, BINPRM_BUF_SIZE); 167362306a36Sopenharmony_ci return kernel_read(bprm->file, bprm->buf, BINPRM_BUF_SIZE, &pos); 167462306a36Sopenharmony_ci} 167562306a36Sopenharmony_ci 167662306a36Sopenharmony_ci/* 167762306a36Sopenharmony_ci * Arguments are '\0' separated strings found at the location bprm->p 167862306a36Sopenharmony_ci * points to; chop off the first by relocating brpm->p to right after 167962306a36Sopenharmony_ci * the first '\0' encountered. 168062306a36Sopenharmony_ci */ 168162306a36Sopenharmony_ciint remove_arg_zero(struct linux_binprm *bprm) 168262306a36Sopenharmony_ci{ 168362306a36Sopenharmony_ci int ret = 0; 168462306a36Sopenharmony_ci unsigned long offset; 168562306a36Sopenharmony_ci char *kaddr; 168662306a36Sopenharmony_ci struct page *page; 168762306a36Sopenharmony_ci 168862306a36Sopenharmony_ci if (!bprm->argc) 168962306a36Sopenharmony_ci return 0; 169062306a36Sopenharmony_ci 169162306a36Sopenharmony_ci do { 169262306a36Sopenharmony_ci offset = bprm->p & ~PAGE_MASK; 169362306a36Sopenharmony_ci page = get_arg_page(bprm, bprm->p, 0); 169462306a36Sopenharmony_ci if (!page) { 169562306a36Sopenharmony_ci ret = -EFAULT; 169662306a36Sopenharmony_ci goto out; 169762306a36Sopenharmony_ci } 169862306a36Sopenharmony_ci kaddr = kmap_local_page(page); 169962306a36Sopenharmony_ci 170062306a36Sopenharmony_ci for (; offset < PAGE_SIZE && kaddr[offset]; 170162306a36Sopenharmony_ci offset++, bprm->p++) 170262306a36Sopenharmony_ci ; 170362306a36Sopenharmony_ci 170462306a36Sopenharmony_ci kunmap_local(kaddr); 170562306a36Sopenharmony_ci put_arg_page(page); 170662306a36Sopenharmony_ci } while (offset == PAGE_SIZE); 170762306a36Sopenharmony_ci 170862306a36Sopenharmony_ci bprm->p++; 170962306a36Sopenharmony_ci bprm->argc--; 171062306a36Sopenharmony_ci ret = 0; 171162306a36Sopenharmony_ci 171262306a36Sopenharmony_ciout: 171362306a36Sopenharmony_ci return ret; 171462306a36Sopenharmony_ci} 171562306a36Sopenharmony_ciEXPORT_SYMBOL(remove_arg_zero); 171662306a36Sopenharmony_ci 171762306a36Sopenharmony_ci#define printable(c) (((c)=='\t') || ((c)=='\n') || (0x20<=(c) && (c)<=0x7e)) 171862306a36Sopenharmony_ci/* 171962306a36Sopenharmony_ci * cycle the list of binary formats handler, until one recognizes the image 172062306a36Sopenharmony_ci */ 172162306a36Sopenharmony_cistatic int search_binary_handler(struct linux_binprm *bprm) 172262306a36Sopenharmony_ci{ 172362306a36Sopenharmony_ci bool need_retry = IS_ENABLED(CONFIG_MODULES); 172462306a36Sopenharmony_ci struct linux_binfmt *fmt; 172562306a36Sopenharmony_ci int retval; 172662306a36Sopenharmony_ci 172762306a36Sopenharmony_ci retval = prepare_binprm(bprm); 172862306a36Sopenharmony_ci if (retval < 0) 172962306a36Sopenharmony_ci return retval; 173062306a36Sopenharmony_ci 173162306a36Sopenharmony_ci retval = security_bprm_check(bprm); 173262306a36Sopenharmony_ci if (retval) 173362306a36Sopenharmony_ci return retval; 173462306a36Sopenharmony_ci 173562306a36Sopenharmony_ci retval = -ENOENT; 173662306a36Sopenharmony_ci retry: 173762306a36Sopenharmony_ci read_lock(&binfmt_lock); 173862306a36Sopenharmony_ci list_for_each_entry(fmt, &formats, lh) { 173962306a36Sopenharmony_ci if (!try_module_get(fmt->module)) 174062306a36Sopenharmony_ci continue; 174162306a36Sopenharmony_ci read_unlock(&binfmt_lock); 174262306a36Sopenharmony_ci 174362306a36Sopenharmony_ci retval = fmt->load_binary(bprm); 174462306a36Sopenharmony_ci 174562306a36Sopenharmony_ci read_lock(&binfmt_lock); 174662306a36Sopenharmony_ci put_binfmt(fmt); 174762306a36Sopenharmony_ci if (bprm->point_of_no_return || (retval != -ENOEXEC)) { 174862306a36Sopenharmony_ci read_unlock(&binfmt_lock); 174962306a36Sopenharmony_ci return retval; 175062306a36Sopenharmony_ci } 175162306a36Sopenharmony_ci } 175262306a36Sopenharmony_ci read_unlock(&binfmt_lock); 175362306a36Sopenharmony_ci 175462306a36Sopenharmony_ci if (need_retry) { 175562306a36Sopenharmony_ci if (printable(bprm->buf[0]) && printable(bprm->buf[1]) && 175662306a36Sopenharmony_ci printable(bprm->buf[2]) && printable(bprm->buf[3])) 175762306a36Sopenharmony_ci return retval; 175862306a36Sopenharmony_ci if (request_module("binfmt-%04x", *(ushort *)(bprm->buf + 2)) < 0) 175962306a36Sopenharmony_ci return retval; 176062306a36Sopenharmony_ci need_retry = false; 176162306a36Sopenharmony_ci goto retry; 176262306a36Sopenharmony_ci } 176362306a36Sopenharmony_ci 176462306a36Sopenharmony_ci return retval; 176562306a36Sopenharmony_ci} 176662306a36Sopenharmony_ci 176762306a36Sopenharmony_ci/* binfmt handlers will call back into begin_new_exec() on success. */ 176862306a36Sopenharmony_cistatic int exec_binprm(struct linux_binprm *bprm) 176962306a36Sopenharmony_ci{ 177062306a36Sopenharmony_ci pid_t old_pid, old_vpid; 177162306a36Sopenharmony_ci int ret, depth; 177262306a36Sopenharmony_ci 177362306a36Sopenharmony_ci /* Need to fetch pid before load_binary changes it */ 177462306a36Sopenharmony_ci old_pid = current->pid; 177562306a36Sopenharmony_ci rcu_read_lock(); 177662306a36Sopenharmony_ci old_vpid = task_pid_nr_ns(current, task_active_pid_ns(current->parent)); 177762306a36Sopenharmony_ci rcu_read_unlock(); 177862306a36Sopenharmony_ci 177962306a36Sopenharmony_ci /* This allows 4 levels of binfmt rewrites before failing hard. */ 178062306a36Sopenharmony_ci for (depth = 0;; depth++) { 178162306a36Sopenharmony_ci struct file *exec; 178262306a36Sopenharmony_ci if (depth > 5) 178362306a36Sopenharmony_ci return -ELOOP; 178462306a36Sopenharmony_ci 178562306a36Sopenharmony_ci ret = search_binary_handler(bprm); 178662306a36Sopenharmony_ci if (ret < 0) 178762306a36Sopenharmony_ci return ret; 178862306a36Sopenharmony_ci if (!bprm->interpreter) 178962306a36Sopenharmony_ci break; 179062306a36Sopenharmony_ci 179162306a36Sopenharmony_ci exec = bprm->file; 179262306a36Sopenharmony_ci bprm->file = bprm->interpreter; 179362306a36Sopenharmony_ci bprm->interpreter = NULL; 179462306a36Sopenharmony_ci 179562306a36Sopenharmony_ci allow_write_access(exec); 179662306a36Sopenharmony_ci if (unlikely(bprm->have_execfd)) { 179762306a36Sopenharmony_ci if (bprm->executable) { 179862306a36Sopenharmony_ci fput(exec); 179962306a36Sopenharmony_ci return -ENOEXEC; 180062306a36Sopenharmony_ci } 180162306a36Sopenharmony_ci bprm->executable = exec; 180262306a36Sopenharmony_ci } else 180362306a36Sopenharmony_ci fput(exec); 180462306a36Sopenharmony_ci } 180562306a36Sopenharmony_ci 180662306a36Sopenharmony_ci audit_bprm(bprm); 180762306a36Sopenharmony_ci trace_sched_process_exec(current, old_pid, bprm); 180862306a36Sopenharmony_ci ptrace_event(PTRACE_EVENT_EXEC, old_vpid); 180962306a36Sopenharmony_ci proc_exec_connector(current); 181062306a36Sopenharmony_ci return 0; 181162306a36Sopenharmony_ci} 181262306a36Sopenharmony_ci 181362306a36Sopenharmony_ci/* 181462306a36Sopenharmony_ci * sys_execve() executes a new program. 181562306a36Sopenharmony_ci */ 181662306a36Sopenharmony_cistatic int bprm_execve(struct linux_binprm *bprm, 181762306a36Sopenharmony_ci int fd, struct filename *filename, int flags) 181862306a36Sopenharmony_ci{ 181962306a36Sopenharmony_ci struct file *file; 182062306a36Sopenharmony_ci int retval; 182162306a36Sopenharmony_ci 182262306a36Sopenharmony_ci retval = prepare_bprm_creds(bprm); 182362306a36Sopenharmony_ci if (retval) 182462306a36Sopenharmony_ci return retval; 182562306a36Sopenharmony_ci 182662306a36Sopenharmony_ci /* 182762306a36Sopenharmony_ci * Check for unsafe execution states before exec_binprm(), which 182862306a36Sopenharmony_ci * will call back into begin_new_exec(), into bprm_creds_from_file(), 182962306a36Sopenharmony_ci * where setuid-ness is evaluated. 183062306a36Sopenharmony_ci */ 183162306a36Sopenharmony_ci check_unsafe_exec(bprm); 183262306a36Sopenharmony_ci current->in_execve = 1; 183362306a36Sopenharmony_ci sched_mm_cid_before_execve(current); 183462306a36Sopenharmony_ci 183562306a36Sopenharmony_ci file = do_open_execat(fd, filename, flags); 183662306a36Sopenharmony_ci retval = PTR_ERR(file); 183762306a36Sopenharmony_ci if (IS_ERR(file)) 183862306a36Sopenharmony_ci goto out_unmark; 183962306a36Sopenharmony_ci 184062306a36Sopenharmony_ci sched_exec(); 184162306a36Sopenharmony_ci 184262306a36Sopenharmony_ci bprm->file = file; 184362306a36Sopenharmony_ci /* 184462306a36Sopenharmony_ci * Record that a name derived from an O_CLOEXEC fd will be 184562306a36Sopenharmony_ci * inaccessible after exec. This allows the code in exec to 184662306a36Sopenharmony_ci * choose to fail when the executable is not mmaped into the 184762306a36Sopenharmony_ci * interpreter and an open file descriptor is not passed to 184862306a36Sopenharmony_ci * the interpreter. This makes for a better user experience 184962306a36Sopenharmony_ci * than having the interpreter start and then immediately fail 185062306a36Sopenharmony_ci * when it finds the executable is inaccessible. 185162306a36Sopenharmony_ci */ 185262306a36Sopenharmony_ci if (bprm->fdpath && get_close_on_exec(fd)) 185362306a36Sopenharmony_ci bprm->interp_flags |= BINPRM_FLAGS_PATH_INACCESSIBLE; 185462306a36Sopenharmony_ci 185562306a36Sopenharmony_ci /* Set the unchanging part of bprm->cred */ 185662306a36Sopenharmony_ci retval = security_bprm_creds_for_exec(bprm); 185762306a36Sopenharmony_ci if (retval) 185862306a36Sopenharmony_ci goto out; 185962306a36Sopenharmony_ci 186062306a36Sopenharmony_ci retval = exec_binprm(bprm); 186162306a36Sopenharmony_ci if (retval < 0) 186262306a36Sopenharmony_ci goto out; 186362306a36Sopenharmony_ci 186462306a36Sopenharmony_ci sched_mm_cid_after_execve(current); 186562306a36Sopenharmony_ci /* execve succeeded */ 186662306a36Sopenharmony_ci current->fs->in_exec = 0; 186762306a36Sopenharmony_ci current->in_execve = 0; 186862306a36Sopenharmony_ci rseq_execve(current); 186962306a36Sopenharmony_ci user_events_execve(current); 187062306a36Sopenharmony_ci acct_update_integrals(current); 187162306a36Sopenharmony_ci task_numa_free(current, false); 187262306a36Sopenharmony_ci CALL_HCK_LITE_HOOK(ced_detection_lhck, current); 187362306a36Sopenharmony_ci return retval; 187462306a36Sopenharmony_ci 187562306a36Sopenharmony_ciout: 187662306a36Sopenharmony_ci /* 187762306a36Sopenharmony_ci * If past the point of no return ensure the code never 187862306a36Sopenharmony_ci * returns to the userspace process. Use an existing fatal 187962306a36Sopenharmony_ci * signal if present otherwise terminate the process with 188062306a36Sopenharmony_ci * SIGSEGV. 188162306a36Sopenharmony_ci */ 188262306a36Sopenharmony_ci if (bprm->point_of_no_return && !fatal_signal_pending(current)) 188362306a36Sopenharmony_ci force_fatal_sig(SIGSEGV); 188462306a36Sopenharmony_ci 188562306a36Sopenharmony_ciout_unmark: 188662306a36Sopenharmony_ci sched_mm_cid_after_execve(current); 188762306a36Sopenharmony_ci current->fs->in_exec = 0; 188862306a36Sopenharmony_ci current->in_execve = 0; 188962306a36Sopenharmony_ci 189062306a36Sopenharmony_ci return retval; 189162306a36Sopenharmony_ci} 189262306a36Sopenharmony_ci 189362306a36Sopenharmony_cistatic int do_execveat_common(int fd, struct filename *filename, 189462306a36Sopenharmony_ci struct user_arg_ptr argv, 189562306a36Sopenharmony_ci struct user_arg_ptr envp, 189662306a36Sopenharmony_ci int flags) 189762306a36Sopenharmony_ci{ 189862306a36Sopenharmony_ci struct linux_binprm *bprm; 189962306a36Sopenharmony_ci int retval; 190062306a36Sopenharmony_ci 190162306a36Sopenharmony_ci if (IS_ERR(filename)) 190262306a36Sopenharmony_ci return PTR_ERR(filename); 190362306a36Sopenharmony_ci 190462306a36Sopenharmony_ci /* 190562306a36Sopenharmony_ci * We move the actual failure in case of RLIMIT_NPROC excess from 190662306a36Sopenharmony_ci * set*uid() to execve() because too many poorly written programs 190762306a36Sopenharmony_ci * don't check setuid() return code. Here we additionally recheck 190862306a36Sopenharmony_ci * whether NPROC limit is still exceeded. 190962306a36Sopenharmony_ci */ 191062306a36Sopenharmony_ci if ((current->flags & PF_NPROC_EXCEEDED) && 191162306a36Sopenharmony_ci is_rlimit_overlimit(current_ucounts(), UCOUNT_RLIMIT_NPROC, rlimit(RLIMIT_NPROC))) { 191262306a36Sopenharmony_ci retval = -EAGAIN; 191362306a36Sopenharmony_ci goto out_ret; 191462306a36Sopenharmony_ci } 191562306a36Sopenharmony_ci 191662306a36Sopenharmony_ci /* We're below the limit (still or again), so we don't want to make 191762306a36Sopenharmony_ci * further execve() calls fail. */ 191862306a36Sopenharmony_ci current->flags &= ~PF_NPROC_EXCEEDED; 191962306a36Sopenharmony_ci 192062306a36Sopenharmony_ci bprm = alloc_bprm(fd, filename); 192162306a36Sopenharmony_ci if (IS_ERR(bprm)) { 192262306a36Sopenharmony_ci retval = PTR_ERR(bprm); 192362306a36Sopenharmony_ci goto out_ret; 192462306a36Sopenharmony_ci } 192562306a36Sopenharmony_ci 192662306a36Sopenharmony_ci retval = count(argv, MAX_ARG_STRINGS); 192762306a36Sopenharmony_ci if (retval == 0) 192862306a36Sopenharmony_ci pr_warn_once("process '%s' launched '%s' with NULL argv: empty string added\n", 192962306a36Sopenharmony_ci current->comm, bprm->filename); 193062306a36Sopenharmony_ci if (retval < 0) 193162306a36Sopenharmony_ci goto out_free; 193262306a36Sopenharmony_ci bprm->argc = retval; 193362306a36Sopenharmony_ci 193462306a36Sopenharmony_ci retval = count(envp, MAX_ARG_STRINGS); 193562306a36Sopenharmony_ci if (retval < 0) 193662306a36Sopenharmony_ci goto out_free; 193762306a36Sopenharmony_ci bprm->envc = retval; 193862306a36Sopenharmony_ci 193962306a36Sopenharmony_ci retval = bprm_stack_limits(bprm); 194062306a36Sopenharmony_ci if (retval < 0) 194162306a36Sopenharmony_ci goto out_free; 194262306a36Sopenharmony_ci 194362306a36Sopenharmony_ci retval = copy_string_kernel(bprm->filename, bprm); 194462306a36Sopenharmony_ci if (retval < 0) 194562306a36Sopenharmony_ci goto out_free; 194662306a36Sopenharmony_ci bprm->exec = bprm->p; 194762306a36Sopenharmony_ci 194862306a36Sopenharmony_ci retval = copy_strings(bprm->envc, envp, bprm); 194962306a36Sopenharmony_ci if (retval < 0) 195062306a36Sopenharmony_ci goto out_free; 195162306a36Sopenharmony_ci 195262306a36Sopenharmony_ci retval = copy_strings(bprm->argc, argv, bprm); 195362306a36Sopenharmony_ci if (retval < 0) 195462306a36Sopenharmony_ci goto out_free; 195562306a36Sopenharmony_ci 195662306a36Sopenharmony_ci /* 195762306a36Sopenharmony_ci * When argv is empty, add an empty string ("") as argv[0] to 195862306a36Sopenharmony_ci * ensure confused userspace programs that start processing 195962306a36Sopenharmony_ci * from argv[1] won't end up walking envp. See also 196062306a36Sopenharmony_ci * bprm_stack_limits(). 196162306a36Sopenharmony_ci */ 196262306a36Sopenharmony_ci if (bprm->argc == 0) { 196362306a36Sopenharmony_ci retval = copy_string_kernel("", bprm); 196462306a36Sopenharmony_ci if (retval < 0) 196562306a36Sopenharmony_ci goto out_free; 196662306a36Sopenharmony_ci bprm->argc = 1; 196762306a36Sopenharmony_ci } 196862306a36Sopenharmony_ci 196962306a36Sopenharmony_ci retval = bprm_execve(bprm, fd, filename, flags); 197062306a36Sopenharmony_ciout_free: 197162306a36Sopenharmony_ci free_bprm(bprm); 197262306a36Sopenharmony_ci 197362306a36Sopenharmony_ciout_ret: 197462306a36Sopenharmony_ci putname(filename); 197562306a36Sopenharmony_ci return retval; 197662306a36Sopenharmony_ci} 197762306a36Sopenharmony_ci 197862306a36Sopenharmony_ciint kernel_execve(const char *kernel_filename, 197962306a36Sopenharmony_ci const char *const *argv, const char *const *envp) 198062306a36Sopenharmony_ci{ 198162306a36Sopenharmony_ci struct filename *filename; 198262306a36Sopenharmony_ci struct linux_binprm *bprm; 198362306a36Sopenharmony_ci int fd = AT_FDCWD; 198462306a36Sopenharmony_ci int retval; 198562306a36Sopenharmony_ci 198662306a36Sopenharmony_ci /* It is non-sense for kernel threads to call execve */ 198762306a36Sopenharmony_ci if (WARN_ON_ONCE(current->flags & PF_KTHREAD)) 198862306a36Sopenharmony_ci return -EINVAL; 198962306a36Sopenharmony_ci 199062306a36Sopenharmony_ci filename = getname_kernel(kernel_filename); 199162306a36Sopenharmony_ci if (IS_ERR(filename)) 199262306a36Sopenharmony_ci return PTR_ERR(filename); 199362306a36Sopenharmony_ci 199462306a36Sopenharmony_ci bprm = alloc_bprm(fd, filename); 199562306a36Sopenharmony_ci if (IS_ERR(bprm)) { 199662306a36Sopenharmony_ci retval = PTR_ERR(bprm); 199762306a36Sopenharmony_ci goto out_ret; 199862306a36Sopenharmony_ci } 199962306a36Sopenharmony_ci 200062306a36Sopenharmony_ci retval = count_strings_kernel(argv); 200162306a36Sopenharmony_ci if (WARN_ON_ONCE(retval == 0)) 200262306a36Sopenharmony_ci retval = -EINVAL; 200362306a36Sopenharmony_ci if (retval < 0) 200462306a36Sopenharmony_ci goto out_free; 200562306a36Sopenharmony_ci bprm->argc = retval; 200662306a36Sopenharmony_ci 200762306a36Sopenharmony_ci retval = count_strings_kernel(envp); 200862306a36Sopenharmony_ci if (retval < 0) 200962306a36Sopenharmony_ci goto out_free; 201062306a36Sopenharmony_ci bprm->envc = retval; 201162306a36Sopenharmony_ci 201262306a36Sopenharmony_ci retval = bprm_stack_limits(bprm); 201362306a36Sopenharmony_ci if (retval < 0) 201462306a36Sopenharmony_ci goto out_free; 201562306a36Sopenharmony_ci 201662306a36Sopenharmony_ci retval = copy_string_kernel(bprm->filename, bprm); 201762306a36Sopenharmony_ci if (retval < 0) 201862306a36Sopenharmony_ci goto out_free; 201962306a36Sopenharmony_ci bprm->exec = bprm->p; 202062306a36Sopenharmony_ci 202162306a36Sopenharmony_ci retval = copy_strings_kernel(bprm->envc, envp, bprm); 202262306a36Sopenharmony_ci if (retval < 0) 202362306a36Sopenharmony_ci goto out_free; 202462306a36Sopenharmony_ci 202562306a36Sopenharmony_ci retval = copy_strings_kernel(bprm->argc, argv, bprm); 202662306a36Sopenharmony_ci if (retval < 0) 202762306a36Sopenharmony_ci goto out_free; 202862306a36Sopenharmony_ci 202962306a36Sopenharmony_ci retval = bprm_execve(bprm, fd, filename, 0); 203062306a36Sopenharmony_ciout_free: 203162306a36Sopenharmony_ci free_bprm(bprm); 203262306a36Sopenharmony_ciout_ret: 203362306a36Sopenharmony_ci putname(filename); 203462306a36Sopenharmony_ci return retval; 203562306a36Sopenharmony_ci} 203662306a36Sopenharmony_ci 203762306a36Sopenharmony_cistatic int do_execve(struct filename *filename, 203862306a36Sopenharmony_ci const char __user *const __user *__argv, 203962306a36Sopenharmony_ci const char __user *const __user *__envp) 204062306a36Sopenharmony_ci{ 204162306a36Sopenharmony_ci struct user_arg_ptr argv = { .ptr.native = __argv }; 204262306a36Sopenharmony_ci struct user_arg_ptr envp = { .ptr.native = __envp }; 204362306a36Sopenharmony_ci return do_execveat_common(AT_FDCWD, filename, argv, envp, 0); 204462306a36Sopenharmony_ci} 204562306a36Sopenharmony_ci 204662306a36Sopenharmony_cistatic int do_execveat(int fd, struct filename *filename, 204762306a36Sopenharmony_ci const char __user *const __user *__argv, 204862306a36Sopenharmony_ci const char __user *const __user *__envp, 204962306a36Sopenharmony_ci int flags) 205062306a36Sopenharmony_ci{ 205162306a36Sopenharmony_ci struct user_arg_ptr argv = { .ptr.native = __argv }; 205262306a36Sopenharmony_ci struct user_arg_ptr envp = { .ptr.native = __envp }; 205362306a36Sopenharmony_ci 205462306a36Sopenharmony_ci return do_execveat_common(fd, filename, argv, envp, flags); 205562306a36Sopenharmony_ci} 205662306a36Sopenharmony_ci 205762306a36Sopenharmony_ci#ifdef CONFIG_COMPAT 205862306a36Sopenharmony_cistatic int compat_do_execve(struct filename *filename, 205962306a36Sopenharmony_ci const compat_uptr_t __user *__argv, 206062306a36Sopenharmony_ci const compat_uptr_t __user *__envp) 206162306a36Sopenharmony_ci{ 206262306a36Sopenharmony_ci struct user_arg_ptr argv = { 206362306a36Sopenharmony_ci .is_compat = true, 206462306a36Sopenharmony_ci .ptr.compat = __argv, 206562306a36Sopenharmony_ci }; 206662306a36Sopenharmony_ci struct user_arg_ptr envp = { 206762306a36Sopenharmony_ci .is_compat = true, 206862306a36Sopenharmony_ci .ptr.compat = __envp, 206962306a36Sopenharmony_ci }; 207062306a36Sopenharmony_ci return do_execveat_common(AT_FDCWD, filename, argv, envp, 0); 207162306a36Sopenharmony_ci} 207262306a36Sopenharmony_ci 207362306a36Sopenharmony_cistatic int compat_do_execveat(int fd, struct filename *filename, 207462306a36Sopenharmony_ci const compat_uptr_t __user *__argv, 207562306a36Sopenharmony_ci const compat_uptr_t __user *__envp, 207662306a36Sopenharmony_ci int flags) 207762306a36Sopenharmony_ci{ 207862306a36Sopenharmony_ci struct user_arg_ptr argv = { 207962306a36Sopenharmony_ci .is_compat = true, 208062306a36Sopenharmony_ci .ptr.compat = __argv, 208162306a36Sopenharmony_ci }; 208262306a36Sopenharmony_ci struct user_arg_ptr envp = { 208362306a36Sopenharmony_ci .is_compat = true, 208462306a36Sopenharmony_ci .ptr.compat = __envp, 208562306a36Sopenharmony_ci }; 208662306a36Sopenharmony_ci return do_execveat_common(fd, filename, argv, envp, flags); 208762306a36Sopenharmony_ci} 208862306a36Sopenharmony_ci#endif 208962306a36Sopenharmony_ci 209062306a36Sopenharmony_civoid set_binfmt(struct linux_binfmt *new) 209162306a36Sopenharmony_ci{ 209262306a36Sopenharmony_ci struct mm_struct *mm = current->mm; 209362306a36Sopenharmony_ci 209462306a36Sopenharmony_ci if (mm->binfmt) 209562306a36Sopenharmony_ci module_put(mm->binfmt->module); 209662306a36Sopenharmony_ci 209762306a36Sopenharmony_ci mm->binfmt = new; 209862306a36Sopenharmony_ci if (new) 209962306a36Sopenharmony_ci __module_get(new->module); 210062306a36Sopenharmony_ci} 210162306a36Sopenharmony_ciEXPORT_SYMBOL(set_binfmt); 210262306a36Sopenharmony_ci 210362306a36Sopenharmony_ci/* 210462306a36Sopenharmony_ci * set_dumpable stores three-value SUID_DUMP_* into mm->flags. 210562306a36Sopenharmony_ci */ 210662306a36Sopenharmony_civoid set_dumpable(struct mm_struct *mm, int value) 210762306a36Sopenharmony_ci{ 210862306a36Sopenharmony_ci if (WARN_ON((unsigned)value > SUID_DUMP_ROOT)) 210962306a36Sopenharmony_ci return; 211062306a36Sopenharmony_ci 211162306a36Sopenharmony_ci set_mask_bits(&mm->flags, MMF_DUMPABLE_MASK, value); 211262306a36Sopenharmony_ci} 211362306a36Sopenharmony_ci 211462306a36Sopenharmony_ciSYSCALL_DEFINE3(execve, 211562306a36Sopenharmony_ci const char __user *, filename, 211662306a36Sopenharmony_ci const char __user *const __user *, argv, 211762306a36Sopenharmony_ci const char __user *const __user *, envp) 211862306a36Sopenharmony_ci{ 211962306a36Sopenharmony_ci return do_execve(getname(filename), argv, envp); 212062306a36Sopenharmony_ci} 212162306a36Sopenharmony_ci 212262306a36Sopenharmony_ciSYSCALL_DEFINE5(execveat, 212362306a36Sopenharmony_ci int, fd, const char __user *, filename, 212462306a36Sopenharmony_ci const char __user *const __user *, argv, 212562306a36Sopenharmony_ci const char __user *const __user *, envp, 212662306a36Sopenharmony_ci int, flags) 212762306a36Sopenharmony_ci{ 212862306a36Sopenharmony_ci return do_execveat(fd, 212962306a36Sopenharmony_ci getname_uflags(filename, flags), 213062306a36Sopenharmony_ci argv, envp, flags); 213162306a36Sopenharmony_ci} 213262306a36Sopenharmony_ci 213362306a36Sopenharmony_ci#ifdef CONFIG_COMPAT 213462306a36Sopenharmony_ciCOMPAT_SYSCALL_DEFINE3(execve, const char __user *, filename, 213562306a36Sopenharmony_ci const compat_uptr_t __user *, argv, 213662306a36Sopenharmony_ci const compat_uptr_t __user *, envp) 213762306a36Sopenharmony_ci{ 213862306a36Sopenharmony_ci return compat_do_execve(getname(filename), argv, envp); 213962306a36Sopenharmony_ci} 214062306a36Sopenharmony_ci 214162306a36Sopenharmony_ciCOMPAT_SYSCALL_DEFINE5(execveat, int, fd, 214262306a36Sopenharmony_ci const char __user *, filename, 214362306a36Sopenharmony_ci const compat_uptr_t __user *, argv, 214462306a36Sopenharmony_ci const compat_uptr_t __user *, envp, 214562306a36Sopenharmony_ci int, flags) 214662306a36Sopenharmony_ci{ 214762306a36Sopenharmony_ci return compat_do_execveat(fd, 214862306a36Sopenharmony_ci getname_uflags(filename, flags), 214962306a36Sopenharmony_ci argv, envp, flags); 215062306a36Sopenharmony_ci} 215162306a36Sopenharmony_ci#endif 215262306a36Sopenharmony_ci 215362306a36Sopenharmony_ci#ifdef CONFIG_SYSCTL 215462306a36Sopenharmony_ci 215562306a36Sopenharmony_cistatic int proc_dointvec_minmax_coredump(struct ctl_table *table, int write, 215662306a36Sopenharmony_ci void *buffer, size_t *lenp, loff_t *ppos) 215762306a36Sopenharmony_ci{ 215862306a36Sopenharmony_ci int error = proc_dointvec_minmax(table, write, buffer, lenp, ppos); 215962306a36Sopenharmony_ci 216062306a36Sopenharmony_ci if (!error) 216162306a36Sopenharmony_ci validate_coredump_safety(); 216262306a36Sopenharmony_ci return error; 216362306a36Sopenharmony_ci} 216462306a36Sopenharmony_ci 216562306a36Sopenharmony_cistatic struct ctl_table fs_exec_sysctls[] = { 216662306a36Sopenharmony_ci { 216762306a36Sopenharmony_ci .procname = "suid_dumpable", 216862306a36Sopenharmony_ci .data = &suid_dumpable, 216962306a36Sopenharmony_ci .maxlen = sizeof(int), 217062306a36Sopenharmony_ci .mode = 0644, 217162306a36Sopenharmony_ci .proc_handler = proc_dointvec_minmax_coredump, 217262306a36Sopenharmony_ci .extra1 = SYSCTL_ZERO, 217362306a36Sopenharmony_ci .extra2 = SYSCTL_TWO, 217462306a36Sopenharmony_ci }, 217562306a36Sopenharmony_ci { } 217662306a36Sopenharmony_ci}; 217762306a36Sopenharmony_ci 217862306a36Sopenharmony_cistatic int __init init_fs_exec_sysctls(void) 217962306a36Sopenharmony_ci{ 218062306a36Sopenharmony_ci register_sysctl_init("fs", fs_exec_sysctls); 218162306a36Sopenharmony_ci return 0; 218262306a36Sopenharmony_ci} 218362306a36Sopenharmony_ci 218462306a36Sopenharmony_cifs_initcall(init_fs_exec_sysctls); 218562306a36Sopenharmony_ci#endif /* CONFIG_SYSCTL */ 2186