From patchwork Thu Apr 7 22:48:00 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Helge Deller X-Patchwork-Id: 8777851 Return-Path: X-Original-To: patchwork-linux-parisc@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id BD838C0553 for ; Thu, 7 Apr 2016 22:48:21 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id A8A88201ED for ; Thu, 7 Apr 2016 22:48:20 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 66591201CD for ; Thu, 7 Apr 2016 22:48:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756411AbcDGWsS (ORCPT ); Thu, 7 Apr 2016 18:48:18 -0400 Received: from mout.gmx.net ([212.227.15.19]:55126 "EHLO mout.gmx.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753278AbcDGWsR (ORCPT ); Thu, 7 Apr 2016 18:48:17 -0400 Received: from [192.168.20.60] ([92.203.48.155]) by mail.gmx.com (mrgmx001) with ESMTPSA (Nemesis) id 0LoEwL-1bUGBG05V3-00gDc7; Fri, 08 Apr 2016 00:48:03 +0200 Subject: Re: kernel 4.6-rc unbootable due to module changes To: Mikulas Patocka , John David Anglin References: <570409DA.1060508@gmx.de> <57058332.8050204@gmx.de> Cc: linux-parisc@vger.kernel.org From: Helge Deller Message-ID: <5706E3A0.2020902@gmx.de> Date: Fri, 8 Apr 2016 00:48:00 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.1.0 MIME-Version: 1.0 In-Reply-To: <57058332.8050204@gmx.de> X-Provags-ID: V03:K0:oKwCn9ATtWxPBsK36YAl8tiN/AGW4CQTu987N8nTqjUXtTnmROa PpZ4PCBAs1CxIgb+ZVujn0vkio4MFhGBkH1uOuX+g/CvwxM1cx4Lxtl+gKV+5sl9Hpjpy5n bmXswiPuPLhZMO4JbZLaPpPJmxe1WJS7BV/vqRHT7srbD4mR+MaSZwcLAWAtpAusX4Z+ukM WaJWGRRTe8DbePwlJdqWg== X-UI-Out-Filterresults: notjunk:1; V01:K0:vZVXVk1ejRU=:UJtiI1HNa5fdgyo1GxHU1L NpvcmaU5wo75VvDKV3q1xcZ7p1mT4UUboA+iF2bI3WfJ7uY5dB/l9yzoDaDMhcTZuuFDwDg3L SzKj9Z3CD9P0r+znOxOcraCUFre5UBOV4+tWSPg/Owe4qBbymlGbAKns5K81rSCIDeWwUY2Ma F/zPTRw72VUffiAwbK4t5bwQymrINLtebk6FTrLSJ3WfdbcIX7Pe/KOnrOEEkX8a5QGSBP6of 0K0OWhVzdgFG8UkqDTEqXOaJxQlzSScg/z+zhkiI3DLC14WjBdPPAeZOJpsdMxovAKnI9JiPe lHTgUqT3zgAhh6sVuFIR6r6YuX1LaAK+QUeJ/kx3kpqfR3QY1dZQGmZrPmMNs/V2U3mXZs/Qq PWXtpzreS+fVpg91GKuSZIraDqjgLbw/BoSZCcaVG2AXGK/RzPjM9ms0mbIATFShj4S60lqsG OI9QcdgletTbWvI1E9tuUI2wRMMJk3iryNIp28z58kYGgJGB0OdUlBKKQQKGv2i6YyadSOcP2 UIEk9gRMinP15JW3tGYJnkKmwBTZjqVJSv0fwPNSTpGusKdo8nFT/UN8JyuyZYFzbrylcb7H5 0fT9f2Z6TjscfbJvMJglPhowlizqGQgoRMGKfj+R5DBtUWgpv+XFIFD1uUjYbsK9On4FN1/Ox u1K4xZ1bhontvQWy0JJJlF/nUyZJeXn41aRu/WMRyR7FFkf1QeUoaSu9VPctcKKuy3xm5TD1R /ExiSqhe+dYEesipeUSv1IJxDlubmue2P2pIFiZ49ipGHKyTP3FMrh9yVqE= Sender: linux-parisc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-parisc@vger.kernel.org X-Spam-Status: No, score=-7.9 required=5.0 tests=BAYES_00,FREEMAIL_FROM, RCVD_IN_DNSWL_HI,RP_MATCHES_RCVD,T_TVD_MIME_EPI,UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP On 06.04.2016 23:44, Helge Deller wrote: > On 06.04.2016 16:30, Mikulas Patocka wrote: >>>>>> The patch "parisc: Use generic extable search and sort routines" makes the >>>>>> kernel unable to load any modules. It fails with: >>>>>> >>>>>> module unix: Unknown relocation: 9 >>>>>> modprobe: FATAL: Error inserting unix (/lib/modules/4.6.0-rc2/kernel/net/unix/unix.ko): Invalid module format >>>>>> >>>>>> When I revert the patch, the kernel 4.6-rc2 boots fine. >>>>>> >>>>>> Apparently, the function apply_relocate_add in arch/parisc/kernel/module.c >>>>>> doesn't handle the new relocation type. >> Hmm - it's even more strange. >> >> I created a test kernel module that triggers an exception by using >> get_user with an invalid address (see the attached file exception.tar) > > I see there is a kernel module /lib/test_user_copy.c as well. > It seems to crash too. >> So, it seems that handling exceptions from modules never worked on >> pa-risc, it was just masked by the fact that exceptions from modules don't >> happen during normal use. Sadly you seem to be right :-( I did more testing with the test_user_copy module (with vanilla kernel 4.5 and without the relative extable support). The attached patch fixes most of the issues: 1. Kernel doesn't crash any longer on the "illegal reversed copy_to_user" testcase. 2. It fixes the R_PARISC_DIR64 ex_table entries to create absolute addresses for the exceptions in the module instead of trying to refer to function pointers. BUT: It then crashes afterwards. What happens is that the exception fixup handler now jumps from the module directly to fixup_get_user_skip_1() in the kernel code. In arch/parisc/lib/fixup.S we have: ENTRY(fixup_get_user_skip_1) get_fault_ip %r1,%r8 .... which expands to: 0000000040a5aab0 : 40a5aab0: 2b 76 50 00 addil L%6c800,dp,r1 40a5aab4: 50 21 02 f0 ldd 178(r1),r1 40a5aab8: 03 c0 08 a8 mfctl tr6,r8 40a5aabc: 49 08 00 28 ldw 14(r8),r8 and the kernel then crashes at 40a5aab4 because dp still has the value of the module and not of the kernel. I wonder how we should avoid that. Maybe the easiest way is to not inline the get_user()/put_user() code in modules, but instead jumping into the kernel and call functions like - get_user_1(), get_user_2(), get_user_4()... and so on. What shall we do? - Skip the exception handling in modules (as mentioned above by get_user_1()) with the drawback of less performance due to additional calls, - rewrite the exception table code to use function pointers, or - rewrite get_fault_ip() macro to temporary set dp to %r0 (if possible at all?), - other ideas / opinions ? Helge FYI, here is my current log while loading the test_copy_user module: [ 289.900000] Non local DIR64 Symbol fixup_get_user_skip_1 loc 00000000020b16a0 val 40a5aab0 points to 0x40a5aab0 [ 290.020000] --- local DIR64 Symbol loc 00000000020b16a8 val 20b32c0 points to 0x20b34e4 [ 290.120000] Non local DIR64 Symbol fixup_get_user_skip_1 loc 00000000020b16b0 val 40a5aab0 points to 0x40a5aab0 [ 290.240000] --- local DIR64 Symbol loc 00000000020b16b8 val 20b32c0 points to 0x20b3558 [ 290.336000] Non local DIR64 Symbol fixup_put_user_skip_1 loc 00000000020b16c0 val 40a5ab20 points to 0x40a5ab20 [ 290.456000] --- local DIR64 Symbol loc 00000000020b16c8 val 20b32c0 points to 0x20b3564 [ 290.552000] Non local DIR64 Symbol fixup_put_user_skip_1 loc 00000000020b16d0 val 40a5ab20 points to 0x40a5ab20 [ 290.676000] --- local DIR64 Symbol loc 00000000020b16d8 val 20b32c0 points to 0x20b3808 [ 290.772000] Non local DIR64 Symbol fixup_get_user_skip_1 loc 00000000020b16e0 val 40a5aab0 points to 0x40a5aab0 [ 290.892000] --- local DIR64 Symbol loc 00000000020b16e8 val 20b32c0 points to 0x20b3814 [ 290.988000] Non local DIR64 Symbol fixup_get_user_skip_1 loc 00000000020b16f0 val 40a5aab0 points to 0x40a5aab0 [ 291.112000] --- local DIR64 Symbol loc 00000000020b16f8 val 20b32c0 points to 0x20b3898 [ 291.208000] Non local DIR64 Symbol fixup_put_user_skip_1 loc 00000000020b1700 val 40a5ab20 points to 0x40a5ab20 [ 291.328000] --- local DIR64 Symbol loc 00000000020b1708 val 20b32c0 points to 0x20b38a4 [ 291.424000] Non local DIR64 Symbol fixup_put_user_skip_1 loc 00000000020b1710 val 40a5ab20 points to 0x40a5ab20 [ 291.548000] test_user_copy: Testing: legitimate copy_from_user failed [ 291.624000] test_user_copy: FINISHED: result = 0 [ 291.680000] test_user_copy: Testing: legitimate copy_to_user failed [ 291.756000] test_user_copy: FINISHED: result = 0 [ 291.808000] test_user_copy: Testing: legitimate get_user failed [ 291.880000] test_user_copy: FINISHED: result = 0 [ 291.936000] test_user_copy: Testing: legitimate put_user failed [ 292.008000] test_user_copy: FINISHED: result = 0 [ 292.064000] test_user_copy: Testing: illegal all-kernel copy_from_user passed [ 292.148000] fault at 0x406d671c ... found ! fixup = 0x406d6844 [ 292.220000] test_user_copy: FINISHED: result = 0 [ 292.272000] test_user_copy: Testing: illegal reversed copy_from_user passed [ 292.356000] fault at 0x406d671c ... found ! fixup = 0x406d6844 [ 292.428000] test_user_copy: FINISHED: result = 0 [ 292.484000] test_user_copy: Testing: illegal all-kernel copy_to_user passed [ 292.568000] fault at 0x406d672c ... found ! fixup = 0x406d684c [ 292.640000] test_user_copy: FINISHED: result = 0 [ 292.692000] test_user_copy: Testing: illegal reversed copy_to_user passed [ 292.776000] fault at 0x406d671c ... found ! fixup = 0x406d6844 [ 292.844000] test_user_copy: FINISHED: result = 0 [ 292.900000] test_user_copy: Testing: illegal get_user passed [ 292.968000] fault at 0x020b3814 ... found ! fixup = 0x40a5aab0 [ 293.040000] fault at 0x40a5aab4 ... not found ! [ 293.096000] Backtrace: [ 293.096000] fault at 0x40223eac ... found ! fixup = 0x40a5aab0 [ 293.096000] [ 293.096000] [ 293.096000] Kernel Fault: Code=15 regs=00000000b12946a0 (Addr=000000000211d978) [ 293.096000] CPU: 0 PID: 1320 Comm: modprobe Not tainted 4.5.0-64bit+ #290 [ 293.096000] task: 00000000b290a700 ti: 00000000b1294000 task.ti: 00000000b1294000 [ 293.096000] [ 293.096000] YZrvWESTHLNXBCVMcbcbcbcbOGFRQPDI [ 293.096000] PSW: 00001000000001001111110000001111 Not tainted [ 293.096000] r00-03 000000ff0804fc0f 000000000211d800 00000000020b37f4 00000000b12945b0 [ 293.096000] r04-07 00000000020b1000 00000000b2b3a000 00000000fa6fa000 00000000020b1478 [ 293.096000] r08-11 0000000000000000 00000000020b15d0 00000000020b1430 0000000000000000 [ 293.096000] r12-15 0000000000000000 0000000000000000 0000000000000000 0000000000000000 [ 293.096000] r16-19 0000000000000000 0000000000000000 00000000020b15d0 0000000000000000 [ 293.096000] r20-23 0000000000000000 00000000000002f5 0000000000000000 00000000000002ee [ 293.096000] r24-27 0000000000000000 000000000800000f 0000000040d62080 00000000020b1000 [ 293.096000] r28-31 0000000000000001 00000000b12949c0 00000000b12946a0 0000000040dce928 [ 293.096000] sr00-03 00000000003eb800 0000000000000000 0000000000000000 00000000003eb800 [ 293.096000] sr04-07 0000000000000000 0000000000000000 0000000000000000 0000000000000000 [ 293.096000] [ 293.096000] IASQ: 0000000000000000 0000000000000000 IAOQ: 0000000040a5aab4 0000000040a5aab8 [ 293.096000] IIR: 502102f0 ISR: 0000000000000000 IOR: 000000000211d978 [ 293.096000] CPU: 0 CR30: 00000000b1294000 CR31: 00000000fffff5ff [ 293.096000] ORIG_R28: 0000000040e24df0 [ 293.096000] IAOQ[0]: fixup_get_user_skip_1+0x4/0x38 [ 293.096000] IAOQ[1]: fixup_get_user_skip_1+0x8/0x38 [ 293.096000] RP(r2): test_user_copy_init+0x534/0x6e8 [test_user_copy] [ 293.096000] Backtrace: [ 293.096000] fault at 0x40223eac ... found ! fixup = 0x40a5aab0 [ 293.096000] [ 293.096000] Kernel panic - not syncing: Kernel Fault diff --git a/arch/parisc/kernel/parisc_ksyms.c b/arch/parisc/kernel/parisc_ksyms.c index 568b2c6..4b18a04 100644 --- a/arch/parisc/kernel/parisc_ksyms.c +++ b/arch/parisc/kernel/parisc_ksyms.c @@ -48,10 +48,14 @@ EXPORT_SYMBOL(lclear_user); EXPORT_SYMBOL(lstrnlen_user); /* Global fixups */ -extern void fixup_get_user_skip_1(void); -extern void fixup_get_user_skip_2(void); -extern void fixup_put_user_skip_1(void); -extern void fixup_put_user_skip_2(void); +//extern void fixup_get_user_skip_1(void); +//extern void fixup_get_user_skip_2(void); +//extern void fixup_put_user_skip_1(void); +//extern void fixup_put_user_skip_2(void); +extern int fixup_get_user_skip_1; +extern int fixup_get_user_skip_2; +extern int fixup_put_user_skip_1; +extern int fixup_put_user_skip_2; EXPORT_SYMBOL(fixup_get_user_skip_1); EXPORT_SYMBOL(fixup_get_user_skip_2); EXPORT_SYMBOL(fixup_put_user_skip_1); diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c index 553b098..bb7f191 100644 --- a/arch/parisc/kernel/traps.c +++ b/arch/parisc/kernel/traps.c @@ -798,6 +798,9 @@ void notrace handle_interruption(int code, struct pt_regs *regs) if (fault_space == 0 && !faulthandler_disabled()) { + /* Clean up and return if in exception table. */ + if (fixup_exception(regs)) + return; pdc_chassis_send_status(PDC_CHASSIS_DIRECT_PANIC); parisc_terminate("Kernel Fault", regs, code, fault_address); }