diff -Nur linux-2.4.21-40.EL/fs/exec.c linux-2.4.21-40.EL-snare/fs/exec.c
--- linux-2.4.21-40.EL/fs/exec.c	2006-03-16 05:30:51.000000000 +1100
+++ linux-2.4.21-40.EL-snare/fs/exec.c	2006-04-12 02:04:10.000000000 +1000
@@ -37,6 +37,7 @@
 #include <linux/spinlock.h>
 #include <linux/personality.h>
 #include <linux/binfmts.h>
+#include <linux/saudit.h>
 #include <linux/swap.h>
 #include <linux/utsname.h>
 #define __NO_VERSION__
@@ -1092,11 +1093,16 @@
 	int retval;
 	int i;
 
+	char *SNARE_arguments;
+	SNARE_arguments=saudit_copy_argv(argv);
+
 	file = open_exec(filename);
 
 	retval = PTR_ERR(file);
-	if (IS_ERR(file))
+	if (IS_ERR(file)) {
+		saudit_execve((char *)NULL, filename, SNARE_arguments, retval);
 		return retval;
+	}
 
 	bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *);
 	memset(bprm.page, 0, MAX_ARG_PAGES*sizeof(bprm.page[0])); 
@@ -1109,12 +1115,14 @@
 	bprm.exec = 0;
 	if ((bprm.argc = count(argv, bprm.p / sizeof(void *))) < 0) {
 		allow_write_access(file);
+		saudit_execve((char *) NULL, filename, SNARE_arguments, bprm.argc);
 		fput(file);
 		return bprm.argc;
 	}
 
 	if ((bprm.envc = count(envp, bprm.p / sizeof(void *))) < 0) {
 		allow_write_access(file);
+		saudit_execve((char *) NULL, filename, SNARE_arguments, bprm.envc);
 		fput(file);
 		return bprm.envc;
 	}
@@ -1137,15 +1145,19 @@
 		goto out; 
 
 	retval = search_binary_handler(&bprm,regs);
-	if (retval >= 0)
+	if (retval >= 0) {
+		saudit_execve((char *)NULL, filename, SNARE_arguments, retval);
 		/* execve success */
 		return retval;
+	}
 
 out:
 	/* Something went wrong, return the inode and free the argument pages*/
 	allow_write_access(bprm.file);
-	if (bprm.file)
+	if (bprm.file) {
 		fput(bprm.file);
+	}
+	saudit_execve((char *) NULL, filename, SNARE_arguments, retval);
 
 	for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
 		struct page * page = bprm.page[i];
diff -Nur linux-2.4.21-40.EL/fs/namei.c linux-2.4.21-40.EL-snare/fs/namei.c
--- linux-2.4.21-40.EL/fs/namei.c	2006-03-16 05:30:51.000000000 +1100
+++ linux-2.4.21-40.EL-snare/fs/namei.c	2006-04-12 02:04:10.000000000 +1000
@@ -22,6 +22,7 @@
 #include <linux/dnotify.h>
 #include <linux/smp_lock.h>
 #include <linux/personality.h>
+#include <linux/saudit.h>
 
 #include <asm/namei.h>
 #include <asm/uaccess.h>
@@ -1286,15 +1287,20 @@
 	struct dentry * dentry;
 	struct nameidata nd;
 
-	if (S_ISDIR(mode))
+	if (S_ISDIR(mode)) {
+		saudit_mknod((char *)NULL,filename,mode,dev,-EPERM);
 		return -EPERM;
+	}
 	tmp = getname(filename);
-	if (IS_ERR(tmp))
+	if (IS_ERR(tmp)) {
+		saudit_mknod((char *)NULL,(char *)NULL,mode,dev,PTR_ERR(tmp));
 		return PTR_ERR(tmp);
+	}
 
 	error = path_lookup(tmp, LOOKUP_PARENT, &nd);
-	if (error)
+	if (error) {
 		goto out;
+	}
 	dentry = lookup_create(&nd, 0);
 	error = PTR_ERR(dentry);
 
@@ -1319,6 +1325,7 @@
 	up(&nd.dentry->d_inode->i_sem);
 	path_release(&nd);
 out:
+	saudit_mknod(tmp,(char *)NULL,mode,dev,error);
 	putname(tmp);
 
 	return error;
@@ -1357,13 +1364,16 @@
 
 	tmp = getname(pathname);
 	error = PTR_ERR(tmp);
