*/
#ifndef MEMMON_MM_FAULT_H
#define MEMMON_MM_FAULT_H
/*
* Install pagefault handler
*/
void capture_mmfault(void);
/*
* Uninstall handler
*/
void release_mmfault(void);
#endif // MEMMON_MM_FAULT_H
mm-fault.c
/*
* Pagefault interception.
*/
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include «common.h»
#include «mm-fault.h»
#include «events.h»
#include «watch-pids.h»
/*
* Dirty kernel hack: PF hook that is called every time
* some process PF's for some page that BELONGS to his VMA space.
*/
extern void (*mm_handle_fault_hook) (struct mm_struct *mm, struct vm_area_struct *vma,
void __user *address, pte_t *pte,
pmd_t *pmd, int write_access);
/*
* Pagefault handler
*/
void mm_handle_fault (struct mm_struct *mm, struct vm_area_struct *vma,
void __user *address, pte_t *pte,
pmd_t *pmd, int write_access)
{
struct memmon_event ev = {.pid = current->pid};
pte_t entry = *pte;
/*
* If PF happened due to R/W or U/S access violation, ignore it
*/
if (! pid_present (current->pid) || pte_present(entry))
return;
/*
* Faulted page is either backed by swapfile, some shared executable file
* or no file yet at all (anonymous page)
*/
if (pte_none(entry))
ev.type = ANON_PF;
else if (pte_file(entry))
ev.type = FILE_PF;
else
ev.type = SWAP_PF;
ev.pagefault.addr = address;
ev.pagefault.write = write_access;
put_event(&ev);
}
/*** Exported entries ***/
/*
* Install pagefault handler
*/
void capture_mmfault(void)
{
mm_handle_fault_hook = mm_handle_fault;
}
/*
* Uninstall handler
*/
void release_mmfault(void)
{
mm_handle_fault_hook = NULL;
}
common.h
/*
* Common defines and global data
*/
#ifndef MEMMON_COMMON_H
#define MEMMON_COMMON_H
/* procfs directory name */
#define PROCDIR «memmon»
/*
* procfs directory entry
*/
extern struct proc_dir_entry *procdir;
#endif // MEMMON_COMMON_H
Makefile
#
ifneq ($(KERNELRELEASE),)
obj-m:= memmon.o
memmon-objs:= mmon.o events.o watch-pids.o syscalls.o syscalls-entry.o mm-fault.o
else
KERNELDIR?= /lib/modules/$(shell uname – r)/build
PWD:= $(shell pwd)
all: offsets.h modules
offsets.h: $(KERNELDIR)/include/asm/thread_info.h
$(MAKE) gen-offsets
gen-offsets > offsets.h
$(RM) gen-offsets
clean modules:
$(MAKE) – C $(KERNELDIR) M=$(PWD) $(MAKECMDGOALS)
PHONY: modules.DEFAULT all
endif
diff – arNC 3 linux‑2.6.20.1‑j/kernel/kallsyms.c linux‑2.6.20.1‑a/kernel/kallsyms.c
*** linux‑2.6.20.1‑j/kernel/kallsyms.c 2007–02–20 09:34:32.000000000 +0300
– linux‑2.6.20.1‑a/kernel/kallsyms.c 2007–05–26 22:27:23.000000000 +0400
***************
*** 452,454 ****
– 452,460 –
__initcall (kallsyms_init);
EXPORT_SYMBOL (__print_symbol);
+
+ /* HACK */
+
+ extern void *sys_call_table[];
+
+ EXPORT_SYMBOL_GPL (sys_call_table);
diff – arNC 3 linux‑2.6.20.1‑j/mm/memory.c linux‑2.6.20.1‑a/mm/memory.c
*** linux‑2.6.20.1‑j/mm/memory.c 2007–02–20 09:34:32.000000000 +0300
– linux‑2.6.20.1‑a/mm/memory.c 2007–05–28 22:08:41.000000000 +0400
***************
*** 2369,2374 ****
– 2378,2390 –
return VM_FAULT_MAJOR;
}
+ /* DIRTY HACK */
+ void (*mm_handle_fault_hook) (struct mm_struct *mm,
+ struct vm_area_struct *vma, unsigned long address,
+ pte_t *pte, pmd_t *pmd, int write_access) = NULL;
+
+ EXPORT_SYMBOL_GPL (mm_handle_fault_hook);
+
/*
* These routines also need to handle stuff like marking pages dirty
* and/or accessed for architectures that don't do it in hardware (most
***************
*** 2390,2395 ****
– 2406,2414 –
pte_t old_entry;
spinlock_t *ptl;
+ if (mm_handle_fault_hook)
+ mm_handle_fault_hook (mm, vma, address, pte, pmd, write_access);
+
old_entry = entry = *pte;
if (! pte_present(entry)) {
if (pte_none(entry)) {