[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>
This commit is contained in:
parent
01ebb77b31
commit
ec0063b40a
1 changed files with 31 additions and 26 deletions
|
@ -73,39 +73,44 @@ typedef elf_greg_t elf_gregset_t[ELF_NGREG];
|
|||
* Dumping its extra ELF program headers includes all the other information
|
||||
* a debugger needs to easily find how the vsyscall DSO was being used.
|
||||
*/
|
||||
#define ELF_CORE_EXTRA_PHDRS (VSYSCALL32_EHDR->e_phnum)
|
||||
#define ELF_CORE_EXTRA_PHDRS (find_vma(current->mm, VSYSCALL32_BASE) ? \
|
||||
(VSYSCALL32_EHDR->e_phnum) : 0)
|
||||
#define ELF_CORE_WRITE_EXTRA_PHDRS \
|
||||
do { \
|
||||
const struct elf32_phdr *const vsyscall_phdrs = \
|
||||
(const struct elf32_phdr *) (VSYSCALL32_BASE \
|
||||
+ VSYSCALL32_EHDR->e_phoff); \
|
||||
int i; \
|
||||
Elf32_Off ofs = 0; \
|
||||
for (i = 0; i < VSYSCALL32_EHDR->e_phnum; ++i) { \
|
||||
struct elf32_phdr phdr = vsyscall_phdrs[i]; \
|
||||
if (phdr.p_type == PT_LOAD) { \
|
||||
BUG_ON(ofs != 0); \
|
||||
ofs = phdr.p_offset = offset; \
|
||||
phdr.p_memsz = PAGE_ALIGN(phdr.p_memsz); \
|
||||
phdr.p_filesz = phdr.p_memsz; \
|
||||
offset += phdr.p_filesz; \
|
||||
if (find_vma(current->mm, VSYSCALL32_BASE)) { \
|
||||
const struct elf32_phdr *const vsyscall_phdrs = \
|
||||
(const struct elf32_phdr *) (VSYSCALL32_BASE \
|
||||
+ VSYSCALL32_EHDR->e_phoff);\
|
||||
int i; \
|
||||
Elf32_Off ofs = 0; \
|
||||
for (i = 0; i < VSYSCALL32_EHDR->e_phnum; ++i) { \
|
||||
struct elf32_phdr phdr = vsyscall_phdrs[i]; \
|
||||
if (phdr.p_type == PT_LOAD) { \
|
||||
BUG_ON(ofs != 0); \
|
||||
ofs = phdr.p_offset = offset; \
|
||||
phdr.p_memsz = PAGE_ALIGN(phdr.p_memsz); \
|
||||
phdr.p_filesz = phdr.p_memsz; \
|
||||
offset += phdr.p_filesz; \
|
||||
} \
|
||||
else \
|
||||
phdr.p_offset += ofs; \
|
||||
phdr.p_paddr = 0; /* match other core phdrs */ \
|
||||
DUMP_WRITE(&phdr, sizeof(phdr)); \
|
||||
} \
|
||||
else \
|
||||
phdr.p_offset += ofs; \
|
||||
phdr.p_paddr = 0; /* match other core phdrs */ \
|
||||
DUMP_WRITE(&phdr, sizeof(phdr)); \
|
||||
} \
|
||||
} while (0)
|
||||
#define ELF_CORE_WRITE_EXTRA_DATA \
|
||||
do { \
|
||||
const struct elf32_phdr *const vsyscall_phdrs = \
|
||||
(const struct elf32_phdr *) (VSYSCALL32_BASE \
|
||||
+ VSYSCALL32_EHDR->e_phoff); \
|
||||
int i; \
|
||||
for (i = 0; i < VSYSCALL32_EHDR->e_phnum; ++i) { \
|
||||
if (vsyscall_phdrs[i].p_type == PT_LOAD) \
|
||||
DUMP_WRITE((void *) (u64) vsyscall_phdrs[i].p_vaddr, \
|
||||
PAGE_ALIGN(vsyscall_phdrs[i].p_memsz)); \
|
||||
if (find_vma(current->mm, VSYSCALL32_BASE)) { \
|
||||
const struct elf32_phdr *const vsyscall_phdrs = \
|
||||
(const struct elf32_phdr *) (VSYSCALL32_BASE \
|
||||
+ VSYSCALL32_EHDR->e_phoff); \
|
||||
int i; \
|
||||
for (i = 0; i < VSYSCALL32_EHDR->e_phnum; ++i) { \
|
||||
if (vsyscall_phdrs[i].p_type == PT_LOAD) \
|
||||
DUMP_WRITE((void *) (u64) vsyscall_phdrs[i].p_vaddr,\
|
||||
PAGE_ALIGN(vsyscall_phdrs[i].p_memsz)); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
|
Loading…
Reference in a new issue