11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * linux/fs/exec.c 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * Copyright (C) 1991, 1992 Linus Torvalds 51da177e4SLinus Torvalds */ 61da177e4SLinus Torvalds 71da177e4SLinus Torvalds /* 81da177e4SLinus Torvalds * #!-checking implemented by tytso. 91da177e4SLinus Torvalds */ 101da177e4SLinus Torvalds /* 111da177e4SLinus Torvalds * Demand-loading implemented 01.12.91 - no need to read anything but 121da177e4SLinus Torvalds * the header into memory. The inode of the executable is put into 131da177e4SLinus Torvalds * "current->executable", and page faults do the actual loading. Clean. 141da177e4SLinus Torvalds * 151da177e4SLinus Torvalds * Once more I can proudly say that linux stood up to being changed: it 161da177e4SLinus Torvalds * was less than 2 hours work to get demand-loading completely implemented. 171da177e4SLinus Torvalds * 181da177e4SLinus Torvalds * Demand loading changed July 1993 by Eric Youngdale. Use mmap instead, 191da177e4SLinus Torvalds * current->executable is only used by the procfs. This allows a dispatch 201da177e4SLinus Torvalds * table to check for several different types of binary formats. We keep 211da177e4SLinus Torvalds * trying until we recognize the file or we run out of supported binary 221da177e4SLinus Torvalds * formats. 231da177e4SLinus Torvalds */ 241da177e4SLinus Torvalds 251da177e4SLinus Torvalds #include <linux/config.h> 261da177e4SLinus Torvalds #include <linux/slab.h> 271da177e4SLinus Torvalds #include <linux/file.h> 281da177e4SLinus Torvalds #include <linux/mman.h> 291da177e4SLinus Torvalds #include <linux/a.out.h> 301da177e4SLinus Torvalds #include <linux/stat.h> 311da177e4SLinus Torvalds #include <linux/fcntl.h> 321da177e4SLinus Torvalds #include <linux/smp_lock.h> 331da177e4SLinus Torvalds #include <linux/init.h> 341da177e4SLinus Torvalds #include <linux/pagemap.h> 351da177e4SLinus Torvalds #include <linux/highmem.h> 361da177e4SLinus Torvalds #include <linux/spinlock.h> 371da177e4SLinus Torvalds #include <linux/key.h> 381da177e4SLinus Torvalds #include <linux/personality.h> 391da177e4SLinus Torvalds #include <linux/binfmts.h> 401da177e4SLinus Torvalds #include <linux/swap.h> 411da177e4SLinus Torvalds #include <linux/utsname.h> 421da177e4SLinus Torvalds #include <linux/module.h> 431da177e4SLinus Torvalds #include <linux/namei.h> 441da177e4SLinus Torvalds #include <linux/proc_fs.h> 451da177e4SLinus Torvalds #include <linux/ptrace.h> 461da177e4SLinus Torvalds #include <linux/mount.h> 471da177e4SLinus Torvalds #include <linux/security.h> 481da177e4SLinus Torvalds #include <linux/syscalls.h> 491da177e4SLinus Torvalds #include <linux/rmap.h> 501da177e4SLinus Torvalds #include <linux/acct.h> 519f46080cSMatt Helsley #include <linux/cn_proc.h> 521da177e4SLinus Torvalds 531da177e4SLinus Torvalds #include <asm/uaccess.h> 541da177e4SLinus Torvalds #include <asm/mmu_context.h> 551da177e4SLinus Torvalds 561da177e4SLinus Torvalds #ifdef CONFIG_KMOD 571da177e4SLinus Torvalds #include <linux/kmod.h> 581da177e4SLinus Torvalds #endif 591da177e4SLinus Torvalds 601da177e4SLinus Torvalds int core_uses_pid; 611da177e4SLinus Torvalds char core_pattern[65] = "core"; 62d6e71144SAlan Cox int suid_dumpable = 0; 63d6e71144SAlan Cox 64d6e71144SAlan Cox EXPORT_SYMBOL(suid_dumpable); 651da177e4SLinus Torvalds /* The maximal length of core_pattern is also specified in sysctl.c */ 661da177e4SLinus Torvalds 671da177e4SLinus Torvalds static struct linux_binfmt *formats; 681da177e4SLinus Torvalds static DEFINE_RWLOCK(binfmt_lock); 691da177e4SLinus Torvalds 701da177e4SLinus Torvalds int register_binfmt(struct linux_binfmt * fmt) 711da177e4SLinus Torvalds { 721da177e4SLinus Torvalds struct linux_binfmt ** tmp = &formats; 731da177e4SLinus Torvalds 741da177e4SLinus Torvalds if (!fmt) 751da177e4SLinus Torvalds return -EINVAL; 761da177e4SLinus Torvalds if (fmt->next) 771da177e4SLinus Torvalds return -EBUSY; 781da177e4SLinus Torvalds write_lock(&binfmt_lock); 791da177e4SLinus Torvalds while (*tmp) { 801da177e4SLinus Torvalds if (fmt == *tmp) { 811da177e4SLinus Torvalds write_unlock(&binfmt_lock); 821da177e4SLinus Torvalds return -EBUSY; 831da177e4SLinus Torvalds } 841da177e4SLinus Torvalds tmp = &(*tmp)->next; 851da177e4SLinus Torvalds } 861da177e4SLinus Torvalds fmt->next = formats; 871da177e4SLinus Torvalds formats = fmt; 881da177e4SLinus Torvalds write_unlock(&binfmt_lock); 891da177e4SLinus Torvalds return 0; 901da177e4SLinus Torvalds } 911da177e4SLinus Torvalds 921da177e4SLinus Torvalds EXPORT_SYMBOL(register_binfmt); 931da177e4SLinus Torvalds 941da177e4SLinus Torvalds int unregister_binfmt(struct linux_binfmt * fmt) 951da177e4SLinus Torvalds { 961da177e4SLinus Torvalds struct linux_binfmt ** tmp = &formats; 971da177e4SLinus Torvalds 981da177e4SLinus Torvalds write_lock(&binfmt_lock); 991da177e4SLinus Torvalds while (*tmp) { 1001da177e4SLinus Torvalds if (fmt == *tmp) { 1011da177e4SLinus Torvalds *tmp = fmt->next; 1021da177e4SLinus Torvalds write_unlock(&binfmt_lock); 1031da177e4SLinus Torvalds return 0; 1041da177e4SLinus Torvalds } 1051da177e4SLinus Torvalds tmp = &(*tmp)->next; 1061da177e4SLinus Torvalds } 1071da177e4SLinus Torvalds write_unlock(&binfmt_lock); 1081da177e4SLinus Torvalds return -EINVAL; 1091da177e4SLinus Torvalds } 1101da177e4SLinus Torvalds 1111da177e4SLinus Torvalds EXPORT_SYMBOL(unregister_binfmt); 1121da177e4SLinus Torvalds 1131da177e4SLinus Torvalds static inline void put_binfmt(struct linux_binfmt * fmt) 1141da177e4SLinus Torvalds { 1151da177e4SLinus Torvalds module_put(fmt->module); 1161da177e4SLinus Torvalds } 1171da177e4SLinus Torvalds 1181da177e4SLinus Torvalds /* 1191da177e4SLinus Torvalds * Note that a shared library must be both readable and executable due to 1201da177e4SLinus Torvalds * security reasons. 1211da177e4SLinus Torvalds * 1221da177e4SLinus Torvalds * Also note that we take the address to load from from the file itself. 1231da177e4SLinus Torvalds */ 1241da177e4SLinus Torvalds asmlinkage long sys_uselib(const char __user * library) 1251da177e4SLinus Torvalds { 1261da177e4SLinus Torvalds struct file * file; 1271da177e4SLinus Torvalds struct nameidata nd; 1281da177e4SLinus Torvalds int error; 1291da177e4SLinus Torvalds 130834f2a4aSTrond Myklebust error = __user_path_lookup_open(library, LOOKUP_FOLLOW, &nd, FMODE_READ); 1311da177e4SLinus Torvalds if (error) 1321da177e4SLinus Torvalds goto out; 1331da177e4SLinus Torvalds 1341da177e4SLinus Torvalds error = -EINVAL; 1351da177e4SLinus Torvalds if (!S_ISREG(nd.dentry->d_inode->i_mode)) 1361da177e4SLinus Torvalds goto exit; 1371da177e4SLinus Torvalds 138e4543eddSChristoph Hellwig error = vfs_permission(&nd, MAY_READ | MAY_EXEC); 1391da177e4SLinus Torvalds if (error) 1401da177e4SLinus Torvalds goto exit; 1411da177e4SLinus Torvalds 142834f2a4aSTrond Myklebust file = nameidata_to_filp(&nd, O_RDONLY); 1431da177e4SLinus Torvalds error = PTR_ERR(file); 1441da177e4SLinus Torvalds if (IS_ERR(file)) 1451da177e4SLinus Torvalds goto out; 1461da177e4SLinus Torvalds 1471da177e4SLinus Torvalds error = -ENOEXEC; 1481da177e4SLinus Torvalds if(file->f_op) { 1491da177e4SLinus Torvalds struct linux_binfmt * fmt; 1501da177e4SLinus Torvalds 1511da177e4SLinus Torvalds read_lock(&binfmt_lock); 1521da177e4SLinus Torvalds for (fmt = formats ; fmt ; fmt = fmt->next) { 1531da177e4SLinus Torvalds if (!fmt->load_shlib) 1541da177e4SLinus Torvalds continue; 1551da177e4SLinus Torvalds if (!try_module_get(fmt->module)) 1561da177e4SLinus Torvalds continue; 1571da177e4SLinus Torvalds read_unlock(&binfmt_lock); 1581da177e4SLinus Torvalds error = fmt->load_shlib(file); 1591da177e4SLinus Torvalds read_lock(&binfmt_lock); 1601da177e4SLinus Torvalds put_binfmt(fmt); 1611da177e4SLinus Torvalds if (error != -ENOEXEC) 1621da177e4SLinus Torvalds break; 1631da177e4SLinus Torvalds } 1641da177e4SLinus Torvalds read_unlock(&binfmt_lock); 1651da177e4SLinus Torvalds } 1661da177e4SLinus Torvalds fput(file); 1671da177e4SLinus Torvalds out: 1681da177e4SLinus Torvalds return error; 1691da177e4SLinus Torvalds exit: 170834f2a4aSTrond Myklebust release_open_intent(&nd); 1711da177e4SLinus Torvalds path_release(&nd); 1721da177e4SLinus Torvalds goto out; 1731da177e4SLinus Torvalds } 1741da177e4SLinus Torvalds 1751da177e4SLinus Torvalds /* 1761da177e4SLinus Torvalds * count() counts the number of strings in array ARGV. 1771da177e4SLinus Torvalds */ 1781da177e4SLinus Torvalds static int count(char __user * __user * argv, int max) 1791da177e4SLinus Torvalds { 1801da177e4SLinus Torvalds int i = 0; 1811da177e4SLinus Torvalds 1821da177e4SLinus Torvalds if (argv != NULL) { 1831da177e4SLinus Torvalds for (;;) { 1841da177e4SLinus Torvalds char __user * p; 1851da177e4SLinus Torvalds 1861da177e4SLinus Torvalds if (get_user(p, argv)) 1871da177e4SLinus Torvalds return -EFAULT; 1881da177e4SLinus Torvalds if (!p) 1891da177e4SLinus Torvalds break; 1901da177e4SLinus Torvalds argv++; 1911da177e4SLinus Torvalds if(++i > max) 1921da177e4SLinus Torvalds return -E2BIG; 1931da177e4SLinus Torvalds cond_resched(); 1941da177e4SLinus Torvalds } 1951da177e4SLinus Torvalds } 1961da177e4SLinus Torvalds return i; 1971da177e4SLinus Torvalds } 1981da177e4SLinus Torvalds 1991da177e4SLinus Torvalds /* 2001da177e4SLinus Torvalds * 'copy_strings()' copies argument/environment strings from user 2011da177e4SLinus Torvalds * memory to free pages in kernel mem. These are in a format ready 2021da177e4SLinus Torvalds * to be put directly into the top of new user memory. 2031da177e4SLinus Torvalds */ 20475c96f85SAdrian Bunk static int copy_strings(int argc, char __user * __user * argv, 20575c96f85SAdrian Bunk struct linux_binprm *bprm) 2061da177e4SLinus Torvalds { 2071da177e4SLinus Torvalds struct page *kmapped_page = NULL; 2081da177e4SLinus Torvalds char *kaddr = NULL; 2091da177e4SLinus Torvalds int ret; 2101da177e4SLinus Torvalds 2111da177e4SLinus Torvalds while (argc-- > 0) { 2121da177e4SLinus Torvalds char __user *str; 2131da177e4SLinus Torvalds int len; 2141da177e4SLinus Torvalds unsigned long pos; 2151da177e4SLinus Torvalds 2161da177e4SLinus Torvalds if (get_user(str, argv+argc) || 2171da177e4SLinus Torvalds !(len = strnlen_user(str, bprm->p))) { 2181da177e4SLinus Torvalds ret = -EFAULT; 2191da177e4SLinus Torvalds goto out; 2201da177e4SLinus Torvalds } 2211da177e4SLinus Torvalds 2221da177e4SLinus Torvalds if (bprm->p < len) { 2231da177e4SLinus Torvalds ret = -E2BIG; 2241da177e4SLinus Torvalds goto out; 2251da177e4SLinus Torvalds } 2261da177e4SLinus Torvalds 2271da177e4SLinus Torvalds bprm->p -= len; 2281da177e4SLinus Torvalds /* XXX: add architecture specific overflow check here. */ 2291da177e4SLinus Torvalds pos = bprm->p; 2301da177e4SLinus Torvalds 2311da177e4SLinus Torvalds while (len > 0) { 2321da177e4SLinus Torvalds int i, new, err; 2331da177e4SLinus Torvalds int offset, bytes_to_copy; 2341da177e4SLinus Torvalds struct page *page; 2351da177e4SLinus Torvalds 2361da177e4SLinus Torvalds offset = pos % PAGE_SIZE; 2371da177e4SLinus Torvalds i = pos/PAGE_SIZE; 2381da177e4SLinus Torvalds page = bprm->page[i]; 2391da177e4SLinus Torvalds new = 0; 2401da177e4SLinus Torvalds if (!page) { 2411da177e4SLinus Torvalds page = alloc_page(GFP_HIGHUSER); 2421da177e4SLinus Torvalds bprm->page[i] = page; 2431da177e4SLinus Torvalds if (!page) { 2441da177e4SLinus Torvalds ret = -ENOMEM; 2451da177e4SLinus Torvalds goto out; 2461da177e4SLinus Torvalds } 2471da177e4SLinus Torvalds new = 1; 2481da177e4SLinus Torvalds } 2491da177e4SLinus Torvalds 2501da177e4SLinus Torvalds if (page != kmapped_page) { 2511da177e4SLinus Torvalds if (kmapped_page) 2521da177e4SLinus Torvalds kunmap(kmapped_page); 2531da177e4SLinus Torvalds kmapped_page = page; 2541da177e4SLinus Torvalds kaddr = kmap(kmapped_page); 2551da177e4SLinus Torvalds } 2561da177e4SLinus Torvalds if (new && offset) 2571da177e4SLinus Torvalds memset(kaddr, 0, offset); 2581da177e4SLinus Torvalds bytes_to_copy = PAGE_SIZE - offset; 2591da177e4SLinus Torvalds if (bytes_to_copy > len) { 2601da177e4SLinus Torvalds bytes_to_copy = len; 2611da177e4SLinus Torvalds if (new) 2621da177e4SLinus Torvalds memset(kaddr+offset+len, 0, 2631da177e4SLinus Torvalds PAGE_SIZE-offset-len); 2641da177e4SLinus Torvalds } 2651da177e4SLinus Torvalds err = copy_from_user(kaddr+offset, str, bytes_to_copy); 2661da177e4SLinus Torvalds if (err) { 2671da177e4SLinus Torvalds ret = -EFAULT; 2681da177e4SLinus Torvalds goto out; 2691da177e4SLinus Torvalds } 2701da177e4SLinus Torvalds 2711da177e4SLinus Torvalds pos += bytes_to_copy; 2721da177e4SLinus Torvalds str += bytes_to_copy; 2731da177e4SLinus Torvalds len -= bytes_to_copy; 2741da177e4SLinus Torvalds } 2751da177e4SLinus Torvalds } 2761da177e4SLinus Torvalds ret = 0; 2771da177e4SLinus Torvalds out: 2781da177e4SLinus Torvalds if (kmapped_page) 2791da177e4SLinus Torvalds kunmap(kmapped_page); 2801da177e4SLinus Torvalds return ret; 2811da177e4SLinus Torvalds } 2821da177e4SLinus Torvalds 2831da177e4SLinus Torvalds /* 2841da177e4SLinus Torvalds * Like copy_strings, but get argv and its values from kernel memory. 2851da177e4SLinus Torvalds */ 2861da177e4SLinus Torvalds int copy_strings_kernel(int argc,char ** argv, struct linux_binprm *bprm) 2871da177e4SLinus Torvalds { 2881da177e4SLinus Torvalds int r; 2891da177e4SLinus Torvalds mm_segment_t oldfs = get_fs(); 2901da177e4SLinus Torvalds set_fs(KERNEL_DS); 2911da177e4SLinus Torvalds r = copy_strings(argc, (char __user * __user *)argv, bprm); 2921da177e4SLinus Torvalds set_fs(oldfs); 2931da177e4SLinus Torvalds return r; 2941da177e4SLinus Torvalds } 2951da177e4SLinus Torvalds 2961da177e4SLinus Torvalds EXPORT_SYMBOL(copy_strings_kernel); 2971da177e4SLinus Torvalds 2981da177e4SLinus Torvalds #ifdef CONFIG_MMU 2991da177e4SLinus Torvalds /* 3001da177e4SLinus Torvalds * This routine is used to map in a page into an address space: needed by 3011da177e4SLinus Torvalds * execve() for the initial stack and environment pages. 3021da177e4SLinus Torvalds * 3031da177e4SLinus Torvalds * vma->vm_mm->mmap_sem is held for writing. 3041da177e4SLinus Torvalds */ 3051da177e4SLinus Torvalds void install_arg_page(struct vm_area_struct *vma, 3061da177e4SLinus Torvalds struct page *page, unsigned long address) 3071da177e4SLinus Torvalds { 3081da177e4SLinus Torvalds struct mm_struct *mm = vma->vm_mm; 3091da177e4SLinus Torvalds pte_t * pte; 310c74df32cSHugh Dickins spinlock_t *ptl; 3111da177e4SLinus Torvalds 3121da177e4SLinus Torvalds if (unlikely(anon_vma_prepare(vma))) 313c74df32cSHugh Dickins goto out; 3141da177e4SLinus Torvalds 3151da177e4SLinus Torvalds flush_dcache_page(page); 316c9cfcddfSLinus Torvalds pte = get_locked_pte(mm, address, &ptl); 3171da177e4SLinus Torvalds if (!pte) 3181da177e4SLinus Torvalds goto out; 3191da177e4SLinus Torvalds if (!pte_none(*pte)) { 320c74df32cSHugh Dickins pte_unmap_unlock(pte, ptl); 3211da177e4SLinus Torvalds goto out; 3221da177e4SLinus Torvalds } 3234294621fSHugh Dickins inc_mm_counter(mm, anon_rss); 3241da177e4SLinus Torvalds lru_cache_add_active(page); 3251da177e4SLinus Torvalds set_pte_at(mm, address, pte, pte_mkdirty(pte_mkwrite(mk_pte( 3261da177e4SLinus Torvalds page, vma->vm_page_prot)))); 3279617d95eSNick Piggin page_add_new_anon_rmap(page, vma, address); 328c74df32cSHugh Dickins pte_unmap_unlock(pte, ptl); 3291da177e4SLinus Torvalds 3301da177e4SLinus Torvalds /* no need for flush_tlb */ 3311da177e4SLinus Torvalds return; 3321da177e4SLinus Torvalds out: 3331da177e4SLinus Torvalds __free_page(page); 3341da177e4SLinus Torvalds force_sig(SIGKILL, current); 3351da177e4SLinus Torvalds } 3361da177e4SLinus Torvalds 3371da177e4SLinus Torvalds #define EXTRA_STACK_VM_PAGES 20 /* random */ 3381da177e4SLinus Torvalds 3391da177e4SLinus Torvalds int setup_arg_pages(struct linux_binprm *bprm, 3401da177e4SLinus Torvalds unsigned long stack_top, 3411da177e4SLinus Torvalds int executable_stack) 3421da177e4SLinus Torvalds { 3431da177e4SLinus Torvalds unsigned long stack_base; 3441da177e4SLinus Torvalds struct vm_area_struct *mpnt; 3451da177e4SLinus Torvalds struct mm_struct *mm = current->mm; 3461da177e4SLinus Torvalds int i, ret; 3471da177e4SLinus Torvalds long arg_size; 3481da177e4SLinus Torvalds 3491da177e4SLinus Torvalds #ifdef CONFIG_STACK_GROWSUP 3501da177e4SLinus Torvalds /* Move the argument and environment strings to the bottom of the 3511da177e4SLinus Torvalds * stack space. 3521da177e4SLinus Torvalds */ 3531da177e4SLinus Torvalds int offset, j; 3541da177e4SLinus Torvalds char *to, *from; 3551da177e4SLinus Torvalds 3561da177e4SLinus Torvalds /* Start by shifting all the pages down */ 3571da177e4SLinus Torvalds i = 0; 3581da177e4SLinus Torvalds for (j = 0; j < MAX_ARG_PAGES; j++) { 3591da177e4SLinus Torvalds struct page *page = bprm->page[j]; 3601da177e4SLinus Torvalds if (!page) 3611da177e4SLinus Torvalds continue; 3621da177e4SLinus Torvalds bprm->page[i++] = page; 3631da177e4SLinus Torvalds } 3641da177e4SLinus Torvalds 3651da177e4SLinus Torvalds /* Now move them within their pages */ 3661da177e4SLinus Torvalds offset = bprm->p % PAGE_SIZE; 3671da177e4SLinus Torvalds to = kmap(bprm->page[0]); 3681da177e4SLinus Torvalds for (j = 1; j < i; j++) { 3691da177e4SLinus Torvalds memmove(to, to + offset, PAGE_SIZE - offset); 3701da177e4SLinus Torvalds from = kmap(bprm->page[j]); 3711da177e4SLinus Torvalds memcpy(to + PAGE_SIZE - offset, from, offset); 3721da177e4SLinus Torvalds kunmap(bprm->page[j - 1]); 3731da177e4SLinus Torvalds to = from; 3741da177e4SLinus Torvalds } 3751da177e4SLinus Torvalds memmove(to, to + offset, PAGE_SIZE - offset); 3761da177e4SLinus Torvalds kunmap(bprm->page[j - 1]); 3771da177e4SLinus Torvalds 3781da177e4SLinus Torvalds /* Limit stack size to 1GB */ 3791da177e4SLinus Torvalds stack_base = current->signal->rlim[RLIMIT_STACK].rlim_max; 3801da177e4SLinus Torvalds if (stack_base > (1 << 30)) 3811da177e4SLinus Torvalds stack_base = 1 << 30; 3821da177e4SLinus Torvalds stack_base = PAGE_ALIGN(stack_top - stack_base); 3831da177e4SLinus Torvalds 3841da177e4SLinus Torvalds /* Adjust bprm->p to point to the end of the strings. */ 3851da177e4SLinus Torvalds bprm->p = stack_base + PAGE_SIZE * i - offset; 3861da177e4SLinus Torvalds 3871da177e4SLinus Torvalds mm->arg_start = stack_base; 3881da177e4SLinus Torvalds arg_size = i << PAGE_SHIFT; 3891da177e4SLinus Torvalds 3901da177e4SLinus Torvalds /* zero pages that were copied above */ 3911da177e4SLinus Torvalds while (i < MAX_ARG_PAGES) 3921da177e4SLinus Torvalds bprm->page[i++] = NULL; 3931da177e4SLinus Torvalds #else 3941da177e4SLinus Torvalds stack_base = arch_align_stack(stack_top - MAX_ARG_PAGES*PAGE_SIZE); 3951da177e4SLinus Torvalds stack_base = PAGE_ALIGN(stack_base); 3961da177e4SLinus Torvalds bprm->p += stack_base; 3971da177e4SLinus Torvalds mm->arg_start = bprm->p; 3981da177e4SLinus Torvalds arg_size = stack_top - (PAGE_MASK & (unsigned long) mm->arg_start); 3991da177e4SLinus Torvalds #endif 4001da177e4SLinus Torvalds 4011da177e4SLinus Torvalds arg_size += EXTRA_STACK_VM_PAGES * PAGE_SIZE; 4021da177e4SLinus Torvalds 4031da177e4SLinus Torvalds if (bprm->loader) 4041da177e4SLinus Torvalds bprm->loader += stack_base; 4051da177e4SLinus Torvalds bprm->exec += stack_base; 4061da177e4SLinus Torvalds 4071da177e4SLinus Torvalds mpnt = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL); 4081da177e4SLinus Torvalds if (!mpnt) 4091da177e4SLinus Torvalds return -ENOMEM; 4101da177e4SLinus Torvalds 4111da177e4SLinus Torvalds memset(mpnt, 0, sizeof(*mpnt)); 4121da177e4SLinus Torvalds 4131da177e4SLinus Torvalds down_write(&mm->mmap_sem); 4141da177e4SLinus Torvalds { 4151da177e4SLinus Torvalds mpnt->vm_mm = mm; 4161da177e4SLinus Torvalds #ifdef CONFIG_STACK_GROWSUP 4171da177e4SLinus Torvalds mpnt->vm_start = stack_base; 4181da177e4SLinus Torvalds mpnt->vm_end = stack_base + arg_size; 4191da177e4SLinus Torvalds #else 4201da177e4SLinus Torvalds mpnt->vm_end = stack_top; 4211da177e4SLinus Torvalds mpnt->vm_start = mpnt->vm_end - arg_size; 4221da177e4SLinus Torvalds #endif 4231da177e4SLinus Torvalds /* Adjust stack execute permissions; explicitly enable 4241da177e4SLinus Torvalds * for EXSTACK_ENABLE_X, disable for EXSTACK_DISABLE_X 4251da177e4SLinus Torvalds * and leave alone (arch default) otherwise. */ 4261da177e4SLinus Torvalds if (unlikely(executable_stack == EXSTACK_ENABLE_X)) 4271da177e4SLinus Torvalds mpnt->vm_flags = VM_STACK_FLAGS | VM_EXEC; 4281da177e4SLinus Torvalds else if (executable_stack == EXSTACK_DISABLE_X) 4291da177e4SLinus Torvalds mpnt->vm_flags = VM_STACK_FLAGS & ~VM_EXEC; 4301da177e4SLinus Torvalds else 4311da177e4SLinus Torvalds mpnt->vm_flags = VM_STACK_FLAGS; 4321da177e4SLinus Torvalds mpnt->vm_flags |= mm->def_flags; 4331da177e4SLinus Torvalds mpnt->vm_page_prot = protection_map[mpnt->vm_flags & 0x7]; 4341da177e4SLinus Torvalds if ((ret = insert_vm_struct(mm, mpnt))) { 4351da177e4SLinus Torvalds up_write(&mm->mmap_sem); 4361da177e4SLinus Torvalds kmem_cache_free(vm_area_cachep, mpnt); 4371da177e4SLinus Torvalds return ret; 4381da177e4SLinus Torvalds } 4391da177e4SLinus Torvalds mm->stack_vm = mm->total_vm = vma_pages(mpnt); 4401da177e4SLinus Torvalds } 4411da177e4SLinus Torvalds 4421da177e4SLinus Torvalds for (i = 0 ; i < MAX_ARG_PAGES ; i++) { 4431da177e4SLinus Torvalds struct page *page = bprm->page[i]; 4441da177e4SLinus Torvalds if (page) { 4451da177e4SLinus Torvalds bprm->page[i] = NULL; 4461da177e4SLinus Torvalds install_arg_page(mpnt, page, stack_base); 4471da177e4SLinus Torvalds } 4481da177e4SLinus Torvalds stack_base += PAGE_SIZE; 4491da177e4SLinus Torvalds } 4501da177e4SLinus Torvalds up_write(&mm->mmap_sem); 4511da177e4SLinus Torvalds 4521da177e4SLinus Torvalds return 0; 4531da177e4SLinus Torvalds } 4541da177e4SLinus Torvalds 4551da177e4SLinus Torvalds EXPORT_SYMBOL(setup_arg_pages); 4561da177e4SLinus Torvalds 4571da177e4SLinus Torvalds #define free_arg_pages(bprm) do { } while (0) 4581da177e4SLinus Torvalds 4591da177e4SLinus Torvalds #else 4601da177e4SLinus Torvalds 4611da177e4SLinus Torvalds static inline void free_arg_pages(struct linux_binprm *bprm) 4621da177e4SLinus Torvalds { 4631da177e4SLinus Torvalds int i; 4641da177e4SLinus Torvalds 4651da177e4SLinus Torvalds for (i = 0; i < MAX_ARG_PAGES; i++) { 4661da177e4SLinus Torvalds if (bprm->page[i]) 4671da177e4SLinus Torvalds __free_page(bprm->page[i]); 4681da177e4SLinus Torvalds bprm->page[i] = NULL; 4691da177e4SLinus Torvalds } 4701da177e4SLinus Torvalds } 4711da177e4SLinus Torvalds 4721da177e4SLinus Torvalds #endif /* CONFIG_MMU */ 4731da177e4SLinus Torvalds 4741da177e4SLinus Torvalds struct file *open_exec(const char *name) 4751da177e4SLinus Torvalds { 4761da177e4SLinus Torvalds struct nameidata nd; 4771da177e4SLinus Torvalds int err; 4781da177e4SLinus Torvalds struct file *file; 4791da177e4SLinus Torvalds 480834f2a4aSTrond Myklebust err = path_lookup_open(name, LOOKUP_FOLLOW, &nd, FMODE_READ); 4811da177e4SLinus Torvalds file = ERR_PTR(err); 4821da177e4SLinus Torvalds 4831da177e4SLinus Torvalds if (!err) { 4841da177e4SLinus Torvalds struct inode *inode = nd.dentry->d_inode; 4851da177e4SLinus Torvalds file = ERR_PTR(-EACCES); 4861da177e4SLinus Torvalds if (!(nd.mnt->mnt_flags & MNT_NOEXEC) && 4871da177e4SLinus Torvalds S_ISREG(inode->i_mode)) { 488e4543eddSChristoph Hellwig int err = vfs_permission(&nd, MAY_EXEC); 4891da177e4SLinus Torvalds if (!err && !(inode->i_mode & 0111)) 4901da177e4SLinus Torvalds err = -EACCES; 4911da177e4SLinus Torvalds file = ERR_PTR(err); 4921da177e4SLinus Torvalds if (!err) { 493834f2a4aSTrond Myklebust file = nameidata_to_filp(&nd, O_RDONLY); 4941da177e4SLinus Torvalds if (!IS_ERR(file)) { 4951da177e4SLinus Torvalds err = deny_write_access(file); 4961da177e4SLinus Torvalds if (err) { 4971da177e4SLinus Torvalds fput(file); 4981da177e4SLinus Torvalds file = ERR_PTR(err); 4991da177e4SLinus Torvalds } 5001da177e4SLinus Torvalds } 5011da177e4SLinus Torvalds out: 5021da177e4SLinus Torvalds return file; 5031da177e4SLinus Torvalds } 5041da177e4SLinus Torvalds } 505834f2a4aSTrond Myklebust release_open_intent(&nd); 5061da177e4SLinus Torvalds path_release(&nd); 5071da177e4SLinus Torvalds } 5081da177e4SLinus Torvalds goto out; 5091da177e4SLinus Torvalds } 5101da177e4SLinus Torvalds 5111da177e4SLinus Torvalds EXPORT_SYMBOL(open_exec); 5121da177e4SLinus Torvalds 5131da177e4SLinus Torvalds int kernel_read(struct file *file, unsigned long offset, 5141da177e4SLinus Torvalds char *addr, unsigned long count) 5151da177e4SLinus Torvalds { 5161da177e4SLinus Torvalds mm_segment_t old_fs; 5171da177e4SLinus Torvalds loff_t pos = offset; 5181da177e4SLinus Torvalds int result; 5191da177e4SLinus Torvalds 5201da177e4SLinus Torvalds old_fs = get_fs(); 5211da177e4SLinus Torvalds set_fs(get_ds()); 5221da177e4SLinus Torvalds /* The cast to a user pointer is valid due to the set_fs() */ 5231da177e4SLinus Torvalds result = vfs_read(file, (void __user *)addr, count, &pos); 5241da177e4SLinus Torvalds set_fs(old_fs); 5251da177e4SLinus Torvalds return result; 5261da177e4SLinus Torvalds } 5271da177e4SLinus Torvalds 5281da177e4SLinus Torvalds EXPORT_SYMBOL(kernel_read); 5291da177e4SLinus Torvalds 5301da177e4SLinus Torvalds static int exec_mmap(struct mm_struct *mm) 5311da177e4SLinus Torvalds { 5321da177e4SLinus Torvalds struct task_struct *tsk; 5331da177e4SLinus Torvalds struct mm_struct * old_mm, *active_mm; 5341da177e4SLinus Torvalds 5351da177e4SLinus Torvalds /* Notify parent that we're no longer interested in the old VM */ 5361da177e4SLinus Torvalds tsk = current; 5371da177e4SLinus Torvalds old_mm = current->mm; 5381da177e4SLinus Torvalds mm_release(tsk, old_mm); 5391da177e4SLinus Torvalds 5401da177e4SLinus Torvalds if (old_mm) { 5411da177e4SLinus Torvalds /* 5421da177e4SLinus Torvalds * Make sure that if there is a core dump in progress 5431da177e4SLinus Torvalds * for the old mm, we get out and die instead of going 5441da177e4SLinus Torvalds * through with the exec. We must hold mmap_sem around 5451da177e4SLinus Torvalds * checking core_waiters and changing tsk->mm. The 5461da177e4SLinus Torvalds * core-inducing thread will increment core_waiters for 5471da177e4SLinus Torvalds * each thread whose ->mm == old_mm. 5481da177e4SLinus Torvalds */ 5491da177e4SLinus Torvalds down_read(&old_mm->mmap_sem); 5501da177e4SLinus Torvalds if (unlikely(old_mm->core_waiters)) { 5511da177e4SLinus Torvalds up_read(&old_mm->mmap_sem); 5521da177e4SLinus Torvalds return -EINTR; 5531da177e4SLinus Torvalds } 5541da177e4SLinus Torvalds } 5551da177e4SLinus Torvalds task_lock(tsk); 5561da177e4SLinus Torvalds active_mm = tsk->active_mm; 5571da177e4SLinus Torvalds tsk->mm = mm; 5581da177e4SLinus Torvalds tsk->active_mm = mm; 5591da177e4SLinus Torvalds activate_mm(active_mm, mm); 5601da177e4SLinus Torvalds task_unlock(tsk); 5611da177e4SLinus Torvalds arch_pick_mmap_layout(mm); 5621da177e4SLinus Torvalds if (old_mm) { 5631da177e4SLinus Torvalds up_read(&old_mm->mmap_sem); 5641da177e4SLinus Torvalds if (active_mm != old_mm) BUG(); 5651da177e4SLinus Torvalds mmput(old_mm); 5661da177e4SLinus Torvalds return 0; 5671da177e4SLinus Torvalds } 5681da177e4SLinus Torvalds mmdrop(active_mm); 5691da177e4SLinus Torvalds return 0; 5701da177e4SLinus Torvalds } 5711da177e4SLinus Torvalds 5721da177e4SLinus Torvalds /* 5731da177e4SLinus Torvalds * This function makes sure the current process has its own signal table, 5741da177e4SLinus Torvalds * so that flush_signal_handlers can later reset the handlers without 5751da177e4SLinus Torvalds * disturbing other processes. (Other processes might share the signal 5761da177e4SLinus Torvalds * table via the CLONE_SIGHAND option to clone().) 5771da177e4SLinus Torvalds */ 578*858119e1SArjan van de Ven static int de_thread(struct task_struct *tsk) 5791da177e4SLinus Torvalds { 5801da177e4SLinus Torvalds struct signal_struct *sig = tsk->signal; 5811da177e4SLinus Torvalds struct sighand_struct *newsighand, *oldsighand = tsk->sighand; 5821da177e4SLinus Torvalds spinlock_t *lock = &oldsighand->siglock; 583329f7dbaSOleg Nesterov struct task_struct *leader = NULL; 5841da177e4SLinus Torvalds int count; 5851da177e4SLinus Torvalds 5861da177e4SLinus Torvalds /* 5871da177e4SLinus Torvalds * If we don't share sighandlers, then we aren't sharing anything 5881da177e4SLinus Torvalds * and we can just re-use it all. 5891da177e4SLinus Torvalds */ 5901da177e4SLinus Torvalds if (atomic_read(&oldsighand->count) <= 1) { 5911da177e4SLinus Torvalds BUG_ON(atomic_read(&sig->count) != 1); 5921da177e4SLinus Torvalds exit_itimers(sig); 5931da177e4SLinus Torvalds return 0; 5941da177e4SLinus Torvalds } 5951da177e4SLinus Torvalds 5961da177e4SLinus Torvalds newsighand = kmem_cache_alloc(sighand_cachep, GFP_KERNEL); 5971da177e4SLinus Torvalds if (!newsighand) 5981da177e4SLinus Torvalds return -ENOMEM; 5991da177e4SLinus Torvalds 6001da177e4SLinus Torvalds if (thread_group_empty(current)) 6011da177e4SLinus Torvalds goto no_thread_group; 6021da177e4SLinus Torvalds 6031da177e4SLinus Torvalds /* 6041da177e4SLinus Torvalds * Kill all other threads in the thread group. 6051da177e4SLinus Torvalds * We must hold tasklist_lock to call zap_other_threads. 6061da177e4SLinus Torvalds */ 6071da177e4SLinus Torvalds read_lock(&tasklist_lock); 6081da177e4SLinus Torvalds spin_lock_irq(lock); 6091da177e4SLinus Torvalds if (sig->flags & SIGNAL_GROUP_EXIT) { 6101da177e4SLinus Torvalds /* 6111da177e4SLinus Torvalds * Another group action in progress, just 6121da177e4SLinus Torvalds * return so that the signal is processed. 6131da177e4SLinus Torvalds */ 6141da177e4SLinus Torvalds spin_unlock_irq(lock); 6151da177e4SLinus Torvalds read_unlock(&tasklist_lock); 6161da177e4SLinus Torvalds kmem_cache_free(sighand_cachep, newsighand); 6171da177e4SLinus Torvalds return -EAGAIN; 6181da177e4SLinus Torvalds } 6191da177e4SLinus Torvalds zap_other_threads(current); 6201da177e4SLinus Torvalds read_unlock(&tasklist_lock); 6211da177e4SLinus Torvalds 6221da177e4SLinus Torvalds /* 6231da177e4SLinus Torvalds * Account for the thread group leader hanging around: 6241da177e4SLinus Torvalds */ 6251da177e4SLinus Torvalds count = 1; 6269e4e23bcSOleg Nesterov if (!thread_group_leader(current)) { 6279e4e23bcSOleg Nesterov count = 2; 62853231250SRoland McGrath /* 62953231250SRoland McGrath * The SIGALRM timer survives the exec, but needs to point 63053231250SRoland McGrath * at us as the new group leader now. We have a race with 63153231250SRoland McGrath * a timer firing now getting the old leader, so we need to 63253231250SRoland McGrath * synchronize with any firing (by calling del_timer_sync) 63353231250SRoland McGrath * before we can safely let the old group leader die. 63453231250SRoland McGrath */ 6352ff678b8SThomas Gleixner sig->real_timer.data = current; 636932aeafbSOleg Nesterov spin_unlock_irq(lock); 6372ff678b8SThomas Gleixner if (hrtimer_cancel(&sig->real_timer)) 6382ff678b8SThomas Gleixner hrtimer_restart(&sig->real_timer); 639932aeafbSOleg Nesterov spin_lock_irq(lock); 64053231250SRoland McGrath } 6411da177e4SLinus Torvalds while (atomic_read(&sig->count) > count) { 6421da177e4SLinus Torvalds sig->group_exit_task = current; 6431da177e4SLinus Torvalds sig->notify_count = count; 6441da177e4SLinus Torvalds __set_current_state(TASK_UNINTERRUPTIBLE); 6451da177e4SLinus Torvalds spin_unlock_irq(lock); 6461da177e4SLinus Torvalds schedule(); 6471da177e4SLinus Torvalds spin_lock_irq(lock); 6481da177e4SLinus Torvalds } 6491da177e4SLinus Torvalds sig->group_exit_task = NULL; 6501da177e4SLinus Torvalds sig->notify_count = 0; 6511da177e4SLinus Torvalds spin_unlock_irq(lock); 6521da177e4SLinus Torvalds 6531da177e4SLinus Torvalds /* 6541da177e4SLinus Torvalds * At this point all other threads have exited, all we have to 6551da177e4SLinus Torvalds * do is to wait for the thread group leader to become inactive, 6561da177e4SLinus Torvalds * and to assume its PID: 6571da177e4SLinus Torvalds */ 6581da177e4SLinus Torvalds if (!thread_group_leader(current)) { 659329f7dbaSOleg Nesterov struct task_struct *parent; 6601da177e4SLinus Torvalds struct dentry *proc_dentry1, *proc_dentry2; 661962b564cSOleg Nesterov unsigned long ptrace; 6621da177e4SLinus Torvalds 6631da177e4SLinus Torvalds /* 6641da177e4SLinus Torvalds * Wait for the thread group leader to be a zombie. 6651da177e4SLinus Torvalds * It should already be zombie at this point, most 6661da177e4SLinus Torvalds * of the time. 6671da177e4SLinus Torvalds */ 668329f7dbaSOleg Nesterov leader = current->group_leader; 6691da177e4SLinus Torvalds while (leader->exit_state != EXIT_ZOMBIE) 6701da177e4SLinus Torvalds yield(); 6711da177e4SLinus Torvalds 6721da177e4SLinus Torvalds spin_lock(&leader->proc_lock); 6731da177e4SLinus Torvalds spin_lock(¤t->proc_lock); 6741da177e4SLinus Torvalds proc_dentry1 = proc_pid_unhash(current); 6751da177e4SLinus Torvalds proc_dentry2 = proc_pid_unhash(leader); 6761da177e4SLinus Torvalds write_lock_irq(&tasklist_lock); 6771da177e4SLinus Torvalds 678c2a0f594SLinus Torvalds BUG_ON(leader->tgid != current->tgid); 679c2a0f594SLinus Torvalds BUG_ON(current->pid == current->tgid); 6801da177e4SLinus Torvalds /* 6811da177e4SLinus Torvalds * An exec() starts a new thread group with the 6821da177e4SLinus Torvalds * TGID of the previous thread group. Rehash the 6831da177e4SLinus Torvalds * two threads with a switched PID, and release 6841da177e4SLinus Torvalds * the former thread group leader: 6851da177e4SLinus Torvalds */ 6861da177e4SLinus Torvalds ptrace = leader->ptrace; 6871da177e4SLinus Torvalds parent = leader->parent; 6881da177e4SLinus Torvalds if (unlikely(ptrace) && unlikely(parent == current)) { 6891da177e4SLinus Torvalds /* 6901da177e4SLinus Torvalds * Joker was ptracing his own group leader, 6911da177e4SLinus Torvalds * and now he wants to be his own parent! 6921da177e4SLinus Torvalds * We can't have that. 6931da177e4SLinus Torvalds */ 6941da177e4SLinus Torvalds ptrace = 0; 6951da177e4SLinus Torvalds } 6961da177e4SLinus Torvalds 6971da177e4SLinus Torvalds ptrace_unlink(current); 6981da177e4SLinus Torvalds ptrace_unlink(leader); 6991da177e4SLinus Torvalds remove_parent(current); 7001da177e4SLinus Torvalds remove_parent(leader); 7011da177e4SLinus Torvalds 7021da177e4SLinus Torvalds switch_exec_pids(leader, current); 7031da177e4SLinus Torvalds 7041da177e4SLinus Torvalds current->parent = current->real_parent = leader->real_parent; 7051da177e4SLinus Torvalds leader->parent = leader->real_parent = child_reaper; 7061da177e4SLinus Torvalds current->group_leader = current; 7071da177e4SLinus Torvalds leader->group_leader = leader; 7081da177e4SLinus Torvalds 7091da177e4SLinus Torvalds add_parent(current, current->parent); 7101da177e4SLinus Torvalds add_parent(leader, leader->parent); 7111da177e4SLinus Torvalds if (ptrace) { 7121da177e4SLinus Torvalds current->ptrace = ptrace; 7131da177e4SLinus Torvalds __ptrace_link(current, parent); 7141da177e4SLinus Torvalds } 7151da177e4SLinus Torvalds 7161da177e4SLinus Torvalds list_del(¤t->tasks); 7171da177e4SLinus Torvalds list_add_tail(¤t->tasks, &init_task.tasks); 7181da177e4SLinus Torvalds current->exit_signal = SIGCHLD; 719962b564cSOleg Nesterov 720962b564cSOleg Nesterov BUG_ON(leader->exit_state != EXIT_ZOMBIE); 721962b564cSOleg Nesterov leader->exit_state = EXIT_DEAD; 7221da177e4SLinus Torvalds 7231da177e4SLinus Torvalds write_unlock_irq(&tasklist_lock); 7241da177e4SLinus Torvalds spin_unlock(&leader->proc_lock); 7251da177e4SLinus Torvalds spin_unlock(¤t->proc_lock); 7261da177e4SLinus Torvalds proc_pid_flush(proc_dentry1); 7271da177e4SLinus Torvalds proc_pid_flush(proc_dentry2); 7281da177e4SLinus Torvalds } 7291da177e4SLinus Torvalds 7301da177e4SLinus Torvalds /* 731fb085cf1SAlexander Nyberg * There may be one thread left which is just exiting, 732fb085cf1SAlexander Nyberg * but it's safe to stop telling the group to kill themselves. 7331da177e4SLinus Torvalds */ 7341da177e4SLinus Torvalds sig->flags = 0; 7351da177e4SLinus Torvalds 7361da177e4SLinus Torvalds no_thread_group: 7371da177e4SLinus Torvalds exit_itimers(sig); 738329f7dbaSOleg Nesterov if (leader) 739329f7dbaSOleg Nesterov release_task(leader); 740329f7dbaSOleg Nesterov 741329f7dbaSOleg Nesterov BUG_ON(atomic_read(&sig->count) != 1); 7421da177e4SLinus Torvalds 7431da177e4SLinus Torvalds if (atomic_read(&oldsighand->count) == 1) { 7441da177e4SLinus Torvalds /* 7451da177e4SLinus Torvalds * Now that we nuked the rest of the thread group, 7461da177e4SLinus Torvalds * it turns out we are not sharing sighand any more either. 7471da177e4SLinus Torvalds * So we can just keep it. 7481da177e4SLinus Torvalds */ 7491da177e4SLinus Torvalds kmem_cache_free(sighand_cachep, newsighand); 7501da177e4SLinus Torvalds } else { 7511da177e4SLinus Torvalds /* 7521da177e4SLinus Torvalds * Move our state over to newsighand and switch it in. 7531da177e4SLinus Torvalds */ 7541da177e4SLinus Torvalds spin_lock_init(&newsighand->siglock); 7551da177e4SLinus Torvalds atomic_set(&newsighand->count, 1); 7561da177e4SLinus Torvalds memcpy(newsighand->action, oldsighand->action, 7571da177e4SLinus Torvalds sizeof(newsighand->action)); 7581da177e4SLinus Torvalds 7591da177e4SLinus Torvalds write_lock_irq(&tasklist_lock); 7601da177e4SLinus Torvalds spin_lock(&oldsighand->siglock); 7611da177e4SLinus Torvalds spin_lock(&newsighand->siglock); 7621da177e4SLinus Torvalds 763e56d0903SIngo Molnar rcu_assign_pointer(current->sighand, newsighand); 7641da177e4SLinus Torvalds recalc_sigpending(); 7651da177e4SLinus Torvalds 7661da177e4SLinus Torvalds spin_unlock(&newsighand->siglock); 7671da177e4SLinus Torvalds spin_unlock(&oldsighand->siglock); 7681da177e4SLinus Torvalds write_unlock_irq(&tasklist_lock); 7691da177e4SLinus Torvalds 7701da177e4SLinus Torvalds if (atomic_dec_and_test(&oldsighand->count)) 771e56d0903SIngo Molnar sighand_free(oldsighand); 7721da177e4SLinus Torvalds } 7731da177e4SLinus Torvalds 774c2a0f594SLinus Torvalds BUG_ON(!thread_group_leader(current)); 7751da177e4SLinus Torvalds return 0; 7761da177e4SLinus Torvalds } 7771da177e4SLinus Torvalds 7781da177e4SLinus Torvalds /* 7791da177e4SLinus Torvalds * These functions flushes out all traces of the currently running executable 7801da177e4SLinus Torvalds * so that a new one can be started 7811da177e4SLinus Torvalds */ 7821da177e4SLinus Torvalds 783*858119e1SArjan van de Ven static void flush_old_files(struct files_struct * files) 7841da177e4SLinus Torvalds { 7851da177e4SLinus Torvalds long j = -1; 786badf1662SDipankar Sarma struct fdtable *fdt; 7871da177e4SLinus Torvalds 7881da177e4SLinus Torvalds spin_lock(&files->file_lock); 7891da177e4SLinus Torvalds for (;;) { 7901da177e4SLinus Torvalds unsigned long set, i; 7911da177e4SLinus Torvalds 7921da177e4SLinus Torvalds j++; 7931da177e4SLinus Torvalds i = j * __NFDBITS; 794badf1662SDipankar Sarma fdt = files_fdtable(files); 795badf1662SDipankar Sarma if (i >= fdt->max_fds || i >= fdt->max_fdset) 7961da177e4SLinus Torvalds break; 797badf1662SDipankar Sarma set = fdt->close_on_exec->fds_bits[j]; 7981da177e4SLinus Torvalds if (!set) 7991da177e4SLinus Torvalds continue; 800badf1662SDipankar Sarma fdt->close_on_exec->fds_bits[j] = 0; 8011da177e4SLinus Torvalds spin_unlock(&files->file_lock); 8021da177e4SLinus Torvalds for ( ; set ; i++,set >>= 1) { 8031da177e4SLinus Torvalds if (set & 1) { 8041da177e4SLinus Torvalds sys_close(i); 8051da177e4SLinus Torvalds } 8061da177e4SLinus Torvalds } 8071da177e4SLinus Torvalds spin_lock(&files->file_lock); 8081da177e4SLinus Torvalds 8091da177e4SLinus Torvalds } 8101da177e4SLinus Torvalds spin_unlock(&files->file_lock); 8111da177e4SLinus Torvalds } 8121da177e4SLinus Torvalds 8131da177e4SLinus Torvalds void get_task_comm(char *buf, struct task_struct *tsk) 8141da177e4SLinus Torvalds { 8151da177e4SLinus Torvalds /* buf must be at least sizeof(tsk->comm) in size */ 8161da177e4SLinus Torvalds task_lock(tsk); 8171da177e4SLinus Torvalds strncpy(buf, tsk->comm, sizeof(tsk->comm)); 8181da177e4SLinus Torvalds task_unlock(tsk); 8191da177e4SLinus Torvalds } 8201da177e4SLinus Torvalds 8211da177e4SLinus Torvalds void set_task_comm(struct task_struct *tsk, char *buf) 8221da177e4SLinus Torvalds { 8231da177e4SLinus Torvalds task_lock(tsk); 8241da177e4SLinus Torvalds strlcpy(tsk->comm, buf, sizeof(tsk->comm)); 8251da177e4SLinus Torvalds task_unlock(tsk); 8261da177e4SLinus Torvalds } 8271da177e4SLinus Torvalds 8281da177e4SLinus Torvalds int flush_old_exec(struct linux_binprm * bprm) 8291da177e4SLinus Torvalds { 8301da177e4SLinus Torvalds char * name; 8311da177e4SLinus Torvalds int i, ch, retval; 8321da177e4SLinus Torvalds struct files_struct *files; 8331da177e4SLinus Torvalds char tcomm[sizeof(current->comm)]; 8341da177e4SLinus Torvalds 8351da177e4SLinus Torvalds /* 8361da177e4SLinus Torvalds * Make sure we have a private signal table and that 8371da177e4SLinus Torvalds * we are unassociated from the previous thread group. 8381da177e4SLinus Torvalds */ 8391da177e4SLinus Torvalds retval = de_thread(current); 8401da177e4SLinus Torvalds if (retval) 8411da177e4SLinus Torvalds goto out; 8421da177e4SLinus Torvalds 8431da177e4SLinus Torvalds /* 8441da177e4SLinus Torvalds * Make sure we have private file handles. Ask the 8451da177e4SLinus Torvalds * fork helper to do the work for us and the exit 8461da177e4SLinus Torvalds * helper to do the cleanup of the old one. 8471da177e4SLinus Torvalds */ 8481da177e4SLinus Torvalds files = current->files; /* refcounted so safe to hold */ 8491da177e4SLinus Torvalds retval = unshare_files(); 8501da177e4SLinus Torvalds if (retval) 8511da177e4SLinus Torvalds goto out; 8521da177e4SLinus Torvalds /* 8531da177e4SLinus Torvalds * Release all of the old mmap stuff 8541da177e4SLinus Torvalds */ 8551da177e4SLinus Torvalds retval = exec_mmap(bprm->mm); 8561da177e4SLinus Torvalds if (retval) 8571da177e4SLinus Torvalds goto mmap_failed; 8581da177e4SLinus Torvalds 8591da177e4SLinus Torvalds bprm->mm = NULL; /* We're using it now */ 8601da177e4SLinus Torvalds 8611da177e4SLinus Torvalds /* This is the point of no return */ 8621da177e4SLinus Torvalds steal_locks(files); 8631da177e4SLinus Torvalds put_files_struct(files); 8641da177e4SLinus Torvalds 8651da177e4SLinus Torvalds current->sas_ss_sp = current->sas_ss_size = 0; 8661da177e4SLinus Torvalds 8671da177e4SLinus Torvalds if (current->euid == current->uid && current->egid == current->gid) 8681da177e4SLinus Torvalds current->mm->dumpable = 1; 869d6e71144SAlan Cox else 870d6e71144SAlan Cox current->mm->dumpable = suid_dumpable; 871d6e71144SAlan Cox 8721da177e4SLinus Torvalds name = bprm->filename; 87336772092SPaolo 'Blaisorblade' Giarrusso 87436772092SPaolo 'Blaisorblade' Giarrusso /* Copies the binary name from after last slash */ 8751da177e4SLinus Torvalds for (i=0; (ch = *(name++)) != '\0';) { 8761da177e4SLinus Torvalds if (ch == '/') 87736772092SPaolo 'Blaisorblade' Giarrusso i = 0; /* overwrite what we wrote */ 8781da177e4SLinus Torvalds else 8791da177e4SLinus Torvalds if (i < (sizeof(tcomm) - 1)) 8801da177e4SLinus Torvalds tcomm[i++] = ch; 8811da177e4SLinus Torvalds } 8821da177e4SLinus Torvalds tcomm[i] = '\0'; 8831da177e4SLinus Torvalds set_task_comm(current, tcomm); 8841da177e4SLinus Torvalds 8851da177e4SLinus Torvalds current->flags &= ~PF_RANDOMIZE; 8861da177e4SLinus Torvalds flush_thread(); 8871da177e4SLinus Torvalds 8881da177e4SLinus Torvalds if (bprm->e_uid != current->euid || bprm->e_gid != current->egid || 8898c744fb8SChristoph Hellwig file_permission(bprm->file, MAY_READ) || 8901da177e4SLinus Torvalds (bprm->interp_flags & BINPRM_FLAGS_ENFORCE_NONDUMP)) { 8911da177e4SLinus Torvalds suid_keys(current); 892d6e71144SAlan Cox current->mm->dumpable = suid_dumpable; 8931da177e4SLinus Torvalds } 8941da177e4SLinus Torvalds 8951da177e4SLinus Torvalds /* An exec changes our domain. We are no longer part of the thread 8961da177e4SLinus Torvalds group */ 8971da177e4SLinus Torvalds 8981da177e4SLinus Torvalds current->self_exec_id++; 8991da177e4SLinus Torvalds 9001da177e4SLinus Torvalds flush_signal_handlers(current, 0); 9011da177e4SLinus Torvalds flush_old_files(current->files); 9021da177e4SLinus Torvalds 9031da177e4SLinus Torvalds return 0; 9041da177e4SLinus Torvalds 9051da177e4SLinus Torvalds mmap_failed: 9061da177e4SLinus Torvalds put_files_struct(current->files); 9071da177e4SLinus Torvalds current->files = files; 9081da177e4SLinus Torvalds out: 9091da177e4SLinus Torvalds return retval; 9101da177e4SLinus Torvalds } 9111da177e4SLinus Torvalds 9121da177e4SLinus Torvalds EXPORT_SYMBOL(flush_old_exec); 9131da177e4SLinus Torvalds 9141da177e4SLinus Torvalds /* 9151da177e4SLinus Torvalds * Fill the binprm structure from the inode. 9161da177e4SLinus Torvalds * Check permissions, then read the first 128 (BINPRM_BUF_SIZE) bytes 9171da177e4SLinus Torvalds */ 9181da177e4SLinus Torvalds int prepare_binprm(struct linux_binprm *bprm) 9191da177e4SLinus Torvalds { 9201da177e4SLinus Torvalds int mode; 9211da177e4SLinus Torvalds struct inode * inode = bprm->file->f_dentry->d_inode; 9221da177e4SLinus Torvalds int retval; 9231da177e4SLinus Torvalds 9241da177e4SLinus Torvalds mode = inode->i_mode; 9251da177e4SLinus Torvalds /* 9261da177e4SLinus Torvalds * Check execute perms again - if the caller has CAP_DAC_OVERRIDE, 9271da177e4SLinus Torvalds * generic_permission lets a non-executable through 9281da177e4SLinus Torvalds */ 9291da177e4SLinus Torvalds if (!(mode & 0111)) /* with at least _one_ execute bit set */ 9301da177e4SLinus Torvalds return -EACCES; 9311da177e4SLinus Torvalds if (bprm->file->f_op == NULL) 9321da177e4SLinus Torvalds return -EACCES; 9331da177e4SLinus Torvalds 9341da177e4SLinus Torvalds bprm->e_uid = current->euid; 9351da177e4SLinus Torvalds bprm->e_gid = current->egid; 9361da177e4SLinus Torvalds 9371da177e4SLinus Torvalds if(!(bprm->file->f_vfsmnt->mnt_flags & MNT_NOSUID)) { 9381da177e4SLinus Torvalds /* Set-uid? */ 9391da177e4SLinus Torvalds if (mode & S_ISUID) { 9401da177e4SLinus Torvalds current->personality &= ~PER_CLEAR_ON_SETID; 9411da177e4SLinus Torvalds bprm->e_uid = inode->i_uid; 9421da177e4SLinus Torvalds } 9431da177e4SLinus Torvalds 9441da177e4SLinus Torvalds /* Set-gid? */ 9451da177e4SLinus Torvalds /* 9461da177e4SLinus Torvalds * If setgid is set but no group execute bit then this 9471da177e4SLinus Torvalds * is a candidate for mandatory locking, not a setgid 9481da177e4SLinus Torvalds * executable. 9491da177e4SLinus Torvalds */ 9501da177e4SLinus Torvalds if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) { 9511da177e4SLinus Torvalds current->personality &= ~PER_CLEAR_ON_SETID; 9521da177e4SLinus Torvalds bprm->e_gid = inode->i_gid; 9531da177e4SLinus Torvalds } 9541da177e4SLinus Torvalds } 9551da177e4SLinus Torvalds 9561da177e4SLinus Torvalds /* fill in binprm security blob */ 9571da177e4SLinus Torvalds retval = security_bprm_set(bprm); 9581da177e4SLinus Torvalds if (retval) 9591da177e4SLinus Torvalds return retval; 9601da177e4SLinus Torvalds 9611da177e4SLinus Torvalds memset(bprm->buf,0,BINPRM_BUF_SIZE); 9621da177e4SLinus Torvalds return kernel_read(bprm->file,0,bprm->buf,BINPRM_BUF_SIZE); 9631da177e4SLinus Torvalds } 9641da177e4SLinus Torvalds 9651da177e4SLinus Torvalds EXPORT_SYMBOL(prepare_binprm); 9661da177e4SLinus Torvalds 967*858119e1SArjan van de Ven static int unsafe_exec(struct task_struct *p) 9681da177e4SLinus Torvalds { 9691da177e4SLinus Torvalds int unsafe = 0; 9701da177e4SLinus Torvalds if (p->ptrace & PT_PTRACED) { 9711da177e4SLinus Torvalds if (p->ptrace & PT_PTRACE_CAP) 9721da177e4SLinus Torvalds unsafe |= LSM_UNSAFE_PTRACE_CAP; 9731da177e4SLinus Torvalds else 9741da177e4SLinus Torvalds unsafe |= LSM_UNSAFE_PTRACE; 9751da177e4SLinus Torvalds } 9761da177e4SLinus Torvalds if (atomic_read(&p->fs->count) > 1 || 9771da177e4SLinus Torvalds atomic_read(&p->files->count) > 1 || 9781da177e4SLinus Torvalds atomic_read(&p->sighand->count) > 1) 9791da177e4SLinus Torvalds unsafe |= LSM_UNSAFE_SHARE; 9801da177e4SLinus Torvalds 9811da177e4SLinus Torvalds return unsafe; 9821da177e4SLinus Torvalds } 9831da177e4SLinus Torvalds 9841da177e4SLinus Torvalds void compute_creds(struct linux_binprm *bprm) 9851da177e4SLinus Torvalds { 9861da177e4SLinus Torvalds int unsafe; 9871da177e4SLinus Torvalds 9881da177e4SLinus Torvalds if (bprm->e_uid != current->uid) 9891da177e4SLinus Torvalds suid_keys(current); 9901da177e4SLinus Torvalds exec_keys(current); 9911da177e4SLinus Torvalds 9921da177e4SLinus Torvalds task_lock(current); 9931da177e4SLinus Torvalds unsafe = unsafe_exec(current); 9941da177e4SLinus Torvalds security_bprm_apply_creds(bprm, unsafe); 9951da177e4SLinus Torvalds task_unlock(current); 9961da177e4SLinus Torvalds security_bprm_post_apply_creds(bprm); 9971da177e4SLinus Torvalds } 9981da177e4SLinus Torvalds 9991da177e4SLinus Torvalds EXPORT_SYMBOL(compute_creds); 10001da177e4SLinus Torvalds 10011da177e4SLinus Torvalds void remove_arg_zero(struct linux_binprm *bprm) 10021da177e4SLinus Torvalds { 10031da177e4SLinus Torvalds if (bprm->argc) { 10041da177e4SLinus Torvalds unsigned long offset; 10051da177e4SLinus Torvalds char * kaddr; 10061da177e4SLinus Torvalds struct page *page; 10071da177e4SLinus Torvalds 10081da177e4SLinus Torvalds offset = bprm->p % PAGE_SIZE; 10091da177e4SLinus Torvalds goto inside; 10101da177e4SLinus Torvalds 10111da177e4SLinus Torvalds while (bprm->p++, *(kaddr+offset++)) { 10121da177e4SLinus Torvalds if (offset != PAGE_SIZE) 10131da177e4SLinus Torvalds continue; 10141da177e4SLinus Torvalds offset = 0; 10151da177e4SLinus Torvalds kunmap_atomic(kaddr, KM_USER0); 10161da177e4SLinus Torvalds inside: 10171da177e4SLinus Torvalds page = bprm->page[bprm->p/PAGE_SIZE]; 10181da177e4SLinus Torvalds kaddr = kmap_atomic(page, KM_USER0); 10191da177e4SLinus Torvalds } 10201da177e4SLinus Torvalds kunmap_atomic(kaddr, KM_USER0); 10211da177e4SLinus Torvalds bprm->argc--; 10221da177e4SLinus Torvalds } 10231da177e4SLinus Torvalds } 10241da177e4SLinus Torvalds 10251da177e4SLinus Torvalds EXPORT_SYMBOL(remove_arg_zero); 10261da177e4SLinus Torvalds 10271da177e4SLinus Torvalds /* 10281da177e4SLinus Torvalds * cycle the list of binary formats handler, until one recognizes the image 10291da177e4SLinus Torvalds */ 10301da177e4SLinus Torvalds int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs) 10311da177e4SLinus Torvalds { 10321da177e4SLinus Torvalds int try,retval; 10331da177e4SLinus Torvalds struct linux_binfmt *fmt; 10341da177e4SLinus Torvalds #ifdef __alpha__ 10351da177e4SLinus Torvalds /* handle /sbin/loader.. */ 10361da177e4SLinus Torvalds { 10371da177e4SLinus Torvalds struct exec * eh = (struct exec *) bprm->buf; 10381da177e4SLinus Torvalds 10391da177e4SLinus Torvalds if (!bprm->loader && eh->fh.f_magic == 0x183 && 10401da177e4SLinus Torvalds (eh->fh.f_flags & 0x3000) == 0x3000) 10411da177e4SLinus Torvalds { 10421da177e4SLinus Torvalds struct file * file; 10431da177e4SLinus Torvalds unsigned long loader; 10441da177e4SLinus Torvalds 10451da177e4SLinus Torvalds allow_write_access(bprm->file); 10461da177e4SLinus Torvalds fput(bprm->file); 10471da177e4SLinus Torvalds bprm->file = NULL; 10481da177e4SLinus Torvalds 10491da177e4SLinus Torvalds loader = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *); 10501da177e4SLinus Torvalds 10511da177e4SLinus Torvalds file = open_exec("/sbin/loader"); 10521da177e4SLinus Torvalds retval = PTR_ERR(file); 10531da177e4SLinus Torvalds if (IS_ERR(file)) 10541da177e4SLinus Torvalds return retval; 10551da177e4SLinus Torvalds 10561da177e4SLinus Torvalds /* Remember if the application is TASO. */ 10571da177e4SLinus Torvalds bprm->sh_bang = eh->ah.entry < 0x100000000UL; 10581da177e4SLinus Torvalds 10591da177e4SLinus Torvalds bprm->file = file; 10601da177e4SLinus Torvalds bprm->loader = loader; 10611da177e4SLinus Torvalds retval = prepare_binprm(bprm); 10621da177e4SLinus Torvalds if (retval<0) 10631da177e4SLinus Torvalds return retval; 10641da177e4SLinus Torvalds /* should call search_binary_handler recursively here, 10651da177e4SLinus Torvalds but it does not matter */ 10661da177e4SLinus Torvalds } 10671da177e4SLinus Torvalds } 10681da177e4SLinus Torvalds #endif 10691da177e4SLinus Torvalds retval = security_bprm_check(bprm); 10701da177e4SLinus Torvalds if (retval) 10711da177e4SLinus Torvalds return retval; 10721da177e4SLinus Torvalds 10731da177e4SLinus Torvalds /* kernel module loader fixup */ 10741da177e4SLinus Torvalds /* so we don't try to load run modprobe in kernel space. */ 10751da177e4SLinus Torvalds set_fs(USER_DS); 10761da177e4SLinus Torvalds retval = -ENOENT; 10771da177e4SLinus Torvalds for (try=0; try<2; try++) { 10781da177e4SLinus Torvalds read_lock(&binfmt_lock); 10791da177e4SLinus Torvalds for (fmt = formats ; fmt ; fmt = fmt->next) { 10801da177e4SLinus Torvalds int (*fn)(struct linux_binprm *, struct pt_regs *) = fmt->load_binary; 10811da177e4SLinus Torvalds if (!fn) 10821da177e4SLinus Torvalds continue; 10831da177e4SLinus Torvalds if (!try_module_get(fmt->module)) 10841da177e4SLinus Torvalds continue; 10851da177e4SLinus Torvalds read_unlock(&binfmt_lock); 10861da177e4SLinus Torvalds retval = fn(bprm, regs); 10871da177e4SLinus Torvalds if (retval >= 0) { 10881da177e4SLinus Torvalds put_binfmt(fmt); 10891da177e4SLinus Torvalds allow_write_access(bprm->file); 10901da177e4SLinus Torvalds if (bprm->file) 10911da177e4SLinus Torvalds fput(bprm->file); 10921da177e4SLinus Torvalds bprm->file = NULL; 10931da177e4SLinus Torvalds current->did_exec = 1; 10949f46080cSMatt Helsley proc_exec_connector(current); 10951da177e4SLinus Torvalds return retval; 10961da177e4SLinus Torvalds } 10971da177e4SLinus Torvalds read_lock(&binfmt_lock); 10981da177e4SLinus Torvalds put_binfmt(fmt); 10991da177e4SLinus Torvalds if (retval != -ENOEXEC || bprm->mm == NULL) 11001da177e4SLinus Torvalds break; 11011da177e4SLinus Torvalds if (!bprm->file) { 11021da177e4SLinus Torvalds read_unlock(&binfmt_lock); 11031da177e4SLinus Torvalds return retval; 11041da177e4SLinus Torvalds } 11051da177e4SLinus Torvalds } 11061da177e4SLinus Torvalds read_unlock(&binfmt_lock); 11071da177e4SLinus Torvalds if (retval != -ENOEXEC || bprm->mm == NULL) { 11081da177e4SLinus Torvalds break; 11091da177e4SLinus Torvalds #ifdef CONFIG_KMOD 11101da177e4SLinus Torvalds }else{ 11111da177e4SLinus Torvalds #define printable(c) (((c)=='\t') || ((c)=='\n') || (0x20<=(c) && (c)<=0x7e)) 11121da177e4SLinus Torvalds if (printable(bprm->buf[0]) && 11131da177e4SLinus Torvalds printable(bprm->buf[1]) && 11141da177e4SLinus Torvalds printable(bprm->buf[2]) && 11151da177e4SLinus Torvalds printable(bprm->buf[3])) 11161da177e4SLinus Torvalds break; /* -ENOEXEC */ 11171da177e4SLinus Torvalds request_module("binfmt-%04x", *(unsigned short *)(&bprm->buf[2])); 11181da177e4SLinus Torvalds #endif 11191da177e4SLinus Torvalds } 11201da177e4SLinus Torvalds } 11211da177e4SLinus Torvalds return retval; 11221da177e4SLinus Torvalds } 11231da177e4SLinus Torvalds 11241da177e4SLinus Torvalds EXPORT_SYMBOL(search_binary_handler); 11251da177e4SLinus Torvalds 11261da177e4SLinus Torvalds /* 11271da177e4SLinus Torvalds * sys_execve() executes a new program. 11281da177e4SLinus Torvalds */ 11291da177e4SLinus Torvalds int do_execve(char * filename, 11301da177e4SLinus Torvalds char __user *__user *argv, 11311da177e4SLinus Torvalds char __user *__user *envp, 11321da177e4SLinus Torvalds struct pt_regs * regs) 11331da177e4SLinus Torvalds { 11341da177e4SLinus Torvalds struct linux_binprm *bprm; 11351da177e4SLinus Torvalds struct file *file; 11361da177e4SLinus Torvalds int retval; 11371da177e4SLinus Torvalds int i; 11381da177e4SLinus Torvalds 11391da177e4SLinus Torvalds retval = -ENOMEM; 11401da177e4SLinus Torvalds bprm = kmalloc(sizeof(*bprm), GFP_KERNEL); 11411da177e4SLinus Torvalds if (!bprm) 11421da177e4SLinus Torvalds goto out_ret; 11431da177e4SLinus Torvalds memset(bprm, 0, sizeof(*bprm)); 11441da177e4SLinus Torvalds 11451da177e4SLinus Torvalds file = open_exec(filename); 11461da177e4SLinus Torvalds retval = PTR_ERR(file); 11471da177e4SLinus Torvalds if (IS_ERR(file)) 11481da177e4SLinus Torvalds goto out_kfree; 11491da177e4SLinus Torvalds 11501da177e4SLinus Torvalds sched_exec(); 11511da177e4SLinus Torvalds 11521da177e4SLinus Torvalds bprm->p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *); 11531da177e4SLinus Torvalds 11541da177e4SLinus Torvalds bprm->file = file; 11551da177e4SLinus Torvalds bprm->filename = filename; 11561da177e4SLinus Torvalds bprm->interp = filename; 11571da177e4SLinus Torvalds bprm->mm = mm_alloc(); 11581da177e4SLinus Torvalds retval = -ENOMEM; 11591da177e4SLinus Torvalds if (!bprm->mm) 11601da177e4SLinus Torvalds goto out_file; 11611da177e4SLinus Torvalds 11621da177e4SLinus Torvalds retval = init_new_context(current, bprm->mm); 11631da177e4SLinus Torvalds if (retval < 0) 11641da177e4SLinus Torvalds goto out_mm; 11651da177e4SLinus Torvalds 11661da177e4SLinus Torvalds bprm->argc = count(argv, bprm->p / sizeof(void *)); 11671da177e4SLinus Torvalds if ((retval = bprm->argc) < 0) 11681da177e4SLinus Torvalds goto out_mm; 11691da177e4SLinus Torvalds 11701da177e4SLinus Torvalds bprm->envc = count(envp, bprm->p / sizeof(void *)); 11711da177e4SLinus Torvalds if ((retval = bprm->envc) < 0) 11721da177e4SLinus Torvalds goto out_mm; 11731da177e4SLinus Torvalds 11741da177e4SLinus Torvalds retval = security_bprm_alloc(bprm); 11751da177e4SLinus Torvalds if (retval) 11761da177e4SLinus Torvalds goto out; 11771da177e4SLinus Torvalds 11781da177e4SLinus Torvalds retval = prepare_binprm(bprm); 11791da177e4SLinus Torvalds if (retval < 0) 11801da177e4SLinus Torvalds goto out; 11811da177e4SLinus Torvalds 11821da177e4SLinus Torvalds retval = copy_strings_kernel(1, &bprm->filename, bprm); 11831da177e4SLinus Torvalds if (retval < 0) 11841da177e4SLinus Torvalds goto out; 11851da177e4SLinus Torvalds 11861da177e4SLinus Torvalds bprm->exec = bprm->p; 11871da177e4SLinus Torvalds retval = copy_strings(bprm->envc, envp, bprm); 11881da177e4SLinus Torvalds if (retval < 0) 11891da177e4SLinus Torvalds goto out; 11901da177e4SLinus Torvalds 11911da177e4SLinus Torvalds retval = copy_strings(bprm->argc, argv, bprm); 11921da177e4SLinus Torvalds if (retval < 0) 11931da177e4SLinus Torvalds goto out; 11941da177e4SLinus Torvalds 11951da177e4SLinus Torvalds retval = search_binary_handler(bprm,regs); 11961da177e4SLinus Torvalds if (retval >= 0) { 11971da177e4SLinus Torvalds free_arg_pages(bprm); 11981da177e4SLinus Torvalds 11991da177e4SLinus Torvalds /* execve success */ 12001da177e4SLinus Torvalds security_bprm_free(bprm); 12011da177e4SLinus Torvalds acct_update_integrals(current); 12021da177e4SLinus Torvalds kfree(bprm); 12031da177e4SLinus Torvalds return retval; 12041da177e4SLinus Torvalds } 12051da177e4SLinus Torvalds 12061da177e4SLinus Torvalds out: 12071da177e4SLinus Torvalds /* Something went wrong, return the inode and free the argument pages*/ 12081da177e4SLinus Torvalds for (i = 0 ; i < MAX_ARG_PAGES ; i++) { 12091da177e4SLinus Torvalds struct page * page = bprm->page[i]; 12101da177e4SLinus Torvalds if (page) 12111da177e4SLinus Torvalds __free_page(page); 12121da177e4SLinus Torvalds } 12131da177e4SLinus Torvalds 12141da177e4SLinus Torvalds if (bprm->security) 12151da177e4SLinus Torvalds security_bprm_free(bprm); 12161da177e4SLinus Torvalds 12171da177e4SLinus Torvalds out_mm: 12181da177e4SLinus Torvalds if (bprm->mm) 12191da177e4SLinus Torvalds mmdrop(bprm->mm); 12201da177e4SLinus Torvalds 12211da177e4SLinus Torvalds out_file: 12221da177e4SLinus Torvalds if (bprm->file) { 12231da177e4SLinus Torvalds allow_write_access(bprm->file); 12241da177e4SLinus Torvalds fput(bprm->file); 12251da177e4SLinus Torvalds } 12261da177e4SLinus Torvalds 12271da177e4SLinus Torvalds out_kfree: 12281da177e4SLinus Torvalds kfree(bprm); 12291da177e4SLinus Torvalds 12301da177e4SLinus Torvalds out_ret: 12311da177e4SLinus Torvalds return retval; 12321da177e4SLinus Torvalds } 12331da177e4SLinus Torvalds 12341da177e4SLinus Torvalds int set_binfmt(struct linux_binfmt *new) 12351da177e4SLinus Torvalds { 12361da177e4SLinus Torvalds struct linux_binfmt *old = current->binfmt; 12371da177e4SLinus Torvalds 12381da177e4SLinus Torvalds if (new) { 12391da177e4SLinus Torvalds if (!try_module_get(new->module)) 12401da177e4SLinus Torvalds return -1; 12411da177e4SLinus Torvalds } 12421da177e4SLinus Torvalds current->binfmt = new; 12431da177e4SLinus Torvalds if (old) 12441da177e4SLinus Torvalds module_put(old->module); 12451da177e4SLinus Torvalds return 0; 12461da177e4SLinus Torvalds } 12471da177e4SLinus Torvalds 12481da177e4SLinus Torvalds EXPORT_SYMBOL(set_binfmt); 12491da177e4SLinus Torvalds 12501da177e4SLinus Torvalds #define CORENAME_MAX_SIZE 64 12511da177e4SLinus Torvalds 12521da177e4SLinus Torvalds /* format_corename will inspect the pattern parameter, and output a 12531da177e4SLinus Torvalds * name into corename, which must have space for at least 12541da177e4SLinus Torvalds * CORENAME_MAX_SIZE bytes plus one byte for the zero terminator. 12551da177e4SLinus Torvalds */ 12561da177e4SLinus Torvalds static void format_corename(char *corename, const char *pattern, long signr) 12571da177e4SLinus Torvalds { 12581da177e4SLinus Torvalds const char *pat_ptr = pattern; 12591da177e4SLinus Torvalds char *out_ptr = corename; 12601da177e4SLinus Torvalds char *const out_end = corename + CORENAME_MAX_SIZE; 12611da177e4SLinus Torvalds int rc; 12621da177e4SLinus Torvalds int pid_in_pattern = 0; 12631da177e4SLinus Torvalds 12641da177e4SLinus Torvalds /* Repeat as long as we have more pattern to process and more output 12651da177e4SLinus Torvalds space */ 12661da177e4SLinus Torvalds while (*pat_ptr) { 12671da177e4SLinus Torvalds if (*pat_ptr != '%') { 12681da177e4SLinus Torvalds if (out_ptr == out_end) 12691da177e4SLinus Torvalds goto out; 12701da177e4SLinus Torvalds *out_ptr++ = *pat_ptr++; 12711da177e4SLinus Torvalds } else { 12721da177e4SLinus Torvalds switch (*++pat_ptr) { 12731da177e4SLinus Torvalds case 0: 12741da177e4SLinus Torvalds goto out; 12751da177e4SLinus Torvalds /* Double percent, output one percent */ 12761da177e4SLinus Torvalds case '%': 12771da177e4SLinus Torvalds if (out_ptr == out_end) 12781da177e4SLinus Torvalds goto out; 12791da177e4SLinus Torvalds *out_ptr++ = '%'; 12801da177e4SLinus Torvalds break; 12811da177e4SLinus Torvalds /* pid */ 12821da177e4SLinus Torvalds case 'p': 12831da177e4SLinus Torvalds pid_in_pattern = 1; 12841da177e4SLinus Torvalds rc = snprintf(out_ptr, out_end - out_ptr, 12851da177e4SLinus Torvalds "%d", current->tgid); 12861da177e4SLinus Torvalds if (rc > out_end - out_ptr) 12871da177e4SLinus Torvalds goto out; 12881da177e4SLinus Torvalds out_ptr += rc; 12891da177e4SLinus Torvalds break; 12901da177e4SLinus Torvalds /* uid */ 12911da177e4SLinus Torvalds case 'u': 12921da177e4SLinus Torvalds rc = snprintf(out_ptr, out_end - out_ptr, 12931da177e4SLinus Torvalds "%d", current->uid); 12941da177e4SLinus Torvalds if (rc > out_end - out_ptr) 12951da177e4SLinus Torvalds goto out; 12961da177e4SLinus Torvalds out_ptr += rc; 12971da177e4SLinus Torvalds break; 12981da177e4SLinus Torvalds /* gid */ 12991da177e4SLinus Torvalds case 'g': 13001da177e4SLinus Torvalds rc = snprintf(out_ptr, out_end - out_ptr, 13011da177e4SLinus Torvalds "%d", current->gid); 13021da177e4SLinus Torvalds if (rc > out_end - out_ptr) 13031da177e4SLinus Torvalds goto out; 13041da177e4SLinus Torvalds out_ptr += rc; 13051da177e4SLinus Torvalds break; 13061da177e4SLinus Torvalds /* signal that caused the coredump */ 13071da177e4SLinus Torvalds case 's': 13081da177e4SLinus Torvalds rc = snprintf(out_ptr, out_end - out_ptr, 13091da177e4SLinus Torvalds "%ld", signr); 13101da177e4SLinus Torvalds if (rc > out_end - out_ptr) 13111da177e4SLinus Torvalds goto out; 13121da177e4SLinus Torvalds out_ptr += rc; 13131da177e4SLinus Torvalds break; 13141da177e4SLinus Torvalds /* UNIX time of coredump */ 13151da177e4SLinus Torvalds case 't': { 13161da177e4SLinus Torvalds struct timeval tv; 13171da177e4SLinus Torvalds do_gettimeofday(&tv); 13181da177e4SLinus Torvalds rc = snprintf(out_ptr, out_end - out_ptr, 13191da177e4SLinus Torvalds "%lu", tv.tv_sec); 13201da177e4SLinus Torvalds if (rc > out_end - out_ptr) 13211da177e4SLinus Torvalds goto out; 13221da177e4SLinus Torvalds out_ptr += rc; 13231da177e4SLinus Torvalds break; 13241da177e4SLinus Torvalds } 13251da177e4SLinus Torvalds /* hostname */ 13261da177e4SLinus Torvalds case 'h': 13271da177e4SLinus Torvalds down_read(&uts_sem); 13281da177e4SLinus Torvalds rc = snprintf(out_ptr, out_end - out_ptr, 13291da177e4SLinus Torvalds "%s", system_utsname.nodename); 13301da177e4SLinus Torvalds up_read(&uts_sem); 13311da177e4SLinus Torvalds if (rc > out_end - out_ptr) 13321da177e4SLinus Torvalds goto out; 13331da177e4SLinus Torvalds out_ptr += rc; 13341da177e4SLinus Torvalds break; 13351da177e4SLinus Torvalds /* executable */ 13361da177e4SLinus Torvalds case 'e': 13371da177e4SLinus Torvalds rc = snprintf(out_ptr, out_end - out_ptr, 13381da177e4SLinus Torvalds "%s", current->comm); 13391da177e4SLinus Torvalds if (rc > out_end - out_ptr) 13401da177e4SLinus Torvalds goto out; 13411da177e4SLinus Torvalds out_ptr += rc; 13421da177e4SLinus Torvalds break; 13431da177e4SLinus Torvalds default: 13441da177e4SLinus Torvalds break; 13451da177e4SLinus Torvalds } 13461da177e4SLinus Torvalds ++pat_ptr; 13471da177e4SLinus Torvalds } 13481da177e4SLinus Torvalds } 13491da177e4SLinus Torvalds /* Backward compatibility with core_uses_pid: 13501da177e4SLinus Torvalds * 13511da177e4SLinus Torvalds * If core_pattern does not include a %p (as is the default) 13521da177e4SLinus Torvalds * and core_uses_pid is set, then .%pid will be appended to 13531da177e4SLinus Torvalds * the filename */ 13541da177e4SLinus Torvalds if (!pid_in_pattern 13551da177e4SLinus Torvalds && (core_uses_pid || atomic_read(¤t->mm->mm_users) != 1)) { 13561da177e4SLinus Torvalds rc = snprintf(out_ptr, out_end - out_ptr, 13571da177e4SLinus Torvalds ".%d", current->tgid); 13581da177e4SLinus Torvalds if (rc > out_end - out_ptr) 13591da177e4SLinus Torvalds goto out; 13601da177e4SLinus Torvalds out_ptr += rc; 13611da177e4SLinus Torvalds } 13621da177e4SLinus Torvalds out: 13631da177e4SLinus Torvalds *out_ptr = 0; 13641da177e4SLinus Torvalds } 13651da177e4SLinus Torvalds 13661da177e4SLinus Torvalds static void zap_threads (struct mm_struct *mm) 13671da177e4SLinus Torvalds { 13681da177e4SLinus Torvalds struct task_struct *g, *p; 13691da177e4SLinus Torvalds struct task_struct *tsk = current; 13701da177e4SLinus Torvalds struct completion *vfork_done = tsk->vfork_done; 13711da177e4SLinus Torvalds int traced = 0; 13721da177e4SLinus Torvalds 13731da177e4SLinus Torvalds /* 13741da177e4SLinus Torvalds * Make sure nobody is waiting for us to release the VM, 13751da177e4SLinus Torvalds * otherwise we can deadlock when we wait on each other 13761da177e4SLinus Torvalds */ 13771da177e4SLinus Torvalds if (vfork_done) { 13781da177e4SLinus Torvalds tsk->vfork_done = NULL; 13791da177e4SLinus Torvalds complete(vfork_done); 13801da177e4SLinus Torvalds } 13811da177e4SLinus Torvalds 13821da177e4SLinus Torvalds read_lock(&tasklist_lock); 13831da177e4SLinus Torvalds do_each_thread(g,p) 13841da177e4SLinus Torvalds if (mm == p->mm && p != tsk) { 13851da177e4SLinus Torvalds force_sig_specific(SIGKILL, p); 13861da177e4SLinus Torvalds mm->core_waiters++; 13871da177e4SLinus Torvalds if (unlikely(p->ptrace) && 13881da177e4SLinus Torvalds unlikely(p->parent->mm == mm)) 13891da177e4SLinus Torvalds traced = 1; 13901da177e4SLinus Torvalds } 13911da177e4SLinus Torvalds while_each_thread(g,p); 13921da177e4SLinus Torvalds 13931da177e4SLinus Torvalds read_unlock(&tasklist_lock); 13941da177e4SLinus Torvalds 13951da177e4SLinus Torvalds if (unlikely(traced)) { 13961da177e4SLinus Torvalds /* 13971da177e4SLinus Torvalds * We are zapping a thread and the thread it ptraces. 13981da177e4SLinus Torvalds * If the tracee went into a ptrace stop for exit tracing, 13991da177e4SLinus Torvalds * we could deadlock since the tracer is waiting for this 14001da177e4SLinus Torvalds * coredump to finish. Detach them so they can both die. 14011da177e4SLinus Torvalds */ 14021da177e4SLinus Torvalds write_lock_irq(&tasklist_lock); 14031da177e4SLinus Torvalds do_each_thread(g,p) { 14041da177e4SLinus Torvalds if (mm == p->mm && p != tsk && 14051da177e4SLinus Torvalds p->ptrace && p->parent->mm == mm) { 14061da177e4SLinus Torvalds __ptrace_unlink(p); 14071da177e4SLinus Torvalds } 14081da177e4SLinus Torvalds } while_each_thread(g,p); 14091da177e4SLinus Torvalds write_unlock_irq(&tasklist_lock); 14101da177e4SLinus Torvalds } 14111da177e4SLinus Torvalds } 14121da177e4SLinus Torvalds 14131da177e4SLinus Torvalds static void coredump_wait(struct mm_struct *mm) 14141da177e4SLinus Torvalds { 14151da177e4SLinus Torvalds DECLARE_COMPLETION(startup_done); 14162384f55fSOleg Nesterov int core_waiters; 14171da177e4SLinus Torvalds 14181da177e4SLinus Torvalds mm->core_startup_done = &startup_done; 14191da177e4SLinus Torvalds 14201da177e4SLinus Torvalds zap_threads(mm); 14212384f55fSOleg Nesterov core_waiters = mm->core_waiters; 14221da177e4SLinus Torvalds up_write(&mm->mmap_sem); 14232384f55fSOleg Nesterov 14242384f55fSOleg Nesterov if (core_waiters) 14251da177e4SLinus Torvalds wait_for_completion(&startup_done); 14261da177e4SLinus Torvalds BUG_ON(mm->core_waiters); 14271da177e4SLinus Torvalds } 14281da177e4SLinus Torvalds 14291da177e4SLinus Torvalds int do_coredump(long signr, int exit_code, struct pt_regs * regs) 14301da177e4SLinus Torvalds { 14311da177e4SLinus Torvalds char corename[CORENAME_MAX_SIZE + 1]; 14321da177e4SLinus Torvalds struct mm_struct *mm = current->mm; 14331da177e4SLinus Torvalds struct linux_binfmt * binfmt; 14341da177e4SLinus Torvalds struct inode * inode; 14351da177e4SLinus Torvalds struct file * file; 14361da177e4SLinus Torvalds int retval = 0; 1437d6e71144SAlan Cox int fsuid = current->fsuid; 1438d6e71144SAlan Cox int flag = 0; 14391da177e4SLinus Torvalds 14401da177e4SLinus Torvalds binfmt = current->binfmt; 14411da177e4SLinus Torvalds if (!binfmt || !binfmt->core_dump) 14421da177e4SLinus Torvalds goto fail; 14431da177e4SLinus Torvalds down_write(&mm->mmap_sem); 14441da177e4SLinus Torvalds if (!mm->dumpable) { 14451da177e4SLinus Torvalds up_write(&mm->mmap_sem); 14461da177e4SLinus Torvalds goto fail; 14471da177e4SLinus Torvalds } 1448d6e71144SAlan Cox 1449d6e71144SAlan Cox /* 1450d6e71144SAlan Cox * We cannot trust fsuid as being the "true" uid of the 1451d6e71144SAlan Cox * process nor do we know its entire history. We only know it 1452d6e71144SAlan Cox * was tainted so we dump it as root in mode 2. 1453d6e71144SAlan Cox */ 1454d6e71144SAlan Cox if (mm->dumpable == 2) { /* Setuid core dump mode */ 1455d6e71144SAlan Cox flag = O_EXCL; /* Stop rewrite attacks */ 1456d6e71144SAlan Cox current->fsuid = 0; /* Dump root private */ 1457d6e71144SAlan Cox } 14581da177e4SLinus Torvalds mm->dumpable = 0; 14591291cf41SOleg Nesterov 14601291cf41SOleg Nesterov retval = -EAGAIN; 14611da177e4SLinus Torvalds spin_lock_irq(¤t->sighand->siglock); 14621291cf41SOleg Nesterov if (!(current->signal->flags & SIGNAL_GROUP_EXIT)) { 14631da177e4SLinus Torvalds current->signal->flags = SIGNAL_GROUP_EXIT; 14641da177e4SLinus Torvalds current->signal->group_exit_code = exit_code; 1465bb6f6dbaSOleg Nesterov current->signal->group_stop_count = 0; 14661291cf41SOleg Nesterov retval = 0; 14671291cf41SOleg Nesterov } 14681da177e4SLinus Torvalds spin_unlock_irq(¤t->sighand->siglock); 14691291cf41SOleg Nesterov if (retval) { 14701291cf41SOleg Nesterov up_write(&mm->mmap_sem); 14711291cf41SOleg Nesterov goto fail; 14721291cf41SOleg Nesterov } 14731291cf41SOleg Nesterov 14741291cf41SOleg Nesterov init_completion(&mm->core_done); 14751da177e4SLinus Torvalds coredump_wait(mm); 14761da177e4SLinus Torvalds 14771da177e4SLinus Torvalds /* 14781da177e4SLinus Torvalds * Clear any false indication of pending signals that might 14791da177e4SLinus Torvalds * be seen by the filesystem code called to write the core file. 14801da177e4SLinus Torvalds */ 14811da177e4SLinus Torvalds clear_thread_flag(TIF_SIGPENDING); 14821da177e4SLinus Torvalds 14831da177e4SLinus Torvalds if (current->signal->rlim[RLIMIT_CORE].rlim_cur < binfmt->min_coredump) 14841da177e4SLinus Torvalds goto fail_unlock; 14851da177e4SLinus Torvalds 14861da177e4SLinus Torvalds /* 14871da177e4SLinus Torvalds * lock_kernel() because format_corename() is controlled by sysctl, which 14881da177e4SLinus Torvalds * uses lock_kernel() 14891da177e4SLinus Torvalds */ 14901da177e4SLinus Torvalds lock_kernel(); 14911da177e4SLinus Torvalds format_corename(corename, core_pattern, signr); 14921da177e4SLinus Torvalds unlock_kernel(); 1493d6e71144SAlan Cox file = filp_open(corename, O_CREAT | 2 | O_NOFOLLOW | O_LARGEFILE | flag, 0600); 14941da177e4SLinus Torvalds if (IS_ERR(file)) 14951da177e4SLinus Torvalds goto fail_unlock; 14961da177e4SLinus Torvalds inode = file->f_dentry->d_inode; 14971da177e4SLinus Torvalds if (inode->i_nlink > 1) 14981da177e4SLinus Torvalds goto close_fail; /* multiple links - don't dump */ 14991da177e4SLinus Torvalds if (d_unhashed(file->f_dentry)) 15001da177e4SLinus Torvalds goto close_fail; 15011da177e4SLinus Torvalds 15021da177e4SLinus Torvalds if (!S_ISREG(inode->i_mode)) 15031da177e4SLinus Torvalds goto close_fail; 15041da177e4SLinus Torvalds if (!file->f_op) 15051da177e4SLinus Torvalds goto close_fail; 15061da177e4SLinus Torvalds if (!file->f_op->write) 15071da177e4SLinus Torvalds goto close_fail; 15084a30131eSNeilBrown if (do_truncate(file->f_dentry, 0, 0, file) != 0) 15091da177e4SLinus Torvalds goto close_fail; 15101da177e4SLinus Torvalds 15111da177e4SLinus Torvalds retval = binfmt->core_dump(signr, regs, file); 15121da177e4SLinus Torvalds 15131da177e4SLinus Torvalds if (retval) 15141da177e4SLinus Torvalds current->signal->group_exit_code |= 0x80; 15151da177e4SLinus Torvalds close_fail: 15161da177e4SLinus Torvalds filp_close(file, NULL); 15171da177e4SLinus Torvalds fail_unlock: 1518d6e71144SAlan Cox current->fsuid = fsuid; 15191da177e4SLinus Torvalds complete_all(&mm->core_done); 15201da177e4SLinus Torvalds fail: 15211da177e4SLinus Torvalds return retval; 15221da177e4SLinus Torvalds } 1523