aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2008-01-10 04:53:18 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2008-02-01 14:05:28 -0500
commitbfef93a5d1fb5654fe2025276c55e202d10b5255 (patch)
tree573d8153c5d5216b0c4007b652286eeddd3c0987
parent0c11b9428f619ab377c92eff2f160a834a6585dd (diff)
[PATCH] get rid of loginuid races
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>
-rw-r--r--include/linux/audit.h2
-rw-r--r--include/linux/init_task.h7
-rw-r--r--include/linux/sched.h3
-rw-r--r--kernel/auditsc.c56
4 files changed, 26 insertions, 42 deletions
diff --git a/include/linux/audit.h b/include/linux/audit.h
index f63117fab30..d7c6a12f4d1 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -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);
diff --git a/include/linux/init_task.h b/include/linux/init_task.h
index e6b3f708067..ea3e9efd739 100644
--- a/include/linux/init_task.h
+++ b/include/linux/init_task.h
@@ -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 \
}
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 6c333579d9d..5e273038908 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -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 */
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index bd4e0a2443f..c95173a194b 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -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);