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, ¬e, 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");