-	if (!IS_ERR(tmp)) {
+	if (IS_ERR(tmp)) {
+		saudit_mkdir((char *)NULL,(char *)NULL,mode & ~current->fs->umask,error);
+	} else {
 		struct dentry *dentry;
 		struct nameidata nd;
 
 		error = path_lookup(tmp, LOOKUP_PARENT, &nd);
-		if (error)
+		if (error) {
 			goto out;
+		}
 		dentry = lookup_create(&nd, 1);
 		error = PTR_ERR(dentry);
 		if (!IS_ERR(dentry)) {
@@ -1375,6 +1385,7 @@
 		up(&nd.dentry->d_inode->i_sem);
 		path_release(&nd);
 out:
+		saudit_mkdir(tmp,(char *)NULL,mode & ~current->fs->umask,error);
 		putname(tmp);
 	}
 
@@ -1455,12 +1466,15 @@
 	struct nameidata nd;
 
 	name = getname(pathname);
-	if(IS_ERR(name))
+	if(IS_ERR(name)) {
+		saudit_rmdir((char *)NULL,(char *)NULL,PTR_ERR(name));
 		return PTR_ERR(name);
+	}
 
 	error = path_lookup(name, LOOKUP_PARENT, &nd);
-	if (error)
+	if (error) {
 		goto exit;
+	}
 
 	switch(nd.last_type) {
 		case LAST_DOTDOT:
@@ -1484,6 +1498,7 @@
 exit1:
 	path_release(&nd);
 exit:
+	saudit_rmdir(name,(char *)NULL,error);
 	putname(name);
 	return error;
 }
@@ -1523,12 +1538,15 @@
 	struct nameidata nd;
 
 	name = getname(pathname);
-	if(IS_ERR(name))
+	if(IS_ERR(name)) {
+		saudit_unlink((char *)NULL,pathname,PTR_ERR(name));
 		return PTR_ERR(name);
+	}
 
 	error = path_lookup(name, LOOKUP_PARENT, &nd);
-	if (error)
+	if (error) {
 		goto exit;
+	}
 	error = -EISDIR;
 	if (nd.last_type != LAST_NORM)
 		goto exit1;
@@ -1547,8 +1565,8 @@
 exit1:
 	path_release(&nd);
 exit:
+	saudit_unlink(name,(char *)NULL,error);
 	putname(name);
-
 	return error;
 
 slashes:
@@ -1589,17 +1607,22 @@
 	char * to;
 
 	from = getname(oldname);
-	if(IS_ERR(from))
+	if(IS_ERR(from)) {
+		saudit_symlink((char *)NULL,(char *)NULL,(char *)NULL,newname,PTR_ERR(from));
 		return PTR_ERR(from);
+	}
 	to = getname(newname);
 	error = PTR_ERR(to);
-	if (!IS_ERR(to)) {
+	if(IS_ERR(to)) {
+		saudit_symlink(from,(char *)NULL,(char *)NULL,(char *)NULL,PTR_ERR(to));
+	} else {
 		struct dentry *dentry;
 		struct nameidata nd;
 
 		error = path_lookup(to, LOOKUP_PARENT, &nd);
-		if (error)
+		if (error) {
 			goto out;
+		}
 		dentry = lookup_create(&nd, 0);
 		error = PTR_ERR(dentry);
 		if (!IS_ERR(dentry)) {
@@ -1609,6 +1632,7 @@
 		up(&nd.dentry->d_inode->i_sem);
 		path_release(&nd);
 out:
+		saudit_symlink(from,(char *)NULL,to,(char *)NULL,error);
 		putname(to);
 	}
 	putname(from);
@@ -1671,19 +1695,24 @@
 
 	to = getname(newname);
 	error = PTR_ERR(to);
-	if (!IS_ERR(to)) {
+	if (IS_ERR(to)) {
+		saudit_link((char *)NULL,oldname,(char *)NULL,(char *)NULL,error);
+	} else {
 		struct dentry *new_dentry;
 		struct nameidata nd, old_nd;
 
 		error = __user_walk(oldname, LOOKUP_POSITIVE, &old_nd);
-		if (error)
+		if (error) {
 			goto exit;
+		}
 		error = path_lookup(to, LOOKUP_PARENT, &nd);
-		if (error)
+		if (error) {
 			goto out;
+		}
 		error = -EXDEV;
-		if (old_nd.mnt != nd.mnt)
+		if (old_nd.mnt != nd.mnt) {
 			goto out_release;
+		}
 		new_dentry = lookup_create(&nd, 0);
 		error = PTR_ERR(new_dentry);
 		if (!IS_ERR(new_dentry)) {
@@ -1696,6 +1725,7 @@
 out:
 		path_release(&old_nd);
 exit:
+		saudit_link((char *)NULL,oldname,to,(char *)NULL,error);
 		putname(to);
 	}
 	return error;
@@ -1943,13 +1973,18 @@
 	char * to;
 
 	from = getname(oldname);
-	if(IS_ERR(from))
+	if(IS_ERR(from)) {
+		saudit_rename((char *)NULL,(char *)NULL,(char *)NULL,newname,PTR_ERR(from));
 		return PTR_ERR(from);
+	}
 	to = getname(newname);
 	error = PTR_ERR(to);
 	if (!IS_ERR(to)) {
 		error = do_rename(from,to);
+		saudit_rename(from,(char *)NULL,to,(char *)NULL,error);
 		putname(to);
+	} else {
+		saudit_rename(from,(char *)NULL,(char *)NULL,(char *)NULL,error);
 	}
 	putname(from);
 	return error;
diff -Nur linux-2.4.21-40.EL/fs/namespace.c linux-2.4.21-40.EL-snare/fs/namespace.c
--- linux-2.4.21-40.EL/fs/namespace.c	2006-03-16 05:30:45.000000000 +1100
+++ linux-2.4.21-40.EL-snare/fs/namespace.c	2006-04-12 02:04:10.000000000 +1000
@@ -21,6 +21,8 @@
 #include <linux/seq_file.h>
 #include <linux/namespace.h>
 
+#include <linux/saudit.h>
+
 struct vfsmount *do_kern_mount(const char *type, int flags, char *name, void *data);
 int do_remount_sb(struct super_block *sb, int flags, void * data);
 void kill_super(struct super_block *sb);
@@ -367,8 +369,9 @@
 	int retval;
 
 	retval = __user_walk(name, LOOKUP_POSITIVE|LOOKUP_FOLLOW, &nd);
-	if (retval)
+	if (retval) {
 		goto out;
+	}
 	retval = -EINVAL;
 	if (nd.dentry != nd.mnt->mnt_root)
 		goto dput_and_out;
@@ -383,6 +386,7 @@
 dput_and_out:
 	path_release(&nd);
 out:
+	saudit_umount((char *)NULL,name,flags,retval);
 	return retval;
 }
 
@@ -832,18 +836,25 @@
 	unsigned long dev_page;
 	char *dir_page;
 
+
 	retval = copy_mount_options (type, &type_page);
-	if (retval < 0)
+	if (retval < 0) {
+		saudit_mount((char *)NULL,dev_name,(char *)NULL,dir_name,flags,retval);
 		return retval;
+	}
 
 	dir_page = getname(dir_name);
 	retval = PTR_ERR(dir_page);
-	if (IS_ERR(dir_page))
+	if (IS_ERR(dir_page)) {
+		saudit_mount((char *)NULL,dev_name,(char *)NULL,dir_name,flags,retval);
 		goto out1;
+	}
 
 	retval = copy_mount_options (dev_name, &dev_page);
-	if (retval < 0)
+	if (retval < 0) {
+		saudit_mount((char *)NULL,dev_name,dir_page,(char *)NULL,flags,retval);
 		goto out2;
+	}
 
 	retval = copy_mount_options (data, &data_page);
 	if (retval < 0)
@@ -856,6 +867,7 @@
 	free_page(data_page);
 
 out3:
+	saudit_mount((char *)dev_page,(char *)NULL,dir_page,(char *)NULL,flags,retval);
 	free_page(dev_page);
 out2:
 	putname(dir_page);
diff -Nur linux-2.4.21-40.EL/fs/open.c linux-2.4.21-40.EL-snare/fs/open.c
--- linux-2.4.21-40.EL/fs/open.c	2006-03-16 05:30:51.000000000 +1100
+++ linux-2.4.21-40.EL-snare/fs/open.c	2006-04-12 02:04:10.000000000 +1000
@@ -15,6 +15,7 @@
 #include <linux/slab.h>
 #include <linux/tty.h>
 #include <linux/iobuf.h>
+#include <linux/saudit.h>
 #include <linux/pagemap.h>
 
 #include <asm/uaccess.h>
@@ -197,12 +198,16 @@
 	int error;
 
 	error = -EINVAL;
-	if (length < 0)	/* sorry, but loff_t says... */
+	if (length < 0) {	/* sorry, but loff_t says... */
+		saudit_truncate((char *)NULL,path,length,error);
 		goto out;
+	}
 
 	error = user_path_walk(path, &nd);
-	if (error)
+	if (error) {
+		saudit_truncate((char *)NULL,path,length,error);
 		goto out;
+	}
 	inode = nd.dentry->d_inode;
 
 	/* For directories it's -EISDIR, for other non-regulars - -EINVAL */
@@ -245,6 +250,7 @@
 	put_write_access(inode);
 
 dput_and_out:
+	saudit_truncate((char *)NULL,path,length,error);
 	path_release(&nd);
 out:
 	return error;
@@ -264,12 +270,14 @@
 	int error;
 
 	error = -EINVAL;
-	if (length < 0)
+	if (length < 0) {
 		goto out;
+	}
 	error = -EBADF;
 	file = fget(fd);
-	if (!file)
+	if (!file) {
 		goto out;
+	}
 
 	/* explicitly opened as large or we are on 64-bit box */
 	if (file->f_flags & O_LARGEFILE)
@@ -277,6 +285,7 @@
 
 	dentry = file->f_dentry;
 	inode = dentry->d_inode;
+
 	error = -EINVAL;
 	if (!S_ISREG(inode->i_mode) || !(file->f_mode & FMODE_WRITE))
 		goto out_putf;
@@ -514,10 +523,13 @@
 	int error;
 	struct nameidata nd;
 
+
 	error = __user_walk(filename, LOOKUP_POSITIVE | LOOKUP_FOLLOW |
 		      LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd);
-	if (error)
+	if (error) {
+		saudit_chroot((char *)NULL,filename,error);
 		goto out;
+	}
 
 	error = permission(nd.dentry->d_inode,MAY_EXEC);
 	if (error)
@@ -531,6 +543,7 @@
 	set_fs_altroot();
 	error = 0;
 dput_and_out:
+	saudit_chroot((char *)NULL,filename,error);
 	path_release(&nd);
 out:
 	return error;
@@ -545,8 +558,9 @@
 	struct iattr newattrs;
 
 	file = fget(fd);
-	if (!file)
+	if (!file) {
 		goto out;
+	}
 
 	dentry = file->f_dentry;
 	inode = dentry->d_inode;
@@ -576,9 +590,12 @@
 	int error;
 	struct iattr newattrs;
 
+
 	error = user_path_walk(filename, &nd);
-	if (error)
+	if (error) {
+		saudit_chmod((char *)NULL,filename,mode,error);
 		goto out;
+	}
 	inode = nd.dentry->d_inode;
 
 	error = -EROFS;
@@ -596,6 +613,7 @@
 	error = notify_change(nd.dentry, &newattrs);
 
 dput_and_out:
+	saudit_chmod((char *)NULL,filename,mode,error);
 	path_release(&nd);
 out:
 	return error;
@@ -671,6 +689,8 @@
 		error = chown_common(nd.dentry, user, group);
 		path_release(&nd);
 	}
+
+	saudit_chown((char *)NULL,filename,user,group,error);
 	return error;
 }
 
@@ -684,6 +704,8 @@
 		error = chown_common(nd.dentry, user, group);
 		path_release(&nd);
 	}
+
+	saudit_chown((char *)NULL,filename,user,group,error);
 	return error;
 }
 
diff -Nur linux-2.4.21-40.EL/include/linux/saudit.h linux-2.4.21-40.EL-snare/include/linux/saudit.h
--- linux-2.4.21-40.EL/include/linux/saudit.h	1970-01-01 10:00:00.000000000 +1000
+++ linux-2.4.21-40.EL-snare/include/linux/saudit.h	2006-04-12 02:04:10.000000000 +1000
@@ -0,0 +1,460 @@
+/*
+ * linux/audit/saudit.h
+ *
+ * Original:
+ * Copyright (c) 1999-2004 InterSect Alliance Pty Ltd 
+ *                         - http://www.intersectalliance.com/
+ * Additions:
+ * Copyright (c) 2004 Silicon Graphics, Inc. All rights reserved.
+ */
+
+#ifndef __C2_AUDIT_H
+#define __C2_AUDIT_H
+
+// I was going to use __NR_xxx, but we need audit events for events that
+// may NOT be system calls specifically (eg: login, connect/accept)
+#define AUDIT_open		1
+#define AUDIT_mkdir		2
+#define AUDIT_unlink		3
+#define AUDIT_rmdir		4
+#define AUDIT_chown		5
+#define AUDIT_chmod		6
+#define AUDIT_symlink		7
+#define AUDIT_link		8
+#define AUDIT_rename		9
+#define AUDIT_mknod		10
+#define AUDIT_truncate		11
+#define AUDIT_ftruncate		12
+#define AUDIT_chroot		13
+#define AUDIT_execve		14
+#define AUDIT_exit		15
+#define AUDIT_setuid		16
+#define AUDIT_setreuid		17
+#define AUDIT_setresuid		18
+#define AUDIT_setgid		19
+#define AUDIT_setregid		20
+#define AUDIT_setresgid		21
+#define AUDIT_create_module	22
+#define AUDIT_delete_module	23
+#define AUDIT_reboot		24
+#define AUDIT_connect		25
+#define AUDIT_accept		26
+#define AUDIT_mount		27
+#define AUDIT_umount		28
+#define AUDIT_fork		29
+
+// Size of the bitmask array that we need to store the information
+// associated with whether an audit event is currently turned on.
+#define MAXAUDIT			AUDIT_fork
+
+// ioctl modes - note that '1' doesnt seem to work. Added 10.
+#define AUDIT_STOP			10  // stop auditing
+#define AUDIT_START			11  // start auditing
+#define AUDIT_INFO			12  // Give me a list of events
+					    // currently active, and other
+					    // info such as the process ID
+#define AUDIT_LOSTEVENTS		13
+#define AUDIT_FLUSH			14  // Stop all events.
+#define AUDIT_EVENT_ON			15  // Turn on a selected event
+#define AUDIT_EVENT_OFF			16  // Turn off a selected event
+#define AUDIT_DELIVERY 			17  // Do we want to guarantee audit event delivery
+#define AUDIT_TOTALEVENTS		18  // How many events have been received this session?
+
+#define AUDIT_HIGHWATERMARK_MEM		19  // Set the High Water Mark memory usage
+#define AUDIT_HIGHWATERMARK_PER		20  // Set the High Water Mark memory as a percentage mem.
+#define AUDIT_HIGHWATERMARK_PAUSE	21  // Set the High Water Mark pause percetage 
+#define AUDIT_LOWWATERMARK_PAUSE        22  // Set the Low Water Mark to resume
+#define AUDIT_HIGHWATERMARK_NICE        23  // Set the High Water Mark to change nice value
+#define AUDIT_LOWWATERMARK_NICE         24  // Set the Low Water Mark to restore nice value
+#define AUDIT_HIGHWATER_NICE_VAL	25  // The nice value to change the audit daemon to
+
+
+
+
+
+#define AUDIT_CLASS_NONE	0
+#define AUDIT_CLASS_IO		1	// Input/output (file opens)
+#define AUDIT_CLASS_PC		2	// Process Control
+#define AUDIT_CLASS_EXEC	3	// Execution
+#define AUDIT_CLASS_NET		4	// Network related
+#define AUDIT_CLASS_ADMIN	5	// Administrative events
+#define AUDIT_CLASS_CH		6	// CHMOD event. Might not use this for anything else.
+#define AUDIT_CLASS_CP		7	// Where more than one pathname is required
+#define AUDIT_CLASS_SU		8	// SetUID
+#define AUDIT_CLASS_AD		9	// Admin such as create/delete module
+
+#define SNAREAUDIT_MAJOR_VERSION 0
+#define SNAREAUDIT_MINOR_VERSION 9
+#define SNAREAUDIT_PATCH_VERSION 7
+
+
+// /proc entry
+#define AUDITDEV_NAME  "snare"			// device name in /dev and /proc/devices
+#define AUDITINFO_NAME	"snareinfo"		// Information about the process
+#define AUDITDEV_FILE  "/proc/snare"		// full file name
+#define AUDITINFO_FILE "/proc/snareinfo"	// Information about the process.
+#define MAX_PATH   512				// NOTE: will migrgate this to PATH_MAX eventually
+#define MAXCOMMAND 25
+
+
+// This contains the details that are common to ALL audit events.
+typedef struct
+{
+	unsigned short event_class;		// event class. Each class has a predictable format for tokens.
+	unsigned short event_id;		// number of the event
+	unsigned short event_size;		// size of the event struct - don't include header
+						// since it's always the same
+	struct timeval time;			// time
+
+	int user_id;				// User ID
+	int euser_id;				// Effective User ID
+	int group_id;				// Group ID
+	int egroup_id;				// Effective Group ID
+
+	int returncode;				// Make sure that this is big enough to contain the largest returncode.
+
+	pid_t pid;				// process ID.
+	pid_t ppid;				// Parent process ID.
+	char processname[MAXCOMMAND];	// Same as in /usr/include/linux/sched.h for current->comm
+} header_token;
+
+typedef struct
+{
+	char path[MAX_PATH];
+} path_token;
+
+typedef struct
+{
+	int mode;			// How the file was attempted to be opened or created
+	unsigned long	createmode;	// Flags associated with the file creation. Ulong for mknod.
+} attributes_token;
+
+typedef struct
+{
+	int owner;			// new owner of a file - was uid_t, but these are different between kernel and user.
+	int group;			// new group of a file
+} owner_token;
+
+typedef struct
+{
+	char args[MAX_PATH];		// Should really allocate more here. Whats is the max command line size?
+} execargs_token;
+
+// System calls like setuid
+typedef struct
+{
+	int id;		// uid/gid/euid depending on the call
+	int rid;	// ruid/rgid
+	int sid;	// suid/sgid
+} target_token;
+
+// Network connections
+typedef struct
+{
+	char src_ip[40];	// String containing source dotted ip address - 40 bytes, for IPv6
+	int src_port;		// Source port
+	char dst_ip[40];	// String containing destination dotted ip address - 40 bytes, for IPv6
+	int dst_port;		// Destination port
+	int protocol;		// Protocol type - IPPROTO_UDP or IPPROTO_TCP
+} connection_token;
+
+
+
+// Now for the audit event classes
+
+// Just a bare class with the minimal data
+// note that this will mean that EVERY class must start with header_token
+typedef struct
+{
+	header_token	t_header;
+} null_class;
+	
+
+// NOTE: ANY CLASS STRUCTURE SHOULD HAVE THE RETURN TOKEN AS THE SECOND ELEMENT.
+// SEE AUDITD FOR MORE INFO.
+// io - reads/writes
+typedef struct
+{
+	header_token		t_header;
+	path_token		t_path;
+	path_token		t_pwd;	// Working directory
+	attributes_token	t_attributes;
+} io_class;
+
+typedef struct
+{
+	header_token		t_header;
+	path_token		t_path;
+	path_token		t_pwd;	// Working directory
+	owner_token		t_owner;
+} ch_class;
+
+typedef struct
+{
+	header_token		t_header;
+	path_token		t_path;
+	path_token		t_pwd;	// Working directory
+	execargs_token		t_execargs;
+	// environment variables too?
+} ex_class;
+
+typedef struct
+{
+	header_token		t_header;
+} pc_class;
+
+// copy one file to another (amongst others - eg: symlink)
+typedef struct
+{
+	header_token		t_header;
+	path_token		t_sourcepath;
+	path_token		t_pwd;	// Working directory
+	path_token		t_destpath;
+} cp_class;
+
+typedef struct
+{
+	header_token		t_header;
+	target_token		t_target;	// target UID or GID.. I really only need a single value here.
+} su_class;
+
+typedef struct
+{
+	header_token		t_header;
+	connection_token	t_connection;	
+} nt_class;	// Network
+
+typedef struct
+{
+	header_token		t_header;
+	path_token		t_name;		// Name of the module loaded / removed
+} ad_class;	// General Administrative
+
+struct _auditnode
+{
+	void * location;	// Location in RAM of the allocated chunk
+	int size;		// Size of the chunk
+	struct _auditnode *next;	// Next node in the series.
+};
+
+typedef struct _auditnode AuditNode;
+
+
+#ifdef __KERNEL__
+#include <linux/sched.h>
+
+int _audit_mknod(const char * kfile, const char * ufile, int mode, dev_t dev, int retval);
+int _audit_execve(const char * kfilename, const char * ufilename, char *arguments, int retval);
+// _Add this back in..
+// _char *audit_copy_exec_strings(char **argv);
+int _audit_exit(int retval);
+int _audit_fork(int retval);
+int _audit_open(const char * kfile,const char *ufile, int flags, int mode, int retval);
+int _audit_mkdir(const char * kfile, const char * ufile, int mode, int retval);
+int _audit_unlink(const char * kfile,const char * ufile, int retval);
+int _audit_rmdir(const char * kfile, const char * ufile, int retval);
+int _audit_chown(const char * kfile,const char * ufile, uid_t user, gid_t group, int retval);
+int _audit_chmod(const char * kfile, const char * ufile, mode_t mode, int retval);
+int _audit_symlink(const char * kfrom,const char * ufrom, const char * kto,const char * uto, int retval);
+int _audit_link(const char * kfrom,const char * ufrom, const char * kto,const char * uto, int retval);
+int _audit_rename(const char * kfrom,const char * ufrom, const char * kto, const char * uto, int retval);
+int _audit_truncate(const char * kfile,const char * ufile, loff_t length, int retval);
+int _audit_ftruncate(const char * file, loff_t length, int retval);
+int _audit_chroot(const char * kfile, const char * ufile, int retval);
+int _audit_setuid(uid_t uid, int retval);
+int _audit_setreuid(uid_t ruid, uid_t euid, int retval);
+int _audit_setresuid(uid_t ruid, uid_t euid, uid_t suid, int retval);
+int _audit_setgid(gid_t gid, int retval);
+int _audit_setregid(gid_t rgid, gid_t egid, int retval);
+int _audit_setresgid(gid_t rgid, gid_t egid, gid_t sgid, int retval);
+int _audit_create_module(const char * kname, const char * uname, int retval);
+int _audit_delete_module(const char * kname, const char * uname, int retval);
+int _audit_reboot(int magic1, int magic2, unsigned int cmd, void * arg, int retval);
+int _audit_connect(int sockfd, struct sockaddr *serv_addr, int addrlen, int retval);
+int _audit_accept(int sockfd, struct sockaddr *serv_addr, int *addrlen, int retval);
+int _audit_mount(const char *kdev_name, const char *udev_name, const char *kdir_name, const char *udir_name, unsigned long flags, int retval);
+int _audit_umount(const char *kname, const char *uname, int flags, int retval);
+
+void audit_init(void);
+char * audit_copy_argv(char **argv);
+
+extern int AUDIT_IS_RUNNING;
+
+// Inline routines in order to speed things up a little.
+static inline int saudit_mknod(const char * kfile, const char * ufile, int mode, dev_t dev, int retval) {
+	if (unlikely(AUDIT_IS_RUNNING))
+		return (_audit_mknod(kfile,ufile,mode,dev,retval));
+	else
+		return(0);
+}
+static inline int saudit_execve(const char * kfilename, const char * ufilename, char *arguments, int retval) {
+	if (unlikely(AUDIT_IS_RUNNING))
+		return (_audit_execve(kfilename,ufilename,arguments,retval));
+	else
+		return(0);
+}
+static inline int saudit_exit(int retval) {
+	if (unlikely(AUDIT_IS_RUNNING))
+		return (_audit_exit(retval));
+	else
+		return(0);
+}
+static inline int saudit_fork(int retval) {
+	if (unlikely(AUDIT_IS_RUNNING))
+		return (_audit_fork(retval));
+	else
+		return(0);
+}
+static inline int saudit_open(const char * kfile,const char *ufile, int flags, int mode, int retval) {
+	if (unlikely(AUDIT_IS_RUNNING))
+		return (_audit_open(kfile,ufile,flags,mode,retval));
+	else
+		return(0);
+}
+static inline int saudit_mkdir(const char * kfile, const char * ufile, int mode, int retval) {
+	if (unlikely(AUDIT_IS_RUNNING))
+		return (_audit_mkdir(kfile,ufile,mode,retval));
+	else
+		return(0);
+}
+static inline int saudit_unlink(const char * kfile,const char * ufile, int retval) {
+	if (unlikely(AUDIT_IS_RUNNING))
+		return (_audit_unlink(kfile,ufile,retval));
+	else
+		return(0);
+}
+static inline int saudit_rmdir(const char * kfile, const char * ufile, int retval) {
+	if (unlikely(AUDIT_IS_RUNNING))
+		return (_audit_rmdir(kfile,ufile,retval));
+	else
+		return(0);
+}
+static inline int saudit_chown(const char * kfile,const char * ufile, uid_t user, gid_t group, int retval) {
+	if (unlikely(AUDIT_IS_RUNNING))
+		return (_audit_chown(kfile,ufile,user,group,retval));
+	else
+		return(0);
+}
+static inline int saudit_chmod(const char * kfile, const char * ufile, mode_t mode, int retval) {
+	if (unlikely(AUDIT_IS_RUNNING))
+		return (_audit_chmod(kfile,ufile,mode,retval));
+	else
+		return(0);
+}
+static inline int saudit_symlink(const char * kfrom,const char * ufrom, const char * kto,const char * uto, int retval) {
+	if (unlikely(AUDIT_IS_RUNNING))
+		return (_audit_symlink(kfrom,ufrom,kto,uto,retval));
+	else
+		return(0);
+}
+static inline int saudit_link(const char * kfrom,const char * ufrom, const char * kto,const char * uto, int retval) {
+	if (unlikely(AUDIT_IS_RUNNING))
+		return (_audit_link(kfrom,ufrom,kto,uto,retval));
+	else
+		return(0);
+}
+static inline int saudit_rename(const char * kfrom,const char * ufrom, const char * kto, const char * uto, int retval) {
+	if (unlikely(AUDIT_IS_RUNNING))
+		return (_audit_rename(kfrom,ufrom,kto,uto,retval));
+	else
+		return(0);
+}
+static inline int saudit_truncate(const char * kfile,const char * ufile, loff_t length, int retval) {
+	if (unlikely(AUDIT_IS_RUNNING))
+		return (_audit_truncate(kfile,ufile,length,retval));
+	else
+		return(0);
+}
+static inline int saudit_ftruncate(const char * file, loff_t length, int retval) {
+	if (unlikely(AUDIT_IS_RUNNING))
+		return (_audit_ftruncate(file,length,retval));
+	else
+		return(0);
+}
+static inline int saudit_chroot(const char * kfile, const char * ufile, int retval) {
+	if (unlikely(AUDIT_IS_RUNNING))
+		return (_audit_chroot(kfile,ufile,retval));
+	else
+		return(0);
+}
+static inline int saudit_setuid(uid_t uid, int retval) {
+	if (unlikely(AUDIT_IS_RUNNING))
+		return (_audit_setuid(uid,retval));
+	else
+		return(0);
+}
+static inline int saudit_setreuid(uid_t ruid, uid_t euid, int retval) {
+	if (unlikely(AUDIT_IS_RUNNING))
+		return (_audit_setreuid(ruid,euid,retval));
+	else
+		return(0);
+}
+static inline int saudit_setresuid(uid_t ruid, uid_t euid, uid_t suid, int retval) {
+	if (unlikely(AUDIT_IS_RUNNING))
+		return (_audit_setresuid(ruid,euid,suid,retval));
+	else
+		return(0);
+}
+static inline int saudit_setgid(gid_t gid, int retval) {
+	if (unlikely(AUDIT_IS_RUNNING))
+		return (_audit_setgid(gid,retval));
+	else
+		return(0);
+}
+static inline int saudit_setregid(gid_t rgid, gid_t egid, int retval) {
+	if (unlikely(AUDIT_IS_RUNNING))
+		return (_audit_setregid(rgid,egid,retval));
+	else
+		return(0);
+}
+static inline int saudit_setresgid(gid_t rgid, gid_t egid, gid_t sgid, int retval) {
+	if (unlikely(AUDIT_IS_RUNNING))
+		return (_audit_setresgid(rgid,egid,sgid,retval));
+	else
+		return(0);
+}
+static inline int saudit_create_module(const char * kname, const char * uname, int retval) {
+	if (unlikely(AUDIT_IS_RUNNING))
+		return (_audit_create_module(kname,uname,retval));
+	else
+		return(0);
+}
+static inline int saudit_delete_module(const char * kname, const char * uname, int retval) {
+	if (unlikely(AUDIT_IS_RUNNING))
+		return (_audit_delete_module(kname,uname,retval));
+	else
+		return(0);
+}
+static inline int saudit_reboot(int magic1, int magic2, unsigned int cmd, void * arg, int retval) {
+	if (unlikely(AUDIT_IS_RUNNING))
+		return (_audit_reboot(magic1,magic2,cmd,arg,retval));
+	else
+		return(0);
+}
+static inline int saudit_connect(int sockfd, struct sockaddr *serv_addr, int addrlen, int retval) {
+	if (unlikely(AUDIT_IS_RUNNING))
+		return (_audit_connect(sockfd,serv_addr,addrlen,retval));
+	else
+		return(0);
+}
+static inline int saudit_accept(int sockfd, struct sockaddr *serv_addr, int *addrlen, int retval) {
+	if (unlikely(AUDIT_IS_RUNNING))
+		return (_audit_accept(sockfd,serv_addr,addrlen,retval));
+	else
+		return(0);
+}
+static inline int saudit_mount(const char *kdev_name, const char *udev_name, const char *kdir_name, const char *udir_name, unsigned long flags, int retval) {
+	if (unlikely(AUDIT_IS_RUNNING))
+		return (_audit_mount(kdev_name,udev_name,kdir_name,udir_name,flags,retval));
+	else
+		return(0);
+}
+static inline int saudit_umount(const char *kname, const char *uname, int flags, int retval) {
+	if (unlikely(AUDIT_IS_RUNNING))
+		return (_audit_umount(kname,uname,flags,retval));
+	else
+		return(0);
+}
+
+#endif /* __KERNEL__ */
+#endif /* __C2_AUDIT_H */
diff -Nur linux-2.4.21-40.EL/include/linux/sched.h linux-2.4.21-40.EL-snare/include/linux/sched.h
--- linux-2.4.21-40.EL/include/linux/sched.h	2006-03-16 05:31:54.000000000 +1100
+++ linux-2.4.21-40.EL-snare/include/linux/sched.h	2006-04-12 02:04:10.000000000 +1000
@@ -575,6 +575,9 @@
 /* journalling filesystem info */
 	void *journal_info;
 
+ /* Audit record pointer */
+        void *saudit_record;
+
 	unsigned long ptrace_message;
 	siginfo_t *last_siginfo; /* For ptrace use.  */
 
diff -Nur linux-2.4.21-40.EL/init/main.c linux-2.4.21-40.EL-snare/init/main.c
--- linux-2.4.21-40.EL/init/main.c	2006-03-16 05:30:50.000000000 +1100
+++ linux-2.4.21-40.EL-snare/init/main.c	2006-04-12 02:04:10.000000000 +1000
@@ -28,6 +28,7 @@
 #include <linux/bootmem.h>
 #include <linux/file.h>
 #include <linux/tty.h>
+#include <linux/saudit.h>
 #include <linux/profile.h>
 #include <linux/process_timing.h>
 
@@ -435,6 +436,9 @@
 #if defined(CONFIG_SYSVIPC)
 	ipc_init();
 #endif
+
+	saudit_init();
+
 	check_bugs();
 
 	printk("POSIX conformance testing by UNIFIX\n");
diff -Nur linux-2.4.21-40.EL/kernel/exit.c linux-2.4.21-40.EL-snare/kernel/exit.c
--- linux-2.4.21-40.EL/kernel/exit.c	2006-03-16 05:30:51.000000000 +1100
+++ linux-2.4.21-40.EL-snare/kernel/exit.c	2006-04-12 02:04:10.000000000 +1000
@@ -14,6 +14,7 @@
 #include <linux/personality.h>
 #include <linux/tty.h>
 #include <linux/namespace.h>
+#include <linux/saudit.h>
 #include <linux/acct.h>
 #include <linux/audit.h>
 #include <linux/file.h>
@@ -743,6 +744,7 @@
 
 asmlinkage void sys_exit(int error_code)
 {
+	saudit_exit(error_code);
 	do_exit((error_code&0xff)<<8);
 }
 
diff -Nur linux-2.4.21-40.EL/kernel/fork.c linux-2.4.21-40.EL-snare/kernel/fork.c
--- linux-2.4.21-40.EL/kernel/fork.c	2006-03-16 05:30:51.000000000 +1100
+++ linux-2.4.21-40.EL-snare/kernel/fork.c	2006-04-12 02:04:10.000000000 +1000
@@ -22,6 +22,7 @@
 #include <linux/namespace.h>
 #include <linux/personality.h>
 #include <linux/compiler.h>
+#include <linux/saudit.h>
 #include <linux/mman.h>
 #include <linux/file.h>
 #include <linux/binfmts.h>
@@ -757,27 +758,38 @@
 			         int *child_tidptr)
 {
 	int retval;
+	int auditretval=0;
 	struct task_struct *p = NULL;
 
-	if ((clone_flags & (CLONE_NEWNS|CLONE_FS)) == (CLONE_NEWNS|CLONE_FS))
-		return ERR_PTR(-EINVAL);
+	if ((clone_flags & (CLONE_NEWNS|CLONE_FS)) == (CLONE_NEWNS|CLONE_FS)) {
+	  saudit_fork(-1);
+	  return ERR_PTR(-EINVAL);
+	}
 
 	/*
 	 * Thread groups must share signals as well, and detached threads
 	 * can only be started up within the thread group.
 	 */
-	if ((clone_flags & CLONE_THREAD) && !(clone_flags & CLONE_SIGHAND))
+	if ((clone_flags & CLONE_THREAD) && !(clone_flags & CLONE_SIGHAND)) {
+	  	saudit_fork(-1);
 		return ERR_PTR(-EINVAL);
-	if ((clone_flags & CLONE_DETACHED) && !(clone_flags & CLONE_THREAD))
+	}
+	if ((clone_flags & CLONE_DETACHED) && !(clone_flags & CLONE_THREAD)) {
+	  	saudit_fork(-1);
 		return ERR_PTR(-EINVAL);
-	if (!(clone_flags & CLONE_DETACHED) && (clone_flags & CLONE_THREAD))
+	}
+	if (!(clone_flags & CLONE_DETACHED) && (clone_flags & CLONE_THREAD)) {
+	  	saudit_fork(-1);
 		return ERR_PTR(-EINVAL);
+	}
 
 	retval = -ENOMEM;
 	p = dup_task_struct(current);
 	if (!p)
 		goto fork_out;
 
+	p->saudit_record = NULL;
+
 	p->tux_info = NULL;
 
 	retval = -EAGAIN;
@@ -1017,6 +1029,11 @@
 	retval = 0;
 
 fork_out:
+	if (auditretval == -1)
+	  saudit_fork(-1);
+	else
+	  saudit_fork(p->pid);
+
 	if (retval)
 		return ERR_PTR(retval);
 	return p;
@@ -1047,6 +1064,7 @@
 	p->state = TASK_ZOMBIE; /* debug */
 	atomic_dec(&p->usage);
 	put_task_struct(p);
+	auditretval = -1;
 	goto fork_out;
 }
 
