[PATCH] auditfsify the audit-0.6.7 userspace package

Timothy R. Chavez tinytim at us.ibm.com
Mon Mar 14 16:30:55 UTC 2005


Hello,

This patch is updated for audit-0.6.7.  The most notable change is the removal 
of runtime enablement/disablement of the filesystem auditing mechanism.  
Though I don't envision many more changes on my part, to the userspace 
package,  I have to reiterate that the mixed-spacing is atrocious and that we 
should just "indent -i8 -kr" the entire audit userspace package so we can get 
some normalcy going.

A patch for auditfs against linux-2.6.11 should follow suit.  I just need to 
do a little more testing of the newer logic.

Please note, it's probably best to patch with a seperate audit-0.6.7 package 
and ./configure it with an sbindir other then the one you used for your 
original audit-0.6.7 install.

-tim

diff -Nurp audit-0.6.7/lib/libaudit.c auditfs-audit-0.6.7/lib/libaudit.c
--- audit-0.6.7/lib/libaudit.c	2005-03-09 12:11:39.000000000 -0600
+++ auditfs-audit-0.6.7/lib/libaudit.c	2005-03-14 00:29:58.000000000 -0600
@@ -200,6 +200,17 @@ uid_t audit_getloginuid(void)
 		return uid;
 }
 
