lkml.org 
[lkml]   [2007]   [Jul]   [26]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
Subject[PATCH] exporting address to the page fault notifier
I made a module using the notifier scheme which already exists inside 
the kernel. The problem is that the page fault notifier doesn't show the
address which happened the fault.

This little patch increments this functionality. I chose to break the
ABI putting a new field in 'die_args' instead build a new struct only
for it. The patch and the module notifier comes attached.

my regards


--
Tiago Vignatti
C3SL - Centro de Computação Científica e Software Livre
www.c3sl.ufpr.br
diff --git a/arch/i386/mm/fault.c b/arch/i386/mm/fault.c
index 01ffdd4..c405802 100644
--- a/arch/i386/mm/fault.c
+++ b/arch/i386/mm/fault.c
@@ -47,14 +47,15 @@ int unregister_page_fault_notifier(struct notifier_block *nb)
}
EXPORT_SYMBOL_GPL(unregister_page_fault_notifier);

-static inline int notify_page_fault(struct pt_regs *regs, long err)
+static inline int notify_page_fault(struct pt_regs *regs, long err, unsigned long address)
{
struct die_args args = {
.regs = regs,
.str = "page fault",
.err = err,
.trapnr = 14,
- .signr = SIGSEGV
+ .signr = SIGSEGV,
+ .address = address
};
return atomic_notifier_call_chain(&notify_page_fault_chain,
DIE_PAGE_FAULT, &args);
@@ -330,7 +331,7 @@ fastcall void __kprobes do_page_fault(struct pt_regs *regs,
if (unlikely(address >= TASK_SIZE)) {
if (!(error_code & 0x0000000d) && vmalloc_fault(address) >= 0)
return;
- if (notify_page_fault(regs, error_code) == NOTIFY_STOP)
+ if (notify_page_fault(regs, error_code, address) == NOTIFY_STOP)
return;
/*
* Don't take the mm semaphore here. If we fixup a prefetch
@@ -339,7 +340,7 @@ fastcall void __kprobes do_page_fault(struct pt_regs *regs,
goto bad_area_nosemaphore;
}

- if (notify_page_fault(regs, error_code) == NOTIFY_STOP)
+ if (notify_page_fault(regs, error_code, address) == NOTIFY_STOP)
return;

/* It's safe to allow irq's after cr2 has been saved and the vmalloc
diff --git a/include/linux/kdebug.h b/include/linux/kdebug.h
index 5db38d6..e8005c2 100644
--- a/include/linux/kdebug.h
+++ b/include/linux/kdebug.h
@@ -9,6 +9,7 @@ struct die_args {
long err;
int trapnr;
int signr;
+ unsigned long address;
};

int register_die_notifier(struct notifier_block *nb);/*
* Author: Tiago Vignatti <vignatti (at) c3sl ufpr br>
* 2007 - code under GPL
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/notifier.h>
#include <linux/kdebug.h>

/*
* error_code:
* bit 0 == 0 means no page found, 1 means protection fault
* bit 1 == 0 means read, 1 means write
* bit 2 == 0 means kernel, 1 means user-mode
* bit 3 == 1 means use of reserved bit detected
* bit 4 == 1 means fault was an instruction fetch
*/
static int pf_notify (struct notifier_block *self,
unsigned long val, void *data)
{
struct die_args *args = (struct die_args *) data;

/* You can filter the types of page like this:
if (args->err < 4)
return NOTIFY_DONE;
*/

printk("pagefault regs: %p, address: 0x%lx, fault: %lx ",
args->regs, args->address, args->err);

switch (args->err) {
case 7:
printk("(write protection fault in user-mode)\n");
break;
case 6:
printk("(write page fault in user-mode)\n");
break;
case 5:
printk("(write protection fault in user-mode)\n");
break;
case 4:
printk("(read page fault in user-mode)\n");
break;
case 3:
printk("(write protection fault in kernel-mode)\n");
break;
case 2:
printk("(write page fault in kernel-mode)\n");
break;
case 1:
printk("(read protection fault in kernel-mode)\n");
break;
case 0:
printk("(read page fault in kernel-mode)\n");
break;
default :
printk("(use of reserved bit detected or fault was an instruction fetch)\n");
break;
}

return NOTIFY_DONE;
}

static struct notifier_block my_nb = {
.notifier_call = pf_notify,
};

static int __init notifier_init(void)
{
int ret;

if ((ret = register_page_fault_notifier(&my_nb)) < 0) {
printk("register_page_fault_notifier failed, returned %d\n", ret);
return -1;
}

printk("Planted page fault notifier!\n");
return 0;
}

static void __exit notifier_exit(void)
{
unregister_page_fault_notifier(&my_nb);
printk("Page fault notifier unregistered\n");
}

module_init(notifier_init)
module_exit(notifier_exit)
MODULE_LICENSE("GPL");
\
 
 \ /
  Last update: 2007-07-27 05:23    [W:0.047 / U:0.096 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site