From 5f74972ce69fdc6473f74253283408af75a3be15 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Mon, 22 Jan 2018 14:58:57 -0600 Subject: signal: Don't use structure initializers for struct siginfo The siginfo structure has all manners of holes with the result that a structure initializer is not guaranteed to initialize all of the bits. As we have to copy the structure to userspace don't even try to use a structure initializer. Instead use clear_siginfo followed by initializing selected fields. This gives a guarantee that uninitialized kernel memory is not copied to userspace. Signed-off-by: "Eric W. Biederman" --- arch/tile/kernel/single_step.c | 24 +++++++++++++--------- arch/tile/kernel/traps.c | 4 +++- arch/tile/kernel/unaligned.c | 46 ++++++++++++++++++++++++------------------ 3 files changed, 43 insertions(+), 31 deletions(-) (limited to 'arch/tile') diff --git a/arch/tile/kernel/single_step.c b/arch/tile/kernel/single_step.c index de3eae813e52..479d8033a801 100644 --- a/arch/tile/kernel/single_step.c +++ b/arch/tile/kernel/single_step.c @@ -163,11 +163,13 @@ static tilepro_bundle_bits rewrite_load_store_unaligned( * actual bad address in an SPR, which it doesn't. */ if (align_ctl == 0) { - siginfo_t info = { - .si_signo = SIGBUS, - .si_code = BUS_ADRALN, - .si_addr = addr - }; + siginfo_t info; + + clear_siginfo(&info); + info.si_signo = SIGBUS; + info.si_code = BUS_ADRALN; + info.si_addr = addr; + trace_unhandled_signal("unaligned trap", regs, (unsigned long)addr, SIGBUS); force_sig_info(info.si_signo, &info, current); @@ -210,11 +212,13 @@ static tilepro_bundle_bits rewrite_load_store_unaligned( } if (err) { - siginfo_t info = { - .si_signo = SIGBUS, - .si_code = BUS_ADRALN, - .si_addr = addr - }; + siginfo_t info; + + clear_siginfo(&info); + info.si_signo = SIGBUS; + info.si_code = BUS_ADRALN; + info.si_addr = addr; + trace_unhandled_signal("bad address for unaligned fixup", regs, (unsigned long)addr, SIGBUS); force_sig_info(info.si_signo, &info, current); diff --git a/arch/tile/kernel/traps.c b/arch/tile/kernel/traps.c index 9b08c6055f15..83a7186198d7 100644 --- a/arch/tile/kernel/traps.c +++ b/arch/tile/kernel/traps.c @@ -256,12 +256,14 @@ static int do_bpt(struct pt_regs *regs) void __kprobes do_trap(struct pt_regs *regs, int fault_num, unsigned long reason) { - siginfo_t info = { 0 }; + siginfo_t info; int signo, code; unsigned long address = 0; tile_bundle_bits instr; int is_kernel = !user_mode(regs); + clear_siginfo(&info); + /* Handle breakpoints, etc. */ if (is_kernel && fault_num == INT_ILL && do_bpt(regs)) return; diff --git a/arch/tile/kernel/unaligned.c b/arch/tile/kernel/unaligned.c index 8149c38f67b6..77a0b6b6a2a1 100644 --- a/arch/tile/kernel/unaligned.c +++ b/arch/tile/kernel/unaligned.c @@ -980,11 +980,13 @@ void jit_bundle_gen(struct pt_regs *regs, tilegx_bundle_bits bundle, } if ((align_ctl == 0) || unexpected) { - siginfo_t info = { - .si_signo = SIGBUS, - .si_code = BUS_ADRALN, - .si_addr = (unsigned char __user *)0 - }; + siginfo_t info; + + clear_siginfo(&info); + info.si_signo = SIGBUS; + info.si_code = BUS_ADRALN; + info.si_addr = (unsigned char __user *)0; + if (unaligned_printk) pr_info("Unalign bundle: unexp @%llx, %llx\n", (unsigned long long)regs->pc, @@ -1396,11 +1398,12 @@ void jit_bundle_gen(struct pt_regs *regs, tilegx_bundle_bits bundle, &frag, sizeof(frag)); if (status) { /* Fail to copy JIT into user land. send SIGSEGV. */ - siginfo_t info = { - .si_signo = SIGSEGV, - .si_code = SEGV_MAPERR, - .si_addr = (void __user *)&jit_code_area[idx] - }; + siginfo_t info; + + clear_siginfo(&info); + info.si_signo = SIGSEGV; + info.si_code = SEGV_MAPERR; + info.si_addr = (void __user *)&jit_code_area[idx]; pr_warn("Unalign fixup: pid=%d %s jit_code_area=%llx\n", current->pid, current->comm, @@ -1511,11 +1514,12 @@ void do_unaligned(struct pt_regs *regs, int vecnum) * If so, we will trigger SIGBUS. */ if ((regs->sp & 0x7) || (regs->ex1) || (align_ctl < 0)) { - siginfo_t info = { - .si_signo = SIGBUS, - .si_code = BUS_ADRALN, - .si_addr = (unsigned char __user *)0 - }; + siginfo_t info; + + clear_siginfo(&info); + info.si_signo = SIGBUS; + info.si_code = BUS_ADRALN; + info.si_addr = (unsigned char __user *)0; if (unaligned_printk) pr_info("Unalign fixup: %d %llx @%llx\n", @@ -1535,11 +1539,13 @@ void do_unaligned(struct pt_regs *regs, int vecnum) pc = (tilegx_bundle_bits __user *)(regs->pc); if (get_user(bundle, pc) != 0) { /* Probably never be here since pc is valid user address.*/ - siginfo_t info = { - .si_signo = SIGSEGV, - .si_code = SEGV_MAPERR, - .si_addr = (void __user *)pc - }; + siginfo_t info; + + clear_siginfo(&info); + info.si_signo = SIGSEGV; + info.si_code = SEGV_MAPERR; + info.si_addr = (void __user *)pc; + pr_err("Couldn't read instruction at %p trying to step\n", pc); trace_unhandled_signal("segfault in unalign fixup", regs, (unsigned long)info.si_addr, SIGSEGV); -- cgit v1.2.3