From patchwork Thu Dec 24 19:44:38 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Al Viro X-Patchwork-Id: 11989731 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id C8DF9C433DB for ; Thu, 24 Dec 2020 19:46:02 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 7F071227BF for ; Thu, 24 Dec 2020 19:46:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728679AbgLXTpq (ORCPT ); Thu, 24 Dec 2020 14:45:46 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49636 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728266AbgLXTpq (ORCPT ); Thu, 24 Dec 2020 14:45:46 -0500 Received: from ZenIV.linux.org.uk (zeniv.linux.org.uk [IPv6:2002:c35c:fd02::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8B394C061573; Thu, 24 Dec 2020 11:45:02 -0800 (PST) Received: from viro by ZenIV.linux.org.uk with local (Exim 4.92.3 #3 (Red Hat Linux)) id 1ksWXP-003sWr-0X; Thu, 24 Dec 2020 19:44:39 +0000 Date: Thu, 24 Dec 2020 19:44:38 +0000 From: Al Viro To: "Maciej W. Rozycki" Cc: Linus Torvalds , Thomas Bogendoerfer , Linux Kernel Mailing List , the arch/x86 maintainers , linux-mips@vger.kernel.org, Randy Dunlap , Denys Vlasenko Subject: [RFC][PATCH] NT_FILE/NT_SIGINFO breakage on mips compat coredumps Message-ID: <20201224194438.GY3579531@ZenIV.linux.org.uk> References: <20201203214529.GB3579531@ZenIV.linux.org.uk> <20201203230336.GC3579531@ZenIV.linux.org.uk> <20201216030154.GL3579531@ZenIV.linux.org.uk> <20201223070320.GW3579531@ZenIV.linux.org.uk> <20201223071213.GX3579531@ZenIV.linux.org.uk> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20201223071213.GX3579531@ZenIV.linux.org.uk> Sender: Al Viro Precedence: bulk List-ID: X-Mailing-List: linux-mips@vger.kernel.org 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 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: . Find the GDB manual and other documentation resources online at: . 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 }, _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 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: . Find the GDB manual and other documentation resources online at: . 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 }, _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 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"