rpms/kernel/devel linux-2.6-audit-fix-operators.patch, NONE, 1.1.2.1 linux-2.6-audit-git.patch, NONE, 1.1.10.1 linux-2.6-audit-inotify-api.patch, NONE, 1.1.4.1 linux-2.6-audit-no-rules-speedup.patch, NONE, 1.1.2.1 linux-2.6-audit-promisc.patch, NONE, 1.1.6.1 linux-2.6-audit-rule-log.patch, NONE, 1.1.6.1 linux-2.6-audit-string-1.patch, NONE, 1.1.6.1 linux-2.6-audit-string-2.patch, NONE, 1.1.6.1 linux-2.6-audit-tty.patch, NONE, 1.1.6.1 linux-2.6-audit_log_exit-gfp_mask.patch, NONE, 1.1.2.1 kernel-2.6.spec, 1.1959, 1.1959.2.1

fedora-cvs-commits at redhat.com fedora-cvs-commits at redhat.com
Mon Feb 20 19:56:53 UTC 2006


Author: sgrubb

Update of /cvs/dist/rpms/kernel/devel
In directory cvs.devel.redhat.com:/tmp/cvs-serv23829

Modified Files:
      Tag: private-fc5-lspp-branch
	kernel-2.6.spec 
Added Files:
      Tag: private-fc5-lspp-branch
	linux-2.6-audit-fix-operators.patch linux-2.6-audit-git.patch 
	linux-2.6-audit-inotify-api.patch 
	linux-2.6-audit-no-rules-speedup.patch 
	linux-2.6-audit-promisc.patch linux-2.6-audit-rule-log.patch 
	linux-2.6-audit-string-1.patch linux-2.6-audit-string-2.patch 
	linux-2.6-audit-tty.patch 
	linux-2.6-audit_log_exit-gfp_mask.patch 
Log Message:
Patches for lspp9 kernel


linux-2.6-audit-fix-operators.patch:
 auditfilter.c |   16 ++++++++++------
 1 files changed, 10 insertions(+), 6 deletions(-)

--- NEW FILE linux-2.6-audit-fix-operators.patch ---
>From dustin.kirkland at us.ibm.com Thu Feb 16 14:40:01 2006
Return-Path: <linux-audit-bounces at redhat.com>
Received: from mail.boston.redhat.com ([unix socket])
	by mail.boston.redhat.com (Cyrus v2.1.12) with LMTP; Thu, 16 Feb 2006 14:40:31 -0500
X-Sieve: CMU Sieve 2.2
Received: from int-mx1.corp.redhat.com (int-mx1.corp.redhat.com [172.16.52.254])
	by mail.boston.redhat.com (8.12.8/8.12.8) with ESMTP id k1GJeVi7015183;
	Thu, 16 Feb 2006 14:40:31 -0500
Received: from mx1.util.phx.redhat.com (mx1.util.phx.redhat.com [10.8.4.92])
	by int-mx1.corp.redhat.com (8.11.6/8.11.6) with ESMTP id k1GJeN124283;
	Thu, 16 Feb 2006 14:40:23 -0500
Received: from hormel.redhat.com (hormel.util.phx.redhat.com [10.8.4.111])
	by mx1.util.phx.redhat.com (8.13.1/8.13.1) with ESMTP id k1GJeISC009512;
	Thu, 16 Feb 2006 14:40:18 -0500
Received: from listman.util.phx.redhat.com (listman.util.phx.redhat.com [10.8.4.110])
	by hormel.redhat.com (Postfix) with ESMTP
	id 5FA4A73083; Thu, 16 Feb 2006 14:40:18 -0500 (EST)
Received: from int-mx1.corp.redhat.com (int-mx1.corp.redhat.com
	[172.16.52.254])
	by listman.util.phx.redhat.com (8.13.1/8.13.1) with ESMTP id
	k1GJeGRW016720 for <linux-audit at listman.util.phx.redhat.com>;
	Thu, 16 Feb 2006 14:40:16 -0500
Received: from mx1.redhat.com (mx1.redhat.com [172.16.48.31])
	by int-mx1.corp.redhat.com (8.11.6/8.11.6) with ESMTP id k1GJeF124129
	for <linux-audit at redhat.com>; Thu, 16 Feb 2006 14:40:15 -0500
Received: from e33.co.us.ibm.com (e33.co.us.ibm.com [32.97.110.151])
	by mx1.redhat.com (8.12.11/8.12.11) with ESMTP id k1GJeFU3032558
	for <linux-audit at redhat.com>; Thu, 16 Feb 2006 14:40:15 -0500
Received: from d03relay04.boulder.ibm.com (d03relay04.boulder.ibm.com
	[9.17.195.106])
	by e33.co.us.ibm.com (8.12.11/8.12.11) with ESMTP id k1GJe5Ls030154
	for <linux-audit at redhat.com>; Thu, 16 Feb 2006 14:40:05 -0500
Received: from d03av04.boulder.ibm.com (d03av04.boulder.ibm.com [9.17.195.170])
	by d03relay04.boulder.ibm.com (8.12.10/NCO/VERS6.8) with ESMTP id
	k1GJgbM7180628
	for <linux-audit at redhat.com>; Thu, 16 Feb 2006 12:42:39 -0700
Received: from d03av04.boulder.ibm.com (loopback [127.0.0.1])
	by d03av04.boulder.ibm.com (8.12.11/8.13.3) with ESMTP id
	k1GJe3Uo012219
	for <linux-audit at redhat.com>; Thu, 16 Feb 2006 12:40:03 -0700
Received: from kirkland1.austin.ibm.com (kirkland1.austin.ibm.com [9.53.40.52])
	by d03av04.boulder.ibm.com (8.12.11/8.12.11) with ESMTP id
	k1GJe2mY012185
	for <linux-audit at redhat.com>; Thu, 16 Feb 2006 12:40:02 -0700
From: Dustin Kirkland <dustin.kirkland at us.ibm.com>
To: Linux Audit Discussion <linux-audit at redhat.com>
Content-Type: text/plain
Date: Thu, 16 Feb 2006 13:40:01 -0600
Message-Id: <1140118802.3083.97.camel at kirkland1.austin.ibm.com>
Mime-Version: 1.0
X-Mailer: Evolution 2.2.3 (2.2.3-2.fc4) 
Content-Transfer-Encoding: 7bit
X-RedHat-Spam-Score: 0.261 
X-loop: linux-audit at redhat.com
Subject: [PATCH] Fix audit operators
X-BeenThere: linux-audit at redhat.com
X-Mailman-Version: 2.1.5
Precedence: junk
Reply-To: dustin.kirkland at us.ibm.com
List-Id: Linux Audit Discussion <linux-audit.redhat.com>
List-Unsubscribe: <https://www.redhat.com/mailman/listinfo/linux-audit>,
	<mailto:linux-audit-request at redhat.com?subject=unsubscribe>
List-Archive: <https://www.redhat.com/archives/linux-audit>
List-Post: <mailto:linux-audit at redhat.com>
List-Help: <mailto:linux-audit-request at redhat.com?subject=help>
List-Subscribe: <https://www.redhat.com/mailman/listinfo/linux-audit>,
	<mailto:linux-audit-request at redhat.com?subject=subscribe>
Sender: linux-audit-bounces at redhat.com
Errors-To: linux-audit-bounces at redhat.com
X-Length: 6684
X-UID: 49954

Darrel Goeddel initiated a discussion on IRC regarding the possibility
of audit_comparator() returning -EINVAL signaling an invalid operator.

It is possible when creating the rule to assure that the operator is one
of the 6 sane values.  Here's a snip from include/linux/audit.h  Note
that 0 (nonsense) and 7 (all operators) are not valid values for an
operator.

...
#define AUDIT_NEGATE                    0x80000000

/* These are the supported operators.
 *      4  2  1
 *      =  >  <
 *      -------
 *      0  0  0         0       nonsense
 *      0  0  1         1       <
 *      0  1  0         2       >
 *      0  1  1         3       !=
 *      1  0  0         4       =
 *      1  0  1         5       <=
 *      1  1  0         6       >=
 *      1  1  1         7       all operators
 */
#define AUDIT_LESS_THAN                 0x10000000
#define AUDIT_GREATER_THAN              0x20000000
#define AUDIT_NOT_EQUAL                 0x30000000
#define AUDIT_EQUAL                     0x40000000
#define AUDIT_LESS_THAN_OR_EQUAL        (AUDIT_LESS_THAN|AUDIT_EQUAL)
#define AUDIT_GREATER_THAN_OR_EQUAL     (AUDIT_GREATER_THAN|AUDIT_EQUAL)
#define AUDIT_OPERATORS                 (AUDIT_EQUAL|AUDIT_NOT_EQUAL)
...

Furthermore, prior to adding these extended operators, flagging the
AUDIT_NEGATE bit implied !=, and otherwise == was assumed.

The following code forces the operator to be != if the AUDIT_NEGATE bit
was flipped on.  And if no operator was specified, == is assumed.  The
only invalid condition is if the AUDIT_NEGATE bit is off and all of the
AUDIT_EQUAL, AUDIT_LESS_THAN, and AUDIT_GREATER_THAN bits are
on--clearly a nonsensical operator.

Now that this is handled at rule insertion time, the default -EINVAL
return of audit_comparator() is eliminated such that the function can
only return 1 or 0.

If this is acceptable, let's get this applied to the current tree.

:-Dustin

--

diff -urpN a/kernel/auditfilter.c b/kernel/auditfilter.c
--- a/kernel/auditfilter.c	2006-02-16 11:57:17.000000000 -0600
+++ b/kernel/auditfilter.c	2006-02-16 13:30:33.000000000 -0600
@@ -139,11 +139,17 @@ static struct audit_entry *audit_rule_to
 		f->val = rule->values[i];
 
 		entry->rule.vers_ops = (f->op & AUDIT_OPERATORS) ? 2 : 1;
+
+		/* Support for legacy operators where
+		 * AUDIT_NEGATE bit signifies != and otherwise assumes == */
 		if (f->op & AUDIT_NEGATE)
-			f->op |= AUDIT_NOT_EQUAL;
-		else if (!(f->op & AUDIT_OPERATORS))
-			f->op |= AUDIT_EQUAL;
-		f->op &= ~AUDIT_NEGATE;
+			f->op = AUDIT_NOT_EQUAL;
+		else if (!f->op)
+			f->op = AUDIT_EQUAL;
+		else if (f->op == AUDIT_OPERATORS) {
+			err = -EINVAL;
+			goto exit_free;
+		}
 	}
 
 exit_nofree:
@@ -537,8 +543,6 @@ int audit_comparator(const u32 left, con
 		return (left > right);
 	case AUDIT_GREATER_THAN_OR_EQUAL:
 		return (left >= right);
-	default:
-		return -EINVAL;
 	}
 }
 


--
Linux-audit mailing list
Linux-audit at redhat.com
https://www.redhat.com/mailman/listinfo/linux-audit


linux-2.6-audit-git.patch:
 arch/ia64/kernel/ptrace.c      |   10 
 fs/namei.c                     |   14 
 fs/open.c                      |    8 
 fs/xattr.c                     |   11 
 include/linux/audit.h          |   98 ++++-
 include/linux/fsnotify.h       |   14 
 include/linux/security.h       |   33 +
 ipc/msg.c                      |    5 
 ipc/sem.c                      |    5 
 ipc/shm.c                      |    4 
 ipc/util.c                     |    2 
 kernel/Makefile                |    2 
 kernel/audit.c                 |  142 +++++--
 kernel/audit.h                 |   70 +++
 kernel/auditfilter.c           |  375 +++++++++++++++++++
 kernel/auditsc.c               |  786 +++++++++++++++++++++--------------------
 security/dummy.c               |   14 
 security/selinux/hooks.c       |   98 ++---
 security/selinux/nlmsgtab.c    |    6 
 security/selinux/selinuxfs.c   |   11 
 security/selinux/ss/services.c |   15 
 21 files changed, 1204 insertions(+), 519 deletions(-)

