Skip to content

Commit 49ae4d4

Browse files
Denys Vlasenkotorvalds
Denys Vlasenko
authored andcommitted
coredump: add a new elf note with siginfo of the signal
Existing PRSTATUS note contains only si_signo, si_code, si_errno fields from the siginfo of the signal which caused core to be dumped. There are tools which try to analyze crashes for possible security implications, and they want to use, among other data, si_addr field from the SIGSEGV. This patch adds a new elf note, NT_SIGINFO, which contains the complete siginfo_t of the signal which killed the process. Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com> Reviewed-by: Oleg Nesterov <oleg@redhat.com> Cc: Amerigo Wang <amwang@redhat.com> Cc: "Jonathan M. Foote" <jmfoote@cert.org> Cc: Roland McGrath <roland@hack.frob.com> Cc: Pedro Alves <palves@redhat.com> Cc: Fengguang Wu <fengguang.wu@intel.com> Cc: Stephen Rothwell <sfr@canb.auug.org.au> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
1 parent 751f409 commit 49ae4d4

File tree

3 files changed

+36
-2
lines changed

3 files changed

+36
-2
lines changed

fs/binfmt_elf.c

+25-2
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@
3737
#include <asm/page.h>
3838
#include <asm/exec.h>
3939

40+
#ifndef user_siginfo_t
41+
#define user_siginfo_t siginfo_t
42+
#endif
43+
4044
static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs);
4145
static int load_elf_library(struct file *);
4246
static unsigned long elf_map(struct file *, unsigned long, struct elf_phdr *,
@@ -1372,6 +1376,16 @@ static void fill_auxv_note(struct memelfnote *note, struct mm_struct *mm)
13721376
fill_note(note, "CORE", NT_AUXV, i * sizeof(elf_addr_t), auxv);
13731377
}
13741378

1379+
static void fill_siginfo_note(struct memelfnote *note, user_siginfo_t *csigdata,
1380+
siginfo_t *siginfo)
1381+
{
1382+
mm_segment_t old_fs = get_fs();
1383+
set_fs(KERNEL_DS);
1384+
copy_siginfo_to_user((user_siginfo_t __user *) csigdata, siginfo);
1385+
set_fs(old_fs);
1386+
fill_note(note, "CORE", NT_SIGINFO, sizeof(*csigdata), csigdata);
1387+
}
1388+
13751389
#ifdef CORE_DUMP_USE_REGSET
13761390
#include <linux/regset.h>
13771391

@@ -1385,7 +1399,9 @@ struct elf_thread_core_info {
13851399
struct elf_note_info {
13861400
struct elf_thread_core_info *thread;
13871401
struct memelfnote psinfo;
1402+
struct memelfnote signote;
13881403
struct memelfnote auxv;
1404+
user_siginfo_t csigdata;
13891405
size_t size;
13901406
int thread_notes;
13911407
};
@@ -1559,6 +1575,9 @@ static int fill_note_info(struct elfhdr *elf, int phdrs,
15591575
fill_psinfo(psinfo, dump_task->group_leader, dump_task->mm);
15601576
info->size += notesize(&info->psinfo);
15611577

1578+
fill_siginfo_note(&info->signote, &info->csigdata, siginfo);
1579+
info->size += notesize(&info->signote);
1580+
15621581
fill_auxv_note(&info->auxv, current->mm);
15631582
info->size += notesize(&info->auxv);
15641583

@@ -1588,6 +1607,8 @@ static int write_note_info(struct elf_note_info *info,
15881607

15891608
if (first && !writenote(&info->psinfo, file, foffset))
15901609
return 0;
1610+
if (first && !writenote(&info->signote, file, foffset))
1611+
return 0;
15911612
if (first && !writenote(&info->auxv, file, foffset))
15921613
return 0;
15931614

@@ -1681,6 +1702,7 @@ struct elf_note_info {
16811702
#ifdef ELF_CORE_COPY_XFPREGS
16821703
elf_fpxregset_t *xfpu;
16831704
#endif
1705+
user_siginfo_t csigdata;
16841706
int thread_status_size;
16851707
int numnote;
16861708
};
@@ -1690,8 +1712,8 @@ static int elf_note_info_init(struct elf_note_info *info)
16901712
memset(info, 0, sizeof(*info));
16911713
INIT_LIST_HEAD(&info->thread_list);
16921714

1693-
/* Allocate space for six ELF notes */
1694-
info->notes = kmalloc(6 * sizeof(struct memelfnote), GFP_KERNEL);
1715+
/* Allocate space for ELF notes */
1716+
info->notes = kmalloc(7 * sizeof(struct memelfnote), GFP_KERNEL);
16951717
if (!info->notes)
16961718
return 0;
16971719
info->psinfo = kmalloc(sizeof(*info->psinfo), GFP_KERNEL);
@@ -1763,6 +1785,7 @@ static int fill_note_info(struct elfhdr *elf, int phdrs,
17631785

17641786
info->numnote = 2;
17651787

1788+
fill_siginfo_note(&info->notes[info->numnote++], &info->csigdata, siginfo);
17661789
fill_auxv_note(&info->notes[info->numnote++], current->mm);
17671790

17681791
/* Try to dump the FPU. */

fs/compat_binfmt_elf.c

+6
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,12 @@
3737
#define elf_note elf32_note
3838
#define elf_addr_t Elf32_Addr
3939

40+
/*
41+
* Some data types as stored in coredump.
42+
*/
43+
#define user_siginfo_t compat_siginfo_t
44+
#define copy_siginfo_to_user copy_siginfo_to_user32
45+
4046
/*
4147
* The machine-dependent core note format types are defined in elfcore-compat.h,
4248
* which requires asm/elf.h to define compat_elf_gregset_t et al.

include/linux/elf.h

+5
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,11 @@ typedef struct elf64_shdr {
372372
#define NT_PRPSINFO 3
373373
#define NT_TASKSTRUCT 4
374374
#define NT_AUXV 6
375+
/*
376+
* Note to userspace developers: size of NT_SIGINFO note may increase
377+
* in the future to accomodate more fields, don't assume it is fixed!
378+
*/
379+
#define NT_SIGINFO 0x53494749
375380
#define NT_PRXFPREG 0x46e62b7f /* copied from gdb5.1/include/elf/common.h */
376381
#define NT_PPC_VMX 0x100 /* PowerPC Altivec/VMX registers */
377382
#define NT_PPC_SPE 0x101 /* PowerPC SPE/EVR registers */

0 commit comments

Comments
 (0)