linux-mips.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Al Viro <viro@zeniv.linux.org.uk>
To: "Maciej W. Rozycki" <macro@linux-mips.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>,
	Thomas Bogendoerfer <tsbogend@alpha.franken.de>,
	Linux Kernel Mailing List <linux-kernel@vger.kernel.org>,
	the arch/x86 maintainers <x86@kernel.org>,
	linux-mips@vger.kernel.org, Randy Dunlap <rdunlap@infradead.org>,
	Denys Vlasenko <dvlasenk@redhat.com>
Subject: [RFC][PATCH] NT_FILE/NT_SIGINFO breakage on mips compat coredumps
Date: Thu, 24 Dec 2020 19:44:38 +0000	[thread overview]
Message-ID: <20201224194438.GY3579531@ZenIV.linux.org.uk> (raw)
In-Reply-To: <20201223071213.GX3579531@ZenIV.linux.org.uk>

On Wed, Dec 23, 2020 at 07:12:13AM +0000, Al Viro wrote:
> On Wed, Dec 23, 2020 at 07:03:20AM +0000, Al Viro wrote:
> 
> 	Argh....  Wrong commit blamed - the parent of the correct one.
> It's actually 2aa362c49c31 ("coredump: extend core dump note section to
> contain file names of mapped files").  My apologies - fat-fingered
> cut'n'paste...
> 
> 	siginfo commit does suffer the same problem, but it becomes an issue
> only for 32bit processes under mips64 big-endian kernel (there it yields
> e.g. zero .__sigfault.si_addr in $_siginfo when using gdb with a coredump
> of 32bit process, whatever the actual faulting address had been).  And
> b-e mips64 is rather uncommon, so that's less of an issue.

	FWIW, here's debian/mips image (stretch) booted with
qemu-system-mips64 -M malta -cpu 5KEc:
root@mips:~# uname -a
Linux mips 4.9.0-13-5kc-malta #1 Debian 4.9.228-1 (2020-07-05) mips64 GNU/Linux
root@mips:~# cat a.c
main()
{
        *(char *)0x0123 = 0;
}
root@mips:~# gcc a.c 
a.c:1:1: warning: return type defaults to ‘int’ [-Wimplicit-int]
 main()
 ^~~~
root@mips:~# ulimit -c unlimited
root@mips:~# ./a.out 
[  519.744983] do_page_fault(): sending SIGSEGV to a.out for invalid write access to 0000000000000123
[  519.746735] epc = 00000000558477c0 in a.out[55847000+1000]
[  519.747758] ra  = 000000007792f4a8 in libc-2.24.so[77916000+16a000]
Segmentation fault (core dumped)
root@mips:~# gdb a.out core 
GNU gdb (Debian 7.12-6) 7.12.0.20161007-git
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "mips-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from a.out...(no debugging symbols found)...done.
[New LWP 1202]
Core was generated by `./a.out'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x55dde7c0 in main ()
(gdb) print $_siginfo
$1 = {si_signo = 11, si_errno = 1, si_code = 0, _sifields = {_pad = {0, 0, 
      291, 0 <repeats 26 times>}, _kill = {si_pid = 0, si_uid = 0}, _timer = {
      si_tid = 0, si_overrun = 0, si_sigval = {sival_int = 291, 
        sival_ptr = 0x123}}, _rt = {si_pid = 0, si_uid = 0, si_sigval = {
        sival_int = 291, sival_ptr = 0x123}}, _sigchld = {si_pid = 0, 
      si_uid = 0, si_status = 291, si_utime = 0, si_stime = 0}, _sigfault = {
      si_addr = 0x0}, _sigpoll = {si_band = 0, si_fd = 0}}}
(gdb) quit


Note the wrong value in _sigfault.si_addr - it should've been 0x123, not 0.

root@mips:~# readelf -n core

Displaying notes found at file offset 0x00000234 with length 0x000005f4:
  Owner                 Data size       Description
  CORE                 0x00000100       NT_PRSTATUS (prstatus structure)
  CORE                 0x00000080       NT_PRPSINFO (prpsinfo structure)
  CORE                 0x00000080       NT_SIGINFO (siginfo_t data)
  CORE                 0x00000090       NT_AUXV (auxiliary vector)
  CORE                 0x000001e1       NT_FILE (mapped files)
    Page size: 9
         Start         End Page Offset
  CORE                 0x00000108       NT_FPREGSET (floating point registers)

For comparison, exact same image booted with qemu-system-mips -M malta:

root@mips:~# uname -a
Linux mips 4.9.0-13-4kc-malta #1 Debian 4.9.228-1 (2020-07-05) mips GNU/Linux
root@mips:~# ulimit -c unlimited
root@mips:~# ./a.out
[   83.380870] do_page_fault(): sending SIGSEGV to a.out for invalid write access to 00000123
[   83.390678] epc = 55e0e7c0 in a.out[55e0e000+1000]
[   83.391525] ra  = 76f644a8 in libc-2.24.so[76f4b000+16a000]
Segmentation fault (core dumped)
root@mips:~# gdb a.out core
GNU gdb (Debian 7.12-6) 7.12.0.20161007-git
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "mips-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from a.out...(no debugging symbols found)...done.
[New LWP 1184]
Core was generated by `./a.out'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x55e0e7c0 in main ()
(gdb) print $_siginfo
$1 = {si_signo = 11, si_errno = 1, si_code = 0, _sifields = {_pad = {291, 
      0 <repeats 28 times>}, _kill = {si_pid = 291, si_uid = 0}, _timer = {
      si_tid = 291, si_overrun = 0, si_sigval = {sival_int = 0, 
        sival_ptr = 0x0}}, _rt = {si_pid = 291, si_uid = 0, si_sigval = {
        sival_int = 0, sival_ptr = 0x0}}, _sigchld = {si_pid = 291, 
      si_uid = 0, si_status = 0, si_utime = 0, si_stime = 0}, _sigfault = {
      si_addr = 0x123}, _sigpoll = {si_band = 291, si_fd = 0}}}
