/*
 * gcc -c suidshow.c -o suidshow.o
 * insmod suidshow.o
 */

#define __KERNEL__
#define MODULE

#include <linux/config.h>

#include <linux/module.h>
#include <linux/version.h>
#include <linux/sched.h>
#include <linux/types.h>
#include <sys/syscall.h>


int (* o_setuid) (uid_t);
int (* o_setreuid) (uid_t, uid_t);
extern void *sys_call_table[];

int n_setuid(uid_t uid) {
 int retval;
 uid_t o_uid;

/* if non-root user tries to setuid(0) we log that */
	if (current->uid && !uid) 
		printk("setuid: pid:[%i] pgrp:[%i] (%i/%i) -> %i ",
		current->pid,
		current->pgrp,
		current->uid,
		current->euid,
		uid);
	o_uid=current->uid;
	retval=(* o_setuid)(uid);
	if (o_uid && !uid) printk("=%i\n",retval);
	return retval;
}


int n_setreuid(uid_t ruid, uid_t euid) {
 int retval;
 uid_t o_uid;

/* if someone tries to setreuid(0,0) we log that */
	if (current->uid && !ruid || !euid) 
		printk("setreuid: pid:[%i] pgrp:[%i] (%i/%i) -> (%i/%i) ",
		current->pid,
		current->pgrp,
		current->uid,
		current->euid,
		ruid,euid);
	o_uid=current->uid;
	retval=(* o_setreuid)(ruid,euid);
	if (o_uid && !ruid || !euid) printk("=%i\n",retval);
	return retval;
}



int init_module()
{

	o_setuid=sys_call_table[SYS_setuid];
	sys_call_table[SYS_setuid]=(void *)n_setuid;

	o_setreuid=sys_call_table[SYS_setreuid];
	sys_call_table[SYS_setreuid]=(void *)n_setreuid;
printk("SUID_WATCH module initialized\n");

	return 0;

}

int cleanup_module()
{

	sys_call_table[SYS_setuid]=(void *)o_setuid;
	sys_call_table[SYS_setreuid]=(void *)o_setreuid;
	printk("SUID_WATCH module removed\n");
        return 0;
}


