:: Tools ::
To enable the kernel functionality one will need to download the audit-0.6.9
source tree (
http://people.redhat.com/sgrubb/audit/) and apply the attached
patch. Read the README-install file for installation instructions. If the
audit daemon is not running (also included in this package), then audit
records will appear in /var/log/syslog rather then /var/log/audit.log. Use
the "auditctl" tool for inserting, removing, and listing watches.
Note: At the time of writing this e-mail the user space / kernel space
interaction is not yet complete. For instance, I'd eventually like to add
serialization routines to both spaces to pass "watch" structures more easily.
There is also talk about another type of watch listing feature that can list
all the watches present in memory.
++++
diff -Nurp audit-0.6.9/lib/libaudit.c audit-0.6.9~scratch/lib/libaudit.c
--- audit-0.6.9/lib/libaudit.c 2005-03-17 16:21:17.000000000 -0600
+++ audit-0.6.9~scratch/lib/libaudit.c 2005-03-29 23:33:51.000000000 -0600
@@ -220,6 +220,15 @@ int audit_remove_watch(int fd, struct au
return rc;
}
+int audit_list_watches(int fd, char *path)
+{
+ int rc = audit_send(fd, AUDIT_WATCH_LIST, path, strlen(path)+1);
+ if (rc < 0)
+ msg(LOG_WARNING, "Error sending watch list request (%s)",
+ strerror(-rc));
+ return rc;
+}
+
int audit_add_rule(int fd, struct audit_rule *rule, int flags, int action)
{
int rc;
diff -Nurp audit-0.6.9/lib/libaudit.h audit-0.6.9~scratch/lib/libaudit.h
--- audit-0.6.9/lib/libaudit.h 2005-03-17 16:20:26.000000000 -0600
+++ audit-0.6.9~scratch/lib/libaudit.h 2005-03-29 23:39:42.000000000 -0600
@@ -38,11 +38,12 @@
#ifndef AUDIT_WATCH_INS
#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 watches on dir */
struct audit_watch {
- int namelen;
- int fklen;
- char *name;
- char *filterkey;
+ uint32_t namelen;
+ uint32_t fklen;
+ char *name;
+ char *filterkey;
uint32_t perms;
};
/* 32 byte max key size */
@@ -62,7 +63,7 @@ struct audit_reply {
struct audit_login *login;
const char *message;
struct nlmsgerr *error;
- int watch;
+ const char *watch;
};
struct auditd_reply_list {
@@ -119,6 +120,7 @@ extern int audit_request_list(int fd);
/* AUDIT_WATCH */
extern int audit_insert_watch(int fd, struct audit_watch *req);
extern int audit_remove_watch(int fd, struct audit_watch *req);
+extern int audit_list_watches(int fd, char *path);
/* AUDIT_ADD */
extern int audit_add_rule(int fd, struct audit_rule *rule,
diff -Nurp audit-0.6.9/lib/netlink.c audit-0.6.9~scratch/lib/netlink.c
--- audit-0.6.9/lib/netlink.c 2005-03-17 16:25:21.000000000 -0600
+++ audit-0.6.9~scratch/lib/netlink.c 2005-03-29 23:33:57.000000000 -0600
@@ -132,7 +132,7 @@ static int adjust_reply(struct audit_rep
rep->rule = NULL;
rep->message = NULL;
rep->error = NULL;
- rep->watch = 0;
+ rep->watch = NULL;
if (!NLMSG_OK(rep->nlh, (unsigned int)len))
return 0;
switch (rep->type) {
@@ -150,9 +150,8 @@ 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));
+ case AUDIT_WATCH_LIST:
+ rep->watch = NLMSG_DATA(rep->nlh);
break;
}
return len;
diff -Nurp audit-0.6.9/src/auditctl.c audit-0.6.9~scratch/src/auditctl.c
--- audit-0.6.9/src/auditctl.c 2005-03-17 16:24:50.000000000 -0600
+++ audit-0.6.9~scratch/src/auditctl.c 2005-03-29 23:44:10.000000000 -0600
@@ -71,7 +71,8 @@ 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 int ins = 0, rem = 0, list = 0;
+static char *path;
static struct audit_rule rule;
static struct audit_watch watch;
@@ -122,10 +123,11 @@ static void usage(void)
" -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"
+ " -p [rwea] Set permissions filter on watch:\n"
" r=read, w=write, e=execute, a=append\n"
" -k <key> Set filterkey on watch\n"
+ " -W <path> Remove watch at <path>\n"
+ " -L <path> List all watches at <path>\n"
);
}
@@ -295,7 +297,7 @@ 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:w:W:k:p:")) != EOF &&
+ "hslDe:f:r:b:a:A:d:S:F:m:t:R:w:W:L:k:p:")) != EOF &&
retval != -1) {
switch (c) {
case 'h':
@@ -467,6 +469,16 @@ static int setopt(int count, char *vars[
retval = -1;
}
break;
+ case 'L':
+ if (optarg) {
+ list = 1;
+ path = optarg;
+ retval = audit_list_watches(fd, path);
+ } else {
+ fprintf(stderr, "watch option needs a path\n");
+ retval = -1;
+ }
+ break;
case 'k':
if (!ins) {
fprintf(stderr,
@@ -646,13 +658,13 @@ int main(int argc, char *argv[])
/*
* This function is called after setopt to handle the return code.
* status = 0 means just get the reply. Greater than 0 means we
- * are adding or deleting a rule. Less than 0 means an error occurred.
- * Even if there's an error, we need to call this routine to close up the
- * audit fd.
+ * are adding or deleting a rule or watch. Less than 0 means an error
+ * occurred. Even if there's an error, we need to call this routine
+ * to close up the audit fd.
*/
static int handle_request(int status)
{
- if (status == 0)
+ if (list || status == 0)
get_reply();
else if (status > 0) {
int rc;
@@ -669,20 +681,21 @@ static int handle_request(int status)
audit_close(fd);
exit(1);
}
- if (rc > 0) {
- if (audit_request_list(fd) > 0) {
- list_requested = 1;
- get_reply();
+ if (!ins && !rem) {
+ if (rc > 0) {
+ if (audit_request_list(fd) > 0) {
+ list_requested = 1;
+ get_reply();
+ } else {
+ fprintf(stderr, "Error requesting list\n");
+ status = -1;
+ }
} else {
- fprintf(stderr, "Error requesting list\n");
+ fprintf(stderr, "Error sending rule to kernel\n");
status = -1;
- }
- } else {
- fprintf(stderr, "Error sending rule to kernel\n");
- status = -1;
+ }
}
- }
- else {
+ } else {
status = -1;
}
audit_close(fd);
@@ -727,7 +740,7 @@ static int audit_print_reply(struct audi
case NLMSG_NOOP:
return 1;
case NLMSG_DONE:
- if (list_requested)
+ if (list_requested && (!rem && !ins))
printf("No rules\n");
return 0;
case NLMSG_ERROR:
@@ -788,18 +801,16 @@ 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;
+ case AUDIT_WATCH_LIST: {
+ if (rep->watch)
+ if (path[strlen(path)-1] == '/')
+ printf("AUDIT_WATCH: LIST: path=%s%s\n",
+ path, rep->watch);
+ else
+ printf("AUDIT_WATCH: LIST: path=%s/%s\n",
+ path, rep->watch);
+ return 1;
+ }
default:
printf("Unknown: type=%d, len=%d\n", rep->type,
rep->nlh->nlmsg_len);
return 0;
-tim