lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Thu, 18 Oct 2018 16:34:34 +0800
From:   Nickhu <nickhu@...estech.com>
To:     <greentime@...estech.com>, <linux-kernel@...r.kernel.org>,
        <arnd@...db.de>, <deanbo422@...il.com>, <zong@...estech.com>,
        <ebiederm@...ssion.com>
CC:     Nickhu <nickhu@...estech.com>, <green.hu@...il.com>
Subject: [PATCH 3/3] nds32: Add unaligned access in kernel space.

As my colleague has encountered kernel panic when unaligned access
in kernel space. Here is the situation, the structure 'TP_STRUCT__entry':

TP_STRUCT__entry(
                __field(        u32,    tb_id           )
                __field(        int,    err             )
                __field(        int,    oif             )
                __field(        int,    iif             )
                __field(        __u8,   tos             )
                __field(        __u8,   scope           )
                __field(        __u8,   flags           )
                __field(        u8,     proto           )
                __array(        __u8,   src,    4       )
                __array(        __u8,   dst,    4       )
                __array(        __u8,   gw,     4       )
                __array(        __u8,   saddr,  4       )
                __field(        u16,    sport           )
                __field(        u16,    dport           )
                __dynamic_array(char,  name,   IFNAMSIZ )
        )

When he try to access the element in the structure, the kernel panic
happen. Although he has rearrange the order of the structure to fix
the problem, but we cannot ignore the fact that there still need
unaligned access in kernel space. It can help us to avoid kernel panic
when reasonable unaligned address access happen. The users need to have
the knowledge that some unreasonable unaligned address may cause the bug
in kernel.

The config 'HAVE_EFFICIENT_UNALIGNED_ACCESS' must be with the hw
unaligned access config 'HW_SUPPORT_UNALIGNMENT_ACCESS'. In sw
unalinged access handler, the code 'get_inst()' in arch/nds32/mm/
alignment.c:522 would be generate as load word instruction if
'HAVE_EFFICIENT_UNALIGNED_ACCESS' is set. This would cause the kernel
hang in loop if the address of the load word instruction is unaligned.
For example:

	0xbc39e: lwi450 $r0, [$r1], if the $r1 cause unaligned access.
								|
								| unaligned access handler
								v
	arch/nds32/mm/alignment.c:522: get_ints():0xb0874b7e lwi450 $r2, [$3],
	$r3 is the address '0xbc39e', it would cause kernel unaligned access.
								|
								| unaligned access handler
								v
	arch/nds32/mm/alignment.c:522: get_ints():0xb0874b7e lwi450 $r2, [$3],
	$r3 is the address '0xb0874b7e', it would cause kernel unaligned access.

The kernel is hang in the loop.

Signed-off-by: Nickhu <nickhu@...estech.com>
---
 arch/nds32/kernel/traps.c | 4 +++-
 arch/nds32/mm/alignment.c | 6 ++++--
 2 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/arch/nds32/kernel/traps.c b/arch/nds32/kernel/traps.c
index 1496aab48998..dcde7abc5515 100644
--- a/arch/nds32/kernel/traps.c
+++ b/arch/nds32/kernel/traps.c
@@ -331,6 +331,7 @@ void do_revinsn(struct pt_regs *regs)
 #ifdef CONFIG_ALIGNMENT_TRAP
 extern int unalign_access_mode;
 extern int do_unaligned_access(unsigned long addr, struct pt_regs *regs);
+extern int va_kernel_present(unsigned long addr);
 #endif
 void do_dispatch_general(unsigned long entry, unsigned long addr,
 			 unsigned long itype, struct pt_regs *regs,
@@ -341,7 +342,8 @@ void do_dispatch_general(unsigned long entry, unsigned long addr,
 	if (type == ETYPE_ALIGNMENT_CHECK) {
 #ifdef CONFIG_ALIGNMENT_TRAP
 		/* Alignment check */
-		if (user_mode(regs) && unalign_access_mode) {
+		if ((user_mode(regs) && unalign_access_mode) ||
+		    va_kernel_present(addr)) {
 			int ret;
 			ret = do_unaligned_access(addr, regs);
 
diff --git a/arch/nds32/mm/alignment.c b/arch/nds32/mm/alignment.c
index 66a556befd05..2d7a08af6622 100644
--- a/arch/nds32/mm/alignment.c
+++ b/arch/nds32/mm/alignment.c
@@ -524,8 +524,10 @@ int do_unaligned_access(unsigned long addr, struct pt_regs *regs)
 	DEBUG((unalign_access_debug > 0), 1,
 	      "Faulting addr: 0x%08lx, pc: 0x%08lx [inst: 0x%08lx ]\n", addr,
 	      regs->ipc, inst);
-
-	set_fs(USER_DS);
+	if ((user_mode(regs) && unalign_access_mode))
+		set_fs(USER_DS);
+	else if (va_kernel_present(addr))
+		set_fs(KERNEL_DS);
 
 	if (inst & NDS32_16BIT_INSTRUCTION)
 		ret = do_16((inst >> 16) & 0xffff, regs);
-- 
2.17.0

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