audit: use current whenever possible

There are many places, notably audit_log_task_info() and
audit_log_exit(), that take task_struct pointers but in reality they
are always working on the current task.  This patch eliminates the
task_struct arguments and uses current directly which allows a number
of cleanups as well.

Acked-by: Richard Guy Briggs <rgb@redhat.com>
Signed-off-by: Paul Moore <paul@paul-moore.com>
This commit is contained in:
Paul Moore 2018-11-26 18:40:07 -05:00
parent d0a3f18a70
commit 2a1fe215e7
6 changed files with 90 additions and 98 deletions

View File

@ -61,20 +61,19 @@ static void tty_audit_log(const char *description, dev_t dev,
unsigned char *data, size_t size) unsigned char *data, size_t size)
{ {
struct audit_buffer *ab; struct audit_buffer *ab;
struct task_struct *tsk = current; pid_t pid = task_pid_nr(current);
pid_t pid = task_pid_nr(tsk); uid_t uid = from_kuid(&init_user_ns, task_uid(current));
uid_t uid = from_kuid(&init_user_ns, task_uid(tsk)); uid_t loginuid = from_kuid(&init_user_ns, audit_get_loginuid(current));
uid_t loginuid = from_kuid(&init_user_ns, audit_get_loginuid(tsk)); unsigned int sessionid = audit_get_sessionid(current);
unsigned int sessionid = audit_get_sessionid(tsk);
ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_TTY); ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_TTY);
if (ab) { if (ab) {
char name[sizeof(tsk->comm)]; char name[sizeof(current->comm)];
audit_log_format(ab, "%s pid=%u uid=%u auid=%u ses=%u major=%d" audit_log_format(ab, "%s pid=%u uid=%u auid=%u ses=%u major=%d"
" minor=%d comm=", description, pid, uid, " minor=%d comm=", description, pid, uid,
loginuid, sessionid, MAJOR(dev), MINOR(dev)); loginuid, sessionid, MAJOR(dev), MINOR(dev));
get_task_comm(name, tsk); get_task_comm(name, current);
audit_log_untrustedstring(ab, name); audit_log_untrustedstring(ab, name);
audit_log_format(ab, " data="); audit_log_format(ab, " data=");
audit_log_n_hex(ab, data, size); audit_log_n_hex(ab, data, size);

View File

@ -151,8 +151,7 @@ extern void audit_log_link_denied(const char *operation);
extern void audit_log_lost(const char *message); extern void audit_log_lost(const char *message);
extern int audit_log_task_context(struct audit_buffer *ab); extern int audit_log_task_context(struct audit_buffer *ab);
extern void audit_log_task_info(struct audit_buffer *ab, extern void audit_log_task_info(struct audit_buffer *ab);
struct task_struct *tsk);
extern int audit_update_lsm_rules(void); extern int audit_update_lsm_rules(void);
@ -200,8 +199,7 @@ static inline int audit_log_task_context(struct audit_buffer *ab)
{ {
return 0; return 0;
} }
static inline void audit_log_task_info(struct audit_buffer *ab, static inline void audit_log_task_info(struct audit_buffer *ab)
struct task_struct *tsk)
{ } { }
#define audit_enabled AUDIT_OFF #define audit_enabled AUDIT_OFF
#endif /* CONFIG_AUDIT */ #endif /* CONFIG_AUDIT */

View File

@ -1096,10 +1096,11 @@ static void audit_log_feature_change(int which, u32 old_feature, u32 new_feature
if (audit_enabled == AUDIT_OFF) if (audit_enabled == AUDIT_OFF)
return; return;
ab = audit_log_start(audit_context(), GFP_KERNEL, AUDIT_FEATURE_CHANGE); ab = audit_log_start(audit_context(), GFP_KERNEL, AUDIT_FEATURE_CHANGE);
if (!ab) if (!ab)
return; return;
audit_log_task_info(ab, current); audit_log_task_info(ab);
audit_log_format(ab, " feature=%s old=%u new=%u old_lock=%u new_lock=%u res=%d", audit_log_format(ab, " feature=%s old=%u new=%u old_lock=%u new_lock=%u res=%d",
audit_feature_names[which], !!old_feature, !!new_feature, audit_feature_names[which], !!old_feature, !!new_feature,
!!old_lock, !!new_lock, res); !!old_lock, !!new_lock, res);
@ -2246,15 +2247,15 @@ out_null:
audit_log_format(ab, " exe=(null)"); audit_log_format(ab, " exe=(null)");
} }
struct tty_struct *audit_get_tty(struct task_struct *tsk) struct tty_struct *audit_get_tty(void)
{ {
struct tty_struct *tty = NULL; struct tty_struct *tty = NULL;
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&tsk->sighand->siglock, flags); spin_lock_irqsave(&current->sighand->siglock, flags);
if (tsk->signal) if (current->signal)
tty = tty_kref_get(tsk->signal->tty); tty = tty_kref_get(current->signal->tty);
spin_unlock_irqrestore(&tsk->sighand->siglock, flags); spin_unlock_irqrestore(&current->sighand->siglock, flags);
return tty; return tty;
} }
@ -2263,25 +2264,24 @@ void audit_put_tty(struct tty_struct *tty)
tty_kref_put(tty); tty_kref_put(tty);
} }
void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk) void audit_log_task_info(struct audit_buffer *ab)
{ {
const struct cred *cred; const struct cred *cred;
char comm[sizeof(tsk->comm)]; char comm[sizeof(current->comm)];
struct tty_struct *tty; struct tty_struct *tty;
if (!ab) if (!ab)
return; return;
/* tsk == current */
cred = current_cred(); cred = current_cred();
tty = audit_get_tty(tsk); tty = audit_get_tty();
audit_log_format(ab, audit_log_format(ab,
" ppid=%d pid=%d auid=%u uid=%u gid=%u" " ppid=%d pid=%d auid=%u uid=%u gid=%u"
" euid=%u suid=%u fsuid=%u" " euid=%u suid=%u fsuid=%u"
" egid=%u sgid=%u fsgid=%u tty=%s ses=%u", " egid=%u sgid=%u fsgid=%u tty=%s ses=%u",
task_ppid_nr(tsk), task_ppid_nr(current),
task_tgid_nr(tsk), task_tgid_nr(current),
from_kuid(&init_user_ns, audit_get_loginuid(tsk)), from_kuid(&init_user_ns, audit_get_loginuid(current)),
from_kuid(&init_user_ns, cred->uid), from_kuid(&init_user_ns, cred->uid),
from_kgid(&init_user_ns, cred->gid), from_kgid(&init_user_ns, cred->gid),
from_kuid(&init_user_ns, cred->euid), from_kuid(&init_user_ns, cred->euid),
@ -2291,11 +2291,11 @@ void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk)
from_kgid(&init_user_ns, cred->sgid), from_kgid(&init_user_ns, cred->sgid),
from_kgid(&init_user_ns, cred->fsgid), from_kgid(&init_user_ns, cred->fsgid),
tty ? tty_name(tty) : "(none)", tty ? tty_name(tty) : "(none)",
audit_get_sessionid(tsk)); audit_get_sessionid(current));
audit_put_tty(tty); audit_put_tty(tty);
audit_log_format(ab, " comm="); audit_log_format(ab, " comm=");
audit_log_untrustedstring(ab, get_task_comm(comm, tsk)); audit_log_untrustedstring(ab, get_task_comm(comm, current));
audit_log_d_path_exe(ab, tsk->mm); audit_log_d_path_exe(ab, current->mm);
audit_log_task_context(ab); audit_log_task_context(ab);
} }
EXPORT_SYMBOL(audit_log_task_info); EXPORT_SYMBOL(audit_log_task_info);
@ -2316,7 +2316,7 @@ void audit_log_link_denied(const char *operation)
if (!ab) if (!ab)
return; return;
audit_log_format(ab, "op=%s", operation); audit_log_format(ab, "op=%s", operation);
audit_log_task_info(ab, current); audit_log_task_info(ab);
audit_log_format(ab, " res=0"); audit_log_format(ab, " res=0");
audit_log_end(ab); audit_log_end(ab);
} }

