From: Linus Torvalds Date: Wed, 10 Oct 2012 03:02:25 +0000 (+0900) Subject: Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=42859eea96ba6beabfb0369a1eeffa3c7d2bd9cb;p=GitHub%2FLineageOS%2Fandroid_kernel_motorola_exynos9610.git Merge branch 'for-linus' of git://git./linux/kernel/git/viro/signal Pull generic execve() changes from Al Viro: "This introduces the generic kernel_thread() and kernel_execve() functions, and switches x86, arm, alpha, um and s390 over to them." * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal: (26 commits) s390: convert to generic kernel_execve() s390: switch to generic kernel_thread() s390: fold kernel_thread_helper() into ret_from_fork() s390: fold execve_tail() into start_thread(), convert to generic sys_execve() um: switch to generic kernel_thread() x86, um/x86: switch to generic sys_execve and kernel_execve x86: split ret_from_fork alpha: introduce ret_from_kernel_execve(), switch to generic kernel_execve() alpha: switch to generic kernel_thread() alpha: switch to generic sys_execve() arm: get rid of execve wrapper, switch to generic execve() implementation arm: optimized current_pt_regs() arm: introduce ret_from_kernel_execve(), switch to generic kernel_execve() arm: split ret_from_fork, simplify kernel_thread() [based on patch by rmk] generic sys_execve() generic kernel_execve() new helper: current_pt_regs() preparation for generic kernel_thread() um: kill thread->forking um: let signal_delivered() do SIGTRAP on singlestepping into handler ... --- 42859eea96ba6beabfb0369a1eeffa3c7d2bd9cb diff --cc arch/avr32/include/asm/Kbuild index e3ba7bca06fa,aa47fff70760..be0433ee5a8e --- a/arch/avr32/include/asm/Kbuild +++ b/arch/avr32/include/asm/Kbuild @@@ -1,5 -1,4 +1,6 @@@ include include/asm-generic/Kbuild.asm +generic-y += clkdev.h + generic-y += exec.h + header-y += cachectl.h diff --cc arch/cris/include/asm/Kbuild index a8eab26a1ec7,b68ad4bfa088..ff1bf7fcae8e --- a/arch/cris/include/asm/Kbuild +++ b/arch/cris/include/asm/Kbuild @@@ -8,4 -8,4 +8,5 @@@ header-y += etraxgpio. header-y += rs485.h header-y += sync_serial.h +generic-y += clkdev.h + generic-y += exec.h diff --cc arch/frv/include/asm/Kbuild index 13cd044aabdf,32c16468cf5e..251bd7125576 --- a/arch/frv/include/asm/Kbuild +++ b/arch/frv/include/asm/Kbuild @@@ -2,4 -2,4 +2,5 @@@ include include/asm-generic/Kbuild.as header-y += registers.h header-y += termios.h +generic-y += clkdev.h + generic-y += exec.h diff --cc arch/h8300/include/asm/Kbuild index 0e152a93c125,3a2af1a2974f..fccd81eddff1 --- a/arch/h8300/include/asm/Kbuild +++ b/arch/h8300/include/asm/Kbuild @@@ -1,3 -1,2 +1,4 @@@ include include/asm-generic/Kbuild.asm + - generic-y += clkdev.h ++generic-y += clkdev.h + generic-y += exec.h diff --cc arch/ia64/include/asm/Kbuild index 58f3d14a6cd4,98efd48d7da4..562f59315847 --- a/arch/ia64/include/asm/Kbuild +++ b/arch/ia64/include/asm/Kbuild @@@ -13,4 -13,4 +13,5 @@@ header-y += ptrace_offsets. header-y += rse.h header-y += ucontext.h header-y += ustack.h +generic-y += clkdev.h + generic-y += exec.h diff --cc arch/m32r/include/asm/Kbuild index 0e152a93c125,708340339b05..fccd81eddff1 --- a/arch/m32r/include/asm/Kbuild +++ b/arch/m32r/include/asm/Kbuild @@@ -1,3 -1,3 +1,4 @@@ include include/asm-generic/Kbuild.asm - generic-y += clkdev.h ++generic-y += clkdev.h + generic-y += exec.h diff --cc arch/microblaze/include/asm/Kbuild index 48510f6cec8f,5a0e72bf998d..8653072d7e9f --- a/arch/microblaze/include/asm/Kbuild +++ b/arch/microblaze/include/asm/Kbuild @@@ -1,4 -1,4 +1,5 @@@ include include/asm-generic/Kbuild.asm header-y += elf.h +generic-y += clkdev.h + generic-y += exec.h diff --cc arch/mn10300/include/asm/Kbuild index 0d20f5526dd8,708340339b05..fccd81eddff1 --- a/arch/mn10300/include/asm/Kbuild +++ b/arch/mn10300/include/asm/Kbuild @@@ -1,3 -1,3 +1,4 @@@ include include/asm-generic/Kbuild.asm +generic-y += clkdev.h + generic-y += exec.h diff --cc arch/parisc/include/asm/Kbuild index 0587f62e5b76,818d65165678..458371a1565a --- a/arch/parisc/include/asm/Kbuild +++ b/arch/parisc/include/asm/Kbuild @@@ -1,5 -1,5 +1,6 @@@ include include/asm-generic/Kbuild.asm header-y += pdc.h +generic-y += clkdev.h generic-y += word-at-a-time.h + generic-y += exec.h diff --cc arch/s390/include/asm/processor.h index 56831dfa9198,da6f5baeee5c..94e749c90230 --- a/arch/s390/include/asm/processor.h +++ b/arch/s390/include/asm/processor.h @@@ -142,15 -133,8 +145,14 @@@ struct task_struct struct mm_struct; struct seq_file; +#ifdef CONFIG_64BIT +extern void show_cacheinfo(struct seq_file *m); +#else +static inline void show_cacheinfo(struct seq_file *m) { } +#endif + /* Free all resources held by a thread. */ extern void release_thread(struct task_struct *); - extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); /* * Return saved PC of a blocked thread. diff --cc arch/s390/kernel/process.c index 5024be27df44,bab088de4569..cd31ad457a9b --- a/arch/s390/kernel/process.c +++ b/arch/s390/kernel/process.c @@@ -169,15 -146,25 +149,30 @@@ int copy_thread(unsigned long clone_fla /* fake return stack for resume(), don't go back to schedule */ frame->sf.gprs[9] = (unsigned long) frame; - /* Save access registers to new thread structure. */ - save_access_regs(&p->thread.acrs[0]); + /* Store access registers to kernel stack of new process. */ + if (unlikely(!regs)) { + /* kernel thread */ + memset(&frame->childregs, 0, sizeof(struct pt_regs)); + frame->childregs.psw.mask = psw_kernel_bits | PSW_MASK_DAT | + PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK; + frame->childregs.psw.addr = PSW_ADDR_AMODE | + (unsigned long) kernel_thread_starter; + frame->childregs.gprs[9] = new_stackp; /* function */ + frame->childregs.gprs[10] = arg; + frame->childregs.gprs[11] = (unsigned long) do_exit; + frame->childregs.orig_gpr2 = -1; + + return 0; + } + frame->childregs = *regs; + frame->childregs.gprs[2] = 0; /* child returns 0 on fork. */ + frame->childregs.gprs[15] = new_stackp; + /* Don't copy runtime instrumentation info */ + p->thread.ri_cb = NULL; + p->thread.ri_signum = 0; + frame->childregs.psw.mask &= ~PSW_MASK_RI; + #ifndef CONFIG_64BIT /* * save fprs to current->thread.fp_regs to merge them with diff --cc arch/sparc/include/asm/Kbuild index 61d41c11ee0a,cf1e85782703..10d54e5e37f5 --- a/arch/sparc/include/asm/Kbuild +++ b/arch/sparc/include/asm/Kbuild @@@ -1,8 -1,24 +1,9 @@@ # User exported sparc header files -include include/asm-generic/Kbuild.asm -header-y += apc.h -header-y += asi.h -header-y += display7seg.h -header-y += envctrl.h -header-y += fbio.h -header-y += jsflash.h -header-y += openpromio.h -header-y += perfctr.h -header-y += psrcompat.h -header-y += psr.h -header-y += pstate.h -header-y += traps.h -header-y += uctx.h -header-y += utrap.h -header-y += watchdog.h +generic-y += clkdev.h generic-y += div64.h + generic-y += exec.h generic-y += local64.h generic-y += irq_regs.h generic-y += local.h diff --cc arch/um/kernel/exec.c index de66c421ae9d,e427301f55d6..ab019c7f0b57 --- a/arch/um/kernel/exec.c +++ b/arch/um/kernel/exec.c @@@ -12,11 -12,10 +12,10 @@@ #include #include #include -#include "as-layout.h" -#include "mem_user.h" -#include "skas.h" -#include "os.h" +#include +#include +#include +#include - #include "internal.h" void flush_thread(void) { diff --cc arch/um/kernel/syscall.c index 10808bda3671,a5639c472772..a81f3705e90f --- a/arch/um/kernel/syscall.c +++ b/arch/um/kernel/syscall.c @@@ -3,17 -3,16 +3,16 @@@ * Licensed under the GPL */ -#include "linux/file.h" -#include "linux/fs.h" -#include "linux/mm.h" -#include "linux/sched.h" -#include "linux/utsname.h" -#include "linux/syscalls.h" -#include "asm/current.h" -#include "asm/mman.h" -#include "asm/uaccess.h" -#include "asm/unistd.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include - #include "internal.h" long sys_fork(void) { diff --cc arch/x86/Kconfig index 1ae94bcae5d9,d93eb9d1bb97..42d2c35a5bbd --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@@ -106,12 -97,10 +106,13 @@@ config X8 select KTIME_SCALAR if X86_32 select GENERIC_STRNCPY_FROM_USER select GENERIC_STRNLEN_USER + select HAVE_RCU_USER_QS if X86_64 + select HAVE_IRQ_TIME_ACCOUNTING + select GENERIC_KERNEL_THREAD config INSTRUCTION_DECODER - def_bool (KPROBES || PERF_EVENTS || UPROBES) + def_bool y + depends on KPROBES || PERF_EVENTS || UPROBES config OUTPUT_FORMAT string diff --cc arch/x86/kernel/process_32.c index b9ff83c7135b,25e7e9390d26..44e0bff38e72 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c @@@ -190,6 -207,16 +207,12 @@@ start_thread(struct pt_regs *regs, unsi regs->cs = __USER_CS; regs->ip = new_ip; regs->sp = new_sp; + regs->flags = X86_EFLAGS_IF; - /* - * Free the old FP and other extended state - */ - free_thread_xstate(current); + /* + * force it to the iret return path by making it look as if there was + * some work pending. + */ + set_thread_flag(TIF_NOTIFY_RESUME); } EXPORT_SYMBOL_GPL(start_thread); diff --cc arch/x86/kernel/signal.c index b33144c8b309,c648fc529872..29ad351804e9 --- a/arch/x86/kernel/signal.c +++ b/arch/x86/kernel/signal.c @@@ -839,12 -800,6 +839,8 @@@ do_notify_resume(struct pt_regs *regs, } if (thread_info_flags & _TIF_USER_RETURN_NOTIFY) fire_user_return_notifiers(); + - #ifdef CONFIG_X86_32 - clear_thread_flag(TIF_IRET); - #endif /* CONFIG_X86_32 */ - + rcu_user_enter(); } void signal_fault(struct pt_regs *regs, void __user *frame, char *where) diff --cc arch/xtensa/include/asm/Kbuild index 0d20f5526dd8,708340339b05..fccd81eddff1 --- a/arch/xtensa/include/asm/Kbuild +++ b/arch/xtensa/include/asm/Kbuild @@@ -1,3 -1,3 +1,4 @@@ include include/asm-generic/Kbuild.asm +generic-y += clkdev.h + generic-y += exec.h diff --cc fs/binfmt_elf.c index e800dec958c3,2ab91905b2e2..fbd9f60bd763 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@@ -36,15 -35,7 +36,14 @@@ #include #include #include - #include +#ifndef user_long_t +#define user_long_t long +#endif +#ifndef user_siginfo_t +#define user_siginfo_t siginfo_t +#endif + static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs); static int load_elf_library(struct file *); static unsigned long elf_map(struct file *, unsigned long, struct elf_phdr *, diff --cc fs/exec.c index 4f2bebc276c5,50a1270da95b..ca434534ae9a --- a/fs/exec.c +++ b/fs/exec.c @@@ -1658,3 -2031,342 +1657,55 @@@ int get_dumpable(struct mm_struct *mm { return __get_dumpable(mm->flags); } + -static void wait_for_dump_helpers(struct file *file) -{ - struct pipe_inode_info *pipe; - - pipe = file->f_path.dentry->d_inode->i_pipe; - - pipe_lock(pipe); - pipe->readers++; - pipe->writers--; - - while ((pipe->readers > 1) && (!signal_pending(current))) { - wake_up_interruptible_sync(&pipe->wait); - kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN); - pipe_wait(pipe); - } - - pipe->readers--; - pipe->writers++; - pipe_unlock(pipe); - -} - - -/* - * umh_pipe_setup - * helper function to customize the process used - * to collect the core in userspace. Specifically - * it sets up a pipe and installs it as fd 0 (stdin) - * for the process. Returns 0 on success, or - * PTR_ERR on failure. - * Note that it also sets the core limit to 1. This - * is a special value that we use to trap recursive - * core dumps - */ -static int umh_pipe_setup(struct subprocess_info *info, struct cred *new) -{ - struct file *files[2]; - struct fdtable *fdt; - struct coredump_params *cp = (struct coredump_params *)info->data; - struct files_struct *cf = current->files; - int err = create_pipe_files(files, 0); - if (err) - return err; - - cp->file = files[1]; - - sys_close(0); - fd_install(0, files[0]); - spin_lock(&cf->file_lock); - fdt = files_fdtable(cf); - __set_open_fd(0, fdt); - __clear_close_on_exec(0, fdt); - spin_unlock(&cf->file_lock); - - /* and disallow core files too */ - current->signal->rlim[RLIMIT_CORE] = (struct rlimit){1, 1}; - - return 0; -} - -void do_coredump(long signr, int exit_code, struct pt_regs *regs) -{ - struct core_state core_state; - struct core_name cn; - struct mm_struct *mm = current->mm; - struct linux_binfmt * binfmt; - const struct cred *old_cred; - struct cred *cred; - int retval = 0; - int flag = 0; - int ispipe; - bool need_nonrelative = false; - static atomic_t core_dump_count = ATOMIC_INIT(0); - struct coredump_params cprm = { - .signr = signr, - .regs = regs, - .limit = rlimit(RLIMIT_CORE), - /* - * We must use the same mm->flags while dumping core to avoid - * inconsistency of bit flags, since this flag is not protected - * by any locks. - */ - .mm_flags = mm->flags, - }; - - audit_core_dumps(signr); - - binfmt = mm->binfmt; - if (!binfmt || !binfmt->core_dump) - goto fail; - if (!__get_dumpable(cprm.mm_flags)) - goto fail; - - cred = prepare_creds(); - if (!cred) - goto fail; - /* - * We cannot trust fsuid as being the "true" uid of the process - * nor do we know its entire history. We only know it was tainted - * so we dump it as root in mode 2, and only into a controlled - * environment (pipe handler or fully qualified path). - */ - if (__get_dumpable(cprm.mm_flags) == SUID_DUMPABLE_SAFE) { - /* Setuid core dump mode */ - flag = O_EXCL; /* Stop rewrite attacks */ - cred->fsuid = GLOBAL_ROOT_UID; /* Dump root private */ - need_nonrelative = true; - } - - retval = coredump_wait(exit_code, &core_state); - if (retval < 0) - goto fail_creds; - - old_cred = override_creds(cred); - - /* - * Clear any false indication of pending signals that might - * be seen by the filesystem code called to write the core file. - */ - clear_thread_flag(TIF_SIGPENDING); - - ispipe = format_corename(&cn, signr); - - if (ispipe) { - int dump_count; - char **helper_argv; - - if (ispipe < 0) { - printk(KERN_WARNING "format_corename failed\n"); - printk(KERN_WARNING "Aborting core\n"); - goto fail_corename; - } - - if (cprm.limit == 1) { - /* See umh_pipe_setup() which sets RLIMIT_CORE = 1. - * - * Normally core limits are irrelevant to pipes, since - * we're not writing to the file system, but we use - * cprm.limit of 1 here as a speacial value, this is a - * consistent way to catch recursive crashes. - * We can still crash if the core_pattern binary sets - * RLIM_CORE = !1, but it runs as root, and can do - * lots of stupid things. - * - * Note that we use task_tgid_vnr here to grab the pid - * of the process group leader. That way we get the - * right pid if a thread in a multi-threaded - * core_pattern process dies. - */ - printk(KERN_WARNING - "Process %d(%s) has RLIMIT_CORE set to 1\n", - task_tgid_vnr(current), current->comm); - printk(KERN_WARNING "Aborting core\n"); - goto fail_unlock; - } - cprm.limit = RLIM_INFINITY; - - dump_count = atomic_inc_return(&core_dump_count); - if (core_pipe_limit && (core_pipe_limit < dump_count)) { - printk(KERN_WARNING "Pid %d(%s) over core_pipe_limit\n", - task_tgid_vnr(current), current->comm); - printk(KERN_WARNING "Skipping core dump\n"); - goto fail_dropcount; - } - - helper_argv = argv_split(GFP_KERNEL, cn.corename+1, NULL); - if (!helper_argv) { - printk(KERN_WARNING "%s failed to allocate memory\n", - __func__); - goto fail_dropcount; - } - - retval = call_usermodehelper_fns(helper_argv[0], helper_argv, - NULL, UMH_WAIT_EXEC, umh_pipe_setup, - NULL, &cprm); - argv_free(helper_argv); - if (retval) { - printk(KERN_INFO "Core dump to %s pipe failed\n", - cn.corename); - goto close_fail; - } - } else { - struct inode *inode; - - if (cprm.limit < binfmt->min_coredump) - goto fail_unlock; - - if (need_nonrelative && cn.corename[0] != '/') { - printk(KERN_WARNING "Pid %d(%s) can only dump core "\ - "to fully qualified path!\n", - task_tgid_vnr(current), current->comm); - printk(KERN_WARNING "Skipping core dump\n"); - goto fail_unlock; - } - - cprm.file = filp_open(cn.corename, - O_CREAT | 2 | O_NOFOLLOW | O_LARGEFILE | flag, - 0600); - if (IS_ERR(cprm.file)) - goto fail_unlock; - - inode = cprm.file->f_path.dentry->d_inode; - if (inode->i_nlink > 1) - goto close_fail; - if (d_unhashed(cprm.file->f_path.dentry)) - goto close_fail; - /* - * AK: actually i see no reason to not allow this for named - * pipes etc, but keep the previous behaviour for now. - */ - if (!S_ISREG(inode->i_mode)) - goto close_fail; - /* - * Dont allow local users get cute and trick others to coredump - * into their pre-created files. - */ - if (!uid_eq(inode->i_uid, current_fsuid())) - goto close_fail; - if (!cprm.file->f_op || !cprm.file->f_op->write) - goto close_fail; - if (do_truncate(cprm.file->f_path.dentry, 0, 0, cprm.file)) - goto close_fail; - } - - retval = binfmt->core_dump(&cprm); - if (retval) - current->signal->group_exit_code |= 0x80; - - if (ispipe && core_pipe_limit) - wait_for_dump_helpers(cprm.file); -close_fail: - if (cprm.file) - filp_close(cprm.file, NULL); -fail_dropcount: - if (ispipe) - atomic_dec(&core_dump_count); -fail_unlock: - kfree(cn.corename); -fail_corename: - coredump_finish(mm); - revert_creds(old_cred); -fail_creds: - put_cred(cred); -fail: - return; -} - -/* - * Core dumping helper functions. These are the only things you should - * do on a core-file: use only these functions to write out all the - * necessary info. - */ -int dump_write(struct file *file, const void *addr, int nr) -{ - return access_ok(VERIFY_READ, addr, nr) && file->f_op->write(file, addr, nr, &file->f_pos) == nr; -} -EXPORT_SYMBOL(dump_write); - -int dump_seek(struct file *file, loff_t off) -{ - int ret = 1; - - if (file->f_op->llseek && file->f_op->llseek != no_llseek) { - if (file->f_op->llseek(file, off, SEEK_CUR) < 0) - return 0; - } else { - char *buf = (char *)get_zeroed_page(GFP_KERNEL); - - if (!buf) - return 0; - while (off > 0) { - unsigned long n = off; - - if (n > PAGE_SIZE) - n = PAGE_SIZE; - if (!dump_write(file, buf, n)) { - ret = 0; - break; - } - off -= n; - } - free_page((unsigned long)buf); - } - return ret; -} -EXPORT_SYMBOL(dump_seek); - + #ifdef __ARCH_WANT_SYS_EXECVE + SYSCALL_DEFINE3(execve, + const char __user *, filename, + const char __user *const __user *, argv, + const char __user *const __user *, envp) + { + const char *path = getname(filename); + int error = PTR_ERR(path); + if (!IS_ERR(path)) { + error = do_execve(path, argv, envp, current_pt_regs()); + putname(path); + } + return error; + } + #ifdef CONFIG_COMPAT + asmlinkage long compat_sys_execve(const char __user * filename, + const compat_uptr_t __user * argv, + const compat_uptr_t __user * envp) + { + const char *path = getname(filename); + int error = PTR_ERR(path); + if (!IS_ERR(path)) { + error = compat_do_execve(path, argv, envp, current_pt_regs()); + putname(path); + } + return error; + } + #endif + #endif + + #ifdef __ARCH_WANT_KERNEL_EXECVE + int kernel_execve(const char *filename, + const char *const argv[], + const char *const envp[]) + { + struct pt_regs *p = current_pt_regs(); + int ret; + + ret = do_execve(filename, + (const char __user *const __user *)argv, + (const char __user *const __user *)envp, p); + if (ret < 0) + return ret; + + /* + * We were successful. We won't be returning to our caller, but + * instead to user space by manipulating the kernel stack. + */ + ret_from_kernel_execve(p); + } + #endif