[AUDIT] do not panic on exclude messages in audit_log_pid_context()
[safe/jmp/linux-2.6] / kernel / auditsc.c
index c95173a..aaaca8a 100644 (file)
@@ -176,7 +176,11 @@ struct audit_aux_data_fd_pair {
 struct audit_aux_data_pids {
        struct audit_aux_data   d;
        pid_t                   target_pid[AUDIT_AUX_PIDS];
+       uid_t                   target_auid[AUDIT_AUX_PIDS];
+       uid_t                   target_uid[AUDIT_AUX_PIDS];
+       unsigned int            target_sessionid[AUDIT_AUX_PIDS];
        u32                     target_sid[AUDIT_AUX_PIDS];
+       char                    target_comm[AUDIT_AUX_PIDS][TASK_COMM_LEN];
        int                     pid_count;
 };
 
@@ -214,7 +218,11 @@ struct audit_context {
        int                 arch;
 
        pid_t               target_pid;
+       uid_t               target_auid;
+       uid_t               target_uid;
+       unsigned int        target_sessionid;
        u32                 target_sid;
+       char                target_comm[TASK_COMM_LEN];
 
        struct audit_tree_refs *trees, *first_trees;
        int tree_count;
@@ -701,7 +709,24 @@ static inline struct audit_context *audit_get_context(struct task_struct *tsk,
        if (likely(!context))
                return NULL;
        context->return_valid = return_valid;
-       context->return_code  = return_code;
+
+       /*
+        * we need to fix up the return code in the audit logs if the actual
+        * return codes are later going to be fixed up by the arch specific
+        * signal handlers
+        *
+        * This is actually a test for:
+        * (rc == ERESTARTSYS ) || (rc == ERESTARTNOINTR) ||
+        * (rc == ERESTARTNOHAND) || (rc == ERESTART_RESTARTBLOCK)
+        *
+        * but is faster than a bunch of ||
+        */
+       if (unlikely(return_code <= -ERESTARTSYS) &&
+           (return_code >= -ERESTART_RESTARTBLOCK) &&
+           (return_code != -ENOIOCTLCMD))
+               context->return_code = -EINTR;
+       else
+               context->return_code  = return_code;
 
        if (context->in_syscall && !context->dummy && !context->auditable) {
                enum audit_state state;
@@ -913,7 +938,8 @@ static void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk
 }
 
 static int audit_log_pid_context(struct audit_context *context, pid_t pid,
-                                u32 sid)
+                                uid_t auid, uid_t uid, unsigned int sessionid,
+                                u32 sid, char *comm)
 {
        struct audit_buffer *ab;
        char *s = NULL;
@@ -922,13 +948,17 @@ static int audit_log_pid_context(struct audit_context *context, pid_t pid,
 
        ab = audit_log_start(context, GFP_KERNEL, AUDIT_OBJ_PID);
        if (!ab)
-               return 1;
+               return rc;
 
+       audit_log_format(ab, "opid=%d oauid=%d ouid=%d oses=%d", pid, auid,
+                        uid, sessionid);
        if (selinux_sid_to_string(sid, &s, &len)) {
-               audit_log_format(ab, "opid=%d obj=(none)", pid);
+               audit_log_format(ab, " obj=(none)");
                rc = 1;
        } else
-               audit_log_format(ab, "opid=%d  obj=%s", pid, s);
+               audit_log_format(ab, " obj=%s", s);
+       audit_log_format(ab, " ocomm=");
+       audit_log_untrustedstring(ab, comm);
        audit_log_end(ab);
        kfree(s);
 
@@ -1030,7 +1060,7 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
                  " a0=%lx a1=%lx a2=%lx a3=%lx items=%d"
                  " ppid=%d pid=%d auid=%u uid=%u gid=%u"
                  " euid=%u suid=%u fsuid=%u"
-                 " egid=%u sgid=%u fsgid=%u tty=%s",
+                 " egid=%u sgid=%u fsgid=%u tty=%s ses=%u",
                  context->argv[0],
                  context->argv[1],
                  context->argv[2],
@@ -1042,7 +1072,8 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
                  context->uid,
                  context->gid,
                  context->euid, context->suid, context->fsuid,
-                 context->egid, context->sgid, context->fsgid, tty);
+                 context->egid, context->sgid, context->fsgid, tty,
+                 tsk->sessionid);
 
        mutex_unlock(&tty_mutex);
 
@@ -1159,13 +1190,19 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
 
                for (i = 0; i < axs->pid_count; i++)
                        if (audit_log_pid_context(context, axs->target_pid[i],
-                                                 axs->target_sid[i]))
+                                                 axs->target_auid[i],
+                                                 axs->target_uid[i],
+                                                 axs->target_sessionid[i],
+                                                 axs->target_sid[i],
+                                                 axs->target_comm[i]))
                                call_panic = 1;
        }
 
        if (context->target_pid &&
            audit_log_pid_context(context, context->target_pid,
-                                 context->target_sid))
+                                 context->target_auid, context->target_uid,
+                                 context->target_sessionid,
+                                 context->target_sid, context->target_comm))
                        call_panic = 1;
 
        if (context->pwd && context->pwdmnt) {
@@ -1233,6 +1270,11 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
 
                audit_log_end(ab);
        }
