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(a)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;