5aa6b70ed1
In case of a use after free kernel oops, the freeing path of the object is required to debug futher. In most of cases the object address is present in one of the registers. Thus check the register's address and if it belongs to slab, print its alloc and free path. e.g. in the below issue register r6 belongs to slab, and a use after free issue occurred on one of its dereferenced values: Unable to handle kernel paging request at virtual address 6b6b6b6f .... pc : [<c0538afc>] lr : [<c0465674>] psr: 60000013 sp : c8927d40 ip : ffffefff fp : c8aa8020 r10: c8927e10 r9 : 00000001 r8 : 00400cc0 r7 : 00000000 r6 : c8ab0180 r5 : c1804a80 r4 : c8aa8008 r3 : c1a5661c r2 : 00000000 r1 : 6b6b6b6b r0 : c139bf48 ..... Register r6 information: slab kmalloc-64 start c8ab0140 data offset 64 pointer offset 0 size 64 allocated at meminfo_proc_show+0x40/0x4fc meminfo_proc_show+0x40/0x4fc seq_read_iter+0x18c/0x4c4 proc_reg_read_iter+0x84/0xac generic_file_splice_read+0xe8/0x17c splice_direct_to_actor+0xb8/0x290 do_splice_direct+0xa0/0xe0 do_sendfile+0x2d0/0x438 sys_sendfile64+0x12c/0x140 ret_fast_syscall+0x0/0x58 0xbeeacde4 Free path: meminfo_proc_show+0x5c/0x4fc seq_read_iter+0x18c/0x4c4 proc_reg_read_iter+0x84/0xac generic_file_splice_read+0xe8/0x17c splice_direct_to_actor+0xb8/0x290 do_splice_direct+0xa0/0xe0 do_sendfile+0x2d0/0x438 sys_sendfile64+0x12c/0x140 ret_fast_syscall+0x0/0x58 0xbeeacde4 Link: https://lkml.kernel.org/r/1615891032-29160-3-git-send-email-maninder1.s@samsung.com Co-developed-by: Vaneet Narang <v.narang@samsung.com> Signed-off-by: Vaneet Narang <v.narang@samsung.com> Signed-off-by: Maninder Singh <maninder1.s@samsung.com> Cc: Al Viro <viro@zeniv.linux.org.uk> Cc: Christoph Lameter <cl@linux.com> Cc: David Rientjes <rientjes@google.com> Cc: Dmitry Safonov <0x7f454c46@gmail.com> Cc: Joonsoo Kim <iamjoonsoo.kim@lge.com> Cc: Paul E. McKenney <paulmck@kernel.org> Cc: Pekka Enberg <penberg@kernel.org> Cc: Russell King <linux@armlinux.org.uk> Cc: Vlastimil Babka <vbabka@suse.cz> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
94 lines
2.6 KiB
C
94 lines
2.6 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
#ifndef _ASMARM_BUG_H
|
|
#define _ASMARM_BUG_H
|
|
|
|
#include <linux/linkage.h>
|
|
#include <linux/types.h>
|
|
#include <asm/opcodes.h>
|
|
|
|
/*
|
|
* Use a suitable undefined instruction to use for ARM/Thumb2 bug handling.
|
|
* We need to be careful not to conflict with those used by other modules and
|
|
* the register_undef_hook() system.
|
|
*/
|
|
#ifdef CONFIG_THUMB2_KERNEL
|
|
#define BUG_INSTR_VALUE 0xde02
|
|
#define BUG_INSTR(__value) __inst_thumb16(__value)
|
|
#else
|
|
#define BUG_INSTR_VALUE 0xe7f001f2
|
|
#define BUG_INSTR(__value) __inst_arm(__value)
|
|
#endif
|
|
|
|
|
|
#define BUG() _BUG(__FILE__, __LINE__, BUG_INSTR_VALUE)
|
|
#define _BUG(file, line, value) __BUG(file, line, value)
|
|
|
|
#ifdef CONFIG_DEBUG_BUGVERBOSE
|
|
|
|
/*
|
|
* The extra indirection is to ensure that the __FILE__ string comes through
|
|
* OK. Many version of gcc do not support the asm %c parameter which would be
|
|
* preferable to this unpleasantness. We use mergeable string sections to
|
|
* avoid multiple copies of the string appearing in the kernel image.
|
|
*/
|
|
|
|
#define __BUG(__file, __line, __value) \
|
|
do { \
|
|
asm volatile("1:\t" BUG_INSTR(__value) "\n" \
|
|
".pushsection .rodata.str, \"aMS\", %progbits, 1\n" \
|
|
"2:\t.asciz " #__file "\n" \
|
|
".popsection\n" \
|
|
".pushsection __bug_table,\"aw\"\n" \
|
|
".align 2\n" \
|
|
"3:\t.word 1b, 2b\n" \
|
|
"\t.hword " #__line ", 0\n" \
|
|
".popsection"); \
|
|
unreachable(); \
|
|
} while (0)
|
|
|
|
#else
|
|
|
|
#define __BUG(__file, __line, __value) \
|
|
do { \
|
|
asm volatile(BUG_INSTR(__value) "\n"); \
|
|
unreachable(); \
|
|
} while (0)
|
|
#endif /* CONFIG_DEBUG_BUGVERBOSE */
|
|
|
|
#define HAVE_ARCH_BUG
|
|
|
|
#include <asm-generic/bug.h>
|
|
|
|
struct pt_regs;
|
|
void die(const char *msg, struct pt_regs *regs, int err);
|
|
|
|
void arm_notify_die(const char *str, struct pt_regs *regs,
|
|
int signo, int si_code, void __user *addr,
|
|
unsigned long err, unsigned long trap);
|
|
|
|
#ifdef CONFIG_ARM_LPAE
|
|
#define FAULT_CODE_ALIGNMENT 33
|
|
#define FAULT_CODE_DEBUG 34
|
|
#else
|
|
#define FAULT_CODE_ALIGNMENT 1
|
|
#define FAULT_CODE_DEBUG 2
|
|
#endif
|
|
|
|
void hook_fault_code(int nr, int (*fn)(unsigned long, unsigned int,
|
|
struct pt_regs *),
|
|
int sig, int code, const char *name);
|
|
|
|
void hook_ifault_code(int nr, int (*fn)(unsigned long, unsigned int,
|
|
struct pt_regs *),
|
|
int sig, int code, const char *name);
|
|
|
|
extern asmlinkage void c_backtrace(unsigned long fp, int pmode,
|
|
const char *loglvl);
|
|
|
|
struct mm_struct;
|
|
void show_pte(const char *lvl, struct mm_struct *mm, unsigned long addr);
|
|
extern void __show_regs(struct pt_regs *);
|
|
extern void __show_regs_alloc_free(struct pt_regs *regs);
|
|
|
|
#endif
|