mirror of https://gitee.com/openkylin/linux.git
[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>
This commit is contained in:
parent
0c11b9428f
commit
bfef93a5d1
|
@ -409,7 +409,7 @@ extern unsigned int audit_serial(void);
|
||||||
extern void auditsc_get_stamp(struct audit_context *ctx,
|
extern void auditsc_get_stamp(struct audit_context *ctx,
|
||||||
struct timespec *t, unsigned int *serial);
|
struct timespec *t, unsigned int *serial);
|
||||||
extern int audit_set_loginuid(struct task_struct *task, uid_t loginuid);
|
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 void audit_log_task_context(struct audit_buffer *ab);
|
||||||
extern int __audit_ipc_obj(struct kern_ipc_perm *ipcp);
|
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);
|
extern int __audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode);
|
||||||
|
|
|
@ -114,6 +114,12 @@ extern struct group_info init_groups;
|
||||||
.pid = &init_struct_pid, \
|
.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
|
* INIT_TASK is used to set up the first task table, touch at
|
||||||
* your own risk!. Base=0, limit=0x1fffff (=2MB)
|
* 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), \
|
[PIDTYPE_SID] = INIT_PID_LINK(PIDTYPE_SID), \
|
||||||
}, \
|
}, \
|
||||||
.dirties = INIT_PROP_LOCAL_SINGLE(dirties), \
|
.dirties = INIT_PROP_LOCAL_SINGLE(dirties), \
|
||||||
|
INIT_IDS \
|
||||||
INIT_TRACE_IRQFLAGS \
|
INIT_TRACE_IRQFLAGS \
|
||||||
INIT_LOCKDEP \
|
INIT_LOCKDEP \
|
||||||
}
|
}
|
||||||
|
|
|
@ -1139,6 +1139,9 @@ struct task_struct {
|
||||||
void *security;
|
void *security;
|
||||||
#endif
|
#endif
|
||||||
struct audit_context *audit_context;
|
struct audit_context *audit_context;
|
||||||
|
#ifdef CONFIG_AUDITSYSCALL
|
||||||
|
uid_t loginuid;
|
||||||
|
#endif
|
||||||
seccomp_t seccomp;
|
seccomp_t seccomp;
|
||||||
|
|
||||||
/* Thread group tracking */
|
/* Thread group tracking */
|
||||||
|
|
|
@ -192,7 +192,6 @@ struct audit_context {
|
||||||
enum audit_state state;
|
enum audit_state state;
|
||||||
unsigned int serial; /* serial number for record */
|
unsigned int serial; /* serial number for record */
|
||||||
struct timespec ctime; /* time of syscall entry */
|
struct timespec ctime; /* time of syscall entry */
|
||||||
uid_t loginuid; /* login uid (identity) */
|
|
||||||
int major; /* syscall number */
|
int major; /* syscall number */
|
||||||
unsigned long argv[4]; /* syscall arguments */
|
unsigned long argv[4]; /* syscall arguments */
|
||||||
int return_valid; /* return code is valid */
|
int return_valid; /* return code is valid */
|
||||||
|
@ -506,7 +505,7 @@ static int audit_filter_rules(struct task_struct *tsk,
|
||||||
case AUDIT_LOGINUID:
|
case AUDIT_LOGINUID:
|
||||||
result = 0;
|
result = 0;
|
||||||
if (ctx)
|
if (ctx)
|
||||||
result = audit_comparator(ctx->loginuid, f->op, f->val);
|
result = audit_comparator(tsk->loginuid, f->op, f->val);
|
||||||
break;
|
break;
|
||||||
case AUDIT_SUBJ_USER:
|
case AUDIT_SUBJ_USER:
|
||||||
case AUDIT_SUBJ_ROLE:
|
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,
|
static inline void audit_zero_context(struct audit_context *context,
|
||||||
enum audit_state state)
|
enum audit_state state)
|
||||||
{
|
{
|
||||||
uid_t loginuid = context->loginuid;
|
|
||||||
|
|
||||||
memset(context, 0, sizeof(*context));
|
memset(context, 0, sizeof(*context));
|
||||||
context->state = state;
|
context->state = state;
|
||||||
context->loginuid = loginuid;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline struct audit_context *audit_alloc_context(enum audit_state state)
|
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;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Preserve login uid */
|
|
||||||
context->loginuid = -1;
|
|
||||||
if (current->audit_context)
|
|
||||||
context->loginuid = current->audit_context->loginuid;
|
|
||||||
|
|
||||||
tsk->audit_context = context;
|
tsk->audit_context = context;
|
||||||
set_tsk_thread_flag(tsk, TIF_SYSCALL_AUDIT);
|
set_tsk_thread_flag(tsk, TIF_SYSCALL_AUDIT);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1047,7 +1038,7 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
|
||||||
context->name_count,
|
context->name_count,
|
||||||
context->ppid,
|
context->ppid,
|
||||||
context->pid,
|
context->pid,
|
||||||
context->loginuid,
|
tsk->loginuid,
|
||||||
context->uid,
|
context->uid,
|
||||||
context->gid,
|
context->gid,
|
||||||
context->euid, context->suid, context->fsuid,
|
context->euid, context->suid, context->fsuid,
|
||||||
|
@ -1779,39 +1770,22 @@ int audit_set_loginuid(struct task_struct *task, uid_t loginuid)
|
||||||
{
|
{
|
||||||
struct audit_context *context = task->audit_context;
|
struct audit_context *context = task->audit_context;
|
||||||
|
|
||||||
if (context) {
|
if (context && context->in_syscall) {
|
||||||
/* Only log if audit is enabled */
|
struct audit_buffer *ab;
|
||||||
if (context->in_syscall) {
|
|
||||||
struct audit_buffer *ab;
|
|
||||||
|
|
||||||
ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_LOGIN);
|
ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_LOGIN);
|
||||||
if (ab) {
|
if (ab) {
|
||||||
audit_log_format(ab, "login pid=%d uid=%u "
|
audit_log_format(ab, "login pid=%d uid=%u "
|
||||||
"old auid=%u new auid=%u",
|
"old auid=%u new auid=%u",
|
||||||
task->pid, task->uid,
|
task->pid, task->uid,
|
||||||
context->loginuid, loginuid);
|
task->loginuid, loginuid);
|
||||||
audit_log_end(ab);
|
audit_log_end(ab);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
context->loginuid = loginuid;
|
|
||||||
}
|
}
|
||||||
|
task->loginuid = loginuid;
|
||||||
return 0;
|
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
|
* __audit_mq_open - record audit data for a POSIX MQ open
|
||||||
* @oflag: open flag
|
* @oflag: open flag
|
||||||
|
@ -2217,8 +2191,8 @@ int __audit_signal_info(int sig, struct task_struct *t)
|
||||||
if (audit_pid && t->tgid == audit_pid) {
|
if (audit_pid && t->tgid == audit_pid) {
|
||||||
if (sig == SIGTERM || sig == SIGHUP || sig == SIGUSR1) {
|
if (sig == SIGTERM || sig == SIGHUP || sig == SIGUSR1) {
|
||||||
audit_sig_pid = tsk->pid;
|
audit_sig_pid = tsk->pid;
|
||||||
if (ctx)
|
if (tsk->loginuid != -1)
|
||||||
audit_sig_uid = ctx->loginuid;
|
audit_sig_uid = tsk->loginuid;
|
||||||
else
|
else
|
||||||
audit_sig_uid = tsk->uid;
|
audit_sig_uid = tsk->uid;
|
||||||
selinux_get_task_sid(tsk, &audit_sig_sid);
|
selinux_get_task_sid(tsk, &audit_sig_sid);
|
||||||
|
|
Loading…
Reference in New Issue