diff options
author | Stephen Smalley <sds@tycho.nsa.gov> | 2005-05-21 01:15:52 +0200 |
---|---|---|
committer | David Woodhouse <dwmw2@shinybook.infradead.org> | 2005-05-21 01:15:52 +0200 |
commit | 011161051bbc25f7f8b7df059dbd934c534443f0 (patch) | |
tree | f1ca3727e4130cacad86dfdae65e7533fcb67784 /kernel | |
parent | AUDIT: Honour audit_backlog_limit again. (diff) | |
download | linux-011161051bbc25f7f8b7df059dbd934c534443f0.tar.xz linux-011161051bbc25f7f8b7df059dbd934c534443f0.zip |
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 <sds@tycho.nsa.gov>
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/auditsc.c | 40 |
1 files changed, 40 insertions, 0 deletions
diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 78d7a13fc86f..8dc5b2767145 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -34,6 +34,7 @@ #include <asm/types.h> #include <linux/mm.h> #include <linux/module.h> +#include <linux/mount.h> #include <linux/socket.h> #include <linux/audit.h> #include <linux/personality.h> @@ -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; |