diff options
Diffstat (limited to 'kernel/auditsc.c')
-rw-r--r-- | kernel/auditsc.c | 133 |
1 files changed, 67 insertions, 66 deletions
diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 90594c9..9845cb3 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -95,6 +95,13 @@ struct audit_aux_data { /* Number of target pids per aux struct. */ #define AUDIT_AUX_PIDS 16 +struct audit_aux_data_execve { + struct audit_aux_data d; + int argc; + int envc; + struct mm_struct *mm; +}; + struct audit_aux_data_pids { struct audit_aux_data d; pid_t target_pid[AUDIT_AUX_PIDS]; @@ -114,6 +121,12 @@ struct audit_aux_data_bprm_fcaps { struct audit_cap_data new_pcap; }; +struct audit_aux_data_capset { + struct audit_aux_data d; + pid_t pid; + struct audit_cap_data cap; +}; + struct audit_tree_refs { struct audit_tree_refs *next; struct audit_chunk *c[31]; @@ -553,7 +566,7 @@ static int audit_filter_rules(struct task_struct *tsk, break; case AUDIT_INODE: if (name) - result = audit_comparator(name->ino, f->op, f->val); + result = (name->ino == f->val); else if (ctx) { list_for_each_entry(n, &ctx->names_list, list) { if (audit_comparator(n->ino, f->op, f->val)) { @@ -930,10 +943,8 @@ int audit_alloc(struct task_struct *tsk) return 0; /* Return if not auditing. */ state = audit_filter_task(tsk, &key); - if (state == AUDIT_DISABLED) { - clear_tsk_thread_flag(tsk, TIF_SYSCALL_AUDIT); + if (state == AUDIT_DISABLED) return 0; - } if (!(context = audit_alloc_context(state))) { kfree(key); @@ -1138,16 +1149,20 @@ static int audit_log_single_execve_arg(struct audit_context *context, } static void audit_log_execve_info(struct audit_context *context, - struct audit_buffer **ab) + struct audit_buffer **ab, + struct audit_aux_data_execve *axi) { int i, len; size_t len_sent = 0; const char __user *p; char *buf; - p = (const char __user *)current->mm->arg_start; + if (axi->mm != current->mm) + return; /* execve failed, no additional info */ + + p = (const char __user *)axi->mm->arg_start; - audit_log_format(*ab, "argc=%d", context->execve.argc); + audit_log_format(*ab, "argc=%d", axi->argc); /* * we need some kernel buffer to hold the userspace args. Just @@ -1161,7 +1176,7 @@ static void audit_log_execve_info(struct audit_context *context, return; } - for (i = 0; i < context->execve.argc; i++) { + for (i = 0; i < axi->argc; i++) { len = audit_log_single_execve_arg(context, ab, i, &len_sent, p, buf); if (len <= 0) @@ -1264,9 +1279,6 @@ static void show_special(struct audit_context *context, int *call_panic) audit_log_format(ab, "fd=%d flags=0x%x", context->mmap.fd, context->mmap.flags); break; } - case AUDIT_EXECVE: { - audit_log_execve_info(context, &ab); - break; } } audit_log_end(ab); } @@ -1313,6 +1325,11 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts switch (aux->type) { + case AUDIT_EXECVE: { + struct audit_aux_data_execve *axi = (void *)aux; + audit_log_execve_info(context, &ab, axi); + break; } + case AUDIT_BPRM_FCAPS: { struct audit_aux_data_bprm_fcaps *axs = (void *)aux; audit_log_format(ab, "fver=%x", axs->fcap_ver); @@ -1947,43 +1964,6 @@ int auditsc_get_stamp(struct audit_context *ctx, /* global counter which is incremented every time something logs in */ static atomic_t session_id = ATOMIC_INIT(0); -static int audit_set_loginuid_perm(kuid_t loginuid) -{ - /* if we are unset, we don't need privs */ - if (!audit_loginuid_set(current)) - return 0; - /* if AUDIT_FEATURE_LOGINUID_IMMUTABLE means never ever allow a change*/ - if (is_audit_feature_set(AUDIT_FEATURE_LOGINUID_IMMUTABLE)) - return -EPERM; - /* it is set, you need permission */ - if (!capable(CAP_AUDIT_CONTROL)) - return -EPERM; - /* reject if this is not an unset and we don't allow that */ - if (is_audit_feature_set(AUDIT_FEATURE_ONLY_UNSET_LOGINUID) && uid_valid(loginuid)) - return -EPERM; - return 0; -} - -static void audit_log_set_loginuid(kuid_t koldloginuid, kuid_t kloginuid, - unsigned int oldsessionid, unsigned int sessionid, - int rc) -{ - struct audit_buffer *ab; - uid_t uid, ologinuid, nloginuid; - - uid = from_kuid(&init_user_ns, task_uid(current)); - ologinuid = from_kuid(&init_user_ns, koldloginuid); - nloginuid = from_kuid(&init_user_ns, kloginuid), - - ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_LOGIN); - if (!ab) - return; - audit_log_format(ab, "pid=%d uid=%u old auid=%u new auid=%u old " - "ses=%u new ses=%u res=%d", current->pid, uid, ologinuid, - nloginuid, oldsessionid, sessionid, !rc); - audit_log_end(ab); -} - /** * audit_set_loginuid - set current task's audit_context loginuid * @loginuid: loginuid value @@ -1995,26 +1975,37 @@ static void audit_log_set_loginuid(kuid_t koldloginuid, kuid_t kloginuid, int audit_set_loginuid(kuid_t loginuid) { struct task_struct *task = current; - unsigned int oldsessionid, sessionid = (unsigned int)-1; - kuid_t oldloginuid; - int rc; - - oldloginuid = audit_get_loginuid(current); - oldsessionid = audit_get_sessionid(current); + struct audit_context *context = task->audit_context; + unsigned int sessionid; - rc = audit_set_loginuid_perm(loginuid); - if (rc) - goto out; +#ifdef CONFIG_AUDIT_LOGINUID_IMMUTABLE + if (audit_loginuid_set(task)) + return -EPERM; +#else /* CONFIG_AUDIT_LOGINUID_IMMUTABLE */ + if (!capable(CAP_AUDIT_CONTROL)) + return -EPERM; +#endif /* CONFIG_AUDIT_LOGINUID_IMMUTABLE */ - /* are we setting or clearing? */ - if (uid_valid(loginuid)) - sessionid = atomic_inc_return(&session_id); + sessionid = atomic_inc_return(&session_id); + 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" + " old ses=%u new ses=%u", + task->pid, + from_kuid(&init_user_ns, task_uid(task)), + from_kuid(&init_user_ns, task->loginuid), + from_kuid(&init_user_ns, loginuid), + task->sessionid, sessionid); + audit_log_end(ab); + } + } task->sessionid = sessionid; task->loginuid = loginuid; -out: - audit_log_set_loginuid(oldloginuid, loginuid, oldsessionid, sessionid, rc); - return rc; + return 0; } /** @@ -2135,12 +2126,22 @@ void __audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, umode_t mo context->ipc.has_perm = 1; } -void __audit_bprm(struct linux_binprm *bprm) +int __audit_bprm(struct linux_binprm *bprm) { + struct audit_aux_data_execve *ax; struct audit_context *context = current->audit_context; - context->type = AUDIT_EXECVE; - context->execve.argc = bprm->argc; + ax = kmalloc(sizeof(*ax), GFP_KERNEL); + if (!ax) + return -ENOMEM; + + ax->argc = bprm->argc; + ax->envc = bprm->envc; + ax->mm = bprm->mm; + ax->d.type = AUDIT_EXECVE; + ax->d.next = context->aux; + context->aux = (void *)ax; + return 0; } |