--- NEW FILE linux-2.6-audit-git.patch ---
diff --git a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c
index 4b19d04..49fd3f6 100644
--- a/arch/ia64/kernel/ptrace.c
+++ b/arch/ia64/kernel/ptrace.c
@@ -1663,8 +1663,14 @@ syscall_trace_leave (long arg0, long arg
 		     long arg4, long arg5, long arg6, long arg7,
 		     struct pt_regs regs)
 {
-	if (unlikely(current->audit_context))
-		audit_syscall_exit(current, AUDITSC_RESULT(regs.r10), regs.r8);
+	if (unlikely(current->audit_context)) {
+		int success = AUDITSC_RESULT(regs.r10);
+		long result = regs.r8;
+
+		if (success != AUDITSC_SUCCESS)
+			result = -result;
+		audit_syscall_exit(current, success, result);
+	}
 
 	if (test_thread_flag(TIF_SYSCALL_TRACE)
 	    && (current->ptrace & PT_PTRACED))
diff --git a/fs/namei.c b/fs/namei.c
index 6dbbd42..55798c3 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1126,8 +1126,7 @@ int fastcall path_lookup(const char *nam
 	retval = link_path_walk(name, nd);
 out:
	if (likely(retval == 0)) {
-		if (unlikely(current->audit_context && nd && nd->dentry &&
-				nd->dentry->d_inode))
+		if (nd && nd->dentry && nd->dentry->d_inode)
 		audit_inode(name, nd->dentry->d_inode, flags);
	}
 	return retval;
@@ -1301,6 +1300,7 @@ static inline int may_delete(struct inod
 		return -ENOENT;
 
 	BUG_ON(victim->d_parent->d_inode != dir);
+	audit_inode_child(victim->d_name.name, victim->d_inode, dir->i_ino);
 
 	error = permission(dir,MAY_WRITE | MAY_EXEC, NULL);
 	if (error)
@@ -1420,7 +1420,7 @@ int vfs_create(struct inode *dir, struct
 	DQUOT_INIT(dir);
 	error = dir->i_op->create(dir, dentry, mode, nd);
 	if (!error)
-		fsnotify_create(dir, dentry->d_name.name);
+		fsnotify_create(dir, dentry);
 	return error;
 }
 
@@ -1739,7 +1739,7 @@ int vfs_mknod(struct inode *dir, struct 
 	DQUOT_INIT(dir);
 	error = dir->i_op->mknod(dir, dentry, mode, dev);
 	if (!error)
-		fsnotify_create(dir, dentry->d_name.name);
+		fsnotify_create(dir, dentry);
 	return error;
 }
 
@@ -1810,7 +1810,7 @@ int vfs_mkdir(struct inode *dir, struct 
 	DQUOT_INIT(dir);
 	error = dir->i_op->mkdir(dir, dentry, mode);
 	if (!error)
-		fsnotify_mkdir(dir, dentry->d_name.name);
+		fsnotify_mkdir(dir, dentry);
 	return error;
 }
 
@@ -2047,7 +2047,7 @@ int vfs_symlink(struct inode *dir, struc
 	DQUOT_INIT(dir);
 	error = dir->i_op->symlink(dir, dentry, oldname);
 	if (!error)
-		fsnotify_create(dir, dentry->d_name.name);
+		fsnotify_create(dir, dentry);
 	return error;
 }
 
@@ -2118,7 +2118,7 @@ int vfs_link(struct dentry *old_dentry, 
 	error = dir->i_op->link(old_dentry, dir, new_dentry);
 	up(&old_dentry->d_inode->i_sem);
 	if (!error)
-		fsnotify_create(dir, new_dentry->d_name.name);
+		fsnotify_create(dir, new_dentry);
 	return error;
 }
 
diff --git a/fs/open.c b/fs/open.c
index f53a5b9..3231a67 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -25,6 +25,7 @@
 #include <linux/pagemap.h>
 #include <linux/syscalls.h>
 #include <linux/rcupdate.h>
+#include <linux/audit.h>
 
 #include <asm/unistd.h>
 
@@ -613,6 +614,8 @@ asmlinkage long sys_fchmod(unsigned int 
 	dentry = file->f_dentry;
 	inode = dentry->d_inode;
 
+	audit_inode(NULL, inode, 0);
+
 	err = -EROFS;
 	if (IS_RDONLY(inode))
 		goto out_putf;
@@ -736,7 +739,10 @@ asmlinkage long sys_fchown(unsigned int 
 
 	file = fget(fd);
 	if (file) {
-		error = chown_common(file->f_dentry, user, group);
+		struct dentry * dentry;
+		dentry = file->f_dentry;
+		audit_inode(NULL, dentry->d_inode, 0);
+		error = chown_common(dentry, user, group);
 		fput(file);
 	}
 	return error;
diff --git a/fs/xattr.c b/fs/xattr.c
index bcc2156..8f40edf 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -17,6 +17,7 @@
 #include <linux/syscalls.h>
 #include <linux/module.h>
 #include <linux/fsnotify.h>
+#include <linux/audit.h>
 #include <asm/uaccess.h>
 
 /*
@@ -113,12 +114,15 @@ sys_fsetxattr(int fd, char __user *name,
 	      size_t size, int flags)
 {
 	struct file *f;
+	struct dentry *dentry;
 	int error = -EBADF;
 
 	f = fget(fd);
 	if (!f)
 		return error;
-	error = setxattr(f->f_dentry, name, value, size, flags);
+	dentry = f->f_dentry;
+	audit_inode(NULL, dentry->d_inode, 0);
+	error = setxattr(dentry, name, value, size, flags);
 	fput(f);
 	return error;
 }
@@ -365,12 +369,15 @@ asmlinkage long
 sys_fremovexattr(int fd, char __user *name)
 {
 	struct file *f;
+	struct dentry *dentry;
 	int error = -EBADF;
 
 	f = fget(fd);
 	if (!f)
 		return error;
-	error = removexattr(f->f_dentry, name);
+	dentry = f->f_dentry;
+	audit_inode(NULL, dentry->d_inode, 0);
+	error = removexattr(dentry, name);
 	fput(f);
 	return error;
 }
diff --git a/include/linux/audit.h b/include/linux/audit.h
index da3c019..a485639 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -33,11 +33,20 @@
  * 1200 - 1299 messages internal to the audit daemon
  * 1300 - 1399 audit event messages
  * 1400 - 1499 SE Linux use
- * 1500 - 1999 future use
- * 2000 is for otherwise unclassified kernel audit messages
+ * 1500 - 1599 kernel LSPP events
+ * 1600 - 1699 kernel crypto events
+ * 1700 - 1999 future kernel use (maybe integrity labels and related events)
+ * 2000 is for otherwise unclassified kernel audit messages (legacy)
+ * 2001 - 2099 unused (kernel)
+ * 2100 - 2199 user space anomaly records
+ * 2200 - 2299 user space actions taken in response to anomalies
+ * 2300 - 2399 user space generated LSPP events
+ * 2400 - 2499 user space crypto events
+ * 2500 - 2999 future user space (maybe integrity labels and related events)
  *
- * Messages from 1000-1199 are bi-directional. 1200-1299 are exclusively user
- * space. Anything over that is kernel --> user space communication.
+ * Messages from 1000-1199 are bi-directional. 1200-1299 & 2100 - 2999 are
+ * exclusively user space. 1300-2099 is kernel --> user space 
+ * communication.
  */
 #define AUDIT_GET		1000	/* Get status */
 #define AUDIT_SET		1001	/* Set status (enable/disable/auditd) */
@@ -54,6 +63,8 @@
 #define AUDIT_FIRST_USER_MSG	1100	/* Userspace messages mostly uninteresting to kernel */
 #define AUDIT_USER_AVC		1107	/* We filter this differently */
[...2439 lines suppressed...]
-		rc = -EOPNOTSUPP;
-		goto out;
-	}
-
-	rc = security_sid_to_context(isec->sid, &context, &len);
-	if (rc)
-		goto out;
-
-	/* Probe for required buffer size */
-	if (!buffer || !size) {
-		rc = len;
-		goto out_free;
-	}
 
-	if (size < len) {
-		rc = -ERANGE;
-		goto out_free;
-	}
+	if (strcmp(name, XATTR_SELINUX_SUFFIX))
+		return -EOPNOTSUPP;
 
-	if (err > 0) {
-		if ((len == err) && !(memcmp(context, buffer, len))) {
-			/* Don't need to canonicalize value */
-			rc = err;
-			goto out_free;
-		}
-		memset(buffer, 0, size);
-	}
-	memcpy(buffer, context, len);
-	rc = len;
-out_free:
-	kfree(context);
-out:
-	return rc;
+	return selinux_getsecurity(isec->sid, buffer, size);
 }
 
 static int selinux_inode_setsecurity(struct inode *inode, const char *name,
@@ -4054,6 +4052,13 @@ static int selinux_ipc_permission(struct
 	return ipc_has_perm(ipcp, av);
 }
 
+static int selinux_ipc_getsecurity(struct kern_ipc_perm *ipcp, void *buffer, size_t size)
+{
+	struct ipc_security_struct *isec = ipcp->security;
+
+	return selinux_getsecurity(isec->sid, buffer, size);
+}
+
 /* module stacking operations */
 static int selinux_register_security (const char *name, struct security_operations *ops)
 {
@@ -4095,8 +4100,7 @@ static int selinux_getprocattr(struct ta
 			       char *name, void *value, size_t size)
 {
 	struct task_security_struct *tsec;
-	u32 sid, len;
-	char *context;
+	u32 sid;
 	int error;
 
 	if (current != p) {
@@ -4105,9 +4109,6 @@ static int selinux_getprocattr(struct ta
 			return error;
 	}
 
-	if (!size)
-		return -ERANGE;
-
 	tsec = p->security;
 
 	if (!strcmp(name, "current"))
@@ -4124,16 +4125,7 @@ static int selinux_getprocattr(struct ta
 	if (!sid)
 		return 0;
 
-	error = security_sid_to_context(sid, &context, &len);
-	if (error)
-		return error;
-	if (len > size) {
-		kfree(context);
-		return -ERANGE;
-	}
-	memcpy(value, context, len);
-	kfree(context);
-	return len;
+	return selinux_getsecurity(sid, value, size);
 }
 
 static int selinux_setprocattr(struct task_struct *p,
@@ -4291,6 +4283,7 @@ static struct security_operations selinu
 	.inode_getxattr =		selinux_inode_getxattr,
 	.inode_listxattr =		selinux_inode_listxattr,
 	.inode_removexattr =		selinux_inode_removexattr,
+	.inode_xattr_getsuffix =        selinux_inode_xattr_getsuffix,
 	.inode_getsecurity =            selinux_inode_getsecurity,
 	.inode_setsecurity =            selinux_inode_setsecurity,
 	.inode_listsecurity =           selinux_inode_listsecurity,
@@ -4328,6 +4321,7 @@ static struct security_operations selinu
 	.task_to_inode =                selinux_task_to_inode,
 
 	.ipc_permission =		selinux_ipc_permission,
+	.ipc_getsecurity =		selinux_ipc_getsecurity,
 
 	.msg_msg_alloc_security =	selinux_msg_msg_alloc_security,
 	.msg_msg_free_security =	selinux_msg_msg_free_security,
diff --git a/security/selinux/nlmsgtab.c b/security/selinux/nlmsgtab.c
index 69b9329..d7c0e91 100644
--- a/security/selinux/nlmsgtab.c
+++ b/security/selinux/nlmsgtab.c
@@ -148,8 +148,10 @@ int selinux_nlmsg_lookup(u16 sclass, u16
 		break;
 
 	case SECCLASS_NETLINK_AUDIT_SOCKET:
-		if (nlmsg_type >= AUDIT_FIRST_USER_MSG &&
-		    nlmsg_type <= AUDIT_LAST_USER_MSG) {
+		if ((nlmsg_type >= AUDIT_FIRST_USER_MSG &&
+		     nlmsg_type <= AUDIT_LAST_USER_MSG) ||
+		    (nlmsg_type >= AUDIT_FIRST_USER_MSG2 &&
+                     nlmsg_type <= AUDIT_LAST_USER_MSG2)) {
 			*perm = NETLINK_AUDIT_SOCKET__NLMSG_RELAY;
 		} else {
 			err = nlmsg_perm(nlmsg_type, perm, nlmsg_audit_perms,
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index 0e1352a..e64923b 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -21,6 +21,7 @@
 #include <linux/major.h>
 #include <linux/seq_file.h>
 #include <linux/percpu.h>
+#include <linux/audit.h>
 #include <asm/uaccess.h>
 #include <asm/semaphore.h>
 
@@ -126,6 +127,10 @@ static ssize_t sel_write_enforce(struct 
 		length = task_has_security(current, SECURITY__SETENFORCE);
 		if (length)
 			goto out;
+		audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_STATUS,
+			"enforcing=%d old_enforcing=%d auid=%u", new_value, 
+			selinux_enforcing,
+			audit_get_loginuid(current->audit_context));
 		selinux_enforcing = new_value;
 		if (selinux_enforcing)
 			avc_ss_reset(0);
@@ -176,6 +181,9 @@ static ssize_t sel_write_disable(struct 
 		length = selinux_disable();
 		if (length < 0)
 			goto out;
+		audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_STATUS,
+			"selinux=0 auid=%u",
+			audit_get_loginuid(current->audit_context));
 	}
 
 	length = count;
@@ -261,6 +269,9 @@ static ssize_t sel_write_load(struct fil
 		length = ret;
 	else
 		length = count;
+	audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_POLICY_LOAD,
+		"policy loaded auid=%u",
+		audit_get_loginuid(current->audit_context));
 out:
 	up(&sel_sem);
 	vfree(data);
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 44eb4d7..2311255 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -1758,19 +1758,22 @@ int security_set_bools(int len, int *val
 		goto out;
 	}
 
-	printk(KERN_INFO "security: committed booleans { ");
 	for (i = 0; i < len; i++) {
+		if (!!values[i] != policydb.bool_val_to_struct[i]->state) {
+			audit_log(current->audit_context, GFP_ATOMIC,
+				AUDIT_MAC_CONFIG_CHANGE,
+				"bool=%s val=%d old_val=%d auid=%u",
+				policydb.p_bool_val_to_name[i],
+				!!values[i],
+				policydb.bool_val_to_struct[i]->state,
+				audit_get_loginuid(current->audit_context));
+		}
 		if (values[i]) {
 			policydb.bool_val_to_struct[i]->state = 1;
 		} else {
 			policydb.bool_val_to_struct[i]->state = 0;
 		}
-		if (i != 0)
-			printk(", ");
-		printk("%s:%d", policydb.p_bool_val_to_name[i],
-		       policydb.bool_val_to_struct[i]->state);
 	}
-	printk(" }\n");
 
 	for (cur = policydb.cond_list; cur != NULL; cur = cur->next) {
 		rc = evaluate_cond_node(&policydb, cur);

linux-2.6-audit-inotify-api.patch:
 fs/inotify.c             |  395 +++++++++++++++++++++++++++++------------------
 include/linux/fsnotify.h |   29 +--
 include/linux/inotify.h  |   17 +-
 3 files changed, 279 insertions(+), 162 deletions(-)

--- NEW FILE linux-2.6-audit-inotify-api.patch ---
>From amy.griffis at hp.com Thu Feb  9 14:07:59 2006
Return-Path: <linux-audit-bounces at redhat.com>
Received: from mail.boston.redhat.com ([unix socket])
	by mail.boston.redhat.com (Cyrus v2.1.12) with LMTP; Thu, 09 Feb 2006 14:08:27 -0500
X-Sieve: CMU Sieve 2.2
Received: from int-mx1.corp.redhat.com (int-mx1.corp.redhat.com [172.16.52.254])
	by mail.boston.redhat.com (8.12.8/8.12.8) with ESMTP id k19J8QQo003353;
	Thu, 9 Feb 2006 14:08:27 -0500
Received: from mx1.util.phx.redhat.com (mx1.util.phx.redhat.com [10.8.4.92])
	by int-mx1.corp.redhat.com (8.11.6/8.11.6) with ESMTP id k19J8N110283;
	Thu, 9 Feb 2006 14:08:23 -0500
Received: from hormel.redhat.com (hormel.util.phx.redhat.com [10.8.4.111])
	by mx1.util.phx.redhat.com (8.13.1/8.13.1) with ESMTP id k19J8Imo011143;
	Thu, 9 Feb 2006 14:08:18 -0500
Received: from listman.util.phx.redhat.com (listman.util.phx.redhat.com [10.8.4.110])
	by hormel.redhat.com (Postfix) with ESMTP
	id 67C5573351; Thu,  9 Feb 2006 14:08:18 -0500 (EST)
Received: from int-mx1.corp.redhat.com (int-mx1.corp.redhat.com
	[172.16.52.254])
	by listman.util.phx.redhat.com (8.13.1/8.13.1) with ESMTP id
	k19J8GKS020511 for <linux-audit at listman.util.phx.redhat.com>;
	Thu, 9 Feb 2006 14:08:16 -0500
Received: from mx3.redhat.com (mx3.redhat.com [172.16.48.32])
	by int-mx1.corp.redhat.com (8.11.6/8.11.6) with ESMTP id k19J8G110252; 
	Thu, 9 Feb 2006 14:08:16 -0500
Received: from tayrelbas01.tay.hp.com (tayrelbas01.tay.hp.com [161.114.80.244])
	by mx3.redhat.com (8.13.1/8.13.1) with ESMTP id k19J85qE016990;
	Thu, 9 Feb 2006 14:08:05 -0500
Received: from tayrelint01.nz-tay.cpqcorp.net (tayrelint01.nz-tay.cpqcorp.net
	[16.47.5.6])
	by tayrelbas01.tay.hp.com (Postfix) with ESMTP id CA77434016;
	Thu,  9 Feb 2006 14:08:01 -0500 (EST)
Received: from dill.zko.hp.com (dill.zko.hp.com [16.116.96.242])
	by tayrelint01.nz-tay.cpqcorp.net (Postfix) with ESMTP id 5E6F03405E;
	Thu,  9 Feb 2006 14:07:59 -0500 (EST)
Received: by dill.zko.hp.com (Postfix, from userid 10412)
	id 44F1C38448A3; Thu,  9 Feb 2006 14:07:59 -0500 (EST)
Date: Thu, 9 Feb 2006 14:07:59 -0500
From: Amy Griffis <amy.griffis at hp.com>
To: linux-audit at redhat.com
Message-ID: <20060209190759.GB9652 at zk3.dec.com>
Mail-Followup-To: linux-audit at redhat.com, aviro at redhat.com
References: <200602091009.16523.sgrubb at redhat.com>
Mime-Version: 1.0
Content-Type: text/plain;
  charset=us-ascii
Content-Disposition: inline
In-Reply-To: <200602091009.16523.sgrubb at redhat.com>
X-Mailer: Mutt http://www.mutt.org/
X-Editor: Vim http://www.vim.org/
User-Agent: Mutt/1.5.10i
X-RedHat-Spam-Score: -100 
X-loop: linux-audit at redhat.com
Cc: aviro at redhat.com
Subject: Re: git tree
X-BeenThere: linux-audit at redhat.com
X-Mailman-Version: 2.1.5
Precedence: junk
List-Id: Linux Audit Discussion <linux-audit.redhat.com>
List-Unsubscribe: <https://www.redhat.com/mailman/listinfo/linux-audit>,
	<mailto:linux-audit-request at redhat.com?subject=unsubscribe>
List-Archive: <https://www.redhat.com/archives/linux-audit>
List-Post: <mailto:linux-audit at redhat.com>
List-Help: <mailto:linux-audit-request at redhat.com?subject=help>
List-Subscribe: <https://www.redhat.com/mailman/listinfo/linux-audit>,
	<mailto:linux-audit-request at redhat.com?subject=subscribe>
Sender: linux-audit-bounces at redhat.com
Errors-To: linux-audit-bounces at redhat.com
X-Length: 25658
X-UID: 48537
Status: RO
X-Status: ORC
X-KMail-EncryptionState: N
X-KMail-SignatureState: N
X-KMail-MDN-Sent:  

Hi Al,

Steve Grubb wrote:     [Thu Feb 09 2006, 10:09:16AM EST]
> >From Al:
> 
>        OK...  Untangling the mess around ppoll/unshare for backport to
> 2.6.15-based tree turns out to be just too messy.  Therefore,
> git://git.kernel.org/pub/scm/linux/kernel/git/viro/audit-current.git/
> contains the tree based on Linus' current.  Branches:
>         * origin = mainline
>         * audit = ported stuff, that's where everything got to settle
> 
> Amy, I've moved 3 of 4 patches to current tree; please see if they
> are OK (the 3rd might be worth a look)

Looks good, except in 3rd patch fs/inotify.c should have:

#@@ -628,7 +628,7 @@ s32 inotify_add_watch(struct inotify_dev
# 		mask_add = 1;
# 
# 	/* don't let user-space set invalid bits: we don't want flags set */
#-	mask &= IN_ALL_EVENTS;
#+	mask &= IN_ALL_EVENTS | IN_ONESHOT;
# 	if (unlikely(!mask)) {
# 		ret = -EINVAL;
# 		goto out;

Here's the full diff with this change:

diff --git a/fs/inotify.c b/fs/inotify.c
index 3041503..ab57df6 100644
--- a/fs/inotify.c
+++ b/fs/inotify.c
@@ -85,14 +85,18 @@ struct inotify_device {
 	wait_queue_head_t 	wq;		/* wait queue for i/o */
 	struct idr		idr;		/* idr mapping wd -> watch */
 	struct semaphore	sem;		/* protects this bad boy */
-	struct list_head 	events;		/* list of queued events */
 	struct list_head	watches;	/* list of watches */
 	atomic_t		count;		/* reference count */
+	u32			last_wd;	/* the last wd allocated */
+	/* userland consumer API */
+	struct list_head 	events;		/* list of queued events */
 	struct user_struct	*user;		/* user who opened this dev */
 	unsigned int		queue_size;	/* size of the queue (bytes) */
 	unsigned int		event_count;	/* number of pending events */
 	unsigned int		max_events;	/* maximum number of events */
-	u32			last_wd;	/* the last wd allocated */
+	/* kernel consumer API */
+	void (*callback)(struct inotify_event *, const char *, struct inode *,
+			 void *);		/* event callback */
 };
 
 /*
@@ -124,6 +128,7 @@ struct inotify_watch {
 	struct inode		*inode;	/* associated inode */
 	s32 			wd;	/* watch descriptor */
 	u32			mask;	/* event mask for this watch */
+	void		*callback_arg;	/* callback argument - kernel API */
 };
 
 #ifdef CONFIG_SYSCTL
@@ -175,8 +180,10 @@ static inline void get_inotify_dev(struc
 static inline void put_inotify_dev(struct inotify_device *dev)
 {
 	if (atomic_dec_and_test(&dev->count)) {
-		atomic_dec(&dev->user->inotify_devs);
-		free_uid(dev->user);
+		if (dev->user) {
+			atomic_dec(&dev->user->inotify_devs);
+			free_uid(dev->user);
+		}
 		idr_destroy(&dev->idr);
 		kfree(dev);
 	}
@@ -344,6 +351,24 @@ static void inotify_dev_event_dequeue(st
 }
 
 /*
+ * inotify_callback_event - notify kernel consumers of events
+ */
+static void inotify_callback_event(struct inotify_device *dev,
+				   struct inotify_watch *watch,
+				   u32 mask, u32 cookie, const char *name,
+				   struct inode *inode)
+{
+	struct inotify_event event;
+
+	event.wd = watch->wd;
+	event.mask = mask;
+	event.cookie = cookie;
+	event.len = 0; /* kernel consumers don't need length */
+
+	dev->callback(&event, name, inode, watch->callback_arg);
+}
+
+/*
  * inotify_dev_get_wd - returns the next WD for use by the given dev
  *
  * Callers must hold dev->sem.  This function can sleep.
@@ -387,12 +412,13 @@ static int find_inode(const char __user 
  * Both 'dev' and 'inode' (by way of nameidata) need to be pinned.
  */
 static struct inotify_watch *create_watch(struct inotify_device *dev,
-					  u32 mask, struct inode *inode)
+					  u32 mask, struct inode *inode,
+					  void *callback_arg)
 {
 	struct inotify_watch *watch;
 	int ret;
 
-	if (atomic_read(&dev->user->inotify_watches) >=
+	if (dev->user && atomic_read(&dev->user->inotify_watches) >=
 			inotify_max_user_watches)
 		return ERR_PTR(-ENOSPC);
 
@@ -408,6 +434,7 @@ static struct inotify_watch *create_watc
 
 	dev->last_wd = watch->wd;
 	watch->mask = mask;
+	watch->callback_arg = callback_arg;
 	atomic_set(&watch->count, 0);
 	INIT_LIST_HEAD(&watch->d_list);
 	INIT_LIST_HEAD(&watch->i_list);
@@ -425,7 +452,8 @@ static struct inotify_watch *create_watc
 	/* bump our own count, corresponding to our entry in dev->watches */
 	get_inotify_watch(watch);
 
-	atomic_inc(&dev->user->inotify_watches);
+	if (dev->user)
+		atomic_inc(&dev->user->inotify_watches);
 	atomic_inc(&inotify_watches);
 
 	return watch;
@@ -458,7 +486,8 @@ static void remove_watch_no_event(struct
 	list_del(&watch->i_list);
 	list_del(&watch->d_list);
 
-	atomic_dec(&dev->user->inotify_watches);
+	if (dev->user)
+		atomic_dec(&dev->user->inotify_watches);
 	atomic_dec(&inotify_watches);
 	idr_remove(&dev->idr, watch->wd);
 	put_inotify_watch(watch);
@@ -477,7 +506,10 @@ static void remove_watch_no_event(struct
  */
 static void remove_watch(struct inotify_watch *watch,struct inotify_device *dev)
 {
-	inotify_dev_queue_event(dev, watch, IN_IGNORED, 0, NULL);
+	if (dev->callback)
+		inotify_callback_event(dev, watch, IN_IGNORED, 0, NULL, NULL);
+	else
+		inotify_dev_queue_event(dev, watch, IN_IGNORED, 0, NULL);
 	remove_watch_no_event(watch, dev);
 }
 
@@ -490,7 +522,190 @@ static inline int inotify_inode_watched(
 	return !list_empty(&inode->inotify_watches);
 }
 
-/* Kernel API */
+/* Kernel consumer API */
+
+/**
+ * inotify_init - allocates and initializes an inotify device
+ * @callback: kernel consumer's event callback
+ */
+struct inotify_device *inotify_init(void (*callback)(struct inotify_event *,
+						     const char *,
+						     struct inode *, void *))
+{
+	struct inotify_device *dev;
+
+	dev = kmalloc(sizeof(struct inotify_device), GFP_KERNEL);
+	if (unlikely(!dev))
+		return NULL;
+
+	idr_init(&dev->idr);
+	INIT_LIST_HEAD(&dev->events);
+	INIT_LIST_HEAD(&dev->watches);
+	init_waitqueue_head(&dev->wq);
+	sema_init(&dev->sem, 1);
+	dev->event_count = 0;
+	dev->queue_size = 0;
+	dev->max_events = inotify_max_queued_events;
+	dev->user = NULL;	/* set in sys_inotify_init */
+	dev->last_wd = 0;
+	dev->callback = callback;
+	atomic_set(&dev->count, 0);
+	get_inotify_dev(dev);
+
+	return dev;
+}
+EXPORT_SYMBOL_GPL(inotify_init);
+
+/**
+ * inotify_free - clean up and free an inotify device
+ * @dev: inotify device to free
+ */
+int inotify_free(struct inotify_device *dev)
+{
+	/*
+	 * Destroy all of the watches on this device.  Unfortunately, not very
+	 * pretty.  We cannot do a simple iteration over the list, because we
+	 * do not know the inode until we iterate to the watch.  But we need to
+	 * hold inode->inotify_sem before dev->sem.  The following works.
+	 */
+	while (1) {
+		struct inotify_watch *watch;
+		struct list_head *watches;
+		struct inode *inode;
+
+		down(&dev->sem);
+		watches = &dev->watches;
+		if (list_empty(watches)) {
+			up(&dev->sem);
+			break;
+		}
+		watch = list_entry(watches->next, struct inotify_watch, d_list);
+		get_inotify_watch(watch);
+		up(&dev->sem);
+
+		inode = watch->inode;
+		down(&inode->inotify_sem);
+		down(&dev->sem);
+		remove_watch_no_event(watch, dev);
+		up(&dev->sem);
+		up(&inode->inotify_sem);
+		put_inotify_watch(watch);
+	}
+
+	/* destroy all of the events on this device */
+	down(&dev->sem);
+	while (!list_empty(&dev->events))
+		inotify_dev_event_dequeue(dev);
+	up(&dev->sem);
+
+	/* free this device: the put matching the get in inotify_init() */
+	put_inotify_dev(dev);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(inotify_free);
+
+/**
+ * inotify_inotify_add_watch - add a watch to this inotify device
+ * @dev: inotify device
+ * @inode: inode to watch for events
+ * @mask: filesystem event mask
+ * @callback_arg - ptr to data that kernel consumer associates with this watch
+ *
+ * Caller must pin the inode in question, e.g. by calling path_lookup.
+ */
+s32 inotify_add_watch(struct inotify_device *dev, struct inode *inode,
+		      u32 mask, void *callback_arg)
+{
+	int mask_add = 0;
+	struct inotify_watch *watch, *old;
+	int ret;
+
+	down(&inode->inotify_sem);
+	down(&dev->sem);
+
+	if (mask & IN_MASK_ADD)
+		mask_add = 1;
+
+	/* don't let user-space set invalid bits: we don't want flags set */
+	mask &= IN_ALL_EVENTS | IN_ONESHOT;
+	if (unlikely(!mask)) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	/*
+	 * Handle the case of re-adding a watch on an (inode,dev) pair that we
+	 * are already watching.  We just update the mask and callback_arg and
+	 * return its wd.
+	 */
+	old = inode_find_dev(inode, dev);
+	if (unlikely(old)) {
+		if (mask_add)
+			old->mask |= mask;
+		else
+			old->mask = mask;
+		old->callback_arg = callback_arg;
+		ret = old->wd;
+		goto out;
+	}
+
+	watch = create_watch(dev, mask, inode, callback_arg);
+	if (unlikely(IS_ERR(watch))) {
+		ret = PTR_ERR(watch);
+		goto out;
+	}
+
+	/* Add the watch to the device's and the inode's list */
+	list_add(&watch->d_list, &dev->watches);
+	list_add(&watch->i_list, &inode->inotify_watches);
+	ret = watch->wd;
+
+out:
+	up(&dev->sem);
+	up(&inode->inotify_sem);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(inotify_add_watch);
+
+/**
+ * inotify_ignore - remove a given wd from this inotify device
+ * @dev: inotify device
+ * @wd: watch descriptor to remove
+ */
+int inotify_ignore(struct inotify_device *dev, s32 wd)
+{
+	struct inotify_watch *watch;
+	struct inode *inode;
+
+	down(&dev->sem);
+	watch = idr_find(&dev->idr, wd);
+	if (unlikely(!watch)) {
+		up(&dev->sem);
+		return -EINVAL;
+	}
+	get_inotify_watch(watch);
+	inode = watch->inode;
+	up(&dev->sem);
+
+	down(&inode->inotify_sem);
+	down(&dev->sem);
+
+	/* make sure that we did not race */
+	watch = idr_find(&dev->idr, wd);
+	if (likely(watch))
+		remove_watch(watch, dev);
+
+	up(&dev->sem);
+	up(&inode->inotify_sem);
+	put_inotify_watch(watch);
+
+	return 0;
+
+}
+EXPORT_SYMBOL_GPL(inotify_ignore);
+
+/* Kernel producer API */
 
 /**
  * inotify_inode_queue_event - queue an event to all watches on this inode
@@ -498,9 +713,10 @@ static inline int inotify_inode_watched(
  * @mask: event mask describing this event
  * @cookie: cookie for synchronization, or zero
  * @name: filename, if any
+ * @cinode: child inode, used for events on directories
  */
 void inotify_inode_queue_event(struct inode *inode, u32 mask, u32 cookie,
-			       const char *name)
+			       const char *name, struct inode *cinode)
 {
 	struct inotify_watch *watch, *next;
 
@@ -514,7 +730,12 @@ void inotify_inode_queue_event(struct in
 			struct inotify_device *dev = watch->dev;
 			get_inotify_watch(watch);
 			down(&dev->sem);
-			inotify_dev_queue_event(dev, watch, mask, cookie, name);
+			if (dev->callback)
+				inotify_callback_event(dev, watch, mask,
+						       cookie, name, cinode);
+			else
+				inotify_dev_queue_event(dev, watch, mask,
+							cookie, name);
 			if (watch_mask & IN_ONESHOT)
 				remove_watch_no_event(watch, dev);
 			up(&dev->sem);
@@ -548,7 +769,8 @@ void inotify_dentry_parent_queue_event(s
 	if (inotify_inode_watched(inode)) {
 		dget(parent);
 		spin_unlock(&dentry->d_lock);
-		inotify_inode_queue_event(inode, mask, cookie, name);
+		inotify_inode_queue_event(inode, mask, cookie, name,
+					  dentry->d_inode);
 		dput(parent);
 	} else
 		spin_unlock(&dentry->d_lock);
@@ -631,7 +853,12 @@ void inotify_unmount_inodes(struct list_
 		list_for_each_entry_safe(watch, next_w, watches, i_list) {
 			struct inotify_device *dev = watch->dev;
 			down(&dev->sem);
-			inotify_dev_queue_event(dev, watch, IN_UNMOUNT,0,NULL);
+			if (dev->callback)
+				inotify_callback_event(dev, watch, IN_UNMOUNT,
+						       0, NULL, NULL);
+			else
+				inotify_dev_queue_event(dev, watch, IN_UNMOUNT,
+							0, NULL);
 			remove_watch(watch, dev);
 			up(&dev->sem);
 		}
@@ -757,83 +984,7 @@ static ssize_t inotify_read(struct file 
 
 static int inotify_release(struct inode *ignored, struct file *file)
 {
-	struct inotify_device *dev = file->private_data;
-
-	/*
-	 * Destroy all of the watches on this device.  Unfortunately, not very
-	 * pretty.  We cannot do a simple iteration over the list, because we
-	 * do not know the inode until we iterate to the watch.  But we need to
-	 * hold inode->inotify_sem before dev->sem.  The following works.
-	 */
-	while (1) {
-		struct inotify_watch *watch;
-		struct list_head *watches;
-		struct inode *inode;
-
-		down(&dev->sem);
-		watches = &dev->watches;
-		if (list_empty(watches)) {
-			up(&dev->sem);
-			break;
-		}
-		watch = list_entry(watches->next, struct inotify_watch, d_list);
-		get_inotify_watch(watch);
-		up(&dev->sem);
-
-		inode = watch->inode;
-		down(&inode->inotify_sem);
-		down(&dev->sem);
-		remove_watch_no_event(watch, dev);
-		up(&dev->sem);
-		up(&inode->inotify_sem);
-		put_inotify_watch(watch);
-	}
-
-	/* destroy all of the events on this device */
-	down(&dev->sem);
-	while (!list_empty(&dev->events))
-		inotify_dev_event_dequeue(dev);
-	up(&dev->sem);
-
-	/* free this device: the put matching the get in inotify_init() */
-	put_inotify_dev(dev);
-
-	return 0;
-}
-
-/*
- * inotify_ignore - remove a given wd from this inotify instance.
- *
- * Can sleep.
- */
-static int inotify_ignore(struct inotify_device *dev, s32 wd)
-{
-	struct inotify_watch *watch;
-	struct inode *inode;
-
-	down(&dev->sem);
-	watch = idr_find(&dev->idr, wd);
-	if (unlikely(!watch)) {
-		up(&dev->sem);
-		return -EINVAL;
-	}
-	get_inotify_watch(watch);
-	inode = watch->inode;
-	up(&dev->sem);
-
-	down(&inode->inotify_sem);
-	down(&dev->sem);
-
-	/* make sure that we did not race */
-	watch = idr_find(&dev->idr, wd);
-	if (likely(watch))
-		remove_watch(watch, dev);
-
-	up(&dev->sem);
-	up(&inode->inotify_sem);
-	put_inotify_watch(watch);
-
-	return 0;
+	return inotify_free(file->private_data);
 }
 
 static long inotify_ioctl(struct file *file, unsigned int cmd,
@@ -887,12 +1038,15 @@ asmlinkage long sys_inotify_init(void)
 		goto out_free_uid;
 	}
 
-	dev = kmalloc(sizeof(struct inotify_device), GFP_KERNEL);
+	dev = inotify_init(NULL);
 	if (unlikely(!dev)) {
 		ret = -ENOMEM;
 		goto out_free_uid;
 	}
 
+	dev->user = user;
+	atomic_inc(&user->inotify_devs);
+
 	filp->f_op = &inotify_fops;
 	filp->f_vfsmnt = mntget(inotify_mnt);
 	filp->f_dentry = dget(inotify_mnt->mnt_root);
@@ -901,20 +1055,6 @@ asmlinkage long sys_inotify_init(void)
 	filp->f_flags = O_RDONLY;
 	filp->private_data = dev;
 
-	idr_init(&dev->idr);
-	INIT_LIST_HEAD(&dev->events);
-	INIT_LIST_HEAD(&dev->watches);
-	init_waitqueue_head(&dev->wq);
-	sema_init(&dev->sem, 1);
-	dev->event_count = 0;
-	dev->queue_size = 0;
-	dev->max_events = inotify_max_queued_events;
-	dev->user = user;
-	dev->last_wd = 0;
-	atomic_set(&dev->count, 0);
-
-	get_inotify_dev(dev);
-	atomic_inc(&user->inotify_devs);
 	fd_install(fd, filp);
 
 	return fd;
@@ -928,13 +1068,11 @@ out_put_fd:
 
 asmlinkage long sys_inotify_add_watch(int fd, const char __user *path, u32 mask)
 {
-	struct inotify_watch *watch, *old;
 	struct inode *inode;
 	struct inotify_device *dev;
 	struct nameidata nd;
 	struct file *filp;
 	int ret, fput_needed;
-	int mask_add = 0;
 	unsigned flags = 0;
 
 	filp = fget_light(fd, &fput_needed);
@@ -960,46 +1098,7 @@ asmlinkage long sys_inotify_add_watch(in
 	inode = nd.dentry->d_inode;
 	dev = filp->private_data;
 
-	down(&inode->inotify_sem);
-	down(&dev->sem);
-
-	if (mask & IN_MASK_ADD)
-		mask_add = 1;
-
-	/* don't let user-space set invalid bits: we don't want flags set */
-	mask &= IN_ALL_EVENTS | IN_ONESHOT;
-	if (unlikely(!mask)) {
-		ret = -EINVAL;
-		goto out;
-	}
-
-	/*
-	 * Handle the case of re-adding a watch on an (inode,dev) pair that we
-	 * are already watching.  We just update the mask and return its wd.
-	 */
-	old = inode_find_dev(inode, dev);
-	if (unlikely(old)) {
-		if (mask_add)
-			old->mask |= mask;
-		else
-			old->mask = mask;
-		ret = old->wd;
-		goto out;
-	}
-
-	watch = create_watch(dev, mask, inode);
-	if (unlikely(IS_ERR(watch))) {
-		ret = PTR_ERR(watch);
-		goto out;
-	}
-
-	/* Add the watch to the device's and the inode's list */
-	list_add(&watch->d_list, &dev->watches);
-	list_add(&watch->i_list, &inode->inotify_watches);
-	ret = watch->wd;
-out:
-	up(&dev->sem);
-	up(&inode->inotify_sem);
+	ret = inotify_add_watch(dev, inode, mask, NULL);
 	path_release(&nd);
 fput_and_out:
 	fput_light(filp, fput_needed);
diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h
index 94919c3..606b875 100644
--- a/include/linux/fsnotify.h
+++ b/include/linux/fsnotify.h
@@ -35,16 +35,18 @@ static inline void fsnotify_move(struct 
 
 	if (isdir)
 		isdir = IN_ISDIR;
-	inotify_inode_queue_event(old_dir, IN_MOVED_FROM|isdir,cookie,old_name);
-	inotify_inode_queue_event(new_dir, IN_MOVED_TO|isdir, cookie, new_name);
+	inotify_inode_queue_event(old_dir, IN_MOVED_FROM|isdir, cookie,
+				  old_name, NULL);
+	inotify_inode_queue_event(new_dir, IN_MOVED_TO|isdir, cookie,
+				  new_name, source);
 
 	if (target) {
-		inotify_inode_queue_event(target, IN_DELETE_SELF, 0, NULL);
+		inotify_inode_queue_event(target, IN_DELETE_SELF, 0, NULL,NULL);
 		inotify_inode_is_dead(target);
 	}
 
 	if (source) {
-		inotify_inode_queue_event(source, IN_MOVE_SELF, 0, NULL);
+		inotify_inode_queue_event(source, IN_MOVE_SELF, 0, NULL, NULL);
 	}
 	audit_inode_child(old_name, source, old_dir->i_ino);
 	audit_inode_child(new_name, target, new_dir->i_ino);
@@ -66,7 +68,7 @@ static inline void fsnotify_nameremove(s
  */
 static inline void fsnotify_inoderemove(struct inode *inode)
 {
-	inotify_inode_queue_event(inode, IN_DELETE_SELF, 0, NULL);
+	inotify_inode_queue_event(inode, IN_DELETE_SELF, 0, NULL, NULL);
 	inotify_inode_is_dead(inode);
 }
 
@@ -76,7 +78,8 @@ static inline void fsnotify_inoderemove(
 static inline void fsnotify_create(struct inode *inode, struct dentry *dentry)
 {
 	inode_dir_notify(inode, DN_CREATE);
-	inotify_inode_queue_event(inode, IN_CREATE, 0, dentry->d_name.name);
+	inotify_inode_queue_event(inode, IN_CREATE, 0, dentry->d_name.name,
+				  dentry->d_inode);
 	audit_inode_child(dentry->d_name.name, dentry->d_inode, inode->i_ino);
 }
 
@@ -87,7 +90,7 @@ static inline void fsnotify_mkdir(struct
 {
 	inode_dir_notify(inode, DN_CREATE);
 	inotify_inode_queue_event(inode, IN_CREATE | IN_ISDIR, 0, 
-				  dentry->d_name.name);
+				  dentry->d_name.name, dentry->d_inode);
 	audit_inode_child(dentry->d_name.name, dentry->d_inode, inode->i_ino);
 }
 
@@ -104,7 +107,7 @@ static inline void fsnotify_access(struc
 
 	dnotify_parent(dentry, DN_ACCESS);
 	inotify_dentry_parent_queue_event(dentry, mask, 0, dentry->d_name.name);
-	inotify_inode_queue_event(inode, mask, 0, NULL);
+	inotify_inode_queue_event(inode, mask, 0, NULL, NULL);
 }
 
 /*
@@ -120,7 +123,7 @@ static inline void fsnotify_modify(struc
 
 	dnotify_parent(dentry, DN_MODIFY);
 	inotify_dentry_parent_queue_event(dentry, mask, 0, dentry->d_name.name);
-	inotify_inode_queue_event(inode, mask, 0, NULL);
+	inotify_inode_queue_event(inode, mask, 0, NULL, NULL);
 }
 
 /*
@@ -135,7 +138,7 @@ static inline void fsnotify_open(struct 
 		mask |= IN_ISDIR;
 
 	inotify_dentry_parent_queue_event(dentry, mask, 0, dentry->d_name.name);
-	inotify_inode_queue_event(inode, mask, 0, NULL);	
+	inotify_inode_queue_event(inode, mask, 0, NULL, NULL);
 }
 
 /*
@@ -153,7 +156,7 @@ static inline void fsnotify_close(struct
 		mask |= IN_ISDIR;
 
 	inotify_dentry_parent_queue_event(dentry, mask, 0, name);
-	inotify_inode_queue_event(inode, mask, 0, NULL);
+	inotify_inode_queue_event(inode, mask, 0, NULL, NULL);
 }
 
 /*
@@ -168,7 +171,7 @@ static inline void fsnotify_xattr(struct
 		mask |= IN_ISDIR;
 
 	inotify_dentry_parent_queue_event(dentry, mask, 0, dentry->d_name.name);
-	inotify_inode_queue_event(inode, mask, 0, NULL);
+	inotify_inode_queue_event(inode, mask, 0, NULL, NULL);
 }
 
 /*
@@ -215,7 +218,7 @@ static inline void fsnotify_change(struc
 	if (in_mask) {
 		if (S_ISDIR(inode->i_mode))
 			in_mask |= IN_ISDIR;
-		inotify_inode_queue_event(inode, in_mask, 0, NULL);
+		inotify_inode_queue_event(inode, in_mask, 0, NULL, NULL);
 		inotify_dentry_parent_queue_event(dentry, in_mask, 0,
 						  dentry->d_name.name);
 	}
diff --git a/include/linux/inotify.h b/include/linux/inotify.h
index 267c88b..2a8d1bd 100644
--- a/include/linux/inotify.h
+++ b/include/linux/inotify.h
@@ -14,6 +14,9 @@
  *
  * When you are watching a directory, you will receive the filename for events
  * such as IN_CREATE, IN_DELETE, IN_OPEN, IN_CLOSE, ..., relative to the wd.
+ *
+ * When using inotify from the kernel, len will always be zero.  Instead you
+ * should check the path for non-NULL in your callback.
  */
 struct inotify_event {
 	__s32		wd;		/* watch descriptor */
@@ -71,8 +74,19 @@ struct inotify_event {
 
 #ifdef CONFIG_INOTIFY
 
+/* Kernel consumer API */
+
+extern struct inotify_device *inotify_init(void (*)(struct inotify_event *,
+						    const char *,
+						    struct inode *, void *));
+extern int inotify_free(struct inotify_device *);
+extern __s32 inotify_add_watch(struct inotify_device *, struct inode *, __u32,
+			       void *);
+extern int inotify_ignore(struct inotify_device *, __s32);
+
+/* Kernel producer API */
 extern void inotify_inode_queue_event(struct inode *, __u32, __u32,
-				      const char *);
+				      const char *, struct inode *);
 extern void inotify_dentry_parent_queue_event(struct dentry *, __u32, __u32,
 					      const char *);
 extern void inotify_unmount_inodes(struct list_head *);
@@ -81,6 +95,7 @@ extern u32 inotify_get_cookie(void);
 
 #else
 
+/* Kernel producer API stubs */
 static inline void inotify_inode_queue_event(struct inode *inode,
 					     __u32 mask, __u32 cookie,
 					     const char *filename)

--
Linux-audit mailing list
Linux-audit at redhat.com
https://www.redhat.com/mailman/listinfo/linux-audit


linux-2.6-audit-no-rules-speedup.patch:
 arch/i386/kernel/ptrace.c    |    6 ++--
 arch/ia64/kernel/ptrace.c    |    4 +-
 arch/mips/kernel/ptrace.c    |    4 +-
 arch/powerpc/kernel/ptrace.c |    4 +-
 arch/s390/kernel/ptrace.c    |    4 +-
 arch/sparc64/kernel/ptrace.c |    4 +-
 arch/um/kernel/ptrace.c      |    2 -
 arch/x86_64/kernel/ptrace.c  |    4 +-
 include/linux/audit.h        |    3 ++
 kernel/auditfilter.c         |   13 ++++++++
 kernel/auditsc.c             |   64 +++++++++++++++++++++++++++----------------
 11 files changed, 73 insertions(+), 39 deletions(-)

--- NEW FILE linux-2.6-audit-no-rules-speedup.patch ---
diff -urP linux-2.6.15.x86_64.orig/arch/i386/kernel/ptrace.c linux-2.6.15.x86_64/arch/i386/kernel/ptrace.c
--- linux-2.6.15.x86_64.orig/arch/i386/kernel/ptrace.c	2006-02-16 15:55:06.000000000 -0500
+++ linux-2.6.15.x86_64/arch/i386/kernel/ptrace.c	2006-02-16 15:26:43.000000000 -0500
@@ -670,7 +670,7 @@
 		secure_computing(regs->orig_eax);
 
 	if (unlikely(current->audit_context)) {
-		if (entryexit)
+		if (n_audit_rules && entryexit)
 			audit_syscall_exit(current, AUDITSC_RESULT(regs->eax),
 						regs->eax);
 		/* Debug traps, when using PTRACE_SINGLESTEP, must be sent only
@@ -719,14 +719,14 @@
 	}
 	ret = is_sysemu;
 out:
-	if (unlikely(current->audit_context) && !entryexit)
+	if (unlikely(current->audit_context) && n_audit_rules && !entryexit)
 		audit_syscall_entry(current, AUDIT_ARCH_I386, regs->orig_eax,
 				    regs->ebx, regs->ecx, regs->edx, regs->esi);
 	if (ret == 0)
 		return 0;
 
 	regs->orig_eax = -1; /* force skip of syscall restarting */
-	if (unlikely(current->audit_context))
+	if (unlikely(current->audit_context) && n_audit_rules)
 		audit_syscall_exit(current, AUDITSC_RESULT(regs->eax),
 				regs->eax);
 	return 1;
diff -urP linux-2.6.15.x86_64.orig/arch/ia64/kernel/ptrace.c linux-2.6.15.x86_64/arch/ia64/kernel/ptrace.c
--- linux-2.6.15.x86_64.orig/arch/ia64/kernel/ptrace.c	2006-02-16 15:55:10.000000000 -0500
+++ linux-2.6.15.x86_64/arch/ia64/kernel/ptrace.c	2006-02-16 15:38:37.000000000 -0500
@@ -1632,7 +1632,7 @@
 	    && (current->ptrace & PT_PTRACED))
 		syscall_trace();
 
-	if (unlikely(current->audit_context)) {
+	if (unlikely(current->audit_context) && n_audit_rules) {
 		long syscall;
 		int arch;
 
@@ -1656,7 +1656,7 @@
 		     long arg4, long arg5, long arg6, long arg7,
 		     struct pt_regs regs)
 {
-	if (unlikely(current->audit_context)) {
+	if (unlikely(current->audit_context) && n_audit_rules) {
 		int success = AUDITSC_RESULT(regs.r10);
 		long result = regs.r8;
 
diff -urP linux-2.6.15.x86_64.orig/arch/mips/kernel/ptrace.c linux-2.6.15.x86_64/arch/mips/kernel/ptrace.c
--- linux-2.6.15.x86_64.orig/arch/mips/kernel/ptrace.c	2006-02-16 15:55:11.000000000 -0500
+++ linux-2.6.15.x86_64/arch/mips/kernel/ptrace.c	2006-02-16 15:26:43.000000000 -0500
@@ -468,7 +468,7 @@
  */
 asmlinkage void do_syscall_trace(struct pt_regs *regs, int entryexit)
 {
-	if (unlikely(current->audit_context) && entryexit)
+	if (unlikely(current->audit_context) && n_audit_rules && entryexit)
 		audit_syscall_exit(current, AUDITSC_RESULT(regs->regs[2]),
 		                   regs->regs[2]);
 
@@ -492,7 +492,7 @@
 		current->exit_code = 0;
 	}
  out:
-	if (unlikely(current->audit_context) && !entryexit)
+	if (unlikely(current->audit_context) && n_audit_rules && !entryexit)
 		audit_syscall_entry(current, audit_arch(), regs->regs[2],
 				    regs->regs[4], regs->regs[5],
 				    regs->regs[6], regs->regs[7]);
diff -urP linux-2.6.15.x86_64.orig/arch/powerpc/kernel/ptrace.c linux-2.6.15.x86_64/arch/powerpc/kernel/ptrace.c
--- linux-2.6.15.x86_64.orig/arch/powerpc/kernel/ptrace.c	2006-02-16 15:55:12.000000000 -0500
+++ linux-2.6.15.x86_64/arch/powerpc/kernel/ptrace.c	2006-02-16 15:26:43.000000000 -0500
@@ -537,7 +537,7 @@
 	    && (current->ptrace & PT_PTRACED))
 		do_syscall_trace();
 
-	if (unlikely(current->audit_context))
+	if (unlikely(current->audit_context) && n_audit_rules)
 		audit_syscall_entry(current,
 #ifdef CONFIG_PPC32
 				    AUDIT_ARCH_PPC,
@@ -555,7 +555,7 @@
 	secure_computing(regs->gpr[0]);
 #endif
 
-	if (unlikely(current->audit_context))
+	if (unlikely(current->audit_context) && n_audit_rules)
 		audit_syscall_exit(current,
 				   (regs->ccr&0x1000)?AUDITSC_FAILURE:AUDITSC_SUCCESS,
 				   regs->result);
diff -urP linux-2.6.15.x86_64.orig/arch/s390/kernel/ptrace.c linux-2.6.15.x86_64/arch/s390/kernel/ptrace.c
--- linux-2.6.15.x86_64.orig/arch/s390/kernel/ptrace.c	2006-02-16 15:55:09.000000000 -0500
+++ linux-2.6.15.x86_64/arch/s390/kernel/ptrace.c	2006-02-16 15:26:43.000000000 -0500
@@ -733,7 +733,7 @@
 asmlinkage void
 syscall_trace(struct pt_regs *regs, int entryexit)
 {
-	if (unlikely(current->audit_context) && entryexit)
+	if (unlikely(current->audit_context) && n_audit_rules && entryexit)
 		audit_syscall_exit(current, AUDITSC_RESULT(regs->gprs[2]), regs->gprs[2]);
 
 	if (!test_thread_flag(TIF_SYSCALL_TRACE))
@@ -760,7 +760,7 @@
 		current->exit_code = 0;
 	}
  out:
-	if (unlikely(current->audit_context) && !entryexit)
+	if (unlikely(current->audit_contex) && n_audit_rules && !entryexit)
 		audit_syscall_entry(current, 
 				    test_thread_flag(TIF_31BIT)?AUDIT_ARCH_S390:AUDIT_ARCH_S390X,
 				    regs->gprs[2], regs->orig_gpr2, regs->gprs[3],
diff -urP linux-2.6.15.x86_64.orig/arch/sparc64/kernel/ptrace.c linux-2.6.15.x86_64/arch/sparc64/kernel/ptrace.c
--- linux-2.6.15.x86_64.orig/arch/sparc64/kernel/ptrace.c	2006-02-16 15:55:05.000000000 -0500
+++ linux-2.6.15.x86_64/arch/sparc64/kernel/ptrace.c	2006-02-16 15:26:43.000000000 -0500
@@ -620,7 +620,7 @@
 	/* do the secure computing check first */
 	secure_computing(regs->u_regs[UREG_G1]);
 
-	if (unlikely(current->audit_context) && syscall_exit_p) {
+	if (unlikely(current->audit_context) && n_audit_rules && syscall_exit_p) {
 		unsigned long tstate = regs->tstate;
 		int result = AUDITSC_SUCCESS;
 
@@ -650,7 +650,7 @@
 	}
 
 out:
-	if (unlikely(current->audit_context) && !syscall_exit_p)
+	if (unlikely(current->audit_context) && n_audit_rules && !syscall_exit_p)
 		audit_syscall_entry(current,
 				    (test_thread_flag(TIF_32BIT) ?
 				     AUDIT_ARCH_SPARC :
diff -urP linux-2.6.15.x86_64.orig/arch/um/kernel/ptrace.c linux-2.6.15.x86_64/arch/um/kernel/ptrace.c
--- linux-2.6.15.x86_64.orig/arch/um/kernel/ptrace.c	2006-02-16 15:55:09.000000000 -0500
+++ linux-2.6.15.x86_64/arch/um/kernel/ptrace.c	2006-02-16 15:26:43.000000000 -0500
@@ -267,7 +267,7 @@
 	int is_singlestep = (current->ptrace & PT_DTRACE) && entryexit;
 	int tracesysgood;
 
-	if (unlikely(current->audit_context)) {
+	if (unlikely(current->audit_context) && n_audit_rules) {
 		if (!entryexit)
 			audit_syscall_entry(current,
                                             HOST_AUDIT_ARCH,
diff -urP linux-2.6.15.x86_64.orig/arch/x86_64/kernel/ptrace.c linux-2.6.15.x86_64/arch/x86_64/kernel/ptrace.c
--- linux-2.6.15.x86_64.orig/arch/x86_64/kernel/ptrace.c	2006-02-16 15:55:06.000000000 -0500
+++ linux-2.6.15.x86_64/arch/x86_64/kernel/ptrace.c	2006-02-16 15:26:43.000000000 -0500
@@ -603,7 +603,7 @@
 	    && (current->ptrace & PT_PTRACED))
 		syscall_trace(regs);
 
-	if (unlikely(current->audit_context)) {
+	if (unlikely(current->audit_context) && n_audit_rules) {
 		if (test_thread_flag(TIF_IA32)) {
 			audit_syscall_entry(current, AUDIT_ARCH_I386,
 					    regs->orig_rax,
@@ -620,7 +620,7 @@
 
 asmlinkage void syscall_trace_leave(struct pt_regs *regs)
 {
-	if (unlikely(current->audit_context))
+	if (unlikely(current->audit_context) && n_audit_rules)
 		audit_syscall_exit(current, AUDITSC_RESULT(regs->rax), regs->rax);
 
 	if ((test_thread_flag(TIF_SYSCALL_TRACE)
diff -urP linux-2.6.15.x86_64.orig/include/linux/audit.h linux-2.6.15.x86_64/include/linux/audit.h
--- linux-2.6.15.x86_64.orig/include/linux/audit.h	2006-02-16 15:55:37.000000000 -0500
+++ linux-2.6.15.x86_64/include/linux/audit.h	2006-02-16 16:34:15.000000000 -0500
@@ -83,6 +83,7 @@
 #define AUDIT_CONFIG_CHANGE	1305	/* Audit system configuration change */
 #define AUDIT_SOCKADDR		1306	/* sockaddr copied as syscall arg */
 #define AUDIT_CWD		1307	/* Current working directory */
+#define AUDIT_SYSCALL_PARTIAL	1310	/* Partial syscall event */
 
 #define AUDIT_AVC		1400	/* SE Linux avc denial or grant */
 #define AUDIT_SELINUX_ERR	1401	/* Internal SE Linux Errors */
@@ -370,6 +371,7 @@
 extern int audit_filter_type(int type);
 extern int  audit_receive_filter(int type, int pid, int uid, int seq,
 				 void *data, size_t datasz, uid_t loginuid);
+extern int n_audit_rules;
 #else
 #define audit_log(c,g,t,f,...) do { ; } while (0)
 #define audit_log_start(c,g,t) ({ NULL; })
@@ -380,6 +382,7 @@
 #define audit_log_untrustedstring(a,s) do { ; } while (0)
 #define audit_log_d_path(b,p,d,v) do { ; } while (0)
 #define audit_panic(m) do { ; } while (0)
+#define n_audit_rules 0
 #endif
 #endif
 #endif
diff -urP linux-2.6.15.x86_64.orig/kernel/auditfilter.c linux-2.6.15.x86_64/kernel/auditfilter.c
--- linux-2.6.15.x86_64.orig/kernel/auditfilter.c	2006-02-16 15:55:47.000000000 -0500
+++ linux-2.6.15.x86_64/kernel/auditfilter.c	2006-02-16 16:29:43.000000000 -0500
@@ -42,6 +42,9 @@
 #endif
 };
 
+/* number of audit rules */
+int n_audit_rules = 0;
+
 static inline void audit_free_watch(struct audit_watch *watch)
 {
 	kfree(watch->path);
@@ -419,11 +422,16 @@
 
 	if (entry->rule.watch)
 		audit_add_watch(&entry->rule);
+	/* If either of these, don't count towards total */
+	else if (entry->rule.listnr == AUDIT_FILTER_USER ||
+		 entry->rule.listnr == AUDIT_FILTER_TYPE)
+		n_audit_rules--;
 	if (entry->rule.flags & AUDIT_FILTER_PREPEND) {
 		list_add_rcu(&entry->list, list);
 	} else {
 		list_add_tail_rcu(&entry->list, list);
 	}
+	n_audit_rules++;
 
 	return 0;
 }
@@ -456,7 +464,12 @@
 			list_del_rcu(&e->list);
 			if (e->rule.watch)
 				audit_detach_watch(&e->rule);
+			/* If either of these, don't count towards total */
+			else if (entry->rule.listnr == AUDIT_FILTER_USER ||
+				 entry->rule.listnr == AUDIT_FILTER_TYPE)
+				n_audit_rules++;
 			call_rcu(&e->rcu, audit_free_rule_rcu);
+			n_audit_rules--;
 			return 0;
 		}
 	}
diff -urP linux-2.6.15.x86_64.orig/kernel/auditsc.c linux-2.6.15.x86_64/kernel/auditsc.c
--- linux-2.6.15.x86_64.orig/kernel/auditsc.c	2006-02-16 15:55:47.000000000 -0500
+++ linux-2.6.15.x86_64/kernel/auditsc.c	2006-02-16 17:15:45.000000000 -0500
@@ -569,37 +569,55 @@
 	struct audit_aux_data *aux;
 	const char *tty;
 
-	ab = audit_log_start(context, gfp_mask, AUDIT_SYSCALL);
+	ab = audit_log_start(context, gfp_mask,
+			n_audit_rules ? AUDIT_SYSCALL :	AUDIT_SYSCALL_PARTIAL);
 	if (!ab)
 		return;		/* audit_panic has been called */
-	audit_log_format(ab, "arch=%x syscall=%d",
+	if (current->signal->tty && current->signal->tty->name)
+		tty = current->signal->tty->name;
+	else
+		tty = "(none)";
+	if (n_audit_rules) {
+		audit_log_format(ab, "arch=%x syscall=%d",
 			 context->arch, context->major);
+	}
 	if (context->personality != PER_LINUX)
 		audit_log_format(ab, " per=%lx", context->personality);
 	if (context->return_valid)
 		audit_log_format(ab, " success=%s exit=%ld", 
-				 (context->return_valid==AUDITSC_SUCCESS)?"yes":"no",
+			 (context->return_valid==AUDITSC_SUCCESS)?"yes":"no",
 				 context->return_code);
-	if (current->signal->tty && current->signal->tty->name)
-		tty = current->signal->tty->name;
-	else
-		tty = "(none)";
-	audit_log_format(ab,
-		  " a0=%lx a1=%lx a2=%lx a3=%lx items=%d"
-		  " pid=%d auid=%u uid=%u gid=%u"
-		  " euid=%u suid=%u fsuid=%u"
-		  " egid=%u sgid=%u fsgid=%u tty=%s",
-		  context->argv[0],
-		  context->argv[1],
-		  context->argv[2],
-		  context->argv[3],
-		  context->name_count,
-		  context->pid,
-		  context->loginuid,
-		  context->uid,
-		  context->gid,
-		  context->euid, context->suid, context->fsuid,
-		  context->egid, context->sgid, context->fsgid, tty);
+	if (n_audit_rules) {
+		audit_log_format(ab,
+			  " a0=%lx a1=%lx a2=%lx a3=%lx items=%d"
+			  " pid=%d auid=%u uid=%u gid=%u"
+			  " euid=%u suid=%u fsuid=%u"
+			  " egid=%u sgid=%u fsgid=%u tty=%s",
+			  context->argv[0],
+			  context->argv[1],
+			  context->argv[2],
+			  context->argv[3],
+			  context->name_count,
+			  context->pid,
+			  context->loginuid,
+			  context->uid,
+			  context->gid,
+			  context->euid, context->suid, context->fsuid,
+			  context->egid, context->sgid, context->fsgid, tty);
+	} else {
+		audit_log_format(ab,
+			  " items=%d"
+			  " pid=%d auid=%u uid=%u gid=%u"
+			  " euid=%u suid=%u fsuid=%u"
+			  " egid=%u sgid=%u fsgid=%u tty=%s",
+			  context->name_count,
+			  context->pid,
+			  context->loginuid,
+			  context->uid,
+			  context->gid,
+			  context->euid, context->suid, context->fsuid,
+			  context->egid, context->sgid, context->fsgid, tty);
+	}
 	audit_log_task_info(ab, gfp_mask);
 	audit_log_end(ab);
 

linux-2.6-audit-promisc.patch:
 include/linux/audit.h |    7 ++++++-
 net/core/dev.c        |    7 +++++++
 2 files changed, 13 insertions(+), 1 deletion(-)

--- NEW FILE linux-2.6-audit-promisc.patch ---
>From linux-audit-bounces at redhat.com Sat Dec  3 13:39:07 2005
Return-path: <linux-audit-bounces at redhat.com>
Envelope-to: dwmw2 at baythorne.infradead.org
Delivery-date: Sat, 03 Dec 2005 13:39:07 +0000
Received: from [2002:d592:9a28::1] (helo=pentafluge.infradead.org) by
	baythorne.infradead.org with esmtps (Exim 4.54 #1 (Red Hat Linux)) id
	1EiXbW-0003Ra-S4 for dwmw2 at baythorne.infradead.org; Sat, 03 Dec 2005
	13:39:07 +0000
Received: from hormel.redhat.com ([209.132.177.30]) by
	pentafluge.infradead.org with esmtp (Exim 4.54 #1 (Red Hat Linux)) id
	1EiXbU-0006dw-2W for dwmw2 at infradead.org; Sat, 03 Dec 2005 13:39:06 +0000
Received: from listman.util.phx.redhat.com (listman.util.phx.redhat.com
	[10.8.4.110]) by hormel.redhat.com (Postfix) with ESMTP id 18B39732FF; Sat,
	 3 Dec 2005 08:39:03 -0500 (EST)
Received: from int-mx1.corp.redhat.com (int-mx1.corp.redhat.com
	[172.16.52.254]) by listman.util.phx.redhat.com (8.13.1/8.13.1) with ESMTP
	id jB3Dd1du018704; Sat, 3 Dec 2005 08:39:01 -0500
Received: from mail.boston.redhat.com (mail.boston.redhat.com
	[172.16.76.12]) by int-mx1.corp.redhat.com (8.11.6/8.11.6) with ESMTP id
	jB3Dd1V16833; Sat, 3 Dec 2005 08:39:01 -0500
Received: from vpn83-123.boston.redhat.com (vpn83-123.boston.redhat.com
	[172.16.83.123]) by mail.boston.redhat.com (8.12.8/8.12.8) with ESMTP id
	jB3Dd0EW010094;  Sat, 3 Dec 2005 08:39:00 -0500
From: Steve Grubb <sgrubb at redhat.com>
To: Linux Audit Discussion <linux-audit at redhat.com>
Date: Sat, 3 Dec 2005 08:39:35 -0500
User-Agent: KMail/1.7.2
MIME-Version: 1.0
Content-Type: Multipart/Mixed; boundary="Boundary-00=_XAakD2Qt0krjnKY"
Message-Id: <200512030839.35344.sgrubb at redhat.com>
X-loop: linux-audit at redhat.com
Cc: lspp-list <redhat-lspp at redhat.com>
Subject: [PATCH] promiscuous mode
X-BeenThere: linux-audit at redhat.com
X-Mailman-Version: 2.1.5
Precedence: junk
List-Id: Linux Audit Discussion <linux-audit.redhat.com>
List-Unsubscribe: <https://www.redhat.com/mailman/listinfo/linux-audit>,
	<mailto:linux-audit-request at redhat.com?subject=unsubscribe>
List-Archive: <https://www.redhat.com/archives/linux-audit>
List-Post: <mailto:linux-audit at redhat.com>
List-Help: <mailto:linux-audit-request at redhat.com?subject=help>
List-Subscribe: <https://www.redhat.com/mailman/listinfo/linux-audit>,
	<mailto:linux-audit-request at redhat.com?subject=subscribe>
Sender: linux-audit-bounces at redhat.com
Errors-To: linux-audit-bounces at redhat.com
X-Spam-Score: 0.0 (/)
X-Evolution-Source: imap://dwmw2@pentafluge.infradead.org/


--Boundary-00=_XAakD2Qt0krjnKY
Content-Type: text/plain; charset="us-ascii"
Content-Disposition: inline
Content-Transfer-Encoding: 8bit

Hi,

When a network interface goes into promiscuous mode, its an important security 
issue. The attached patch is intended to capture that action and send an 
event to the audit system.

The patch carves out a new block of numbers for kernel detected anomalies. 
These are events that may indicate suspicious activity. Other examples of 
potential kernel anomalies would be: exceeding disk quota, rlimit violations, 
changes to syscall entry table.

Signed-off-by: Steve Grubb <sgrubb at redhat.com>


--Boundary-00=_XAakD2Qt0krjnKY
Content-Type: text/x-diff; charset="us-ascii"; name="linux-2.6.14-audit-promiscuous.patch"
Content-Disposition: attachment; filename="linux-2.6.14-audit-promiscuous.patch"
Content-Transfer-Encoding: 8bit

diff -urp linux-2.6.14.orig/include/linux/audit.h linux-2.6.14/include/linux/audit.h
--- linux-2.6.14.orig/include/linux/audit.h	2005-12-02 15:28:34.000000000 -0500
+++ linux-2.6.14/include/linux/audit.h	2005-12-02 15:28:22.000000000 -0500
@@ -35,7 +35,8 @@
  * 1400 - 1499 SE Linux use
  * 1500 - 1599 kernel LSPP events
  * 1600 - 1699 kernel crypto events
- * 1700 - 1999 future kernel use (maybe integrity labels and related events)
+ * 1700 - 1799 kernel anomaly records
+ * 1800 - 1999 future kernel use (maybe integrity labels and related events)
  * 2000 is for otherwise unclassified kernel audit messages (legacy)
  * 2001 - 2099 unused (kernel)
  * 2100 - 2199 user space anomaly records
@@ -87,6 +88,10 @@
 #define AUDIT_MAC_STATUS	1404	/* Changed enforcing,permissive,off */
 #define AUDIT_MAC_CONFIG_CHANGE	1405	/* Changes to booleans */
 
+#define AUDIT_FIRST_KERN_ANOM_MSG   1700
+#define AUDIT_LAST_KERN_ANOM_MSG    1799
+#define AUDIT_ANOM_PROMISCUOUS      1700 /* Device changed promiscuous mode */
+
 #define AUDIT_KERNEL		2000	/* Asynchronous audit record. NOT A REQUEST. */
 
 /* Rule flags */
diff -urp linux-2.6.14.orig/net/core/dev.c linux-2.6.14/net/core/dev.c
--- linux-2.6.14.orig/net/core/dev.c	2005-12-02 14:22:10.000000000 -0500
+++ linux-2.6.14/net/core/dev.c	2005-12-02 15:23:27.000000000 -0500
@@ -114,6 +114,7 @@
 #include <net/iw_handler.h>
 #endif	/* CONFIG_NET_RADIO */
 #include <asm/current.h>
+#include <linux/audit.h>
 
 /*
  *	The list of packet types we will receive (as opposed to discard)
@@ -2121,6 +2122,12 @@ void dev_set_promiscuity(struct net_devi
 		printk(KERN_INFO "device %s %s promiscuous mode\n",
 		       dev->name, (dev->flags & IFF_PROMISC) ? "entered" :
 		       					       "left");
+		audit_log(current->audit_context, GFP_ATOMIC,
+			AUDIT_ANOM_PROMISCUOUS,
+			"dev=%s prom=%d old_prom=%d auid=%u",
+			dev->name, (dev->flags & IFF_PROMISC),
+			(old_flags & IFF_PROMISC),
+			audit_get_loginuid(current->audit_context)); 
 	}
 }
 

--Boundary-00=_XAakD2Qt0krjnKY
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Disposition: inline
Content-Transfer-Encoding: 8bit

--
Linux-audit mailing list
Linux-audit at redhat.com
https://www.redhat.com/mailman/listinfo/linux-audit
--Boundary-00=_XAakD2Qt0krjnKY--

linux-2.6-audit-rule-log.patch:
 include/linux/audit.h |    2 +-
 kernel/auditfilter.c  |   16 +++++++++-------
 2 files changed, 10 insertions(+), 8 deletions(-)

--- NEW FILE linux-2.6-audit-rule-log.patch ---
diff -ur linux-2.6.15.x86_64.orig/include/linux/audit.h linux-2.6.15.x86_64/include/linux/audit.h
--- linux-2.6.15.x86_64.orig/include/linux/audit.h	2006-02-14 10:50:56.000000000 -0500
+++ linux-2.6.15.x86_64/include/linux/audit.h	2006-02-14 10:51:41.000000000 -0500
@@ -246,7 +246,7 @@
 	__u32		flags;	/* AUDIT_PER_{TASK,CALL}, AUDIT_PREPEND */
 	__u32		action;	/* AUDIT_NEVER, AUDIT_POSSIBLE, AUDIT_ALWAYS */
 	__u32		field_count;
-	__u32		mask[AUDIT_BITMASK_SIZE];
+	__u32		mask[AUDIT_BITMASK_SIZE]; /* syscall(s) affected */
 	__u32		fields[AUDIT_MAX_FIELDS];
 	__u32		values[AUDIT_MAX_FIELDS];
 	__u32		fieldflags[AUDIT_MAX_FIELDS];
diff -ur linux-2.6.15.x86_64.orig/kernel/auditfilter.c linux-2.6.15.x86_64/kernel/auditfilter.c
--- linux-2.6.15.x86_64.orig/kernel/auditfilter.c	2006-02-14 10:51:25.000000000 -0500
+++ linux-2.6.15.x86_64/kernel/auditfilter.c	2006-02-14 10:52:54.000000000 -0500
@@ -586,10 +586,11 @@
 
 		err = audit_add_rule(entry,
 				     &audit_filter_list[entry->rule.listnr]);
-		if (!err)
-			audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
-				  "auid=%u added an audit rule\n", loginuid);
-		else {
+		audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
+			"auid=%u add rule to list=%d res=%d\n",
+			loginuid, entry->rule.listnr, !err);
+
+		if (err) {
 			if (entry->rule.watch)
 				audit_free_watch(entry->rule.watch);
 			audit_free_rule(entry);
@@ -606,9 +607,10 @@
 
 		err = audit_del_rule(entry,
 				     &audit_filter_list[entry->rule.listnr]);
-		if (!err)
-			audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
-				  "auid=%u removed an audit rule\n", loginuid);
+		audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
+			"auid=%u remove rule from list=%d res=%d\n",
+			loginuid, entry->rule.listnr, !err);
+
 		if (entry->rule.watch)
 			audit_free_watch(entry->rule.watch);
 		audit_free_rule(entry);

linux-2.6-audit-string-1.patch:
 include/linux/audit.h       |   31 ++
 kernel/audit.c              |   19 +
 kernel/audit.h              |   23 +-
 kernel/auditfilter.c        |  463 +++++++++++++++++++++++++++++++++-----------
 kernel/auditsc.c            |   50 ++--
 security/selinux/nlmsgtab.c |    3 
 6 files changed, 446 insertions(+), 143 deletions(-)

--- NEW FILE linux-2.6-audit-string-1.patch ---
>From amy.griffis at hp.com Tue Feb  7 12:05:27 2006
Return-Path: <linux-audit-bounces at redhat.com>
Received: from mail.boston.redhat.com ([unix socket])
	by mail.boston.redhat.com (Cyrus v2.1.12) with LMTP; Tue, 07 Feb 2006 12:05:54 -0500
X-Sieve: CMU Sieve 2.2
Received: from int-mx1.corp.redhat.com (int-mx1.corp.redhat.com [172.16.52.254])
	by mail.boston.redhat.com (8.12.8/8.12.8) with ESMTP id k17H5rQo013224;
	Tue, 7 Feb 2006 12:05:53 -0500
Received: from mx1.util.phx.redhat.com (mx1.util.phx.redhat.com [10.8.4.92])
	by int-mx1.corp.redhat.com (8.11.6/8.11.6) with ESMTP id k17H5o125027;
	Tue, 7 Feb 2006 12:05:50 -0500
Received: from hormel.redhat.com (hormel.util.phx.redhat.com [10.8.4.111])
	by mx1.util.phx.redhat.com (8.13.1/8.13.1) with ESMTP id k17H5jmt006474;
	Tue, 7 Feb 2006 12:05:45 -0500
Received: from listman.util.phx.redhat.com (listman.util.phx.redhat.com [10.8.4.110])
	by hormel.redhat.com (Postfix) with ESMTP
	id 4C2D472F6F; Tue,  7 Feb 2006 12:05:45 -0500 (EST)
Received: from int-mx1.corp.redhat.com (int-mx1.corp.redhat.com
	[172.16.52.254])
	by listman.util.phx.redhat.com (8.13.1/8.13.1) with ESMTP id
	k17H5hnh005461 for <linux-audit at listman.util.phx.redhat.com>;
	Tue, 7 Feb 2006 12:05:43 -0500
Received: from mx1.redhat.com (mx1.redhat.com [172.16.48.31])
	by int-mx1.corp.redhat.com (8.11.6/8.11.6) with ESMTP id k17H5g124983
	for <linux-audit at redhat.com>; Tue, 7 Feb 2006 12:05:42 -0500
Received: from ccerelbas04.cce.hp.com (ccerelbas04.cce.hp.com [161.114.21.107])
	by mx1.redhat.com (8.12.11/8.12.11) with ESMTP id k17H5fMr025186
	for <linux-audit at redhat.com>; Tue, 7 Feb 2006 12:05:41 -0500
Received: from ccerelint01.cce.cpqcorp.net (ccerelint01.cce.cpqcorp.net
	[16.110.74.103])
	by ccerelbas04.cce.hp.com (Postfix) with ESMTP id 0523834129
	for <linux-audit at redhat.com>; Tue,  7 Feb 2006 11:05:27 -0600 (CST)
Received: from dill.zko.hp.com (dill.zko.hp.com [16.116.96.242])
	by ccerelint01.cce.cpqcorp.net (Postfix) with ESMTP id A3CB134021
	for <linux-audit at redhat.com>; Tue,  7 Feb 2006 11:05:27 -0600 (CST)
Received: by dill.zko.hp.com (Postfix, from userid 10412)
	id 4289738448A2; Tue,  7 Feb 2006 12:05:27 -0500 (EST)
Date: Tue, 7 Feb 2006 12:05:27 -0500
From: Amy Griffis <amy.griffis at hp.com>
To: linux-audit at redhat.com
Message-ID: <20060207170527.GB2664 at zk3.dec.com>
Mail-Followup-To: linux-audit at redhat.com
References: <20060111185921.GA24489 at zk3.dec.com>
	<20060111190231.GB24489 at zk3.dec.com>
Mime-Version: 1.0
Content-Type: text/plain;
  charset=us-ascii
Content-Disposition: inline
In-Reply-To: <20060111190231.GB24489 at zk3.dec.com>
X-Mailer: Mutt http://www.mutt.org/
X-Editor: Vim http://www.vim.org/
User-Agent: Mutt/1.5.10i
X-RedHat-Spam-Score: -100 
X-loop: linux-audit at redhat.com
Subject: Re: [PATCH 1/2] audit string fields interface + consumer
X-BeenThere: linux-audit at redhat.com
X-Mailman-Version: 2.1.5
Precedence: junk
List-Id: Linux Audit Discussion <linux-audit.redhat.com>
List-Unsubscribe: <https://www.redhat.com/mailman/listinfo/linux-audit>,
	<mailto:linux-audit-request at redhat.com?subject=unsubscribe>
List-Archive: <https://www.redhat.com/archives/linux-audit>
List-Post: <mailto:linux-audit at redhat.com>
List-Help: <mailto:linux-audit-request at redhat.com?subject=help>
List-Subscribe: <https://www.redhat.com/mailman/listinfo/linux-audit>,
	<mailto:linux-audit-request at redhat.com?subject=subscribe>
Sender: linux-audit-bounces at redhat.com
Errors-To: linux-audit-bounces at redhat.com
X-Length: 32646
X-UID: 48007

Updated patch to dynamically allocate audit rule fields in kernel's
internal representation.  Added unlikely() calls for testing memory
allocation result.

Amy Griffis wrote:     [Wed Jan 11 2006, 02:02:31PM EST]
> Modify audit's kernel-userspace interface to allow the specification
> of string fields in audit rules.
> 
> Signed-off-by: Amy Griffis <amy.griffis at hp.com>

---

 include/linux/audit.h       |   31 +++
 kernel/audit.c              |   19 ++
 kernel/audit.h              |   23 ++
 kernel/auditfilter.c        |  463 +++++++++++++++++++++++++++++++++----------
 kernel/auditsc.c            |   50 ++---
 security/selinux/nlmsgtab.c |    3 
 6 files changed, 446 insertions(+), 143 deletions(-)

b5d36f87ed2ce86a306e3ae709805e892211f870
diff --git a/include/linux/audit.h b/include/linux/audit.h
index a485639..c208554 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -50,15 +50,18 @@
  */
 #define AUDIT_GET		1000	/* Get status */
 #define AUDIT_SET		1001	/* Set status (enable/disable/auditd) */
-#define AUDIT_LIST		1002	/* List syscall filtering rules */
-#define AUDIT_ADD		1003	/* Add syscall filtering rule */
-#define AUDIT_DEL		1004	/* Delete syscall filtering rule */
+#define AUDIT_LIST		1002	/* List syscall rules -- deprecated */
+#define AUDIT_ADD		1003	/* Add syscall rule -- deprecated */
+#define AUDIT_DEL		1004	/* Delete syscall rule -- deprecated */
 #define AUDIT_USER		1005	/* Message from userspace -- deprecated */
 #define AUDIT_LOGIN		1006	/* Define the login id and information */
 #define AUDIT_WATCH_INS		1007	/* Insert file/dir watch entry */
 #define AUDIT_WATCH_REM		1008	/* Remove file/dir watch entry */
 #define AUDIT_WATCH_LIST	1009	/* List all file/dir watches */
 #define AUDIT_SIGNAL_INFO	1010	/* Get info about sender of signal to auditd */
+#define AUDIT_ADD_RULE		1011	/* Add syscall filtering rule */
+#define AUDIT_DEL_RULE		1012	/* Delete syscall filtering rule */
+#define AUDIT_LIST_RULES	1013	/* List syscall filtering rules */
 
 #define AUDIT_FIRST_USER_MSG	1100	/* Userspace messages mostly uninteresting to kernel */
 #define AUDIT_USER_AVC		1107	/* We filter this differently */
@@ -229,6 +232,26 @@ struct audit_status {
 	__u32		backlog;	/* messages waiting in queue */
 };
 
+/* audit_rule_data supports filter rules with both integer and string
+ * fields.  It corresponds with AUDIT_ADD_RULE, AUDIT_DEL_RULE and
+ * AUDIT_LIST_RULES requests.
+ */
+struct audit_rule_data {
+	__u32		flags;	/* AUDIT_PER_{TASK,CALL}, AUDIT_PREPEND */
+	__u32		action;	/* AUDIT_NEVER, AUDIT_POSSIBLE, AUDIT_ALWAYS */
+	__u32		field_count;
+	__u32		mask[AUDIT_BITMASK_SIZE];
+	__u32		fields[AUDIT_MAX_FIELDS];
+	__u32		values[AUDIT_MAX_FIELDS];
+	__u32		fieldflags[AUDIT_MAX_FIELDS];
+	__u32		buflen;	/* total length of string fields */
+	char		buf[0];	/* string fields buffer */
+};
+
+/* audit_rule is supported to maintain backward compatibility with
+ * userspace.  It supports integer fields only and corresponds to
+ * AUDIT_ADD, AUDIT_DEL and AUDIT_LIST requests.
+ */
 struct audit_rule {		/* for AUDIT_LIST, AUDIT_ADD, and AUDIT_DEL */
 	__u32		flags;	/* AUDIT_PER_{TASK,CALL}, AUDIT_PREPEND */
 	__u32		action;	/* AUDIT_NEVER, AUDIT_POSSIBLE, AUDIT_ALWAYS */
@@ -340,7 +363,7 @@ extern void		    audit_log_d_path(struct
 extern int audit_filter_user(struct netlink_skb_parms *cb, int type);
 extern int audit_filter_type(int type);
 extern int  audit_receive_filter(int type, int pid, int uid, int seq,
-				 void *data, uid_t loginuid);
+				 void *data, size_t datasz, uid_t loginuid);
 #else
 #define audit_log(c,g,t,f,...) do { ; } while (0)
 #define audit_log_start(c,g,t) ({ NULL; })
diff --git a/kernel/audit.c b/kernel/audit.c
index d95efd6..bdda766 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -52,6 +52,7 @@
 #include <linux/audit.h>
 
 #include <net/sock.h>
+#include <net/netlink.h>
 #include <linux/skbuff.h>
 #include <linux/netlink.h>
 
@@ -361,9 +362,12 @@ static int audit_netlink_ok(kernel_cap_t
 	switch (msg_type) {
 	case AUDIT_GET:
 	case AUDIT_LIST:
+	case AUDIT_LIST_RULES:
 	case AUDIT_SET:
 	case AUDIT_ADD:
+	case AUDIT_ADD_RULE:
 	case AUDIT_DEL:
+	case AUDIT_DEL_RULE:
 	case AUDIT_SIGNAL_INFO:
 		if (!cap_raised(eff_cap, CAP_AUDIT_CONTROL))
 			err = -EPERM;
@@ -470,12 +474,23 @@ static int audit_receive_msg(struct sk_b
 		break;
 	case AUDIT_ADD:
 	case AUDIT_DEL:
-		if (nlh->nlmsg_len < sizeof(struct audit_rule))
+		if (nlmsg_len(nlh) < sizeof(struct audit_rule))
 			return -EINVAL;
 		/* fallthrough */
 	case AUDIT_LIST:
 		err = audit_receive_filter(nlh->nlmsg_type, NETLINK_CB(skb).pid,
-					   uid, seq, data, loginuid);
+					   uid, seq, data, nlmsg_len(nlh),
+					   loginuid);
+		break;
+	case AUDIT_ADD_RULE:
+	case AUDIT_DEL_RULE:
+		if (nlmsg_len(nlh) < sizeof(struct audit_rule_data))
+			return -EINVAL;
+		/* fallthrough */
+	case AUDIT_LIST_RULES:
+		err = audit_receive_filter(nlh->nlmsg_type, NETLINK_CB(skb).pid,
+					   uid, seq, data, nlmsg_len(nlh),
+					   loginuid);
 		break;
 	case AUDIT_SIGNAL_INFO:
 		sig_data.uid = audit_sig_uid;
diff --git a/kernel/audit.h b/kernel/audit.h
index 7643e46..4b602cd 100644
--- a/kernel/audit.h
+++ b/kernel/audit.h
@@ -52,10 +52,27 @@ enum audit_state {
 };
 
 /* Rule lists */
+struct audit_field {
+	u32			type;
+	u32			val;
+	u32			op;
+};
+
+struct audit_krule {
+	int			vers_ops;
+	u32			flags;
+	u32			listnr;
+	u32			action;
+	u32			mask[AUDIT_BITMASK_SIZE];
+	u32			buflen; /* for data alloc on list rules */
+	u32			field_count;
+	struct audit_field	*fields;
+};
+
 struct audit_entry {
-	struct list_head  list;
-	struct rcu_head   rcu;
-	struct audit_rule rule;
+	struct list_head	list;
+	struct rcu_head		rcu;
+	struct audit_krule	rule;
 };
 
 
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
index a3a3275..5735acd 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -40,52 +40,279 @@ struct list_head audit_filter_list[AUDIT
 #endif
 };
 
-/* Copy rule from user-space to kernel-space.  Called from 
- * audit_add_rule during AUDIT_ADD. */
-static inline int audit_copy_rule(struct audit_rule *d, struct audit_rule *s)
+static inline void audit_free_rule(struct audit_entry *e)
 {
+	kfree(e->rule.fields);
+	kfree(e);
+}
+
+static inline void audit_free_rule_rcu(struct rcu_head *head)
+{
+	struct audit_entry *e = container_of(head, struct audit_entry, rcu);
+	audit_free_rule(e);
+}
+
+/* Unpack a filter field's string representation from user-space
+ * buffer. */
+static char *audit_unpack_string(void **bufp, size_t *remain, size_t len)
+{
+	char *str;
+
+	if (!*bufp || (len == 0) || (len > *remain))
+		return ERR_PTR(-EINVAL);
+
+	/* Of the currently implemented string fields, PATH_MAX
+	 * defines the longest valid length.
+	 */
+	if (len > PATH_MAX)
+		return ERR_PTR(-ENAMETOOLONG);
+
+	str = kmalloc(len + 1, GFP_KERNEL);
+	if (unlikely(!str))
+		return ERR_PTR(-ENOMEM);
+
+	memcpy(str, *bufp, len);
+	str[len] = 0;
+	*bufp += len;
+	*remain -= len;
+
+	return str;
+}
+
+/* Common user-space to kernel rule translation. */
+static inline struct audit_entry *audit_to_entry_common(struct audit_rule *rule)
+{
+	unsigned listnr;
+	struct audit_entry *entry;
+	struct audit_field *fields;
+	int i, err;
+
+	err = -EINVAL;
+	listnr = rule->flags & ~AUDIT_FILTER_PREPEND;
+	switch(listnr) {
+	default:
+		goto exit_err;
+	case AUDIT_FILTER_USER:
+	case AUDIT_FILTER_TYPE:
+#ifdef CONFIG_AUDITSYSCALL
+	case AUDIT_FILTER_ENTRY:
+	case AUDIT_FILTER_EXIT:
+	case AUDIT_FILTER_TASK:
+#endif
+		;
+	}
+	if (rule->action != AUDIT_NEVER && rule->action != AUDIT_POSSIBLE &&
+	    rule->action != AUDIT_ALWAYS)
+		goto exit_err;
+	if (rule->field_count > AUDIT_MAX_FIELDS)
+		goto exit_err;
+
+	err = -ENOMEM;
+	entry = kmalloc(sizeof(*entry), GFP_KERNEL);
+	if (unlikely(!entry))
+		goto exit_err;
+	fields = kmalloc(sizeof(*fields) * rule->field_count, GFP_KERNEL);
+	if (unlikely(!fields)) {
+		kfree(entry);
+		goto exit_err;
+	}
+
+	memset(&entry->rule, 0, sizeof(struct audit_krule));
+	memset(fields, 0, sizeof(struct audit_field));
+
+	entry->rule.flags = rule->flags & AUDIT_FILTER_PREPEND;
+	entry->rule.listnr = listnr;
+	entry->rule.action = rule->action;
+	entry->rule.field_count = rule->field_count;
+	entry->rule.fields = fields;
+
+	for (i = 0; i < AUDIT_BITMASK_SIZE; i++)
+		entry->rule.mask[i] = rule->mask[i];
+
+	return entry;
+
+exit_err:
+	return ERR_PTR(err);
+}
+
+/* Translate struct audit_rule to kernel's rule respresentation.
+ * Exists for backward compatibility with userspace. */
+static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule)
+{
+	struct audit_entry *entry;
+	int err = 0;
 	int i;
 
-	if (s->action != AUDIT_NEVER
-	    && s->action != AUDIT_POSSIBLE
-	    && s->action != AUDIT_ALWAYS)
-		return -1;
-	if (s->field_count < 0 || s->field_count > AUDIT_MAX_FIELDS)
-		return -1;
-	if ((s->flags & ~AUDIT_FILTER_PREPEND) >= AUDIT_NR_FILTERS)
-		return -1;
-
-	d->flags	= s->flags;
-	d->action	= s->action;
-	d->field_count	= s->field_count;
-	for (i = 0; i < d->field_count; i++) {
-		d->fields[i] = s->fields[i];
-		d->values[i] = s->values[i];
+	entry = audit_to_entry_common(rule);
+	if (IS_ERR(entry))
+		goto exit_nofree;
+
+	for (i = 0; i < rule->field_count; i++) {
+		struct audit_field *f = &entry->rule.fields[i];
+
+		if (rule->fields[i] & AUDIT_UNUSED_BITS) {
+			err = -EINVAL;
+			goto exit_free;
+		}
+
+		f->op = rule->fields[i] & (AUDIT_NEGATE|AUDIT_OPERATORS);
+		f->type = rule->fields[i] & ~(AUDIT_NEGATE|AUDIT_OPERATORS);
+		f->val = rule->values[i];
+
+		entry->rule.vers_ops = (f->op & AUDIT_OPERATORS) ? 2 : 1;
+		if (f->op & AUDIT_NEGATE)
+			f->op |= AUDIT_NOT_EQUAL;
+		else if (!(f->op & AUDIT_OPERATORS))
+			f->op |= AUDIT_EQUAL;
+		f->op &= ~AUDIT_NEGATE;
 	}
-	for (i = 0; i < AUDIT_BITMASK_SIZE; i++) d->mask[i] = s->mask[i];
-	return 0;
+
+exit_nofree:
+	return entry;
+
+exit_free:
+	audit_free_rule(entry);
+	return ERR_PTR(err);
 }
 
-/* Check to see if two rules are identical.  It is called from
- * audit_add_rule during AUDIT_ADD and 
- * audit_del_rule during AUDIT_DEL. */
-static int audit_compare_rule(struct audit_rule *a, struct audit_rule *b)
+/* Translate struct audit_rule_data to kernel's rule respresentation. */
+static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
+					       size_t datasz)
 {
+	int err = 0;
+	struct audit_entry *entry;
+	void *bufp;
+	/* size_t remain = datasz - sizeof(struct audit_rule_data); */
 	int i;
 
-	if (a->flags != b->flags)
-		return 1;
+	entry = audit_to_entry_common((struct audit_rule *)data);
+	if (IS_ERR(entry))
+		goto exit_nofree;
+
+	bufp = data->buf;
+	entry->rule.vers_ops = 2;
+	for (i = 0; i < data->field_count; i++) {
+		struct audit_field *f = &entry->rule.fields[i];
+
+		err = -EINVAL;
+		if (!(data->fieldflags[i] & AUDIT_OPERATORS) ||
+		    data->fieldflags[i] & ~AUDIT_OPERATORS)
+			goto exit_free;
+
+		f->op = data->fieldflags[i] & AUDIT_OPERATORS;
+		f->type = data->fields[i];
+		switch(f->type) {
+		/* call type-specific conversion routines here */
+		default:
+			f->val = data->values[i];
+		}
+	}
 
-	if (a->action != b->action)
-		return 1;
+exit_nofree:
+	return entry;
+
+exit_free:
+	audit_free_rule(entry);
+	return ERR_PTR(err);
+}
+
+/* Pack a filter field's string representation into data block. */
+static inline size_t audit_pack_string(void **bufp, char *str)
+{
+	size_t len = strlen(str);
+
+	memcpy(*bufp, str, len);
+	*bufp += len;
+
+	return len;
+}
+
+/* Translate kernel rule respresentation to struct audit_rule.
+ * Exists for backward compatibility with userspace. */
+static struct audit_rule *audit_krule_to_rule(struct audit_krule *krule)
+{
+	struct audit_rule *rule;
+	int i;
+
+	rule = kmalloc(sizeof(*rule), GFP_KERNEL);
+	if (unlikely(!rule))
+		return ERR_PTR(-ENOMEM);
+	memset(rule, 0, sizeof(*rule));
+
+	rule->flags = krule->flags | krule->listnr;
+	rule->action = krule->action;
+	rule->field_count = krule->field_count;
+	for (i = 0; i < rule->field_count; i++) {
+		rule->values[i] = krule->fields[i].val;
+		rule->fields[i] = krule->fields[i].type;
+
+		if (krule->vers_ops == 1) {
+			if (krule->fields[i].op & AUDIT_NOT_EQUAL)
+				rule->fields[i] |= AUDIT_NEGATE;
+		} else {
+			rule->fields[i] |= krule->fields[i].op;
+		}
+	}
+	for (i = 0; i < AUDIT_BITMASK_SIZE; i++) rule->mask[i] = krule->mask[i];
 
-	if (a->field_count != b->field_count)
+	return rule;
+}
+
+/* Translate kernel rule respresentation to struct audit_rule_data. */
+static struct audit_rule_data *audit_krule_to_data(struct audit_krule *krule)
+{
+	struct audit_rule_data *data;
+	void *bufp;
+	int i;
+
+	data = kmalloc(sizeof(*data) + krule->buflen, GFP_KERNEL);
+	if (unlikely(!data))
+		return ERR_PTR(-ENOMEM);
+	memset(data, 0, sizeof(*data));
+
+	data->flags = krule->flags | krule->listnr;
+	data->action = krule->action;
+	data->field_count = krule->field_count;
+	bufp = data->buf;
+	for (i = 0; i < data->field_count; i++) {
+		struct audit_field *f = &krule->fields[i];
+
+		data->fields[i] = f->type;
+		data->fieldflags[i] = f->op;
+		switch(f->type) {
+		/* call type-specific conversion routines here */
+		default:
+			data->values[i] = f->val;
+		}
+	}
+	for (i = 0; i < AUDIT_BITMASK_SIZE; i++) data->mask[i] = krule->mask[i];
+
+	return data;
+}
+
+/* Compare two rules in kernel format.  Considered success if rules
+ * don't match. */
+static int audit_compare_rule(struct audit_krule *a, struct audit_krule *b)
+{
+	int i;
+
+	if (a->flags != b->flags ||
+	    a->listnr != b->listnr ||
+	    a->action != b->action ||
+	    a->field_count != b->field_count)
 		return 1;
 
 	for (i = 0; i < a->field_count; i++) {
-		if (a->fields[i] != b->fields[i]
-		    || a->values[i] != b->values[i])
+		if (a->fields[i].type != b->fields[i].type ||
+		    a->fields[i].op != b->fields[i].op)
 			return 1;
+
+		switch(a->fields[i].type) {
+		/* call type-specific comparison routines here */
+		default:
+			if (a->fields[i].val != b->fields[i].val)
+				return 1;
+		}
 	}
 
 	for (i = 0; i < AUDIT_BITMASK_SIZE; i++)
@@ -95,41 +322,21 @@ static int audit_compare_rule(struct aud
 	return 0;
 }
 
-/* Note that audit_add_rule and audit_del_rule are called via
- * audit_receive() in audit.c, and are protected by
+/* Add rule to given filterlist if not a duplicate.  Protected by
  * audit_netlink_sem. */
-static inline int audit_add_rule(struct audit_rule *rule,
+static inline int audit_add_rule(struct audit_entry *entry,
 				  struct list_head *list)
 {
-	struct audit_entry  *entry;
-	int i;
+	struct audit_entry *e;
 
 	/* Do not use the _rcu iterator here, since this is the only
 	 * addition routine. */
-	list_for_each_entry(entry, list, list) {
-		if (!audit_compare_rule(rule, &entry->rule))
+	list_for_each_entry(e, list, list) {
+		if (!audit_compare_rule(&entry->rule, &e->rule))
 			return -EEXIST;
 	}
 
-	for (i = 0; i < rule->field_count; i++) {
-		if (rule->fields[i] & AUDIT_UNUSED_BITS)
-			return -EINVAL;
-		if ( rule->fields[i] & AUDIT_NEGATE)
-			rule->fields[i] |= AUDIT_NOT_EQUAL;
-		else if ( (rule->fields[i] & AUDIT_OPERATORS) == 0 )
-			rule->fields[i] |= AUDIT_EQUAL;
-		rule->fields[i] &= ~AUDIT_NEGATE;
-	}
-
-	if (!(entry = kmalloc(sizeof(*entry), GFP_KERNEL)))
-		return -ENOMEM;
-	if (audit_copy_rule(&entry->rule, rule)) {
-		kfree(entry);
-		return -EINVAL;
-	}
-
 	if (entry->rule.flags & AUDIT_FILTER_PREPEND) {
-		entry->rule.flags &= ~AUDIT_FILTER_PREPEND;
 		list_add_rcu(&entry->list, list);
 	} else {
 		list_add_tail_rcu(&entry->list, list);
@@ -138,16 +345,9 @@ static inline int audit_add_rule(struct 
 	return 0;
 }
 
-static inline void audit_free_rule(struct rcu_head *head)
-{
-	struct audit_entry *e = container_of(head, struct audit_entry, rcu);
-	kfree(e);
-}
-
-/* Note that audit_add_rule and audit_del_rule are called via
- * audit_receive() in audit.c, and are protected by
+/* Remove an existing rule from filterlist.  Protected by
  * audit_netlink_sem. */
-static inline int audit_del_rule(struct audit_rule *rule,
+static inline int audit_del_rule(struct audit_entry *entry,
 				 struct list_head *list)
 {
 	struct audit_entry  *e;
@@ -155,16 +355,18 @@ static inline int audit_del_rule(struct 
 	/* Do not use the _rcu iterator here, since this is the only
 	 * deletion routine. */
 	list_for_each_entry(e, list, list) {
-		if (!audit_compare_rule(rule, &e->rule)) {
+		if (!audit_compare_rule(&entry->rule, &e->rule)) {
 			list_del_rcu(&e->list);
-			call_rcu(&e->rcu, audit_free_rule);
+			call_rcu(&e->rcu, audit_free_rule_rcu);
 			return 0;
 		}
 	}
 	return -ENOENT;		/* No matching rule */
 }
 
-static int audit_list_rules(void *_dest)
+/* List rules using struct audit_rule.  Exists for backward
+ * compatibility with userspace. */
+static int audit_list(void *_dest)
 {
 	int pid, seq;
 	int *dest = _dest;
@@ -180,9 +382,16 @@ static int audit_list_rules(void *_dest)
 	/* The *_rcu iterators not needed here because we are
 	   always called with audit_netlink_sem held. */
 	for (i=0; i<AUDIT_NR_FILTERS; i++) {
-		list_for_each_entry(entry, &audit_filter_list[i], list)
+		list_for_each_entry(entry, &audit_filter_list[i], list) {
+			struct audit_rule *rule;
+
+			rule = audit_krule_to_rule(&entry->rule);
+			if (unlikely(!rule))
+				break;
 			audit_send_reply(pid, seq, AUDIT_LIST, 0, 1,
-					 &entry->rule, sizeof(entry->rule));
+					 rule, sizeof(*rule));
+			kfree(rule);
+		}
 	}
 	audit_send_reply(pid, seq, AUDIT_LIST, 1, 1, NULL, 0);
 	
@@ -190,6 +399,40 @@ static int audit_list_rules(void *_dest)
 	return 0;
 }
 
+/* List rules using struct audit_rule_data. */
+static int audit_list_rules(void *_dest)
+{
+	int pid, seq;
+	int *dest = _dest;
+	struct audit_entry *e;
+	int i;
+
+	pid = dest[0];
+	seq = dest[1];
+	kfree(dest);
+
+	down(&audit_netlink_sem);
+
+	/* The *_rcu iterators not needed here because we are
+	   always called with audit_netlink_sem held. */
+	for (i=0; i<AUDIT_NR_FILTERS; i++) {
+		list_for_each_entry(e, &audit_filter_list[i], list) {
+			struct audit_rule_data *data;
+
+			data = audit_krule_to_data(&e->rule);
+			if (unlikely(!data))
+				break;
+			audit_send_reply(pid, seq, AUDIT_LIST_RULES, 0, 1,
+					 data, sizeof(*data));
+			kfree(data);
+		}
+	}
+	audit_send_reply(pid, seq, AUDIT_LIST_RULES, 1, 1, NULL, 0);
+
+	up(&audit_netlink_sem);
+	return 0;
+}
+
 /**
  * audit_receive_filter - apply all rules to the specified message type
  * @type: audit message type
@@ -197,18 +440,20 @@ static int audit_list_rules(void *_dest)
  * @uid: target uid for netlink audit messages
  * @seq: netlink audit message sequence (serial) number
  * @data: payload data
+ * @datasz: size of payload data
  * @loginuid: loginuid of sender
  */
 int audit_receive_filter(int type, int pid, int uid, int seq, void *data,
-							uid_t loginuid)
+			 size_t datasz, uid_t loginuid)
 {
 	struct task_struct *tsk;
 	int *dest;
-	int		   err = 0;
-	unsigned listnr;
+	int err = 0;
+	struct audit_entry *entry;
 
 	switch (type) {
 	case AUDIT_LIST:
+	case AUDIT_LIST_RULES:
 		/* We can't just spew out the rules here because we might fill
 		 * the available socket buffer space and deadlock waiting for
 		 * auditctl to read from it... which isn't ever going to
@@ -221,41 +466,48 @@ int audit_receive_filter(int type, int p
 		dest[0] = pid;
 		dest[1] = seq;
 
-		tsk = kthread_run(audit_list_rules, dest, "audit_list_rules");
+		if (type == AUDIT_LIST)
+			tsk = kthread_run(audit_list, dest, "audit_list");
+		else
+			tsk = kthread_run(audit_list_rules, dest,
+					  "audit_list_rules");
 		if (IS_ERR(tsk)) {
 			kfree(dest);
 			err = PTR_ERR(tsk);
 		}
 		break;
 	case AUDIT_ADD:
-		listnr = ((struct audit_rule *)data)->flags & ~AUDIT_FILTER_PREPEND;
-		switch(listnr) {
-		default:
-			return -EINVAL;
+	case AUDIT_ADD_RULE:
+		if (type == AUDIT_ADD)
+			entry = audit_rule_to_entry(data);
+		else
+			entry = audit_data_to_entry(data, datasz);
+		if (IS_ERR(entry))
+			return PTR_ERR(entry);
 
-		case AUDIT_FILTER_USER:
-		case AUDIT_FILTER_TYPE:
-#ifdef CONFIG_AUDITSYSCALL
-		case AUDIT_FILTER_ENTRY:
-		case AUDIT_FILTER_EXIT:
-		case AUDIT_FILTER_TASK:
-#endif
-			;
-		}
-		err = audit_add_rule(data, &audit_filter_list[listnr]);
+		err = audit_add_rule(entry,
+				     &audit_filter_list[entry->rule.listnr]);
 		if (!err)
 			audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
 				  "auid=%u added an audit rule\n", loginuid);
+		else
+			audit_free_rule(entry);
 		break;
 	case AUDIT_DEL:
-		listnr =((struct audit_rule *)data)->flags & ~AUDIT_FILTER_PREPEND;
-		if (listnr >= AUDIT_NR_FILTERS)
-			return -EINVAL;
+	case AUDIT_DEL_RULE:
+		if (type == AUDIT_DEL)
+			entry = audit_rule_to_entry(data);
+		else
+			entry = audit_data_to_entry(data, datasz);
+		if (IS_ERR(entry))
+			return PTR_ERR(entry);
 
-		err = audit_del_rule(data, &audit_filter_list[listnr]);
+		err = audit_del_rule(entry,
+				     &audit_filter_list[entry->rule.listnr]);
 		if (!err)
 			audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
 				  "auid=%u removed an audit rule\n", loginuid);
+		audit_free_rule(entry);
 		break;
 	default:
 		return -EINVAL;
@@ -287,29 +539,27 @@ int audit_comparator(const u32 left, con
 
 
 static int audit_filter_user_rules(struct netlink_skb_parms *cb,
-				   struct audit_rule *rule,
+				   struct audit_krule *rule,
 				   enum audit_state *state)
 {
 	int i;
 
 	for (i = 0; i < rule->field_count; i++) {
-		u32 field  = rule->fields[i] & ~AUDIT_OPERATORS;
-		u32 op  = rule->fields[i] & AUDIT_OPERATORS;
-		u32 value  = rule->values[i];
+		struct audit_field *f = &rule->fields[i];
 		int result = 0;
 
-		switch (field) {
+		switch (f->type) {
 		case AUDIT_PID:
-			result = audit_comparator(cb->creds.pid, op, value);
+			result = audit_comparator(cb->creds.pid, f->op, f->val);
 			break;
 		case AUDIT_UID:
-			result = audit_comparator(cb->creds.uid, op, value);
+			result = audit_comparator(cb->creds.uid, f->op, f->val);
 			break;
 		case AUDIT_GID:
-			result = audit_comparator(cb->creds.gid, op, value);
+			result = audit_comparator(cb->creds.gid, f->op, f->val);
 			break;
 		case AUDIT_LOGINUID:
-			result = audit_comparator(cb->loginuid, op, value);
+			result = audit_comparator(cb->loginuid, f->op, f->val);
 			break;
 		}
 
@@ -354,14 +604,11 @@ int audit_filter_type(int type)
 
 	list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_TYPE],
 				list) {
-		struct audit_rule *rule = &e->rule;
 		int i;
-		for (i = 0; i < rule->field_count; i++) {
-			u32 field  = rule->fields[i] & ~AUDIT_OPERATORS;
-			u32 op  = rule->fields[i] & AUDIT_OPERATORS;
-			u32 value  = rule->values[i];
-			if ( field == AUDIT_MSGTYPE ) {
-				result = audit_comparator(type, op, value); 
+		for (i = 0; i < e->rule.field_count; i++) {
+			struct audit_field *f = &e->rule.fields[i];
+			if (f->type == AUDIT_MSGTYPE) {
+				result = audit_comparator(type, f->op, f->val);
 				if (!result)
 					break;
 			}
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 8f0a61c..e4f7096 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -161,70 +161,68 @@ struct audit_context {
 /* Compare a task_struct with an audit_rule.  Return 1 on match, 0
  * otherwise. */
 static int audit_filter_rules(struct task_struct *tsk,
-			      struct audit_rule *rule,
+			      struct audit_krule *rule,
 			      struct audit_context *ctx,
 			      enum audit_state *state)
 {
 	int i, j;
 
 	for (i = 0; i < rule->field_count; i++) {
-		u32 field  = rule->fields[i] & ~AUDIT_OPERATORS;
-		u32 op  = rule->fields[i] & AUDIT_OPERATORS;
-		u32 value  = rule->values[i];
+		struct audit_field *f = &rule->fields[i];
 		int result = 0;
 
-		switch (field) {
+		switch (f->type) {
 		case AUDIT_PID:
-			result = audit_comparator(tsk->pid, op, value);
+			result = audit_comparator(tsk->pid, f->op, f->val);
 			break;
 		case AUDIT_UID:
-			result = audit_comparator(tsk->uid, op, value);
+			result = audit_comparator(tsk->uid, f->op, f->val);
 			break;
 		case AUDIT_EUID:
-			result = audit_comparator(tsk->euid, op, value);
+			result = audit_comparator(tsk->euid, f->op, f->val);
 			break;
 		case AUDIT_SUID:
-			result = audit_comparator(tsk->suid, op, value);
+			result = audit_comparator(tsk->suid, f->op, f->val);
 			break;
 		case AUDIT_FSUID:
-			result = audit_comparator(tsk->fsuid, op, value);
+			result = audit_comparator(tsk->fsuid, f->op, f->val);
 			break;
 		case AUDIT_GID:
-			result = audit_comparator(tsk->gid, op, value);
+			result = audit_comparator(tsk->gid, f->op, f->val);
 			break;
 		case AUDIT_EGID:
-			result = audit_comparator(tsk->egid, op, value);
+			result = audit_comparator(tsk->egid, f->op, f->val);
 			break;
 		case AUDIT_SGID:
-			result = audit_comparator(tsk->sgid, op, value);
+			result = audit_comparator(tsk->sgid, f->op, f->val);
 			break;
 		case AUDIT_FSGID:
-			result = audit_comparator(tsk->fsgid, op, value);
+			result = audit_comparator(tsk->fsgid, f->op, f->val);
 			break;
 		case AUDIT_PERS:
-			result = audit_comparator(tsk->personality, op, value);
+			result = audit_comparator(tsk->personality, f->op, f->val);
 			break;
 		case AUDIT_ARCH:
  			if (ctx)
-				result = audit_comparator(ctx->arch, op, value);
+				result = audit_comparator(ctx->arch, f->op, f->val);
 			break;
 
 		case AUDIT_EXIT:
 			if (ctx && ctx->return_valid)
-				result = audit_comparator(ctx->return_code, op, value);
+				result = audit_comparator(ctx->return_code, f->op, f->val);
 			break;
 		case AUDIT_SUCCESS:
 			if (ctx && ctx->return_valid) {
-				if (value)
-					result = audit_comparator(ctx->return_valid, op, AUDITSC_SUCCESS);
+				if (f->val)
+					result = audit_comparator(ctx->return_valid, f->op, AUDITSC_SUCCESS);
 				else
-					result = audit_comparator(ctx->return_valid, op, AUDITSC_FAILURE);
+					result = audit_comparator(ctx->return_valid, f->op, AUDITSC_FAILURE);
 			}
 			break;
 		case AUDIT_DEVMAJOR:
 			if (ctx) {
 				for (j = 0; j < ctx->name_count; j++) {
-					if (audit_comparator(MAJOR(ctx->names[j].dev),	op, value)) {
+					if (audit_comparator(MAJOR(ctx->names[j].dev),	f->op, f->val)) {
 						++result;
 						break;
 					}
@@ -234,7 +232,7 @@ static int audit_filter_rules(struct tas
 		case AUDIT_DEVMINOR:
 			if (ctx) {
 				for (j = 0; j < ctx->name_count; j++) {
-					if (audit_comparator(MINOR(ctx->names[j].dev), op, value)) {
+					if (audit_comparator(MINOR(ctx->names[j].dev), f->op, f->val)) {
 						++result;
 						break;
 					}
@@ -244,8 +242,8 @@ static int audit_filter_rules(struct tas
 		case AUDIT_INODE:
 			if (ctx) {
 				for (j = 0; j < ctx->name_count; j++) {
-					if (audit_comparator(ctx->names[j].ino, op, value) ||
-					    audit_comparator(ctx->names[j].pino, op, value)) {
+					if (audit_comparator(ctx->names[j].ino, f->op, f->val) ||
+					    audit_comparator(ctx->names[j].pino, f->op, f->val)) {
 						++result;
 						break;
 					}
@@ -255,14 +253,14 @@ static int audit_filter_rules(struct tas
 		case AUDIT_LOGINUID:
 			result = 0;
 			if (ctx)
-				result = audit_comparator(ctx->loginuid, op, value);
+				result = audit_comparator(ctx->loginuid, f->op, f->val);
 			break;
 		case AUDIT_ARG0:
 		case AUDIT_ARG1:
 		case AUDIT_ARG2:
 		case AUDIT_ARG3:
 			if (ctx)
-				result = audit_comparator(ctx->argv[field-AUDIT_ARG0], op, value);
+				result = audit_comparator(ctx->argv[f->type-AUDIT_ARG0], f->op, f->val);
 			break;
 		}
 
diff --git a/security/selinux/nlmsgtab.c b/security/selinux/nlmsgtab.c
index d7c0e91..7315824 100644
--- a/security/selinux/nlmsgtab.c
+++ b/security/selinux/nlmsgtab.c
@@ -99,6 +99,9 @@ static struct nlmsg_perm nlmsg_audit_per
 	{ AUDIT_LIST,		NETLINK_AUDIT_SOCKET__NLMSG_READPRIV },
 	{ AUDIT_ADD,		NETLINK_AUDIT_SOCKET__NLMSG_WRITE    },
 	{ AUDIT_DEL,		NETLINK_AUDIT_SOCKET__NLMSG_WRITE    },
+	{ AUDIT_LIST_RULES,	NETLINK_AUDIT_SOCKET__NLMSG_READPRIV },
+	{ AUDIT_ADD_RULE,	NETLINK_AUDIT_SOCKET__NLMSG_WRITE    },
+	{ AUDIT_DEL_RULE,	NETLINK_AUDIT_SOCKET__NLMSG_WRITE    },
 	{ AUDIT_USER,		NETLINK_AUDIT_SOCKET__NLMSG_RELAY    },
 	{ AUDIT_SIGNAL_INFO,	NETLINK_AUDIT_SOCKET__NLMSG_READ     },
 };
-- 
0.99.9n

--
Linux-audit mailing list
Linux-audit at redhat.com
https://www.redhat.com/mailman/listinfo/linux-audit


linux-2.6-audit-string-2.patch:
 include/linux/audit.h |    1 
 kernel/audit.h        |    8 +++
 kernel/auditfilter.c  |  130 +++++++++++++++++++++++++++++++++++++++++++++-----
 kernel/auditsc.c      |    3 -
 4 files changed, 128 insertions(+), 14 deletions(-)

--- NEW FILE linux-2.6-audit-string-2.patch ---
>From amy.griffis at hp.com Tue Feb  7 12:06:57 2006
Return-Path: <linux-audit-bounces at redhat.com>
Received: from mail.boston.redhat.com ([unix socket])
	by mail.boston.redhat.com (Cyrus v2.1.12) with LMTP; Tue, 07 Feb 2006 12:07:15 -0500
X-Sieve: CMU Sieve 2.2
Received: from int-mx1.corp.redhat.com (int-mx1.corp.redhat.com [172.16.52.254])
	by mail.boston.redhat.com (8.12.8/8.12.8) with ESMTP id k17H7FQo013463;
	Tue, 7 Feb 2006 12:07:15 -0500
Received: from mx1.util.phx.redhat.com (mx1.util.phx.redhat.com [10.8.4.92])
	by int-mx1.corp.redhat.com (8.11.6/8.11.6) with ESMTP id k17H7C125794;
	Tue, 7 Feb 2006 12:07:12 -0500
Received: from hormel.redhat.com (hormel.util.phx.redhat.com [10.8.4.111])
	by mx1.util.phx.redhat.com (8.13.1/8.13.1) with ESMTP id k17H7635006635;
	Tue, 7 Feb 2006 12:07:06 -0500
Received: from listman.util.phx.redhat.com (listman.util.phx.redhat.com [10.8.4.110])
	by hormel.redhat.com (Postfix) with ESMTP
	id B388872F9D; Tue,  7 Feb 2006 12:07:06 -0500 (EST)
Received: from int-mx1.corp.redhat.com (int-mx1.corp.redhat.com
	[172.16.52.254])
	by listman.util.phx.redhat.com (8.13.1/8.13.1) with ESMTP id
	k17H74IH005569 for <linux-audit at listman.util.phx.redhat.com>;
	Tue, 7 Feb 2006 12:07:04 -0500
Received: from mx1.redhat.com (mx1.redhat.com [172.16.48.31])
	by int-mx1.corp.redhat.com (8.11.6/8.11.6) with ESMTP id k17H74125739
	for <linux-audit at redhat.com>; Tue, 7 Feb 2006 12:07:04 -0500
Received: from tayrelbas01.tay.hp.com (tayrelbas01.tay.hp.com [161.114.80.244])
	by mx1.redhat.com (8.12.11/8.12.11) with ESMTP id k17H732a025911
	for <linux-audit at redhat.com>; Tue, 7 Feb 2006 12:07:03 -0500
Received: from tayrelint01.nz-tay.cpqcorp.net (tayrelint01.nz-tay.cpqcorp.net
	[16.47.5.6])
	by tayrelbas01.tay.hp.com (Postfix) with ESMTP id E699034111
	for <linux-audit at redhat.com>; Tue,  7 Feb 2006 12:07:00 -0500 (EST)
Received: from dill.zko.hp.com (dill.zko.hp.com [16.116.96.242])
	by tayrelint01.nz-tay.cpqcorp.net (Postfix) with ESMTP id DE9C63401D
	for <linux-audit at redhat.com>; Tue,  7 Feb 2006 12:06:57 -0500 (EST)
Received: by dill.zko.hp.com (Postfix, from userid 10412)
	id CC89C38448A2; Tue,  7 Feb 2006 12:06:57 -0500 (EST)
Date: Tue, 7 Feb 2006 12:06:57 -0500
From: Amy Griffis <amy.griffis at hp.com>
To: linux-audit at redhat.com
Message-ID: <20060207170657.GC2664 at zk3.dec.com>
Mail-Followup-To: linux-audit at redhat.com
References: <20060111185921.GA24489 at zk3.dec.com>
	<20060111190453.GC24489 at zk3.dec.com>
Mime-Version: 1.0
Content-Type: text/plain;
  charset=us-ascii
Content-Disposition: inline
In-Reply-To: <20060111190453.GC24489 at zk3.dec.com>
X-Mailer: Mutt http://www.mutt.org/
X-Editor: Vim http://www.vim.org/
User-Agent: Mutt/1.5.10i
X-RedHat-Spam-Score: -100 
X-loop: linux-audit at redhat.com
Subject: Re: [PATCH 2/2] audit string fields interface + consumer
X-BeenThere: linux-audit at redhat.com
X-Mailman-Version: 2.1.5
Precedence: junk
List-Id: Linux Audit Discussion <linux-audit.redhat.com>
List-Unsubscribe: <https://www.redhat.com/mailman/listinfo/linux-audit>,
	<mailto:linux-audit-request at redhat.com?subject=unsubscribe>
List-Archive: <https://www.redhat.com/archives/linux-audit>
List-Post: <mailto:linux-audit at redhat.com>
List-Help: <mailto:linux-audit-request at redhat.com?subject=help>
List-Subscribe: <https://www.redhat.com/mailman/listinfo/linux-audit>,
	<mailto:linux-audit-request at redhat.com?subject=subscribe>
Sender: linux-audit-bounces at redhat.com
Errors-To: linux-audit-bounces at redhat.com
X-Length: 13244
X-UID: 48008

Merge updates to patch 1/2 of this set.

Amy Griffis wrote:     [Wed Jan 11 2006, 02:04:53PM EST]
> Add AUDIT_WATCH field type and associated helpers.
> 
> Signed-off-by: Amy Griffis <amy.griffis at hp.com>

---

 include/linux/audit.h |    1 
 kernel/audit.h        |    8 +++
 kernel/auditfilter.c  |  130 ++++++++++++++++++++++++++++++++++++++++++++-----
 kernel/auditsc.c      |    3 +
 4 files changed, 128 insertions(+), 14 deletions(-)

237afe663373e4f908cb1d0a188fd8b5216069e9
diff --git a/include/linux/audit.h b/include/linux/audit.h
index c208554..d76fa58 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -148,6 +148,7 @@
 #define AUDIT_INODE	102
 #define AUDIT_EXIT	103
 #define AUDIT_SUCCESS   104	/* exit >= 0; value ignored */
+#define AUDIT_WATCH	105
 
 #define AUDIT_ARG0      200
 #define AUDIT_ARG1      (AUDIT_ARG0+1)
diff --git a/kernel/audit.h b/kernel/audit.h
index 4b602cd..eb33354 100644
--- a/kernel/audit.h
+++ b/kernel/audit.h
@@ -52,6 +52,12 @@ enum audit_state {
 };
 
 /* Rule lists */
+struct audit_watch {
+	char			*path;	 /* watch insertion path */
+	struct list_head	mlist;	 /* entry in master_watchlist */
+	struct list_head	rules;	 /* associated rules */
+};
+
 struct audit_field {
 	u32			type;
 	u32			val;
@@ -67,6 +73,8 @@ struct audit_krule {
 	u32			buflen; /* for data alloc on list rules */
 	u32			field_count;
 	struct audit_field	*fields;
+	struct audit_watch	*watch;	 /* associated watch */
+	struct list_head	rlist;	 /* entry in audit_watch.rules list */
 };
 
 struct audit_entry {
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
index 5735acd..5e9f650 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -22,6 +22,8 @@
 #include <linux/kernel.h>
 #include <linux/audit.h>
 #include <linux/kthread.h>
+#include <linux/fs.h>
+#include <linux/namei.h>
 #include <linux/netlink.h>
 #include "audit.h"
 
@@ -40,6 +42,12 @@ struct list_head audit_filter_list[AUDIT
 #endif
 };
 
+static inline void audit_free_watch(struct audit_watch *watch)
+{
+	kfree(watch->path);
+	kfree(watch);
+}
+
 static inline void audit_free_rule(struct audit_entry *e)
 {
 	kfree(e->rule.fields);
@@ -52,6 +60,8 @@ static inline void audit_free_rule_rcu(s
 	audit_free_rule(e);
 }
 
+static LIST_HEAD(master_watchlist);
+
 /* Unpack a filter field's string representation from user-space
  * buffer. */
 static char *audit_unpack_string(void **bufp, size_t *remain, size_t len)
@@ -79,6 +89,33 @@ static char *audit_unpack_string(void **
 	return str;
 }
 
+/* Translate a watch string to kernel respresentation. */
+static int audit_to_watch(char *path, struct audit_krule *krule, int fidx)
+{
+	struct audit_field *f = &krule->fields[fidx];
+	struct nameidata nd;
+	struct audit_watch *watch;
+
+	if (path[0] != '/' || path[f->val-1] == '/' ||
+	    krule->listnr != AUDIT_FILTER_EXIT ||
+	    f->op & ~AUDIT_EQUAL)
+		return -EINVAL;
+
+	if (path_lookup(path, 0, &nd) == 0)
+		f->val = nd.dentry->d_inode->i_ino;
+	else
+		f->val = (unsigned int)-1;
+	path_release(&nd);
+
+	watch = kmalloc(sizeof(*watch), GFP_KERNEL);
+	if (unlikely(!watch))
+		return -ENOMEM;
+	watch->path = path;
+	krule->watch = watch;
+
+	return 0;
+}
+
 /* Common user-space to kernel rule translation. */
 static inline struct audit_entry *audit_to_entry_common(struct audit_rule *rule)
 {
@@ -150,15 +187,16 @@ static struct audit_entry *audit_rule_to
 	for (i = 0; i < rule->field_count; i++) {
 		struct audit_field *f = &entry->rule.fields[i];
 
-		if (rule->fields[i] & AUDIT_UNUSED_BITS) {
-			err = -EINVAL;
-			goto exit_free;
-		}
-
 		f->op = rule->fields[i] & (AUDIT_NEGATE|AUDIT_OPERATORS);
 		f->type = rule->fields[i] & ~(AUDIT_NEGATE|AUDIT_OPERATORS);
 		f->val = rule->values[i];
 
+		if (f->type & AUDIT_UNUSED_BITS ||
+		    f->type == AUDIT_WATCH) {
+			err = -EINVAL;
+			goto exit_free;
+		}
+
 		entry->rule.vers_ops = (f->op & AUDIT_OPERATORS) ? 2 : 1;
 		if (f->op & AUDIT_NEGATE)
 			f->op |= AUDIT_NOT_EQUAL;
@@ -182,8 +220,9 @@ static struct audit_entry *audit_data_to
 	int err = 0;
 	struct audit_entry *entry;
 	void *bufp;
-	/* size_t remain = datasz - sizeof(struct audit_rule_data); */
+	size_t remain = datasz - sizeof(struct audit_rule_data);
 	int i;
+	char *path;
 
 	entry = audit_to_entry_common((struct audit_rule *)data);
 	if (IS_ERR(entry))
@@ -201,10 +240,20 @@ static struct audit_entry *audit_data_to
 
 		f->op = data->fieldflags[i] & AUDIT_OPERATORS;
 		f->type = data->fields[i];
+		f->val = data->values[i];
 		switch(f->type) {
-		/* call type-specific conversion routines here */
-		default:
-			f->val = data->values[i];
+		case AUDIT_WATCH:
+			path = audit_unpack_string(&bufp, &remain, f->val);
+			if (IS_ERR(path))
+				goto exit_free;
+			entry->rule.buflen += f->val;
+
+			err = audit_to_watch(path, &entry->rule, i);
+			if (err) {
+				kfree(path);
+				goto exit_free;
+			}
+			break;
 		}
 	}
 
@@ -280,7 +329,10 @@ static struct audit_rule_data *audit_kru
 		data->fields[i] = f->type;
 		data->fieldflags[i] = f->op;
 		switch(f->type) {
-		/* call type-specific conversion routines here */
+		case AUDIT_WATCH:
+			data->buflen += data->values[i] =
+				audit_pack_string(&bufp, krule->watch->path);
+			break;
 		default:
 			data->values[i] = f->val;
 		}
@@ -290,6 +342,12 @@ static struct audit_rule_data *audit_kru
 	return data;
 }
 
+/* Compare two watches.  Considered success if rules don't match. */
+static inline int audit_compare_watch(struct audit_watch *a, struct audit_watch *b)
+{
+	return strcmp(a->path, b->path);
+}
+
 /* Compare two rules in kernel format.  Considered success if rules
  * don't match. */
 static int audit_compare_rule(struct audit_krule *a, struct audit_krule *b)
@@ -308,7 +366,10 @@ static int audit_compare_rule(struct aud
 			return 1;
 
 		switch(a->fields[i].type) {
-		/* call type-specific comparison routines here */
+		case AUDIT_WATCH:
+			if (audit_compare_watch(a->watch, b->watch))
+				return 1;
+			break;
 		default:
 			if (a->fields[i].val != b->fields[i].val)
 				return 1;
@@ -322,6 +383,26 @@ static int audit_compare_rule(struct aud
 	return 0;
 }
 
+/* Attach krule's watch to master_watchlist, using existing watches
+ * when possible. */
+static inline void audit_add_watch(struct audit_krule *krule)
+{
+	struct audit_watch *w;
+
+	list_for_each_entry(w, &master_watchlist, mlist) {
+		if (audit_compare_watch(w, krule->watch))
+			continue;
+
+		audit_free_watch(krule->watch);
+		krule->watch = w;
+		list_add(&krule->rlist, &w->rules);
+		return;
+	}
+	INIT_LIST_HEAD(&krule->watch->rules);
+	list_add(&krule->rlist, &krule->watch->rules);
+	list_add(&krule->watch->mlist, &master_watchlist);
+}
+
 /* Add rule to given filterlist if not a duplicate.  Protected by
  * audit_netlink_sem. */
 static inline int audit_add_rule(struct audit_entry *entry,
@@ -336,6 +417,8 @@ static inline int audit_add_rule(struct 
 			return -EEXIST;
 	}
 
+	if (entry->rule.watch)
+		audit_add_watch(&entry->rule);
 	if (entry->rule.flags & AUDIT_FILTER_PREPEND) {
 		list_add_rcu(&entry->list, list);
 	} else {
@@ -345,6 +428,20 @@ static inline int audit_add_rule(struct 
 	return 0;
 }
 
+/* Detach watch from krule, freeing if it has no associated rules. */
+static inline void audit_detach_watch(struct audit_krule *krule)
+{
+	struct audit_watch *watch = krule->watch;
+
+	list_del(&krule->rlist);
+	krule->watch = NULL;
+
+	if (list_empty(&watch->rules)) {
+		list_del(&watch->mlist);
+		audit_free_watch(watch);
+	}
+}
+
 /* Remove an existing rule from filterlist.  Protected by
  * audit_netlink_sem. */
 static inline int audit_del_rule(struct audit_entry *entry,
@@ -357,6 +454,8 @@ static inline int audit_del_rule(struct 
 	list_for_each_entry(e, list, list) {
 		if (!audit_compare_rule(&entry->rule, &e->rule)) {
 			list_del_rcu(&e->list);
+			if (e->rule.watch)
+				audit_detach_watch(&e->rule);
 			call_rcu(&e->rcu, audit_free_rule_rcu);
 			return 0;
 		}
@@ -423,7 +522,7 @@ static int audit_list_rules(void *_dest)
 			if (unlikely(!data))
 				break;
 			audit_send_reply(pid, seq, AUDIT_LIST_RULES, 0, 1,
-					 data, sizeof(*data));
+					 data, sizeof(*data) + data->buflen);
 			kfree(data);
 		}
 	}
@@ -490,8 +589,11 @@ int audit_receive_filter(int type, int p
 		if (!err)
 			audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
 				  "auid=%u added an audit rule\n", loginuid);
-		else
+		else {
+			if (entry->rule.watch)
+				audit_free_watch(entry->rule.watch);
 			audit_free_rule(entry);
+		}
 		break;
 	case AUDIT_DEL:
 	case AUDIT_DEL_RULE:
@@ -507,6 +609,8 @@ int audit_receive_filter(int type, int p
 		if (!err)
 			audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
 				  "auid=%u removed an audit rule\n", loginuid);
+		if (entry->rule.watch)
+			audit_free_watch(entry->rule.watch);
 		audit_free_rule(entry);
 		break;
 	default:
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index e4f7096..8e98b65 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -240,7 +240,8 @@ static int audit_filter_rules(struct tas
 			}
 			break;
 		case AUDIT_INODE:
-			if (ctx) {
+		case AUDIT_WATCH:
+			if (ctx && f->val != (unsigned int)-1) {
 				for (j = 0; j < ctx->name_count; j++) {
 					if (audit_comparator(ctx->names[j].ino, f->op, f->val) ||
 					    audit_comparator(ctx->names[j].pino, f->op, f->val)) {
-- 
0.99.9n

--
Linux-audit mailing list
Linux-audit at redhat.com
https://www.redhat.com/mailman/listinfo/linux-audit


linux-2.6-audit-tty.patch:
 auditsc.c |   10 ++++++++--
 1 files changed, 8 insertions(+), 2 deletions(-)

--- NEW FILE linux-2.6-audit-tty.patch ---
>From linux-audit-bounces at redhat.com Sun Jan  1 19:07:06 2006
Return-path: <linux-audit-bounces at redhat.com>
Envelope-to: dwmw2 at baythorne.infradead.org
Delivery-date: Sun, 01 Jan 2006 19:07:06 +0000
Received: from [2002:d592:9a28::1] (helo=pentafluge.infradead.org) by
	baythorne.infradead.org with esmtps (Exim 4.54 #1 (Red Hat Linux)) id
	1Et8Xq-0006yT-4F for dwmw2 at baythorne.infradead.org; Sun, 01 Jan 2006
	19:07:06 +0000
Received: from hormel.redhat.com ([209.132.177.30]) by
	pentafluge.infradead.org with esmtp (Exim 4.54 #1 (Red Hat Linux)) id
	1Et8Xo-0000N4-CS for dwmw2 at infradead.org; Sun, 01 Jan 2006 19:07:05 +0000
Received: from listman.util.phx.redhat.com (listman.util.phx.redhat.com
	[10.8.4.110]) by hormel.redhat.com (Postfix) with ESMTP id 2C86D72EB7; Sun,
	 1 Jan 2006 14:07:02 -0500 (EST)
Received: from int-mx1.corp.redhat.com (int-mx1.corp.redhat.com
	[172.16.52.254]) by listman.util.phx.redhat.com (8.13.1/8.13.1) with ESMTP
	id k01J71MX011720 for <linux-audit at listman.util.phx.redhat.com>; Sun, 1 Jan
	2006 14:07:01 -0500
Received: from mail.boston.redhat.com (mail.boston.redhat.com
	[172.16.76.12]) by int-mx1.corp.redhat.com (8.11.6/8.11.6) with ESMTP id
	k01J70127937 for <linux-audit at int-mx1.corp.redhat.com>; Sun, 1 Jan 2006
	14:07:00 -0500
Received: from vpn50-34.rdu.redhat.com (vpn50-34.rdu.redhat.com
	[172.16.50.34]) by mail.boston.redhat.com (8.12.8/8.12.8) with ESMTP id
	k01J6xa3016921 for <linux-audit at redhat.com>; Sun, 1 Jan 2006 14:07:00 -0500
From: Steve Grubb <sgrubb at redhat.com>
Organization: Red Hat
To: linux-audit at redhat.com
Date: Sun, 1 Jan 2006 14:07:00 -0500
User-Agent: KMail/1.9
MIME-Version: 1.0
Content-Type: text/plain; charset="us-ascii"
Content-Disposition: inline
Message-Id: <200601011407.00175.sgrubb at redhat.com>
X-MIME-Autoconverted: from quoted-printable to 8bit by
	listman.util.phx.redhat.com id k01J71MX011720
X-loop: linux-audit at redhat.com
Subject: Add tty to syscall audit records
X-BeenThere: linux-audit at redhat.com
X-Mailman-Version: 2.1.5
Precedence: junk
List-Id: Linux Audit Discussion <linux-audit.redhat.com>
List-Unsubscribe: <https://www.redhat.com/mailman/listinfo/linux-audit>,
	<mailto:linux-audit-request at redhat.com?subject=unsubscribe>
List-Archive: <https://www.redhat.com/archives/linux-audit>
List-Post: <mailto:linux-audit at redhat.com>
List-Help: <mailto:linux-audit-request at redhat.com?subject=help>
List-Subscribe: <https://www.redhat.com/mailman/listinfo/linux-audit>,
	<mailto:linux-audit-request at redhat.com?subject=subscribe>
Sender: linux-audit-bounces at redhat.com
Errors-To: linux-audit-bounces at redhat.com
X-Spam-Score: 0.0 (/)
X-Evolution-Source: imap://dwmw2@pentafluge.infradead.org/
Content-Transfer-Encoding: 8bit

Hi,

>From the RBAC specs:

FAU_SAR.1.1 The TSF shall provide the set of authorized 
RBAC administrators with the capability to read the following
audit information from the audit records:

<snip>
(e) The User Session Identifier or Terminal Type 

A patch adding the tty for all syscalls is included in this email.
Please apply.

Signed-off-by: Steve Grubb <sgrubb at redhat.com>



diff -urp linux-2.6.14.orig/kernel/auditsc.c linux-2.6.14/kernel/auditsc.c
--- linux-2.6.14.orig/kernel/auditsc.c	2005-12-28 10:39:04.000000000 -0500
+++ linux-2.6.14/kernel/auditsc.c	2005-12-28 10:40:28.000000000 -0500
@@ -56,6 +56,7 @@
 #include <asm/unistd.h>
 #include <linux/security.h>
 #include <linux/list.h>
+#include <linux/tty.h>
 
 #include "audit.h"
 
@@ -567,6 +568,7 @@ static void audit_log_exit(struct audit_
 	int i;
 	struct audit_buffer *ab;
 	struct audit_aux_data *aux;
+	const char *tty;
 
 	ab = audit_log_start(context, gfp_mask, AUDIT_SYSCALL);
 	if (!ab)
@@ -579,11 +581,15 @@ static void audit_log_exit(struct audit_
 		audit_log_format(ab, " success=%s exit=%ld", 
 				 (context->return_valid==AUDITSC_SUCCESS)?"yes":"no",
 				 context->return_code);
+	if (current->signal->tty && current->signal->tty->name)
+		tty = current->signal->tty->name;
+	else
+		tty = "(none)";
 	audit_log_format(ab,
 		  " a0=%lx a1=%lx a2=%lx a3=%lx items=%d"
 		  " pid=%d auid=%u uid=%u gid=%u"
 		  " euid=%u suid=%u fsuid=%u"
-		  " egid=%u sgid=%u fsgid=%u",
+		  " egid=%u sgid=%u fsgid=%u tty=%s",
 		  context->argv[0],
 		  context->argv[1],
 		  context->argv[2],
@@ -594,7 +600,7 @@ static void audit_log_exit(struct audit_
 		  context->uid,
 		  context->gid,
 		  context->euid, context->suid, context->fsuid,
-		  context->egid, context->sgid, context->fsgid);
+		  context->egid, context->sgid, context->fsgid, tty);
 	audit_log_task_info(ab);
 	audit_log_end(ab);
 

--
Linux-audit mailing list
Linux-audit at redhat.com
https://www.redhat.com/mailman/listinfo/linux-audit

linux-2.6-audit_log_exit-gfp_mask.patch:
 auditsc.c |   20 ++++++++++++--------
 1 files changed, 12 insertions(+), 8 deletions(-)

--- NEW FILE linux-2.6-audit_log_exit-gfp_mask.patch ---
>From aviro at redhat.com Wed Feb 15 17:14:11 2006
Return-Path: <linux-audit-bounces at redhat.com>
Received: from mail.boston.redhat.com ([unix socket])
	by mail.boston.redhat.com (Cyrus v2.1.12) with LMTP; Wed, 15 Feb 2006 17:14:21 -0500
X-Sieve: CMU Sieve 2.2
Received: from int-mx1.corp.redhat.com (int-mx1.corp.redhat.com [172.16.52.254])
	by mail.boston.redhat.com (8.12.8/8.12.8) with ESMTP id k1FMEKi7012958;
	Wed, 15 Feb 2006 17:14:21 -0500
Received: from mx1.util.phx.redhat.com (mx1.util.phx.redhat.com [10.8.4.92])
	by int-mx1.corp.redhat.com (8.11.6/8.11.6) with ESMTP id k1FMEI100895;
	Wed, 15 Feb 2006 17:14:18 -0500
Received: from hormel.redhat.com (hormel.util.phx.redhat.com [10.8.4.111])
	by mx1.util.phx.redhat.com (8.13.1/8.13.1) with ESMTP id k1FMEDiK022652;
	Wed, 15 Feb 2006 17:14:13 -0500
Received: from listman.util.phx.redhat.com (listman.util.phx.redhat.com [10.8.4.110])
	by hormel.redhat.com (Postfix) with ESMTP
	id F186E7341E; Wed, 15 Feb 2006 17:14:12 -0500 (EST)
Received: from int-mx1.corp.redhat.com (int-mx1.corp.redhat.com
	[172.16.52.254])
	by listman.util.phx.redhat.com (8.13.1/8.13.1) with ESMTP id
	k1FMEB2n013835 for <linux-audit at listman.util.phx.redhat.com>;
	Wed, 15 Feb 2006 17:14:11 -0500
Received: from devserv.devel.redhat.com (devserv.devel.redhat.com
	[172.16.58.1])
	by int-mx1.corp.redhat.com (8.11.6/8.11.6) with ESMTP id k1FMEB100869
	for <linux-audit at redhat.com>; Wed, 15 Feb 2006 17:14:11 -0500
Received: from devserv.devel.redhat.com (localhost.localdomain [127.0.0.1])
	by devserv.devel.redhat.com (8.12.11/8.12.11) with ESMTP id
	k1FMEBP7003338
	for <linux-audit at redhat.com>; Wed, 15 Feb 2006 17:14:11 -0500
Received: (from aviro at localhost)
	by devserv.devel.redhat.com (8.12.11/8.12.11/Submit) id k1FMEBaK003335
	for linux-audit at redhat.com; Wed, 15 Feb 2006 17:14:11 -0500
Date: Wed, 15 Feb 2006 17:14:11 -0500
From: Alexander Viro <aviro at redhat.com>
To: linux-audit at redhat.com
Message-ID: <20060215221411.GX20691 at devserv.devel.redhat.com>
Mime-Version: 1.0
Content-Type: text/plain;
  charset=us-ascii
Content-Disposition: inline
User-Agent: Mutt/1.4.1i
X-loop: linux-audit at redhat.com
Subject: [PATCH] pass gfp_mask to kmalloc() done from audit_log_exit()
X-BeenThere: linux-audit at redhat.com
X-Mailman-Version: 2.1.5
Precedence: junk
List-Id: Linux Audit Discussion <linux-audit.redhat.com>
List-Unsubscribe: <https://www.redhat.com/mailman/listinfo/linux-audit>,
	<mailto:linux-audit-request at redhat.com?subject=unsubscribe>
List-Archive: <https://www.redhat.com/archives/linux-audit>
List-Post: <mailto:linux-audit at redhat.com>
List-Help: <mailto:linux-audit-request at redhat.com?subject=help>
List-Subscribe: <https://www.redhat.com/mailman/listinfo/linux-audit>,
	<mailto:linux-audit-request at redhat.com?subject=subscribe>
Sender: linux-audit-bounces at redhat.com
Errors-To: linux-audit-bounces at redhat.com
X-Length: 5978
X-UID: 49739

When caller tells us that there are constraints on allocations we are allowed
to do, we'd better follow those for more than the first allocation.

Signed-off-by: Al Viro <viro at zeniv.linux.org.uk>

---

 kernel/auditsc.c |   20 ++++++++++++--------
 1 files changed, 12 insertions(+), 8 deletions(-)

483cfcd5b5076acedd1729b23f84a901ab165baf
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 8b92132..a9e991b 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -503,7 +503,7 @@ static inline void audit_free_context(st
 		printk(KERN_ERR "audit: freed %d contexts\n", count);
 }
 
-static void audit_log_task_context(struct audit_buffer *ab)
+static void audit_log_task_context(struct audit_buffer *ab, gfp_t gfp_mask)
 {
 	char *ctx = NULL;
 	ssize_t len = 0;
@@ -515,7 +515,7 @@ static void audit_log_task_context(struc
 		return;
 	}
 
-	ctx = kmalloc(len, GFP_KERNEL);
+	ctx = kmalloc(len, gfp_mask);
 	if (!ctx)
 		goto error_path;
 
@@ -533,7 +533,7 @@ error_path:
 	return;
 }
 
-static void audit_log_task_info(struct audit_buffer *ab)
+static void audit_log_task_info(struct audit_buffer *ab, gfp_t gfp_mask)
 {
 	char name[sizeof(current->comm)];
 	struct mm_struct *mm = current->mm;
@@ -546,6 +546,10 @@ static void audit_log_task_info(struct a
 	if (!mm)
 		return;
 
+	/*
+	 * this is brittle; all callers that pass GFP_ATOMIC will have
+	 * NULL current->mm and we won't get here.
+	 */
 	down_read(&mm->mmap_sem);
 	vma = mm->mmap;
 	while (vma) {
@@ -559,7 +563,7 @@ static void audit_log_task_info(struct a
 		vma = vma->vm_next;
 	}
 	up_read(&mm->mmap_sem);
-	audit_log_task_context(ab);
+	audit_log_task_context(ab, gfp_mask);
 }
 
 static void audit_log_exit(struct audit_context *context, gfp_t gfp_mask)
@@ -595,12 +599,12 @@ static void audit_log_exit(struct audit_
 		  context->gid,
 		  context->euid, context->suid, context->fsuid,
 		  context->egid, context->sgid, context->fsgid, tty);
-	audit_log_task_info(ab);
+	audit_log_task_info(ab, gfp_mask);
 	audit_log_end(ab);
 
 	for (aux = context->aux; aux; aux = aux->next) {
 
-		ab = audit_log_start(context, GFP_KERNEL, aux->type);
+		ab = audit_log_start(context, gfp_mask, aux->type);
 		if (!ab)
 			continue; /* audit_panic has been called */
 
@@ -637,7 +641,7 @@ static void audit_log_exit(struct audit_
 	}
 
 	if (context->pwd && context->pwdmnt) {
-		ab = audit_log_start(context, GFP_KERNEL, AUDIT_CWD);
+		ab = audit_log_start(context, gfp_mask, AUDIT_CWD);
 		if (ab) {
 			audit_log_d_path(ab, "cwd=", context->pwd, context->pwdmnt);
 			audit_log_end(ab);
@@ -647,7 +651,7 @@ static void audit_log_exit(struct audit_
 		unsigned long ino  = context->names[i].ino;
 		unsigned long pino = context->names[i].pino;
 
-		ab = audit_log_start(context, GFP_KERNEL, AUDIT_PATH);
+		ab = audit_log_start(context, gfp_mask, AUDIT_PATH);
 		if (!ab)
 			continue; /* audit_panic has been called */
 
-- 
0.99.9.GIT

--
Linux-audit mailing list
Linux-audit at redhat.com
https://www.redhat.com/mailman/listinfo/linux-audit



Index: kernel-2.6.spec
===================================================================
RCS file: /cvs/dist/rpms/kernel/devel/kernel-2.6.spec,v
retrieving revision 1.1959
retrieving revision 1.1959.2.1
diff -u -r1.1959 -r1.1959.2.1
--- kernel-2.6.spec	16 Feb 2006 21:16:34 -0000	1.1959
+++ kernel-2.6.spec	20 Feb 2006 19:56:50 -0000	1.1959.2.1
@@ -22,7 +22,7 @@
 %define sublevel 15
 %define kversion 2.6.%{sublevel}
 %define rpmversion 2.6.%{sublevel}
-%define rhbsys  %([ -r /etc/beehive-root -o -n "%{?__beehive_build}" ] && echo || echo .`whoami`)
+%define rhbsys .lspp.9 
 %define release %(R="$Revision$"; RR="${R##: }"; echo ${RR%%?})_FC5%{rhbsys}
 %define signmodules 0
 %define make_target bzImage
@@ -403,6 +403,18 @@
 
 Patch20000: linux-2.6-xen-gcc-4.1-compile-fix.patch
 
+# Audit patches
+Patch20010: linux-2.6-audit-git.patch
+Patch20011: linux-2.6-audit-promisc.patch
+Patch20012: linux-2.6-audit-tty.patch
+Patch20013: linux-2.6-vm86-audit_syscall_exit.patch
+Patch20014: linux-2.6-audit-string-1.patch
+Patch20015: linux-2.6-audit-string-2.patch
+Patch20016: linux-2.6-audit-inotify-api.patch
+Patch20017: linux-2.6-audit-rule-log.patch
+Patch20018: linux-2.6-audit_log_exit-gfp_mask.patch
+Patch20019: linux-2.6-audit-fix-operators.patch
+
 # END OF PATCH DEFINITIONS
 
 BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root
@@ -933,7 +945,7 @@
 %patch1800 -p1
 # PNP support for smsc-ircc2
 %patch1810 -p1
-%patch1820 -p1
+#%patch1820 -p1
 # Silence debug messages in w1
 %patch1830 -p1
 # Reboot through BIOS on HP laptops.
@@ -985,6 +997,17 @@
 # Small 1-2 liners fixing silly bugs that get pushed upstream quickly.
 %patch10001 -p1
 
+%patch20010 -p1
+%patch20011 -p1
+%patch20012 -p1
+%patch20013 -p1
+%patch20014 -p1
+%patch20015 -p1
+%patch20016 -p1
+%patch20017 -p1
+%patch20018 -p1
+%patch20019 -p1
+
 
 # END OF PATCH APPLICATIONS
 
@@ -1573,6 +1596,9 @@
 %endif
 
 %changelog
+* Mon Feb 20 2006 Steve Grubb <sgrubb at redhat.com>
+- lspp9 kernel
+
 * Thu Feb 16 2006 John W. Linville <linville at redhat.com>
 - stop adding duplicate MODULE_VERSION line to tg3
 




More information about the fedora-cvs-commits mailing list