From: Helge Deller <deller@gmx.de>
To: Mikulas Patocka <mpatocka@redhat.com>,
John David Anglin <dave.anglin@bell.net>
Cc: linux-parisc@vger.kernel.org
Subject: Re: kernel 4.6-rc unbootable due to module changes
Date: Fri, 8 Apr 2016 00:48:00 +0200 [thread overview]
Message-ID: <5706E3A0.2020902@gmx.de> (raw)
In-Reply-To: <57058332.8050204@gmx.de>
[-- Attachment #1: Type: text/plain, Size: 7879 bytes --]
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 <sourcetree>/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 <fixup_get_user_skip_1>:
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
[-- Attachment #2: fixup.patch --]
[-- Type: text/x-diff, Size: 1432 bytes --]
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);
}
next prev parent reply other threads:[~2016-04-07 22:48 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-04-05 17:31 kernel 4.6-rc unbootable due to module changes Mikulas Patocka
2016-04-05 17:36 ` Mikulas Patocka
2016-04-05 18:54 ` Helge Deller
2016-04-05 20:15 ` Mikulas Patocka
2016-04-06 14:30 ` Mikulas Patocka
2016-04-06 21:44 ` Helge Deller
2016-04-07 22:48 ` Helge Deller [this message]
2016-04-08 12:06 ` Aw: " Helge Deller
2016-04-08 14:59 ` Helge Deller
2016-04-08 19:43 ` Helge Deller
2016-04-05 20:18 ` John David Anglin
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=5706E3A0.2020902@gmx.de \
--to=deller@gmx.de \
--cc=dave.anglin@bell.net \
--cc=linux-parisc@vger.kernel.org \
--cc=mpatocka@redhat.com \
/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