/* gcc -I /usr/src/linux/include -c -o rw.{o,c} && insmod ./rw.o */
/* use at your own risk ;> (tak, zamienia miejscami syscalle read i write) */

/*
>> insmodnąć
>>
> Co masz na myśli?

Zlinkować z żywym, pracującym jądrem, relokować co trzeba i wywołać 
konstruktor modułu, czyli funkcję init_module(). W przypadku mojego 
rw.c konstruktor odwołuje się do trzymanej w jądrze tablicy syscalli 
(odwołania do niej w konstruktorze są właśnie relokowane przed 
zlinkowaniem) i zamienia w niej miejscami adresy wywołań read() 
i write() (nie w bibliotece C, z którą każdy program jest linkowany 
podczas uruchamiania przez loader ELF, tylko w samym jądrze), tak że 
transfer danych z deskryptora (pliku, gniazda, rurki, urządzenia lub 
czegokolwiek innego) do pamięci będzie wykonywany wtedy, kiedy program 
będzie chciał wykonać odwrotną operację.
*/

#define MODULE
#define __KERNEL__
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/sched.h>
#include <linux/string.h>
#include <linux/smp_lock.h>
#include <asm/unistd.h>

extern void *sys_call_table[];

int init_module (void)
{
	unsigned long flags;
	void *tmp;

	save_flags (flags);
	cli();
	// sys_call_table[__NR_read] ^= sys_call_table[__NR_write] ^= sys_call_table[__NR_read] ^= sys_call_table[__NR_write];
	tmp = sys_call_table[__NR_read];
	sys_call_table[__NR_read] = sys_call_table[__NR_write];
	sys_call_table[__NR_write] = tmp;
	restore_flags (flags);
	
	return 0;
}

void cleanup_module (void)
{
}
