summaryrefslogtreecommitdiff
path: root/kernel/auditsc.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/auditsc.c')
-rw-r--r--kernel/auditsc.c133
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;
}