VisionFive2 Linux kernel

StarFive Tech Linux Kernel for VisionFive (JH7110) boards (mirror)

More than 9999 Commits   32 Branches   54 Tags
09c434b8a0047 (Thomas Gleixner         2019-05-19 13:08:20 +0100    1) // SPDX-License-Identifier: GPL-2.0-only
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700    2) /*
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700    3)  * linux/fs/binfmt_elf.c
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700    4)  *
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700    5)  * These are the functions used to load ELF format executables as used
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700    6)  * on SVr4 machines.  Information on the format may be found in the book
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700    7)  * "UNIX SYSTEM V RELEASE 4 Programmers Guide: Ansi C and Programming Support
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700    8)  * Tools".
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700    9)  *
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700   10)  * Copyright 1993, 1994: Eric Youngdale (ericy@cais.com).
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700   11)  */
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700   12) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700   13) #include <linux/module.h>
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700   14) #include <linux/kernel.h>
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700   15) #include <linux/fs.h>
ce81bb256a224 (Chris Kennelly          2020-10-15 20:12:32 -0700   16) #include <linux/log2.h>
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700   17) #include <linux/mm.h>
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700   18) #include <linux/mman.h>
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700   19) #include <linux/errno.h>
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700   20) #include <linux/signal.h>
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700   21) #include <linux/binfmts.h>
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700   22) #include <linux/string.h>
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700   23) #include <linux/file.h>
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700   24) #include <linux/slab.h>
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700   25) #include <linux/personality.h>
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700   26) #include <linux/elfcore.h>
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700   27) #include <linux/init.h>
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700   28) #include <linux/highuid.h>
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700   29) #include <linux/compiler.h>
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700   30) #include <linux/highmem.h>
03911132aafd6 (Anshuman Khandual       2020-04-06 20:03:51 -0700   31) #include <linux/hugetlb.h>
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700   32) #include <linux/pagemap.h>
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700   33) #include <linux/vmalloc.h>
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700   34) #include <linux/security.h>
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700   35) #include <linux/random.h>
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700   36) #include <linux/elf.h>
d1fd836dcf00d (Kees Cook               2015-04-14 15:48:07 -0700   37) #include <linux/elf-randomize.h>
7e80d0d0b64f5 (Alexey Dobriyan         2007-05-08 00:28:59 -0700   38) #include <linux/utsname.h>
088e7af73a962 (Daisuke HATAYAMA        2010-03-05 13:44:06 -0800   39) #include <linux/coredump.h>
6fac4829ce0ef (Frederic Weisbecker     2012-11-13 14:20:55 +0100   40) #include <linux/sched.h>
f7ccbae45c5e2 (Ingo Molnar             2017-02-08 18:51:30 +0100   41) #include <linux/sched/coredump.h>
68db0cf106786 (Ingo Molnar             2017-02-08 18:51:37 +0100   42) #include <linux/sched/task_stack.h>
32ef5517c2980 (Ingo Molnar             2017-02-05 11:48:36 +0100   43) #include <linux/sched/cputime.h>
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000   44) #include <linux/sizes.h>
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000   45) #include <linux/types.h>
5b825c3af1d8a (Ingo Molnar             2017-02-02 17:54:15 +0100   46) #include <linux/cred.h>
5037835c1f3ea (Ross Zwisler            2015-10-05 16:33:36 -0600   47) #include <linux/dax.h>
7c0f6ba682b9c (Linus Torvalds          2016-12-24 11:46:01 -0800   48) #include <linux/uaccess.h>
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700   49) #include <asm/param.h>
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700   50) #include <asm/page.h>
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700   51) 
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000   52) #ifndef ELF_COMPAT
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000   53) #define ELF_COMPAT 0
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000   54) #endif
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000   55) 
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700   56) #ifndef user_long_t
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700   57) #define user_long_t long
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700   58) #endif
49ae4d4b113be (Denys Vlasenko          2012-10-04 17:15:35 -0700   59) #ifndef user_siginfo_t
49ae4d4b113be (Denys Vlasenko          2012-10-04 17:15:35 -0700   60) #define user_siginfo_t siginfo_t
49ae4d4b113be (Denys Vlasenko          2012-10-04 17:15:35 -0700   61) #endif
49ae4d4b113be (Denys Vlasenko          2012-10-04 17:15:35 -0700   62) 
4755200b6b116 (Nicolas Pitre           2017-08-16 16:05:13 -0400   63) /* That's for binfmt_elf_fdpic to deal with */
4755200b6b116 (Nicolas Pitre           2017-08-16 16:05:13 -0400   64) #ifndef elf_check_fdpic
4755200b6b116 (Nicolas Pitre           2017-08-16 16:05:13 -0400   65) #define elf_check_fdpic(ex) false
4755200b6b116 (Nicolas Pitre           2017-08-16 16:05:13 -0400   66) #endif
4755200b6b116 (Nicolas Pitre           2017-08-16 16:05:13 -0400   67) 
71613c3b871c5 (Al Viro                 2012-10-20 22:00:48 -0400   68) static int load_elf_binary(struct linux_binprm *bprm);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700   69) 
69369a7003735 (Josh Triplett           2014-04-03 14:48:27 -0700   70) #ifdef CONFIG_USELIB
69369a7003735 (Josh Triplett           2014-04-03 14:48:27 -0700   71) static int load_elf_library(struct file *);
69369a7003735 (Josh Triplett           2014-04-03 14:48:27 -0700   72) #else
69369a7003735 (Josh Triplett           2014-04-03 14:48:27 -0700   73) #define load_elf_library NULL
69369a7003735 (Josh Triplett           2014-04-03 14:48:27 -0700   74) #endif
69369a7003735 (Josh Triplett           2014-04-03 14:48:27 -0700   75) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700   76) /*
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700   77)  * If we don't support core dumping, then supply a NULL so we
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700   78)  * don't even try.
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700   79)  */
698ba7b5a3a7b (Christoph Hellwig       2009-12-15 16:47:37 -0800   80) #ifdef CONFIG_ELF_CORE
f6151dfea2149 (Masami Hiramatsu        2009-12-17 15:27:16 -0800   81) static int elf_core_dump(struct coredump_params *cprm);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700   82) #else
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700   83) #define elf_core_dump	NULL
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700   84) #endif
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700   85) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700   86) #if ELF_EXEC_PAGESIZE > PAGE_SIZE
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700   87) #define ELF_MIN_ALIGN	ELF_EXEC_PAGESIZE
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700   88) #else
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700   89) #define ELF_MIN_ALIGN	PAGE_SIZE
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700   90) #endif
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700   91) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700   92) #ifndef ELF_CORE_EFLAGS
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700   93) #define ELF_CORE_EFLAGS	0
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700   94) #endif
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700   95) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700   96) #define ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(ELF_MIN_ALIGN-1))
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700   97) #define ELF_PAGEOFFSET(_v) ((_v) & (ELF_MIN_ALIGN-1))
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700   98) #define ELF_PAGEALIGN(_v) (((_v) + ELF_MIN_ALIGN - 1) & ~(ELF_MIN_ALIGN - 1))
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700   99) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  100) static struct linux_binfmt elf_format = {
f670d0ecda73b (Mikael Pettersson       2011-01-12 17:00:02 -0800  101) 	.module		= THIS_MODULE,
f670d0ecda73b (Mikael Pettersson       2011-01-12 17:00:02 -0800  102) 	.load_binary	= load_elf_binary,
f670d0ecda73b (Mikael Pettersson       2011-01-12 17:00:02 -0800  103) 	.load_shlib	= load_elf_library,
f670d0ecda73b (Mikael Pettersson       2011-01-12 17:00:02 -0800  104) 	.core_dump	= elf_core_dump,
f670d0ecda73b (Mikael Pettersson       2011-01-12 17:00:02 -0800  105) 	.min_coredump	= ELF_EXEC_PAGESIZE,
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  106) };
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  107) 
18676ffcee596 (Alexey Dobriyan         2020-01-30 22:17:01 -0800  108) #define BAD_ADDR(x) (unlikely((unsigned long)(x) >= TASK_SIZE))
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  109) 
16e72e9b30986 (Denys Vlasenko          2017-02-22 15:45:16 -0800  110) static int set_brk(unsigned long start, unsigned long end, int prot)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  111) {
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  112) 	start = ELF_PAGEALIGN(start);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  113) 	end = ELF_PAGEALIGN(end);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  114) 	if (end > start) {
16e72e9b30986 (Denys Vlasenko          2017-02-22 15:45:16 -0800  115) 		/*
16e72e9b30986 (Denys Vlasenko          2017-02-22 15:45:16 -0800  116) 		 * Map the last of the bss segment.
16e72e9b30986 (Denys Vlasenko          2017-02-22 15:45:16 -0800  117) 		 * If the header is requesting these pages to be
16e72e9b30986 (Denys Vlasenko          2017-02-22 15:45:16 -0800  118) 		 * executable, honour that (ppc32 needs this).
16e72e9b30986 (Denys Vlasenko          2017-02-22 15:45:16 -0800  119) 		 */
16e72e9b30986 (Denys Vlasenko          2017-02-22 15:45:16 -0800  120) 		int error = vm_brk_flags(start, end - start,
16e72e9b30986 (Denys Vlasenko          2017-02-22 15:45:16 -0800  121) 				prot & PROT_EXEC ? VM_EXEC : 0);
5d22fc25d4fc8 (Linus Torvalds          2016-05-27 15:57:31 -0700  122) 		if (error)
5d22fc25d4fc8 (Linus Torvalds          2016-05-27 15:57:31 -0700  123) 			return error;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  124) 	}
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  125) 	current->mm->start_brk = current->mm->brk = end;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  126) 	return 0;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  127) }
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  128) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  129) /* We need to explicitly zero any fractional pages
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  130)    after the data section (i.e. bss).  This would
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  131)    contain the junk from the file that should not
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700  132)    be in memory
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700  133)  */
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  134) static int padzero(unsigned long elf_bss)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  135) {
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  136) 	unsigned long nbyte;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  137) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  138) 	nbyte = ELF_PAGEOFFSET(elf_bss);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  139) 	if (nbyte) {
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  140) 		nbyte = ELF_MIN_ALIGN - nbyte;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  141) 		if (clear_user((void __user *) elf_bss, nbyte))
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  142) 			return -EFAULT;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  143) 	}
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  144) 	return 0;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  145) }
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  146) 
09c6dd3c9d99b (Ohad Ben-Cohen          2008-02-03 18:05:15 +0200  147) /* Let's use some macros to make this stack manipulation a little clearer */
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  148) #ifdef CONFIG_STACK_GROWSUP
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  149) #define STACK_ADD(sp, items) ((elf_addr_t __user *)(sp) + (items))
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  150) #define STACK_ROUND(sp, items) \
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  151) 	((15 + (unsigned long) ((sp) + (items))) &~ 15UL)
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700  152) #define STACK_ALLOC(sp, len) ({ \
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700  153) 	elf_addr_t __user *old_sp = (elf_addr_t __user *)sp; sp += len; \
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700  154) 	old_sp; })
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  155) #else
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  156) #define STACK_ADD(sp, items) ((elf_addr_t __user *)(sp) - (items))
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  157) #define STACK_ROUND(sp, items) \
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  158) 	(((unsigned long) (sp - items)) &~ 15UL)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  159) #define STACK_ALLOC(sp, len) ({ sp -= len ; sp; })
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  160) #endif
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  161) 
483fad1c3fa10 (Nathan Lynch            2008-07-22 04:48:46 +1000  162) #ifndef ELF_BASE_PLATFORM
483fad1c3fa10 (Nathan Lynch            2008-07-22 04:48:46 +1000  163) /*
483fad1c3fa10 (Nathan Lynch            2008-07-22 04:48:46 +1000  164)  * AT_BASE_PLATFORM indicates the "real" hardware/microarchitecture.
483fad1c3fa10 (Nathan Lynch            2008-07-22 04:48:46 +1000  165)  * If the arch defines ELF_BASE_PLATFORM (in asm/elf.h), the value
483fad1c3fa10 (Nathan Lynch            2008-07-22 04:48:46 +1000  166)  * will be copied to the user stack in the same manner as AT_PLATFORM.
483fad1c3fa10 (Nathan Lynch            2008-07-22 04:48:46 +1000  167)  */
483fad1c3fa10 (Nathan Lynch            2008-07-22 04:48:46 +1000  168) #define ELF_BASE_PLATFORM NULL
483fad1c3fa10 (Nathan Lynch            2008-07-22 04:48:46 +1000  169) #endif
483fad1c3fa10 (Nathan Lynch            2008-07-22 04:48:46 +1000  170) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  171) static int
a62c5b1b6647e (Alexey Dobriyan         2020-01-30 22:16:55 -0800  172) create_elf_tables(struct linux_binprm *bprm, const struct elfhdr *exec,
a62c5b1b6647e (Alexey Dobriyan         2020-01-30 22:16:55 -0800  173) 		unsigned long load_addr, unsigned long interp_load_addr,
a62c5b1b6647e (Alexey Dobriyan         2020-01-30 22:16:55 -0800  174) 		unsigned long e_entry)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  175) {
03c6d723eeac2 (Alexey Dobriyan         2020-01-30 22:16:58 -0800  176) 	struct mm_struct *mm = current->mm;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  177) 	unsigned long p = bprm->p;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  178) 	int argc = bprm->argc;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  179) 	int envc = bprm->envc;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  180) 	elf_addr_t __user *sp;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  181) 	elf_addr_t __user *u_platform;
483fad1c3fa10 (Nathan Lynch            2008-07-22 04:48:46 +1000  182) 	elf_addr_t __user *u_base_platform;
f06295b44c296 (Kees Cook               2009-01-07 18:08:52 -0800  183) 	elf_addr_t __user *u_rand_bytes;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  184) 	const char *k_platform = ELF_PLATFORM;
483fad1c3fa10 (Nathan Lynch            2008-07-22 04:48:46 +1000  185) 	const char *k_base_platform = ELF_BASE_PLATFORM;
f06295b44c296 (Kees Cook               2009-01-07 18:08:52 -0800  186) 	unsigned char k_rand_bytes[16];
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  187) 	int items;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  188) 	elf_addr_t *elf_info;
2347961b11d40 (Laurent Vivier          2020-01-28 14:25:39 +0100  189) 	elf_addr_t flags = 0;
1f83d80677a24 (Alexey Dobriyan         2020-01-30 22:16:50 -0800  190) 	int ei_index;
86a264abe542c (David Howells           2008-11-14 10:39:18 +1100  191) 	const struct cred *cred = current_cred();
b6a2fea39318e (Ollie Wild              2007-07-19 01:48:16 -0700  192) 	struct vm_area_struct *vma;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  193) 
d68c9d6ae8f1f (Franck Bui-Huu          2007-10-16 23:30:24 -0700  194) 	/*
d68c9d6ae8f1f (Franck Bui-Huu          2007-10-16 23:30:24 -0700  195) 	 * In some cases (e.g. Hyper-Threading), we want to avoid L1
d68c9d6ae8f1f (Franck Bui-Huu          2007-10-16 23:30:24 -0700  196) 	 * evictions by the processes running on the same package. One
d68c9d6ae8f1f (Franck Bui-Huu          2007-10-16 23:30:24 -0700  197) 	 * thing we can do is to shuffle the initial stack for them.
d68c9d6ae8f1f (Franck Bui-Huu          2007-10-16 23:30:24 -0700  198) 	 */
d68c9d6ae8f1f (Franck Bui-Huu          2007-10-16 23:30:24 -0700  199) 
d68c9d6ae8f1f (Franck Bui-Huu          2007-10-16 23:30:24 -0700  200) 	p = arch_align_stack(p);
d68c9d6ae8f1f (Franck Bui-Huu          2007-10-16 23:30:24 -0700  201) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  202) 	/*
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  203) 	 * If this architecture has a platform capability string, copy it
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  204) 	 * to userspace.  In some cases (Sparc), this info is impossible
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  205) 	 * for userspace to get any other way, in others (i386) it is
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  206) 	 * merely difficult.
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  207) 	 */
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  208) 	u_platform = NULL;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  209) 	if (k_platform) {
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  210) 		size_t len = strlen(k_platform) + 1;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  211) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  212) 		u_platform = (elf_addr_t __user *)STACK_ALLOC(p, len);
646e84deb4496 (Al Viro                 2020-02-19 09:23:34 -0500  213) 		if (copy_to_user(u_platform, k_platform, len))
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  214) 			return -EFAULT;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  215) 	}
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  216) 
483fad1c3fa10 (Nathan Lynch            2008-07-22 04:48:46 +1000  217) 	/*
483fad1c3fa10 (Nathan Lynch            2008-07-22 04:48:46 +1000  218) 	 * If this architecture has a "base" platform capability
483fad1c3fa10 (Nathan Lynch            2008-07-22 04:48:46 +1000  219) 	 * string, copy it to userspace.
483fad1c3fa10 (Nathan Lynch            2008-07-22 04:48:46 +1000  220) 	 */
483fad1c3fa10 (Nathan Lynch            2008-07-22 04:48:46 +1000  221) 	u_base_platform = NULL;
483fad1c3fa10 (Nathan Lynch            2008-07-22 04:48:46 +1000  222) 	if (k_base_platform) {
483fad1c3fa10 (Nathan Lynch            2008-07-22 04:48:46 +1000  223) 		size_t len = strlen(k_base_platform) + 1;
483fad1c3fa10 (Nathan Lynch            2008-07-22 04:48:46 +1000  224) 
483fad1c3fa10 (Nathan Lynch            2008-07-22 04:48:46 +1000  225) 		u_base_platform = (elf_addr_t __user *)STACK_ALLOC(p, len);
646e84deb4496 (Al Viro                 2020-02-19 09:23:34 -0500  226) 		if (copy_to_user(u_base_platform, k_base_platform, len))
483fad1c3fa10 (Nathan Lynch            2008-07-22 04:48:46 +1000  227) 			return -EFAULT;
483fad1c3fa10 (Nathan Lynch            2008-07-22 04:48:46 +1000  228) 	}
483fad1c3fa10 (Nathan Lynch            2008-07-22 04:48:46 +1000  229) 
f06295b44c296 (Kees Cook               2009-01-07 18:08:52 -0800  230) 	/*
f06295b44c296 (Kees Cook               2009-01-07 18:08:52 -0800  231) 	 * Generate 16 random bytes for userspace PRNG seeding.
f06295b44c296 (Kees Cook               2009-01-07 18:08:52 -0800  232) 	 */
f06295b44c296 (Kees Cook               2009-01-07 18:08:52 -0800  233) 	get_random_bytes(k_rand_bytes, sizeof(k_rand_bytes));
f06295b44c296 (Kees Cook               2009-01-07 18:08:52 -0800  234) 	u_rand_bytes = (elf_addr_t __user *)
f06295b44c296 (Kees Cook               2009-01-07 18:08:52 -0800  235) 		       STACK_ALLOC(p, sizeof(k_rand_bytes));
646e84deb4496 (Al Viro                 2020-02-19 09:23:34 -0500  236) 	if (copy_to_user(u_rand_bytes, k_rand_bytes, sizeof(k_rand_bytes)))
f06295b44c296 (Kees Cook               2009-01-07 18:08:52 -0800  237) 		return -EFAULT;
f06295b44c296 (Kees Cook               2009-01-07 18:08:52 -0800  238) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  239) 	/* Create the ELF interpreter info */
03c6d723eeac2 (Alexey Dobriyan         2020-01-30 22:16:58 -0800  240) 	elf_info = (elf_addr_t *)mm->saved_auxv;
4f9a58d75bfe8 (Olaf Hering             2007-10-16 23:30:12 -0700  241) 	/* update AT_VECTOR_SIZE_BASE if the number of NEW_AUX_ENT() changes */
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  242) #define NEW_AUX_ENT(id, val) \
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700  243) 	do { \
1f83d80677a24 (Alexey Dobriyan         2020-01-30 22:16:50 -0800  244) 		*elf_info++ = id; \
1f83d80677a24 (Alexey Dobriyan         2020-01-30 22:16:50 -0800  245) 		*elf_info++ = val; \
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700  246) 	} while (0)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  247) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  248) #ifdef ARCH_DLINFO
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  249) 	/* 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  250) 	 * ARCH_DLINFO must come first so PPC can do its special alignment of
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  251) 	 * AUXV.
4f9a58d75bfe8 (Olaf Hering             2007-10-16 23:30:12 -0700  252) 	 * update AT_VECTOR_SIZE_ARCH if the number of NEW_AUX_ENT() in
4f9a58d75bfe8 (Olaf Hering             2007-10-16 23:30:12 -0700  253) 	 * ARCH_DLINFO changes
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  254) 	 */
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  255) 	ARCH_DLINFO;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  256) #endif
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  257) 	NEW_AUX_ENT(AT_HWCAP, ELF_HWCAP);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  258) 	NEW_AUX_ENT(AT_PAGESZ, ELF_EXEC_PAGESIZE);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  259) 	NEW_AUX_ENT(AT_CLKTCK, CLOCKS_PER_SEC);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  260) 	NEW_AUX_ENT(AT_PHDR, load_addr + exec->e_phoff);
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700  261) 	NEW_AUX_ENT(AT_PHENT, sizeof(struct elf_phdr));
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  262) 	NEW_AUX_ENT(AT_PHNUM, exec->e_phnum);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  263) 	NEW_AUX_ENT(AT_BASE, interp_load_addr);
2347961b11d40 (Laurent Vivier          2020-01-28 14:25:39 +0100  264) 	if (bprm->interp_flags & BINPRM_FLAGS_PRESERVE_ARGV0)
2347961b11d40 (Laurent Vivier          2020-01-28 14:25:39 +0100  265) 		flags |= AT_FLAGS_PRESERVE_ARGV0;
2347961b11d40 (Laurent Vivier          2020-01-28 14:25:39 +0100  266) 	NEW_AUX_ENT(AT_FLAGS, flags);
a62c5b1b6647e (Alexey Dobriyan         2020-01-30 22:16:55 -0800  267) 	NEW_AUX_ENT(AT_ENTRY, e_entry);
ebc887b278944 (Eric W. Biederman       2012-02-07 18:36:10 -0800  268) 	NEW_AUX_ENT(AT_UID, from_kuid_munged(cred->user_ns, cred->uid));
ebc887b278944 (Eric W. Biederman       2012-02-07 18:36:10 -0800  269) 	NEW_AUX_ENT(AT_EUID, from_kuid_munged(cred->user_ns, cred->euid));
ebc887b278944 (Eric W. Biederman       2012-02-07 18:36:10 -0800  270) 	NEW_AUX_ENT(AT_GID, from_kgid_munged(cred->user_ns, cred->gid));
ebc887b278944 (Eric W. Biederman       2012-02-07 18:36:10 -0800  271) 	NEW_AUX_ENT(AT_EGID, from_kgid_munged(cred->user_ns, cred->egid));
c425e189ffd77 (Kees Cook               2017-07-18 15:25:22 -0700  272) 	NEW_AUX_ENT(AT_SECURE, bprm->secureexec);
f06295b44c296 (Kees Cook               2009-01-07 18:08:52 -0800  273) 	NEW_AUX_ENT(AT_RANDOM, (elf_addr_t)(unsigned long)u_rand_bytes);
2171364d1a92d (Michael Neuling         2013-04-17 17:33:11 +0000  274) #ifdef ELF_HWCAP2
2171364d1a92d (Michael Neuling         2013-04-17 17:33:11 +0000  275) 	NEW_AUX_ENT(AT_HWCAP2, ELF_HWCAP2);
2171364d1a92d (Michael Neuling         2013-04-17 17:33:11 +0000  276) #endif
651910874633a (John Reiser             2008-07-21 14:21:32 -0700  277) 	NEW_AUX_ENT(AT_EXECFN, bprm->exec);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  278) 	if (k_platform) {
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700  279) 		NEW_AUX_ENT(AT_PLATFORM,
785d55708c24c (Jesper Juhl             2006-06-23 02:05:35 -0700  280) 			    (elf_addr_t)(unsigned long)u_platform);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  281) 	}
483fad1c3fa10 (Nathan Lynch            2008-07-22 04:48:46 +1000  282) 	if (k_base_platform) {
483fad1c3fa10 (Nathan Lynch            2008-07-22 04:48:46 +1000  283) 		NEW_AUX_ENT(AT_BASE_PLATFORM,
483fad1c3fa10 (Nathan Lynch            2008-07-22 04:48:46 +1000  284) 			    (elf_addr_t)(unsigned long)u_base_platform);
483fad1c3fa10 (Nathan Lynch            2008-07-22 04:48:46 +1000  285) 	}
b8a61c9e7b4a0 (Eric W. Biederman       2020-05-14 15:17:40 -0500  286) 	if (bprm->have_execfd) {
b8a61c9e7b4a0 (Eric W. Biederman       2020-05-14 15:17:40 -0500  287) 		NEW_AUX_ENT(AT_EXECFD, bprm->execfd);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  288) 	}
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  289) #undef NEW_AUX_ENT
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  290) 	/* AT_NULL is zero; clear the rest too */
03c6d723eeac2 (Alexey Dobriyan         2020-01-30 22:16:58 -0800  291) 	memset(elf_info, 0, (char *)mm->saved_auxv +
03c6d723eeac2 (Alexey Dobriyan         2020-01-30 22:16:58 -0800  292) 			sizeof(mm->saved_auxv) - (char *)elf_info);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  293) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  294) 	/* And advance past the AT_NULL entry.  */
1f83d80677a24 (Alexey Dobriyan         2020-01-30 22:16:50 -0800  295) 	elf_info += 2;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  296) 
03c6d723eeac2 (Alexey Dobriyan         2020-01-30 22:16:58 -0800  297) 	ei_index = elf_info - (elf_addr_t *)mm->saved_auxv;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  298) 	sp = STACK_ADD(p, ei_index);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  299) 
d20894a23708c (Andi Kleen              2008-02-08 04:21:54 -0800  300) 	items = (argc + 1) + (envc + 1) + 1;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  301) 	bprm->p = STACK_ROUND(sp, items);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  302) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  303) 	/* Point sp at the lowest address on the stack */
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  304) #ifdef CONFIG_STACK_GROWSUP
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  305) 	sp = (elf_addr_t __user *)bprm->p - items - ei_index;
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700  306) 	bprm->exec = (unsigned long)sp; /* XXX: PARISC HACK */
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  307) #else
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  308) 	sp = (elf_addr_t __user *)bprm->p;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  309) #endif
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  310) 
b6a2fea39318e (Ollie Wild              2007-07-19 01:48:16 -0700  311) 
b6a2fea39318e (Ollie Wild              2007-07-19 01:48:16 -0700  312) 	/*
b6a2fea39318e (Ollie Wild              2007-07-19 01:48:16 -0700  313) 	 * Grow the stack manually; some architectures have a limit on how
b6a2fea39318e (Ollie Wild              2007-07-19 01:48:16 -0700  314) 	 * far ahead a user-space access may be in order to grow the stack.
b6a2fea39318e (Ollie Wild              2007-07-19 01:48:16 -0700  315) 	 */
b2767d97f5ff7 (Jann Horn               2020-10-17 16:14:15 -0700  316) 	if (mmap_read_lock_killable(mm))
b2767d97f5ff7 (Jann Horn               2020-10-17 16:14:15 -0700  317) 		return -EINTR;
03c6d723eeac2 (Alexey Dobriyan         2020-01-30 22:16:58 -0800  318) 	vma = find_extend_vma(mm, bprm->p);
b2767d97f5ff7 (Jann Horn               2020-10-17 16:14:15 -0700  319) 	mmap_read_unlock(mm);
b6a2fea39318e (Ollie Wild              2007-07-19 01:48:16 -0700  320) 	if (!vma)
b6a2fea39318e (Ollie Wild              2007-07-19 01:48:16 -0700  321) 		return -EFAULT;
b6a2fea39318e (Ollie Wild              2007-07-19 01:48:16 -0700  322) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  323) 	/* Now, let's put argc (and argv, envp if appropriate) on the stack */
646e84deb4496 (Al Viro                 2020-02-19 09:23:34 -0500  324) 	if (put_user(argc, sp++))
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  325) 		return -EFAULT;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  326) 
67c6777a5d331 (Kees Cook               2017-07-10 15:52:54 -0700  327) 	/* Populate list of argv pointers back to argv strings. */
03c6d723eeac2 (Alexey Dobriyan         2020-01-30 22:16:58 -0800  328) 	p = mm->arg_end = mm->arg_start;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  329) 	while (argc-- > 0) {
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  330) 		size_t len;
646e84deb4496 (Al Viro                 2020-02-19 09:23:34 -0500  331) 		if (put_user((elf_addr_t)p, sp++))
841d5fb7c7526 (Heiko Carstens          2006-12-06 20:36:35 -0800  332) 			return -EFAULT;
b6a2fea39318e (Ollie Wild              2007-07-19 01:48:16 -0700  333) 		len = strnlen_user((void __user *)p, MAX_ARG_STRLEN);
b6a2fea39318e (Ollie Wild              2007-07-19 01:48:16 -0700  334) 		if (!len || len > MAX_ARG_STRLEN)
23c4971e3d97d (WANG Cong               2008-05-08 21:52:33 +0800  335) 			return -EINVAL;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  336) 		p += len;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  337) 	}
646e84deb4496 (Al Viro                 2020-02-19 09:23:34 -0500  338) 	if (put_user(0, sp++))
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  339) 		return -EFAULT;
03c6d723eeac2 (Alexey Dobriyan         2020-01-30 22:16:58 -0800  340) 	mm->arg_end = p;
67c6777a5d331 (Kees Cook               2017-07-10 15:52:54 -0700  341) 
67c6777a5d331 (Kees Cook               2017-07-10 15:52:54 -0700  342) 	/* Populate list of envp pointers back to envp strings. */
03c6d723eeac2 (Alexey Dobriyan         2020-01-30 22:16:58 -0800  343) 	mm->env_end = mm->env_start = p;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  344) 	while (envc-- > 0) {
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  345) 		size_t len;
646e84deb4496 (Al Viro                 2020-02-19 09:23:34 -0500  346) 		if (put_user((elf_addr_t)p, sp++))
841d5fb7c7526 (Heiko Carstens          2006-12-06 20:36:35 -0800  347) 			return -EFAULT;
b6a2fea39318e (Ollie Wild              2007-07-19 01:48:16 -0700  348) 		len = strnlen_user((void __user *)p, MAX_ARG_STRLEN);
b6a2fea39318e (Ollie Wild              2007-07-19 01:48:16 -0700  349) 		if (!len || len > MAX_ARG_STRLEN)
23c4971e3d97d (WANG Cong               2008-05-08 21:52:33 +0800  350) 			return -EINVAL;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  351) 		p += len;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  352) 	}
646e84deb4496 (Al Viro                 2020-02-19 09:23:34 -0500  353) 	if (put_user(0, sp++))
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  354) 		return -EFAULT;
03c6d723eeac2 (Alexey Dobriyan         2020-01-30 22:16:58 -0800  355) 	mm->env_end = p;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  356) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  357) 	/* Put the elf_info on the stack in the right place.  */
03c6d723eeac2 (Alexey Dobriyan         2020-01-30 22:16:58 -0800  358) 	if (copy_to_user(sp, mm->saved_auxv, ei_index * sizeof(elf_addr_t)))
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  359) 		return -EFAULT;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  360) 	return 0;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  361) }
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  362) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  363) static unsigned long elf_map(struct file *filep, unsigned long addr,
49ac981965e00 (Alexey Dobriyan         2019-03-07 16:29:03 -0800  364) 		const struct elf_phdr *eppnt, int prot, int type,
cc503c1b43e00 (Jiri Kosina             2008-01-30 13:31:07 +0100  365) 		unsigned long total_size)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  366) {
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  367) 	unsigned long map_addr;
cc503c1b43e00 (Jiri Kosina             2008-01-30 13:31:07 +0100  368) 	unsigned long size = eppnt->p_filesz + ELF_PAGEOFFSET(eppnt->p_vaddr);
cc503c1b43e00 (Jiri Kosina             2008-01-30 13:31:07 +0100  369) 	unsigned long off = eppnt->p_offset - ELF_PAGEOFFSET(eppnt->p_vaddr);
cc503c1b43e00 (Jiri Kosina             2008-01-30 13:31:07 +0100  370) 	addr = ELF_PAGESTART(addr);
cc503c1b43e00 (Jiri Kosina             2008-01-30 13:31:07 +0100  371) 	size = ELF_PAGEALIGN(size);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  372) 
dda6ebde96044 (David Gibson            2006-01-08 01:03:35 -0800  373) 	/* mmap() will return -EINVAL if given a zero size, but a
dda6ebde96044 (David Gibson            2006-01-08 01:03:35 -0800  374) 	 * segment with zero filesize is perfectly valid */
cc503c1b43e00 (Jiri Kosina             2008-01-30 13:31:07 +0100  375) 	if (!size)
cc503c1b43e00 (Jiri Kosina             2008-01-30 13:31:07 +0100  376) 		return addr;
cc503c1b43e00 (Jiri Kosina             2008-01-30 13:31:07 +0100  377) 
cc503c1b43e00 (Jiri Kosina             2008-01-30 13:31:07 +0100  378) 	/*
cc503c1b43e00 (Jiri Kosina             2008-01-30 13:31:07 +0100  379) 	* total_size is the size of the ELF (interpreter) image.
cc503c1b43e00 (Jiri Kosina             2008-01-30 13:31:07 +0100  380) 	* The _first_ mmap needs to know the full size, otherwise
cc503c1b43e00 (Jiri Kosina             2008-01-30 13:31:07 +0100  381) 	* randomization might put this image into an overlapping
cc503c1b43e00 (Jiri Kosina             2008-01-30 13:31:07 +0100  382) 	* position with the ELF binary image. (since size < total_size)
cc503c1b43e00 (Jiri Kosina             2008-01-30 13:31:07 +0100  383) 	* So we first map the 'big' image - and unmap the remainder at
cc503c1b43e00 (Jiri Kosina             2008-01-30 13:31:07 +0100  384) 	* the end. (which unmap is needed for ELF images with holes.)
cc503c1b43e00 (Jiri Kosina             2008-01-30 13:31:07 +0100  385) 	*/
cc503c1b43e00 (Jiri Kosina             2008-01-30 13:31:07 +0100  386) 	if (total_size) {
cc503c1b43e00 (Jiri Kosina             2008-01-30 13:31:07 +0100  387) 		total_size = ELF_PAGEALIGN(total_size);
5a5e4c2eca030 (Al Viro                 2012-05-30 01:49:38 -0400  388) 		map_addr = vm_mmap(filep, addr, total_size, prot, type, off);
cc503c1b43e00 (Jiri Kosina             2008-01-30 13:31:07 +0100  389) 		if (!BAD_ADDR(map_addr))
5a5e4c2eca030 (Al Viro                 2012-05-30 01:49:38 -0400  390) 			vm_munmap(map_addr+size, total_size-size);
cc503c1b43e00 (Jiri Kosina             2008-01-30 13:31:07 +0100  391) 	} else
5a5e4c2eca030 (Al Viro                 2012-05-30 01:49:38 -0400  392) 		map_addr = vm_mmap(filep, addr, size, prot, type, off);
cc503c1b43e00 (Jiri Kosina             2008-01-30 13:31:07 +0100  393) 
d23a61ee90af3 (Tetsuo Handa            2018-04-20 14:56:13 -0700  394) 	if ((type & MAP_FIXED_NOREPLACE) &&
d23a61ee90af3 (Tetsuo Handa            2018-04-20 14:56:13 -0700  395) 	    PTR_ERR((void *)map_addr) == -EEXIST)
d23a61ee90af3 (Tetsuo Handa            2018-04-20 14:56:13 -0700  396) 		pr_info("%d (%s): Uhuuh, elf segment at %px requested but the memory is mapped already\n",
d23a61ee90af3 (Tetsuo Handa            2018-04-20 14:56:13 -0700  397) 			task_pid_nr(current), current->comm, (void *)addr);
4ed28639519c7 (Michal Hocko            2018-04-10 16:36:01 -0700  398) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  399) 	return(map_addr);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  400) }
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  401) 
49ac981965e00 (Alexey Dobriyan         2019-03-07 16:29:03 -0800  402) static unsigned long total_mapping_size(const struct elf_phdr *cmds, int nr)
cc503c1b43e00 (Jiri Kosina             2008-01-30 13:31:07 +0100  403) {
cc503c1b43e00 (Jiri Kosina             2008-01-30 13:31:07 +0100  404) 	int i, first_idx = -1, last_idx = -1;
cc503c1b43e00 (Jiri Kosina             2008-01-30 13:31:07 +0100  405) 
cc503c1b43e00 (Jiri Kosina             2008-01-30 13:31:07 +0100  406) 	for (i = 0; i < nr; i++) {
cc503c1b43e00 (Jiri Kosina             2008-01-30 13:31:07 +0100  407) 		if (cmds[i].p_type == PT_LOAD) {
cc503c1b43e00 (Jiri Kosina             2008-01-30 13:31:07 +0100  408) 			last_idx = i;
cc503c1b43e00 (Jiri Kosina             2008-01-30 13:31:07 +0100  409) 			if (first_idx == -1)
cc503c1b43e00 (Jiri Kosina             2008-01-30 13:31:07 +0100  410) 				first_idx = i;
cc503c1b43e00 (Jiri Kosina             2008-01-30 13:31:07 +0100  411) 		}
cc503c1b43e00 (Jiri Kosina             2008-01-30 13:31:07 +0100  412) 	}
cc503c1b43e00 (Jiri Kosina             2008-01-30 13:31:07 +0100  413) 	if (first_idx == -1)
cc503c1b43e00 (Jiri Kosina             2008-01-30 13:31:07 +0100  414) 		return 0;
cc503c1b43e00 (Jiri Kosina             2008-01-30 13:31:07 +0100  415) 
cc503c1b43e00 (Jiri Kosina             2008-01-30 13:31:07 +0100  416) 	return cmds[last_idx].p_vaddr + cmds[last_idx].p_memsz -
cc503c1b43e00 (Jiri Kosina             2008-01-30 13:31:07 +0100  417) 				ELF_PAGESTART(cmds[first_idx].p_vaddr);
cc503c1b43e00 (Jiri Kosina             2008-01-30 13:31:07 +0100  418) }
cc503c1b43e00 (Jiri Kosina             2008-01-30 13:31:07 +0100  419) 
658c033565118 (Alexey Dobriyan         2019-12-04 16:52:25 -0800  420) static int elf_read(struct file *file, void *buf, size_t len, loff_t pos)
658c033565118 (Alexey Dobriyan         2019-12-04 16:52:25 -0800  421) {
658c033565118 (Alexey Dobriyan         2019-12-04 16:52:25 -0800  422) 	ssize_t rv;
658c033565118 (Alexey Dobriyan         2019-12-04 16:52:25 -0800  423) 
658c033565118 (Alexey Dobriyan         2019-12-04 16:52:25 -0800  424) 	rv = kernel_read(file, buf, len, &pos);
658c033565118 (Alexey Dobriyan         2019-12-04 16:52:25 -0800  425) 	if (unlikely(rv != len)) {
658c033565118 (Alexey Dobriyan         2019-12-04 16:52:25 -0800  426) 		return (rv < 0) ? rv : -EIO;
658c033565118 (Alexey Dobriyan         2019-12-04 16:52:25 -0800  427) 	}
658c033565118 (Alexey Dobriyan         2019-12-04 16:52:25 -0800  428) 	return 0;
658c033565118 (Alexey Dobriyan         2019-12-04 16:52:25 -0800  429) }
658c033565118 (Alexey Dobriyan         2019-12-04 16:52:25 -0800  430) 
ce81bb256a224 (Chris Kennelly          2020-10-15 20:12:32 -0700  431) static unsigned long maximum_alignment(struct elf_phdr *cmds, int nr)
ce81bb256a224 (Chris Kennelly          2020-10-15 20:12:32 -0700  432) {
ce81bb256a224 (Chris Kennelly          2020-10-15 20:12:32 -0700  433) 	unsigned long alignment = 0;
ce81bb256a224 (Chris Kennelly          2020-10-15 20:12:32 -0700  434) 	int i;
ce81bb256a224 (Chris Kennelly          2020-10-15 20:12:32 -0700  435) 
ce81bb256a224 (Chris Kennelly          2020-10-15 20:12:32 -0700  436) 	for (i = 0; i < nr; i++) {
ce81bb256a224 (Chris Kennelly          2020-10-15 20:12:32 -0700  437) 		if (cmds[i].p_type == PT_LOAD) {
ce81bb256a224 (Chris Kennelly          2020-10-15 20:12:32 -0700  438) 			unsigned long p_align = cmds[i].p_align;
ce81bb256a224 (Chris Kennelly          2020-10-15 20:12:32 -0700  439) 
ce81bb256a224 (Chris Kennelly          2020-10-15 20:12:32 -0700  440) 			/* skip non-power of two alignments as invalid */
ce81bb256a224 (Chris Kennelly          2020-10-15 20:12:32 -0700  441) 			if (!is_power_of_2(p_align))
ce81bb256a224 (Chris Kennelly          2020-10-15 20:12:32 -0700  442) 				continue;
ce81bb256a224 (Chris Kennelly          2020-10-15 20:12:32 -0700  443) 			alignment = max(alignment, p_align);
ce81bb256a224 (Chris Kennelly          2020-10-15 20:12:32 -0700  444) 		}
ce81bb256a224 (Chris Kennelly          2020-10-15 20:12:32 -0700  445) 	}
ce81bb256a224 (Chris Kennelly          2020-10-15 20:12:32 -0700  446) 
ce81bb256a224 (Chris Kennelly          2020-10-15 20:12:32 -0700  447) 	/* ensure we align to at least one page */
ce81bb256a224 (Chris Kennelly          2020-10-15 20:12:32 -0700  448) 	return ELF_PAGEALIGN(alignment);
ce81bb256a224 (Chris Kennelly          2020-10-15 20:12:32 -0700  449) }
ce81bb256a224 (Chris Kennelly          2020-10-15 20:12:32 -0700  450) 
6a8d38945cf4e (Paul Burton             2014-09-11 08:30:14 +0100  451) /**
6a8d38945cf4e (Paul Burton             2014-09-11 08:30:14 +0100  452)  * load_elf_phdrs() - load ELF program headers
6a8d38945cf4e (Paul Burton             2014-09-11 08:30:14 +0100  453)  * @elf_ex:   ELF header of the binary whose program headers should be loaded
6a8d38945cf4e (Paul Burton             2014-09-11 08:30:14 +0100  454)  * @elf_file: the opened ELF binary file
6a8d38945cf4e (Paul Burton             2014-09-11 08:30:14 +0100  455)  *
6a8d38945cf4e (Paul Burton             2014-09-11 08:30:14 +0100  456)  * Loads ELF program headers from the binary file elf_file, which has the ELF
6a8d38945cf4e (Paul Burton             2014-09-11 08:30:14 +0100  457)  * header pointed to by elf_ex, into a newly allocated array. The caller is
6a8d38945cf4e (Paul Burton             2014-09-11 08:30:14 +0100  458)  * responsible for freeing the allocated data. Returns an ERR_PTR upon failure.
6a8d38945cf4e (Paul Burton             2014-09-11 08:30:14 +0100  459)  */
49ac981965e00 (Alexey Dobriyan         2019-03-07 16:29:03 -0800  460) static struct elf_phdr *load_elf_phdrs(const struct elfhdr *elf_ex,
6a8d38945cf4e (Paul Burton             2014-09-11 08:30:14 +0100  461) 				       struct file *elf_file)
6a8d38945cf4e (Paul Burton             2014-09-11 08:30:14 +0100  462) {
6a8d38945cf4e (Paul Burton             2014-09-11 08:30:14 +0100  463) 	struct elf_phdr *elf_phdata = NULL;
faf1c31520322 (Alexey Dobriyan         2019-03-07 16:28:56 -0800  464) 	int retval, err = -1;
faf1c31520322 (Alexey Dobriyan         2019-03-07 16:28:56 -0800  465) 	unsigned int size;
6a8d38945cf4e (Paul Burton             2014-09-11 08:30:14 +0100  466) 
6a8d38945cf4e (Paul Burton             2014-09-11 08:30:14 +0100  467) 	/*
6a8d38945cf4e (Paul Burton             2014-09-11 08:30:14 +0100  468) 	 * If the size of this structure has changed, then punt, since
6a8d38945cf4e (Paul Burton             2014-09-11 08:30:14 +0100  469) 	 * we will be doing the wrong thing.
6a8d38945cf4e (Paul Burton             2014-09-11 08:30:14 +0100  470) 	 */
6a8d38945cf4e (Paul Burton             2014-09-11 08:30:14 +0100  471) 	if (elf_ex->e_phentsize != sizeof(struct elf_phdr))
6a8d38945cf4e (Paul Burton             2014-09-11 08:30:14 +0100  472) 		goto out;
6a8d38945cf4e (Paul Burton             2014-09-11 08:30:14 +0100  473) 
6a8d38945cf4e (Paul Burton             2014-09-11 08:30:14 +0100  474) 	/* Sanity check the number of program headers... */
6a8d38945cf4e (Paul Burton             2014-09-11 08:30:14 +0100  475) 	/* ...and their total size. */
6a8d38945cf4e (Paul Burton             2014-09-11 08:30:14 +0100  476) 	size = sizeof(struct elf_phdr) * elf_ex->e_phnum;
faf1c31520322 (Alexey Dobriyan         2019-03-07 16:28:56 -0800  477) 	if (size == 0 || size > 65536 || size > ELF_MIN_ALIGN)
6a8d38945cf4e (Paul Burton             2014-09-11 08:30:14 +0100  478) 		goto out;
6a8d38945cf4e (Paul Burton             2014-09-11 08:30:14 +0100  479) 
6a8d38945cf4e (Paul Burton             2014-09-11 08:30:14 +0100  480) 	elf_phdata = kmalloc(size, GFP_KERNEL);
6a8d38945cf4e (Paul Burton             2014-09-11 08:30:14 +0100  481) 	if (!elf_phdata)
6a8d38945cf4e (Paul Burton             2014-09-11 08:30:14 +0100  482) 		goto out;
6a8d38945cf4e (Paul Burton             2014-09-11 08:30:14 +0100  483) 
6a8d38945cf4e (Paul Burton             2014-09-11 08:30:14 +0100  484) 	/* Read in the program headers */
658c033565118 (Alexey Dobriyan         2019-12-04 16:52:25 -0800  485) 	retval = elf_read(elf_file, elf_phdata, size, elf_ex->e_phoff);
658c033565118 (Alexey Dobriyan         2019-12-04 16:52:25 -0800  486) 	if (retval < 0) {
658c033565118 (Alexey Dobriyan         2019-12-04 16:52:25 -0800  487) 		err = retval;
6a8d38945cf4e (Paul Burton             2014-09-11 08:30:14 +0100  488) 		goto out;
6a8d38945cf4e (Paul Burton             2014-09-11 08:30:14 +0100  489) 	}
6a8d38945cf4e (Paul Burton             2014-09-11 08:30:14 +0100  490) 
6a8d38945cf4e (Paul Burton             2014-09-11 08:30:14 +0100  491) 	/* Success! */
6a8d38945cf4e (Paul Burton             2014-09-11 08:30:14 +0100  492) 	err = 0;
6a8d38945cf4e (Paul Burton             2014-09-11 08:30:14 +0100  493) out:
6a8d38945cf4e (Paul Burton             2014-09-11 08:30:14 +0100  494) 	if (err) {
6a8d38945cf4e (Paul Burton             2014-09-11 08:30:14 +0100  495) 		kfree(elf_phdata);
6a8d38945cf4e (Paul Burton             2014-09-11 08:30:14 +0100  496) 		elf_phdata = NULL;
6a8d38945cf4e (Paul Burton             2014-09-11 08:30:14 +0100  497) 	}
6a8d38945cf4e (Paul Burton             2014-09-11 08:30:14 +0100  498) 	return elf_phdata;
6a8d38945cf4e (Paul Burton             2014-09-11 08:30:14 +0100  499) }
cc503c1b43e00 (Jiri Kosina             2008-01-30 13:31:07 +0100  500) 
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  501) #ifndef CONFIG_ARCH_BINFMT_ELF_STATE
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  502) 
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  503) /**
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  504)  * struct arch_elf_state - arch-specific ELF loading state
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  505)  *
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  506)  * This structure is used to preserve architecture specific data during
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  507)  * the loading of an ELF file, throughout the checking of architecture
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  508)  * specific ELF headers & through to the point where the ELF load is
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  509)  * known to be proceeding (ie. SET_PERSONALITY).
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  510)  *
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  511)  * This implementation is a dummy for architectures which require no
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  512)  * specific state.
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  513)  */
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  514) struct arch_elf_state {
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  515) };
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  516) 
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  517) #define INIT_ARCH_ELF_STATE {}
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  518) 
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  519) /**
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  520)  * arch_elf_pt_proc() - check a PT_LOPROC..PT_HIPROC ELF program header
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  521)  * @ehdr:	The main ELF header
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  522)  * @phdr:	The program header to check
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  523)  * @elf:	The open ELF file
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  524)  * @is_interp:	True if the phdr is from the interpreter of the ELF being
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  525)  *		loaded, else false.
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  526)  * @state:	Architecture-specific state preserved throughout the process
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  527)  *		of loading the ELF.
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  528)  *
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  529)  * Inspects the program header phdr to validate its correctness and/or
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  530)  * suitability for the system. Called once per ELF program header in the
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  531)  * range PT_LOPROC to PT_HIPROC, for both the ELF being loaded and its
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  532)  * interpreter.
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  533)  *
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  534)  * Return: Zero to proceed with the ELF load, non-zero to fail the ELF load
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  535)  *         with that return code.
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  536)  */
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  537) static inline int arch_elf_pt_proc(struct elfhdr *ehdr,
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  538) 				   struct elf_phdr *phdr,
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  539) 				   struct file *elf, bool is_interp,
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  540) 				   struct arch_elf_state *state)
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  541) {
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  542) 	/* Dummy implementation, always proceed */
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  543) 	return 0;
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  544) }
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  545) 
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  546) /**
54d15714f7497 (Maciej W. Rozycki       2015-10-26 15:47:57 +0000  547)  * arch_check_elf() - check an ELF executable
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  548)  * @ehdr:	The main ELF header
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  549)  * @has_interp:	True if the ELF has an interpreter, else false.
eb4bc076ff94b (Maciej W. Rozycki       2015-11-13 00:47:48 +0000  550)  * @interp_ehdr: The interpreter's ELF header
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  551)  * @state:	Architecture-specific state preserved throughout the process
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  552)  *		of loading the ELF.
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  553)  *
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  554)  * Provides a final opportunity for architecture code to reject the loading
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  555)  * of the ELF & cause an exec syscall to return an error. This is called after
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  556)  * all program headers to be checked by arch_elf_pt_proc have been.
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  557)  *
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  558)  * Return: Zero to proceed with the ELF load, non-zero to fail the ELF load
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  559)  *         with that return code.
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  560)  */
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  561) static inline int arch_check_elf(struct elfhdr *ehdr, bool has_interp,
eb4bc076ff94b (Maciej W. Rozycki       2015-11-13 00:47:48 +0000  562) 				 struct elfhdr *interp_ehdr,
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  563) 				 struct arch_elf_state *state)
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  564) {
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  565) 	/* Dummy implementation, always proceed */
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  566) 	return 0;
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  567) }
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  568) 
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  569) #endif /* !CONFIG_ARCH_BINFMT_ELF_STATE */
cc503c1b43e00 (Jiri Kosina             2008-01-30 13:31:07 +0100  570) 
fe0f67660ee9c (Dave Martin             2020-03-16 16:50:46 +0000  571) static inline int make_prot(u32 p_flags, struct arch_elf_state *arch_state,
fe0f67660ee9c (Dave Martin             2020-03-16 16:50:46 +0000  572) 			    bool has_interp, bool is_interp)
d8e7cb39acc66 (Alexey Dobriyan         2019-05-14 15:43:51 -0700  573) {
d8e7cb39acc66 (Alexey Dobriyan         2019-05-14 15:43:51 -0700  574) 	int prot = 0;
d8e7cb39acc66 (Alexey Dobriyan         2019-05-14 15:43:51 -0700  575) 
d8e7cb39acc66 (Alexey Dobriyan         2019-05-14 15:43:51 -0700  576) 	if (p_flags & PF_R)
d8e7cb39acc66 (Alexey Dobriyan         2019-05-14 15:43:51 -0700  577) 		prot |= PROT_READ;
d8e7cb39acc66 (Alexey Dobriyan         2019-05-14 15:43:51 -0700  578) 	if (p_flags & PF_W)
d8e7cb39acc66 (Alexey Dobriyan         2019-05-14 15:43:51 -0700  579) 		prot |= PROT_WRITE;
d8e7cb39acc66 (Alexey Dobriyan         2019-05-14 15:43:51 -0700  580) 	if (p_flags & PF_X)
d8e7cb39acc66 (Alexey Dobriyan         2019-05-14 15:43:51 -0700  581) 		prot |= PROT_EXEC;
fe0f67660ee9c (Dave Martin             2020-03-16 16:50:46 +0000  582) 
fe0f67660ee9c (Dave Martin             2020-03-16 16:50:46 +0000  583) 	return arch_elf_adjust_prot(prot, arch_state, has_interp, is_interp);
d8e7cb39acc66 (Alexey Dobriyan         2019-05-14 15:43:51 -0700  584) }
d8e7cb39acc66 (Alexey Dobriyan         2019-05-14 15:43:51 -0700  585) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  586) /* This is much more generalized than the library routine read function,
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  587)    so we keep this separate.  Technically the library read function
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  588)    is only provided so that we can read a.out libraries that have
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  589)    an ELF header */
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  590) 
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700  591) static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex,
81696d5d544e6 (Alexey Dobriyan         2019-12-04 16:52:22 -0800  592) 		struct file *interpreter,
fe0f67660ee9c (Dave Martin             2020-03-16 16:50:46 +0000  593) 		unsigned long no_base, struct elf_phdr *interp_elf_phdata,
fe0f67660ee9c (Dave Martin             2020-03-16 16:50:46 +0000  594) 		struct arch_elf_state *arch_state)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  595) {
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  596) 	struct elf_phdr *eppnt;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  597) 	unsigned long load_addr = 0;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  598) 	int load_addr_set = 0;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  599) 	unsigned long last_bss = 0, elf_bss = 0;
16e72e9b30986 (Denys Vlasenko          2017-02-22 15:45:16 -0800  600) 	int bss_prot = 0;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  601) 	unsigned long error = ~0UL;
cc503c1b43e00 (Jiri Kosina             2008-01-30 13:31:07 +0100  602) 	unsigned long total_size;
6a8d38945cf4e (Paul Burton             2014-09-11 08:30:14 +0100  603) 	int i;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  604) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  605) 	/* First of all, some simple consistency checks */
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  606) 	if (interp_elf_ex->e_type != ET_EXEC &&
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  607) 	    interp_elf_ex->e_type != ET_DYN)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  608) 		goto out;
4755200b6b116 (Nicolas Pitre           2017-08-16 16:05:13 -0400  609) 	if (!elf_check_arch(interp_elf_ex) ||
4755200b6b116 (Nicolas Pitre           2017-08-16 16:05:13 -0400  610) 	    elf_check_fdpic(interp_elf_ex))
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  611) 		goto out;
72c2d53192004 (Al Viro                 2013-09-22 16:27:52 -0400  612) 	if (!interpreter->f_op->mmap)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  613) 		goto out;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  614) 
a9d9ef133f443 (Paul Burton             2014-09-11 08:30:15 +0100  615) 	total_size = total_mapping_size(interp_elf_phdata,
a9d9ef133f443 (Paul Burton             2014-09-11 08:30:15 +0100  616) 					interp_elf_ex->e_phnum);
cc503c1b43e00 (Jiri Kosina             2008-01-30 13:31:07 +0100  617) 	if (!total_size) {
cc503c1b43e00 (Jiri Kosina             2008-01-30 13:31:07 +0100  618) 		error = -EINVAL;
a9d9ef133f443 (Paul Burton             2014-09-11 08:30:15 +0100  619) 		goto out;
cc503c1b43e00 (Jiri Kosina             2008-01-30 13:31:07 +0100  620) 	}
cc503c1b43e00 (Jiri Kosina             2008-01-30 13:31:07 +0100  621) 
a9d9ef133f443 (Paul Burton             2014-09-11 08:30:15 +0100  622) 	eppnt = interp_elf_phdata;
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700  623) 	for (i = 0; i < interp_elf_ex->e_phnum; i++, eppnt++) {
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700  624) 		if (eppnt->p_type == PT_LOAD) {
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700  625) 			int elf_type = MAP_PRIVATE | MAP_DENYWRITE;
fe0f67660ee9c (Dave Martin             2020-03-16 16:50:46 +0000  626) 			int elf_prot = make_prot(eppnt->p_flags, arch_state,
fe0f67660ee9c (Dave Martin             2020-03-16 16:50:46 +0000  627) 						 true, true);
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700  628) 			unsigned long vaddr = 0;
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700  629) 			unsigned long k, map_addr;
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700  630) 
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700  631) 			vaddr = eppnt->p_vaddr;
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700  632) 			if (interp_elf_ex->e_type == ET_EXEC || load_addr_set)
4ed28639519c7 (Michal Hocko            2018-04-10 16:36:01 -0700  633) 				elf_type |= MAP_FIXED_NOREPLACE;
cc503c1b43e00 (Jiri Kosina             2008-01-30 13:31:07 +0100  634) 			else if (no_base && interp_elf_ex->e_type == ET_DYN)
cc503c1b43e00 (Jiri Kosina             2008-01-30 13:31:07 +0100  635) 				load_addr = -vaddr;
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700  636) 
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700  637) 			map_addr = elf_map(interpreter, load_addr + vaddr,
bb1ad8205be4c (Andrew Morton           2008-01-30 13:31:07 +0100  638) 					eppnt, elf_prot, elf_type, total_size);
cc503c1b43e00 (Jiri Kosina             2008-01-30 13:31:07 +0100  639) 			total_size = 0;
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700  640) 			error = map_addr;
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700  641) 			if (BAD_ADDR(map_addr))
a9d9ef133f443 (Paul Burton             2014-09-11 08:30:15 +0100  642) 				goto out;
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700  643) 
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700  644) 			if (!load_addr_set &&
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700  645) 			    interp_elf_ex->e_type == ET_DYN) {
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700  646) 				load_addr = map_addr - ELF_PAGESTART(vaddr);
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700  647) 				load_addr_set = 1;
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700  648) 			}
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700  649) 
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700  650) 			/*
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700  651) 			 * Check to see if the section's size will overflow the
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700  652) 			 * allowed task size. Note that p_filesz must always be
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700  653) 			 * <= p_memsize so it's only necessary to check p_memsz.
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700  654) 			 */
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700  655) 			k = load_addr + eppnt->p_vaddr;
ce51059be56f6 (Chuck Ebbert            2006-07-03 00:24:14 -0700  656) 			if (BAD_ADDR(k) ||
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700  657) 			    eppnt->p_filesz > eppnt->p_memsz ||
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700  658) 			    eppnt->p_memsz > TASK_SIZE ||
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700  659) 			    TASK_SIZE - eppnt->p_memsz < k) {
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700  660) 				error = -ENOMEM;
a9d9ef133f443 (Paul Burton             2014-09-11 08:30:15 +0100  661) 				goto out;
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700  662) 			}
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700  663) 
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700  664) 			/*
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700  665) 			 * Find the end of the file mapping for this phdr, and
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700  666) 			 * keep track of the largest address we see for this.
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700  667) 			 */
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700  668) 			k = load_addr + eppnt->p_vaddr + eppnt->p_filesz;
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700  669) 			if (k > elf_bss)
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700  670) 				elf_bss = k;
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700  671) 
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700  672) 			/*
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700  673) 			 * Do the same thing for the memory mapping - between
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700  674) 			 * elf_bss and last_bss is the bss section.
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700  675) 			 */
0036d1f7eb95b (Kees Cook               2016-08-02 14:04:51 -0700  676) 			k = load_addr + eppnt->p_vaddr + eppnt->p_memsz;
16e72e9b30986 (Denys Vlasenko          2017-02-22 15:45:16 -0800  677) 			if (k > last_bss) {
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700  678) 				last_bss = k;
16e72e9b30986 (Denys Vlasenko          2017-02-22 15:45:16 -0800  679) 				bss_prot = elf_prot;
16e72e9b30986 (Denys Vlasenko          2017-02-22 15:45:16 -0800  680) 			}
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700  681) 		}
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  682) 	}
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  683) 
0036d1f7eb95b (Kees Cook               2016-08-02 14:04:51 -0700  684) 	/*
0036d1f7eb95b (Kees Cook               2016-08-02 14:04:51 -0700  685) 	 * Now fill out the bss section: first pad the last page from
0036d1f7eb95b (Kees Cook               2016-08-02 14:04:51 -0700  686) 	 * the file up to the page boundary, and zero it from elf_bss
0036d1f7eb95b (Kees Cook               2016-08-02 14:04:51 -0700  687) 	 * up to the end of the page.
0036d1f7eb95b (Kees Cook               2016-08-02 14:04:51 -0700  688) 	 */
0036d1f7eb95b (Kees Cook               2016-08-02 14:04:51 -0700  689) 	if (padzero(elf_bss)) {
0036d1f7eb95b (Kees Cook               2016-08-02 14:04:51 -0700  690) 		error = -EFAULT;
0036d1f7eb95b (Kees Cook               2016-08-02 14:04:51 -0700  691) 		goto out;
0036d1f7eb95b (Kees Cook               2016-08-02 14:04:51 -0700  692) 	}
0036d1f7eb95b (Kees Cook               2016-08-02 14:04:51 -0700  693) 	/*
0036d1f7eb95b (Kees Cook               2016-08-02 14:04:51 -0700  694) 	 * Next, align both the file and mem bss up to the page size,
0036d1f7eb95b (Kees Cook               2016-08-02 14:04:51 -0700  695) 	 * since this is where elf_bss was just zeroed up to, and where
16e72e9b30986 (Denys Vlasenko          2017-02-22 15:45:16 -0800  696) 	 * last_bss will end after the vm_brk_flags() below.
0036d1f7eb95b (Kees Cook               2016-08-02 14:04:51 -0700  697) 	 */
0036d1f7eb95b (Kees Cook               2016-08-02 14:04:51 -0700  698) 	elf_bss = ELF_PAGEALIGN(elf_bss);
0036d1f7eb95b (Kees Cook               2016-08-02 14:04:51 -0700  699) 	last_bss = ELF_PAGEALIGN(last_bss);
0036d1f7eb95b (Kees Cook               2016-08-02 14:04:51 -0700  700) 	/* Finally, if there is still more bss to allocate, do it. */
752015d1b0683 (Roland McGrath          2009-09-08 19:49:40 -0700  701) 	if (last_bss > elf_bss) {
16e72e9b30986 (Denys Vlasenko          2017-02-22 15:45:16 -0800  702) 		error = vm_brk_flags(elf_bss, last_bss - elf_bss,
16e72e9b30986 (Denys Vlasenko          2017-02-22 15:45:16 -0800  703) 				bss_prot & PROT_EXEC ? VM_EXEC : 0);
5d22fc25d4fc8 (Linus Torvalds          2016-05-27 15:57:31 -0700  704) 		if (error)
a9d9ef133f443 (Paul Burton             2014-09-11 08:30:15 +0100  705) 			goto out;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  706) 	}
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  707) 
cc503c1b43e00 (Jiri Kosina             2008-01-30 13:31:07 +0100  708) 	error = load_addr;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  709) out:
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  710) 	return error;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  711) }
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  712) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  713) /*
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  714)  * These are the functions used to load ELF style executables and shared
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  715)  * libraries.  There is no binary dependent code anywhere else.
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  716)  */
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  717) 
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  718) static int parse_elf_property(const char *data, size_t *off, size_t datasz,
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  719) 			      struct arch_elf_state *arch,
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  720) 			      bool have_prev_type, u32 *prev_type)
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  721) {
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  722) 	size_t o, step;
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  723) 	const struct gnu_property *pr;
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  724) 	int ret;
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  725) 
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  726) 	if (*off == datasz)
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  727) 		return -ENOENT;
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  728) 
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  729) 	if (WARN_ON_ONCE(*off > datasz || *off % ELF_GNU_PROPERTY_ALIGN))
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  730) 		return -EIO;
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  731) 	o = *off;
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  732) 	datasz -= *off;
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  733) 
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  734) 	if (datasz < sizeof(*pr))
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  735) 		return -ENOEXEC;
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  736) 	pr = (const struct gnu_property *)(data + o);
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  737) 	o += sizeof(*pr);
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  738) 	datasz -= sizeof(*pr);
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  739) 
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  740) 	if (pr->pr_datasz > datasz)
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  741) 		return -ENOEXEC;
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  742) 
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  743) 	WARN_ON_ONCE(o % ELF_GNU_PROPERTY_ALIGN);
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  744) 	step = round_up(pr->pr_datasz, ELF_GNU_PROPERTY_ALIGN);
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  745) 	if (step > datasz)
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  746) 		return -ENOEXEC;
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  747) 
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  748) 	/* Properties are supposed to be unique and sorted on pr_type: */
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  749) 	if (have_prev_type && pr->pr_type <= *prev_type)
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  750) 		return -ENOEXEC;
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  751) 	*prev_type = pr->pr_type;
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  752) 
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  753) 	ret = arch_parse_elf_property(pr->pr_type, data + o,
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  754) 				      pr->pr_datasz, ELF_COMPAT, arch);
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  755) 	if (ret)
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  756) 		return ret;
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  757) 
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  758) 	*off = o + step;
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  759) 	return 0;
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  760) }
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  761) 
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  762) #define NOTE_DATA_SZ SZ_1K
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  763) #define GNU_PROPERTY_TYPE_0_NAME "GNU"
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  764) #define NOTE_NAME_SZ (sizeof(GNU_PROPERTY_TYPE_0_NAME))
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  765) 
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  766) static int parse_elf_properties(struct file *f, const struct elf_phdr *phdr,
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  767) 				struct arch_elf_state *arch)
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  768) {
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  769) 	union {
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  770) 		struct elf_note nhdr;
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  771) 		char data[NOTE_DATA_SZ];
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  772) 	} note;
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  773) 	loff_t pos;
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  774) 	ssize_t n;
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  775) 	size_t off, datasz;
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  776) 	int ret;
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  777) 	bool have_prev_type;
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  778) 	u32 prev_type;
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  779) 
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  780) 	if (!IS_ENABLED(CONFIG_ARCH_USE_GNU_PROPERTY) || !phdr)
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  781) 		return 0;
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  782) 
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  783) 	/* load_elf_binary() shouldn't call us unless this is true... */
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  784) 	if (WARN_ON_ONCE(phdr->p_type != PT_GNU_PROPERTY))
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  785) 		return -ENOEXEC;
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  786) 
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  787) 	/* If the properties are crazy large, that's too bad (for now): */
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  788) 	if (phdr->p_filesz > sizeof(note))
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  789) 		return -ENOEXEC;
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  790) 
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  791) 	pos = phdr->p_offset;
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  792) 	n = kernel_read(f, &note, phdr->p_filesz, &pos);
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  793) 
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  794) 	BUILD_BUG_ON(sizeof(note) < sizeof(note.nhdr) + NOTE_NAME_SZ);
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  795) 	if (n < 0 || n < sizeof(note.nhdr) + NOTE_NAME_SZ)
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  796) 		return -EIO;
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  797) 
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  798) 	if (note.nhdr.n_type != NT_GNU_PROPERTY_TYPE_0 ||
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  799) 	    note.nhdr.n_namesz != NOTE_NAME_SZ ||
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  800) 	    strncmp(note.data + sizeof(note.nhdr),
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  801) 		    GNU_PROPERTY_TYPE_0_NAME, n - sizeof(note.nhdr)))
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  802) 		return -ENOEXEC;
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  803) 
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  804) 	off = round_up(sizeof(note.nhdr) + NOTE_NAME_SZ,
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  805) 		       ELF_GNU_PROPERTY_ALIGN);
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  806) 	if (off > n)
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  807) 		return -ENOEXEC;
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  808) 
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  809) 	if (note.nhdr.n_descsz > n - off)
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  810) 		return -ENOEXEC;
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  811) 	datasz = off + note.nhdr.n_descsz;
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  812) 
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  813) 	have_prev_type = false;
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  814) 	do {
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  815) 		ret = parse_elf_property(note.data, &off, datasz, arch,
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  816) 					 have_prev_type, &prev_type);
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  817) 		have_prev_type = true;
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  818) 	} while (!ret);
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  819) 
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  820) 	return ret == -ENOENT ? 0 : ret;
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  821) }
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  822) 
71613c3b871c5 (Al Viro                 2012-10-20 22:00:48 -0400  823) static int load_elf_binary(struct linux_binprm *bprm)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  824) {
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  825) 	struct file *interpreter = NULL; /* to shut gcc up */
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  826)  	unsigned long load_addr = 0, load_bias = 0;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  827) 	int load_addr_set = 0;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  828) 	unsigned long error;
a9d9ef133f443 (Paul Burton             2014-09-11 08:30:15 +0100  829) 	struct elf_phdr *elf_ppnt, *elf_phdata, *interp_elf_phdata = NULL;
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  830) 	struct elf_phdr *elf_property_phdata = NULL;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  831) 	unsigned long elf_bss, elf_brk;
16e72e9b30986 (Denys Vlasenko          2017-02-22 15:45:16 -0800  832) 	int bss_prot = 0;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  833) 	int retval, i;
cc503c1b43e00 (Jiri Kosina             2008-01-30 13:31:07 +0100  834) 	unsigned long elf_entry;
a62c5b1b6647e (Alexey Dobriyan         2020-01-30 22:16:55 -0800  835) 	unsigned long e_entry;
cc503c1b43e00 (Jiri Kosina             2008-01-30 13:31:07 +0100  836) 	unsigned long interp_load_addr = 0;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  837) 	unsigned long start_code, end_code, start_data, end_data;
1a530a6f23f7d (David Daney             2011-03-22 16:34:48 -0700  838) 	unsigned long reloc_func_desc __maybe_unused = 0;
8de61e69c2feb (David Rientjes          2006-12-06 20:40:16 -0800  839) 	int executable_stack = EXSTACK_DEFAULT;
a62c5b1b6647e (Alexey Dobriyan         2020-01-30 22:16:55 -0800  840) 	struct elfhdr *elf_ex = (struct elfhdr *)bprm->buf;
0693ffebcfe5a (Alexey Dobriyan         2020-04-06 20:11:29 -0700  841) 	struct elfhdr *interp_elf_ex = NULL;
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  842) 	struct arch_elf_state arch_state = INIT_ARCH_ELF_STATE;
03c6d723eeac2 (Alexey Dobriyan         2020-01-30 22:16:58 -0800  843) 	struct mm_struct *mm;
249b08e4e504d (Alexey Dobriyan         2019-05-14 15:43:54 -0700  844) 	struct pt_regs *regs;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  845) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  846) 	retval = -ENOEXEC;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  847) 	/* First of all, some simple consistency checks */
a62c5b1b6647e (Alexey Dobriyan         2020-01-30 22:16:55 -0800  848) 	if (memcmp(elf_ex->e_ident, ELFMAG, SELFMAG) != 0)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  849) 		goto out;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  850) 
a62c5b1b6647e (Alexey Dobriyan         2020-01-30 22:16:55 -0800  851) 	if (elf_ex->e_type != ET_EXEC && elf_ex->e_type != ET_DYN)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  852) 		goto out;
a62c5b1b6647e (Alexey Dobriyan         2020-01-30 22:16:55 -0800  853) 	if (!elf_check_arch(elf_ex))
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  854) 		goto out;
a62c5b1b6647e (Alexey Dobriyan         2020-01-30 22:16:55 -0800  855) 	if (elf_check_fdpic(elf_ex))
4755200b6b116 (Nicolas Pitre           2017-08-16 16:05:13 -0400  856) 		goto out;
72c2d53192004 (Al Viro                 2013-09-22 16:27:52 -0400  857) 	if (!bprm->file->f_op->mmap)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  858) 		goto out;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  859) 
a62c5b1b6647e (Alexey Dobriyan         2020-01-30 22:16:55 -0800  860) 	elf_phdata = load_elf_phdrs(elf_ex, bprm->file);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  861) 	if (!elf_phdata)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  862) 		goto out;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  863) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  864) 	elf_ppnt = elf_phdata;
a62c5b1b6647e (Alexey Dobriyan         2020-01-30 22:16:55 -0800  865) 	for (i = 0; i < elf_ex->e_phnum; i++, elf_ppnt++) {
be0deb585e4c5 (Alexey Dobriyan         2019-05-14 15:43:45 -0700  866) 		char *elf_interpreter;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  867) 
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  868) 		if (elf_ppnt->p_type == PT_GNU_PROPERTY) {
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  869) 			elf_property_phdata = elf_ppnt;
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  870) 			continue;
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  871) 		}
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  872) 
be0deb585e4c5 (Alexey Dobriyan         2019-05-14 15:43:45 -0700  873) 		if (elf_ppnt->p_type != PT_INTERP)
be0deb585e4c5 (Alexey Dobriyan         2019-05-14 15:43:45 -0700  874) 			continue;
1fb844961818c (Alexey Dobriyan         2007-01-26 00:57:16 -0800  875) 
be0deb585e4c5 (Alexey Dobriyan         2019-05-14 15:43:45 -0700  876) 		/*
be0deb585e4c5 (Alexey Dobriyan         2019-05-14 15:43:45 -0700  877) 		 * This is the program interpreter used for shared libraries -
be0deb585e4c5 (Alexey Dobriyan         2019-05-14 15:43:45 -0700  878) 		 * for now assume that this is an a.out format binary.
be0deb585e4c5 (Alexey Dobriyan         2019-05-14 15:43:45 -0700  879) 		 */
be0deb585e4c5 (Alexey Dobriyan         2019-05-14 15:43:45 -0700  880) 		retval = -ENOEXEC;
be0deb585e4c5 (Alexey Dobriyan         2019-05-14 15:43:45 -0700  881) 		if (elf_ppnt->p_filesz > PATH_MAX || elf_ppnt->p_filesz < 2)
be0deb585e4c5 (Alexey Dobriyan         2019-05-14 15:43:45 -0700  882) 			goto out_free_ph;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  883) 
be0deb585e4c5 (Alexey Dobriyan         2019-05-14 15:43:45 -0700  884) 		retval = -ENOMEM;
be0deb585e4c5 (Alexey Dobriyan         2019-05-14 15:43:45 -0700  885) 		elf_interpreter = kmalloc(elf_ppnt->p_filesz, GFP_KERNEL);
be0deb585e4c5 (Alexey Dobriyan         2019-05-14 15:43:45 -0700  886) 		if (!elf_interpreter)
be0deb585e4c5 (Alexey Dobriyan         2019-05-14 15:43:45 -0700  887) 			goto out_free_ph;
cc338010a233c (Alexey Dobriyan         2019-05-14 15:43:39 -0700  888) 
658c033565118 (Alexey Dobriyan         2019-12-04 16:52:25 -0800  889) 		retval = elf_read(bprm->file, elf_interpreter, elf_ppnt->p_filesz,
658c033565118 (Alexey Dobriyan         2019-12-04 16:52:25 -0800  890) 				  elf_ppnt->p_offset);
658c033565118 (Alexey Dobriyan         2019-12-04 16:52:25 -0800  891) 		if (retval < 0)
be0deb585e4c5 (Alexey Dobriyan         2019-05-14 15:43:45 -0700  892) 			goto out_free_interp;
be0deb585e4c5 (Alexey Dobriyan         2019-05-14 15:43:45 -0700  893) 		/* make sure path is NULL terminated */
be0deb585e4c5 (Alexey Dobriyan         2019-05-14 15:43:45 -0700  894) 		retval = -ENOEXEC;
be0deb585e4c5 (Alexey Dobriyan         2019-05-14 15:43:45 -0700  895) 		if (elf_interpreter[elf_ppnt->p_filesz - 1] != '\0')
be0deb585e4c5 (Alexey Dobriyan         2019-05-14 15:43:45 -0700  896) 			goto out_free_interp;
be0deb585e4c5 (Alexey Dobriyan         2019-05-14 15:43:45 -0700  897) 
be0deb585e4c5 (Alexey Dobriyan         2019-05-14 15:43:45 -0700  898) 		interpreter = open_exec(elf_interpreter);
be0deb585e4c5 (Alexey Dobriyan         2019-05-14 15:43:45 -0700  899) 		kfree(elf_interpreter);
be0deb585e4c5 (Alexey Dobriyan         2019-05-14 15:43:45 -0700  900) 		retval = PTR_ERR(interpreter);
be0deb585e4c5 (Alexey Dobriyan         2019-05-14 15:43:45 -0700  901) 		if (IS_ERR(interpreter))
cc338010a233c (Alexey Dobriyan         2019-05-14 15:43:39 -0700  902) 			goto out_free_ph;
be0deb585e4c5 (Alexey Dobriyan         2019-05-14 15:43:45 -0700  903) 
be0deb585e4c5 (Alexey Dobriyan         2019-05-14 15:43:45 -0700  904) 		/*
be0deb585e4c5 (Alexey Dobriyan         2019-05-14 15:43:45 -0700  905) 		 * If the binary is not readable then enforce mm->dumpable = 0
be0deb585e4c5 (Alexey Dobriyan         2019-05-14 15:43:45 -0700  906) 		 * regardless of the interpreter's permissions.
be0deb585e4c5 (Alexey Dobriyan         2019-05-14 15:43:45 -0700  907) 		 */
be0deb585e4c5 (Alexey Dobriyan         2019-05-14 15:43:45 -0700  908) 		would_dump(bprm, interpreter);
be0deb585e4c5 (Alexey Dobriyan         2019-05-14 15:43:45 -0700  909) 
0693ffebcfe5a (Alexey Dobriyan         2020-04-06 20:11:29 -0700  910) 		interp_elf_ex = kmalloc(sizeof(*interp_elf_ex), GFP_KERNEL);
0693ffebcfe5a (Alexey Dobriyan         2020-04-06 20:11:29 -0700  911) 		if (!interp_elf_ex) {
0693ffebcfe5a (Alexey Dobriyan         2020-04-06 20:11:29 -0700  912) 			retval = -ENOMEM;
0693ffebcfe5a (Alexey Dobriyan         2020-04-06 20:11:29 -0700  913) 			goto out_free_ph;
0693ffebcfe5a (Alexey Dobriyan         2020-04-06 20:11:29 -0700  914) 		}
0693ffebcfe5a (Alexey Dobriyan         2020-04-06 20:11:29 -0700  915) 
be0deb585e4c5 (Alexey Dobriyan         2019-05-14 15:43:45 -0700  916) 		/* Get the exec headers */
c69bcc932ef35 (Alexey Dobriyan         2020-04-06 20:11:26 -0700  917) 		retval = elf_read(interpreter, interp_elf_ex,
c69bcc932ef35 (Alexey Dobriyan         2020-04-06 20:11:26 -0700  918) 				  sizeof(*interp_elf_ex), 0);
658c033565118 (Alexey Dobriyan         2019-12-04 16:52:25 -0800  919) 		if (retval < 0)
be0deb585e4c5 (Alexey Dobriyan         2019-05-14 15:43:45 -0700  920) 			goto out_free_dentry;
be0deb585e4c5 (Alexey Dobriyan         2019-05-14 15:43:45 -0700  921) 
be0deb585e4c5 (Alexey Dobriyan         2019-05-14 15:43:45 -0700  922) 		break;
be0deb585e4c5 (Alexey Dobriyan         2019-05-14 15:43:45 -0700  923) 
be0deb585e4c5 (Alexey Dobriyan         2019-05-14 15:43:45 -0700  924) out_free_interp:
be0deb585e4c5 (Alexey Dobriyan         2019-05-14 15:43:45 -0700  925) 		kfree(elf_interpreter);
be0deb585e4c5 (Alexey Dobriyan         2019-05-14 15:43:45 -0700  926) 		goto out_free_ph;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  927) 	}
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  928) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  929) 	elf_ppnt = elf_phdata;
a62c5b1b6647e (Alexey Dobriyan         2020-01-30 22:16:55 -0800  930) 	for (i = 0; i < elf_ex->e_phnum; i++, elf_ppnt++)
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  931) 		switch (elf_ppnt->p_type) {
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  932) 		case PT_GNU_STACK:
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  933) 			if (elf_ppnt->p_flags & PF_X)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  934) 				executable_stack = EXSTACK_ENABLE_X;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  935) 			else
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  936) 				executable_stack = EXSTACK_DISABLE_X;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  937) 			break;
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  938) 
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  939) 		case PT_LOPROC ... PT_HIPROC:
a62c5b1b6647e (Alexey Dobriyan         2020-01-30 22:16:55 -0800  940) 			retval = arch_elf_pt_proc(elf_ex, elf_ppnt,
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  941) 						  bprm->file, false,
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  942) 						  &arch_state);
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  943) 			if (retval)
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  944) 				goto out_free_dentry;
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  945) 			break;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  946) 		}
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  947) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  948) 	/* Some simple consistency checks for the interpreter */
cc338010a233c (Alexey Dobriyan         2019-05-14 15:43:39 -0700  949) 	if (interpreter) {
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  950) 		retval = -ELIBBAD;
d20894a23708c (Andi Kleen              2008-02-08 04:21:54 -0800  951) 		/* Not an ELF interpreter */
c69bcc932ef35 (Alexey Dobriyan         2020-04-06 20:11:26 -0700  952) 		if (memcmp(interp_elf_ex->e_ident, ELFMAG, SELFMAG) != 0)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  953) 			goto out_free_dentry;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  954) 		/* Verify the interpreter has a valid arch */
c69bcc932ef35 (Alexey Dobriyan         2020-04-06 20:11:26 -0700  955) 		if (!elf_check_arch(interp_elf_ex) ||
c69bcc932ef35 (Alexey Dobriyan         2020-04-06 20:11:26 -0700  956) 		    elf_check_fdpic(interp_elf_ex))
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  957) 			goto out_free_dentry;
a9d9ef133f443 (Paul Burton             2014-09-11 08:30:15 +0100  958) 
a9d9ef133f443 (Paul Burton             2014-09-11 08:30:15 +0100  959) 		/* Load the interpreter program headers */
c69bcc932ef35 (Alexey Dobriyan         2020-04-06 20:11:26 -0700  960) 		interp_elf_phdata = load_elf_phdrs(interp_elf_ex,
a9d9ef133f443 (Paul Burton             2014-09-11 08:30:15 +0100  961) 						   interpreter);
a9d9ef133f443 (Paul Burton             2014-09-11 08:30:15 +0100  962) 		if (!interp_elf_phdata)
a9d9ef133f443 (Paul Burton             2014-09-11 08:30:15 +0100  963) 			goto out_free_dentry;
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  964) 
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  965) 		/* Pass PT_LOPROC..PT_HIPROC headers to arch code */
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  966) 		elf_property_phdata = NULL;
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  967) 		elf_ppnt = interp_elf_phdata;
c69bcc932ef35 (Alexey Dobriyan         2020-04-06 20:11:26 -0700  968) 		for (i = 0; i < interp_elf_ex->e_phnum; i++, elf_ppnt++)
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  969) 			switch (elf_ppnt->p_type) {
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  970) 			case PT_GNU_PROPERTY:
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  971) 				elf_property_phdata = elf_ppnt;
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  972) 				break;
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  973) 
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  974) 			case PT_LOPROC ... PT_HIPROC:
c69bcc932ef35 (Alexey Dobriyan         2020-04-06 20:11:26 -0700  975) 				retval = arch_elf_pt_proc(interp_elf_ex,
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  976) 							  elf_ppnt, interpreter,
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  977) 							  true, &arch_state);
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  978) 				if (retval)
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  979) 					goto out_free_dentry;
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  980) 				break;
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  981) 			}
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  982) 	}
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700  983) 
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  984) 	retval = parse_elf_properties(interpreter ?: bprm->file,
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  985) 				      elf_property_phdata, &arch_state);
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  986) 	if (retval)
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  987) 		goto out_free_dentry;
00e19ceec80b0 (Dave Martin             2020-03-16 16:50:44 +0000  988) 
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  989) 	/*
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  990) 	 * Allow arch code to reject the ELF at this point, whilst it's
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  991) 	 * still possible to return an error to the code that invoked
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  992) 	 * the exec syscall.
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  993) 	 */
a62c5b1b6647e (Alexey Dobriyan         2020-01-30 22:16:55 -0800  994) 	retval = arch_check_elf(elf_ex,
c69bcc932ef35 (Alexey Dobriyan         2020-04-06 20:11:26 -0700  995) 				!!interpreter, interp_elf_ex,
eb4bc076ff94b (Maciej W. Rozycki       2015-11-13 00:47:48 +0000  996) 				&arch_state);
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  997) 	if (retval)
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  998) 		goto out_free_dentry;
774c105ed8d79 (Paul Burton             2014-09-11 08:30:16 +0100  999) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1000) 	/* Flush all traces of the currently running executable */
2388777a0a595 (Eric W. Biederman       2020-05-03 07:54:10 -0500 1001) 	retval = begin_new_exec(bprm);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1002) 	if (retval)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1003) 		goto out_free_dentry;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1004) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1005) 	/* Do this immediately, since STACK_TOP as used in setup_arg_pages
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1006) 	   may depend on the personality.  */
a62c5b1b6647e (Alexey Dobriyan         2020-01-30 22:16:55 -0800 1007) 	SET_PERSONALITY2(*elf_ex, &arch_state);
a62c5b1b6647e (Alexey Dobriyan         2020-01-30 22:16:55 -0800 1008) 	if (elf_read_implies_exec(*elf_ex, executable_stack))
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1009) 		current->personality |= READ_IMPLIES_EXEC;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1010) 
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700 1011) 	if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1012) 		current->flags |= PF_RANDOMIZE;
221af7f87b974 (Linus Torvalds          2010-01-28 22:14:42 -0800 1013) 
221af7f87b974 (Linus Torvalds          2010-01-28 22:14:42 -0800 1014) 	setup_new_exec(bprm);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1015) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1016) 	/* Do this so that we can load the interpreter, if need be.  We will
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1017) 	   change some of these later */
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1018) 	retval = setup_arg_pages(bprm, randomize_stack_top(STACK_TOP),
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1019) 				 executable_stack);
19d860a140bea (Al Viro                 2014-05-04 20:11:36 -0400 1020) 	if (retval < 0)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1021) 		goto out_free_dentry;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1022) 	
852643165aea0 (Alexey Dobriyan         2019-05-14 15:43:48 -0700 1023) 	elf_bss = 0;
852643165aea0 (Alexey Dobriyan         2019-05-14 15:43:48 -0700 1024) 	elf_brk = 0;
852643165aea0 (Alexey Dobriyan         2019-05-14 15:43:48 -0700 1025) 
852643165aea0 (Alexey Dobriyan         2019-05-14 15:43:48 -0700 1026) 	start_code = ~0UL;
852643165aea0 (Alexey Dobriyan         2019-05-14 15:43:48 -0700 1027) 	end_code = 0;
852643165aea0 (Alexey Dobriyan         2019-05-14 15:43:48 -0700 1028) 	start_data = 0;
852643165aea0 (Alexey Dobriyan         2019-05-14 15:43:48 -0700 1029) 	end_data = 0;
852643165aea0 (Alexey Dobriyan         2019-05-14 15:43:48 -0700 1030) 
af901ca181d92 (André Goddard Rosa      2009-11-14 13:09:05 -0200 1031) 	/* Now we do a little grungy work by mmapping the ELF image into
cc503c1b43e00 (Jiri Kosina             2008-01-30 13:31:07 +0100 1032) 	   the correct location in memory. */
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700 1033) 	for(i = 0, elf_ppnt = elf_phdata;
a62c5b1b6647e (Alexey Dobriyan         2020-01-30 22:16:55 -0800 1034) 	    i < elf_ex->e_phnum; i++, elf_ppnt++) {
b212921b13bda (Linus Torvalds          2019-10-06 13:53:27 -0700 1035) 		int elf_prot, elf_flags;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1036) 		unsigned long k, vaddr;
a87938b2e246b (Michael Davidson        2015-04-14 15:47:38 -0700 1037) 		unsigned long total_size = 0;
ce81bb256a224 (Chris Kennelly          2020-10-15 20:12:32 -0700 1038) 		unsigned long alignment;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1039) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1040) 		if (elf_ppnt->p_type != PT_LOAD)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1041) 			continue;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1042) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1043) 		if (unlikely (elf_brk > elf_bss)) {
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1044) 			unsigned long nbyte;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1045) 	            
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1046) 			/* There was a PT_LOAD segment with p_memsz > p_filesz
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1047) 			   before this one. Map anonymous pages, if needed,
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1048) 			   and clear the area.  */
f670d0ecda73b (Mikael Pettersson       2011-01-12 17:00:02 -0800 1049) 			retval = set_brk(elf_bss + load_bias,
16e72e9b30986 (Denys Vlasenko          2017-02-22 15:45:16 -0800 1050) 					 elf_brk + load_bias,
16e72e9b30986 (Denys Vlasenko          2017-02-22 15:45:16 -0800 1051) 					 bss_prot);
19d860a140bea (Al Viro                 2014-05-04 20:11:36 -0400 1052) 			if (retval)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1053) 				goto out_free_dentry;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1054) 			nbyte = ELF_PAGEOFFSET(elf_bss);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1055) 			if (nbyte) {
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1056) 				nbyte = ELF_MIN_ALIGN - nbyte;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1057) 				if (nbyte > elf_brk - elf_bss)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1058) 					nbyte = elf_brk - elf_bss;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1059) 				if (clear_user((void __user *)elf_bss +
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1060) 							load_bias, nbyte)) {
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1061) 					/*
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1062) 					 * This bss-zeroing can fail if the ELF
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700 1063) 					 * file specifies odd protections. So
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1064) 					 * we don't check the return value
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1065) 					 */
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1066) 				}
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1067) 			}
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1068) 		}
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1069) 
fe0f67660ee9c (Dave Martin             2020-03-16 16:50:46 +0000 1070) 		elf_prot = make_prot(elf_ppnt->p_flags, &arch_state,
fe0f67660ee9c (Dave Martin             2020-03-16 16:50:46 +0000 1071) 				     !!interpreter, false);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1072) 
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700 1073) 		elf_flags = MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1074) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1075) 		vaddr = elf_ppnt->p_vaddr;
eab09532d4009 (Kees Cook               2017-07-10 15:52:37 -0700 1076) 		/*
eab09532d4009 (Kees Cook               2017-07-10 15:52:37 -0700 1077) 		 * If we are loading ET_EXEC or we have already performed
eab09532d4009 (Kees Cook               2017-07-10 15:52:37 -0700 1078) 		 * the ET_DYN load_addr calculations, proceed normally.
eab09532d4009 (Kees Cook               2017-07-10 15:52:37 -0700 1079) 		 */
a62c5b1b6647e (Alexey Dobriyan         2020-01-30 22:16:55 -0800 1080) 		if (elf_ex->e_type == ET_EXEC || load_addr_set) {
b212921b13bda (Linus Torvalds          2019-10-06 13:53:27 -0700 1081) 			elf_flags |= MAP_FIXED;
a62c5b1b6647e (Alexey Dobriyan         2020-01-30 22:16:55 -0800 1082) 		} else if (elf_ex->e_type == ET_DYN) {
eab09532d4009 (Kees Cook               2017-07-10 15:52:37 -0700 1083) 			/*
eab09532d4009 (Kees Cook               2017-07-10 15:52:37 -0700 1084) 			 * This logic is run once for the first LOAD Program
eab09532d4009 (Kees Cook               2017-07-10 15:52:37 -0700 1085) 			 * Header for ET_DYN binaries to calculate the
eab09532d4009 (Kees Cook               2017-07-10 15:52:37 -0700 1086) 			 * randomization (load_bias) for all the LOAD
eab09532d4009 (Kees Cook               2017-07-10 15:52:37 -0700 1087) 			 * Program Headers, and to calculate the entire
eab09532d4009 (Kees Cook               2017-07-10 15:52:37 -0700 1088) 			 * size of the ELF mapping (total_size). (Note that
eab09532d4009 (Kees Cook               2017-07-10 15:52:37 -0700 1089) 			 * load_addr_set is set to true later once the
eab09532d4009 (Kees Cook               2017-07-10 15:52:37 -0700 1090) 			 * initial mapping is performed.)
eab09532d4009 (Kees Cook               2017-07-10 15:52:37 -0700 1091) 			 *
eab09532d4009 (Kees Cook               2017-07-10 15:52:37 -0700 1092) 			 * There are effectively two types of ET_DYN
eab09532d4009 (Kees Cook               2017-07-10 15:52:37 -0700 1093) 			 * binaries: programs (i.e. PIE: ET_DYN with INTERP)
eab09532d4009 (Kees Cook               2017-07-10 15:52:37 -0700 1094) 			 * and loaders (ET_DYN without INTERP, since they
eab09532d4009 (Kees Cook               2017-07-10 15:52:37 -0700 1095) 			 * _are_ the ELF interpreter). The loaders must
eab09532d4009 (Kees Cook               2017-07-10 15:52:37 -0700 1096) 			 * be loaded away from programs since the program
eab09532d4009 (Kees Cook               2017-07-10 15:52:37 -0700 1097) 			 * may otherwise collide with the loader (especially
eab09532d4009 (Kees Cook               2017-07-10 15:52:37 -0700 1098) 			 * for ET_EXEC which does not have a randomized
eab09532d4009 (Kees Cook               2017-07-10 15:52:37 -0700 1099) 			 * position). For example to handle invocations of
eab09532d4009 (Kees Cook               2017-07-10 15:52:37 -0700 1100) 			 * "./ld.so someprog" to test out a new version of
eab09532d4009 (Kees Cook               2017-07-10 15:52:37 -0700 1101) 			 * the loader, the subsequent program that the
eab09532d4009 (Kees Cook               2017-07-10 15:52:37 -0700 1102) 			 * loader loads must avoid the loader itself, so
eab09532d4009 (Kees Cook               2017-07-10 15:52:37 -0700 1103) 			 * they cannot share the same load range. Sufficient
eab09532d4009 (Kees Cook               2017-07-10 15:52:37 -0700 1104) 			 * room for the brk must be allocated with the
eab09532d4009 (Kees Cook               2017-07-10 15:52:37 -0700 1105) 			 * loader as well, since brk must be available with
eab09532d4009 (Kees Cook               2017-07-10 15:52:37 -0700 1106) 			 * the loader.
eab09532d4009 (Kees Cook               2017-07-10 15:52:37 -0700 1107) 			 *
eab09532d4009 (Kees Cook               2017-07-10 15:52:37 -0700 1108) 			 * Therefore, programs are loaded offset from
eab09532d4009 (Kees Cook               2017-07-10 15:52:37 -0700 1109) 			 * ELF_ET_DYN_BASE and loaders are loaded into the
eab09532d4009 (Kees Cook               2017-07-10 15:52:37 -0700 1110) 			 * independently randomized mmap region (0 load_bias
eab09532d4009 (Kees Cook               2017-07-10 15:52:37 -0700 1111) 			 * without MAP_FIXED).
eab09532d4009 (Kees Cook               2017-07-10 15:52:37 -0700 1112) 			 */
cc338010a233c (Alexey Dobriyan         2019-05-14 15:43:39 -0700 1113) 			if (interpreter) {
eab09532d4009 (Kees Cook               2017-07-10 15:52:37 -0700 1114) 				load_bias = ELF_ET_DYN_BASE;
eab09532d4009 (Kees Cook               2017-07-10 15:52:37 -0700 1115) 				if (current->flags & PF_RANDOMIZE)
eab09532d4009 (Kees Cook               2017-07-10 15:52:37 -0700 1116) 					load_bias += arch_mmap_rnd();
ce81bb256a224 (Chris Kennelly          2020-10-15 20:12:32 -0700 1117) 				alignment = maximum_alignment(elf_phdata, elf_ex->e_phnum);
ce81bb256a224 (Chris Kennelly          2020-10-15 20:12:32 -0700 1118) 				if (alignment)
ce81bb256a224 (Chris Kennelly          2020-10-15 20:12:32 -0700 1119) 					load_bias &= ~(alignment - 1);
b212921b13bda (Linus Torvalds          2019-10-06 13:53:27 -0700 1120) 				elf_flags |= MAP_FIXED;
eab09532d4009 (Kees Cook               2017-07-10 15:52:37 -0700 1121) 			} else
eab09532d4009 (Kees Cook               2017-07-10 15:52:37 -0700 1122) 				load_bias = 0;
eab09532d4009 (Kees Cook               2017-07-10 15:52:37 -0700 1123) 
eab09532d4009 (Kees Cook               2017-07-10 15:52:37 -0700 1124) 			/*
eab09532d4009 (Kees Cook               2017-07-10 15:52:37 -0700 1125) 			 * Since load_bias is used for all subsequent loading
eab09532d4009 (Kees Cook               2017-07-10 15:52:37 -0700 1126) 			 * calculations, we must lower it by the first vaddr
eab09532d4009 (Kees Cook               2017-07-10 15:52:37 -0700 1127) 			 * so that the remaining calculations based on the
eab09532d4009 (Kees Cook               2017-07-10 15:52:37 -0700 1128) 			 * ELF vaddrs will be correctly offset. The result
eab09532d4009 (Kees Cook               2017-07-10 15:52:37 -0700 1129) 			 * is then page aligned.
eab09532d4009 (Kees Cook               2017-07-10 15:52:37 -0700 1130) 			 */
eab09532d4009 (Kees Cook               2017-07-10 15:52:37 -0700 1131) 			load_bias = ELF_PAGESTART(load_bias - vaddr);
eab09532d4009 (Kees Cook               2017-07-10 15:52:37 -0700 1132) 
a87938b2e246b (Michael Davidson        2015-04-14 15:47:38 -0700 1133) 			total_size = total_mapping_size(elf_phdata,
a62c5b1b6647e (Alexey Dobriyan         2020-01-30 22:16:55 -0800 1134) 							elf_ex->e_phnum);
a87938b2e246b (Michael Davidson        2015-04-14 15:47:38 -0700 1135) 			if (!total_size) {
2b1d3ae940acd (Andrew Morton           2015-05-28 15:44:24 -0700 1136) 				retval = -EINVAL;
a87938b2e246b (Michael Davidson        2015-04-14 15:47:38 -0700 1137) 				goto out_free_dentry;
a87938b2e246b (Michael Davidson        2015-04-14 15:47:38 -0700 1138) 			}
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1139) 		}
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1140) 
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700 1141) 		error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt,
a87938b2e246b (Michael Davidson        2015-04-14 15:47:38 -0700 1142) 				elf_prot, elf_flags, total_size);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1143) 		if (BAD_ADDR(error)) {
b140f25108a8b (Alexey Kuznetsov        2007-05-08 00:31:57 -0700 1144) 			retval = IS_ERR((void *)error) ?
b140f25108a8b (Alexey Kuznetsov        2007-05-08 00:31:57 -0700 1145) 				PTR_ERR((void*)error) : -EINVAL;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1146) 			goto out_free_dentry;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1147) 		}
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1148) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1149) 		if (!load_addr_set) {
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1150) 			load_addr_set = 1;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1151) 			load_addr = (elf_ppnt->p_vaddr - elf_ppnt->p_offset);
a62c5b1b6647e (Alexey Dobriyan         2020-01-30 22:16:55 -0800 1152) 			if (elf_ex->e_type == ET_DYN) {
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1153) 				load_bias += error -
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1154) 				             ELF_PAGESTART(load_bias + vaddr);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1155) 				load_addr += load_bias;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1156) 				reloc_func_desc = load_bias;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1157) 			}
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1158) 		}
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1159) 		k = elf_ppnt->p_vaddr;
f67ef446291a0 (Alexey Dobriyan         2020-01-30 22:16:52 -0800 1160) 		if ((elf_ppnt->p_flags & PF_X) && k < start_code)
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700 1161) 			start_code = k;
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700 1162) 		if (start_data < k)
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700 1163) 			start_data = k;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1164) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1165) 		/*
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1166) 		 * Check to see if the section's size will overflow the
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1167) 		 * allowed task size. Note that p_filesz must always be
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1168) 		 * <= p_memsz so it is only necessary to check p_memsz.
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1169) 		 */
ce51059be56f6 (Chuck Ebbert            2006-07-03 00:24:14 -0700 1170) 		if (BAD_ADDR(k) || elf_ppnt->p_filesz > elf_ppnt->p_memsz ||
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1171) 		    elf_ppnt->p_memsz > TASK_SIZE ||
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1172) 		    TASK_SIZE - elf_ppnt->p_memsz < k) {
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700 1173) 			/* set_brk can never work. Avoid overflows. */
b140f25108a8b (Alexey Kuznetsov        2007-05-08 00:31:57 -0700 1174) 			retval = -EINVAL;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1175) 			goto out_free_dentry;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1176) 		}
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1177) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1178) 		k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1179) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1180) 		if (k > elf_bss)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1181) 			elf_bss = k;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1182) 		if ((elf_ppnt->p_flags & PF_X) && end_code < k)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1183) 			end_code = k;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1184) 		if (end_data < k)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1185) 			end_data = k;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1186) 		k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz;
16e72e9b30986 (Denys Vlasenko          2017-02-22 15:45:16 -0800 1187) 		if (k > elf_brk) {
16e72e9b30986 (Denys Vlasenko          2017-02-22 15:45:16 -0800 1188) 			bss_prot = elf_prot;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1189) 			elf_brk = k;
16e72e9b30986 (Denys Vlasenko          2017-02-22 15:45:16 -0800 1190) 		}
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1191) 	}
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1192) 
a62c5b1b6647e (Alexey Dobriyan         2020-01-30 22:16:55 -0800 1193) 	e_entry = elf_ex->e_entry + load_bias;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1194) 	elf_bss += load_bias;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1195) 	elf_brk += load_bias;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1196) 	start_code += load_bias;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1197) 	end_code += load_bias;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1198) 	start_data += load_bias;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1199) 	end_data += load_bias;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1200) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1201) 	/* Calling set_brk effectively mmaps the pages that we need
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1202) 	 * for the bss and break sections.  We must do this before
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1203) 	 * mapping in the interpreter, to make sure it doesn't wind
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1204) 	 * up getting placed where the bss needs to go.
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1205) 	 */
16e72e9b30986 (Denys Vlasenko          2017-02-22 15:45:16 -0800 1206) 	retval = set_brk(elf_bss, elf_brk, bss_prot);
19d860a140bea (Al Viro                 2014-05-04 20:11:36 -0400 1207) 	if (retval)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1208) 		goto out_free_dentry;
6de505173e24e (akpm@osdl.org           2005-10-11 08:29:08 -0700 1209) 	if (likely(elf_bss != elf_brk) && unlikely(padzero(elf_bss))) {
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1210) 		retval = -EFAULT; /* Nobody gets to see this, but.. */
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1211) 		goto out_free_dentry;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1212) 	}
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1213) 
cc338010a233c (Alexey Dobriyan         2019-05-14 15:43:39 -0700 1214) 	if (interpreter) {
c69bcc932ef35 (Alexey Dobriyan         2020-04-06 20:11:26 -0700 1215) 		elf_entry = load_elf_interp(interp_elf_ex,
d20894a23708c (Andi Kleen              2008-02-08 04:21:54 -0800 1216) 					    interpreter,
fe0f67660ee9c (Dave Martin             2020-03-16 16:50:46 +0000 1217) 					    load_bias, interp_elf_phdata,
fe0f67660ee9c (Dave Martin             2020-03-16 16:50:46 +0000 1218) 					    &arch_state);
d20894a23708c (Andi Kleen              2008-02-08 04:21:54 -0800 1219) 		if (!IS_ERR((void *)elf_entry)) {
d20894a23708c (Andi Kleen              2008-02-08 04:21:54 -0800 1220) 			/*
d20894a23708c (Andi Kleen              2008-02-08 04:21:54 -0800 1221) 			 * load_elf_interp() returns relocation
d20894a23708c (Andi Kleen              2008-02-08 04:21:54 -0800 1222) 			 * adjustment
d20894a23708c (Andi Kleen              2008-02-08 04:21:54 -0800 1223) 			 */
d20894a23708c (Andi Kleen              2008-02-08 04:21:54 -0800 1224) 			interp_load_addr = elf_entry;
c69bcc932ef35 (Alexey Dobriyan         2020-04-06 20:11:26 -0700 1225) 			elf_entry += interp_elf_ex->e_entry;
cc503c1b43e00 (Jiri Kosina             2008-01-30 13:31:07 +0100 1226) 		}
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1227) 		if (BAD_ADDR(elf_entry)) {
ce51059be56f6 (Chuck Ebbert            2006-07-03 00:24:14 -0700 1228) 			retval = IS_ERR((void *)elf_entry) ?
ce51059be56f6 (Chuck Ebbert            2006-07-03 00:24:14 -0700 1229) 					(int)elf_entry : -EINVAL;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1230) 			goto out_free_dentry;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1231) 		}
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1232) 		reloc_func_desc = interp_load_addr;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1233) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1234) 		allow_write_access(interpreter);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1235) 		fput(interpreter);
0693ffebcfe5a (Alexey Dobriyan         2020-04-06 20:11:29 -0700 1236) 
0693ffebcfe5a (Alexey Dobriyan         2020-04-06 20:11:29 -0700 1237) 		kfree(interp_elf_ex);
aa0d1564b10f9 (Alexey Dobriyan         2020-04-06 20:11:32 -0700 1238) 		kfree(interp_elf_phdata);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1239) 	} else {
a62c5b1b6647e (Alexey Dobriyan         2020-01-30 22:16:55 -0800 1240) 		elf_entry = e_entry;
5342fba5412ce (Suresh Siddha           2006-02-26 04:18:28 +0100 1241) 		if (BAD_ADDR(elf_entry)) {
ce51059be56f6 (Chuck Ebbert            2006-07-03 00:24:14 -0700 1242) 			retval = -EINVAL;
5342fba5412ce (Suresh Siddha           2006-02-26 04:18:28 +0100 1243) 			goto out_free_dentry;
5342fba5412ce (Suresh Siddha           2006-02-26 04:18:28 +0100 1244) 		}
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1245) 	}
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1246) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1247) 	kfree(elf_phdata);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1248) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1249) 	set_binfmt(&elf_format);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1250) 
547ee84cea376 (Benjamin Herrenschmidt  2005-04-16 15:24:35 -0700 1251) #ifdef ARCH_HAS_SETUP_ADDITIONAL_PAGES
9a29a671902c2 (Gabriel Krisman Bertazi 2020-10-03 23:25:33 -0400 1252) 	retval = ARCH_SETUP_ADDITIONAL_PAGES(bprm, elf_ex, !!interpreter);
19d860a140bea (Al Viro                 2014-05-04 20:11:36 -0400 1253) 	if (retval < 0)
18c8baff8fe15 (Roland McGrath          2005-04-28 15:17:19 -0700 1254) 		goto out;
547ee84cea376 (Benjamin Herrenschmidt  2005-04-16 15:24:35 -0700 1255) #endif /* ARCH_HAS_SETUP_ADDITIONAL_PAGES */
547ee84cea376 (Benjamin Herrenschmidt  2005-04-16 15:24:35 -0700 1256) 
a62c5b1b6647e (Alexey Dobriyan         2020-01-30 22:16:55 -0800 1257) 	retval = create_elf_tables(bprm, elf_ex,
a62c5b1b6647e (Alexey Dobriyan         2020-01-30 22:16:55 -0800 1258) 			  load_addr, interp_load_addr, e_entry);
19d860a140bea (Al Viro                 2014-05-04 20:11:36 -0400 1259) 	if (retval < 0)
b6a2fea39318e (Ollie Wild              2007-07-19 01:48:16 -0700 1260) 		goto out;
03c6d723eeac2 (Alexey Dobriyan         2020-01-30 22:16:58 -0800 1261) 
03c6d723eeac2 (Alexey Dobriyan         2020-01-30 22:16:58 -0800 1262) 	mm = current->mm;
03c6d723eeac2 (Alexey Dobriyan         2020-01-30 22:16:58 -0800 1263) 	mm->end_code = end_code;
03c6d723eeac2 (Alexey Dobriyan         2020-01-30 22:16:58 -0800 1264) 	mm->start_code = start_code;
03c6d723eeac2 (Alexey Dobriyan         2020-01-30 22:16:58 -0800 1265) 	mm->start_data = start_data;
03c6d723eeac2 (Alexey Dobriyan         2020-01-30 22:16:58 -0800 1266) 	mm->end_data = end_data;
03c6d723eeac2 (Alexey Dobriyan         2020-01-30 22:16:58 -0800 1267) 	mm->start_stack = bprm->p;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1268) 
4471a675dfc7c (Jiri Kosina             2011-04-14 15:22:09 -0700 1269) 	if ((current->flags & PF_RANDOMIZE) && (randomize_va_space > 1)) {
bbdc6076d2e5d (Kees Cook               2019-05-14 15:43:57 -0700 1270) 		/*
bbdc6076d2e5d (Kees Cook               2019-05-14 15:43:57 -0700 1271) 		 * For architectures with ELF randomization, when executing
bbdc6076d2e5d (Kees Cook               2019-05-14 15:43:57 -0700 1272) 		 * a loader directly (i.e. no interpreter listed in ELF
bbdc6076d2e5d (Kees Cook               2019-05-14 15:43:57 -0700 1273) 		 * headers), move the brk area out of the mmap region
bbdc6076d2e5d (Kees Cook               2019-05-14 15:43:57 -0700 1274) 		 * (since it grows up, and may collide early with the stack
bbdc6076d2e5d (Kees Cook               2019-05-14 15:43:57 -0700 1275) 		 * growing down), and into the unused ELF_ET_DYN_BASE region.
bbdc6076d2e5d (Kees Cook               2019-05-14 15:43:57 -0700 1276) 		 */
7be3cb019db1c (Kees Cook               2019-09-26 10:15:25 -0700 1277) 		if (IS_ENABLED(CONFIG_ARCH_HAS_ELF_RANDOMIZE) &&
03c6d723eeac2 (Alexey Dobriyan         2020-01-30 22:16:58 -0800 1278) 		    elf_ex->e_type == ET_DYN && !interpreter) {
03c6d723eeac2 (Alexey Dobriyan         2020-01-30 22:16:58 -0800 1279) 			mm->brk = mm->start_brk = ELF_ET_DYN_BASE;
03c6d723eeac2 (Alexey Dobriyan         2020-01-30 22:16:58 -0800 1280) 		}
bbdc6076d2e5d (Kees Cook               2019-05-14 15:43:57 -0700 1281) 
03c6d723eeac2 (Alexey Dobriyan         2020-01-30 22:16:58 -0800 1282) 		mm->brk = mm->start_brk = arch_randomize_brk(mm);
204db6ed17743 (Kees Cook               2015-04-14 15:48:12 -0700 1283) #ifdef compat_brk_randomized
4471a675dfc7c (Jiri Kosina             2011-04-14 15:22:09 -0700 1284) 		current->brk_randomized = 1;
4471a675dfc7c (Jiri Kosina             2011-04-14 15:22:09 -0700 1285) #endif
4471a675dfc7c (Jiri Kosina             2011-04-14 15:22:09 -0700 1286) 	}
c1d171a002942 (Jiri Kosina             2008-01-30 13:30:40 +0100 1287) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1288) 	if (current->personality & MMAP_PAGE_ZERO) {
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1289) 		/* Why this, you ask???  Well SVr4 maps page 0 as read-only,
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1290) 		   and some applications "depend" upon this behavior.
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1291) 		   Since we do not have the power to recompile these, we
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700 1292) 		   emulate the SVr4 behavior. Sigh. */
6be5ceb02e98e (Linus Torvalds          2012-04-20 17:13:58 -0700 1293) 		error = vm_mmap(NULL, 0, PAGE_SIZE, PROT_READ | PROT_EXEC,
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1294) 				MAP_FIXED | MAP_PRIVATE, 0);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1295) 	}
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1296) 
249b08e4e504d (Alexey Dobriyan         2019-05-14 15:43:54 -0700 1297) 	regs = current_pt_regs();
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1298) #ifdef ELF_PLAT_INIT
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1299) 	/*
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1300) 	 * The ABI may specify that certain registers be set up in special
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1301) 	 * ways (on i386 %edx is the address of a DT_FINI function, for
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1302) 	 * example.  In addition, it may also specify (eg, PowerPC64 ELF)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1303) 	 * that the e_entry field is the address of the function descriptor
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1304) 	 * for the startup routine, rather than the address of the startup
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1305) 	 * routine itself.  This macro performs whatever initialization to
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1306) 	 * the regs structure is required as well as any relocations to the
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1307) 	 * function descriptor entries when executing dynamically links apps.
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1308) 	 */
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1309) 	ELF_PLAT_INIT(regs, reloc_func_desc);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1310) #endif
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1311) 
b83838313386f (Kees Cook               2018-04-10 16:34:57 -0700 1312) 	finalize_exec(bprm);
bc3d7bf61a9ea (Gabriel Krisman Bertazi 2020-10-03 23:25:31 -0400 1313) 	START_THREAD(elf_ex, regs, elf_entry, bprm->p);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1314) 	retval = 0;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1315) out:
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1316) 	return retval;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1317) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1318) 	/* error cleanup */
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1319) out_free_dentry:
0693ffebcfe5a (Alexey Dobriyan         2020-04-06 20:11:29 -0700 1320) 	kfree(interp_elf_ex);
a9d9ef133f443 (Paul Burton             2014-09-11 08:30:15 +0100 1321) 	kfree(interp_elf_phdata);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1322) 	allow_write_access(interpreter);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1323) 	if (interpreter)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1324) 		fput(interpreter);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1325) out_free_ph:
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1326) 	kfree(elf_phdata);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1327) 	goto out;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1328) }
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1329) 
69369a7003735 (Josh Triplett           2014-04-03 14:48:27 -0700 1330) #ifdef CONFIG_USELIB
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1331) /* This is really simpleminded and specialized - we are loading an
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1332)    a.out library that is given an ELF header. */
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1333) static int load_elf_library(struct file *file)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1334) {
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1335) 	struct elf_phdr *elf_phdata;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1336) 	struct elf_phdr *eppnt;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1337) 	unsigned long elf_bss, bss, len;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1338) 	int retval, error, i, j;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1339) 	struct elfhdr elf_ex;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1340) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1341) 	error = -ENOEXEC;
658c033565118 (Alexey Dobriyan         2019-12-04 16:52:25 -0800 1342) 	retval = elf_read(file, &elf_ex, sizeof(elf_ex), 0);
658c033565118 (Alexey Dobriyan         2019-12-04 16:52:25 -0800 1343) 	if (retval < 0)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1344) 		goto out;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1345) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1346) 	if (memcmp(elf_ex.e_ident, ELFMAG, SELFMAG) != 0)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1347) 		goto out;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1348) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1349) 	/* First of all, some simple consistency checks */
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1350) 	if (elf_ex.e_type != ET_EXEC || elf_ex.e_phnum > 2 ||
72c2d53192004 (Al Viro                 2013-09-22 16:27:52 -0400 1351) 	    !elf_check_arch(&elf_ex) || !file->f_op->mmap)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1352) 		goto out;
4755200b6b116 (Nicolas Pitre           2017-08-16 16:05:13 -0400 1353) 	if (elf_check_fdpic(&elf_ex))
4755200b6b116 (Nicolas Pitre           2017-08-16 16:05:13 -0400 1354) 		goto out;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1355) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1356) 	/* Now read in all of the header information */
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1357) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1358) 	j = sizeof(struct elf_phdr) * elf_ex.e_phnum;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1359) 	/* j < ELF_MIN_ALIGN because elf_ex.e_phnum <= 2 */
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1360) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1361) 	error = -ENOMEM;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1362) 	elf_phdata = kmalloc(j, GFP_KERNEL);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1363) 	if (!elf_phdata)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1364) 		goto out;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1365) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1366) 	eppnt = elf_phdata;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1367) 	error = -ENOEXEC;
658c033565118 (Alexey Dobriyan         2019-12-04 16:52:25 -0800 1368) 	retval = elf_read(file, eppnt, j, elf_ex.e_phoff);
658c033565118 (Alexey Dobriyan         2019-12-04 16:52:25 -0800 1369) 	if (retval < 0)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1370) 		goto out_free_ph;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1371) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1372) 	for (j = 0, i = 0; i<elf_ex.e_phnum; i++)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1373) 		if ((eppnt + i)->p_type == PT_LOAD)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1374) 			j++;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1375) 	if (j != 1)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1376) 		goto out_free_ph;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1377) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1378) 	while (eppnt->p_type != PT_LOAD)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1379) 		eppnt++;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1380) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1381) 	/* Now use mmap to map the library into memory. */
6be5ceb02e98e (Linus Torvalds          2012-04-20 17:13:58 -0700 1382) 	error = vm_mmap(file,
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1383) 			ELF_PAGESTART(eppnt->p_vaddr),
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1384) 			(eppnt->p_filesz +
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1385) 			 ELF_PAGEOFFSET(eppnt->p_vaddr)),
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1386) 			PROT_READ | PROT_WRITE | PROT_EXEC,
4ed28639519c7 (Michal Hocko            2018-04-10 16:36:01 -0700 1387) 			MAP_FIXED_NOREPLACE | MAP_PRIVATE | MAP_DENYWRITE,
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1388) 			(eppnt->p_offset -
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1389) 			 ELF_PAGEOFFSET(eppnt->p_vaddr)));
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1390) 	if (error != ELF_PAGESTART(eppnt->p_vaddr))
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1391) 		goto out_free_ph;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1392) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1393) 	elf_bss = eppnt->p_vaddr + eppnt->p_filesz;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1394) 	if (padzero(elf_bss)) {
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1395) 		error = -EFAULT;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1396) 		goto out_free_ph;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1397) 	}
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1398) 
24962af7e1041 (Oscar Salvador          2018-07-13 16:59:13 -0700 1399) 	len = ELF_PAGEALIGN(eppnt->p_filesz + eppnt->p_vaddr);
24962af7e1041 (Oscar Salvador          2018-07-13 16:59:13 -0700 1400) 	bss = ELF_PAGEALIGN(eppnt->p_memsz + eppnt->p_vaddr);
ecc2bc8ac0388 (Michal Hocko            2016-05-23 16:25:39 -0700 1401) 	if (bss > len) {
ecc2bc8ac0388 (Michal Hocko            2016-05-23 16:25:39 -0700 1402) 		error = vm_brk(len, bss - len);
5d22fc25d4fc8 (Linus Torvalds          2016-05-27 15:57:31 -0700 1403) 		if (error)
ecc2bc8ac0388 (Michal Hocko            2016-05-23 16:25:39 -0700 1404) 			goto out_free_ph;
ecc2bc8ac0388 (Michal Hocko            2016-05-23 16:25:39 -0700 1405) 	}
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1406) 	error = 0;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1407) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1408) out_free_ph:
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1409) 	kfree(elf_phdata);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1410) out:
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1411) 	return error;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1412) }
69369a7003735 (Josh Triplett           2014-04-03 14:48:27 -0700 1413) #endif /* #ifdef CONFIG_USELIB */
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1414) 
698ba7b5a3a7b (Christoph Hellwig       2009-12-15 16:47:37 -0800 1415) #ifdef CONFIG_ELF_CORE
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1416) /*
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1417)  * ELF core dumper
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1418)  *
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1419)  * Modelled on fs/exec.c:aout_core_dump()
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1420)  * Jeremy Fitzhardinge <jeremy@sw.oz.au>
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1421)  */
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1422) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1423) /* An ELF note in memory */
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1424) struct memelfnote
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1425) {
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1426) 	const char *name;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1427) 	int type;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1428) 	unsigned int datasz;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1429) 	void *data;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1430) };
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1431) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1432) static int notesize(struct memelfnote *en)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1433) {
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1434) 	int sz;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1435) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1436) 	sz = sizeof(struct elf_note);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1437) 	sz += roundup(strlen(en->name) + 1, 4);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1438) 	sz += roundup(en->datasz, 4);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1439) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1440) 	return sz;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1441) }
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1442) 
ecc8c7725e6c2 (Al Viro                 2013-10-05 15:32:35 -0400 1443) static int writenote(struct memelfnote *men, struct coredump_params *cprm)
d025c9db7f31f (Andi Kleen              2006-09-30 23:29:28 -0700 1444) {
d025c9db7f31f (Andi Kleen              2006-09-30 23:29:28 -0700 1445) 	struct elf_note en;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1446) 	en.n_namesz = strlen(men->name) + 1;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1447) 	en.n_descsz = men->datasz;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1448) 	en.n_type = men->type;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1449) 
ecc8c7725e6c2 (Al Viro                 2013-10-05 15:32:35 -0400 1450) 	return dump_emit(cprm, &en, sizeof(en)) &&
22a8cb8248ba5 (Al Viro                 2013-10-08 11:05:01 -0400 1451) 	    dump_emit(cprm, men->name, en.n_namesz) && dump_align(cprm, 4) &&
22a8cb8248ba5 (Al Viro                 2013-10-08 11:05:01 -0400 1452) 	    dump_emit(cprm, men->data, men->datasz) && dump_align(cprm, 4);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1453) }
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1454) 
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 1455) static void fill_elf_header(struct elfhdr *elf, int segs,
d3330cf08ccf9 (Zhang Yanfei            2013-02-21 16:44:20 -0800 1456) 			    u16 machine, u32 flags)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1457) {
6970c8eff85dd (Cyrill Gorcunov         2008-04-29 01:01:18 -0700 1458) 	memset(elf, 0, sizeof(*elf));
6970c8eff85dd (Cyrill Gorcunov         2008-04-29 01:01:18 -0700 1459) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1460) 	memcpy(elf->e_ident, ELFMAG, SELFMAG);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1461) 	elf->e_ident[EI_CLASS] = ELF_CLASS;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1462) 	elf->e_ident[EI_DATA] = ELF_DATA;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1463) 	elf->e_ident[EI_VERSION] = EV_CURRENT;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1464) 	elf->e_ident[EI_OSABI] = ELF_OSABI;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1465) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1466) 	elf->e_type = ET_CORE;
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 1467) 	elf->e_machine = machine;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1468) 	elf->e_version = EV_CURRENT;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1469) 	elf->e_phoff = sizeof(struct elfhdr);
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 1470) 	elf->e_flags = flags;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1471) 	elf->e_ehsize = sizeof(struct elfhdr);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1472) 	elf->e_phentsize = sizeof(struct elf_phdr);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1473) 	elf->e_phnum = segs;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1474) }
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1475) 
8d6b5eeea5eb6 (Andrew Morton           2006-09-25 23:32:04 -0700 1476) static void fill_elf_note_phdr(struct elf_phdr *phdr, int sz, loff_t offset)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1477) {
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1478) 	phdr->p_type = PT_NOTE;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1479) 	phdr->p_offset = offset;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1480) 	phdr->p_vaddr = 0;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1481) 	phdr->p_paddr = 0;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1482) 	phdr->p_filesz = sz;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1483) 	phdr->p_memsz = 0;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1484) 	phdr->p_flags = 0;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1485) 	phdr->p_align = 0;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1486) }
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1487) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1488) static void fill_note(struct memelfnote *note, const char *name, int type, 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1489) 		unsigned int sz, void *data)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1490) {
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1491) 	note->name = name;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1492) 	note->type = type;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1493) 	note->datasz = sz;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1494) 	note->data = data;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1495) }
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1496) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1497) /*
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700 1498)  * fill up all the fields in prstatus from the given task struct, except
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700 1499)  * registers which need to be filled up separately.
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1500)  */
f2485a2dc9f0f (Al Viro                 2020-06-13 00:08:44 -0400 1501) static void fill_prstatus(struct elf_prstatus_common *prstatus,
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700 1502) 		struct task_struct *p, long signr)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1503) {
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1504) 	prstatus->pr_info.si_signo = prstatus->pr_cursig = signr;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1505) 	prstatus->pr_sigpend = p->pending.signal.sig[0];
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1506) 	prstatus->pr_sighold = p->blocked.sig[0];
3b34fc5880a2d (Oleg Nesterov           2009-06-17 16:27:38 -0700 1507) 	rcu_read_lock();
3b34fc5880a2d (Oleg Nesterov           2009-06-17 16:27:38 -0700 1508) 	prstatus->pr_ppid = task_pid_vnr(rcu_dereference(p->real_parent));
3b34fc5880a2d (Oleg Nesterov           2009-06-17 16:27:38 -0700 1509) 	rcu_read_unlock();
b488893a390ed (Pavel Emelyanov         2007-10-18 23:40:14 -0700 1510) 	prstatus->pr_pid = task_pid_vnr(p);
b488893a390ed (Pavel Emelyanov         2007-10-18 23:40:14 -0700 1511) 	prstatus->pr_pgrp = task_pgrp_vnr(p);
b488893a390ed (Pavel Emelyanov         2007-10-18 23:40:14 -0700 1512) 	prstatus->pr_sid = task_session_vnr(p);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1513) 	if (thread_group_leader(p)) {
cd19c364b313c (Frederic Weisbecker     2017-01-31 04:09:27 +0100 1514) 		struct task_cputime cputime;
f06febc96ba8e (Frank Mayhar            2008-09-12 09:54:39 -0700 1515) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1516) 		/*
f06febc96ba8e (Frank Mayhar            2008-09-12 09:54:39 -0700 1517) 		 * This is the record for the group leader.  It shows the
f06febc96ba8e (Frank Mayhar            2008-09-12 09:54:39 -0700 1518) 		 * group-wide total, not its individual thread total.
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1519) 		 */
cd19c364b313c (Frederic Weisbecker     2017-01-31 04:09:27 +0100 1520) 		thread_group_cputime(p, &cputime);
e2bb80d55d75c (Arnd Bergmann           2017-11-23 13:46:33 +0100 1521) 		prstatus->pr_utime = ns_to_kernel_old_timeval(cputime.utime);
e2bb80d55d75c (Arnd Bergmann           2017-11-23 13:46:33 +0100 1522) 		prstatus->pr_stime = ns_to_kernel_old_timeval(cputime.stime);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1523) 	} else {
cd19c364b313c (Frederic Weisbecker     2017-01-31 04:09:27 +0100 1524) 		u64 utime, stime;
6fac4829ce0ef (Frederic Weisbecker     2012-11-13 14:20:55 +0100 1525) 
cd19c364b313c (Frederic Weisbecker     2017-01-31 04:09:27 +0100 1526) 		task_cputime(p, &utime, &stime);
e2bb80d55d75c (Arnd Bergmann           2017-11-23 13:46:33 +0100 1527) 		prstatus->pr_utime = ns_to_kernel_old_timeval(utime);
e2bb80d55d75c (Arnd Bergmann           2017-11-23 13:46:33 +0100 1528) 		prstatus->pr_stime = ns_to_kernel_old_timeval(stime);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1529) 	}
5613fda9a503c (Frederic Weisbecker     2017-01-31 04:09:23 +0100 1530) 
e2bb80d55d75c (Arnd Bergmann           2017-11-23 13:46:33 +0100 1531) 	prstatus->pr_cutime = ns_to_kernel_old_timeval(p->signal->cutime);
e2bb80d55d75c (Arnd Bergmann           2017-11-23 13:46:33 +0100 1532) 	prstatus->pr_cstime = ns_to_kernel_old_timeval(p->signal->cstime);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1533) }
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1534) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1535) static int fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p,
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1536) 		       struct mm_struct *mm)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1537) {
c69e8d9c01db2 (David Howells           2008-11-14 10:39:19 +1100 1538) 	const struct cred *cred;
a84a505956f5c (Greg Kroah-Hartman      2005-05-11 00:10:44 -0700 1539) 	unsigned int i, len;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1540) 	
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1541) 	/* first copy the parameters from user space */
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1542) 	memset(psinfo, 0, sizeof(struct elf_prpsinfo));
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1543) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1544) 	len = mm->arg_end - mm->arg_start;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1545) 	if (len >= ELF_PRARGSZ)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1546) 		len = ELF_PRARGSZ-1;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1547) 	if (copy_from_user(&psinfo->pr_psargs,
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1548) 		           (const char __user *)mm->arg_start, len))
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1549) 		return -EFAULT;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1550) 	for(i = 0; i < len; i++)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1551) 		if (psinfo->pr_psargs[i] == 0)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1552) 			psinfo->pr_psargs[i] = ' ';
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1553) 	psinfo->pr_psargs[len] = 0;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1554) 
3b34fc5880a2d (Oleg Nesterov           2009-06-17 16:27:38 -0700 1555) 	rcu_read_lock();
3b34fc5880a2d (Oleg Nesterov           2009-06-17 16:27:38 -0700 1556) 	psinfo->pr_ppid = task_pid_vnr(rcu_dereference(p->real_parent));
3b34fc5880a2d (Oleg Nesterov           2009-06-17 16:27:38 -0700 1557) 	rcu_read_unlock();
b488893a390ed (Pavel Emelyanov         2007-10-18 23:40:14 -0700 1558) 	psinfo->pr_pid = task_pid_vnr(p);
b488893a390ed (Pavel Emelyanov         2007-10-18 23:40:14 -0700 1559) 	psinfo->pr_pgrp = task_pgrp_vnr(p);
b488893a390ed (Pavel Emelyanov         2007-10-18 23:40:14 -0700 1560) 	psinfo->pr_sid = task_session_vnr(p);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1561) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1562) 	i = p->state ? ffz(~p->state) + 1 : 0;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1563) 	psinfo->pr_state = i;
55148548124e3 (Carsten Otte            2006-03-25 03:08:22 -0800 1564) 	psinfo->pr_sname = (i > 5) ? '.' : "RSDTZW"[i];
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1565) 	psinfo->pr_zomb = psinfo->pr_sname == 'Z';
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1566) 	psinfo->pr_nice = task_nice(p);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1567) 	psinfo->pr_flag = p->flags;
c69e8d9c01db2 (David Howells           2008-11-14 10:39:19 +1100 1568) 	rcu_read_lock();
c69e8d9c01db2 (David Howells           2008-11-14 10:39:19 +1100 1569) 	cred = __task_cred(p);
ebc887b278944 (Eric W. Biederman       2012-02-07 18:36:10 -0800 1570) 	SET_UID(psinfo->pr_uid, from_kuid_munged(cred->user_ns, cred->uid));
ebc887b278944 (Eric W. Biederman       2012-02-07 18:36:10 -0800 1571) 	SET_GID(psinfo->pr_gid, from_kgid_munged(cred->user_ns, cred->gid));
c69e8d9c01db2 (David Howells           2008-11-14 10:39:19 +1100 1572) 	rcu_read_unlock();
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1573) 	strncpy(psinfo->pr_fname, p->comm, sizeof(psinfo->pr_fname));
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1574) 	
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1575) 	return 0;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1576) }
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1577) 
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 1578) static void fill_auxv_note(struct memelfnote *note, struct mm_struct *mm)
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 1579) {
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 1580) 	elf_addr_t *auxv = (elf_addr_t *) mm->saved_auxv;
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 1581) 	int i = 0;
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 1582) 	do
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 1583) 		i += 2;
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 1584) 	while (auxv[i - 2] != AT_NULL);
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 1585) 	fill_note(note, "CORE", NT_AUXV, i * sizeof(elf_addr_t), auxv);
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 1586) }
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 1587) 
49ae4d4b113be (Denys Vlasenko          2012-10-04 17:15:35 -0700 1588) static void fill_siginfo_note(struct memelfnote *note, user_siginfo_t *csigdata,
ae7795bc6187a (Eric W. Biederman       2018-09-25 11:27:20 +0200 1589) 		const kernel_siginfo_t *siginfo)
49ae4d4b113be (Denys Vlasenko          2012-10-04 17:15:35 -0700 1590) {
fa4751f454e6b (Eric W. Biederman       2020-05-05 12:12:54 +0200 1591) 	copy_siginfo_to_external(csigdata, siginfo);
49ae4d4b113be (Denys Vlasenko          2012-10-04 17:15:35 -0700 1592) 	fill_note(note, "CORE", NT_SIGINFO, sizeof(*csigdata), csigdata);
49ae4d4b113be (Denys Vlasenko          2012-10-04 17:15:35 -0700 1593) }
49ae4d4b113be (Denys Vlasenko          2012-10-04 17:15:35 -0700 1594) 
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1595) #define MAX_FILE_NOTE_SIZE (4*1024*1024)
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1596) /*
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1597)  * Format of NT_FILE note:
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1598)  *
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1599)  * long count     -- how many files are mapped
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1600)  * long page_size -- units for file_ofs
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1601)  * array of [COUNT] elements of
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1602)  *   long start
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1603)  *   long end
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1604)  *   long file_ofs
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1605)  * followed by COUNT filenames in ASCII: "FILE1" NUL "FILE2" NUL...
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1606)  */
72023656961b8 (Dan Aloni               2013-09-30 13:45:02 -0700 1607) static int fill_files_note(struct memelfnote *note)
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1608) {
03c6d723eeac2 (Alexey Dobriyan         2020-01-30 22:16:58 -0800 1609) 	struct mm_struct *mm = current->mm;
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1610) 	struct vm_area_struct *vma;
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1611) 	unsigned count, size, names_ofs, remaining, n;
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1612) 	user_long_t *data;
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1613) 	user_long_t *start_end_ofs;
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1614) 	char *name_base, *name_curpos;
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1615) 
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1616) 	/* *Estimated* file count and total data size needed */
03c6d723eeac2 (Alexey Dobriyan         2020-01-30 22:16:58 -0800 1617) 	count = mm->map_count;
60c9d92f887f4 (Alexey Dobriyan         2018-02-06 15:39:13 -0800 1618) 	if (count > UINT_MAX / 64)
60c9d92f887f4 (Alexey Dobriyan         2018-02-06 15:39:13 -0800 1619) 		return -EINVAL;
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1620) 	size = count * 64;
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1621) 
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1622) 	names_ofs = (2 + 3 * count) * sizeof(data[0]);
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1623)  alloc:
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1624) 	if (size >= MAX_FILE_NOTE_SIZE) /* paranoia check */
72023656961b8 (Dan Aloni               2013-09-30 13:45:02 -0700 1625) 		return -EINVAL;
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1626) 	size = round_up(size, PAGE_SIZE);
1fbede6e6f3dc (Alexey Dobriyan         2020-01-30 22:17:10 -0800 1627) 	/*
1fbede6e6f3dc (Alexey Dobriyan         2020-01-30 22:17:10 -0800 1628) 	 * "size" can be 0 here legitimately.
1fbede6e6f3dc (Alexey Dobriyan         2020-01-30 22:17:10 -0800 1629) 	 * Let it ENOMEM and omit NT_FILE section which will be empty anyway.
1fbede6e6f3dc (Alexey Dobriyan         2020-01-30 22:17:10 -0800 1630) 	 */
86a2bb5ad8316 (Alexey Dobriyan         2018-06-14 15:27:24 -0700 1631) 	data = kvmalloc(size, GFP_KERNEL);
86a2bb5ad8316 (Alexey Dobriyan         2018-06-14 15:27:24 -0700 1632) 	if (ZERO_OR_NULL_PTR(data))
72023656961b8 (Dan Aloni               2013-09-30 13:45:02 -0700 1633) 		return -ENOMEM;
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1634) 
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1635) 	start_end_ofs = data + 2;
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1636) 	name_base = name_curpos = ((char *)data) + names_ofs;
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1637) 	remaining = size - names_ofs;
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1638) 	count = 0;
03c6d723eeac2 (Alexey Dobriyan         2020-01-30 22:16:58 -0800 1639) 	for (vma = mm->mmap; vma != NULL; vma = vma->vm_next) {
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1640) 		struct file *file;
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1641) 		const char *filename;
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1642) 
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1643) 		file = vma->vm_file;
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1644) 		if (!file)
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1645) 			continue;
9bf39ab2adafd (Miklos Szeredi          2015-06-19 10:29:13 +0200 1646) 		filename = file_path(file, name_curpos, remaining);
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1647) 		if (IS_ERR(filename)) {
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1648) 			if (PTR_ERR(filename) == -ENAMETOOLONG) {
86a2bb5ad8316 (Alexey Dobriyan         2018-06-14 15:27:24 -0700 1649) 				kvfree(data);
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1650) 				size = size * 5 / 4;
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1651) 				goto alloc;
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1652) 			}
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1653) 			continue;
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1654) 		}
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1655) 
9bf39ab2adafd (Miklos Szeredi          2015-06-19 10:29:13 +0200 1656) 		/* file_path() fills at the end, move name down */
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1657) 		/* n = strlen(filename) + 1: */
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1658) 		n = (name_curpos + remaining) - filename;
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1659) 		remaining = filename - name_curpos;
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1660) 		memmove(name_curpos, filename, n);
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1661) 		name_curpos += n;
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1662) 
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1663) 		*start_end_ofs++ = vma->vm_start;
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1664) 		*start_end_ofs++ = vma->vm_end;
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1665) 		*start_end_ofs++ = vma->vm_pgoff;
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1666) 		count++;
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1667) 	}
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1668) 
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1669) 	/* Now we know exact count of files, can store it */
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1670) 	data[0] = count;
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1671) 	data[1] = PAGE_SIZE;
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1672) 	/*
03c6d723eeac2 (Alexey Dobriyan         2020-01-30 22:16:58 -0800 1673) 	 * Count usually is less than mm->map_count,
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1674) 	 * we need to move filenames down.
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1675) 	 */
03c6d723eeac2 (Alexey Dobriyan         2020-01-30 22:16:58 -0800 1676) 	n = mm->map_count - count;
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1677) 	if (n != 0) {
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1678) 		unsigned shift_bytes = n * 3 * sizeof(data[0]);
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1679) 		memmove(name_base - shift_bytes, name_base,
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1680) 			name_curpos - name_base);
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1681) 		name_curpos -= shift_bytes;
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1682) 	}
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1683) 
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1684) 	size = name_curpos - (char *)data;
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1685) 	fill_note(note, "CORE", NT_FILE, size, data);
72023656961b8 (Dan Aloni               2013-09-30 13:45:02 -0700 1686) 	return 0;
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1687) }
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1688) 
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1689) #ifdef CORE_DUMP_USE_REGSET
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1690) #include <linux/regset.h>
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1691) 
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1692) struct elf_thread_core_info {
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1693) 	struct elf_thread_core_info *next;
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1694) 	struct task_struct *task;
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1695) 	struct elf_prstatus prstatus;
5e01fdff04b7f (Gustavo A. R. Silva     2020-08-31 08:25:42 -0500 1696) 	struct memelfnote notes[];
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1697) };
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1698) 
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1699) struct elf_note_info {
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1700) 	struct elf_thread_core_info *thread;
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1701) 	struct memelfnote psinfo;
49ae4d4b113be (Denys Vlasenko          2012-10-04 17:15:35 -0700 1702) 	struct memelfnote signote;
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1703) 	struct memelfnote auxv;
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1704) 	struct memelfnote files;
49ae4d4b113be (Denys Vlasenko          2012-10-04 17:15:35 -0700 1705) 	user_siginfo_t csigdata;
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1706) 	size_t size;
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1707) 	int thread_notes;
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1708) };
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1709) 
d31472b6d4f79 (Roland McGrath          2008-03-04 14:28:30 -0800 1710) /*
d31472b6d4f79 (Roland McGrath          2008-03-04 14:28:30 -0800 1711)  * When a regset has a writeback hook, we call it on each thread before
d31472b6d4f79 (Roland McGrath          2008-03-04 14:28:30 -0800 1712)  * dumping user memory.  On register window machines, this makes sure the
d31472b6d4f79 (Roland McGrath          2008-03-04 14:28:30 -0800 1713)  * user memory backing the register data is up to date before we read it.
d31472b6d4f79 (Roland McGrath          2008-03-04 14:28:30 -0800 1714)  */
d31472b6d4f79 (Roland McGrath          2008-03-04 14:28:30 -0800 1715) static void do_thread_regset_writeback(struct task_struct *task,
d31472b6d4f79 (Roland McGrath          2008-03-04 14:28:30 -0800 1716) 				       const struct user_regset *regset)
d31472b6d4f79 (Roland McGrath          2008-03-04 14:28:30 -0800 1717) {
d31472b6d4f79 (Roland McGrath          2008-03-04 14:28:30 -0800 1718) 	if (regset->writeback)
d31472b6d4f79 (Roland McGrath          2008-03-04 14:28:30 -0800 1719) 		regset->writeback(task, regset, 1);
d31472b6d4f79 (Roland McGrath          2008-03-04 14:28:30 -0800 1720) }
d31472b6d4f79 (Roland McGrath          2008-03-04 14:28:30 -0800 1721) 
0953f65d5db72 (H. J. Lu                2012-02-14 13:34:52 -0800 1722) #ifndef PRSTATUS_SIZE
8a00dd0012f38 (Al Viro                 2020-06-22 20:14:02 -0400 1723) #define PRSTATUS_SIZE sizeof(struct elf_prstatus)
0953f65d5db72 (H. J. Lu                2012-02-14 13:34:52 -0800 1724) #endif
0953f65d5db72 (H. J. Lu                2012-02-14 13:34:52 -0800 1725) 
0953f65d5db72 (H. J. Lu                2012-02-14 13:34:52 -0800 1726) #ifndef SET_PR_FPVALID
8a00dd0012f38 (Al Viro                 2020-06-22 20:14:02 -0400 1727) #define SET_PR_FPVALID(S) ((S)->pr_fpvalid = 1)
0953f65d5db72 (H. J. Lu                2012-02-14 13:34:52 -0800 1728) #endif
0953f65d5db72 (H. J. Lu                2012-02-14 13:34:52 -0800 1729) 
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1730) static int fill_thread_core_info(struct elf_thread_core_info *t,
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1731) 				 const struct user_regset_view *view,
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1732) 				 long signr, size_t *total)
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1733) {
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1734) 	unsigned int i;
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1735) 
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1736) 	/*
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1737) 	 * NT_PRSTATUS is the one special case, because the regset data
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1738) 	 * goes into the pr_reg field inside the note contents, rather
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1739) 	 * than being the whole note contents.  We fill the reset in here.
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1740) 	 * We assume that regset 0 is NT_PRSTATUS.
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1741) 	 */
f2485a2dc9f0f (Al Viro                 2020-06-13 00:08:44 -0400 1742) 	fill_prstatus(&t->prstatus.common, t->task, signr);
8a00dd0012f38 (Al Viro                 2020-06-22 20:14:02 -0400 1743) 	regset_get(t->task, &view->regsets[0],
b4e9c9549f623 (Al Viro                 2020-06-01 19:42:40 -0400 1744) 		   sizeof(t->prstatus.pr_reg), &t->prstatus.pr_reg);
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1745) 
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1746) 	fill_note(&t->notes[0], "CORE", NT_PRSTATUS,
8a00dd0012f38 (Al Viro                 2020-06-22 20:14:02 -0400 1747) 		  PRSTATUS_SIZE, &t->prstatus);
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1748) 	*total += notesize(&t->notes[0]);
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1749) 
d31472b6d4f79 (Roland McGrath          2008-03-04 14:28:30 -0800 1750) 	do_thread_regset_writeback(t->task, &view->regsets[0]);
d31472b6d4f79 (Roland McGrath          2008-03-04 14:28:30 -0800 1751) 
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1752) 	/*
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1753) 	 * Each other regset might generate a note too.  For each regset
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1754) 	 * that has no core_note_type or is inactive, we leave t->notes[i]
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1755) 	 * all zero and we'll know to skip writing it later.
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1756) 	 */
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1757) 	for (i = 1; i < view->n; ++i) {
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1758) 		const struct user_regset *regset = &view->regsets[i];
b4e9c9549f623 (Al Viro                 2020-06-01 19:42:40 -0400 1759) 		int note_type = regset->core_note_type;
b4e9c9549f623 (Al Viro                 2020-06-01 19:42:40 -0400 1760) 		bool is_fpreg = note_type == NT_PRFPREG;
b4e9c9549f623 (Al Viro                 2020-06-01 19:42:40 -0400 1761) 		void *data;
b4e9c9549f623 (Al Viro                 2020-06-01 19:42:40 -0400 1762) 		int ret;
b4e9c9549f623 (Al Viro                 2020-06-01 19:42:40 -0400 1763) 
d31472b6d4f79 (Roland McGrath          2008-03-04 14:28:30 -0800 1764) 		do_thread_regset_writeback(t->task, regset);
b4e9c9549f623 (Al Viro                 2020-06-01 19:42:40 -0400 1765) 		if (!note_type) // not for coredumps
b4e9c9549f623 (Al Viro                 2020-06-01 19:42:40 -0400 1766) 			continue;
b4e9c9549f623 (Al Viro                 2020-06-01 19:42:40 -0400 1767) 		if (regset->active && regset->active(t->task, regset) <= 0)
b4e9c9549f623 (Al Viro                 2020-06-01 19:42:40 -0400 1768) 			continue;
b4e9c9549f623 (Al Viro                 2020-06-01 19:42:40 -0400 1769) 
b4e9c9549f623 (Al Viro                 2020-06-01 19:42:40 -0400 1770) 		ret = regset_get_alloc(t->task, regset, ~0U, &data);
b4e9c9549f623 (Al Viro                 2020-06-01 19:42:40 -0400 1771) 		if (ret < 0)
b4e9c9549f623 (Al Viro                 2020-06-01 19:42:40 -0400 1772) 			continue;
b4e9c9549f623 (Al Viro                 2020-06-01 19:42:40 -0400 1773) 
b4e9c9549f623 (Al Viro                 2020-06-01 19:42:40 -0400 1774) 		if (is_fpreg)
8a00dd0012f38 (Al Viro                 2020-06-22 20:14:02 -0400 1775) 			SET_PR_FPVALID(&t->prstatus);
b4e9c9549f623 (Al Viro                 2020-06-01 19:42:40 -0400 1776) 
b4e9c9549f623 (Al Viro                 2020-06-01 19:42:40 -0400 1777) 		fill_note(&t->notes[i], is_fpreg ? "CORE" : "LINUX",
b4e9c9549f623 (Al Viro                 2020-06-01 19:42:40 -0400 1778) 			  note_type, ret, data);
b4e9c9549f623 (Al Viro                 2020-06-01 19:42:40 -0400 1779) 
b4e9c9549f623 (Al Viro                 2020-06-01 19:42:40 -0400 1780) 		*total += notesize(&t->notes[i]);
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1781) 	}
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1782) 
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1783) 	return 1;
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1784) }
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1785) 
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1786) static int fill_note_info(struct elfhdr *elf, int phdrs,
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1787) 			  struct elf_note_info *info,
ae7795bc6187a (Eric W. Biederman       2018-09-25 11:27:20 +0200 1788) 			  const kernel_siginfo_t *siginfo, struct pt_regs *regs)
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1789) {
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1790) 	struct task_struct *dump_task = current;
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1791) 	const struct user_regset_view *view = task_user_regset_view(dump_task);
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1792) 	struct elf_thread_core_info *t;
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1793) 	struct elf_prpsinfo *psinfo;
83914441f94c6 (Oleg Nesterov           2008-07-25 01:47:45 -0700 1794) 	struct core_thread *ct;
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1795) 	unsigned int i;
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1796) 
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1797) 	info->size = 0;
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1798) 	info->thread = NULL;
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1799) 
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1800) 	psinfo = kmalloc(sizeof(*psinfo), GFP_KERNEL);
6899e92d65c49 (Alan Cox                2012-12-17 16:02:09 -0800 1801) 	if (psinfo == NULL) {
6899e92d65c49 (Alan Cox                2012-12-17 16:02:09 -0800 1802) 		info->psinfo.data = NULL; /* So we don't free this wrongly */
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1803) 		return 0;
6899e92d65c49 (Alan Cox                2012-12-17 16:02:09 -0800 1804) 	}
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1805) 
e2dbe12557d85 (Amerigo Wang            2009-07-01 01:06:26 -0400 1806) 	fill_note(&info->psinfo, "CORE", NT_PRPSINFO, sizeof(*psinfo), psinfo);
e2dbe12557d85 (Amerigo Wang            2009-07-01 01:06:26 -0400 1807) 
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1808) 	/*
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1809) 	 * Figure out how many notes we're going to need for each thread.
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1810) 	 */
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1811) 	info->thread_notes = 0;
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1812) 	for (i = 0; i < view->n; ++i)
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1813) 		if (view->regsets[i].core_note_type != 0)
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1814) 			++info->thread_notes;
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1815) 
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1816) 	/*
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1817) 	 * Sanity check.  We rely on regset 0 being in NT_PRSTATUS,
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1818) 	 * since it is our one special case.
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1819) 	 */
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1820) 	if (unlikely(info->thread_notes == 0) ||
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1821) 	    unlikely(view->regsets[0].core_note_type != NT_PRSTATUS)) {
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1822) 		WARN_ON(1);
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1823) 		return 0;
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1824) 	}
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1825) 
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1826) 	/*
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1827) 	 * Initialize the ELF file header.
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1828) 	 */
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1829) 	fill_elf_header(elf, phdrs,
d3330cf08ccf9 (Zhang Yanfei            2013-02-21 16:44:20 -0800 1830) 			view->e_machine, view->e_flags);
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1831) 
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1832) 	/*
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1833) 	 * Allocate a structure for each thread.
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1834) 	 */
83914441f94c6 (Oleg Nesterov           2008-07-25 01:47:45 -0700 1835) 	for (ct = &dump_task->mm->core_state->dumper; ct; ct = ct->next) {
83914441f94c6 (Oleg Nesterov           2008-07-25 01:47:45 -0700 1836) 		t = kzalloc(offsetof(struct elf_thread_core_info,
83914441f94c6 (Oleg Nesterov           2008-07-25 01:47:45 -0700 1837) 				     notes[info->thread_notes]),
83914441f94c6 (Oleg Nesterov           2008-07-25 01:47:45 -0700 1838) 			    GFP_KERNEL);
83914441f94c6 (Oleg Nesterov           2008-07-25 01:47:45 -0700 1839) 		if (unlikely(!t))
83914441f94c6 (Oleg Nesterov           2008-07-25 01:47:45 -0700 1840) 			return 0;
83914441f94c6 (Oleg Nesterov           2008-07-25 01:47:45 -0700 1841) 
83914441f94c6 (Oleg Nesterov           2008-07-25 01:47:45 -0700 1842) 		t->task = ct->task;
83914441f94c6 (Oleg Nesterov           2008-07-25 01:47:45 -0700 1843) 		if (ct->task == dump_task || !info->thread) {
83914441f94c6 (Oleg Nesterov           2008-07-25 01:47:45 -0700 1844) 			t->next = info->thread;
83914441f94c6 (Oleg Nesterov           2008-07-25 01:47:45 -0700 1845) 			info->thread = t;
83914441f94c6 (Oleg Nesterov           2008-07-25 01:47:45 -0700 1846) 		} else {
83914441f94c6 (Oleg Nesterov           2008-07-25 01:47:45 -0700 1847) 			/*
83914441f94c6 (Oleg Nesterov           2008-07-25 01:47:45 -0700 1848) 			 * Make sure to keep the original task at
83914441f94c6 (Oleg Nesterov           2008-07-25 01:47:45 -0700 1849) 			 * the head of the list.
83914441f94c6 (Oleg Nesterov           2008-07-25 01:47:45 -0700 1850) 			 */
83914441f94c6 (Oleg Nesterov           2008-07-25 01:47:45 -0700 1851) 			t->next = info->thread->next;
83914441f94c6 (Oleg Nesterov           2008-07-25 01:47:45 -0700 1852) 			info->thread->next = t;
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1853) 		}
83914441f94c6 (Oleg Nesterov           2008-07-25 01:47:45 -0700 1854) 	}
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1855) 
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1856) 	/*
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1857) 	 * Now fill in each thread's information.
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1858) 	 */
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1859) 	for (t = info->thread; t != NULL; t = t->next)
5ab1c309b3448 (Denys Vlasenko          2012-10-04 17:15:29 -0700 1860) 		if (!fill_thread_core_info(t, view, siginfo->si_signo, &info->size))
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1861) 			return 0;
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1862) 
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1863) 	/*
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1864) 	 * Fill in the two process-wide notes.
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1865) 	 */
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1866) 	fill_psinfo(psinfo, dump_task->group_leader, dump_task->mm);
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1867) 	info->size += notesize(&info->psinfo);
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1868) 
49ae4d4b113be (Denys Vlasenko          2012-10-04 17:15:35 -0700 1869) 	fill_siginfo_note(&info->signote, &info->csigdata, siginfo);
49ae4d4b113be (Denys Vlasenko          2012-10-04 17:15:35 -0700 1870) 	info->size += notesize(&info->signote);
49ae4d4b113be (Denys Vlasenko          2012-10-04 17:15:35 -0700 1871) 
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1872) 	fill_auxv_note(&info->auxv, current->mm);
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1873) 	info->size += notesize(&info->auxv);
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1874) 
72023656961b8 (Dan Aloni               2013-09-30 13:45:02 -0700 1875) 	if (fill_files_note(&info->files) == 0)
72023656961b8 (Dan Aloni               2013-09-30 13:45:02 -0700 1876) 		info->size += notesize(&info->files);
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1877) 
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1878) 	return 1;
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1879) }
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1880) 
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1881) static size_t get_note_info_size(struct elf_note_info *info)
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1882) {
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1883) 	return info->size;
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1884) }
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1885) 
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1886) /*
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1887)  * Write all the notes for each thread.  When writing the first thread, the
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1888)  * process-wide notes are interleaved after the first thread-specific note.
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1889)  */
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1890) static int write_note_info(struct elf_note_info *info,
ecc8c7725e6c2 (Al Viro                 2013-10-05 15:32:35 -0400 1891) 			   struct coredump_params *cprm)
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1892) {
b219e25f8dd97 (Fabian Frederick        2014-06-04 16:12:14 -0700 1893) 	bool first = true;
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1894) 	struct elf_thread_core_info *t = info->thread;
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1895) 
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1896) 	do {
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1897) 		int i;
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1898) 
ecc8c7725e6c2 (Al Viro                 2013-10-05 15:32:35 -0400 1899) 		if (!writenote(&t->notes[0], cprm))
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1900) 			return 0;
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1901) 
ecc8c7725e6c2 (Al Viro                 2013-10-05 15:32:35 -0400 1902) 		if (first && !writenote(&info->psinfo, cprm))
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1903) 			return 0;
ecc8c7725e6c2 (Al Viro                 2013-10-05 15:32:35 -0400 1904) 		if (first && !writenote(&info->signote, cprm))
49ae4d4b113be (Denys Vlasenko          2012-10-04 17:15:35 -0700 1905) 			return 0;
ecc8c7725e6c2 (Al Viro                 2013-10-05 15:32:35 -0400 1906) 		if (first && !writenote(&info->auxv, cprm))
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1907) 			return 0;
72023656961b8 (Dan Aloni               2013-09-30 13:45:02 -0700 1908) 		if (first && info->files.data &&
ecc8c7725e6c2 (Al Viro                 2013-10-05 15:32:35 -0400 1909) 				!writenote(&info->files, cprm))
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 1910) 			return 0;
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1911) 
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1912) 		for (i = 1; i < info->thread_notes; ++i)
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1913) 			if (t->notes[i].data &&
ecc8c7725e6c2 (Al Viro                 2013-10-05 15:32:35 -0400 1914) 			    !writenote(&t->notes[i], cprm))
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1915) 				return 0;
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1916) 
b219e25f8dd97 (Fabian Frederick        2014-06-04 16:12:14 -0700 1917) 		first = false;
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1918) 		t = t->next;
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1919) 	} while (t);
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1920) 
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1921) 	return 1;
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1922) }
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1923) 
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1924) static void free_note_info(struct elf_note_info *info)
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1925) {
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1926) 	struct elf_thread_core_info *threads = info->thread;
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1927) 	while (threads) {
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1928) 		unsigned int i;
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1929) 		struct elf_thread_core_info *t = threads;
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1930) 		threads = t->next;
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1931) 		WARN_ON(t->notes[0].data && t->notes[0].data != &t->prstatus);
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1932) 		for (i = 1; i < info->thread_notes; ++i)
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1933) 			kfree(t->notes[i].data);
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1934) 		kfree(t);
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1935) 	}
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1936) 	kfree(info->psinfo.data);
86a2bb5ad8316 (Alexey Dobriyan         2018-06-14 15:27:24 -0700 1937) 	kvfree(info->files.data);
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1938) }
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1939) 
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1940) #else
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 1941) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1942) /* Here is the structure in which status of each thread is captured. */
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1943) struct elf_thread_status
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1944) {
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1945) 	struct list_head list;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1946) 	struct elf_prstatus prstatus;	/* NT_PRSTATUS */
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1947) 	elf_fpregset_t fpu;		/* NT_PRFPREG */
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1948) 	struct task_struct *thread;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1949) 	struct memelfnote notes[3];
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1950) 	int num_notes;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1951) };
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1952) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1953) /*
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1954)  * In order to add the specific thread information for the elf file format,
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700 1955)  * we need to keep a linked list of every threads pr_status and then create
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700 1956)  * a single section for them in the final core file.
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1957)  */
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1958) static int elf_dump_thread_status(long signr, struct elf_thread_status *t)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1959) {
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1960) 	int sz = 0;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1961) 	struct task_struct *p = t->thread;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1962) 	t->num_notes = 0;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1963) 
f2485a2dc9f0f (Al Viro                 2020-06-13 00:08:44 -0400 1964) 	fill_prstatus(&t->prstatus.common, p, signr);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1965) 	elf_core_copy_task_regs(p, &t->prstatus.pr_reg);	
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1966) 	
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700 1967) 	fill_note(&t->notes[0], "CORE", NT_PRSTATUS, sizeof(t->prstatus),
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700 1968) 		  &(t->prstatus));
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1969) 	t->num_notes++;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1970) 	sz += notesize(&t->notes[0]);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1971) 
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700 1972) 	if ((t->prstatus.pr_fpvalid = elf_core_copy_task_fpregs(p, NULL,
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700 1973) 								&t->fpu))) {
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700 1974) 		fill_note(&t->notes[1], "CORE", NT_PRFPREG, sizeof(t->fpu),
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700 1975) 			  &(t->fpu));
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1976) 		t->num_notes++;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1977) 		sz += notesize(&t->notes[1]);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1978) 	}
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1979) 	return sz;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1980) }
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 1981) 
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 1982) struct elf_note_info {
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 1983) 	struct memelfnote *notes;
72023656961b8 (Dan Aloni               2013-09-30 13:45:02 -0700 1984) 	struct memelfnote *notes_files;
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 1985) 	struct elf_prstatus *prstatus;	/* NT_PRSTATUS */
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 1986) 	struct elf_prpsinfo *psinfo;	/* NT_PRPSINFO */
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 1987) 	struct list_head thread_list;
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 1988) 	elf_fpregset_t *fpu;
49ae4d4b113be (Denys Vlasenko          2012-10-04 17:15:35 -0700 1989) 	user_siginfo_t csigdata;
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 1990) 	int thread_status_size;
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 1991) 	int numnote;
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 1992) };
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 1993) 
0cf062d0ffa33 (Amerigo Wang            2009-09-23 15:57:05 -0700 1994) static int elf_note_info_init(struct elf_note_info *info)
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 1995) {
0cf062d0ffa33 (Amerigo Wang            2009-09-23 15:57:05 -0700 1996) 	memset(info, 0, sizeof(*info));
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 1997) 	INIT_LIST_HEAD(&info->thread_list);
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 1998) 
49ae4d4b113be (Denys Vlasenko          2012-10-04 17:15:35 -0700 1999) 	/* Allocate space for ELF notes */
6da2ec56059c3 (Kees Cook               2018-06-12 13:55:00 -0700 2000) 	info->notes = kmalloc_array(8, sizeof(struct memelfnote), GFP_KERNEL);
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2001) 	if (!info->notes)
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2002) 		return 0;
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2003) 	info->psinfo = kmalloc(sizeof(*info->psinfo), GFP_KERNEL);
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2004) 	if (!info->psinfo)
f34f9d186df35 (Denys Vlasenko          2012-09-26 11:34:50 +1000 2005) 		return 0;
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2006) 	info->prstatus = kmalloc(sizeof(*info->prstatus), GFP_KERNEL);
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2007) 	if (!info->prstatus)
f34f9d186df35 (Denys Vlasenko          2012-09-26 11:34:50 +1000 2008) 		return 0;
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2009) 	info->fpu = kmalloc(sizeof(*info->fpu), GFP_KERNEL);
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2010) 	if (!info->fpu)
f34f9d186df35 (Denys Vlasenko          2012-09-26 11:34:50 +1000 2011) 		return 0;
0cf062d0ffa33 (Amerigo Wang            2009-09-23 15:57:05 -0700 2012) 	return 1;
0cf062d0ffa33 (Amerigo Wang            2009-09-23 15:57:05 -0700 2013) }
0cf062d0ffa33 (Amerigo Wang            2009-09-23 15:57:05 -0700 2014) 
0cf062d0ffa33 (Amerigo Wang            2009-09-23 15:57:05 -0700 2015) static int fill_note_info(struct elfhdr *elf, int phdrs,
0cf062d0ffa33 (Amerigo Wang            2009-09-23 15:57:05 -0700 2016) 			  struct elf_note_info *info,
ae7795bc6187a (Eric W. Biederman       2018-09-25 11:27:20 +0200 2017) 			  const kernel_siginfo_t *siginfo, struct pt_regs *regs)
0cf062d0ffa33 (Amerigo Wang            2009-09-23 15:57:05 -0700 2018) {
afabada957a6b (Al Viro                 2013-10-14 07:39:56 -0400 2019) 	struct core_thread *ct;
afabada957a6b (Al Viro                 2013-10-14 07:39:56 -0400 2020) 	struct elf_thread_status *ets;
0cf062d0ffa33 (Amerigo Wang            2009-09-23 15:57:05 -0700 2021) 
0cf062d0ffa33 (Amerigo Wang            2009-09-23 15:57:05 -0700 2022) 	if (!elf_note_info_init(info))
0cf062d0ffa33 (Amerigo Wang            2009-09-23 15:57:05 -0700 2023) 		return 0;
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2024) 
afabada957a6b (Al Viro                 2013-10-14 07:39:56 -0400 2025) 	for (ct = current->mm->core_state->dumper.next;
afabada957a6b (Al Viro                 2013-10-14 07:39:56 -0400 2026) 					ct; ct = ct->next) {
afabada957a6b (Al Viro                 2013-10-14 07:39:56 -0400 2027) 		ets = kzalloc(sizeof(*ets), GFP_KERNEL);
afabada957a6b (Al Viro                 2013-10-14 07:39:56 -0400 2028) 		if (!ets)
afabada957a6b (Al Viro                 2013-10-14 07:39:56 -0400 2029) 			return 0;
83914441f94c6 (Oleg Nesterov           2008-07-25 01:47:45 -0700 2030) 
afabada957a6b (Al Viro                 2013-10-14 07:39:56 -0400 2031) 		ets->thread = ct->task;
afabada957a6b (Al Viro                 2013-10-14 07:39:56 -0400 2032) 		list_add(&ets->list, &info->thread_list);
afabada957a6b (Al Viro                 2013-10-14 07:39:56 -0400 2033) 	}
83914441f94c6 (Oleg Nesterov           2008-07-25 01:47:45 -0700 2034) 
93f044e282b6a (Alexey Dobriyan         2019-03-07 16:28:59 -0800 2035) 	list_for_each_entry(ets, &info->thread_list, list) {
afabada957a6b (Al Viro                 2013-10-14 07:39:56 -0400 2036) 		int sz;
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2037) 
afabada957a6b (Al Viro                 2013-10-14 07:39:56 -0400 2038) 		sz = elf_dump_thread_status(siginfo->si_signo, ets);
afabada957a6b (Al Viro                 2013-10-14 07:39:56 -0400 2039) 		info->thread_status_size += sz;
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2040) 	}
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2041) 	/* now collect the dump for the current */
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2042) 	memset(info->prstatus, 0, sizeof(*info->prstatus));
f2485a2dc9f0f (Al Viro                 2020-06-13 00:08:44 -0400 2043) 	fill_prstatus(&info->prstatus->common, current, siginfo->si_signo);
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2044) 	elf_core_copy_regs(&info->prstatus->pr_reg, regs);
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2045) 
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2046) 	/* Set up header */
d3330cf08ccf9 (Zhang Yanfei            2013-02-21 16:44:20 -0800 2047) 	fill_elf_header(elf, phdrs, ELF_ARCH, ELF_CORE_EFLAGS);
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2048) 
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2049) 	/*
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2050) 	 * Set up the notes in similar form to SVR4 core dumps made
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2051) 	 * with info from their /proc.
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2052) 	 */
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2053) 
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2054) 	fill_note(info->notes + 0, "CORE", NT_PRSTATUS,
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2055) 		  sizeof(*info->prstatus), info->prstatus);
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2056) 	fill_psinfo(info->psinfo, current->group_leader, current->mm);
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2057) 	fill_note(info->notes + 1, "CORE", NT_PRPSINFO,
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2058) 		  sizeof(*info->psinfo), info->psinfo);
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2059) 
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 2060) 	fill_siginfo_note(info->notes + 2, &info->csigdata, siginfo);
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 2061) 	fill_auxv_note(info->notes + 3, current->mm);
72023656961b8 (Dan Aloni               2013-09-30 13:45:02 -0700 2062) 	info->numnote = 4;
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2063) 
72023656961b8 (Dan Aloni               2013-09-30 13:45:02 -0700 2064) 	if (fill_files_note(info->notes + info->numnote) == 0) {
72023656961b8 (Dan Aloni               2013-09-30 13:45:02 -0700 2065) 		info->notes_files = info->notes + info->numnote;
72023656961b8 (Dan Aloni               2013-09-30 13:45:02 -0700 2066) 		info->numnote++;
72023656961b8 (Dan Aloni               2013-09-30 13:45:02 -0700 2067) 	}
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2068) 
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2069) 	/* Try to dump the FPU. */
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2070) 	info->prstatus->pr_fpvalid = elf_core_copy_task_fpregs(current, regs,
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2071) 							       info->fpu);
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2072) 	if (info->prstatus->pr_fpvalid)
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2073) 		fill_note(info->notes + info->numnote++,
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2074) 			  "CORE", NT_PRFPREG, sizeof(*info->fpu), info->fpu);
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2075) 	return 1;
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2076) }
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2077) 
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2078) static size_t get_note_info_size(struct elf_note_info *info)
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2079) {
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2080) 	int sz = 0;
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2081) 	int i;
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2082) 
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2083) 	for (i = 0; i < info->numnote; i++)
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2084) 		sz += notesize(info->notes + i);
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2085) 
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2086) 	sz += info->thread_status_size;
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2087) 
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2088) 	return sz;
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2089) }
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2090) 
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2091) static int write_note_info(struct elf_note_info *info,
ecc8c7725e6c2 (Al Viro                 2013-10-05 15:32:35 -0400 2092) 			   struct coredump_params *cprm)
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2093) {
93f044e282b6a (Alexey Dobriyan         2019-03-07 16:28:59 -0800 2094) 	struct elf_thread_status *ets;
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2095) 	int i;
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2096) 
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2097) 	for (i = 0; i < info->numnote; i++)
ecc8c7725e6c2 (Al Viro                 2013-10-05 15:32:35 -0400 2098) 		if (!writenote(info->notes + i, cprm))
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2099) 			return 0;
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2100) 
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2101) 	/* write out the thread status notes section */
93f044e282b6a (Alexey Dobriyan         2019-03-07 16:28:59 -0800 2102) 	list_for_each_entry(ets, &info->thread_list, list) {
93f044e282b6a (Alexey Dobriyan         2019-03-07 16:28:59 -0800 2103) 		for (i = 0; i < ets->num_notes; i++)
93f044e282b6a (Alexey Dobriyan         2019-03-07 16:28:59 -0800 2104) 			if (!writenote(&ets->notes[i], cprm))
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2105) 				return 0;
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2106) 	}
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2107) 
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2108) 	return 1;
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2109) }
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2110) 
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2111) static void free_note_info(struct elf_note_info *info)
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2112) {
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2113) 	while (!list_empty(&info->thread_list)) {
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2114) 		struct list_head *tmp = info->thread_list.next;
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2115) 		list_del(tmp);
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2116) 		kfree(list_entry(tmp, struct elf_thread_status, list));
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2117) 	}
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2118) 
72023656961b8 (Dan Aloni               2013-09-30 13:45:02 -0700 2119) 	/* Free data possibly allocated by fill_files_note(): */
72023656961b8 (Dan Aloni               2013-09-30 13:45:02 -0700 2120) 	if (info->notes_files)
86a2bb5ad8316 (Alexey Dobriyan         2018-06-14 15:27:24 -0700 2121) 		kvfree(info->notes_files->data);
2aa362c49c314 (Denys Vlasenko          2012-10-04 17:15:36 -0700 2122) 
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2123) 	kfree(info->prstatus);
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2124) 	kfree(info->psinfo);
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2125) 	kfree(info->notes);
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2126) 	kfree(info->fpu);
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2127) }
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2128) 
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 2129) #endif
4206d3aa1978e (Roland McGrath          2008-01-30 13:31:45 +0100 2130) 
8d9032bbe4671 (Daisuke HATAYAMA        2010-03-05 13:44:10 -0800 2131) static void fill_extnum_info(struct elfhdr *elf, struct elf_shdr *shdr4extnum,
8d9032bbe4671 (Daisuke HATAYAMA        2010-03-05 13:44:10 -0800 2132) 			     elf_addr_t e_shoff, int segs)
8d9032bbe4671 (Daisuke HATAYAMA        2010-03-05 13:44:10 -0800 2133) {
8d9032bbe4671 (Daisuke HATAYAMA        2010-03-05 13:44:10 -0800 2134) 	elf->e_shoff = e_shoff;
8d9032bbe4671 (Daisuke HATAYAMA        2010-03-05 13:44:10 -0800 2135) 	elf->e_shentsize = sizeof(*shdr4extnum);
8d9032bbe4671 (Daisuke HATAYAMA        2010-03-05 13:44:10 -0800 2136) 	elf->e_shnum = 1;
8d9032bbe4671 (Daisuke HATAYAMA        2010-03-05 13:44:10 -0800 2137) 	elf->e_shstrndx = SHN_UNDEF;
8d9032bbe4671 (Daisuke HATAYAMA        2010-03-05 13:44:10 -0800 2138) 
8d9032bbe4671 (Daisuke HATAYAMA        2010-03-05 13:44:10 -0800 2139) 	memset(shdr4extnum, 0, sizeof(*shdr4extnum));
8d9032bbe4671 (Daisuke HATAYAMA        2010-03-05 13:44:10 -0800 2140) 
8d9032bbe4671 (Daisuke HATAYAMA        2010-03-05 13:44:10 -0800 2141) 	shdr4extnum->sh_type = SHT_NULL;
8d9032bbe4671 (Daisuke HATAYAMA        2010-03-05 13:44:10 -0800 2142) 	shdr4extnum->sh_size = elf->e_shnum;
8d9032bbe4671 (Daisuke HATAYAMA        2010-03-05 13:44:10 -0800 2143) 	shdr4extnum->sh_link = elf->e_shstrndx;
8d9032bbe4671 (Daisuke HATAYAMA        2010-03-05 13:44:10 -0800 2144) 	shdr4extnum->sh_info = segs;
8d9032bbe4671 (Daisuke HATAYAMA        2010-03-05 13:44:10 -0800 2145) }
8d9032bbe4671 (Daisuke HATAYAMA        2010-03-05 13:44:10 -0800 2146) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 2147) /*
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 2148)  * Actual dumper
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 2149)  *
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 2150)  * This is a two-pass process; first we find the offsets of the bits,
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 2151)  * and then they are actually written out.  If we run out of core limit
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 2152)  * we just truncate.
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 2153)  */
f6151dfea2149 (Masami Hiramatsu        2009-12-17 15:27:16 -0800 2154) static int elf_core_dump(struct coredump_params *cprm)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 2155) {
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 2156) 	int has_dumped = 0;
a07279c9a8cd7 (Jann Horn               2020-10-15 20:12:54 -0700 2157) 	int vma_count, segs, i;
a07279c9a8cd7 (Jann Horn               2020-10-15 20:12:54 -0700 2158) 	size_t vma_data_size;
225a3f53e7fc7 (Alexey Dobriyan         2020-01-30 22:17:04 -0800 2159) 	struct elfhdr elf;
cdc3d5627d5f7 (Al Viro                 2013-10-05 22:24:29 -0400 2160) 	loff_t offset = 0, dataoff;
72023656961b8 (Dan Aloni               2013-09-30 13:45:02 -0700 2161) 	struct elf_note_info info = { };
93eb211e6c9ff (Daisuke HATAYAMA        2010-03-05 13:44:09 -0800 2162) 	struct elf_phdr *phdr4note = NULL;
8d9032bbe4671 (Daisuke HATAYAMA        2010-03-05 13:44:10 -0800 2163) 	struct elf_shdr *shdr4extnum = NULL;
8d9032bbe4671 (Daisuke HATAYAMA        2010-03-05 13:44:10 -0800 2164) 	Elf_Half e_phnum;
8d9032bbe4671 (Daisuke HATAYAMA        2010-03-05 13:44:10 -0800 2165) 	elf_addr_t e_shoff;
a07279c9a8cd7 (Jann Horn               2020-10-15 20:12:54 -0700 2166) 	struct core_vma_metadata *vma_meta;
a07279c9a8cd7 (Jann Horn               2020-10-15 20:12:54 -0700 2167) 
a07279c9a8cd7 (Jann Horn               2020-10-15 20:12:54 -0700 2168) 	if (dump_vma_snapshot(cprm, &vma_count, &vma_meta, &vma_data_size))
a07279c9a8cd7 (Jann Horn               2020-10-15 20:12:54 -0700 2169) 		return 0;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 2170) 
341c87bf346f5 (KAMEZAWA Hiroyuki       2009-06-30 11:41:23 -0700 2171) 	/*
341c87bf346f5 (KAMEZAWA Hiroyuki       2009-06-30 11:41:23 -0700 2172) 	 * The number of segs are recored into ELF header as 16bit value.
341c87bf346f5 (KAMEZAWA Hiroyuki       2009-06-30 11:41:23 -0700 2173) 	 * Please check DEFAULT_MAX_MAP_COUNT definition when you modify here.
341c87bf346f5 (KAMEZAWA Hiroyuki       2009-06-30 11:41:23 -0700 2174) 	 */
a07279c9a8cd7 (Jann Horn               2020-10-15 20:12:54 -0700 2175) 	segs = vma_count + elf_core_extra_phdrs();
f47aef55d9a18 (Roland McGrath          2007-01-26 00:56:49 -0800 2176) 
8d9032bbe4671 (Daisuke HATAYAMA        2010-03-05 13:44:10 -0800 2177) 	/* for notes section */
8d9032bbe4671 (Daisuke HATAYAMA        2010-03-05 13:44:10 -0800 2178) 	segs++;
8d9032bbe4671 (Daisuke HATAYAMA        2010-03-05 13:44:10 -0800 2179) 
8d9032bbe4671 (Daisuke HATAYAMA        2010-03-05 13:44:10 -0800 2180) 	/* If segs > PN_XNUM(0xffff), then e_phnum overflows. To avoid
8d9032bbe4671 (Daisuke HATAYAMA        2010-03-05 13:44:10 -0800 2181) 	 * this, kernel supports extended numbering. Have a look at
8d9032bbe4671 (Daisuke HATAYAMA        2010-03-05 13:44:10 -0800 2182) 	 * include/linux/elf.h for further information. */
8d9032bbe4671 (Daisuke HATAYAMA        2010-03-05 13:44:10 -0800 2183) 	e_phnum = segs > PN_XNUM ? PN_XNUM : segs;
8d9032bbe4671 (Daisuke HATAYAMA        2010-03-05 13:44:10 -0800 2184) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 2185) 	/*
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2186) 	 * Collect all the non-memory information about the process for the
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2187) 	 * notes.  This also sets up the file header.
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 2188) 	 */
225a3f53e7fc7 (Alexey Dobriyan         2020-01-30 22:17:04 -0800 2189) 	if (!fill_note_info(&elf, e_phnum, &info, cprm->siginfo, cprm->regs))
d2530b436f114 (Christoph Hellwig       2020-05-05 12:12:55 +0200 2190) 		goto end_coredump;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 2191) 
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2192) 	has_dumped = 1;
079148b919d0c (Oleg Nesterov           2013-04-30 15:28:16 -0700 2193) 
225a3f53e7fc7 (Alexey Dobriyan         2020-01-30 22:17:04 -0800 2194) 	offset += sizeof(elf);				/* Elf header */
8d9032bbe4671 (Daisuke HATAYAMA        2010-03-05 13:44:10 -0800 2195) 	offset += segs * sizeof(struct elf_phdr);	/* Program headers */
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 2196) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 2197) 	/* Write notes phdr entry */
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 2198) 	{
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2199) 		size_t sz = get_note_info_size(&info);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 2200) 
c39ab6de22730 (Eric W. Biederman       2020-11-25 15:51:32 -0600 2201) 		/* For cell spufs */
e55014923e65e (Michael Ellerman        2007-09-19 14:38:12 +1000 2202) 		sz += elf_coredump_extra_notes_size();
bf1ab978be231 (Dwayne Grant McConnell  2006-11-23 00:46:37 +0100 2203) 
93eb211e6c9ff (Daisuke HATAYAMA        2010-03-05 13:44:09 -0800 2204) 		phdr4note = kmalloc(sizeof(*phdr4note), GFP_KERNEL);
93eb211e6c9ff (Daisuke HATAYAMA        2010-03-05 13:44:09 -0800 2205) 		if (!phdr4note)
088e7af73a962 (Daisuke HATAYAMA        2010-03-05 13:44:06 -0800 2206) 			goto end_coredump;
93eb211e6c9ff (Daisuke HATAYAMA        2010-03-05 13:44:09 -0800 2207) 
93eb211e6c9ff (Daisuke HATAYAMA        2010-03-05 13:44:09 -0800 2208) 		fill_elf_note_phdr(phdr4note, sz, offset);
93eb211e6c9ff (Daisuke HATAYAMA        2010-03-05 13:44:09 -0800 2209) 		offset += sz;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 2210) 	}
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 2211) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 2212) 	dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 2213) 
52f5592e549c0 (Jungseung Lee           2014-12-10 15:52:16 -0800 2214) 	offset += vma_data_size;
8d9032bbe4671 (Daisuke HATAYAMA        2010-03-05 13:44:10 -0800 2215) 	offset += elf_core_extra_data_size();
8d9032bbe4671 (Daisuke HATAYAMA        2010-03-05 13:44:10 -0800 2216) 	e_shoff = offset;
8d9032bbe4671 (Daisuke HATAYAMA        2010-03-05 13:44:10 -0800 2217) 
8d9032bbe4671 (Daisuke HATAYAMA        2010-03-05 13:44:10 -0800 2218) 	if (e_phnum == PN_XNUM) {
8d9032bbe4671 (Daisuke HATAYAMA        2010-03-05 13:44:10 -0800 2219) 		shdr4extnum = kmalloc(sizeof(*shdr4extnum), GFP_KERNEL);
8d9032bbe4671 (Daisuke HATAYAMA        2010-03-05 13:44:10 -0800 2220) 		if (!shdr4extnum)
8d9032bbe4671 (Daisuke HATAYAMA        2010-03-05 13:44:10 -0800 2221) 			goto end_coredump;
225a3f53e7fc7 (Alexey Dobriyan         2020-01-30 22:17:04 -0800 2222) 		fill_extnum_info(&elf, shdr4extnum, e_shoff, segs);
8d9032bbe4671 (Daisuke HATAYAMA        2010-03-05 13:44:10 -0800 2223) 	}
8d9032bbe4671 (Daisuke HATAYAMA        2010-03-05 13:44:10 -0800 2224) 
8d9032bbe4671 (Daisuke HATAYAMA        2010-03-05 13:44:10 -0800 2225) 	offset = dataoff;
8d9032bbe4671 (Daisuke HATAYAMA        2010-03-05 13:44:10 -0800 2226) 
225a3f53e7fc7 (Alexey Dobriyan         2020-01-30 22:17:04 -0800 2227) 	if (!dump_emit(cprm, &elf, sizeof(elf)))
93eb211e6c9ff (Daisuke HATAYAMA        2010-03-05 13:44:09 -0800 2228) 		goto end_coredump;
93eb211e6c9ff (Daisuke HATAYAMA        2010-03-05 13:44:09 -0800 2229) 
ecc8c7725e6c2 (Al Viro                 2013-10-05 15:32:35 -0400 2230) 	if (!dump_emit(cprm, phdr4note, sizeof(*phdr4note)))
93eb211e6c9ff (Daisuke HATAYAMA        2010-03-05 13:44:09 -0800 2231) 		goto end_coredump;
93eb211e6c9ff (Daisuke HATAYAMA        2010-03-05 13:44:09 -0800 2232) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 2233) 	/* Write program headers for segments dump */
a07279c9a8cd7 (Jann Horn               2020-10-15 20:12:54 -0700 2234) 	for (i = 0; i < vma_count; i++) {
a07279c9a8cd7 (Jann Horn               2020-10-15 20:12:54 -0700 2235) 		struct core_vma_metadata *meta = vma_meta + i;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 2236) 		struct elf_phdr phdr;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 2237) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 2238) 		phdr.p_type = PT_LOAD;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 2239) 		phdr.p_offset = offset;
a07279c9a8cd7 (Jann Horn               2020-10-15 20:12:54 -0700 2240) 		phdr.p_vaddr = meta->start;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 2241) 		phdr.p_paddr = 0;
a07279c9a8cd7 (Jann Horn               2020-10-15 20:12:54 -0700 2242) 		phdr.p_filesz = meta->dump_size;
a07279c9a8cd7 (Jann Horn               2020-10-15 20:12:54 -0700 2243) 		phdr.p_memsz = meta->end - meta->start;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 2244) 		offset += phdr.p_filesz;
a07279c9a8cd7 (Jann Horn               2020-10-15 20:12:54 -0700 2245) 		phdr.p_flags = 0;
a07279c9a8cd7 (Jann Horn               2020-10-15 20:12:54 -0700 2246) 		if (meta->flags & VM_READ)
a07279c9a8cd7 (Jann Horn               2020-10-15 20:12:54 -0700 2247) 			phdr.p_flags |= PF_R;
a07279c9a8cd7 (Jann Horn               2020-10-15 20:12:54 -0700 2248) 		if (meta->flags & VM_WRITE)
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700 2249) 			phdr.p_flags |= PF_W;
a07279c9a8cd7 (Jann Horn               2020-10-15 20:12:54 -0700 2250) 		if (meta->flags & VM_EXEC)
f4e5cc2c44bf7 (Jesper Juhl             2006-06-23 02:05:35 -0700 2251) 			phdr.p_flags |= PF_X;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 2252) 		phdr.p_align = ELF_EXEC_PAGESIZE;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 2253) 
ecc8c7725e6c2 (Al Viro                 2013-10-05 15:32:35 -0400 2254) 		if (!dump_emit(cprm, &phdr, sizeof(phdr)))
088e7af73a962 (Daisuke HATAYAMA        2010-03-05 13:44:06 -0800 2255) 			goto end_coredump;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 2256) 	}
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 2257) 
506f21c556c74 (Al Viro                 2013-10-05 17:22:57 -0400 2258) 	if (!elf_core_write_extra_phdrs(cprm, offset))
1fcccbac89f5b (Daisuke HATAYAMA        2010-03-05 13:44:07 -0800 2259) 		goto end_coredump;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 2260) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 2261)  	/* write out the notes section */
ecc8c7725e6c2 (Al Viro                 2013-10-05 15:32:35 -0400 2262) 	if (!write_note_info(&info, cprm))
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2263) 		goto end_coredump;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 2264) 
c39ab6de22730 (Eric W. Biederman       2020-11-25 15:51:32 -0600 2265) 	/* For cell spufs */
cdc3d5627d5f7 (Al Viro                 2013-10-05 22:24:29 -0400 2266) 	if (elf_coredump_extra_notes_write(cprm))
e55014923e65e (Michael Ellerman        2007-09-19 14:38:12 +1000 2267) 		goto end_coredump;
bf1ab978be231 (Dwayne Grant McConnell  2006-11-23 00:46:37 +0100 2268) 
d025c9db7f31f (Andi Kleen              2006-09-30 23:29:28 -0700 2269) 	/* Align to page */
d0f1088b31db2 (Al Viro                 2020-03-08 09:16:37 -0400 2270) 	dump_skip_to(cprm, dataoff);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 2271) 
a07279c9a8cd7 (Jann Horn               2020-10-15 20:12:54 -0700 2272) 	for (i = 0; i < vma_count; i++) {
a07279c9a8cd7 (Jann Horn               2020-10-15 20:12:54 -0700 2273) 		struct core_vma_metadata *meta = vma_meta + i;
a07279c9a8cd7 (Jann Horn               2020-10-15 20:12:54 -0700 2274) 
a07279c9a8cd7 (Jann Horn               2020-10-15 20:12:54 -0700 2275) 		if (!dump_user_range(cprm, meta->start, meta->dump_size))
afc63a97b764b (Jann Horn               2020-10-15 20:12:46 -0700 2276) 			goto end_coredump;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 2277) 	}
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 2278) 
aa3e7eaf0a0f0 (Al Viro                 2013-10-05 17:50:15 -0400 2279) 	if (!elf_core_write_extra_data(cprm))
1fcccbac89f5b (Daisuke HATAYAMA        2010-03-05 13:44:07 -0800 2280) 		goto end_coredump;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 2281) 
8d9032bbe4671 (Daisuke HATAYAMA        2010-03-05 13:44:10 -0800 2282) 	if (e_phnum == PN_XNUM) {
13046ece9625f (Al Viro                 2013-10-05 18:08:47 -0400 2283) 		if (!dump_emit(cprm, shdr4extnum, sizeof(*shdr4extnum)))
8d9032bbe4671 (Daisuke HATAYAMA        2010-03-05 13:44:10 -0800 2284) 			goto end_coredump;
8d9032bbe4671 (Daisuke HATAYAMA        2010-03-05 13:44:10 -0800 2285) 	}
8d9032bbe4671 (Daisuke HATAYAMA        2010-03-05 13:44:10 -0800 2286) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 2287) end_coredump:
3aba481fc94d8 (Roland McGrath          2008-01-30 13:31:44 +0100 2288) 	free_note_info(&info);
8d9032bbe4671 (Daisuke HATAYAMA        2010-03-05 13:44:10 -0800 2289) 	kfree(shdr4extnum);
a07279c9a8cd7 (Jann Horn               2020-10-15 20:12:54 -0700 2290) 	kvfree(vma_meta);
93eb211e6c9ff (Daisuke HATAYAMA        2010-03-05 13:44:09 -0800 2291) 	kfree(phdr4note);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 2292) 	return has_dumped;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 2293) }
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 2294) 
698ba7b5a3a7b (Christoph Hellwig       2009-12-15 16:47:37 -0800 2295) #endif		/* CONFIG_ELF_CORE */
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 2296) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 2297) static int __init init_elf_binfmt(void)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 2298) {
8fc3dc5a3a17a (Al Viro                 2012-03-17 03:05:16 -0400 2299) 	register_binfmt(&elf_format);
8fc3dc5a3a17a (Al Viro                 2012-03-17 03:05:16 -0400 2300) 	return 0;
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 2301) }
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 2302) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 2303) static void __exit exit_elf_binfmt(void)
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 2304) {
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 2305) 	/* Remove the COFF and ELF loaders. */
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 2306) 	unregister_binfmt(&elf_format);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 2307) }
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 2308) 
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 2309) core_initcall(init_elf_binfmt);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 2310) module_exit(exit_elf_binfmt);
^1da177e4c3f4 (Linus Torvalds          2005-04-16 15:20:36 -0700 2311) MODULE_LICENSE("GPL");