+
+       /* Send end of event record to help user space know we are finished */
+       ab = audit_log_start(context, GFP_KERNEL, AUDIT_EOE);
+       if (ab)
+               audit_log_end(ab);
        if (call_panic)
                audit_panic("error converting sid to string");
 }
@@ -1757,6 +1799,9 @@ void auditsc_get_stamp(struct audit_context *ctx,
        ctx->auditable = 1;
 }
 
+/* global counter which is incremented every time something logs in */
+static atomic_t session_id = ATOMIC_INIT(0);
+
 /**
  * audit_set_loginuid - set a task's audit_context loginuid
  * @task: task whose audit context is being modified
@@ -1768,6 +1813,7 @@ void auditsc_get_stamp(struct audit_context *ctx,
  */
 int audit_set_loginuid(struct task_struct *task, uid_t loginuid)
 {
+       unsigned int sessionid = atomic_inc_return(&session_id);
        struct audit_context *context = task->audit_context;
 
        if (context && context->in_syscall) {
@@ -1776,12 +1822,15 @@ int audit_set_loginuid(struct task_struct *task, uid_t loginuid)
                ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_LOGIN);
                if (ab) {
                        audit_log_format(ab, "login pid=%d uid=%u "
-                               "old auid=%u new auid=%u",
+                               "old auid=%u new auid=%u"
+                               " old ses=%u new ses=%u",
                                task->pid, task->uid,
-                               task->loginuid, loginuid);
+                               task->loginuid, loginuid,
+                               task->sessionid, sessionid);
                        audit_log_end(ab);
                }
        }
+       task->sessionid = sessionid;
        task->loginuid = loginuid;
        return 0;
 }
@@ -2168,7 +2217,11 @@ void __audit_ptrace(struct task_struct *t)
        struct audit_context *context = current->audit_context;
 
        context->target_pid = t->pid;
+       context->target_auid = audit_get_loginuid(t);
+       context->target_uid = t->uid;
+       context->target_sessionid = audit_get_sessionid(t);
        selinux_get_task_sid(t, &context->target_sid);
+       memcpy(context->target_comm, t->comm, TASK_COMM_LEN);
 }
 
 /**
@@ -2205,7 +2258,11 @@ int __audit_signal_info(int sig, struct task_struct *t)
         * in audit_context */
        if (!ctx->target_pid) {
                ctx->target_pid = t->tgid;
+               ctx->target_auid = audit_get_loginuid(t);
+               ctx->target_uid = t->uid;
+               ctx->target_sessionid = audit_get_sessionid(t);
                selinux_get_task_sid(t, &ctx->target_sid);
+               memcpy(ctx->target_comm, t->comm, TASK_COMM_LEN);
                return 0;
        }
 
@@ -2222,7 +2279,11 @@ int __audit_signal_info(int sig, struct task_struct *t)
        BUG_ON(axp->pid_count >= AUDIT_AUX_PIDS);
 
        axp->target_pid[axp->pid_count] = t->tgid;
+       axp->target_auid[axp->pid_count] = audit_get_loginuid(t);
+       axp->target_uid[axp->pid_count] = t->uid;
+       axp->target_sessionid[axp->pid_count] = audit_get_sessionid(t);
        selinux_get_task_sid(t, &axp->target_sid[axp->pid_count]);
+       memcpy(axp->target_comm[axp->pid_count], t->comm, TASK_COMM_LEN);
        axp->pid_count++;
 
        return 0;
@@ -2239,6 +2300,8 @@ void audit_core_dumps(long signr)
 {
        struct audit_buffer *ab;
        u32 sid;
+       uid_t auid = audit_get_loginuid(current);
+       unsigned int sessionid = audit_get_sessionid(current);
 
        if (!audit_enabled)
                return;
@@ -2247,9 +2310,8 @@ void audit_core_dumps(long signr)
                return;
 
        ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_ANOM_ABEND);
-       audit_log_format(ab, "auid=%u uid=%u gid=%u",
-                       audit_get_loginuid(current),
-                       current->uid, current->gid);
+       audit_log_format(ab, "auid=%u uid=%u gid=%u ses=%u",
+                       auid, current->uid, current->gid, sessionid);
        selinux_get_task_sid(current, &sid);
        if (sid) {
                char *ctx = NULL;