diff -Nur linux-2.4.21-40.EL/kernel/module.c linux-2.4.21-40.EL-snare/kernel/module.c
--- linux-2.4.21-40.EL/kernel/module.c	2006-03-16 05:30:51.000000000 +1100
+++ linux-2.4.21-40.EL-snare/kernel/module.c	2006-04-12 02:04:10.000000000 +1000
@@ -11,6 +11,7 @@
 #include <linux/slab.h>
 #include <linux/kmod.h>
 #include <linux/seq_file.h>
+#include <linux/saudit.h>
 
 /*
  * Originally by Anonymous (as far as I know...)
@@ -331,11 +332,15 @@
 	struct module *mod;
 	unsigned long flags;
 
-	if (!capable(CAP_SYS_MODULE))
+	if (!capable(CAP_SYS_MODULE)) {
+		saudit_create_module((char *)NULL,name_user,-EPERM);
 		return -EPERM;
+	}
+
 	lock_kernel();
 	if ((namelen = get_mod_name(name_user, &name)) < 0) {
 		error = namelen;
+		saudit_create_module((char *)NULL,name_user,error);
 		goto err0;
 	}
 	if (size < sizeof(struct module)+namelen+1) {
@@ -371,8 +376,11 @@
 	spin_unlock_irqrestore(&modlist_lock, flags);
 
 	error = (long) mod;
+	saudit_create_module(name,(char *)NULL,error);
+	put_mod_name(name);
 	goto err0;
 err1:
+	saudit_create_module(name,(char *)NULL,error);
 	put_mod_name(name);
 err0:
 	unlock_kernel();
@@ -660,13 +668,17 @@
 	long error;
 	int something_changed;
 
-	if (!capable(CAP_SYS_MODULE))
+
+	if (!capable(CAP_SYS_MODULE)) {
+		saudit_delete_module((char *)NULL,name_user,-EPERM);
 		return -EPERM;
+	}
 
 	lock_kernel();
 	if (name_user) {
-		if ((error = get_mod_name(name_user, &name)) < 0)
+		if ((error = get_mod_name(name_user, &name)) < 0) {
 			goto out;
+		}
 		error = -ENOENT;
 		if ((mod = find_module(name)) == NULL) {
 			put_mod_name(name);
@@ -674,8 +686,9 @@
 		}
 		put_mod_name(name);
 		error = -EBUSY;
-		if (mod->refs != NULL)
+		if (mod->refs != NULL) {
 			goto out;
+		}
 
 		spin_lock(&unload_lock);
 		if (!__MOD_IN_USE(mod)) {
@@ -726,6 +739,8 @@
 	error = 0;
 out:
 	unlock_kernel();
+
+	saudit_delete_module((char *)NULL,name_user,error);
 	return error;
 }
 
diff -Nur linux-2.4.21-40.EL/kernel/sys.c linux-2.4.21-40.EL-snare/kernel/sys.c
--- linux-2.4.21-40.EL/kernel/sys.c	2006-03-16 05:30:51.000000000 +1100
+++ linux-2.4.21-40.EL-snare/kernel/sys.c	2006-04-12 02:04:10.000000000 +1000
@@ -15,6 +15,7 @@
 #include <linux/prctl.h>
 #include <linux/init.h>
 #include <linux/highuid.h>
+#include <linux/saudit.h>
 #include <linux/dcookies.h>
 #include <linux/fs.h>
 #include <linux/times.h>
@@ -355,15 +356,22 @@
 	char buffer[256];
 
 	/* We only trust the superuser with rebooting the system. */
-	if (!capable(CAP_SYS_BOOT))
+	if (!capable(CAP_SYS_BOOT)) {
+		saudit_reboot(magic1,magic2,cmd,arg,-EPERM);
 		return -EPERM;
+	}
 
 	/* For safety, we require "magic" arguments. */
 	if (magic1 != LINUX_REBOOT_MAGIC1 ||
 	    (magic2 != LINUX_REBOOT_MAGIC2 && magic2 != LINUX_REBOOT_MAGIC2A &&
-			magic2 != LINUX_REBOOT_MAGIC2B))
+			magic2 != LINUX_REBOOT_MAGIC2B)) {
+		saudit_reboot(magic1,magic2,cmd,arg,-EINVAL);
 		return -EINVAL;
+	}
 
