Hacking Linux Exposed

About
Authors
Contents
Reviews
Foreword
Purchase

Articles
Books
Sourcecode
Tools
Errata

Home

 


(view this code in a separate window)

/*
 * logsetuid kernel module.
 *
 * Log all attempts to run the setuid or setreuid
 * system calls, unless the user is root.
 *
 * To compile:
 *    gcc -o logsetuid.o -c logsetuid.c
 *
 * Then copy logsetuid.o into one of the default
 * insmod directories, such as /lib/modules/misc.
 *
 * Load it into the running kernel with 'insmod logsetuid'.
 *
 * Copyright 2001, Bri Hatch
 * Released under the GPL.  See COPYING file
 * for more information.
 */

#define __KERNEL__
#define MODULE

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

#include <linux/sched.h>
#include <linux/types.h>




int (*real_setuid) (uid_t);
int (*real_setreuid) (uid_t, uid_t);
int new_setuid  (uid_t);
int new_setreuid (uid_t, uid_t);
extern void *sys_call_table[];

int init_module() {

      /* Save a pointer to the old setuid functions */
      real_setuid   = sys_call_table[ SYS_setuid ];
      real_setreuid = sys_call_table[ SYS_setreuid ];

      /* point to our new setuid function in sys_call_table */
      sys_call_table[ SYS_setuid ]   =  (void *)new_setuid;
      sys_call_table[ SYS_setreuid ] =  (void *)new_setreuid;

      printk(KERN_INFO "logsetuid module installed\n");
      return 0;
}

int cleanup_module() {

      /* reset the pointers back to the actual functions */
      sys_call_table[ SYS_setuid ]   = (void *)real_setuid;
      sys_call_table[ SYS_setreuid ] = (void *)real_setreuid;

      printk(KERN_INFO "logsetuid module uninstalled\n");
        return 0;
}


/* The replacement functions */

int new_setuid(uid_t uid) {
      int status;

      /* no warnings if we're already root */
      if ( ! current->uid || uid == current->uid )
            return (*real_setuid)(uid);

      printk("logsetuid: uid:%d euid:%d dest_uid:%d pid:%d proc:%s ",
            current->uid, current->euid, uid,
            current->pid, current->comm);

      printk("status:%s\n",
            (status = (*real_setuid)(uid) ) ? "failed" : "succeeded" );

      return status;
}


int new_setreuid(uid_t uid, uid_t euid) {
      int status;

      /* no warnings if we're already root */
      if ( ! current->uid || (uid == current->uid && euid == current->euid) )
           return (*real_setreuid)(uid,euid);

      printk("logsetreuid: uid:%d euid:%d dest_uid:%d dest_euid:%d "
             "pid:%d proc:%s ", current->uid, current->euid, uid, euid,
             current->pid, current->comm);

      printk("status:%s\n",
            (status = (*real_setreuid)(uid,euid)) ? "failed" : "succeeded");

      return status;
}