+/* req->namelen is used for kernel->user traffic only */
+int audit_insert_watch(int fd, struct audit_watch *req)
+{
+    return audit_send(fd, AUDIT_WATCH_INS, req, sizeof(*req));
+}
+
+int audit_remove_watch(int fd, struct audit_watch *req)
+{
+    return audit_send(fd, AUDIT_WATCH_REM, req, sizeof(*req));
+}
+
 int audit_send_message(int fd, const char *message)
 {
 	if (fd >= 0) {
diff -Nurp audit-0.6.7/lib/libaudit.h auditfs-audit-0.6.7/lib/libaudit.h
--- audit-0.6.7/lib/libaudit.h	2005-03-08 12:56:09.000000000 -0600
+++ auditfs-audit-0.6.7/lib/libaudit.h	2005-03-14 00:32:50.000000000 -0600
@@ -45,6 +45,7 @@ struct audit_reply {
     struct audit_status  *status;
     struct audit_rule    *rule;
     struct audit_login   *login;
+    int			 watch;
     const char           *message;
     struct nlmsgerr      *error;
 };
@@ -120,6 +121,11 @@ extern int  audit_set_loginuid(uid_t uid
 extern int  audit_login_message(int fd, const char *arg);
 extern int  audit_logout_message(int fd, const char *arg);
 
+/* INSERT WATCH */
+extern int audit_insert_watch(int fd, struct audit_watch *req);
+/* REMOVE WATCH */
+extern int audit_remove_watch(int fd, struct audit_watch *req);
+
 /* Rule-building helper functions */
 extern struct audit_rule *audit_rule_alloc(void);
 extern int  audit_rule_syscall(struct audit_rule *rule, int syscall);
diff -Nurp audit-0.6.7/lib/netlink.c auditfs-audit-0.6.7/lib/netlink.c
--- audit-0.6.7/lib/netlink.c	2005-03-08 12:55:31.000000000 -0600
+++ auditfs-audit-0.6.7/lib/netlink.c	2005-03-14 00:32:31.000000000 -0600
@@ -124,6 +124,7 @@ static int adjust_reply(struct audit_rep
     rep->type    = rep->msg.nlh.nlmsg_type;
     rep->len     = rep->msg.nlh.nlmsg_len;
     rep->nlh     = &rep->msg.nlh;
+    rep->watch	 = 0;
     rep->status  = NULL;
     rep->rule    = NULL;
     rep->message = NULL;
@@ -146,6 +147,10 @@ static int adjust_reply(struct audit_rep
     case AUDIT_USER:  
 	rep->message = NLMSG_DATA(rep->nlh); 
 	break;
+    case AUDIT_WATCH_INS:
+    case AUDIT_WATCH_REM:
+	memcpy(&rep->watch, NLMSG_DATA(rep->nlh), sizeof(int));
+	break;
     }
     return len;
 }
diff -Nurp audit-0.6.7/linux/audit.h auditfs-audit-0.6.7/linux/audit.h
--- audit-0.6.7/linux/audit.h	1969-12-31 17:00:00.000000000 -0700
+++ auditfs-audit-0.6.7/linux/audit.h	2005-03-14 00:35:27.000000000 -0600
@@ -0,0 +1,268 @@
+/* audit.h -- Auditing support -*- linux-c -*-
+ *
+ * Copyright 2003-2004 Red Hat Inc., Durham, North Carolina.
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Written by Rickard E. (Rik) Faith <faith at redhat.com>
+ *
+ */
+
+#ifndef _LINUX_AUDIT_H_
+#define _LINUX_AUDIT_H_
+
+#ifdef __KERNEL__
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <asm/atomic.h>
+#endif
+
+/* Request and reply types */
+#define AUDIT_GET      	1000	/* Get status */
+#define AUDIT_SET      	1001	/* Set status (enable/disable/auditd) */
+#define AUDIT_LIST     	1002	/* List filtering rules */
+#define AUDIT_ADD      	1003	/* Add filtering rule */
+#define AUDIT_DEL      	1004	/* Delete filtering rule */
+#define AUDIT_USER     	1005	/* Send a message from user-space */
+#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_KERNEL   	2000	/* Asynchronous audit record. NOT A REQUEST. */
+
+/* Rule flags */
+#define AUDIT_PER_TASK 0x01	/* Apply rule at task creation (not syscall) */
+#define AUDIT_AT_ENTRY 0x02	/* Apply rule at syscall entry */
+#define AUDIT_AT_EXIT  0x04	/* Apply rule at syscall exit */
+#define AUDIT_PREPEND  0x10	/* Prepend to front of list */
+
+/* Rule actions */
+#define AUDIT_NEVER    0	/* Do not build context if rule matches */
+#define AUDIT_POSSIBLE 1	/* Build context if rule matches  */
+#define AUDIT_ALWAYS   2	/* Generate audit record if rule matches */
+
+/* Rule structure sizes -- if these change, different AUDIT_ADD and
+ * AUDIT_LIST commands must be implemented. */
+#define AUDIT_MAX_FIELDS   64
+#define AUDIT_BITMASK_SIZE 64
+#define AUDIT_WORD(nr) ((__u32)((nr)/32))
+#define AUDIT_BIT(nr)  (1 << ((nr) - AUDIT_WORD(nr)*32))
+
+/* Rule fields */
+				/* These are useful when checking the
+				 * task structure at task creation time
+				 * (AUDIT_PER_TASK).  */
+#define AUDIT_PID	0
+#define AUDIT_UID	1
+#define AUDIT_EUID	2
+#define AUDIT_SUID	3
+#define AUDIT_FSUID	4
+#define AUDIT_GID	5
+#define AUDIT_EGID	6
+#define AUDIT_SGID	7
+#define AUDIT_FSGID	8
+#define AUDIT_LOGINUID	9
+#define AUDIT_PERS	10
+
+				/* These are ONLY useful when checking
+				 * at syscall exit time (AUDIT_AT_EXIT). */
+#define AUDIT_DEVMAJOR	100
+#define AUDIT_DEVMINOR	101
+#define AUDIT_INODE	102
+#define AUDIT_EXIT	103
+#define AUDIT_SUCCESS   104	/* exit >= 0; value ignored */
+
+#define AUDIT_ARG0      200
+#define AUDIT_ARG1      (AUDIT_ARG0+1)
+#define AUDIT_ARG2      (AUDIT_ARG0+2)
+#define AUDIT_ARG3      (AUDIT_ARG0+3)
+
+#define AUDIT_NEGATE    0x80000000
+
+
+/* Status symbols */
+				/* Mask values */
+#define AUDIT_STATUS_ENABLED		0x0001
+#define AUDIT_STATUS_FAILURE		0x0002
+#define AUDIT_STATUS_PID		0x0004
+#define AUDIT_STATUS_RATE_LIMIT		0x0008
+#define AUDIT_STATUS_BACKLOG_LIMIT	0x0010
+
+				/* Failure-to-log actions */
+#define AUDIT_FAIL_SILENT	0
+#define AUDIT_FAIL_PRINTK	1
+#define AUDIT_FAIL_PANIC	2
+
+/* 32 byte max key size */
+#define AUDIT_FILTERKEY_MAX	32
+
+#ifndef __KERNEL__
+struct audit_message {
+	struct nlmsghdr nlh;
+	char		data[1200];
+};
+#endif
+
+struct audit_status {
+	__u32		mask;		/* Bit mask for valid entries */
+	__u32		enabled;	/* 1 = enabled, 0 = disbaled */
+	__u32		failure;	/* Failure-to-log action */
+	__u32		pid;		/* pid of auditd process */
+	__u32		rate_limit;	/* messages rate limit (per second) */
+	__u32		backlog_limit;	/* waiting messages limit */
+	__u32		lost;		/* messages lost */
+	__u32		backlog;	/* messages waiting in queue */
+};
+
+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 */
+	__u32		field_count;
+	__u32		mask[AUDIT_BITMASK_SIZE];
+	__u32		fields[AUDIT_MAX_FIELDS];
+	__u32		values[AUDIT_MAX_FIELDS];
+};
+
+struct audit_watch {
+	int	namelen;
+	int 	fklen;
+	char	*name;
+	char	*filterkey;
+	__u32	perms;
+};
+
+#ifdef __KERNEL__
+
+struct audit_data {
+	struct audit_wentry	*wentry;
+	struct list_head 	watchlist;
+	rwlock_t 		watchlist_lock;
+	struct list_head	link;
+};
+
+struct audit_wentry {
+	struct list_head 	w_list;
+	atomic_t 		w_count;
+	struct audit_watch	*w_watch;
+	unsigned int		w_valid;
+	unsigned int		w_cached;
+
+};
+
+#ifdef CONFIG_AUDIT
+struct audit_buffer;
+struct audit_context;
+#endif
+
+#ifdef CONFIG_AUDITSYSCALL
+/* These are defined in auditsc.c */
+				/* Public API */
+extern int  audit_alloc(struct task_struct *task);
+extern void audit_free(struct task_struct *task);
+extern void audit_syscall_entry(struct task_struct *task,
+				int major, unsigned long a0, unsigned long a1,
+				unsigned long a2, unsigned long a3);
+extern void audit_syscall_exit(struct task_struct *task, int return_code);
+extern void audit_getname(const char *name);
+extern void audit_putname(const char *name);
+extern void audit_inode(const char *name, unsigned long ino, dev_t rdev);
+
+				/* Private API (for audit.c only) */
+extern int  audit_receive_filter(int type, int pid, int uid, int seq,
+				 void *data);
+extern void audit_get_stamp(struct audit_context *ctx,
+			    struct timespec *t, int *serial);
+extern int  audit_set_loginuid(struct audit_context *ctx, uid_t loginuid);
+extern uid_t audit_get_loginuid(struct audit_context *ctx);
+#ifdef CONFIG_AUDITFILESYSTEM
+extern int audit_notify_watch(struct inode *inode, int mask);
+#else
+#define audit_notify_watch(i,m) ({ 0; })
+#endif
+#else
+#define audit_alloc(t) ({ 0; })
+#define audit_free(t) do { ; } while (0)
+#define audit_syscall_entry(t,a,b,c,d,e) do { ; } while (0)
+#define audit_syscall_exit(t,r) do { ; } while (0)
+#define audit_getname(n) do { ; } while (0)
+#define audit_putname(n) do { ; } while (0)
+#define audit_inode(n,i,d) do { ; } while (0)
+#define audit_get_loginuid(c) ({ -1; })
+#define audit_notify_watch(i,m) ({ 0; })
+#endif
+
+#ifdef CONFIG_AUDITFILESYSTEM
+extern void audit_receive_watch(int type, int pid, int uid, int seq,
+			       struct audit_watch *req);
+extern int audit_filesystem_init(void);
+extern void audit_inode_alloc(struct inode *inode);
+extern void audit_inode_free(struct inode *inode);
+extern void audit_watch(struct dentry *dentry, int remove);
+extern void audit_wentry_put(struct audit_wentry *wentry);
+extern struct audit_wentry *audit_wentry_get(struct audit_wentry *wentry);
+#else
+#define audit_receive_watch(t,p,u,s,r) ({ -EOPNOTSUPP; })
+#define audit_filesystem_init() ({ 0; })
+#define audit_inode_alloc(i) do { ; } while(0)
+#define audit_inode_free(i) do { ; } while(0)
+#define audit_watch(d,r) do { ; } while (0)
+#define audit_watch_put(w) do { ; } while(0)
+#define audit_watch_get(w) ({ 0; })
+#endif
+
+#ifdef CONFIG_AUDIT
+/* These are defined in audit.c */
+				/* Public API */
+extern void		    audit_log(struct audit_context *ctx,
+				      const char *fmt, ...)
+			    __attribute__((format(printf,2,3)));
+
+extern struct audit_buffer *audit_log_start(struct audit_context *ctx);
+extern void		    audit_log_format(struct audit_buffer *ab,
+					     const char *fmt, ...)
+			    __attribute__((format(printf,2,3)));
+extern void		    audit_log_end(struct audit_buffer *ab);
+extern void		    audit_log_end_fast(struct audit_buffer *ab);
+extern void		    audit_log_end_irq(struct audit_buffer *ab);
+extern void		    audit_log_d_path(struct audit_buffer *ab,
+					     const char *prefix,
+					     struct dentry *dentry,
+					     struct vfsmount *vfsmnt);
+extern int		    audit_set_rate_limit(int limit);
+extern int		    audit_set_backlog_limit(int limit);
+extern int		    audit_set_enabled(int state);
+extern int		    audit_set_failure(int state);
+
+				/* Private API (for auditsc.c only) */
+extern void		    audit_send_reply(int pid, int seq, int type,
+					     int done, int multi,
+					     void *payload, int size);
+extern void		    audit_log_lost(const char *message);
+#else
+#define audit_log(t,f,...) do { ; } while (0)
+#define audit_log_start(t) ({ NULL; })
+#define audit_log_vformat(b,f,a) do { ; } while (0)
+#define audit_log_format(b,f,...) do { ; } while (0)
+#define audit_log_end(b) do { ; } while (0)
+#define audit_log_end_fast(b) do { ; } while (0)
+#define audit_log_end_irq(b) do { ; } while (0)
+#define audit_log_d_path(b,p,d,v) do { ; } while (0)
+#define audit_set_rate_limit(l) do { ; } while (0)
+#define audit_set_backlog_limit(l) do { ; } while (0)
+#define audit_set_enabled(s) do { ; } while (0)
+#define audit_set_failure(s) do { ; } while (0)
+#endif
+#endif
+#endif
diff -Nurp audit-0.6.7/src/auditctl.c auditfs-audit-0.6.7/src/auditctl.c
--- audit-0.6.7/src/auditctl.c	2005-03-14 00:45:01.000000000 -0600
+++ auditfs-audit-0.6.7/src/auditctl.c	2005-03-14 00:39:49.000000000 -0600
@@ -49,6 +49,14 @@
  */
 #define LINE_SIZE 1600
 
+#define WATCH_MAY_EXEC		1
+#define WATCH_MAY_WRITE		2
+#define WATCH_MAY_READ		4
+#define WATCH_MAY_APPEND	8
+
+#define WATCH_NAME		1
+#define WATCH_FILTERKEY		2
+#define WATCH_PERMS		3
 
 /* Global functions */
 static int handle_request(int status);
@@ -61,7 +69,9 @@ static int fd = -1;
 static int list_requested = 0;
 static int syscalladded = 0;
 static int add = 0, del = 0, action = 0;
+static int ins = 0, rem = 0;
 static struct audit_rule  rule;
+static struct audit_watch watch;
 
 /*
  * This function will reset everything used for each loop when loading 
@@ -73,8 +83,11 @@ static int reset_vars(void)
 	syscalladded = 0;
 	add = 0;
 	del = 0;
+	ins = 0;
+	rem = 0;
 	action = 0;
 	memset(&rule, 0, sizeof(rule));
+	memset(&watch, 0, sizeof(watch));
 	if ((fd = audit_open()) < 0) {
 		fprintf(stderr, "Cannot open netlink audit socket\n");
 		return 1;
@@ -104,6 +117,11 @@ static void usage(void)
      "       -s           Report status\n"
      "       -S syscall   Build rule: syscall name or number\n"
      "       -t <syscall> Translate syscall number to syscall name\n"
+     "       -w <path>    Insert watch at <path>\n"
+     "       -W <path>    Remove watch at <path>\n"
+     "       -p [r|w|e|a] Set permissions filter on watch:\n"
+     "                      r=read, w=write, e=execute, a=append\n"
+     "       -k <key>     Set filterkey on watch\n"
      );
 }
 
@@ -128,6 +146,84 @@ static int audit_rule_setup(const char *
     return 0;
 }
 
+/* Setup a watch.  The "name" of the watch in userspace will be the <path> to
+ * the watch.  When this potential watch reaches the kernel, it will resolve
+ * down to <name> (of terminating file or directory).
+ */
+static int audit_watch_setup(int type, struct audit_watch *req,
+			     const char *opt)
+{
+	int i;
+	int ret = 0;
+
+	if (!opt)
+		goto audit_watch_setup_exit;
+
+	switch (type) {
+		case WATCH_NAME:
+			if (!req->name && opt) {
+				req->namelen = strlen(opt) + 1;
+	    			req->name = (char *) malloc(req->namelen);
+	    			if (!req->name)
+	    				goto audit_watch_setup_exit;
+	    			strcpy(req->name, opt);
+	    			ret = 1;
+			}
+		break;
+    		case WATCH_FILTERKEY:
+			if (!req->filterkey && opt) {
+	    			req->fklen = strlen(opt) + 1;
+	    			req->filterkey = (char *) malloc(req->fklen);
+	    			if (!req->filterkey)
+	    				goto audit_watch_setup_exit;
+	    			strcpy(req->filterkey, opt);
+	    			ret = 1;
+			}
+		break;
+		case WATCH_PERMS:
+			if (strlen(opt) > 4)
+				goto audit_watch_setup_exit;
+
+			for (i = 0; i < strlen(opt); i++) {
+			switch (opt[i]) {
+				case 'r':
+					if (!(req->perms & WATCH_MAY_READ))
+						req->perms |= WATCH_MAY_READ;
+					else
+						goto audit_watch_setup_exit;
+					break;
+	    			case 'w':
+					if (!(req->perms & WATCH_MAY_WRITE))
+					req->perms |= WATCH_MAY_WRITE;
+					else
+						goto audit_watch_setup_exit;
+					break;
+				case 'e':
+					if (!(req->perms & WATCH_MAY_EXEC))
+						req->perms |= WATCH_MAY_EXEC;
+					else
+						goto audit_watch_setup_exit;
+					break;
+	    			case 'a':
+					if (!(req->perms & WATCH_MAY_APPEND))
+						req->perms |= WATCH_MAY_APPEND;
+					else
+						goto audit_watch_setup_exit;
+					break;
+	    			default:
+					goto audit_watch_setup_exit;
+			}
+		}
+
+		ret = 1;
+
+		default:
+			break;
+	}
+audit_watch_setup_exit:
+	return ret;
+}
+
 /*
  * returns: < 0 error - noreply, 0 success - reply, > 0 success - rule
  */
@@ -138,8 +234,8 @@ static int setopt(int count, char *vars[
 
     optind = 0;
     opterr = 0;
-    while ((c = getopt(count, vars, "hslDe:f:r:b:a:A:d:S:F:m:t:R:")) != EOF 
&&
-		retval != -1) {
+    while ((c = getopt(count, vars, 
"hslDf:e:E:r:b:a:A:d:S:F:m:t:R:W:w:k:p:"))
+    		!= EOF && retval != -1) {
         switch (c) {
         case 'h':
 		usage();
@@ -291,6 +387,38 @@ static int setopt(int count, char *vars[
 	case 'D':
 		retval = delete_all_rules();
 		break;
+	case 'W':
+		if (audit_watch_setup(WATCH_NAME, &watch, optarg))
+			rem = retval = 1;
+		else {
+			usage();
+			retval = -1;
+		}
+		break;
+	case 'w':
+		if (audit_watch_setup(WATCH_NAME, &watch, optarg))
+			ins = retval = 1;
+		else {
+			usage();
+			retval = -1;
+		}
+		break;
+	case 'k':
+		if (ins && audit_watch_setup(WATCH_FILTERKEY, &watch, optarg))
+			retval = 1;
+		else {
+			usage();
+			retval = -1;
+		}
+		break;
+	case 'p':
+		if (ins && audit_watch_setup(WATCH_PERMS, &watch, optarg))
+			retval = 1;
+		else {
+			usage();
+			retval = -1;
+		}
+		break;
         default: 
 		usage();
 		retval = -1;
@@ -458,6 +586,10 @@ static int handle_request(int status)
 		rc = audit_add_rule(fd, &rule, add, action);
 	else if (del & 0x07) 
 		rc = audit_delete_rule(fd, &rule, del, action);
+	else if (ins && !rem)
+		rc = audit_insert_watch(fd, &watch);
+	else if (rem && !ins)
+		rc = audit_remove_watch(fd, &watch);
 	else {
         	usage();
     		audit_close(fd);
@@ -577,6 +709,18 @@ static int audit_print_reply(struct audi
         }
         printf("\n");
         return 1;               /* get more messages, until NLMSG_DONE */
+   case AUDIT_WATCH_INS:
+   	if (rep->watch < 0)
+		printf("AUDIT_WATCH : INSERT : %s\n", strerror(-(rep->watch)));
+	else
+		printf("AUDIT_WATCH : INSERT : SUCCESS\n");
+	return 0;
+    case AUDIT_WATCH_REM:
+    	if (rep->watch < 0)
+		printf("AUDIT_WATCH : REMOVE : %s\n", strerror(-(rep->watch)));
+	else
+		printf("AUDIT_WATCH : REMOVE : SUCCESS\n");
+	return 0;
     default:
         printf("Unknown: type=%d, len=%d\n", rep->type, rep->nlh->nlmsg_len);
         return 0;




More information about the Linux-audit mailing list