+	// Try and audit before we go down.
+	saudit_reboot(magic1,magic2,cmd,arg,0);
+	
 	lock_kernel();
 	switch (cmd) {
 	case LINUX_REBOOT_CMD_RESTART:
@@ -463,13 +471,16 @@
 	int new_rgid = old_rgid;
 	int new_egid = old_egid;
 
+	
 	if (rgid != (gid_t) -1) {
 		if ((old_rgid == rgid) ||
 		    (current->egid==rgid) ||
 		    capable(CAP_SETGID))
 			new_rgid = rgid;
-		else
+		else {
+			saudit_setregid(rgid,egid,-EPERM);
 			return -EPERM;
+		}
 	}
 	if (egid != (gid_t) -1) {
 		if ((old_rgid == egid) ||
@@ -478,6 +489,7 @@
 		    capable(CAP_SETGID))
 			new_egid = egid;
 		else {
+			saudit_setregid(rgid,egid,-EPERM);
 			return -EPERM;
 		}
 	}
@@ -492,6 +504,8 @@
 	current->fsgid = new_egid;
 	current->egid = new_egid;
 	current->gid = new_rgid;
+
+	saudit_setregid(rgid,egid,0);
 	return 0;
 }
 
@@ -503,9 +517,10 @@
 asmlinkage long sys_setgid(gid_t gid)
 {
 	int old_egid = current->egid;
-
+	
 	if (capable(CAP_SETGID))
 	{
+		saudit_setgid(gid,0);
 		if(old_egid != gid)
 		{
 			current->mm->dumpable=0;
@@ -515,6 +530,7 @@
 	}
 	else if ((gid == current->gid) || (gid == current->sgid))
 	{
+		saudit_setgid(gid,0);
 		if(old_egid != gid)
 		{
 			current->mm->dumpable=0;
@@ -523,7 +539,10 @@
 		current->egid = current->fsgid = gid;
 	}
 	else
+	{
+		saudit_setgid(gid,-EPERM);
 		return -EPERM;
+	}
 	return 0;
 }
   
@@ -627,8 +646,10 @@
 		new_ruid = ruid;
 		if ((old_ruid != ruid) &&
 		    (current->euid != ruid) &&
-		    !capable(CAP_SETUID))
+		    !capable(CAP_SETUID)) {
+			saudit_setreuid(ruid,euid,-EPERM);
 			return -EPERM;
+		}
 	}
 
 	if (euid != (uid_t) -1) {
@@ -636,12 +657,18 @@
 		if ((old_ruid != euid) &&
 		    (current->euid != euid) &&
 		    (current->suid != euid) &&
-		    !capable(CAP_SETUID))
+		    !capable(CAP_SETUID)) {
+			saudit_setreuid(ruid,euid,-EPERM);
 			return -EPERM;
+		}
 	}
 
-	if (new_ruid != old_ruid && set_user(new_ruid, new_euid != old_euid) < 0)
+	if (new_ruid != old_ruid && set_user(new_ruid, new_euid != old_euid) < 0) {
+		saudit_setreuid(ruid,euid,-EAGAIN);
 		return -EAGAIN;
+	}
+
+	saudit_setreuid(ruid,euid,0);	// Before current->*id is changed
 
 	if (new_euid != old_euid)
 	{
@@ -679,17 +706,24 @@
 	int old_euid = current->euid;
 	int old_ruid, old_suid, new_ruid, new_suid;
 
+	
 	old_ruid = new_ruid = current->uid;
 	old_suid = current->suid;
 	new_suid = old_suid;
 	
 	if (capable(CAP_SETUID)) {
-		if (uid != old_ruid && set_user(uid, old_euid != uid) < 0)
+		if (uid != old_ruid && set_user(uid, old_euid != uid) < 0) {
+			saudit_setuid(uid,-EAGAIN);
 			return -EAGAIN;
+		}
 		new_suid = uid;
-	} else if ((uid != current->uid) && (uid != new_suid))
+	} else if ((uid != current->uid) && (uid != new_suid)) {
+		saudit_setuid(uid,-EPERM);
 		return -EPERM;
-
+	}
+	
+	saudit_setuid(uid,0);        // Before current->*id is changed
+	
 	if (old_euid != uid)
 	{
 		current->mm->dumpable = 0;
@@ -718,19 +752,30 @@
 
 	if (!capable(CAP_SETUID)) {
 		if ((ruid != (uid_t) -1) && (ruid != current->uid) &&
-		    (ruid != current->euid) && (ruid != current->suid))
+		    (ruid != current->euid) && (ruid != current->suid)) {
+			saudit_setresuid(ruid,euid,suid,-EPERM);
 			return -EPERM;
+		}
 		if ((euid != (uid_t) -1) && (euid != current->uid) &&
-		    (euid != current->euid) && (euid != current->suid))
+		    (euid != current->euid) && (euid != current->suid)) {
+			saudit_setresuid(ruid,euid,suid,-EPERM);
 			return -EPERM;
+		}
 		if ((suid != (uid_t) -1) && (suid != current->uid) &&
-		    (suid != current->euid) && (suid != current->suid))
+		    (suid != current->euid) && (suid != current->suid)) {
+			saudit_setresuid(ruid,euid,suid,-EPERM);
 			return -EPERM;
+		}
 	}
 	if (ruid != (uid_t) -1) {
-		if (ruid != current->uid && set_user(ruid, euid != current->euid) < 0)
+		if (ruid != current->uid && set_user(ruid, euid != current->euid) < 0) {
+			saudit_setresuid(ruid,euid,suid,-EAGAIN);
 			return -EAGAIN;
+		}
 	}
+	
+	saudit_setresuid(ruid,euid,suid,0);        // Before current->uids change
+
 	if (euid != (uid_t) -1) {
 		if (euid != current->euid)
 		{
@@ -768,15 +813,24 @@
 {
 	if (!capable(CAP_SETGID)) {
 		if ((rgid != (gid_t) -1) && (rgid != current->gid) &&
-		    (rgid != current->egid) && (rgid != current->sgid))
+		    (rgid != current->egid) && (rgid != current->sgid)) {
+			saudit_setresgid(rgid,egid,sgid,-EPERM);
 			return -EPERM;
+		}
 		if ((egid != (gid_t) -1) && (egid != current->gid) &&
-		    (egid != current->egid) && (egid != current->sgid))
+		    (egid != current->egid) && (egid != current->sgid)) {
+			saudit_setresgid(rgid,egid,sgid,-EPERM);
 			return -EPERM;
+		}
 		if ((sgid != (gid_t) -1) && (sgid != current->gid) &&
-		    (sgid != current->egid) && (sgid != current->sgid))
+		    (sgid != current->egid) && (sgid != current->sgid)) {
+			saudit_setresgid(rgid,egid,sgid,-EPERM);
 			return -EPERM;
+		}
 	}
