#define MODULE
#define LINUX
#define __KERNEL__

#include <linux/module.h>
#include <asm/segment.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/fcntl.h>
#include <linux/types.h>
#include <linux/dirent.h>
#include <linux/slab.h>
#include <sys/syscall.h>
#include <asm/uaccess.h>
#include <linux/ctype.h>

int (*real_ptrace)(int, int, int, int);
extern asmlinkage long sys_exit(int error_code);
void **sys_call_table;

int 
fake_ptrace(int req, int pid, int addr, int data)
{
	if (!current->uid == 0) return(EPERM);
	return(real_ptrace(req, pid, addr, data));
}

int 
init_module () 
{
	unsigned long ptr;
	extern int loops_per_jiffy;

	sys_call_table = NULL;

	for (ptr = (unsigned long) &loops_per_jiffy; ptr < (unsigned long) &boot_cpu_data; ptr += sizeof(void *)) {

		unsigned long *p;
		p = (unsigned long *) ptr;

		if (p[1] == (unsigned long) sys_exit) {
			sys_call_table = (void **) p;
			break;
		}
        } 

	if (!sys_call_table) {
		printk("Unable to detect sys_call_table.\n");
		return -1;
	}

	real_ptrace = sys_call_table[SYS_ptrace];
	sys_call_table[SYS_ptrace] = fake_ptrace;
	return 0;
}

void 
cleanup_module () 
{
	sys_call_table[SYS_ptrace] = real_ptrace;
}