(gdb) quit
root@mips:~# readelf -n core

Displaying notes found at file offset 0x00000234 with length 0x00000580:
  Owner                 Data size       Description
  CORE                 0x00000100       NT_PRSTATUS (prstatus structure)
  CORE                 0x00000080       NT_PRPSINFO (prpsinfo structure)
  CORE                 0x00000080       NT_SIGINFO (siginfo_t data)
  CORE                 0x00000090       NT_AUXV (auxiliary vector)
  CORE                 0x0000016d       NT_FILE (mapped files)
    Page size: 4096
         Start         End Page Offset
    0x55e0e000  0x55e0f000  0x00000000
        /root/a.out
    0x55e1e000  0x55e1f000  0x00000000
        /root/a.out
    0x76f4b000  0x770b5000  0x00000000
        /lib/mips-linux-gnu/libc-2.24.so
    0x770b5000  0x770c5000  0x0000016a
        /lib/mips-linux-gnu/libc-2.24.so
    0x770c5000  0x770c8000  0x0000016a
        /lib/mips-linux-gnu/libc-2.24.so
    0x770c8000  0x770cb000  0x0000016d
        /lib/mips-linux-gnu/libc-2.24.so
    0x770cd000  0x770f0000  0x00000000
        /lib/mips-linux-gnu/ld-2.24.so
    0x770ff000  0x77100000  0x00000022
        /lib/mips-linux-gnu/ld-2.24.so
    0x77100000  0x77101000  0x00000023
        /lib/mips-linux-gnu/ld-2.24.so
  CORE                 0x00000108       NT_FPREGSET (floating point registers)

So that's not so theoretical - big-endian mips64 userland is unsupported,
but booting the big-endian mips32 userland on mips64 hardware is clearly
meant to work - they even ship a 64bit kernel built for that.

IOW, both O32 and N32 coredumps in 64bit mips kernels have broken
NT_FILE and NT_SIGINFO.  And while NT_SIGINFO breakage is really
visible only on b-e, NT_FILE one is common to b-e and l-e.  One of
the effects of the latter is that current gdb fails to work with
threaded coredumps of 32bit processes produced on boxen with 64bit
kernels.  Coredumps generated by gcore(1) are fine...

I think the following ought to be applied.  Comments?

[mips] fix malformed NT_FILE and NT_SIGINFO in 32bit coredumps

	Patches that introduced NT_FILE and NT_SIGINFO notes back in 2012
had taken care of native (fs/binfmt_elf.c) and compat (fs/compat_binfmt_elf.c)
coredumps; unfortunately, compat on mips (which does not go through the
usual compat_binfmt_elf.c) had not been noticed.

	As the result, both N32 and O32 coredumps on 64bit mips kernels
have those sections malformed enough to confuse the living hell out of
all gdb and readelf versions (up to and including the tip of binutils-gdb.git).

	Longer term solution is to make both O32 and N32 compat use the
regular compat_binfmt_elf.c, but that's too much for backports.  The minimal
solution is to do in arch/mips/kernel/binfmt_elf[on]32.c the same thing
those patches have done in fs/compat_binfmt_elf.c