+	
+	saudit_setresgid(rgid,egid,sgid,0);        // Before our current process UIDs change
+	
 	if (egid != (gid_t) -1) {
 		if (egid != current->egid)
 		{
diff -Nur linux-2.4.21-40.EL/Makefile linux-2.4.21-40.EL-snare/Makefile
--- linux-2.4.21-40.EL/Makefile	2006-03-16 05:47:48.000000000 +1100
+++ linux-2.4.21-40.EL-snare/Makefile	2006-04-12 02:22:46.000000000 +1000
@@ -130,7 +130,8 @@
 NETWORKS	=net/network.o
 
 LIBS		=$(TOPDIR)/lib/lib.a
-SUBDIRS		=kernel drivers mm fs net ipc lib crypto
+SAUDIT		=saudit/audit.o
+SUBDIRS		=kernel drivers mm fs net ipc lib crypto saudit
 
 DRIVERS-n :=
 DRIVERS-y :=
@@ -285,7 +286,7 @@
 
 export	CPPFLAGS CFLAGS CFLAGS_KERNEL AFLAGS AFLAGS_KERNEL
 
-export	NETWORKS DRIVERS LIBS HEAD LDFLAGS LINKFLAGS MAKEBOOT ASFLAGS
+export	NETWORKS DRIVERS LIBS HEAD LDFLAGS LINKFLAGS MAKEBOOT ASFLAGS SAUDIT
 
 .S.s:
 	$(CPP) $(AFLAGS) $(AFLAGS_KERNEL) -traditional -o $*.s $<
@@ -303,6 +304,7 @@
 			$(CORE_FILES) \
 			$(DRIVERS) \
 			$(NETWORKS) \
+			$(SAUDIT) \
 			$(LIBS) \
 			--end-group
 ifeq ($(CONFIG_KALLSYMS),y)
diff -Nur linux-2.4.21-40.EL/net/socket.c linux-2.4.21-40.EL-snare/net/socket.c
--- linux-2.4.21-40.EL/net/socket.c	2006-03-16 05:30:46.000000000 +1100
+++ linux-2.4.21-40.EL-snare/net/socket.c	2006-04-12 02:04:10.000000000 +1000
@@ -44,6 +44,7 @@
  *		Tigran Aivazian	:	sys_send(args) calls sys_sendto(args, NULL, 0)
  *		Tigran Aivazian	:	Made listen(2) backlog sanity checks 
  *					protocol-independent
+ *              Leigh Purdie    :       Socketcall auditing
  *		Benjamin LaHaise:	real aio support.
  *
  *
@@ -75,6 +76,8 @@
 #include <linux/cache.h>
 #include <linux/module.h>
 #include <linux/highmem.h>
+#include <linux/saudit.h>
+
 
 #if defined(CONFIG_KMOD) && defined(CONFIG_NET)
 #include <linux/kmod.h>
@@ -1609,12 +1612,14 @@
 			break;
 		case SYS_CONNECT:
 			err = sys_connect(a0, (struct sockaddr *)a1, a[2]);
+			saudit_connect(a0, (struct sockaddr *)a1, a[2],err);
 			break;
 		case SYS_LISTEN:
 			err = sys_listen(a0,a1);
 			break;
 		case SYS_ACCEPT:
 			err = sys_accept(a0,(struct sockaddr *)a1, (int *)a[2]);
+			saudit_accept(a0, (struct sockaddr *)a1, (int *)a[2],err);
 			break;
 		case SYS_GETSOCKNAME:
 			err = sys_getsockname(a0,(struct sockaddr *)a1, (int *)a[2]);
diff -Nur linux-2.4.21-40.EL/saudit/auditapi.c linux-2.4.21-40.EL-snare/saudit/auditapi.c
--- linux-2.4.21-40.EL/saudit/auditapi.c	1970-01-01 10:00:00.000000000 +1000
+++ linux-2.4.21-40.EL-snare/saudit/auditapi.c	2006-04-12 02:04:10.000000000 +1000
@@ -0,0 +1,2060 @@
+/* $Id: auditapi.c,v 1.3 2004/11/03 22:44:04 redphoenix Exp $
+ *
+ * saudit/auditapi.c
+ *
+ * Original Copyright (c) 2002-2004 InterSect Alliance Pty Ltd
+ *           - www.intersectalliance.com
+ *
+ * Additions:
+ * 2005: Incorporated Marks GrabString changes for audit_mount
+ * 2004: Modified by Mark Westerman mark.westerman at westcam dot com 
+ * 2004: Copyright (c) 2004 Silicon Graphics, Inc. All rights reserved.
+ * 2004: Modified by Jonathan Abbey, UTexas
+ *
+ */
+
+// Memory usage
+#include <linux/config.h>
+
+// Total events and lost events not working now do not show
+// Modification By mark.westerman at westcam dot com
+#define SHOW_EVENT_COUNTER 0
+#define SNARE_RED_HAT_LINUX_KERNEL 1
+
+#define MAX_SOCK_ADDR 128
+
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/proc_fs.h>
+#include <linux/saudit.h>
+
+#include <net/sock.h>
+
+#include <asm/unistd.h>
+#include <asm/uaccess.h>
+
+#include <linux/version.h>
+
+// Externals
+// Not certain that we need this.
+extern struct socket *sockfd_lookup (int fd, int *err);
+
+
+// Function prototypes
+static int auditproc_ioctl(struct inode *, struct file *, unsigned int,
+			   unsigned long);
+static int auditproc_open(struct inode *, struct file *);
+static int auditproc_close(struct inode *, struct file *);
+static ssize_t auditproc_read(struct file *, char *, size_t, loff_t *);
+
+static int info_open(struct inode *inode, struct file *file);
+static ssize_t info_read(struct file *file, char *ubuf, size_t length,
+			 loff_t * ppos);
+static int info_close(struct inode *inode, struct file *file);
+
+static void audit_on(int auditnumber);
+static void audit_off(int auditnumber);
+static AuditNode *alloc_event(int token_size);
+static void append_event(AuditNode * nodepointer);
+
+static long GrabString(char *destination, const char *kernelstring,
+		const char *userstring, int length);
+
+static void audit_hwcheck(void);
+int saudit_return(int returncode);
+
+static DECLARE_MUTEX(audit_lock);
+static struct task_struct *auditdaemon_task_struct = NULL;	// Daemon interaction
+
+// If we have the audit daemon attached
+int AUDIT_IS_RUNNING = 0;
+static int AUDIT_IS_PAUSED = 0;	// Used for High Water Mark memory testing
+
+#if defined(SNARE_RED_HAT_LINUX_KERNEL) || ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) )
+#define PRIO_TO_NICE(prio)      ((prio) - MAX_RT_PRIO - 20)
+#endif
+
+// How many packets have we lost this session due to low buffer size?
+static int lost_events = 0;
+static int total_events = 0;
+
+// Linked list of audit events - used as an internal buffer
+// so that we don't slow down the kernel significantly while waiting
+// for the user space audit daemon to catch up.
+static AuditNode *list_head = (AuditNode *) NULL;
+static AuditNode *list_tail = (AuditNode *) NULL;
+
+// Audit daemon read position
+static void *read_position = (void *) NULL;
+
+// Setup a bitmask to work out which audit events are currently active.
+// Declare as volatile for the compiler not lock for test events
+volatile static unsigned long active_events[(MAXAUDIT + sizeof(long) - 1) /
+					    sizeof(long)] = { 0, };
+
+#define saudit_active(auditnumber) \
+	(test_bit((auditnumber),active_events))
+
+static struct file_operations info_ops = {
+      read:info_read,		// read
+      open:info_open,
+      release:info_close
+};
+
+static struct file_operations file_ops = {
+      read:auditproc_read,	// read
+      open:auditproc_open,	// open
+      ioctl:auditproc_ioctl,	// ioctl
+      release:auditproc_close	// release
+};
+
+
+static struct proc_dir_entry *ProcEntry;
+static struct proc_dir_entry *ProcInfoEntry;
+
+//
+// For compatibility with Non RedHat i.e. vanilla kernels
+// including debian kernels
+//
+
+#if !defined(SNARE_RED_HAT_LINUX_KERNEL) && ( LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) )
+#define set_user_nice(tsk, n) do { (tsk)->nice = n; } while(0)
+#endif
+
+//
+// Highwater mark varables for memory utilization
+//
+static unsigned long highwater_mark = 15000000;	// Set to 15 MB by Default
+static unsigned long memory_usage = 0;		// Current Memory Usage
+static int nicevalue;				// Nice Value that the
+						// Audit Daemon was stated with
+static int prio_change = 0;			// Has priority Changed
+static int highwater_pause = 100;		// % to of memory usage to pause
+static int lowwater_pause = 90;			// % to resume auditing
+static int highwater_nice = 80;			// % to change audit priority
+static int highwater_nice_val = -10;		// Nice value to change to
+static int lowwater_nice = 60;			// % to change back the priority
+static int highwater_mark_percent = 10;		// % of memory to use for High water mark
+
+wait_queue_head_t proc_audit_queue;
+
+// Use to calculate total ram
+#define BSHIFT(x) ((unsigned long)(x) << PAGE_SHIFT)
+
+// Initialise our audit environment
+void saudit_init(void)
+{
+	struct sysinfo i;
+
+	// Initialise audit here
+	// - create /proc entries etc.
+	printk("SNARE Audit capability is initialising\n");
+
+	// Create the proc file system entries.
+	if ((ProcInfoEntry =
+	     create_proc_entry(AUDITINFO_NAME, S_IRUGO | S_IWUSR,
+			       NULL)) == NULL) {
+		printk("Audit: Cannot create snare information interface in /proc");
+		return;
+	}
+	ProcInfoEntry->proc_fops = &info_ops;
+
+	if ((ProcEntry =
+	     create_proc_entry(AUDITDEV_NAME, S_IRUSR | S_IWUSR,
+			       NULL)) == NULL) {
+		printk("Audit: Cannot create snare daemon interface in /proc");
+		return;
+	}
+
+	ProcEntry->proc_fops = &file_ops;
+
+	// Initialise the wait queue for blocking read
+	init_waitqueue_head(&proc_audit_queue);
+	// Initialise the highwater mark system
+	memory_usage = 0;
+	AUDIT_IS_PAUSED = 0;
+	si_meminfo(&i);
+	// Set the highwater mark as a percentage of total ram
+	highwater_mark = (BSHIFT(i.totalram) / 100) * highwater_mark_percent;
+
+}
+
+static int info_open(struct inode *inode, struct file *file)
+{
+	enum { DATA_LEN = 500 };
+	char *data;
+	char processid[20];
+	int nv;
+	pid_t ad_task = 0;
+	int daemon_running = 0;
+#if SHOW_EVENT_COUNTER
+	int l_lost_events, l_total_events;
+#endif
+
+	if ((data = kmalloc(DATA_LEN, GFP_KERNEL)) == NULL)
+		return (0);
+
+	down(&audit_lock);
+
+	if (auditdaemon_task_struct != NULL) {
+		daemon_running = 1;
+		ad_task = auditdaemon_task_struct->pid;
+	}
+
+#if SHOW_EVENT_COUNTER
+	l_lost_events = lost_events;
+	l_total_events = total_events;
+#endif
+
+	up(&audit_lock);
+
+	if(daemon_running) {
+		snprintf(processid, 20, "%d", (int) ad_task);
+#if !defined(SNARE_RED_HAT_LINUX_KERNEL) && ( LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) )
+		nv = auditdaemon_task_struct->nice;
+#else
+		nv = PRIO_TO_NICE(auditdaemon_task_struct->static_prio);
+#endif
+	} else {
+		snprintf(processid, 20, "No Daemon Running");
+		nv = 0;
+	}
+
+
+#if SHOW_EVENT_COUNTER
+	// Just my perference I like the output lined up
+	snprintf(data, DATA_LEN,
+		 "SNARE Version:                 %d.%d.%d\n"
+		 "Audit Active:                  %s\n"
+		 "Audit Process ID:              %s\n"
+		 "Events Lost This Session:      %d\n"
+		 "Events Processed This Session: %d\n"
+		 "HighWater Mark:                %lu\n"
+		 "Memory Usage:                  %lu\n"
+		 "Audit Paused:                  %s\n"
+		 "Audit Nice Value:              %d\n",
+		 SNAREAUDIT_MAJOR_VERSION, SNAREAUDIT_MINOR_VERSION,
+		 SNAREAUDIT_PATCH_VERSION,
+		 (AUDIT_IS_RUNNING ? "yes" : "no"), processid, l_lost_events,
+		 l_total_events, highwater_mark, memory_usage,
+		 (AUDIT_IS_PAUSED ? "yes" : "no"), nv);
+#else
+	snprintf(data, DATA_LEN,
+		 "SNARE Version:    %d.%d.%d\n"
+		 "Audit Active:     %s\n"
+		 "Audit Process ID: %s\n"
+		 "HighWater Mark:   %lu\n"
+		 "Memory Usage:     %lu\n"
+		 "Audit Paused:     %s\n"
+		 "Audit Nice Value: %d\n",
+		 SNAREAUDIT_MAJOR_VERSION, SNAREAUDIT_MINOR_VERSION,
+		 SNAREAUDIT_PATCH_VERSION,
+		 (AUDIT_IS_RUNNING ? "yes" : "no"), processid,
+		 highwater_mark, memory_usage,
+		 (AUDIT_IS_PAUSED ? "yes" : "no"), nv);
+#endif
+
+	if (data == NULL)
+		return -ENODEV;
+
+	file->private_data = data;
+
+	return (0);
+}
+
+static void audit_hwcheck(void)
+{
+	unsigned long per;
+	int paused;
+
+
+	// We lock the kernel here to handle the
+	// the highwater mark system use lot of 
+	// global varables
+
+	down(&audit_lock);
+	paused = AUDIT_IS_PAUSED;
+	per = memory_usage / (highwater_mark / 100);
+
+	if (per > highwater_pause) {
+		AUDIT_IS_PAUSED = 1;
+		++lost_events;
+		up(&audit_lock);
+		if (!paused) {
+			printk("Auditing: is paused\n");
+		}
+		return;
+	}
+	if (per > highwater_nice) {
+		if (!AUDIT_IS_PAUSED) {
+			if (!prio_change) {
+				prio_change = 1;
+				up(&audit_lock);
+				printk
+				    ("Auditing: Changing Audit daemon Priority\n");
+				set_user_nice(auditdaemon_task_struct,
+					      highwater_nice_val);
+				return;
+			}
+			up(&audit_lock);
+			return;
+		}
+		++lost_events;
+		up(&audit_lock);
+		return;
+	}
+	if (AUDIT_IS_PAUSED && (per < lowwater_pause)) {
+		AUDIT_IS_PAUSED = 0;
+	} else {
+		paused = 0;
+	}
+	if (prio_change && per < lowwater_nice) {
+		prio_change = 0;
+		up(&audit_lock);
+		printk("Auditing: Resuming Audit daemon Priority\n");
+		set_user_nice(auditdaemon_task_struct, nicevalue);
+		return;
+	}
+	if (AUDIT_IS_PAUSED) {
+		++lost_events;
+	}
+
+	up(&audit_lock);
+	if (paused) {
+		printk("Auditing: is resuming\n");
+	}
+}
+
+static int info_close(struct inode *inode, struct file *file)
+{
+	kfree(file->private_data);
+	return (0);
+}
+
+static ssize_t info_read(struct file *file, char *ubuf, size_t length,
+			 loff_t * ppos)
+{
+	int bytes_to_write = 0;
+	int pos = *ppos;
+	char *data = file->private_data;
+
+	// User has asked for a zero-length read?
+	if (length == 0)
+		return (0);
+
+	if ((bytes_to_write = strlen(data) - pos) <= 0)
+		return 0;	// EOF
+	if (bytes_to_write >= length)
+		bytes_to_write = length;
+	if (copy_to_user(ubuf, data + pos, bytes_to_write))
+		return -EFAULT;
+	*ppos = pos + bytes_to_write;
+	return (bytes_to_write);
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// This routine handles ioctl messages from the audit daemon.
+////////////////////////////////////////////////////////////////////////////////
+
+int auditproc_ioctl(struct inode *node, struct file *the_file,
+		    unsigned int command, unsigned long arg)
+{
+	// If the audit facility is running, there is not much point starting again!
+	if ((AUDIT_IS_RUNNING) && (command == AUDIT_START)) {
+		return -EBUSY;
+	}
+
+	// Don't alllow a forked or cloned task to ioctl.
+	// Only the task which opened the audit device may
+	// control this device.
+	if(auditdaemon_task_struct != current) {
+		return -EBUSY;
+	}
+
+	if (command == AUDIT_START) {
+		down(&audit_lock);
+		AUDIT_IS_RUNNING = 1;
+		up(&audit_lock);
+	} else if (command == AUDIT_STOP) {
+		down(&audit_lock);
+		AUDIT_IS_RUNNING = 0;
+		up(&audit_lock);
+	} else if (command == AUDIT_LOSTEVENTS) {
+		return (lost_events);
+	} else if (command == AUDIT_TOTALEVENTS) {
+		return (total_events);
+	} else if (command == AUDIT_EVENT_ON) {
+		if(arg <= 0 || arg > MAXAUDIT) {
+			return -EINVAL;
+		}
+		audit_on(arg);
+	} else if (command == AUDIT_EVENT_OFF) {
+		if(arg <= 0 || arg > MAXAUDIT) {
+			return -EINVAL;
+		}
+		audit_off(arg);
+		// Eg: ioctl(x,SYS_exit);
+	} else if (command == AUDIT_FLUSH) {
+		// Turn off all auditing.
+		// This is generally sent when /etc/audit/snare.conf has been updated
+		// and the user wishes to establish a new audit policy.
+		int counter;
+		for (counter = 1; counter <= MAXAUDIT; counter++) {
+			if (saudit_active(counter))
+				audit_off(counter);
+		}
+
+		// Also reset the lost/total event counters here.
+		lost_events = 0;
+		total_events = 0;
+		// High water mark system should add error checking here.
+	} else if (command == AUDIT_HIGHWATERMARK_MEM) {
+		highwater_mark = arg;
+	} else if (command == AUDIT_HIGHWATERMARK_PER) {
+		struct sysinfo i;
+		si_meminfo(&i);
+		highwater_mark_percent = arg;
+		highwater_mark =
+		    (BSHIFT(i.totalram) / 100) * highwater_mark_percent;
+	} else if (command == AUDIT_HIGHWATERMARK_PAUSE) {
+		highwater_pause = arg;
+	} else if (command == AUDIT_LOWWATERMARK_PAUSE) {
+		lowwater_pause = arg;
+	} else if (command == AUDIT_HIGHWATERMARK_NICE) {
+		highwater_nice_val = arg;
+	} else if (command == AUDIT_LOWWATERMARK_NICE) {
+		lowwater_nice = arg;
+	} else if (command == AUDIT_HIGHWATER_NICE_VAL) {
+		highwater_nice_val = arg;
+	} else {
+		return -ENOSYS;	// Redhat kernel team suggest ENOTTY ? Clarify this.
+	}
+
+	return 0;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Here we give the user the data.
+// NOTE that this module may be executed at any time - even in the middle
+// of the execution of something else. Hence, any variables that are changed
+// by this routine should be surrounded by a kernel lock if they are used
+// elsewhere!
+//
+// In particular:
+//  read_position
+//  list_head
+//  list_tail
+//
+// Let me just repeat this in another way:
+// WARNING: DO NOT CHANGE OR RELY ON THE VARIABLES ABOVE UNLESS YOU ARE
+//                IN A LOCKED STATE - THEY MAY BE CORRUPTED BY THE
+//                AUDIT_READ MODULE, WHICH IS CALLED BY SIGNAL/INTERRUPT
+//
+// Unfortunately, we also need lock within this routine also.
+// Otherwise, an interrupt might occur when we were half way through modifying
+// something like read_position - and if the interrupt happens to generate an
+// audit event, then we may be copying data to the wrong location in the array,
+// leading to data corruption.
+// Locking too much code slows down the system unfortunately. I'll try
+// and keep it minimal.
+////////////////////////////////////////////////////////////////////////////////
+
+static ssize_t auditproc_read(struct file *file, char *filebuffer,
+			      size_t length, loff_t * ppos)
+{
+	// Number of bytes actually written to the buffer
+	int bytes_avail_to_send = 0;
+	int bytes_to_write = 0;
+
+
+	// Don't allow a forked or cloned task to read.
+	// Only the task which opened the audit device may read.
+	if(auditdaemon_task_struct != current) {
+		return -EBUSY;
+	}
+
+	if (length == 0) {
+		return (0);	// Only want zero bytes? Here they are.
+	}
+
+	//if (ppos != &file->f_pos)
+	//	return -ESPIPE;	// No pread() thanks.
+
+	BUG_ON(auditdaemon_task_struct == NULL);
+
+	// Do we have any data?
+	if (list_head == (AuditNode *) NULL) {
+		if (file->f_flags & O_NONBLOCK) {
+			return -EAGAIN;
+		}
+		if (wait_event_interruptible(proc_audit_queue, list_head)) {
+			return -ERESTARTSYS;
+		}
+	}
+
+	// Lock the kernel
+	down(&audit_lock);
+	if (read_position == (void *) NULL) {
+		// Our first time into this routine, or first time back after all data has been read.
+		read_position = list_head->location;
+	}
+
+	bytes_avail_to_send =
+	    (int) (((void *) list_head->location + list_head->size) -
+		   (void *) read_position);
+
+	up(&audit_lock);
+
+	/*
+         * Give the caller all available data up to length.
+         * We know that at least one byte will be available,
+         * because we have the head node, all nodes must
+         * have some data, and the head node must have some
+         * data available (otherwise the head node would
+         * have been tossed in the last call to this function).
+         */
+	if(bytes_avail_to_send > length) {
+		bytes_to_write = length;
+        } else {
+                 bytes_to_write = bytes_avail_to_send;
+	}
+//	while (bytes_avail_to_send < length) {
+//		// up(&audit_lock);
+//
+//		if (file->f_flags & O_NONBLOCK) {
+//			return -EAGAIN;
+//		}
+//
+//		if (wait_event_interruptible(proc_audit_queue,
+//					     (bytes_avail_to_send =
+//					      (int) (list_head->location +
+//						     list_head->size -
+//						     read_position)) >=
+//					     length)) {
+//			return -ERESTARTSYS;
+//		}
+//		// down(&audit_lock);
+//	}
+//	bytes_to_write = length;
+
+	if (copy_to_user(filebuffer, read_position, bytes_to_write)) {
+		// up(&audit_lock);
+		return -EFAULT;
+	}
+
+	down(&audit_lock);
+	read_position += bytes_to_write;
+
+	// Have we reached the end of the current nodes data?
+	if ((void *) read_position >=
+	    ((void *) list_head->location + list_head->size)) {
+		AuditNode *tempnode;
+
+		tempnode = list_head;
+		list_head = list_head->next;
+
+		if (tempnode->size > memory_usage) {
+			memory_usage = 0;
+		} else {
+			memory_usage -= tempnode->size;
+		}
+		// Excellent, we're at the end of the current audit event.
+		// Remove this from the linked list, and set the read_position to the next record.
+		if (list_head != (AuditNode *) NULL) {
+			read_position = list_head->location;
+		} else {
+			read_position = (AuditNode *) NULL;
+		}
+
+		// No events remaining? Set list_tail to null also.
+		if (tempnode->next == (AuditNode *) NULL) {
+			list_tail = (AuditNode *) NULL;
+		}
+
+		// Free our tempnode->location pointer, which actually
+		// is a pointer to ex current->saudit_record
+		kfree(tempnode->location);
+		kfree(tempnode);
+	}
+
+	up(&audit_lock);
+
+	return (bytes_to_write);
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// open the device
+////////////////////////////////////////////////////////////////////////////////
+static int auditproc_open(struct inode *node, struct file *the_file)
+{
+	// Note: This changes to minor(node...) in 2.6
+	// int device_minor = MINOR(node->i_rdev) & 0xf;	// Device minor number
+
+	// We can only have one audit device, and it can only be open once
+	//if (device_minor) {
+	//	return -EBUSY;
+	//}
+
+	down(&audit_lock);
+
+	if (auditdaemon_task_struct != NULL) {
+		up(&audit_lock);
+		return -EBUSY;
+	}
+
+	// reset the lost packets indicator
+	lost_events = 0;
+	total_events = 0;
+	memory_usage = 0;
+	AUDIT_IS_PAUSED = 0;
+
+	// Fetch the task structure of the process that opened the device
+	auditdaemon_task_struct = current;
+#if !defined(SNARE_RED_HAT_LINUX_KERNEL) && ( LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) )
+	nicevalue = auditdaemon_task_struct->nice;
+#else
+	nicevalue = PRIO_TO_NICE(auditdaemon_task_struct->static_prio);
+#endif
+
+	// reset our read position to the beginning of head event data
+	read_position = NULL;
+
+	up(&audit_lock);
+
+	printk("Auditing: Process %d has opened the device\n",
+	       auditdaemon_task_struct->pid);
+
+	return 0;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// close the device and release resources
+////////////////////////////////////////////////////////////////////////////////
+static int auditproc_close(struct inode *node, struct file *the_file)
+{
+	int counter;
+#if SHOW_EVENT_COUNTER
+	int l_lost_events, l_total_events;
+#endif
+
+	// Only the task that opened the audit device can
+	// close the device. We don't want another thread
+	// to interfere.
+	if(auditdaemon_task_struct != current) {
+		return(0);
+	}
+
+	for (counter = 1; counter <= MAXAUDIT; counter++) {
+		audit_off(counter);
+	}
+
+	down(&audit_lock);
+	AUDIT_IS_RUNNING = 0;
+
+	auditdaemon_task_struct = NULL;
+#if SHOW_EVENT_COUNTER
+	l_lost_events = lost_events;
+	l_total_events = total_events;
+#endif
+	lost_events = 0;
+	total_events = 0;
+	memory_usage = 0;
+	AUDIT_IS_PAUSED = 0;
+
+	up(&audit_lock);
+
+	printk("AUDIT: Audit daemon has closed /proc/audit.\n");
+#if SHOW_EVENT_COUNTER
+	printk("AUDIT: Events lost due low memory this session: %d\n",
+	       l_lost_events);
+	printk("AUDIT: Total Events processed this session: %d\n",
+	       l_total_events);
+#endif
+
+	return 0;
+}
+
+static void audit_on(int auditnumber)
+{
+	if(auditnumber <= 0 || auditnumber > MAXAUDIT) {
+		return;
+	}
+	down(&audit_lock);
+	set_bit(auditnumber, active_events);
+	up(&audit_lock);
+}
+
+static void audit_off(int auditnumber)
+{
+	if(auditnumber <= 0 || auditnumber > MAXAUDIT) {
+		return;
+	}
+	down(&audit_lock);
+	clear_bit(auditnumber, active_events);
+	up(&audit_lock);
+}
+
+int _audit_mknod(const char *kfile, const char *ufile, int mode, dev_t dev,
+		int retval)
+{
+	io_class *record;
+
+	// If noone has requested MKNOD to be active, return quickly.
+	if (!saudit_active(AUDIT_mknod))
+		return (0);
+	audit_hwcheck();
+	if (current == auditdaemon_task_struct || AUDIT_IS_PAUSED)
+		return (0);
+	if (current->saudit_record)
+		return (1);
+
+	// alloc the audit record
+	current->saudit_record = kmalloc(sizeof(io_class), GFP_KERNEL);
+	if (!current->saudit_record) {
+		return (0);
+	}
+
+	record = (io_class *) current->saudit_record;
+
+	// Filename.
+	GrabString(record->t_path.path, kfile, ufile, MAX_PATH);
+
+	record->t_attributes.mode = (int) mode;
+	record->t_attributes.createmode = (unsigned long) dev;
+
+	record->t_header.event_id = AUDIT_mknod;
+	record->t_header.event_class = AUDIT_CLASS_IO;
+	saudit_return(retval);
+	return (1);
+}
+
+/*
+ * argcount() counts the number of strings in array ARGV.
+ */
+static int argcount(char **argv, int max)
+{
+	int i = 0;
+
+	if (argv != NULL) {
+		for (;;) {
+			char *p;
+
+			if (get_user(p, argv))
+				return -EFAULT;
+			if (!p)
+				break;
+			argv++;
+			if(++i > max)
+				return -E2BIG;
+		}
+	}
+	return i;
+}
+
+char *saudit_copy_argv(char **argv)
+{
+	char *returnstring;
+	// char tempstring[MAX_PATH];
+	char *tempstring;
+	int argc, argi;
+	char *str;
+	unsigned int delimiter_required = 0;
+
+	if (!saudit_active(AUDIT_execve))
+		return ((char *) NULL);
+	audit_hwcheck();
+	if (current == auditdaemon_task_struct || AUDIT_IS_PAUSED)
+		return ((char *) NULL);
+
+	argc=argcount(argv, 1024);	/* avoid infinite loop on bad data */
+	if (argc < 0) {
+		return ((char *) NULL);
+	}
+
+	//
+	// Dont check saudit_record for NULL Since it it will be here
+	//
+	tempstring = kmalloc(MAX_PATH, GFP_KERNEL);
+	if (!tempstring)
+		return ((char *) NULL);	// Out of mem
+
+	tempstring[0] = '\0';
+	returnstring = kmalloc(MAX_PATH, GFP_KERNEL);
+	if (!returnstring) {
+		kfree(tempstring);
+		return ((char *) NULL);	// Out of mem
+	}
+	returnstring[0] = '\0';
+	argi=0;
+	
+	while (argi < argc) {
+		if (get_user(str, argv+argi)) {
+			    continue;
+		}
+		strncpy_from_user(tempstring, str, MAX_PATH - 1);
+		tempstring[MAX_PATH-1] = '\0';
+
+		// Allow for the delimiter
+		if ((strlen(returnstring) + strlen(tempstring) + 1) <
+		    (MAX_PATH - 1)) {
+			if (!delimiter_required) {
+				delimiter_required = 1;
+			} else {
+				strcat(returnstring, " ");
+			}
+			strcat(returnstring, tempstring);
+		} else {
+			// If the argument size is greater than MAX_PATH, then
+			// ignore this argument, continue on to the next.
+			argi++;
+			continue;
+		}
+		argi++;
+	}
+	kfree(tempstring);
+
+	return (returnstring);
+}
+
+int _audit_execve(const char *ufilename, const char *kfilename,
+		 char *arguments, int retval)
+{
+	ex_class *record;
+
+	if (!saudit_active(AUDIT_execve)) {
+		if (arguments) {
+			kfree(arguments);
+		}
+		return (0);
+	}
+	audit_hwcheck();
+	if (current == auditdaemon_task_struct || AUDIT_IS_PAUSED) {
+		if (arguments) {
+			kfree(arguments);
+		}
+		return (0);
+	}
+
+	if (current->saudit_record) {
+		if (arguments) {
+			kfree(arguments);
+		}
+		return (1);
+	}
+
+	// alloc the audit record
+	current->saudit_record = kmalloc(sizeof(ex_class), GFP_KERNEL);
+	if (!current->saudit_record) {
+		if (arguments) {
+			kfree(arguments);
+		}
+		return (0);
+	}
+
+	record = (ex_class *) current->saudit_record;
+
+	// Use our new grabstring routine
+	GrabString(record->t_path.path, kfilename, ufilename, MAX_PATH);
+
+	if (arguments) {
+		strncpy(record->t_execargs.args, arguments, MAX_PATH);
+		kfree(arguments);
+	} else {
+		strcat(record->t_execargs.args, "");
+	}
+
+	record->t_header.event_id = AUDIT_execve;
+	record->t_header.event_class = AUDIT_CLASS_EXEC;
+
+	saudit_return(retval);
+	return (0);
+}
+
+
+int _audit_exit(int retval)
+{
+	pc_class *record;
+
+	if (!saudit_active(AUDIT_exit))
+		return (0);
+	audit_hwcheck();
+	if (current == auditdaemon_task_struct || AUDIT_IS_PAUSED)
+		return (0);
+	if (current->saudit_record)
+		return (1);
+
+	// alloc the audit record
+	current->saudit_record = kmalloc(sizeof(pc_class), GFP_KERNEL);
+	if (!current->saudit_record) {
+		return (0);
+	}
+
+	record = (pc_class *) current->saudit_record;
+	record->t_header.event_id = AUDIT_exit;
+	record->t_header.event_class = AUDIT_CLASS_PC;
+	saudit_return(retval);
+	return (1);
+}
+
+int _audit_fork(int retval)
+{
+	pc_class *record;
+
+	if (!saudit_active(AUDIT_fork))
+		return (0);
+	audit_hwcheck();
+	if (current == auditdaemon_task_struct || AUDIT_IS_PAUSED)
+		return (0);
+	if (current->saudit_record)
+		return (1);
+
+	// alloc the audit record
+	current->saudit_record = kmalloc(sizeof(pc_class), GFP_KERNEL);
+	if (!current->saudit_record) {
+		return (0);
+	}
+
+	record = (pc_class *) current->saudit_record;
+	record->t_header.event_id = AUDIT_fork;
+	record->t_header.event_class = AUDIT_CLASS_PC;
+	saudit_return(retval);
+	return (1);
+}
+
+int _audit_open(const char *kfile, const char *ufile, int flags, int mode,
+	       int retval)
+{
+	io_class *record;
+
+	if (!saudit_active(AUDIT_open))
+		return (0);
+	audit_hwcheck();
+	if (current == auditdaemon_task_struct || AUDIT_IS_PAUSED)
+		return (0);
+	if (current->saudit_record)
+		return (1);
+
+	// alloc the audit record
+	current->saudit_record = kmalloc(sizeof(io_class), GFP_KERNEL);
+	if (!current->saudit_record) {
+		return (0);
+	}
+
+	record = (io_class *) current->saudit_record;
+
+	// Filename.
+	GrabString(record->t_path.path, kfile, ufile, MAX_PATH);
+
+	record->t_attributes.mode = flags;
+	record->t_attributes.createmode = mode;
+
+	record->t_header.event_id = AUDIT_open;
+	record->t_header.event_class = AUDIT_CLASS_IO;
+
+	saudit_return(retval);
+	return (1);
+}
+
+int _audit_mkdir(const char *kfile, const char *ufile, int mode, int retval)
+{
+	io_class *record;
+
+	// If noone has requested the system call to be active, return quickly.
+	if (!saudit_active(AUDIT_mkdir))
+		return (0);
+	audit_hwcheck();
+	if (current == auditdaemon_task_struct || AUDIT_IS_PAUSED)
+		return (0);
+	if (current->saudit_record)
+		return (1);
+
+	// alloc the audit record
+	current->saudit_record = kmalloc(sizeof(io_class), GFP_KERNEL);
+	if (!current->saudit_record) {
+		return (0);
+	}
+
+	record = (io_class *) current->saudit_record;
+
+	// Filename.
+	GrabString(record->t_path.path, kfile, ufile, MAX_PATH);
+
+	record->t_attributes.mode = 0;
+	record->t_attributes.createmode = mode;
+
+	record->t_header.event_id = AUDIT_mkdir;
+	record->t_header.event_class = AUDIT_CLASS_IO;
+	saudit_return(retval);
+	return (1);
+}
+
+int _audit_unlink(const char *kfile, const char *ufile, int retval)
+{
+	io_class *record;
+
+	// If noone has requested the system call to be active, return quickly.
+	if (!saudit_active(AUDIT_unlink))
+		return (0);
+	audit_hwcheck();
+	if (current == auditdaemon_task_struct || AUDIT_IS_PAUSED)
+		return (0);
+	if (current->saudit_record)
+		return (1);
+
+	// alloc the audit record
+	current->saudit_record = kmalloc(sizeof(io_class), GFP_KERNEL);
+	if (!current->saudit_record) {
+		return (0);
+	}
+
+	record = (io_class *) current->saudit_record;
+
+	// Filename.
+	GrabString(record->t_path.path, kfile, ufile, MAX_PATH);
+
+	record->t_attributes.mode = 0;
+	record->t_attributes.createmode = 0;
+
+	record->t_header.event_id = AUDIT_unlink;
+	record->t_header.event_class = AUDIT_CLASS_IO;
+	saudit_return(retval);
+	return (1);
+}
+
+int _audit_rmdir(const char *kfile, const char *ufile, int retval)
+{
+	io_class *record;
+
+	// If noone has requested the system call to be active, return quickly.
+	if (!saudit_active(AUDIT_rmdir))
+		return (0);
+	audit_hwcheck();
+	if (current == auditdaemon_task_struct || AUDIT_IS_PAUSED)
+		return (0);
+	if (current->saudit_record)
+		return (1);
+
+	// alloc the audit record
+	current->saudit_record = kmalloc(sizeof(io_class), GFP_KERNEL);
+	if (!current->saudit_record) {
+		return (0);
+	}
+
+	record = (io_class *) current->saudit_record;
+
+	// Filename.
+	GrabString(record->t_path.path, kfile, ufile, MAX_PATH);
+
+	record->t_attributes.mode = 0;
+	record->t_attributes.createmode = 0;
+
+	record->t_header.event_id = AUDIT_rmdir;
+	record->t_header.event_class = AUDIT_CLASS_IO;
+	saudit_return(retval);
+	return (1);
+}
+
+int _audit_chown(const char *kfile, const char *ufile, uid_t user,
+		gid_t group, int retval)
+{
+	ch_class *record;
+
+	// If noone has requested the system call to be active, return quickly.
+	if (!saudit_active(AUDIT_chown))
+		return (0);
+	audit_hwcheck();
+	if (current == auditdaemon_task_struct || AUDIT_IS_PAUSED)
+		return (0);
+	if (current->saudit_record)
+		return (1);
+
+	// alloc the audit record
+	current->saudit_record = kmalloc(sizeof(ch_class), GFP_KERNEL);
+	if (!current->saudit_record) {
+		return (0);
+	}
+
+	record = (ch_class *) current->saudit_record;
+
+	// Filename.
+	GrabString(record->t_path.path, kfile, ufile, MAX_PATH);
+
+	record->t_owner.owner = (int) user;
+	record->t_owner.group = (int) group;
+
+	record->t_header.event_id = AUDIT_chown;
+	record->t_header.event_class = AUDIT_CLASS_CH;
+	saudit_return(retval);
+	return (1);
+}
+
+int _audit_chmod(const char *kfile, const char *ufile, mode_t mode,
+		int retval)
+{
+	io_class *record;
+
+	// If noone has requested the system call to be active, return quickly.
+	if (!saudit_active(AUDIT_chmod))
+		return (0);
+	audit_hwcheck();
+	if (current == auditdaemon_task_struct || AUDIT_IS_PAUSED)
+		return (0);
+	if (current->saudit_record)
+		return (1);
+
+	// alloc the audit record
+	current->saudit_record = kmalloc(sizeof(io_class), GFP_KERNEL);
+	if (!current->saudit_record) {
+		return (0);
+	}
+
+	record = (io_class *) current->saudit_record;
+
+	// Filename.
+	GrabString(record->t_path.path, kfile, ufile, MAX_PATH);
+
+	record->t_attributes.mode = 0;
+	record->t_attributes.createmode = (unsigned long) mode;
+
+	record->t_header.event_id = AUDIT_chmod;
+	record->t_header.event_class = AUDIT_CLASS_IO;
+	saudit_return(retval);
+	return (1);
+}
+
+int _audit_symlink(const char *kfrom, const char *ufrom, const char *kto,
+		  const char *uto, int retval)
+{
+	cp_class *record;
+
+	// If noone has requested the system call to be active, return quickly.
+	if (!saudit_active(AUDIT_symlink))
+		return (0);
+	audit_hwcheck();
+	if (current == auditdaemon_task_struct || AUDIT_IS_PAUSED)
+		return (0);
+
+	if (current->saudit_record) {
+		return (1);
+	}
+	// alloc the audit record
+	current->saudit_record = kmalloc(sizeof(cp_class), GFP_KERNEL);
+	if (!current->saudit_record) {
+		return (0);
+	}
+
+	record = (cp_class *) current->saudit_record;
+
+	// Filename.
+	GrabString(record->t_sourcepath.path, kfrom, ufrom, MAX_PATH);
+	GrabString(record->t_destpath.path, kto, uto, MAX_PATH);
+
+	record->t_header.event_id = AUDIT_symlink;
+	record->t_header.event_class = AUDIT_CLASS_CP;
+
+	saudit_return(retval);
+	return (1);
+}
+
+int _audit_link(const char *kfrom, const char *ufrom, const char *kto,
+	       const char *uto, int retval)
+{
+	cp_class *record;
+
+	// If noone has requested the system call to be active, return quickly.
+	if (!saudit_active(AUDIT_link))
+		return (0);
+	audit_hwcheck();
+	if (current == auditdaemon_task_struct || AUDIT_IS_PAUSED)
+		return (0);
+
+	if (current->saudit_record) {
+		return (1);
+	}
+	// alloc the audit record
+	current->saudit_record = kmalloc(sizeof(cp_class), GFP_KERNEL);
+	if (!current->saudit_record) {
+		return (0);
+	}
+
+	record = (cp_class *) current->saudit_record;
+
+	// Filename.
+	GrabString(record->t_sourcepath.path, kfrom, ufrom, MAX_PATH);
+	GrabString(record->t_destpath.path, kto, uto, MAX_PATH);
+
+	record->t_header.event_id = AUDIT_link;
+	record->t_header.event_class = AUDIT_CLASS_CP;
+
+	saudit_return(retval);
+	return (1);
+}
+
+int _audit_rename(const char *kfrom, const char *ufrom, const char *kto,
+		 const char *uto, int retval)
+{
+	cp_class *record;
+
+	// If noone has requested the system call to be active, return quickly.
+	if (!saudit_active(AUDIT_rename))
+		return (0);
+	audit_hwcheck();
+	if (current == auditdaemon_task_struct || AUDIT_IS_PAUSED)
+		return (0);
+	if (current->saudit_record)
+		return (1);
+
+	// alloc the audit record
+	current->saudit_record = kmalloc(sizeof(cp_class), GFP_KERNEL);
+	if (!current->saudit_record) {
+		return (0);
+	}
+
+	record = (cp_class *) current->saudit_record;
+
+	// Filename.
+	GrabString(record->t_sourcepath.path, kfrom, ufrom, MAX_PATH);
+	GrabString(record->t_destpath.path, kto, uto, MAX_PATH);
+
+	record->t_header.event_id = AUDIT_rename;
+	record->t_header.event_class = AUDIT_CLASS_CP;
+	saudit_return(retval);
+	return (1);
+}
+
+// Truncate - note that we need to grab the data from userspace.
+int _audit_truncate(const char *kfile, const char *ufile, loff_t length,
+		   int retval)
+{
+	io_class *record;
+
+	// If noone has requested the system call to be active, return quickly.
+	if (!saudit_active(AUDIT_truncate))
+		return (0);
+	audit_hwcheck();
+	if (current == auditdaemon_task_struct || AUDIT_IS_PAUSED)
+		return (0);
+
+	if (current->saudit_record) {
+		return (1);
+	}
+	// alloc the audit record
+	current->saudit_record = kmalloc(sizeof(io_class), GFP_KERNEL);
+	if (!current->saudit_record) {
+		return (0);
+	}
+
+	record = (io_class *) current->saudit_record;
+
+	// Filename.
+	GrabString(record->t_path.path, kfile, ufile, MAX_PATH);
+
+	record->t_attributes.createmode = (unsigned long) length;
+
+	record->t_header.event_id = AUDIT_truncate;
+	record->t_header.event_class = AUDIT_CLASS_IO;
+	saudit_return(retval);
+	return (1);
+}
+
+int _audit_chroot(const char *kfile, const char *ufile, int retval)
+{
+	io_class *record;
+
+	// If noone has requested the system call to be active, return quickly.
+	if (!saudit_active(AUDIT_chroot))
+		return (0);
+	audit_hwcheck();
+	if (current == auditdaemon_task_struct || AUDIT_IS_PAUSED)
+		return (0);
+
+	if (current->saudit_record) {
+		return (1);
+	}
+	// alloc the audit record
+	current->saudit_record = kmalloc(sizeof(io_class), GFP_KERNEL);
+	if (!current->saudit_record) {
+		return (0);
+	}
+
+	record = (io_class *) current->saudit_record;
+
+	// Filename.
+	GrabString(record->t_path.path, kfile, ufile, MAX_PATH);
+
+	record->t_attributes.createmode = (unsigned long) 0;
+
+	record->t_header.event_id = AUDIT_chroot;
+	record->t_header.event_class = AUDIT_CLASS_IO;
+
+	saudit_return(retval);
+	return (1);
+}
+
+int _audit_mount(const char *kdev_name, const char *udev_name,
+		const char *kdir_name, const char *udir_name,
+		unsigned long flags, int retval)
+{
+	cp_class *record;
+
+	// If noone has requested the system call to be active, return quickly.
+	if (!saudit_active(AUDIT_mount))
+		return (0);
+
+	audit_hwcheck();
+	if (current == auditdaemon_task_struct || AUDIT_IS_PAUSED)
+		return (0);
+	if (current->saudit_record)
+		return (1);
+
+	// alloc the audit record
+	current->saudit_record = kmalloc(sizeof(cp_class), GFP_KERNEL);
+	if (!current->saudit_record) {
+		return (0);
+	}
+
+	record = (cp_class *) current->saudit_record;
+
+	GrabString(record->t_sourcepath.path, kdev_name, udev_name,
+		   MAX_PATH);
+	GrabString(record->t_destpath.path, kdir_name, udir_name,
+		   MAX_PATH);
+
+	record->t_header.event_id = AUDIT_mount;
+	record->t_header.event_class = AUDIT_CLASS_CP;
+
+	saudit_return(retval);
+	return (1);
+}
+
+int _audit_umount(const char *kname, const char *uname, int flags,
+		 int retval)
+{
+	cp_class *record;
+
+	// If noone has requested the system call to be active, return quickly.
+	if (!saudit_active(AUDIT_umount))
+		return (0);
+	audit_hwcheck();
+	if (current == auditdaemon_task_struct || AUDIT_IS_PAUSED)
+		return (0);
+	if (current->saudit_record)
+		return (1);
+
+	// alloc the audit record
+	current->saudit_record = kmalloc(sizeof(cp_class), GFP_KERNEL);
+	if (!current->saudit_record) {
+		return (0);
+	}
+
+	record = (cp_class *) current->saudit_record;
+
+	record->t_sourcepath.path[0] = '\0';
+	// Name has not yet been grabbed from userspace by sys_umount
+	// Copy it from userspace here.
+	GrabString(record->t_sourcepath.path, kname, uname, MAX_PATH);
+
+	record->t_destpath.path[0] = '\0';
+
+	record->t_header.event_id = AUDIT_umount;
+	record->t_header.event_class = AUDIT_CLASS_CP;
+	saudit_return(retval);
+	return (1);
+}
+
+int _audit_setuid(uid_t uid, int retval)
+{
+	su_class *record;
+
+	// If noone has requested the system call to be active, return quickly.
+	if (!saudit_active(AUDIT_setuid))
+		return (0);
+	audit_hwcheck();
+	if (current == auditdaemon_task_struct || AUDIT_IS_PAUSED)
+		return (0);
+	if (current->saudit_record)
+		return (1);
+
+	// alloc the audit record
+	current->saudit_record = kmalloc(sizeof(su_class), GFP_KERNEL);
+	if (!current->saudit_record) {
+		return (0);
+	}
+
+	record = (su_class *) current->saudit_record;
+
+	record->t_target.id = uid;
+
+	record->t_header.event_id = AUDIT_setuid;
+	record->t_header.event_class = AUDIT_CLASS_SU;
+	saudit_return(retval);
+	return (1);
+}
+
+int _audit_setreuid(uid_t ruid, uid_t euid, int retval)
+{
+	su_class *record;
+
+	// If noone has requested the system call to be active, return quickly.
+	if (!saudit_active(AUDIT_setreuid))
+		return (0);
+	audit_hwcheck();
+	if (current == auditdaemon_task_struct || AUDIT_IS_PAUSED)
+		return (0);
+	if (current->saudit_record)
+		return (1);
+
+	// alloc the audit record
+	current->saudit_record = kmalloc(sizeof(su_class), GFP_KERNEL);
+	if (!current->saudit_record) {
+		return (0);
+	}
+
+	record = (su_class *) current->saudit_record;
+
+	record->t_target.id = euid;
+	record->t_target.rid = ruid;
+
+	record->t_header.event_id = AUDIT_setreuid;
+	record->t_header.event_class = AUDIT_CLASS_SU;
+	saudit_return(retval);
+	return (1);
+}
+
+int _audit_setresuid(uid_t ruid, uid_t euid, uid_t suid, int retval)
+{
+	su_class *record;
+
+	// If noone has requested the system call to be active, return quickly.
+	if (!saudit_active(AUDIT_setresuid))
+		return (0);
+	audit_hwcheck();
+	if (current == auditdaemon_task_struct || AUDIT_IS_PAUSED)
+		return (0);
+	if (current->saudit_record)
+		return (1);
+
+	// alloc the audit record
+	current->saudit_record = kmalloc(sizeof(su_class), GFP_KERNEL);
+	if (!current->saudit_record) {
+		return (0);
+	}
+
+	record = (su_class *) current->saudit_record;
+
+	record->t_target.id = euid;
+	record->t_target.rid = ruid;
+	record->t_target.sid = suid;
+
+	record->t_header.event_id = AUDIT_setresuid;
+	record->t_header.event_class = AUDIT_CLASS_SU;
+	saudit_return(retval);
+	return (1);
+}
+
+int _audit_setregid(gid_t rgid, gid_t egid, int retval)
+{
+	su_class *record;
+
+	// If noone has requested the system call to be active, return quickly.
+	if (!saudit_active(AUDIT_setregid))
+		return (0);
+	audit_hwcheck();
+	if (current == auditdaemon_task_struct || AUDIT_IS_PAUSED)
+		return (0);
+	if (current->saudit_record)
+		return (1);
+
+	// alloc the audit record
+	current->saudit_record = kmalloc(sizeof(su_class), GFP_KERNEL);
+	if (!current->saudit_record) {
+		return (0);
+	}
+
+	record = (su_class *) current->saudit_record;
+
+	record->t_target.id = egid;
+	record->t_target.rid = rgid;
+
+	record->t_header.event_id = AUDIT_setregid;
+	record->t_header.event_class = AUDIT_CLASS_SU;
+	saudit_return(retval);
+	return (1);
+}
+
+int _audit_setresgid(gid_t rgid, gid_t egid, gid_t sgid, int retval)
+{
+	su_class *record;
+
+	// If noone has requested the system call to be active, return quickly.
+	if (!saudit_active(AUDIT_setresgid))
+		return (0);
+	audit_hwcheck();
+	if (current == auditdaemon_task_struct || AUDIT_IS_PAUSED)
+		return (0);
+	if (current->saudit_record)
+		return (1);
+
+	// alloc the audit record
+	current->saudit_record = kmalloc(sizeof(su_class), GFP_KERNEL);
+	if (!current->saudit_record) {
+		return (0);
+	}
+
+	record = (su_class *) current->saudit_record;
+
+	record->t_target.id = egid;
+	record->t_target.rid = rgid;
+	record->t_target.sid = sgid;
+
+	record->t_header.event_id = AUDIT_setresgid;
+	record->t_header.event_class = AUDIT_CLASS_SU;
+	saudit_return(retval);
+	return (1);
+}
+
+int _audit_setgid(gid_t gid, int retval)
+{
+	su_class *record;
+
+	// If noone has requested the system call to be active, return quickly.
+	if (!saudit_active(AUDIT_setgid))
+		return (0);
+	audit_hwcheck();
+	if (current == auditdaemon_task_struct || AUDIT_IS_PAUSED)
+		return (0);
+	if (current->saudit_record)
+		return (1);
+
+	// alloc the audit record
+	current->saudit_record = kmalloc(sizeof(su_class), GFP_KERNEL);
+	if (!current->saudit_record) {
+		return (0);
+	}
+
+	record = (su_class *) current->saudit_record;
+
+	record->t_target.id = gid;
+
+	record->t_header.event_id = AUDIT_setgid;
+	record->t_header.event_class = AUDIT_CLASS_SU;
+	saudit_return(retval);
+	return (1);
+}
+
+// Create module
+int _audit_create_module(const char *kname, const char *uname, int retval)
+{
+	ad_class *record;
+
+	// If noone has requested the system call to be active, return quickly.
+	if (!saudit_active(AUDIT_create_module))
+		return (0);
+	audit_hwcheck();
+	if (current == auditdaemon_task_struct || AUDIT_IS_PAUSED)
+		return (0);
+
+	if (current->saudit_record) {
+		return (1);
+	}
+	// alloc the audit record
+	current->saudit_record = kmalloc(sizeof(ad_class), GFP_KERNEL);
+	if (!current->saudit_record) {
+		return (0);
+	}
+
+	record = (ad_class *) current->saudit_record;
+
+	// Module name
+	GrabString(record->t_name.path, kname, uname, MAX_PATH);
+
+	record->t_header.event_id = AUDIT_create_module;
+	record->t_header.event_class = AUDIT_CLASS_AD;
+	saudit_return(retval);
+	return (1);
+}
+
+// Delete module
+int _audit_delete_module(const char *kname, const char *uname, int retval)
+{
+	ad_class *record;
+
+	// If noone has requested the system call to be active, return quickly.
+	if (!saudit_active(AUDIT_delete_module))
+		return (0);
+	audit_hwcheck();
+	if (current == auditdaemon_task_struct || AUDIT_IS_PAUSED)
+		return (0);
+
+	if (current->saudit_record) {
+		return (1);
+	}
+	// alloc the audit record
+	current->saudit_record = kmalloc(sizeof(ad_class), GFP_KERNEL);
+	if (!current->saudit_record) {
+		return (0);
+	}
+
+	record = (ad_class *) current->saudit_record;
+
+	// Module name
+	GrabString(record->t_name.path, kname, uname, MAX_PATH);
+
+	record->t_header.event_id = AUDIT_delete_module;
+	record->t_header.event_class = AUDIT_CLASS_AD;
+	saudit_return(retval);
+	return (1);
+}
+
+int _audit_reboot(int magic1, int magic2, unsigned int cmd, void *arg,
+		 int retval)
+{
+	pc_class *record;
+
+	// If noone has requested the system call to be active, return quickly.
+	if (!saudit_active(AUDIT_reboot))
+		return (0);
+	audit_hwcheck();
+	if (current == auditdaemon_task_struct || AUDIT_IS_PAUSED)
+		return (0);
+	if (current->saudit_record)
+		return (1);
+
+	// alloc the audit record
+	current->saudit_record = kmalloc(sizeof(pc_class), GFP_KERNEL);
+	if (!current->saudit_record) {
+		return (0);
+	}
+
+	record = (pc_class *) current->saudit_record;
+	record->t_header.event_id = AUDIT_reboot;
+	record->t_header.event_class = AUDIT_CLASS_PC;
+	saudit_return(retval);
+	return (1);
+}
+
+int _audit_connect(int sockfd, struct sockaddr *serv_addr, int addrlen,
+		  int retval)
+{
+	nt_class *record;
+	struct socket *sock;
+	int err;
+	struct sockaddr_in *si;
+
+	// If noone has requested the system call to be active, return quickly.
+	if (!saudit_active(AUDIT_connect)) {
+		return (0);
+	}
+
+	audit_hwcheck();
+	if (current == auditdaemon_task_struct || AUDIT_IS_PAUSED)
+		return (0);
+	if (current->saudit_record)
+		return (0);
+
+	// If this is not an AF_INET, drop it.
+	if (!serv_addr) {
+		return (0);
+	}
+	if (serv_addr->sa_family != AF_INET) {
+		return (0);
+	}
+
+	if (serv_addr->sa_data) {
+		return (0);
+	}
+
+	// alloc the audit record
+	current->saudit_record = kmalloc(sizeof(nt_class), GFP_KERNEL);
+	if (!current->saudit_record) {
+		return (0);
+	}
+
+	record = (nt_class *) current->saudit_record;
+	record->t_header.event_id = AUDIT_connect;
+	record->t_header.event_class = AUDIT_CLASS_NET;
+
+	snprintf(record->t_connection.dst_ip, 16, "%u.%u.%u.%u",
+		 serv_addr->sa_data[2] & 255,
+		 serv_addr->sa_data[3] & 255,
+		 serv_addr->sa_data[4] & 255, serv_addr->sa_data[5] & 255);
+	strncpy(record->t_connection.src_ip, "127.0.0.1", 16);
+
+	si = (struct sockaddr_in *) serv_addr;
+
+	record->t_connection.src_port = 0;
+	record->t_connection.dst_port = ntohs(si->sin_port);
+
+	record->t_connection.protocol = 0;
+
+	if(sockfd) {
+		if ((sock = sockfd_lookup(sockfd, &err)) != NULL) {
+			record->t_connection.src_port = sock->sk->num;
+			record->t_connection.protocol = sock->sk->protocol;
+			fput(sock->file);
+		}
+	}
+	saudit_return(retval);
+	return (1);
+}
+
+int _audit_accept(int sockfd, struct sockaddr *peer_addr, int *addrlen,
+		 int retval)
+{
+	nt_class *record;
+	struct sockaddr_in *si;
+	struct socket *sock;
+	int err;
+
+	// If noone has requested the system call to be active, return quickly.
+	if (!saudit_active(AUDIT_accept)) {
+		return (0);
+	}
+
+	audit_hwcheck();
+	if (current == auditdaemon_task_struct || AUDIT_IS_PAUSED)
+		return (0);
+	if (current->saudit_record)
+		return (0);
+
+	// If this is not an AF_INET, drop it.
+	if (!peer_addr) {
+		return (0);
+	}
+	if (peer_addr->sa_family != AF_INET) {
+		return (0);
+	}
+
+	if (peer_addr->sa_data) {
+		return (0);
+	}
+	// alloc the audit record
+	current->saudit_record = kmalloc(sizeof(nt_class), GFP_KERNEL);
+	if (!current->saudit_record) {
+		return (0);
+	}
+
+	record = (nt_class *) current->saudit_record;
+	record->t_header.event_id = AUDIT_accept;
+	record->t_header.event_class = AUDIT_CLASS_NET;
+
+	snprintf(record->t_connection.src_ip, 16, "%u.%u.%u.%u",
+		 peer_addr->sa_data[2] & 255,
+		 peer_addr->sa_data[3] & 255,
+		 peer_addr->sa_data[4] & 255, peer_addr->sa_data[5] & 255);
+	strncpy(record->t_connection.dst_ip, "127.0.0.1", 16);
+
+	si = (struct sockaddr_in *) peer_addr;
+
+	record->t_connection.dst_port = 0;
+	record->t_connection.src_port = ntohs(si->sin_port);
+
+	record->t_connection.protocol = 0;
+
+	if(sockfd) {
+		if ((sock = sockfd_lookup(sockfd, &err)) != NULL) {
+			record->t_connection.dst_port = ntohs(sock->sk->sport);
+			record->t_connection.protocol = sock->sk->protocol;
+			fput(sock->file);
+		}
+	}
+	saudit_return(retval);
+	return (1);
+}
+
+int saudit_return(int returncode)
+{
+	// The static null_class and timeval were changed to 
+	// Local varable for smp machines
+
+	int class;
+	null_class *any_event;
+	AuditNode *node = (AuditNode *) NULL;
+	struct timeval time_temp;
+
+	if (!auditdaemon_task_struct) {
+		goto out;
+	}
+
+	if (current == auditdaemon_task_struct) {
+		return (0);
+	}
+
+	// Unaudited event
+	if (!current->saudit_record) {
+		goto out;
+	}
+
+	any_event = current->saudit_record;
+
+	do_gettimeofday(&time_temp);
+
+	class = any_event->t_header.event_class;
+
+	// Fill out as much of the header structure as we can.
+	any_event->t_header.user_id = current->uid;
+	any_event->t_header.group_id = current->gid;
+	any_event->t_header.euser_id = current->euid;
+	any_event->t_header.egroup_id = current->egid;
+	any_event->t_header.time.tv_sec = time_temp.tv_sec;
+	any_event->t_header.time.tv_usec = time_temp.tv_usec;
+	any_event->t_header.returncode = returncode;
+	strncpy(any_event->t_header.processname, current->comm,
+		MAXCOMMAND);
+	any_event->t_header.pid = current->pid;
+
+#if defined(SNARE_RED_HAT_LINUX_KERNEL)
+	// Note: RHEL 2.4.18 doesn't have current->parent..
+	if (current->parent) {
+		any_event->t_header.ppid = current->parent->pid;
+	} else {
+		any_event->t_header.ppid = 0;
+	}
+#else
+	if(current->p_pptr) {
+		any_event->t_header.ppid=current->p_pptr->pid;
+	} else {
+		any_event->t_header.ppid=0;
+	}
+#endif
+
+	// Modified by Mark Westerman Replaced the if else code with
+	// a switch to help perfromace.
+	switch (class) {
+	case AUDIT_CLASS_IO:
+		{
+			io_class *record;
+			char tmp[MAX_PATH];
+			record = (io_class *) current->saudit_record;
+
+			// Current PWD - IO CLASS, EXEC, CH, CP
+			// NOTE: This will just tell you the file name the user
+			// tried to access. If it's linked to another file, or
+			// from a mountpoint, it will just show you the filename
+			// used in the system call - not the RESOLVED path.
+			strncpy(record->t_pwd.path,
+				d_path(current->fs->pwd,
+				       current->fs->pwdmnt, tmp, MAX_PATH),
+				MAX_PATH);
+
+			record->t_header.event_size =
+			    sizeof(io_class) - sizeof(header_token);
+
+			if ((node = alloc_event(sizeof(io_class))) == NULL) {
+				goto out;
+			}
+			node->location=record;
+		}
+		break;
+	case AUDIT_CLASS_EXEC:
+		{
+			ex_class *record;
+			char tmp[MAX_PATH];
+			record = (ex_class *) current->saudit_record;
+
+			// Current PWD - IO CLASS, EXEC, CH, CP
+			strncpy(record->t_pwd.path,
+				d_path(current->fs->pwd,
+				       current->fs->pwdmnt, tmp, MAX_PATH),
+				MAX_PATH);
+
+			record->t_header.event_size =
+			    sizeof(ex_class) - sizeof(header_token);
+
+			if ((node = alloc_event(sizeof(ex_class))) == NULL) {
+				goto out;
+			}
+			node->location=record;
+		}
+		break;
+	case AUDIT_CLASS_PC:
+		{
+			pc_class *record;
+			record = (pc_class *) current->saudit_record;
+
+			// Current PWD - IO CLASS, EXEC, CH, CP
+			record->t_header.event_size =
+			    sizeof(pc_class) - sizeof(header_token);
+
+			if ((node = alloc_event(sizeof(pc_class))) == NULL) {
+				goto out;
+			}
+			node->location=record;
+		}
+		break;
+	case AUDIT_CLASS_CH:
+		{
+			ch_class *record;
+			char tmp[MAX_PATH];
+			record = (ch_class *) current->saudit_record;
+
+			// Current PWD - IO CLASS, EXEC, CH, CP
+			strncpy(record->t_pwd.path,
+				d_path(current->fs->pwd,
+				       current->fs->pwdmnt, tmp, MAX_PATH),
+				MAX_PATH);
+			record->t_header.event_size =
+			    sizeof(ch_class) - sizeof(header_token);
+
+			if ((node = alloc_event(sizeof(ch_class))) == NULL) {
+				goto out;
+			}
+			node->location=record;
+		}
+		break;
+	case AUDIT_CLASS_CP:
+		{
+			cp_class *record;
+			char tmp[MAX_PATH];
+			record = (cp_class *) current->saudit_record;
+
+			// Current PWD - IO CLASS, EXEC, CH, CP
+			strncpy(record->t_pwd.path,
+				d_path(current->fs->pwd,
+				       current->fs->pwdmnt, tmp, MAX_PATH),
+				MAX_PATH);
+			record->t_header.event_size =
+			    sizeof(cp_class) - sizeof(header_token);
+
+			if ((node = alloc_event(sizeof(cp_class))) == NULL) {
+				goto out;
+			}
+			node->location=record;
+		}
+		break;
+	case AUDIT_CLASS_SU:
+		{
+			su_class *record;
+			record = (su_class *) current->saudit_record;
+
+			record->t_header.event_size =
+			    sizeof(su_class) - sizeof(header_token);
+
+			if ((node = alloc_event(sizeof(su_class))) == NULL) {
+				goto out;
+			}
+			node->location=record;
+		}
+		break;
+	case AUDIT_CLASS_AD:
+		{
+			ad_class *record;
+			record = (ad_class *) current->saudit_record;
+
+			record->t_header.event_size =
+			    sizeof(ad_class) - sizeof(header_token);
+
+			if ((node = alloc_event(sizeof(ad_class))) == NULL) {
+				goto out;
+			}
+			node->location=record;
+		}
+		break;
+	case AUDIT_CLASS_NET:
+		{
+			nt_class *record;
+			record = (nt_class *) current->saudit_record;
+
+			record->t_header.event_size =
+			    sizeof(nt_class) - sizeof(header_token);
+
+			if ((node = alloc_event(sizeof(nt_class))) == NULL) {
+				goto out;
+			}
+			node->location=record;
+
+		}
+		break;
+	default:
+		printk("Auditing Invalid class\n");
+	}
+
+	// Cant free this here.. we're still using it.
+	current->saudit_record = NULL;
+
+	// Send the audit record out the door.
+	append_event(node);
+	wake_up_interruptible(&proc_audit_queue);
+
+	return (1);
+
+      out:
+	if (current->saudit_record) {
+		current->saudit_record = NULL;
+	}
+	if(auditdaemon_task_struct) {
+		down(&audit_lock);
+		lost_events++;
+		up(&audit_lock);
+	}
+	return (0);
+}
+
+static void append_event(AuditNode * nodepointer)
+{
+	down(&audit_lock);
+
+	if (list_tail != (AuditNode *) NULL) {
+		list_tail->next = nodepointer;
+	}
+
+	list_tail = nodepointer;
+
+	// Is this the first node in our linked list?
+	if (list_head == (AuditNode *) NULL) {
+		list_head = nodepointer;
+	}
+	memory_usage += nodepointer->size;
+	++total_events;
+	up(&audit_lock);
+}
+
+AuditNode *alloc_event(int token_size)
+{
+	AuditNode *nodepointer;
+
+	nodepointer = (AuditNode *) kmalloc(sizeof(AuditNode), GFP_KERNEL);
+	if (nodepointer == (AuditNode *) NULL) {
+		return (0);
+	}
+
+	nodepointer->location = (void *)NULL;
+	nodepointer->size = token_size;
+	nodepointer->next = (AuditNode *) NULL;	// This is the end.
+	return nodepointer;
+}
+
+// This grabs data from either kernel or userspace into a string.
+long GrabString(char *destination, const char *kernelstring,
+		const char *userstring, int length)
+{
+	if (!destination)
+		return (0);
+
+	if (length < 1)
+		return (0);
+
+	if (!userstring && !kernelstring) {
+		strncpy(destination, "AUDIT: Invalid data", length);
+		return (0);
+	}
+
+	if (kernelstring) {
+		strncpy(destination, kernelstring, length);
+		return (1);
+	} else {
+		if (strncpy_from_user(destination, userstring, length) ==
+		    -EFAULT) {
+			strncpy(destination, "AUDIT: Invalid data",
+				length);
+			return (0);
+		}
+		return (1);
+	}
+}
diff -Nur linux-2.4.21-40.EL/saudit/Makefile linux-2.4.21-40.EL-snare/saudit/Makefile
--- linux-2.4.21-40.EL/saudit/Makefile	1970-01-01 10:00:00.000000000 +1000
+++ linux-2.4.21-40.EL-snare/saudit/Makefile	2006-04-12 02:04:10.000000000 +1000
@@ -0,0 +1,17 @@
+#
+# Makefile for the linux audit.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definition is now in the main makefile...
+
+O_TARGET := audit.o
+
+export-objs = auditapi.o
+
+# obj-$(CONFIG_C2_AUDIT) += auditapi.o
+obj-y += auditapi.o
+
+include $(TOPDIR)/Rules.make
