[PATCH] SELinux: fix deadlock on dcache lock
authorStephen Smalley <sds@tycho.nsa.gov>
Mon, 18 Apr 2005 17:47:35 +0000 (10:47 -0700)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Mon, 18 Apr 2005 17:47:35 +0000 (10:47 -0700)
This fixes a deadlock on the dcache lock detected during testing at IBM
by moving the logging of the current executable information from the
SELinux avc_audit function to audit_log_exit (via an audit_log_task_info
helper) for processing upon syscall exit.

For consistency, the patch also removes the logging of other
task-related information from avc_audit, deferring handling to
audit_log_exit instead.

This allows simplification of the avc_audit code, allows the exe
information to be obtained more reliably, always includes the comm
information (useful for scripts), and avoids including bogus task
information for checks performed from irq or softirq.

Signed-off-by: Stephen Smalley <sds@tycho.nsa.gov>
Signed-off-by: James Morris <jmorris@redhat.com>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
kernel/auditsc.c
security/selinux/avc.c

index 8c454852d6a52a8cb9e37f75b90e68ca61d7cd28..6f1931381bc9eae1ff454c943036c5b077c4a8a6 100644 (file)
@@ -610,6 +610,33 @@ static inline void audit_free_context(struct audit_context *context)
                printk(KERN_ERR "audit: freed %d contexts\n", count);
 }
 
+static void audit_log_task_info(struct audit_buffer *ab)
+{
+       char name[sizeof(current->comm)];
+       struct mm_struct *mm = current->mm;
+       struct vm_area_struct *vma;
+
+       get_task_comm(name, current);
+       audit_log_format(ab, " comm=%s", name);
+
+       if (!mm)
+               return;
+
+       down_read(&mm->mmap_sem);
+       vma = mm->mmap;
+       while (vma) {
+               if ((vma->vm_flags & VM_EXECUTABLE) &&
+                   vma->vm_file) {
+                       audit_log_d_path(ab, "exe=",
+                                        vma->vm_file->f_dentry,
+                                        vma->vm_file->f_vfsmnt);
+                       break;
+               }
+               vma = vma->vm_next;
+       }
+       up_read(&mm->mmap_sem);
+}
+
 static void audit_log_exit(struct audit_context *context)
 {
        int i;
@@ -639,6 +666,7 @@ static void audit_log_exit(struct audit_context *context)
                  context->gid,
                  context->euid, context->suid, context->fsuid,
                  context->egid, context->sgid, context->fsgid);
+       audit_log_task_info(ab);
        audit_log_end(ab);
        while (context->aux) {
                struct audit_aux_data *aux;
index fe6285e5c68f8989710e5a498637f8e494668ef1..85a6f66a873f5194bc2f32908fb18a9ada1df2de 100644 (file)
@@ -532,7 +532,6 @@ void avc_audit(u32 ssid, u32 tsid,
                u16 tclass, u32 requested,
                struct av_decision *avd, int result, struct avc_audit_data *a)
 {
-       struct task_struct *tsk = current;
        struct inode *inode = NULL;
        u32 denied, audited;
        struct audit_buffer *ab;
@@ -556,39 +555,6 @@ void avc_audit(u32 ssid, u32 tsid,
        audit_log_format(ab, "avc:  %s ", denied ? "denied" : "granted");
        avc_dump_av(ab, tclass,audited);
        audit_log_format(ab, " for ");
-       if (a && a->tsk)
-               tsk = a->tsk;
-       if (tsk && tsk->pid) {
-               struct mm_struct *mm;
-               struct vm_area_struct *vma;
-               audit_log_format(ab, " pid=%d", tsk->pid);
-               if (tsk == current)
-                       mm = current->mm;
-               else
-                       mm = get_task_mm(tsk);
-               if (mm) {
-                       if (down_read_trylock(&mm->mmap_sem)) {
-                               vma = mm->mmap;
-                               while (vma) {
-                                       if ((vma->vm_flags & VM_EXECUTABLE) &&
-                                           vma->vm_file) {
-                                               audit_log_d_path(ab, "exe=",
-                                                       vma->vm_file->f_dentry,
-                                                       vma->vm_file->f_vfsmnt);
-                                               break;
-                                       }
-                                       vma = vma->vm_next;
-                               }
-                               up_read(&mm->mmap_sem);
-                       } else {
-                               audit_log_format(ab, " comm=%s", tsk->comm);
-                       }
-                       if (tsk != current)
-                               mmput(mm);
-               } else {
-                       audit_log_format(ab, " comm=%s", tsk->comm);
-               }
-       }
        if (a) {
                switch (a->type) {
                case AVC_AUDIT_DATA_IPC: