/* Module to patch Linux <2.4.23 against brk overflows
 *
 * by Patrick Bernier <pat@TZoNE.ORG> and Phil Vandry <vandry@TZoNE.ORG>
 *
 * Compile with:
 * gcc -O2 -fomit-frame-pointer -I/usr/src/linux-`uname -r`/include -c brk_patch.c
 */

#define MODULE
#define __KERNEL__

#include <linux/config.h>
#include <linux/version.h>
#include <linux/module.h>

#if CONFIG_MODVERSIONS==1 
#define MODVERSIONS
#include <linux/modversions.h>
#endif

#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/linkage.h>
#include <linux/mm.h>
#include <linux/unistd.h>
#include <sys/syscall.h>


MODULE_AUTHOR("Patrick Bernier <pat@TZoNE.ORG> and Phil Vandry <vandry@TZoNE.ORG>");
MODULE_DESCRIPTION("Patches <2.4.23 kernels against brk overflows");
MODULE_LICENSE("GPL");

extern void *sys_call_table[];

static int (*original_brk)(unsigned long);

asmlinkage int hacked_brk(unsigned long brk)
{
	if (brk >= current->mm->end_code && brk - current->mm->start_data > 1<<31) {
		printk(KERN_WARNING "brk_patch blocked brk = %lu, current->mm->start_data = %lu\n", brk, current->mm->start_data);
		return -ENOMEM;
	}
	return (*original_brk)(brk);
}

int init_module(void)
{
	original_brk = sys_call_table[SYS_brk];
	sys_call_table[SYS_brk] = hacked_brk;
	printk(KERN_INFO "brk patch loaded.\n");
	return (0);
}

void cleanup_module(void)
{
	sys_call_table[SYS_brk] = original_brk;
	printk(KERN_INFO "brk patch unloaded.\n");
}
