[PATCH] get rid of loginuid races
authorAl Viro <viro@zeniv.linux.org.uk>
Thu, 10 Jan 2008 09:53:18 +0000 (04:53 -0500)
committerAl Viro <viro@zeniv.linux.org.uk>
Fri, 1 Feb 2008 19:05:28 +0000 (14:05 -0500)
Keeping loginuid in audit_context is racy and results in messier
code.  Taken to task_struct, out of the way of ->audit_context
changes.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
include/linux/audit.h
include/linux/init_task.h
include/linux/sched.h
kernel/auditsc.c

index f63117f..d7c6a12 100644 (file)
@@ -409,7 +409,7 @@ extern unsigned int audit_serial(void);
 extern void auditsc_get_stamp(struct audit_context *ctx,
                              struct timespec *t, unsigned int *serial);
 extern int  audit_set_loginuid(struct task_struct *task, uid_t loginuid);
-extern uid_t audit_get_loginuid(struct task_struct *task);
+#define audit_get_loginuid(t) ((t)->loginuid)
 extern void audit_log_task_context(struct audit_buffer *ab);
 extern int __audit_ipc_obj(struct kern_ipc_perm *ipcp);
 extern int __audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode);
index e6b3f70..ea3e9ef 100644 (file)
@@ -114,6 +114,12 @@ extern struct group_info init_groups;
        .pid = &init_struct_pid,                                \
 }
 
+#ifdef CONFIG_AUDITSYSCALL
+#define INIT_IDS \
+       .loginuid = -1,
+#else
+#define INIT_IDS
+#endif
 /*
  *  INIT_TASK is used to set up the first task table, touch at
  * your own risk!. Base=0, limit=0x1fffff (=2MB)
@@ -173,6 +179,7 @@ extern struct group_info init_groups;
                [PIDTYPE_SID]  = INIT_PID_LINK(PIDTYPE_SID),            \
        },                                                              \
        .dirties = INIT_PROP_LOCAL_SINGLE(dirties),                     \
+       INIT_IDS                                                        \
        INIT_TRACE_IRQFLAGS                                             \
        INIT_LOCKDEP                                                    \
 }
index 6c33357..5e27303 100644 (file)
@@ -1139,6 +1139,9 @@ struct task_struct {
        void *security;
 #endif
        struct audit_context *audit_context;
+#ifdef CONFIG_AUDITSYSCALL
+       uid_t loginuid;
+#endif
        seccomp_t seccomp;
 
 /* Thread group tracking */
index bd4e0a2..c95173a 100644 (file)
@@ -192,7 +192,6 @@ struct audit_context {
        enum audit_state    state;
        unsigned int        serial;     /* serial number for record */
        struct timespec     ctime;      /* time of syscall entry */
-       uid_t               loginuid;   /* login uid (identity) */
        int                 major;      /* syscall number */
        unsigned long       argv[4];    /* syscall arguments */
        int                 return_valid; /* return code is valid */
@@ -506,7 +505,7 @@ static int audit_filter_rules(struct task_struct *tsk,
                case AUDIT_LOGINUID:
                        result = 0;
                        if (ctx)
-                               result = audit_comparator(ctx->loginuid, f->op, f->val);
+                               result = audit_comparator(tsk->loginuid, f->op, f->val);
                        break;
                case AUDIT_SUBJ_USER:
                case AUDIT_SUBJ_ROLE:
@@ -783,11 +782,8 @@ static inline void audit_free_aux(struct audit_context *context)
 static inline void audit_zero_context(struct audit_context *context,
                                      enum audit_state state)
 {
-       uid_t loginuid = context->loginuid;
-
        memset(context, 0, sizeof(*context));
        context->state      = state;
-       context->loginuid   = loginuid;
 }
 
 static inline struct audit_context *audit_alloc_context(enum audit_state state)
@@ -826,11 +822,6 @@ int audit_alloc(struct task_struct *tsk)
                return -ENOMEM;
        }
 
-                               /* Preserve login uid */
-       context->loginuid = -1;
-       if (current->audit_context)
-               context->loginuid = current->audit_context->loginuid;
-
        tsk->audit_context  = context;
        set_tsk_thread_flag(tsk, TIF_SYSCALL_AUDIT);
        return 0;
@@ -1047,7 +1038,7 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
                  context->name_count,
                  context->ppid,
                  context->pid,
-                 context->loginuid,
+                 tsk->loginuid,
                  context->uid,
                  context->gid,
                  context->euid, context->suid, context->fsuid,
@@ -1779,40 +1770,23 @@ int audit_set_loginuid(struct task_struct *task, uid_t loginuid)
 {
        struct audit_context *context = task->audit_context;
 
-       if (context) {
-               /* Only log if audit is enabled */
-               if (context->in_syscall) {
-                       struct audit_buffer *ab;
-
-                       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",
-                                       task->pid, task->uid,
-                                       context->loginuid, loginuid);
-                               audit_log_end(ab);
-                       }
+       if (context && context->in_syscall) {
+               struct audit_buffer *ab;
+
+               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",
+                               task->pid, task->uid,
+                               task->loginuid, loginuid);
+                       audit_log_end(ab);
                }
-               context->loginuid = loginuid;
        }
+       task->loginuid = loginuid;
        return 0;
 }
 
 /**
- * audit_get_loginuid - get the loginuid for an audit_context
- * @ctx: the audit_context
- *
- * Returns the context's loginuid or -1 if @ctx is NULL.
- */
-uid_t audit_get_loginuid(struct task_struct *task)
-{
-       struct audit_context *ctx = task->audit_context;
-       return ctx ? ctx->loginuid : -1;
-}
-
-EXPORT_SYMBOL(audit_get_loginuid);
-
-/**
  * __audit_mq_open - record audit data for a POSIX MQ open
  * @oflag: open flag
  * @mode: mode bits
@@ -2217,8 +2191,8 @@ int __audit_signal_info(int sig, struct task_struct *t)
        if (audit_pid && t->tgid == audit_pid) {
                if (sig == SIGTERM || sig == SIGHUP || sig == SIGUSR1) {
                        audit_sig_pid = tsk->pid;
-                       if (ctx)
-                               audit_sig_uid = ctx->loginuid;
+                       if (tsk->loginuid != -1)
+                               audit_sig_uid = tsk->loginuid;
                        else
                                audit_sig_uid = tsk->uid;
                        selinux_get_task_sid(tsk, &audit_sig_sid);