Commit ec0063b40a2291e095faf07fbeb94be92e525c54

Authored by Suleiman Souhlal
Committed by Linus Torvalds
1 parent 01ebb77b31

[PATCH] x86_64: Don't write out segments from vsyscall32 DSO if it is not mapped

It's possible to get an invalid page fault in kernel mode when we try to
write out segments from vsyscall32 when dumping core for a 32bit process if
the vsyscall32 DSO is not mapped in its address space (which can happen if,
for example, ulimit -v 100 is run).

Signed-off-by: Suleiman Souhlal <suleiman@google.com>
Signed-off-by: Andi Kleen <ak@suse.de>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

Showing 1 changed file with 31 additions and 26 deletions Side-by-side Diff

arch/x86_64/ia32/ia32_binfmt.c
... ... @@ -73,39 +73,44 @@
73 73 * Dumping its extra ELF program headers includes all the other information
74 74 * a debugger needs to easily find how the vsyscall DSO was being used.
75 75 */
76   -#define ELF_CORE_EXTRA_PHDRS (VSYSCALL32_EHDR->e_phnum)
  76 +#define ELF_CORE_EXTRA_PHDRS (find_vma(current->mm, VSYSCALL32_BASE) ? \
  77 + (VSYSCALL32_EHDR->e_phnum) : 0)
77 78 #define ELF_CORE_WRITE_EXTRA_PHDRS \
78 79 do { \
79   - const struct elf32_phdr *const vsyscall_phdrs = \
80   - (const struct elf32_phdr *) (VSYSCALL32_BASE \
81   - + VSYSCALL32_EHDR->e_phoff); \
82   - int i; \
83   - Elf32_Off ofs = 0; \
84   - for (i = 0; i < VSYSCALL32_EHDR->e_phnum; ++i) { \
85   - struct elf32_phdr phdr = vsyscall_phdrs[i]; \
86   - if (phdr.p_type == PT_LOAD) { \
87   - BUG_ON(ofs != 0); \
88   - ofs = phdr.p_offset = offset; \
89   - phdr.p_memsz = PAGE_ALIGN(phdr.p_memsz); \
90   - phdr.p_filesz = phdr.p_memsz; \
91   - offset += phdr.p_filesz; \
  80 + if (find_vma(current->mm, VSYSCALL32_BASE)) { \
  81 + const struct elf32_phdr *const vsyscall_phdrs = \
  82 + (const struct elf32_phdr *) (VSYSCALL32_BASE \
  83 + + VSYSCALL32_EHDR->e_phoff);\
  84 + int i; \
  85 + Elf32_Off ofs = 0; \
  86 + for (i = 0; i < VSYSCALL32_EHDR->e_phnum; ++i) { \
  87 + struct elf32_phdr phdr = vsyscall_phdrs[i]; \
  88 + if (phdr.p_type == PT_LOAD) { \
  89 + BUG_ON(ofs != 0); \
  90 + ofs = phdr.p_offset = offset; \
  91 + phdr.p_memsz = PAGE_ALIGN(phdr.p_memsz); \
  92 + phdr.p_filesz = phdr.p_memsz; \
  93 + offset += phdr.p_filesz; \
  94 + } \
  95 + else \
  96 + phdr.p_offset += ofs; \
  97 + phdr.p_paddr = 0; /* match other core phdrs */ \
  98 + DUMP_WRITE(&phdr, sizeof(phdr)); \
92 99 } \
93   - else \
94   - phdr.p_offset += ofs; \
95   - phdr.p_paddr = 0; /* match other core phdrs */ \
96   - DUMP_WRITE(&phdr, sizeof(phdr)); \
97 100 } \
98 101 } while (0)
99 102 #define ELF_CORE_WRITE_EXTRA_DATA \
100 103 do { \
101   - const struct elf32_phdr *const vsyscall_phdrs = \
102   - (const struct elf32_phdr *) (VSYSCALL32_BASE \
103   - + VSYSCALL32_EHDR->e_phoff); \
104   - int i; \
105   - for (i = 0; i < VSYSCALL32_EHDR->e_phnum; ++i) { \
106   - if (vsyscall_phdrs[i].p_type == PT_LOAD) \
107   - DUMP_WRITE((void *) (u64) vsyscall_phdrs[i].p_vaddr, \
108   - PAGE_ALIGN(vsyscall_phdrs[i].p_memsz)); \
  104 + if (find_vma(current->mm, VSYSCALL32_BASE)) { \
  105 + const struct elf32_phdr *const vsyscall_phdrs = \
  106 + (const struct elf32_phdr *) (VSYSCALL32_BASE \
  107 + + VSYSCALL32_EHDR->e_phoff); \
  108 + int i; \
  109 + for (i = 0; i < VSYSCALL32_EHDR->e_phnum; ++i) { \
  110 + if (vsyscall_phdrs[i].p_type == PT_LOAD) \
  111 + DUMP_WRITE((void *) (u64) vsyscall_phdrs[i].p_vaddr,\
  112 + PAGE_ALIGN(vsyscall_phdrs[i].p_memsz)); \
  113 + } \
109 114 } \
110 115 } while (0)
111 116