From c2f0c7c356dc9ae15419f00c725a2fcc58eeff58 Mon Sep 17 00:00:00 2001 From: Steve Grubb Date: Fri, 6 May 2005 12:38:39 +0100 Subject: The attached patch addresses the problem with getting the audit daemon shutdown credential information. It creates a new message type AUDIT_TERM_INFO, which is used by the audit daemon to query who issued the shutdown. It requires the placement of a hook function that gathers the information. The hook is after the DAC & MAC checks and before the function returns. Racing threads could overwrite the uid & pid - but they would have to be root and have policy that allows signalling the audit daemon. That should be a manageable risk. The userspace component will be released later in audit 0.7.2. When it receives the TERM signal, it queries the kernel for shutdown information. When it receives it, it writes the message and exits. The message looks like this: type=DAEMON msg=auditd(1114551182.000) auditd normal halt, sending pid=2650 uid=525, auditd pid=1685 Signed-off-by: Steve Grubb Signed-off-by: David Woodhouse --- kernel/auditsc.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'kernel/auditsc.c') diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 37b3ac9..f1bf665 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -1056,3 +1056,22 @@ int audit_ipc_perms(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode) context->aux = (void *)ax; return 0; } + +void audit_signal_info(int sig, struct task_struct *t) +{ + extern pid_t audit_sig_pid; + extern uid_t audit_sig_uid; + extern int audit_pid; + + if (unlikely(audit_pid && t->pid == audit_pid)) { + if (sig == SIGTERM || sig == SIGHUP) { + struct audit_context *ctx = current->audit_context; + audit_sig_pid = current->pid; + if (ctx) + audit_sig_uid = ctx->loginuid; + else + audit_sig_uid = current->uid; + } + } +} + -- cgit v1.1 From 804a6a49d874841a98ebea3247ad2e672812ad6a Mon Sep 17 00:00:00 2001 From: Chris Wright Date: Wed, 11 May 2005 10:52:45 +0100 Subject: Audit requires CONFIG_NET Audit now actually requires netlink. So make it depend on CONFIG_NET, and remove the inline dependencies on CONFIG_NET. Signed-off-by: Chris Wright Signed-off-by: David Woodhouse --- kernel/auditsc.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'kernel/auditsc.c') diff --git a/kernel/auditsc.c b/kernel/auditsc.c index f1bf665..680bb92 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -226,7 +226,6 @@ static inline int audit_del_rule(struct audit_rule *rule, return -EFAULT; /* No matching rule */ } -#ifdef CONFIG_NET /* Copy rule from user-space to kernel-space. Called during * AUDIT_ADD. */ static int audit_copy_rule(struct audit_rule *d, struct audit_rule *s) @@ -305,7 +304,6 @@ int audit_receive_filter(int type, int pid, int uid, int seq, void *data, return err; } -#endif /* Compare a task_struct with an audit_rule. Return 1 on match, 0 * otherwise. */ -- cgit v1.1 From 197c69c6afd2deb7eec44040ff533d90d26c6161 Mon Sep 17 00:00:00 2001 From: Chris Wright Date: Wed, 11 May 2005 10:54:05 +0100 Subject: Move ifdef CONFIG_AUDITSYSCALL to header Remove code conditionally dependent on CONFIG_AUDITSYSCALL from audit.c. Move these dependencies to audit.h with the rest. Signed-off-by: Chris Wright Signed-off-by: David Woodhouse --- kernel/auditsc.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'kernel/auditsc.c') diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 680bb92..94338ab 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -992,7 +992,7 @@ void audit_inode(const char *name, const struct inode *inode) context->names[idx].rdev = inode->i_rdev; } -void audit_get_stamp(struct audit_context *ctx, +int audit_get_stamp(struct audit_context *ctx, struct timespec *t, unsigned int *serial) { if (ctx) { @@ -1000,10 +1000,9 @@ void audit_get_stamp(struct audit_context *ctx, t->tv_nsec = ctx->ctime.tv_nsec; *serial = ctx->serial; ctx->auditable = 1; - } else { - *t = CURRENT_TIME; - *serial = 0; + return 1; } + return 0; } extern int audit_set_type(struct audit_buffer *ab, int type); -- cgit v1.1 From c1b773d87eadc3972d697444127e89a7291769a2 Mon Sep 17 00:00:00 2001 From: Chris Wright Date: Wed, 11 May 2005 10:55:10 +0100 Subject: Add audit_log_type Add audit_log_type to allow callers to specify type and pid when logging. Convert audit_log to wrapper around audit_log_type. Could have converted all audit_log callers directly, but common case is default of type AUDIT_KERNEL and pid 0. Update audit_log_start to take type and pid values when creating a new audit_buffer. Move sequences that did audit_log_start, audit_log_format, audit_set_type, audit_log_end, to simply call audit_log_type directly. This obsoletes audit_set_type and audit_set_pid, so remove them. Signed-off-by: Chris Wright Signed-off-by: David Woodhouse --- kernel/auditsc.c | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) (limited to 'kernel/auditsc.c') diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 94338ab..d089263 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -648,7 +648,7 @@ static void audit_log_exit(struct audit_context *context) int i; struct audit_buffer *ab; - ab = audit_log_start(context); + ab = audit_log_start(context, AUDIT_KERNEL, 0); if (!ab) return; /* audit_panic has been called */ audit_log_format(ab, "syscall=%d", context->major); @@ -680,7 +680,7 @@ static void audit_log_exit(struct audit_context *context) while (context->aux) { struct audit_aux_data *aux; - ab = audit_log_start(context); + ab = audit_log_start(context, AUDIT_KERNEL, 0); if (!ab) continue; /* audit_panic has been called */ @@ -701,7 +701,7 @@ static void audit_log_exit(struct audit_context *context) } for (i = 0; i < context->name_count; i++) { - ab = audit_log_start(context); + ab = audit_log_start(context, AUDIT_KERNEL, 0); if (!ab) continue; /* audit_panic has been called */ audit_log_format(ab, "item=%d", i); @@ -1005,22 +1005,13 @@ int audit_get_stamp(struct audit_context *ctx, return 0; } -extern int audit_set_type(struct audit_buffer *ab, int type); - int audit_set_loginuid(struct task_struct *task, uid_t loginuid) { if (task->audit_context) { - struct audit_buffer *ab; - - ab = audit_log_start(NULL); - if (ab) { - audit_log_format(ab, "login pid=%d uid=%u " - "old loginuid=%u new loginuid=%u", - task->pid, task->uid, - task->audit_context->loginuid, loginuid); - audit_set_type(ab, AUDIT_LOGIN); - audit_log_end(ab); - } + audit_log_type(NULL, AUDIT_LOGIN, 0, + "login pid=%d uid=%u old loginuid=%u new loginuid=%u", + task->pid, task->uid, task->audit_context->loginuid, + loginuid); task->audit_context->loginuid = loginuid; } return 0; -- cgit v1.1 From c04049939f88b29e235d2da217bce6e8ead44f32 Mon Sep 17 00:00:00 2001 From: Steve Grubb Date: Fri, 13 May 2005 18:17:42 +0100 Subject: AUDIT: Add message types to audit records This patch adds more messages types to the audit subsystem so that audit analysis is quicker, intuitive, and more useful. Signed-off-by: Steve Grubb --- I forgot one type in the big patch. I need to add one for user space originating SE Linux avc messages. This is used by dbus and nscd. -Steve --- Updated to 2.6.12-rc4-mm1. -dwmw2 Signed-off-by: David Woodhouse --- kernel/auditsc.c | 42 +++++++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 17 deletions(-) (limited to 'kernel/auditsc.c') diff --git a/kernel/auditsc.c b/kernel/auditsc.c index d089263..1b7c91f 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -286,7 +286,8 @@ int audit_receive_filter(int type, int pid, int uid, int seq, void *data, err = audit_add_rule(entry, &audit_entlist); if (!err && (flags & AUDIT_AT_EXIT)) err = audit_add_rule(entry, &audit_extlist); - audit_log(NULL, "auid %u added an audit rule\n", loginuid); + audit_log(NULL, AUDIT_CONFIG_CHANGE, + "auid %u added an audit rule\n", loginuid); break; case AUDIT_DEL: flags =((struct audit_rule *)data)->flags; @@ -296,7 +297,8 @@ int audit_receive_filter(int type, int pid, int uid, int seq, void *data, err = audit_del_rule(data, &audit_entlist); if (!err && (flags & AUDIT_AT_EXIT)) err = audit_del_rule(data, &audit_extlist); - audit_log(NULL, "auid %u removed an audit rule\n", loginuid); + audit_log(NULL, AUDIT_CONFIG_CHANGE, + "auid %u removed an audit rule\n", loginuid); break; default: return -EINVAL; @@ -648,7 +650,7 @@ static void audit_log_exit(struct audit_context *context) int i; struct audit_buffer *ab; - ab = audit_log_start(context, AUDIT_KERNEL, 0); + ab = audit_log_start(context, AUDIT_SYSCALL); if (!ab) return; /* audit_panic has been called */ audit_log_format(ab, "syscall=%d", context->major); @@ -680,28 +682,28 @@ static void audit_log_exit(struct audit_context *context) while (context->aux) { struct audit_aux_data *aux; - ab = audit_log_start(context, AUDIT_KERNEL, 0); + aux = context->aux; + + ab = audit_log_start(context, aux->type); if (!ab) continue; /* audit_panic has been called */ - aux = context->aux; - context->aux = aux->next; - - audit_log_format(ab, "auxitem=%d", aux->type); switch (aux->type) { - case AUDIT_AUX_IPCPERM: { + case AUDIT_IPC: { struct audit_aux_data_ipcctl *axi = (void *)aux; audit_log_format(ab, - " qbytes=%lx uid=%d gid=%d mode=%x", + " qbytes=%lx iuid=%d igid=%d mode=%x", axi->qbytes, axi->uid, axi->gid, axi->mode); } } audit_log_end(ab); + + context->aux = aux->next; kfree(aux); } for (i = 0; i < context->name_count; i++) { - ab = audit_log_start(context, AUDIT_KERNEL, 0); + ab = audit_log_start(context, AUDIT_PATH); if (!ab) continue; /* audit_panic has been called */ audit_log_format(ab, "item=%d", i); @@ -711,7 +713,7 @@ static void audit_log_exit(struct audit_context *context) } if (context->names[i].ino != (unsigned long)-1) audit_log_format(ab, " inode=%lu dev=%02x:%02x mode=%#o" - " uid=%d gid=%d rdev=%02x:%02x", + " ouid=%d ogid=%d rdev=%02x:%02x", context->names[i].ino, MAJOR(context->names[i].dev), MINOR(context->names[i].dev), @@ -1008,10 +1010,16 @@ int audit_get_stamp(struct audit_context *ctx, int audit_set_loginuid(struct task_struct *task, uid_t loginuid) { if (task->audit_context) { - audit_log_type(NULL, AUDIT_LOGIN, 0, - "login pid=%d uid=%u old loginuid=%u new loginuid=%u", - task->pid, task->uid, task->audit_context->loginuid, - loginuid); + struct audit_buffer *ab; + + ab = audit_log_start(NULL, AUDIT_LOGIN); + if (ab) { + audit_log_format(ab, "login pid=%d uid=%u " + "old loginuid=%u new loginuid=%u", + task->pid, task->uid, + task->audit_context->loginuid, loginuid); + audit_log_end(ab); + } task->audit_context->loginuid = loginuid; } return 0; @@ -1039,7 +1047,7 @@ int audit_ipc_perms(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode) ax->gid = gid; ax->mode = mode; - ax->d.type = AUDIT_AUX_IPCPERM; + ax->d.type = AUDIT_IPC; ax->d.next = context->aux; context->aux = (void *)ax; return 0; -- cgit v1.1 From 23f32d18aa589e228c5a9e12e0d0c67c9b5bcdce Mon Sep 17 00:00:00 2001 From: Steve Grubb Date: Fri, 13 May 2005 18:35:15 +0100 Subject: AUDIT: Fix some spelling errors I'm going through the kernel code and have a patch that corrects several spelling errors in comments. From: Steve Grubb Signed-off-by: David Woodhouse --- kernel/auditsc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'kernel/auditsc.c') diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 1b7c91f..773d28a 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -444,7 +444,7 @@ static enum audit_state audit_filter_task(struct task_struct *tsk) /* At syscall entry and exit time, this filter is called if the * audit_state is not low enough that auditing cannot take place, but is - * also not high enough that we already know we have to write and audit + * also not high enough that we already know we have to write an audit * record (i.e., the state is AUDIT_SETUP_CONTEXT or AUDIT_BUILD_CONTEXT). */ static enum audit_state audit_filter_syscall(struct task_struct *tsk, @@ -750,7 +750,7 @@ void audit_free(struct task_struct *tsk) /* Compute a serial number for the audit record. Audit records are * written to user-space as soon as they are generated, so a complete * audit record may be written in several pieces. The timestamp of the - * record and this serial number are used by the user-space daemon to + * record and this serial number are used by the user-space tools to * determine which pieces belong to the same audit record. The * (timestamp,serial) tuple is unique for each syscall and is live from * syscall entry to syscall exit. -- cgit v1.1 From 3ec3b2fba526ead2fa3f3d7c91924f39a0733749 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Tue, 17 May 2005 12:08:48 +0100 Subject: AUDIT: Capture sys_socketcall arguments and sockaddrs Signed-off-by: David Woodhouse --- kernel/auditsc.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 71 insertions(+), 2 deletions(-) (limited to 'kernel/auditsc.c') diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 773d28a..818778d 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -34,7 +34,7 @@ #include #include #include - +#include #include #include #include @@ -112,6 +112,18 @@ struct audit_aux_data_ipcctl { mode_t mode; }; +struct audit_aux_data_socketcall { + struct audit_aux_data d; + int nargs; + unsigned long args[0]; +}; + +struct audit_aux_data_sockaddr { + struct audit_aux_data d; + int len; + char a[0]; +}; + /* The per-task audit context. */ struct audit_context { @@ -694,7 +706,22 @@ static void audit_log_exit(struct audit_context *context) audit_log_format(ab, " qbytes=%lx iuid=%d igid=%d mode=%x", axi->qbytes, axi->uid, axi->gid, axi->mode); - } + break; } + + case AUDIT_SOCKETCALL: { + int i; + struct audit_aux_data_socketcall *axs = (void *)aux; + audit_log_format(ab, "nargs=%d", axs->nargs); + for (i=0; inargs; i++) + audit_log_format(ab, " a%d=%lx", i, axs->args[i]); + break; } + + case AUDIT_SOCKADDR: { + struct audit_aux_data_sockaddr *axs = (void *)aux; + + audit_log_format(ab, "saddr="); + audit_log_hex(ab, axs->a, axs->len); + break; } } audit_log_end(ab); @@ -1053,6 +1080,48 @@ int audit_ipc_perms(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode) return 0; } +int audit_socketcall(int nargs, unsigned long *args) +{ + struct audit_aux_data_socketcall *ax; + struct audit_context *context = current->audit_context; + + if (likely(!context)) + return 0; + + ax = kmalloc(sizeof(*ax) + nargs * sizeof(unsigned long), GFP_KERNEL); + if (!ax) + return -ENOMEM; + + ax->nargs = nargs; + memcpy(ax->args, args, nargs * sizeof(unsigned long)); + + ax->d.type = AUDIT_SOCKETCALL; + ax->d.next = context->aux; + context->aux = (void *)ax; + return 0; +} + +int audit_sockaddr(int len, void *a) +{ + struct audit_aux_data_sockaddr *ax; + struct audit_context *context = current->audit_context; + + if (likely(!context)) + return 0; + + ax = kmalloc(sizeof(*ax) + len, GFP_KERNEL); + if (!ax) + return -ENOMEM; + + ax->len = len; + memcpy(ax->a, a, len); + + ax->d.type = AUDIT_SOCKADDR; + ax->d.next = context->aux; + context->aux = (void *)ax; + return 0; +} + void audit_signal_info(int sig, struct task_struct *t) { extern pid_t audit_sig_pid; -- cgit v1.1 From 7ca0026495dbb644b4e32ede76be44072cb2bc7a Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Thu, 19 May 2005 11:23:13 +0100 Subject: AUDIT: Quis Custodiet Ipsos Custodes? Nobody does. Really, it gets very silly if auditd is recording its own actions. Signed-off-by: David Woodhouse --- kernel/auditsc.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'kernel/auditsc.c') diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 818778d..78d7a13 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -169,6 +169,8 @@ struct audit_entry { struct audit_rule rule; }; +extern int audit_pid; + /* Check to see if two rules are identical. It is called from * audit_del_rule during AUDIT_DEL. */ static int audit_compare_rule(struct audit_rule *a, struct audit_rule *b) @@ -768,7 +770,7 @@ void audit_free(struct task_struct *tsk) /* Check for system calls that do not go through the exit * function (e.g., exit_group), then free context block. */ - if (context->in_syscall && context->auditable) + if (context->in_syscall && context->auditable && context->pid != audit_pid) audit_log_exit(context); audit_free_context(context); @@ -903,7 +905,7 @@ void audit_syscall_exit(struct task_struct *tsk, int valid, long return_code) if (likely(!context)) return; - if (context->in_syscall && context->auditable) + if (context->in_syscall && context->auditable && context->pid != audit_pid) audit_log_exit(context); context->in_syscall = 0; @@ -1126,7 +1128,6 @@ void audit_signal_info(int sig, struct task_struct *t) { extern pid_t audit_sig_pid; extern uid_t audit_sig_uid; - extern int audit_pid; if (unlikely(audit_pid && t->pid == audit_pid)) { if (sig == SIGTERM || sig == SIGHUP) { -- cgit v1.1 From 011161051bbc25f7f8b7df059dbd934c534443f0 Mon Sep 17 00:00:00 2001 From: Stephen Smalley Date: Sat, 21 May 2005 00:15:52 +0100 Subject: AUDIT: Avoid sleeping function in SElinux AVC audit. This patch changes the SELinux AVC to defer logging of paths to the audit framework upon syscall exit, by saving a reference to the (dentry,vfsmount) pair in an auxiliary audit item on the current audit context for processing by audit_log_exit. Signed-off-by: Stephen Smalley Signed-off-by: David Woodhouse --- kernel/auditsc.c | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) (limited to 'kernel/auditsc.c') diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 78d7a13..8dc5b27 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -124,6 +125,11 @@ struct audit_aux_data_sockaddr { char a[0]; }; +struct audit_aux_data_path { + struct audit_aux_data d; + struct dentry *dentry; + struct vfsmount *mnt; +}; /* The per-task audit context. */ struct audit_context { @@ -553,6 +559,11 @@ static inline void audit_free_aux(struct audit_context *context) struct audit_aux_data *aux; while ((aux = context->aux)) { + if (aux->type == AUDIT_AVC_PATH) { + struct audit_aux_data_path *axi = (void *)aux; + dput(axi->dentry); + mntput(axi->mnt); + } context->aux = aux->next; kfree(aux); } @@ -724,6 +735,14 @@ static void audit_log_exit(struct audit_context *context) audit_log_format(ab, "saddr="); audit_log_hex(ab, axs->a, axs->len); break; } + + case AUDIT_AVC_PATH: { + struct audit_aux_data_path *axi = (void *)aux; + audit_log_d_path(ab, "path=", axi->dentry, axi->mnt); + dput(axi->dentry); + mntput(axi->mnt); + break; } + } audit_log_end(ab); @@ -1124,6 +1143,27 @@ int audit_sockaddr(int len, void *a) return 0; } +int audit_avc_path(struct dentry *dentry, struct vfsmount *mnt) +{ + struct audit_aux_data_path *ax; + struct audit_context *context = current->audit_context; + + if (likely(!context)) + return 0; + + ax = kmalloc(sizeof(*ax), GFP_ATOMIC); + if (!ax) + return -ENOMEM; + + ax->dentry = dget(dentry); + ax->mnt = mntget(mnt); + + ax->d.type = AUDIT_AVC_PATH; + ax->d.next = context->aux; + context->aux = (void *)ax; + return 0; +} + void audit_signal_info(int sig, struct task_struct *t) { extern pid_t audit_sig_pid; -- cgit v1.1 From 326e9c8ba6a149f47e020719b23b24a14ba740d6 Mon Sep 17 00:00:00 2001 From: Steve Grubb Date: Sat, 21 May 2005 00:22:31 +0100 Subject: AUDIT: Fix inconsistent use of loginuid vs. auid, signed vs. unsigned The attached patch changes all occurrences of loginuid to auid. It also changes everything to %u that is an unsigned type. Signed-off-by: Steve Grubb Signed-off-by: David Woodhouse --- kernel/auditsc.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'kernel/auditsc.c') diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 8dc5b27..4193811 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -688,9 +688,9 @@ static void audit_log_exit(struct audit_context *context) context->return_code); audit_log_format(ab, " a0=%lx a1=%lx a2=%lx a3=%lx items=%d" - " pid=%d loginuid=%d uid=%d gid=%d" - " euid=%d suid=%d fsuid=%d" - " egid=%d sgid=%d fsgid=%d", + " pid=%d auid=%u uid=%u gid=%u" + " euid=%u suid=%u fsuid=%u" + " egid=%u sgid=%u fsgid=%u", context->argv[0], context->argv[1], context->argv[2], @@ -717,7 +717,7 @@ static void audit_log_exit(struct audit_context *context) case AUDIT_IPC: { struct audit_aux_data_ipcctl *axi = (void *)aux; audit_log_format(ab, - " qbytes=%lx iuid=%d igid=%d mode=%x", + " qbytes=%lx iuid=%u igid=%u mode=%x", axi->qbytes, axi->uid, axi->gid, axi->mode); break; } @@ -761,7 +761,7 @@ static void audit_log_exit(struct audit_context *context) } if (context->names[i].ino != (unsigned long)-1) audit_log_format(ab, " inode=%lu dev=%02x:%02x mode=%#o" - " ouid=%d ogid=%d rdev=%02x:%02x", + " ouid=%u ogid=%u rdev=%02x:%02x", context->names[i].ino, MAJOR(context->names[i].dev), MINOR(context->names[i].dev), @@ -1063,7 +1063,7 @@ int audit_set_loginuid(struct task_struct *task, uid_t loginuid) ab = audit_log_start(NULL, AUDIT_LOGIN); if (ab) { audit_log_format(ab, "login pid=%d uid=%u " - "old loginuid=%u new loginuid=%u", + "old auid=%u new auid=%u", task->pid, task->uid, task->audit_context->loginuid, loginuid); audit_log_end(ab); -- cgit v1.1 From bfb4496e7239c9132d732a65cdcf3d6a7431ad1a Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Sat, 21 May 2005 21:08:09 +0100 Subject: AUDIT: Assign serial number to non-syscall messages Move audit_serial() into audit.c and use it to generate serial numbers on messages even when there is no audit context from syscall auditing. This allows us to disambiguate audit records when more than one is generated in the same millisecond. Based on a patch by Steve Grubb after he observed the problem. Signed-off-by: David Woodhouse --- kernel/auditsc.c | 46 ++++++---------------------------------------- 1 file changed, 6 insertions(+), 40 deletions(-) (limited to 'kernel/auditsc.c') diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 4193811..74c2ae8 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -795,36 +795,6 @@ void audit_free(struct task_struct *tsk) audit_free_context(context); } -/* Compute a serial number for the audit record. Audit records are - * written to user-space as soon as they are generated, so a complete - * audit record may be written in several pieces. The timestamp of the - * record and this serial number are used by the user-space tools to - * determine which pieces belong to the same audit record. The - * (timestamp,serial) tuple is unique for each syscall and is live from - * syscall entry to syscall exit. - * - * Atomic values are only guaranteed to be 24-bit, so we count down. - * - * NOTE: Another possibility is to store the formatted records off the - * audit context (for those records that have a context), and emit them - * all at syscall exit. However, this could delay the reporting of - * significant errors until syscall exit (or never, if the system - * halts). */ -static inline unsigned int audit_serial(void) -{ - static atomic_t serial = ATOMIC_INIT(0xffffff); - unsigned int a, b; - - do { - a = atomic_read(&serial); - if (atomic_dec_and_test(&serial)) - atomic_set(&serial, 0xffffff); - b = atomic_read(&serial); - } while (b != a - 1); - - return 0xffffff - b; -} - /* Fill in audit context at syscall entry. This only happens if the * audit context was created when the task was created and the state or * filters demand the audit context be built. If the state from the @@ -1042,17 +1012,13 @@ void audit_inode(const char *name, const struct inode *inode) context->names[idx].rdev = inode->i_rdev; } -int audit_get_stamp(struct audit_context *ctx, - struct timespec *t, unsigned int *serial) +void auditsc_get_stamp(struct audit_context *ctx, + struct timespec *t, unsigned int *serial) { - if (ctx) { - t->tv_sec = ctx->ctime.tv_sec; - t->tv_nsec = ctx->ctime.tv_nsec; - *serial = ctx->serial; - ctx->auditable = 1; - return 1; - } - return 0; + t->tv_sec = ctx->ctime.tv_sec; + t->tv_nsec = ctx->ctime.tv_nsec; + *serial = ctx->serial; + ctx->auditable = 1; } int audit_set_loginuid(struct task_struct *task, uid_t loginuid) -- cgit v1.1 From bccf6ae083318ea08094d6ab185fdf7c49906b3a Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Mon, 23 May 2005 21:35:28 +0100 Subject: AUDIT: Unify auid reporting, put arch before syscall number These changes make processing of audit logs easier. Based on a patch from Steve Grubb Signed-off-by: David Woodhouse --- kernel/auditsc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'kernel/auditsc.c') diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 74c2ae8..5fc4f52 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -307,7 +307,7 @@ int audit_receive_filter(int type, int pid, int uid, int seq, void *data, if (!err && (flags & AUDIT_AT_EXIT)) err = audit_add_rule(entry, &audit_extlist); audit_log(NULL, AUDIT_CONFIG_CHANGE, - "auid %u added an audit rule\n", loginuid); + "auid=%u added an audit rule\n", loginuid); break; case AUDIT_DEL: flags =((struct audit_rule *)data)->flags; @@ -318,7 +318,7 @@ int audit_receive_filter(int type, int pid, int uid, int seq, void *data, if (!err && (flags & AUDIT_AT_EXIT)) err = audit_del_rule(data, &audit_extlist); audit_log(NULL, AUDIT_CONFIG_CHANGE, - "auid %u removed an audit rule\n", loginuid); + "auid=%u removed an audit rule\n", loginuid); break; default: return -EINVAL; @@ -678,10 +678,10 @@ static void audit_log_exit(struct audit_context *context) ab = audit_log_start(context, AUDIT_SYSCALL); if (!ab) return; /* audit_panic has been called */ - audit_log_format(ab, "syscall=%d", context->major); + 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); - audit_log_format(ab, " arch=%x", context->arch); if (context->return_valid) audit_log_format(ab, " success=%s exit=%ld", (context->return_valid==AUDITSC_SUCCESS)?"yes":"no", -- cgit v1.1 From 99e45eeac867d51ff3395dcf3d7aedf5ac2812c8 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Mon, 23 May 2005 21:57:41 +0100 Subject: AUDIT: Escape comm when logging task info It comes from the user; it needs to be escaped. Signed-off-by: David Woodhouse --- kernel/auditsc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'kernel/auditsc.c') diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 5fc4f52..b45677e 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -650,7 +650,8 @@ static void audit_log_task_info(struct audit_buffer *ab) struct vm_area_struct *vma; get_task_comm(name, current); - audit_log_format(ab, " comm=%s", name); + audit_log_format(ab, " comm="); + audit_log_untrustedstring(ab, name); if (!mm) return; -- cgit v1.1 From 7551ced334ce6eb2a7a765309871e619f645add1 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Thu, 26 May 2005 12:04:57 +0100 Subject: AUDIT: Defer freeing aux items until audit_free_context() While they were all just simple blobs it made sense to just free them as we walked through and logged them. Now that there are pointers to other objects which need refcounting, we might as well revert to _only_ logging them in audit_log_exit(), and put the code to free them properly in only one place -- in audit_free_aux(). Signed-off-by: David Woodhouse ---------------------------------------------------------- --- kernel/auditsc.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'kernel/auditsc.c') diff --git a/kernel/auditsc.c b/kernel/auditsc.c index b45677e..7556c47 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -675,6 +675,7 @@ static void audit_log_exit(struct audit_context *context) { int i; struct audit_buffer *ab; + struct audit_aux_data *aux; ab = audit_log_start(context, AUDIT_SYSCALL); if (!ab) @@ -705,10 +706,8 @@ static void audit_log_exit(struct audit_context *context) context->egid, context->sgid, context->fsgid); audit_log_task_info(ab); audit_log_end(ab); - while (context->aux) { - struct audit_aux_data *aux; - aux = context->aux; + for (aux = context->aux; aux; aux = aux->next) { ab = audit_log_start(context, aux->type); if (!ab) @@ -740,15 +739,10 @@ static void audit_log_exit(struct audit_context *context) case AUDIT_AVC_PATH: { struct audit_aux_data_path *axi = (void *)aux; audit_log_d_path(ab, "path=", axi->dentry, axi->mnt); - dput(axi->dentry); - mntput(axi->mnt); break; } } audit_log_end(ab); - - context->aux = aux->next; - kfree(aux); } for (i = 0; i < context->name_count; i++) { -- cgit v1.1 From 8f37d47c9bf74cb48692691086b482e315d07f40 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Fri, 27 May 2005 12:17:28 +0100 Subject: AUDIT: Record working directory when syscall arguments are pathnames Signed-off-by: David Woodhouse --- kernel/auditsc.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'kernel/auditsc.c') diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 7556c47..e75f84e 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -145,6 +145,8 @@ struct audit_context { int auditable; /* 1 if record should be written */ int name_count; struct audit_names names[AUDIT_NAMES]; + struct dentry * pwd; + struct vfsmount * pwdmnt; struct audit_context *previous; /* For nested syscalls */ struct audit_aux_data *aux; @@ -552,6 +554,12 @@ static inline void audit_free_names(struct audit_context *context) if (context->names[i].name) __putname(context->names[i].name); context->name_count = 0; + if (context->pwd) + dput(context->pwd); + if (context->pwdmnt) + mntput(context->pwdmnt); + context->pwd = NULL; + context->pwdmnt = NULL; } static inline void audit_free_aux(struct audit_context *context) @@ -745,10 +753,18 @@ static void audit_log_exit(struct audit_context *context) audit_log_end(ab); } + if (context->pwd && context->pwdmnt) { + ab = audit_log_start(context, AUDIT_CWD); + if (ab) { + audit_log_d_path(ab, "cwd=", context->pwd, context->pwdmnt); + audit_log_end(ab); + } + } for (i = 0; i < context->name_count; i++) { ab = audit_log_start(context, AUDIT_PATH); if (!ab) continue; /* audit_panic has been called */ + audit_log_format(ab, "item=%d", i); if (context->names[i].name) { audit_log_format(ab, " name="); @@ -929,6 +945,13 @@ void audit_getname(const char *name) context->names[context->name_count].name = name; context->names[context->name_count].ino = (unsigned long)-1; ++context->name_count; + if (!context->pwd) { + read_lock(¤t->fs->lock); + context->pwd = dget(current->fs->pwd); + context->pwdmnt = mntget(current->fs->pwdmnt); + read_unlock(¤t->fs->lock); + } + } /* Intercept a putname request. Called from -- cgit v1.1