Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 11a4180c authored by Andi Kleen's avatar Andi Kleen Committed by Andi Kleen
Browse files

[PATCH] i386: Use probe_kernel_address instead of __get_user in fault paths



Makes the intention of the code cleaner to read and avoids
a potential deadlock on mmap_sem. Also change the types of
the arguments to not include __user because they're really
not user addresses.

Signed-off-by: default avatarAndi Kleen <ak@suse.de>
parent ab2bf0c1
Loading
Loading
Loading
Loading
+13 −11
Original line number Diff line number Diff line
@@ -380,7 +380,7 @@ void show_registers(struct pt_regs *regs)
	 * time of the fault..
	 */
	if (in_kernel) {
		u8 __user *eip;
		u8 *eip;
		int code_bytes = 64;
		unsigned char c;

@@ -389,18 +389,20 @@ void show_registers(struct pt_regs *regs)

		printk(KERN_EMERG "Code: ");

		eip = (u8 __user *)regs->eip - 43;
		if (eip < (u8 __user *)PAGE_OFFSET || __get_user(c, eip)) {
		eip = (u8 *)regs->eip - 43;
		if (eip < (u8 *)PAGE_OFFSET ||
			probe_kernel_address(eip, c)) {
			/* try starting at EIP */
			eip = (u8 __user *)regs->eip;
			eip = (u8 *)regs->eip;
			code_bytes = 32;
		}
		for (i = 0; i < code_bytes; i++, eip++) {
			if (eip < (u8 __user *)PAGE_OFFSET || __get_user(c, eip)) {
			if (eip < (u8 *)PAGE_OFFSET ||
				probe_kernel_address(eip, c)) {
				printk(" Bad EIP value.");
				break;
			}
			if (eip == (u8 __user *)regs->eip)
			if (eip == (u8 *)regs->eip)
				printk("<%02x> ", c);
			else
				printk("%02x ", c);
@@ -416,7 +418,7 @@ static void handle_BUG(struct pt_regs *regs)

	if (eip < PAGE_OFFSET)
		return;
	if (probe_kernel_address((unsigned short __user *)eip, ud2))
	if (probe_kernel_address((unsigned short *)eip, ud2))
		return;
	if (ud2 != 0x0b0f)
		return;
@@ -429,11 +431,11 @@ static void handle_BUG(struct pt_regs *regs)
		char *file;
		char c;

		if (probe_kernel_address((unsigned short __user *)(eip + 2),
					line))
		if (probe_kernel_address((unsigned short *)(eip + 2), line))
			break;
		if (__get_user(file, (char * __user *)(eip + 4)) ||
		    (unsigned long)file < PAGE_OFFSET || __get_user(c, file))
		if (probe_kernel_address((char **)(eip + 4), file) ||
		    (unsigned long)file < PAGE_OFFSET ||
			probe_kernel_address(file, c))
			file = "<bad filename>";

		printk(KERN_EMERG "kernel BUG at %s:%d!\n", file, line);
+6 −6
Original line number Diff line number Diff line
@@ -22,9 +22,9 @@
#include <linux/highmem.h>
#include <linux/module.h>
#include <linux/kprobes.h>
#include <linux/uaccess.h>

#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/desc.h>
#include <asm/kdebug.h>
#include <asm/segment.h>
@@ -167,7 +167,7 @@ static inline unsigned long get_segment_eip(struct pt_regs *regs,
static int __is_prefetch(struct pt_regs *regs, unsigned long addr)
{ 
	unsigned long limit;
	unsigned long instr = get_segment_eip (regs, &limit);
	unsigned char *instr = (unsigned char *)get_segment_eip (regs, &limit);
	int scan_more = 1;
	int prefetch = 0; 
	int i;
@@ -177,9 +177,9 @@ static int __is_prefetch(struct pt_regs *regs, unsigned long addr)
		unsigned char instr_hi;
		unsigned char instr_lo;

		if (instr > limit)
		if (instr > (unsigned char *)limit)
			break;
		if (__get_user(opcode, (unsigned char __user *) instr))
		if (probe_kernel_address(instr, opcode))
			break; 

		instr_hi = opcode & 0xf0; 
@@ -204,9 +204,9 @@ static int __is_prefetch(struct pt_regs *regs, unsigned long addr)
		case 0x00:
			/* Prefetch instruction is 0x0F0D or 0x0F18 */
			scan_more = 0;
			if (instr > limit)
			if (instr > (unsigned char *)limit)
				break;
			if (__get_user(opcode, (unsigned char __user *) instr))
			if (probe_kernel_address(instr, opcode))
				break;
			prefetch = (instr_lo == 0xF) &&
				(opcode == 0x0D || opcode == 0x18);