View File

@ -264,7 +264,7 @@ extern struct audit_entry *audit_dupe_rule(struct audit_krule *old);
extern void audit_log_d_path_exe(struct audit_buffer *ab, extern void audit_log_d_path_exe(struct audit_buffer *ab,
struct mm_struct *mm); struct mm_struct *mm);
extern struct tty_struct *audit_get_tty(struct task_struct *tsk); extern struct tty_struct *audit_get_tty(void);
extern void audit_put_tty(struct tty_struct *tty); extern void audit_put_tty(struct tty_struct *tty);
/* audit watch functions */ /* audit watch functions */

View File

@ -830,44 +830,6 @@ void audit_filter_inodes(struct task_struct *tsk, struct audit_context *ctx)
rcu_read_unlock(); rcu_read_unlock();
} }
/* Transfer the audit context pointer to the caller, clearing it in the tsk's struct */
static inline struct audit_context *audit_take_context(struct task_struct *tsk,
int return_valid,
long return_code)
{
struct audit_context *context = tsk->audit_context;
if (!context)
return NULL;
context->return_valid = return_valid;
/*
* we need to fix up the return code in the audit logs if the actual
* return codes are later going to be fixed up by the arch specific
* signal handlers
*
* This is actually a test for:
* (rc == ERESTARTSYS ) || (rc == ERESTARTNOINTR) ||
* (rc == ERESTARTNOHAND) || (rc == ERESTART_RESTARTBLOCK)
*
* but is faster than a bunch of ||
*/
if (unlikely(return_code <= -ERESTARTSYS) &&
(return_code >= -ERESTART_RESTARTBLOCK) &&
(return_code != -ENOIOCTLCMD))
context->return_code = -EINTR;
else
context->return_code = return_code;
if (context->in_syscall && !context->dummy) {
audit_filter_syscall(tsk, context, &audit_filter_list[AUDIT_FILTER_EXIT]);
audit_filter_inodes(tsk, context);
}
audit_set_context(tsk, NULL);
return context;
}
static inline void audit_proctitle_free(struct audit_context *context) static inline void audit_proctitle_free(struct audit_context *context)
{ {
kfree(context->proctitle.value); kfree(context->proctitle.value);
@ -1296,15 +1258,18 @@ static inline int audit_proctitle_rtrim(char *proctitle, int len)
return len; return len;
} }
static void audit_log_proctitle(struct task_struct *tsk, static void audit_log_proctitle(void)
struct audit_context *context)
{ {
int res; int res;
char *buf; char *buf;
char *msg = "(null)"; char *msg = "(null)";
int len = strlen(msg); int len = strlen(msg);
struct audit_context *context = audit_context();
struct audit_buffer *ab; struct audit_buffer *ab;
if (!context || context->dummy)
return;
ab = audit_log_start(context, GFP_KERNEL, AUDIT_PROCTITLE); ab = audit_log_start(context, GFP_KERNEL, AUDIT_PROCTITLE);
if (!ab) if (!ab)
return; /* audit_panic or being filtered */ return; /* audit_panic or being filtered */
@ -1317,7 +1282,7 @@ static void audit_log_proctitle(struct task_struct *tsk,
if (!buf) if (!buf)
goto out; goto out;
/* Historically called this from procfs naming */ /* Historically called this from procfs naming */
res = get_cmdline(tsk, buf, MAX_PROCTITLE_AUDIT_LEN); res = get_cmdline(current, buf, MAX_PROCTITLE_AUDIT_LEN);
if (res == 0) { if (res == 0) {
kfree(buf); kfree(buf);
goto out; goto out;
@ -1337,15 +1302,15 @@ out:
audit_log_end(ab); audit_log_end(ab);
} }
static void audit_log_exit(struct audit_context *context, struct task_struct *tsk) static void audit_log_exit(void)
{ {
int i, call_panic = 0; int i, call_panic = 0;
struct audit_context *context = audit_context();
struct audit_buffer *ab; struct audit_buffer *ab;
struct audit_aux_data *aux; struct audit_aux_data *aux;
struct audit_names *n; struct audit_names *n;
/* tsk == current */ context->personality = current->personality;
context->personality = tsk->personality;
ab = audit_log_start(context, GFP_KERNEL, AUDIT_SYSCALL); ab = audit_log_start(context, GFP_KERNEL, AUDIT_SYSCALL);
if (!ab) if (!ab)
@ -1367,7 +1332,7 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
context->argv[3], context->argv[3],
context->name_count); context->name_count);
audit_log_task_info(ab, tsk); audit_log_task_info(ab);
audit_log_key(ab, context->filterkey); audit_log_key(ab, context->filterkey);
audit_log_end(ab); audit_log_end(ab);
@ -1456,7 +1421,7 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
audit_log_name(context, n, NULL, i++, &call_panic); audit_log_name(context, n, NULL, i++, &call_panic);
} }
audit_log_proctitle(tsk, context); audit_log_proctitle();
/* Send end of event record to help user space know we are finished */ /* Send end of event record to help user space know we are finished */
ab = audit_log_start(context, GFP_KERNEL, AUDIT_EOE); ab = audit_log_start(context, GFP_KERNEL, AUDIT_EOE);
@ -1474,22 +1439,31 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
*/ */
void __audit_free(struct task_struct *tsk) void __audit_free(struct task_struct *tsk)
{ {
struct audit_context *context; struct audit_context *context = tsk->audit_context;
context = audit_take_context(tsk, 0, 0);
if (!context) if (!context)
return; return;
/* Check for system calls that do not go through the exit /* We are called either by do_exit() or the fork() error handling code;
* function (e.g., exit_group), then free context block. * in the former case tsk == current and in the latter tsk is a
* We use GFP_ATOMIC here because we might be doing this * random task_struct that doesn't doesn't have any meaningful data we
* in the context of the idle thread */ * need to log via audit_log_exit().
/* that can happen only if we are called from do_exit() */ */
if (context->in_syscall && context->current_state == AUDIT_RECORD_CONTEXT) if (tsk == current && !context->dummy && context->in_syscall) {
audit_log_exit(context, tsk); context->return_valid = 0;
context->return_code = 0;
audit_filter_syscall(tsk, context,
&audit_filter_list[AUDIT_FILTER_EXIT]);
audit_filter_inodes(tsk, context);
if (context->current_state == AUDIT_RECORD_CONTEXT)
audit_log_exit();
}
if (!list_empty(&context->killed_trees)) if (!list_empty(&context->killed_trees))
audit_kill_trees(&context->killed_trees); audit_kill_trees(&context->killed_trees);
audit_set_context(tsk, NULL);
audit_free_context(context); audit_free_context(context);
} }
@ -1559,17 +1533,40 @@ void __audit_syscall_exit(int success, long return_code)
{ {
struct audit_context *context; struct audit_context *context;
if (success) context = audit_context();
success = AUDITSC_SUCCESS;
else
success = AUDITSC_FAILURE;
context = audit_take_context(current, success, return_code);
if (!context) if (!context)
return; return;
if (context->in_syscall && context->current_state == AUDIT_RECORD_CONTEXT) if (!context->dummy && context->in_syscall) {
audit_log_exit(context, current); if (success)
context->return_valid = AUDITSC_SUCCESS;
else
context->return_valid = AUDITSC_FAILURE;
/*
* we need to fix up the return code in the audit logs if the
* actual return codes are later going to be fixed up by the
* arch specific signal handlers
*
* This is actually a test for:
* (rc == ERESTARTSYS ) || (rc == ERESTARTNOINTR) ||
* (rc == ERESTARTNOHAND) || (rc == ERESTART_RESTARTBLOCK)
*
* but is faster than a bunch of ||
*/
if (unlikely(return_code <= -ERESTARTSYS) &&
(return_code >= -ERESTART_RESTARTBLOCK) &&
(return_code != -ENOIOCTLCMD))
context->return_code = -EINTR;
else
context->return_code = return_code;
audit_filter_syscall(current, context,
&audit_filter_list[AUDIT_FILTER_EXIT]);
audit_filter_inodes(current, context);
if (context->current_state == AUDIT_RECORD_CONTEXT)
audit_log_exit();
}
context->in_syscall = 0; context->in_syscall = 0;
context->prio = context->state == AUDIT_RECORD_CONTEXT ? ~0ULL : 0; context->prio = context->state == AUDIT_RECORD_CONTEXT ? ~0ULL : 0;
@ -1591,7 +1588,6 @@ void __audit_syscall_exit(int success, long return_code)
kfree(context->filterkey); kfree(context->filterkey);
context->filterkey = NULL; context->filterkey = NULL;
} }
audit_set_context(current, context);
} }
static inline void handle_one(const struct inode *inode) static inline void handle_one(const struct inode *inode)
@ -2025,7 +2021,7 @@ static void audit_log_set_loginuid(kuid_t koldloginuid, kuid_t kloginuid,
uid = from_kuid(&init_user_ns, task_uid(current)); uid = from_kuid(&init_user_ns, task_uid(current));
oldloginuid = from_kuid(&init_user_ns, koldloginuid); oldloginuid = from_kuid(&init_user_ns, koldloginuid);
loginuid = from_kuid(&init_user_ns, kloginuid), loginuid = from_kuid(&init_user_ns, kloginuid),
tty = audit_get_tty(current); tty = audit_get_tty();
audit_log_format(ab, "pid=%d uid=%u", task_tgid_nr(current), uid); audit_log_format(ab, "pid=%d uid=%u", task_tgid_nr(current), uid);
audit_log_task_context(ab); audit_log_task_context(ab);
@ -2046,7 +2042,6 @@ static void audit_log_set_loginuid(kuid_t koldloginuid, kuid_t kloginuid,
*/ */
int audit_set_loginuid(kuid_t loginuid) int audit_set_loginuid(kuid_t loginuid)
{ {
struct task_struct *task = current;
unsigned int oldsessionid, sessionid = AUDIT_SID_UNSET; unsigned int oldsessionid, sessionid = AUDIT_SID_UNSET;
kuid_t oldloginuid; kuid_t oldloginuid;
int rc; int rc;
@ -2065,8 +2060,8 @@ int audit_set_loginuid(kuid_t loginuid)
sessionid = (unsigned int)atomic_inc_return(&session_id); sessionid = (unsigned int)atomic_inc_return(&session_id);
} }
task->sessionid = sessionid; current->sessionid = sessionid;
task->loginuid = loginuid; current->loginuid = loginuid;
out: out:
audit_log_set_loginuid(oldloginuid, loginuid, oldsessionid, sessionid, rc); audit_log_set_loginuid(oldloginuid, loginuid, oldsessionid, sessionid, rc);
return rc; return rc;

View File

@ -336,7 +336,7 @@ void ima_audit_measurement(struct integrity_iint_cache *iint,
audit_log_untrustedstring(ab, filename); audit_log_untrustedstring(ab, filename);
audit_log_format(ab, " hash=\"%s:%s\"", algo_name, hash); audit_log_format(ab, " hash=\"%s:%s\"", algo_name, hash);
audit_log_task_info(ab, current); audit_log_task_info(ab);
audit_log_end(ab); audit_log_end(ab);
iint->flags |= IMA_AUDITED; iint->flags |= IMA_AUDITED;