Commit 667495de authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'execve-v6.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux

Pull execve updates from Kees Cook:

 - binfmt_elf: Dump smaller VMAs first in ELF cores (Brian Mak)

 - binfmt_elf: mseal address zero (Jeff Xu)

 - binfmt_elf, coredump: Log the reason of the failed core dumps (Roman
   Kisel)

* tag 'execve-v6.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux:
  binfmt_elf: mseal address zero
  binfmt_elf: Dump smaller VMAs first in ELF cores
  binfmt_elf, coredump: Log the reason of the failed core dumps
  coredump: Standartize and fix logging
parents 7c9026b2 44f65d90
...@@ -1314,6 +1314,11 @@ static int load_elf_binary(struct linux_binprm *bprm) ...@@ -1314,6 +1314,11 @@ static int load_elf_binary(struct linux_binprm *bprm)
emulate the SVr4 behavior. Sigh. */ emulate the SVr4 behavior. Sigh. */
error = vm_mmap(NULL, 0, PAGE_SIZE, PROT_READ | PROT_EXEC, error = vm_mmap(NULL, 0, PAGE_SIZE, PROT_READ | PROT_EXEC,
MAP_FIXED | MAP_PRIVATE, 0); MAP_FIXED | MAP_PRIVATE, 0);
retval = do_mseal(0, PAGE_SIZE, 0);
if (retval)
pr_warn_ratelimited("pid=%d, couldn't seal address 0, ret=%d.\n",
task_pid_nr(current), retval);
} }
regs = current_pt_regs(); regs = current_pt_regs();
...@@ -2027,8 +2032,10 @@ static int elf_core_dump(struct coredump_params *cprm) ...@@ -2027,8 +2032,10 @@ static int elf_core_dump(struct coredump_params *cprm)
* Collect all the non-memory information about the process for the * Collect all the non-memory information about the process for the
* notes. This also sets up the file header. * notes. This also sets up the file header.
*/ */
if (!fill_note_info(&elf, e_phnum, &info, cprm)) if (!fill_note_info(&elf, e_phnum, &info, cprm)) {
coredump_report_failure("Error collecting note info");
goto end_coredump; goto end_coredump;
}
has_dumped = 1; has_dumped = 1;
...@@ -2043,8 +2050,10 @@ static int elf_core_dump(struct coredump_params *cprm) ...@@ -2043,8 +2050,10 @@ static int elf_core_dump(struct coredump_params *cprm)
sz += elf_coredump_extra_notes_size(); sz += elf_coredump_extra_notes_size();
phdr4note = kmalloc(sizeof(*phdr4note), GFP_KERNEL); phdr4note = kmalloc(sizeof(*phdr4note), GFP_KERNEL);
if (!phdr4note) if (!phdr4note) {
coredump_report_failure("Error allocating program headers note entry");
goto end_coredump; goto end_coredump;
}
fill_elf_note_phdr(phdr4note, sz, offset); fill_elf_note_phdr(phdr4note, sz, offset);
offset += sz; offset += sz;
...@@ -2058,18 +2067,24 @@ static int elf_core_dump(struct coredump_params *cprm) ...@@ -2058,18 +2067,24 @@ static int elf_core_dump(struct coredump_params *cprm)
if (e_phnum == PN_XNUM) { if (e_phnum == PN_XNUM) {
shdr4extnum = kmalloc(sizeof(*shdr4extnum), GFP_KERNEL); shdr4extnum = kmalloc(sizeof(*shdr4extnum), GFP_KERNEL);
if (!shdr4extnum) if (!shdr4extnum) {
coredump_report_failure("Error allocating extra program headers");
goto end_coredump; goto end_coredump;
}
fill_extnum_info(&elf, shdr4extnum, e_shoff, segs); fill_extnum_info(&elf, shdr4extnum, e_shoff, segs);
} }
offset = dataoff; offset = dataoff;
if (!dump_emit(cprm, &elf, sizeof(elf))) if (!dump_emit(cprm, &elf, sizeof(elf))) {
coredump_report_failure("Error emitting the ELF headers");
goto end_coredump; goto end_coredump;
}
if (!dump_emit(cprm, phdr4note, sizeof(*phdr4note))) if (!dump_emit(cprm, phdr4note, sizeof(*phdr4note))) {
coredump_report_failure("Error emitting the program header for notes");
goto end_coredump; goto end_coredump;
}
/* Write program headers for segments dump */ /* Write program headers for segments dump */
for (i = 0; i < cprm->vma_count; i++) { for (i = 0; i < cprm->vma_count; i++) {
...@@ -2092,20 +2107,28 @@ static int elf_core_dump(struct coredump_params *cprm) ...@@ -2092,20 +2107,28 @@ static int elf_core_dump(struct coredump_params *cprm)
phdr.p_flags |= PF_X; phdr.p_flags |= PF_X;
phdr.p_align = ELF_EXEC_PAGESIZE; phdr.p_align = ELF_EXEC_PAGESIZE;
if (!dump_emit(cprm, &phdr, sizeof(phdr))) if (!dump_emit(cprm, &phdr, sizeof(phdr))) {
coredump_report_failure("Error emitting program headers");
goto end_coredump; goto end_coredump;
} }
}
if (!elf_core_write_extra_phdrs(cprm, offset)) if (!elf_core_write_extra_phdrs(cprm, offset)) {
coredump_report_failure("Error writing out extra program headers");
goto end_coredump; goto end_coredump;
}
/* write out the notes section */ /* write out the notes section */
if (!write_note_info(&info, cprm)) if (!write_note_info(&info, cprm)) {
coredump_report_failure("Error writing out notes");
goto end_coredump; goto end_coredump;
}
/* For cell spufs and x86 xstate */ /* For cell spufs and x86 xstate */
if (elf_coredump_extra_notes_write(cprm)) if (elf_coredump_extra_notes_write(cprm)) {
coredump_report_failure("Error writing out extra notes");
goto end_coredump; goto end_coredump;
}
/* Align to page */ /* Align to page */
dump_skip_to(cprm, dataoff); dump_skip_to(cprm, dataoff);
...@@ -2113,17 +2136,23 @@ static int elf_core_dump(struct coredump_params *cprm) ...@@ -2113,17 +2136,23 @@ static int elf_core_dump(struct coredump_params *cprm)
for (i = 0; i < cprm->vma_count; i++) { for (i = 0; i < cprm->vma_count; i++) {
struct core_vma_metadata *meta = cprm->vma_meta + i; struct core_vma_metadata *meta = cprm->vma_meta + i;
if (!dump_user_range(cprm, meta->start, meta->dump_size)) if (!dump_user_range(cprm, meta->start, meta->dump_size)) {
coredump_report_failure("Error writing out the process memory");
goto end_coredump; goto end_coredump;
} }
}
if (!elf_core_write_extra_data(cprm)) if (!elf_core_write_extra_data(cprm)) {
coredump_report_failure("Error writing out extra data");
goto end_coredump; goto end_coredump;
}
if (e_phnum == PN_XNUM) { if (e_phnum == PN_XNUM) {
if (!dump_emit(cprm, shdr4extnum, sizeof(*shdr4extnum))) if (!dump_emit(cprm, shdr4extnum, sizeof(*shdr4extnum))) {
coredump_report_failure("Error emitting extra program headers");
goto end_coredump; goto end_coredump;
} }
}
end_coredump: end_coredump:
free_note_info(&info); free_note_info(&info);
......
This diff is collapsed.
...@@ -42,9 +42,35 @@ extern int dump_emit(struct coredump_params *cprm, const void *addr, int nr); ...@@ -42,9 +42,35 @@ extern int dump_emit(struct coredump_params *cprm, const void *addr, int nr);
extern int dump_align(struct coredump_params *cprm, int align); extern int dump_align(struct coredump_params *cprm, int align);
int dump_user_range(struct coredump_params *cprm, unsigned long start, int dump_user_range(struct coredump_params *cprm, unsigned long start,
unsigned long len); unsigned long len);
extern void do_coredump(const kernel_siginfo_t *siginfo); extern int do_coredump(const kernel_siginfo_t *siginfo);
/*
* Logging for the coredump code, ratelimited.
* The TGID and comm fields are added to the message.
*/
#define __COREDUMP_PRINTK(Level, Format, ...) \
do { \
char comm[TASK_COMM_LEN]; \
\
get_task_comm(comm, current); \
printk_ratelimited(Level "coredump: %d(%*pE): " Format "\n", \
task_tgid_vnr(current), (int)strlen(comm), comm, ##__VA_ARGS__); \
} while (0) \
#define coredump_report(fmt, ...) __COREDUMP_PRINTK(KERN_INFO, fmt, ##__VA_ARGS__)
#define coredump_report_failure(fmt, ...) __COREDUMP_PRINTK(KERN_WARNING, fmt, ##__VA_ARGS__)
#else #else
static inline void do_coredump(const kernel_siginfo_t *siginfo) {} static inline int do_coredump(const kernel_siginfo_t *siginfo)
{
/* Coredump support is not available, can't fail. */
return 0;
}
#define coredump_report(...)
#define coredump_report_failure(...)
#endif #endif
#if defined(CONFIG_COREDUMP) && defined(CONFIG_SYSCTL) #if defined(CONFIG_COREDUMP) && defined(CONFIG_SYSCTL)
......
...@@ -4221,4 +4221,14 @@ void vma_pgtable_walk_end(struct vm_area_struct *vma); ...@@ -4221,4 +4221,14 @@ void vma_pgtable_walk_end(struct vm_area_struct *vma);
int reserve_mem_find_by_name(const char *name, phys_addr_t *start, phys_addr_t *size); int reserve_mem_find_by_name(const char *name, phys_addr_t *start, phys_addr_t *size);
#ifdef CONFIG_64BIT
int do_mseal(unsigned long start, size_t len_in, unsigned long flags);
#else
static inline int do_mseal(unsigned long start, size_t len_in, unsigned long flags)
{
/* noop on 32 bit */
return 0;
}
#endif
#endif /* _LINUX_MM_H */ #endif /* _LINUX_MM_H */
...@@ -2888,6 +2888,8 @@ bool get_signal(struct ksignal *ksig) ...@@ -2888,6 +2888,8 @@ bool get_signal(struct ksignal *ksig)
current->flags |= PF_SIGNALED; current->flags |= PF_SIGNALED;
if (sig_kernel_coredump(signr)) { if (sig_kernel_coredump(signr)) {
int ret;
if (print_fatal_signals) if (print_fatal_signals)
print_fatal_signal(signr); print_fatal_signal(signr);
proc_coredump_connector(current); proc_coredump_connector(current);
...@@ -2899,7 +2901,24 @@ bool get_signal(struct ksignal *ksig) ...@@ -2899,7 +2901,24 @@ bool get_signal(struct ksignal *ksig)
* first and our do_group_exit call below will use * first and our do_group_exit call below will use
* that value and ignore the one we pass it. * that value and ignore the one we pass it.
*/ */
do_coredump(&ksig->info); ret = do_coredump(&ksig->info);
if (ret)
coredump_report_failure("coredump has not been created, error %d",
ret);
else if (!IS_ENABLED(CONFIG_COREDUMP)) {
/*
* Coredumps are not available, can't fail collecting
* the coredump.
*
* Leave a note though that the coredump is going to be
* not created. This is not an error or a warning as disabling
* support in the kernel for coredumps isn't commonplace, and
* the user must've built the kernel with the custom config so
* let them know all works as desired.
*/
coredump_report("no coredump collected as "
"that is disabled in the kernel configuration");
}
} }
/* /*
......
...@@ -256,7 +256,7 @@ static int apply_mm_seal(unsigned long start, unsigned long end) ...@@ -256,7 +256,7 @@ static int apply_mm_seal(unsigned long start, unsigned long end)
* *
* unseal() is not supported. * unseal() is not supported.
*/ */
static int do_mseal(unsigned long start, size_t len_in, unsigned long flags) int do_mseal(unsigned long start, size_t len_in, unsigned long flags)
{ {
size_t len; size_t len;
int ret = 0; int ret = 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment