[PATCH] unwinder: Use probe_kernel_address instead of __get_user in kernel/unwind.c
This avoids trouble with the page fault handler if the fault happens inside an interrupt context. Suggested by Linus Cc: jbeulich@novell.com Signed-off-by: Andi Kleen <ak@suse.de>
This commit is contained in:
parent
f3d73707a1
commit
e2124bb8d3
|
@ -14,6 +14,7 @@
|
||||||
#include <linux/bootmem.h>
|
#include <linux/bootmem.h>
|
||||||
#include <linux/sort.h>
|
#include <linux/sort.h>
|
||||||
#include <linux/stop_machine.h>
|
#include <linux/stop_machine.h>
|
||||||
|
#include <linux/uaccess.h>
|
||||||
#include <asm/sections.h>
|
#include <asm/sections.h>
|
||||||
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
||||||
#include <asm/unaligned.h>
|
#include <asm/unaligned.h>
|
||||||
|
@ -550,7 +551,7 @@ static unsigned long read_pointer(const u8 **pLoc,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if ((ptrType & DW_EH_PE_indirect)
|
if ((ptrType & DW_EH_PE_indirect)
|
||||||
&& __get_user(value, (unsigned long *)value))
|
&& probe_kernel_address((unsigned long *)value, value))
|
||||||
return 0;
|
return 0;
|
||||||
*pLoc = ptr.p8;
|
*pLoc = ptr.p8;
|
||||||
|
|
||||||
|
@ -982,18 +983,19 @@ int unwind(struct unwind_frame_info *frame)
|
||||||
& (sizeof(unsigned long) - 1))) {
|
& (sizeof(unsigned long) - 1))) {
|
||||||
unsigned long link;
|
unsigned long link;
|
||||||
|
|
||||||
if (!__get_user(link,
|
if (!probe_kernel_address(
|
||||||
(unsigned long *)(UNW_FP(frame)
|
(unsigned long *)(UNW_FP(frame)
|
||||||
+ FRAME_LINK_OFFSET))
|
+ FRAME_LINK_OFFSET),
|
||||||
|
link)
|
||||||
# if FRAME_RETADDR_OFFSET < 0
|
# if FRAME_RETADDR_OFFSET < 0
|
||||||
&& link > bottom && link < UNW_FP(frame)
|
&& link > bottom && link < UNW_FP(frame)
|
||||||
# else
|
# else
|
||||||
&& link > UNW_FP(frame) && link < bottom
|
&& link > UNW_FP(frame) && link < bottom
|
||||||
# endif
|
# endif
|
||||||
&& !(link & (sizeof(link) - 1))
|
&& !(link & (sizeof(link) - 1))
|
||||||
&& !__get_user(UNW_PC(frame),
|
&& !probe_kernel_address(
|
||||||
(unsigned long *)(UNW_FP(frame)
|
(unsigned long *)(UNW_FP(frame)
|
||||||
+ FRAME_RETADDR_OFFSET))) {
|
+ FRAME_RETADDR_OFFSET), UNW_PC(frame))) {
|
||||||
UNW_SP(frame) = UNW_FP(frame) + FRAME_RETADDR_OFFSET
|
UNW_SP(frame) = UNW_FP(frame) + FRAME_RETADDR_OFFSET
|
||||||
# if FRAME_RETADDR_OFFSET < 0
|
# if FRAME_RETADDR_OFFSET < 0
|
||||||
-
|
-
|
||||||
|
@ -1104,7 +1106,7 @@ int unwind(struct unwind_frame_info *frame)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
switch(reg_info[i].width) {
|
switch(reg_info[i].width) {
|
||||||
#define CASE(n) case sizeof(u##n): \
|
#define CASE(n) case sizeof(u##n): \
|
||||||
__get_user(FRAME_REG(i, u##n), (u##n *)addr); \
|
probe_kernel_address((u##n *)addr, FRAME_REG(i, u##n)); \
|
||||||
break
|
break
|
||||||
CASES;
|
CASES;
|
||||||
#undef CASE
|
#undef CASE
|
||||||
|
|
Loading…
Reference in New Issue