From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.0 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI, MENTIONS_GIT_HOSTING,SIGNED_OFF_BY,SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2AE35C10F14 for ; Tue, 9 Apr 2019 03:40:07 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 0401621841 for ; Tue, 9 Apr 2019 03:40:07 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727284AbfDIDkA (ORCPT ); Mon, 8 Apr 2019 23:40:00 -0400 Received: from mx1.redhat.com ([209.132.183.28]:58194 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726456AbfDIDj7 (ORCPT ); Mon, 8 Apr 2019 23:39:59 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id A46A4307EA8F; Tue, 9 Apr 2019 03:39:58 +0000 (UTC) Received: from madcap2.tricolour.ca (ovpn-112-16.phx2.redhat.com [10.3.112.16]) by smtp.corp.redhat.com (Postfix) with ESMTP id 461C519C5A; Tue, 9 Apr 2019 03:39:54 +0000 (UTC) From: Richard Guy Briggs To: containers@lists.linux-foundation.org, linux-api@vger.kernel.org, Linux-Audit Mailing List , linux-fsdevel@vger.kernel.org, LKML , netdev@vger.kernel.org, netfilter-devel@vger.kernel.org Cc: Paul Moore , sgrubb@redhat.com, omosnace@redhat.com, dhowells@redhat.com, simo@redhat.com, eparis@parisplace.org, serge@hallyn.com, ebiederm@xmission.com, nhorman@tuxdriver.com, Richard Guy Briggs Subject: [PATCH ghak90 V6 01/10] audit: collect audit task parameters Date: Mon, 8 Apr 2019 23:39:08 -0400 Message-Id: In-Reply-To: References: In-Reply-To: References: X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.44]); Tue, 09 Apr 2019 03:39:59 +0000 (UTC) Sender: netfilter-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netfilter-devel@vger.kernel.org The audit-related parameters in struct task_struct should ideally be collected together and accessed through a standard audit API. Collect the existing loginuid, sessionid and audit_context together in a new struct audit_task_info called "audit" in struct task_struct. Use kmem_cache to manage this pool of memory. Un-inline audit_free() to be able to always recover that memory. Please see the upstream github issue https://github.com/linux-audit/audit-kernel/issues/81 Signed-off-by: Richard Guy Briggs Acked-by: Neil Horman Reviewed-by: Ondrej Mosnacek --- include/linux/audit.h | 49 +++++++++++++++++++++++------------ include/linux/sched.h | 7 +---- init/init_task.c | 3 +-- init/main.c | 2 ++ kernel/audit.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++-- kernel/audit.h | 5 ++++ kernel/auditsc.c | 26 ++++++++++--------- kernel/fork.c | 1 - 8 files changed, 124 insertions(+), 40 deletions(-) diff --git a/include/linux/audit.h b/include/linux/audit.h index 1e69d9fe16da..bde346e73f0c 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -86,6 +86,16 @@ struct audit_field { u32 op; }; +struct audit_task_info { + kuid_t loginuid; + unsigned int sessionid; +#ifdef CONFIG_AUDITSYSCALL + struct audit_context *ctx; +#endif +}; + +extern struct audit_task_info init_struct_audit; + extern int is_audit_feature_set(int which); extern int __init audit_register_class(int class, unsigned *list); @@ -122,6 +132,9 @@ struct audit_field { #ifdef CONFIG_AUDIT /* These are defined in audit.c */ /* Public API */ +extern int audit_alloc(struct task_struct *task); +extern void audit_free(struct task_struct *task); +extern void __init audit_task_init(void); extern __printf(4, 5) void audit_log(struct audit_context *ctx, gfp_t gfp_mask, int type, const char *fmt, ...); @@ -164,16 +177,28 @@ extern void audit_log_key(struct audit_buffer *ab, static inline kuid_t audit_get_loginuid(struct task_struct *tsk) { - return tsk->loginuid; + if (!tsk->audit) + return INVALID_UID; + return tsk->audit->loginuid; } static inline unsigned int audit_get_sessionid(struct task_struct *tsk) { - return tsk->sessionid; + if (!tsk->audit) + return AUDIT_SID_UNSET; + return tsk->audit->sessionid; } extern u32 audit_enabled; #else /* CONFIG_AUDIT */ +static inline int audit_alloc(struct task_struct *task) +{ + return 0; +} +static inline void audit_free(struct task_struct *task) +{ } +static inline void __init audit_task_init(void) +{ } static inline __printf(4, 5) void audit_log(struct audit_context *ctx, gfp_t gfp_mask, int type, const char *fmt, ...) @@ -239,8 +264,6 @@ static inline unsigned int audit_get_sessionid(struct task_struct *tsk) /* These are defined in auditsc.c */ /* Public API */ -extern int audit_alloc(struct task_struct *task); -extern void __audit_free(struct task_struct *task); extern void __audit_syscall_entry(int major, unsigned long a0, unsigned long a1, unsigned long a2, unsigned long a3); extern void __audit_syscall_exit(int ret_success, long ret_value); @@ -263,12 +286,14 @@ extern void audit_seccomp_actions_logged(const char *names, static inline void audit_set_context(struct task_struct *task, struct audit_context *ctx) { - task->audit_context = ctx; + task->audit->ctx = ctx; } static inline struct audit_context *audit_context(void) { - return current->audit_context; + if (!current->audit) + return NULL; + return current->audit->ctx; } static inline bool audit_dummy_context(void) @@ -276,11 +301,7 @@ static inline bool audit_dummy_context(void) void *p = audit_context(); return !p || *(int *)p; } -static inline void audit_free(struct task_struct *task) -{ - if (unlikely(task->audit_context)) - __audit_free(task); -} + static inline void audit_syscall_entry(int major, unsigned long a0, unsigned long a1, unsigned long a2, unsigned long a3) @@ -470,12 +491,6 @@ static inline void audit_fanotify(unsigned int response) extern int audit_n_rules; extern int audit_signals; #else /* CONFIG_AUDITSYSCALL */ -static inline int audit_alloc(struct task_struct *task) -{ - return 0; -} -static inline void audit_free(struct task_struct *task) -{ } static inline void audit_syscall_entry(int major, unsigned long a0, unsigned long a1, unsigned long a2, unsigned long a3) diff --git a/include/linux/sched.h b/include/linux/sched.h index 1549584a1538..3e0699a26dab 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -32,7 +32,6 @@ #include /* task_struct member predeclarations (sorted alphabetically): */ -struct audit_context; struct backing_dev_info; struct bio_list; struct blk_plug; @@ -873,11 +872,7 @@ struct task_struct { struct callback_head *task_works; #ifdef CONFIG_AUDIT -#ifdef CONFIG_AUDITSYSCALL - struct audit_context *audit_context; -#endif - kuid_t loginuid; - unsigned int sessionid; + struct audit_task_info *audit; #endif struct seccomp seccomp; diff --git a/init/init_task.c b/init/init_task.c index c70ef656d0f4..32420485e54b 100644 --- a/init/init_task.c +++ b/init/init_task.c @@ -123,8 +123,7 @@ struct task_struct init_task .thread_group = LIST_HEAD_INIT(init_task.thread_group), .thread_node = LIST_HEAD_INIT(init_signals.thread_head), #ifdef CONFIG_AUDIT - .loginuid = INVALID_UID, - .sessionid = AUDIT_SID_UNSET, + .audit = &init_struct_audit, #endif #ifdef CONFIG_PERF_EVENTS .perf_event_mutex = __MUTEX_INITIALIZER(init_task.perf_event_mutex), diff --git a/init/main.c b/init/main.c index 598e278b46f7..26b6c80f5b1d 100644 --- a/init/main.c +++ b/init/main.c @@ -92,6 +92,7 @@ #include #include #include +#include #include #include @@ -734,6 +735,7 @@ asmlinkage __visible void __init start_kernel(void) nsfs_init(); cpuset_init(); cgroup_init(); + audit_task_init(); taskstats_init_early(); delayacct_init(); diff --git a/kernel/audit.c b/kernel/audit.c index b96bf69183f4..3fb09783cd4a 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -215,6 +215,73 @@ struct audit_reply { struct sk_buff *skb; }; +static struct kmem_cache *audit_task_cache; + +void __init audit_task_init(void) +{ + audit_task_cache = kmem_cache_create("audit_task", + sizeof(struct audit_task_info), + 0, SLAB_PANIC, NULL); +} + +/** + * audit_alloc - allocate an audit info block for a task + * @tsk: task + * + * Call audit_alloc_syscall to filter on the task information and + * allocate a per-task audit context if necessary. This is called from + * copy_process, so no lock is needed. + */ +int audit_alloc(struct task_struct *tsk) +{ + int ret = 0; + struct audit_task_info *info; + + info = kmem_cache_alloc(audit_task_cache, GFP_KERNEL); + if (!info) { + ret = -ENOMEM; + goto out; + } + info->loginuid = audit_get_loginuid(current); + info->sessionid = audit_get_sessionid(current); + tsk->audit = info; + + ret = audit_alloc_syscall(tsk); + if (ret) { + tsk->audit = NULL; + kmem_cache_free(audit_task_cache, info); + } +out: + return ret; +} + +struct audit_task_info init_struct_audit = { + .loginuid = INVALID_UID, + .sessionid = AUDIT_SID_UNSET, +#ifdef CONFIG_AUDITSYSCALL + .ctx = NULL, +#endif +}; + +/** + * audit_free - free per-task audit info + * @tsk: task whose audit info block to free + * + * Called from copy_process and do_exit + */ +void audit_free(struct task_struct *tsk) +{ + struct audit_task_info *info = tsk->audit; + + audit_free_syscall(tsk); + /* Freeing the audit_task_info struct must be performed after + * audit_log_exit() due to need for loginuid and sessionid. + */ + info = tsk->audit; + tsk->audit = NULL; + kmem_cache_free(audit_task_cache, info); +} + /** * auditd_test_task - Check to see if a given task is an audit daemon * @task: the task to check @@ -2266,8 +2333,8 @@ int audit_set_loginuid(kuid_t loginuid) sessionid = (unsigned int)atomic_inc_return(&session_id); } - current->sessionid = sessionid; - current->loginuid = loginuid; + current->audit->sessionid = sessionid; + current->audit->loginuid = loginuid; out: audit_log_set_loginuid(oldloginuid, loginuid, oldsessionid, sessionid, rc); return rc; diff --git a/kernel/audit.h b/kernel/audit.h index 958d5b8fc1b3..c00e2ee3c6b3 100644 --- a/kernel/audit.h +++ b/kernel/audit.h @@ -264,6 +264,8 @@ extern void audit_log_d_path_exe(struct audit_buffer *ab, extern unsigned int audit_serial(void); extern int auditsc_get_stamp(struct audit_context *ctx, struct timespec64 *t, unsigned int *serial); +extern int audit_alloc_syscall(struct task_struct *tsk); +extern void audit_free_syscall(struct task_struct *tsk); extern void audit_put_watch(struct audit_watch *watch); extern void audit_get_watch(struct audit_watch *watch); @@ -305,6 +307,9 @@ extern void audit_filter_inodes(struct task_struct *tsk, extern struct list_head *audit_killed_trees(void); #else /* CONFIG_AUDITSYSCALL */ #define auditsc_get_stamp(c, t, s) 0 +#define audit_alloc_syscall(t) 0 +#define audit_free_syscall(t) {} + #define audit_put_watch(w) {} #define audit_get_watch(w) {} #define audit_to_watch(k, p, l, o) (-EINVAL) diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 98a98e6dca05..fd7ca983de4f 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -892,23 +892,25 @@ static inline struct audit_context *audit_alloc_context(enum audit_state state) return context; } -/** - * audit_alloc - allocate an audit context block for a task +/* + * audit_alloc_syscall - allocate an audit context block for a task * @tsk: task * * Filter on the task information and allocate a per-task audit context * if necessary. Doing so turns on system call auditing for the - * specified task. This is called from copy_process, so no lock is - * needed. + * specified task. This is called from copy_process via audit_alloc, so + * no lock is needed. */ -int audit_alloc(struct task_struct *tsk) +int audit_alloc_syscall(struct task_struct *tsk) { struct audit_context *context; enum audit_state state; char *key = NULL; - if (likely(!audit_ever_enabled)) + if (likely(!audit_ever_enabled)) { + audit_set_context(tsk, NULL); return 0; /* Return if not auditing. */ + } state = audit_filter_task(tsk, &key); if (state == AUDIT_DISABLED) { @@ -918,7 +920,7 @@ int audit_alloc(struct task_struct *tsk) if (!(context = audit_alloc_context(state))) { kfree(key); - audit_log_lost("out of memory in audit_alloc"); + audit_log_lost("out of memory in audit_alloc_syscall"); return -ENOMEM; } context->filterkey = key; @@ -1563,14 +1565,15 @@ static void audit_log_exit(void) } /** - * __audit_free - free a per-task audit context + * audit_free_syscall - free per-task audit context info * @tsk: task whose audit context block to free * - * Called from copy_process and do_exit + * Called from audit_free */ -void __audit_free(struct task_struct *tsk) +void audit_free_syscall(struct task_struct *tsk) { - struct audit_context *context = tsk->audit_context; + struct audit_task_info *info = tsk->audit; + struct audit_context *context = info->ctx; if (!context) return; @@ -1593,7 +1596,6 @@ void __audit_free(struct task_struct *tsk) if (context->current_state == AUDIT_RECORD_CONTEXT) audit_log_exit(); } - audit_set_context(tsk, NULL); audit_free_context(context); } diff --git a/kernel/fork.c b/kernel/fork.c index 9dcd18aa210b..9167a8f3edae 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -1834,7 +1834,6 @@ static __latent_entropy struct task_struct *copy_process( posix_cpu_timers_init(p); p->io_context = NULL; - audit_set_context(p, NULL); cgroup_fork(p); #ifdef CONFIG_NUMA p->mempolicy = mpol_dup(p->mempolicy); -- 1.8.3.1