/* * Author: Tiago Vignatti * 2007 - code under GPL */ #include #include #include #include /* * 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");