Cc: stable@kernel.org # v3.7+
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
diff --git a/arch/mips/kernel/binfmt_elfn32.c b/arch/mips/kernel/binfmt_elfn32.c
index 6ee3f7218c67..c4441416e96b 100644
--- a/arch/mips/kernel/binfmt_elfn32.c
+++ b/arch/mips/kernel/binfmt_elfn32.c
@@ -103,4 +103,11 @@ jiffies_to_old_timeval32(unsigned long jiffies, struct old_timeval32 *value)
 #undef ns_to_kernel_old_timeval
 #define ns_to_kernel_old_timeval ns_to_old_timeval32
 
+/*
+ * Some data types as stored in coredump.
+ */
+#define user_long_t             compat_long_t
+#define user_siginfo_t          compat_siginfo_t
+#define copy_siginfo_to_external        copy_siginfo_to_external32
+
 #include "../../../fs/binfmt_elf.c"
diff --git a/arch/mips/kernel/binfmt_elfo32.c b/arch/mips/kernel/binfmt_elfo32.c
index 6dd103d3cebb..7b2a23f48c1a 100644
--- a/arch/mips/kernel/binfmt_elfo32.c
+++ b/arch/mips/kernel/binfmt_elfo32.c
@@ -106,4 +106,11 @@ jiffies_to_old_timeval32(unsigned long jiffies, struct old_timeval32 *value)
 #undef ns_to_kernel_old_timeval
 #define ns_to_kernel_old_timeval ns_to_old_timeval32
 
+/*
+ * Some data types as stored in coredump.
+ */
+#define user_long_t             compat_long_t
+#define user_siginfo_t          compat_siginfo_t
+#define copy_siginfo_to_external        copy_siginfo_to_external32
+
 #include "../../../fs/binfmt_elf.c"

  reply	other threads:[~2020-12-24 19:46 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-12-03 21:45 [PATCHSET] saner elf compat Al Viro
2020-12-03 21:46 ` [PATCH 01/10] binfmt_elf: partially sanitize PRSTATUS_SIZE and SET_PR_FPVALID Al Viro
2020-12-03 21:46   ` [PATCH 02/10] elf_prstatus: collect the common part (everything before pr_reg) into a struct Al Viro
2020-12-03 21:46   ` [PATCH 03/10] [elfcore-compat][amd64] clean PRSTATUS_SIZE/SET_PR_FPVALID up properly Al Viro
2020-12-03 21:46   ` [PATCH 04/10] mips binfmt_elf*32.c: use elfcore-compat.h Al Viro
2020-12-03 21:46   ` [PATCH 05/10] mips: kill unused definitions in binfmt_elf[on]32.c Al Viro
2020-12-03 21:46   ` [PATCH 06/10] mips: KVM_GUEST makes no sense for 64bit builds Al Viro
2020-12-03 21:46   ` [PATCH 07/10] mips compat: don't bother with ELF_ET_DYN_BASE Al Viro
2020-12-03 21:46   ` [PATCH 08/10] mips: don't bother with ELF_CORE_EFLAGS Al Viro
2020-12-03 21:46   ` [PATCH 09/10] mips compat: switch to compat_binfmt_elf.c Al Viro
2020-12-03 21:46   ` [PATCH 10/10] Kconfig: regularize selection of CONFIG_BINFMT_ELF Al Viro
2020-12-03 22:09 ` [PATCHSET] saner elf compat Linus Torvalds
2020-12-03 23:03   ` Al Viro
2020-12-06  3:23     ` Al Viro
2020-12-07  3:36       ` hpa
2020-12-07 18:01     ` Maciej W. Rozycki
2020-12-16  3:01       ` Al Viro
2020-12-16  9:44         ` Maciej W. Rozycki
2020-12-22 20:04           ` Al Viro
2020-12-22 21:38             ` Al Viro
2020-12-22 22:57               ` Al Viro
2020-12-23  7:03           ` Al Viro
2020-12-23  7:12             ` Al Viro
2020-12-24 19:44               ` Al Viro [this message]
2020-12-29 15:09                 ` [RFC][PATCH] NT_FILE/NT_SIGINFO breakage on mips compat coredumps Thomas Bogendoerfer
2020-12-15 19:54     ` [PATCHSET] saner elf compat Thomas Bogendoerfer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20201224194438.GY3579531@ZenIV.linux.org.uk \
    --to=viro@zeniv.linux.org.uk \
    --cc=dvlasenk@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mips@vger.kernel.org \
    --cc=macro@linux-mips.org \
    --cc=rdunlap@infradead.org \
    --cc=torvalds@linux-foundation.org \
    --cc=tsbogend@alpha.franken.de \
    --cc=x86@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).