From patchwork Thu Sep 19 01:22:18 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Guy Briggs X-Patchwork-Id: 11151385 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 29E241745 for ; Thu, 19 Sep 2019 01:23:40 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id F1D2021925 for ; Thu, 19 Sep 2019 01:23:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731626AbfISBXd (ORCPT ); Wed, 18 Sep 2019 21:23:33 -0400 Received: from mx1.redhat.com ([209.132.183.28]:32846 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729856AbfISBXc (ORCPT ); Wed, 18 Sep 2019 21:23:32 -0400 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 8786518CB8FB; Thu, 19 Sep 2019 01:23:28 +0000 (UTC) Received: from madcap2.tricolour.ca (ovpn-112-19.phx2.redhat.com [10.3.112.19]) by smtp.corp.redhat.com (Postfix) with ESMTP id 16A7260C44; Thu, 19 Sep 2019 01:23:21 +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, dwalsh@redhat.com, mpatel@redhat.com, Richard Guy Briggs Subject: [PATCH ghak90 V7 01/21] audit: collect audit task parameters Date: Wed, 18 Sep 2019 21:22:18 -0400 Message-Id: <2149c8012480b3d77872e3828b0c4bc3b2910fe6.1568834524.git.rgb@redhat.com> In-Reply-To: References: In-Reply-To: References: X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.6.2 (mx1.redhat.com [10.5.110.63]); Thu, 19 Sep 2019 01:23:31 +0000 (UTC) Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@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 97d0925454df..4fbda55f3cf2 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -95,6 +95,16 @@ struct audit_ntp_data { struct audit_ntp_data {}; #endif +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); @@ -131,6 +141,9 @@ struct audit_ntp_data { #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, ...); @@ -173,12 +186,16 @@ 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; @@ -186,6 +203,14 @@ static inline unsigned int audit_get_sessionid(struct task_struct *tsk) extern int audit_signal_info(int sig, struct task_struct *t); #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, ...) @@ -257,8 +282,6 @@ static inline int audit_signal_info(int sig, struct task_struct *t) /* 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); @@ -281,12 +304,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) @@ -294,11 +319,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) @@ -523,12 +544,6 @@ static inline void audit_ntp_log(const struct audit_ntp_data *ad) 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 8dc1811487f5..a936d162513a 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -31,7 +31,6 @@ #include /* task_struct member predeclarations (sorted alphabetically): */ -struct audit_context; struct backing_dev_info; struct bio_list; struct blk_plug; @@ -940,11 +939,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 7ab773b9b3cd..6496bbe5c56e 100644 --- a/init/init_task.c +++ b/init/init_task.c @@ -124,8 +124,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 96f8d5af52d6..dbcaa49bbaea 100644 --- a/init/main.c +++ b/init/main.c @@ -93,6 +93,7 @@ #include #include #include +#include #include #include @@ -771,6 +772,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 da8dc0db5bd3..5b1c52bafaeb 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -202,6 +202,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 @@ -2253,8 +2320,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 6fb7160412d4..7f623ef216e6 100644 --- a/kernel/audit.h +++ b/kernel/audit.h @@ -251,6 +251,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); @@ -292,6 +294,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 4effe01ebbe2..10679da36bb6 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -903,23 +903,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) { @@ -929,7 +931,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; @@ -1574,14 +1576,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; @@ -1604,7 +1607,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 d8ae0f1b4148..ef9c123e8ae8 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -1938,7 +1938,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); From patchwork Thu Sep 19 01:22:19 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Guy Briggs X-Patchwork-Id: 11151387 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 60CF21745 for ; Thu, 19 Sep 2019 01:23:54 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 33F2521929 for ; Thu, 19 Sep 2019 01:23:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731694AbfISBXs (ORCPT ); Wed, 18 Sep 2019 21:23:48 -0400 Received: from mx1.redhat.com ([209.132.183.28]:56566 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731681AbfISBXr (ORCPT ); Wed, 18 Sep 2019 21:23:47 -0400 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 13411307CDEA; Thu, 19 Sep 2019 01:23:42 +0000 (UTC) Received: from madcap2.tricolour.ca (ovpn-112-19.phx2.redhat.com [10.3.112.19]) by smtp.corp.redhat.com (Postfix) with ESMTP id E3FD560C18; Thu, 19 Sep 2019 01:23:28 +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, dwalsh@redhat.com, mpatel@redhat.com, Richard Guy Briggs Subject: [PATCH ghak90 V7 02/21] audit: add container id Date: Wed, 18 Sep 2019 21:22:19 -0400 Message-Id: In-Reply-To: References: In-Reply-To: References: X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.49]); Thu, 19 Sep 2019 01:23:47 +0000 (UTC) Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org Implement the proc fs write to set the audit container identifier of a process, emitting an AUDIT_CONTAINER_OP record to document the event. This is a write from the container orchestrator task to a proc entry of the form /proc/PID/audit_containerid where PID is the process ID of the newly created task that is to become the first task in a container, or an additional task added to a container. The write expects up to a u64 value (unset: 18446744073709551615). The writer must have capability CAP_AUDIT_CONTROL. This will produce a record such as this: type=CONTAINER_OP msg=audit(2018-06-06 12:39:29.636:26949) : op=set opid=2209 contid=123456 old-contid=18446744073709551615 pid=628 auid=root uid=root tty=ttyS0 ses=1 subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 comm=bash exe=/usr/bin/bash res=yes The "op" field indicates an initial set. The "pid" to "ses" fields are the orchestrator while the "opid" field is the object's PID, the process being "contained". New and old audit container identifier values are given in the "contid" fields, while res indicates its success. It is not permitted to unset the audit container identifier. A child inherits its parent's audit container identifier. Please see the github audit kernel issue for the main feature: https://github.com/linux-audit/audit-kernel/issues/90 Please see the github audit userspace issue for supporting additions: https://github.com/linux-audit/audit-userspace/issues/51 Please see the github audit testsuiite issue for the test case: https://github.com/linux-audit/audit-testsuite/issues/64 Please see the github audit wiki for the feature overview: https://github.com/linux-audit/audit-kernel/wiki/RFE-Audit-Container-ID Signed-off-by: Richard Guy Briggs Acked-by: Serge Hallyn Acked-by: Steve Grubb Acked-by: Neil Horman Reviewed-by: Ondrej Mosnacek Signed-off-by: Richard Guy Briggs --- fs/proc/base.c | 36 +++++++++++++++++++++++ include/linux/audit.h | 25 ++++++++++++++++ include/uapi/linux/audit.h | 2 ++ kernel/audit.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++ kernel/audit.h | 1 + kernel/auditsc.c | 4 +++ 6 files changed, 141 insertions(+) diff --git a/fs/proc/base.c b/fs/proc/base.c index ebea9501afb8..e2e7c9f4702f 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -1307,6 +1307,40 @@ static ssize_t proc_sessionid_read(struct file * file, char __user * buf, .read = proc_sessionid_read, .llseek = generic_file_llseek, }; + +static ssize_t proc_contid_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + struct inode *inode = file_inode(file); + u64 contid; + int rv; + struct task_struct *task = get_proc_task(inode); + + if (!task) + return -ESRCH; + if (*ppos != 0) { + /* No partial writes. */ + put_task_struct(task); + return -EINVAL; + } + + rv = kstrtou64_from_user(buf, count, 10, &contid); + if (rv < 0) { + put_task_struct(task); + return rv; + } + + rv = audit_set_contid(task, contid); + put_task_struct(task); + if (rv < 0) + return rv; + return count; +} + +static const struct file_operations proc_contid_operations = { + .write = proc_contid_write, + .llseek = generic_file_llseek, +}; #endif #ifdef CONFIG_FAULT_INJECTION @@ -3067,6 +3101,7 @@ static int proc_stack_depth(struct seq_file *m, struct pid_namespace *ns, #ifdef CONFIG_AUDIT REG("loginuid", S_IWUSR|S_IRUGO, proc_loginuid_operations), REG("sessionid", S_IRUGO, proc_sessionid_operations), + REG("audit_containerid", S_IWUSR, proc_contid_operations), #endif #ifdef CONFIG_FAULT_INJECTION REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations), @@ -3467,6 +3502,7 @@ static int proc_tid_comm_permission(struct inode *inode, int mask) #ifdef CONFIG_AUDIT REG("loginuid", S_IWUSR|S_IRUGO, proc_loginuid_operations), REG("sessionid", S_IRUGO, proc_sessionid_operations), + REG("audit_containerid", S_IWUSR, proc_contid_operations), #endif #ifdef CONFIG_FAULT_INJECTION REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations), diff --git a/include/linux/audit.h b/include/linux/audit.h index 4fbda55f3cf2..f2e3b81f2942 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -98,6 +98,7 @@ struct audit_ntp_data { struct audit_task_info { kuid_t loginuid; unsigned int sessionid; + u64 contid; #ifdef CONFIG_AUDITSYSCALL struct audit_context *ctx; #endif @@ -198,6 +199,15 @@ static inline unsigned int audit_get_sessionid(struct task_struct *tsk) return tsk->audit->sessionid; } +extern int audit_set_contid(struct task_struct *tsk, u64 contid); + +static inline u64 audit_get_contid(struct task_struct *tsk) +{ + if (!tsk->audit) + return AUDIT_CID_UNSET; + return tsk->audit->contid; +} + extern u32 audit_enabled; extern int audit_signal_info(int sig, struct task_struct *t); @@ -262,6 +272,11 @@ static inline unsigned int audit_get_sessionid(struct task_struct *tsk) return AUDIT_SID_UNSET; } +static inline u64 audit_get_contid(struct task_struct *tsk) +{ + return AUDIT_CID_UNSET; +} + #define audit_enabled AUDIT_OFF static inline int audit_signal_info(int sig, struct task_struct *t) @@ -676,6 +691,16 @@ static inline bool audit_loginuid_set(struct task_struct *tsk) return uid_valid(audit_get_loginuid(tsk)); } +static inline bool audit_contid_valid(u64 contid) +{ + return contid != AUDIT_CID_UNSET; +} + +static inline bool audit_contid_set(struct task_struct *tsk) +{ + return audit_contid_valid(audit_get_contid(tsk)); +} + static inline void audit_log_string(struct audit_buffer *ab, const char *buf) { audit_log_n_string(ab, buf, strlen(buf)); diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h index c89c6495983d..5d0ea2a6783e 100644 --- a/include/uapi/linux/audit.h +++ b/include/uapi/linux/audit.h @@ -71,6 +71,7 @@ #define AUDIT_TTY_SET 1017 /* Set TTY auditing status */ #define AUDIT_SET_FEATURE 1018 /* Turn an audit feature on or off */ #define AUDIT_GET_FEATURE 1019 /* Get which features are enabled */ +#define AUDIT_CONTAINER_OP 1020 /* Define the container id and info */ #define AUDIT_FIRST_USER_MSG 1100 /* Userspace messages mostly uninteresting to kernel */ #define AUDIT_USER_AVC 1107 /* We filter this differently */ @@ -488,6 +489,7 @@ struct audit_tty_status { #define AUDIT_UID_UNSET (unsigned int)-1 #define AUDIT_SID_UNSET ((unsigned int)-1) +#define AUDIT_CID_UNSET ((u64)-1) /* audit_rule_data supports filter rules with both integer and string * fields. It corresponds with AUDIT_ADD_RULE, AUDIT_DEL_RULE and diff --git a/kernel/audit.c b/kernel/audit.c index 5b1c52bafaeb..a36ea57cbb61 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -231,6 +231,7 @@ int audit_alloc(struct task_struct *tsk) } info->loginuid = audit_get_loginuid(current); info->sessionid = audit_get_sessionid(current); + info->contid = audit_get_contid(current); tsk->audit = info; ret = audit_alloc_syscall(tsk); @@ -245,6 +246,7 @@ int audit_alloc(struct task_struct *tsk) struct audit_task_info init_struct_audit = { .loginuid = INVALID_UID, .sessionid = AUDIT_SID_UNSET, + .contid = AUDIT_CID_UNSET, #ifdef CONFIG_AUDITSYSCALL .ctx = NULL, #endif @@ -2354,6 +2356,77 @@ int audit_signal_info(int sig, struct task_struct *t) return audit_signal_info_syscall(t); } +/* + * audit_set_contid - set current task's audit contid + * @task: target task + * @contid: contid value + * + * Returns 0 on success, -EPERM on permission failure. + * + * Called (set) from fs/proc/base.c::proc_contid_write(). + */ +int audit_set_contid(struct task_struct *task, u64 contid) +{ + u64 oldcontid; + int rc = 0; + struct audit_buffer *ab; + uid_t uid; + struct tty_struct *tty; + char comm[sizeof(current->comm)]; + + task_lock(task); + /* Can't set if audit disabled */ + if (!task->audit) { + task_unlock(task); + return -ENOPROTOOPT; + } + oldcontid = audit_get_contid(task); + read_lock(&tasklist_lock); + /* Don't allow the audit containerid to be unset */ + if (!audit_contid_valid(contid)) + rc = -EINVAL; + /* if we don't have caps, reject */ + else if (!capable(CAP_AUDIT_CONTROL)) + rc = -EPERM; + /* if task has children or is not single-threaded, deny */ + else if (!list_empty(&task->children)) + rc = -EBUSY; + else if (!(thread_group_leader(task) && thread_group_empty(task))) + rc = -EALREADY; + /* if contid is already set, deny */ + else if (audit_contid_set(task)) + rc = -ECHILD; + read_unlock(&tasklist_lock); + if (!rc) + task->audit->contid = contid; + task_unlock(task); + + if (!audit_enabled) + return rc; + + ab = audit_log_start(audit_context(), GFP_KERNEL, AUDIT_CONTAINER_OP); + if (!ab) + return rc; + + uid = from_kuid(&init_user_ns, task_uid(current)); + tty = audit_get_tty(); + audit_log_format(ab, + "op=set opid=%d contid=%llu old-contid=%llu pid=%d uid=%u auid=%u tty=%s ses=%u", + task_tgid_nr(task), contid, oldcontid, + task_tgid_nr(current), uid, + from_kuid(&init_user_ns, audit_get_loginuid(current)), + tty ? tty_name(tty) : "(none)", + audit_get_sessionid(current)); + audit_put_tty(tty); + audit_log_task_context(ab); + audit_log_format(ab, " comm="); + audit_log_untrustedstring(ab, get_task_comm(comm, current)); + audit_log_d_path_exe(ab, current->mm); + audit_log_format(ab, " res=%d", !rc); + audit_log_end(ab); + return rc; +} + /** * audit_log_end - end one audit record * @ab: the audit_buffer diff --git a/kernel/audit.h b/kernel/audit.h index 7f623ef216e6..16bd03b88e0d 100644 --- a/kernel/audit.h +++ b/kernel/audit.h @@ -135,6 +135,7 @@ struct audit_context { kuid_t target_uid; unsigned int target_sessionid; u32 target_sid; + u64 target_cid; char target_comm[TASK_COMM_LEN]; struct audit_tree_refs *trees, *first_trees; diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 10679da36bb6..0e2d50533959 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -113,6 +113,7 @@ struct audit_aux_data_pids { kuid_t target_uid[AUDIT_AUX_PIDS]; unsigned int target_sessionid[AUDIT_AUX_PIDS]; u32 target_sid[AUDIT_AUX_PIDS]; + u64 target_cid[AUDIT_AUX_PIDS]; char target_comm[AUDIT_AUX_PIDS][TASK_COMM_LEN]; int pid_count; }; @@ -2375,6 +2376,7 @@ void __audit_ptrace(struct task_struct *t) context->target_uid = task_uid(t); context->target_sessionid = audit_get_sessionid(t); security_task_getsecid(t, &context->target_sid); + context->target_cid = audit_get_contid(t); memcpy(context->target_comm, t->comm, TASK_COMM_LEN); } @@ -2402,6 +2404,7 @@ int audit_signal_info_syscall(struct task_struct *t) ctx->target_uid = t_uid; ctx->target_sessionid = audit_get_sessionid(t); security_task_getsecid(t, &ctx->target_sid); + ctx->target_cid = audit_get_contid(t); memcpy(ctx->target_comm, t->comm, TASK_COMM_LEN); return 0; } @@ -2423,6 +2426,7 @@ int audit_signal_info_syscall(struct task_struct *t) axp->target_uid[axp->pid_count] = t_uid; axp->target_sessionid[axp->pid_count] = audit_get_sessionid(t); security_task_getsecid(t, &axp->target_sid[axp->pid_count]); + axp->target_cid[axp->pid_count] = audit_get_contid(t); memcpy(axp->target_comm[axp->pid_count], t->comm, TASK_COMM_LEN); axp->pid_count++; From patchwork Thu Sep 19 01:22:20 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Guy Briggs X-Patchwork-Id: 11151389 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 87982196C for ; Thu, 19 Sep 2019 01:24:00 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 7153D2196F for ; Thu, 19 Sep 2019 01:24:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731749AbfISBXz (ORCPT ); Wed, 18 Sep 2019 21:23:55 -0400 Received: from mx1.redhat.com ([209.132.183.28]:41778 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731729AbfISBXw (ORCPT ); Wed, 18 Sep 2019 21:23:52 -0400 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 016EE10DCC82; Thu, 19 Sep 2019 01:23:48 +0000 (UTC) Received: from madcap2.tricolour.ca (ovpn-112-19.phx2.redhat.com [10.3.112.19]) by smtp.corp.redhat.com (Postfix) with ESMTP id 7094960C44; Thu, 19 Sep 2019 01:23:42 +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, dwalsh@redhat.com, mpatel@redhat.com, Richard Guy Briggs Subject: [PATCH ghak90 V7 03/21] audit: read container ID of a process Date: Wed, 18 Sep 2019 21:22:20 -0400 Message-Id: In-Reply-To: References: In-Reply-To: References: X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.6.2 (mx1.redhat.com [10.5.110.64]); Thu, 19 Sep 2019 01:23:52 +0000 (UTC) Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org Add support for reading the audit container identifier from the proc filesystem. This is a read from the proc entry of the form /proc/PID/audit_containerid where PID is the process ID of the task whose audit container identifier is sought. The read expects up to a u64 value (unset: 18446744073709551615). This read requires CAP_AUDIT_CONTROL. Signed-off-by: Richard Guy Briggs Acked-by: Serge Hallyn Acked-by: Neil Horman Reviewed-by: Ondrej Mosnacek --- fs/proc/base.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/fs/proc/base.c b/fs/proc/base.c index e2e7c9f4702f..26091800180c 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -1224,7 +1224,7 @@ static ssize_t oom_score_adj_write(struct file *file, const char __user *buf, }; #ifdef CONFIG_AUDIT -#define TMPBUFLEN 11 +#define TMPBUFLEN 21 static ssize_t proc_loginuid_read(struct file * file, char __user * buf, size_t count, loff_t *ppos) { @@ -1308,6 +1308,24 @@ static ssize_t proc_sessionid_read(struct file * file, char __user * buf, .llseek = generic_file_llseek, }; +static ssize_t proc_contid_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + struct inode *inode = file_inode(file); + struct task_struct *task = get_proc_task(inode); + ssize_t length; + char tmpbuf[TMPBUFLEN]; + + if (!task) + return -ESRCH; + /* if we don't have caps, reject */ + if (!capable(CAP_AUDIT_CONTROL)) + return -EPERM; + length = scnprintf(tmpbuf, TMPBUFLEN, "%llu", audit_get_contid(task)); + put_task_struct(task); + return simple_read_from_buffer(buf, count, ppos, tmpbuf, length); +} + static ssize_t proc_contid_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { @@ -1338,6 +1356,7 @@ static ssize_t proc_contid_write(struct file *file, const char __user *buf, } static const struct file_operations proc_contid_operations = { + .read = proc_contid_read, .write = proc_contid_write, .llseek = generic_file_llseek, }; @@ -3101,7 +3120,7 @@ static int proc_stack_depth(struct seq_file *m, struct pid_namespace *ns, #ifdef CONFIG_AUDIT REG("loginuid", S_IWUSR|S_IRUGO, proc_loginuid_operations), REG("sessionid", S_IRUGO, proc_sessionid_operations), - REG("audit_containerid", S_IWUSR, proc_contid_operations), + REG("audit_containerid", S_IWUSR|S_IRUSR, proc_contid_operations), #endif #ifdef CONFIG_FAULT_INJECTION REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations), @@ -3502,7 +3521,7 @@ static int proc_tid_comm_permission(struct inode *inode, int mask) #ifdef CONFIG_AUDIT REG("loginuid", S_IWUSR|S_IRUGO, proc_loginuid_operations), REG("sessionid", S_IRUGO, proc_sessionid_operations), - REG("audit_containerid", S_IWUSR, proc_contid_operations), + REG("audit_containerid", S_IWUSR|S_IRUSR, proc_contid_operations), #endif #ifdef CONFIG_FAULT_INJECTION REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations), From patchwork Thu Sep 19 01:22:21 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Guy Briggs X-Patchwork-Id: 11151391 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 7A3591745 for ; Thu, 19 Sep 2019 01:24:17 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 5997821D56 for ; Thu, 19 Sep 2019 01:24:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731801AbfISBYJ (ORCPT ); Wed, 18 Sep 2019 21:24:09 -0400 Received: from mx1.redhat.com ([209.132.183.28]:48188 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731790AbfISBYJ (ORCPT ); Wed, 18 Sep 2019 21:24:09 -0400 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 7460E85539; Thu, 19 Sep 2019 01:24:05 +0000 (UTC) Received: from madcap2.tricolour.ca (ovpn-112-19.phx2.redhat.com [10.3.112.19]) by smtp.corp.redhat.com (Postfix) with ESMTP id 5EB9B60C18; Thu, 19 Sep 2019 01:23:48 +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, dwalsh@redhat.com, mpatel@redhat.com, Richard Guy Briggs Subject: [PATCH ghak90 V7 04/21] audit: convert to contid list to check for orch/engine ownership Date: Wed, 18 Sep 2019 21:22:21 -0400 Message-Id: <6fb4e270bfafef3d0477a06b0365fdcc5a5305b5.1568834524.git.rgb@redhat.com> In-Reply-To: References: In-Reply-To: References: X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.28]); Thu, 19 Sep 2019 01:24:08 +0000 (UTC) Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org Store the audit container identifier in a refcounted kernel object that is added to the master list of audit container identifiers. This will allow multiple container orchestrators/engines to work on the same machine without danger of inadvertantly re-using an existing identifier. It will also allow an orchestrator to inject a process into an existing container by checking if the original container owner is the one injecting the task. A hash table list is used to optimize searches. Signed-off-by: Richard Guy Briggs --- include/linux/audit.h | 26 ++++++++++++++-- kernel/audit.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++--- kernel/audit.h | 8 +++++ 3 files changed, 112 insertions(+), 8 deletions(-) diff --git a/include/linux/audit.h b/include/linux/audit.h index f2e3b81f2942..e317807cdd3e 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -95,10 +95,18 @@ struct audit_ntp_data { struct audit_ntp_data {}; #endif +struct audit_cont { + struct list_head list; + u64 id; + struct task_struct *owner; + refcount_t refcount; + struct rcu_head rcu; +}; + struct audit_task_info { kuid_t loginuid; unsigned int sessionid; - u64 contid; + struct audit_cont *cont; #ifdef CONFIG_AUDITSYSCALL struct audit_context *ctx; #endif @@ -203,11 +211,15 @@ static inline unsigned int audit_get_sessionid(struct task_struct *tsk) static inline u64 audit_get_contid(struct task_struct *tsk) { - if (!tsk->audit) + if (!tsk->audit || !tsk->audit->cont) return AUDIT_CID_UNSET; - return tsk->audit->contid; + return tsk->audit->cont->id; } +extern struct audit_cont *audit_cont(struct task_struct *tsk); + +extern void audit_cont_put(struct audit_cont *cont); + extern u32 audit_enabled; extern int audit_signal_info(int sig, struct task_struct *t); @@ -277,6 +289,14 @@ static inline u64 audit_get_contid(struct task_struct *tsk) return AUDIT_CID_UNSET; } +static inline struct audit_cont *audit_cont(struct task_struct *tsk) +{ + return NULL; +} + +static inline void audit_cont_put(struct audit_cont *cont) +{ } + #define audit_enabled AUDIT_OFF static inline int audit_signal_info(int sig, struct task_struct *t) diff --git a/kernel/audit.c b/kernel/audit.c index a36ea57cbb61..ea0899130cc1 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -137,6 +137,8 @@ struct audit_net { /* Hash for inode-based rules */ struct list_head audit_inode_hash[AUDIT_INODE_BUCKETS]; +/* Hash for contid-based rules */ +struct list_head audit_contid_hash[AUDIT_CONTID_BUCKETS]; static struct kmem_cache *audit_buffer_cache; @@ -204,6 +206,8 @@ struct audit_reply { static struct kmem_cache *audit_task_cache; +static DEFINE_SPINLOCK(audit_contid_list_lock); + void __init audit_task_init(void) { audit_task_cache = kmem_cache_create("audit_task", @@ -231,7 +235,9 @@ int audit_alloc(struct task_struct *tsk) } info->loginuid = audit_get_loginuid(current); info->sessionid = audit_get_sessionid(current); - info->contid = audit_get_contid(current); + info->cont = audit_cont(current); + if (info->cont) + refcount_inc(&info->cont->refcount); tsk->audit = info; ret = audit_alloc_syscall(tsk); @@ -246,7 +252,7 @@ int audit_alloc(struct task_struct *tsk) struct audit_task_info init_struct_audit = { .loginuid = INVALID_UID, .sessionid = AUDIT_SID_UNSET, - .contid = AUDIT_CID_UNSET, + .cont = NULL, #ifdef CONFIG_AUDITSYSCALL .ctx = NULL, #endif @@ -266,6 +272,9 @@ void audit_free(struct task_struct *tsk) /* Freeing the audit_task_info struct must be performed after * audit_log_exit() due to need for loginuid and sessionid. */ + spin_lock(&audit_contid_list_lock); + audit_cont_put(tsk->audit->cont); + spin_unlock(&audit_contid_list_lock); info = tsk->audit; tsk->audit = NULL; kmem_cache_free(audit_task_cache, info); @@ -1657,6 +1666,9 @@ static int __init audit_init(void) for (i = 0; i < AUDIT_INODE_BUCKETS; i++) INIT_LIST_HEAD(&audit_inode_hash[i]); + for (i = 0; i < AUDIT_CONTID_BUCKETS; i++) + INIT_LIST_HEAD(&audit_contid_hash[i]); + mutex_init(&audit_cmd_mutex.lock); audit_cmd_mutex.owner = NULL; @@ -2356,6 +2368,32 @@ int audit_signal_info(int sig, struct task_struct *t) return audit_signal_info_syscall(t); } +struct audit_cont *audit_cont(struct task_struct *tsk) +{ + if (!tsk->audit || !tsk->audit->cont) + return NULL; + return tsk->audit->cont; +} + +/* audit_contid_list_lock must be held by caller */ +void audit_cont_put(struct audit_cont *cont) +{ + if (!cont) + return; + if (refcount_dec_and_test(&cont->refcount)) { + put_task_struct(cont->owner); + list_del_rcu(&cont->list); + kfree_rcu(cont, rcu); + } +} + +static struct task_struct *audit_cont_owner(struct task_struct *tsk) +{ + if (tsk->audit && tsk->audit->cont) + return tsk->audit->cont->owner; + return NULL; +} + /* * audit_set_contid - set current task's audit contid * @task: target task @@ -2382,9 +2420,12 @@ int audit_set_contid(struct task_struct *task, u64 contid) } oldcontid = audit_get_contid(task); read_lock(&tasklist_lock); - /* Don't allow the audit containerid to be unset */ + /* Don't allow the contid to be unset */ if (!audit_contid_valid(contid)) rc = -EINVAL; + /* Don't allow the contid to be set to the same value again */ + else if (contid == oldcontid) { + rc = -EADDRINUSE; /* if we don't have caps, reject */ else if (!capable(CAP_AUDIT_CONTROL)) rc = -EPERM; @@ -2397,8 +2438,43 @@ int audit_set_contid(struct task_struct *task, u64 contid) else if (audit_contid_set(task)) rc = -ECHILD; read_unlock(&tasklist_lock); - if (!rc) - task->audit->contid = contid; + if (!rc) { + struct audit_cont *oldcont = audit_cont(task); + struct audit_cont *cont = NULL; + struct audit_cont *newcont = NULL; + int h = audit_hash_contid(contid); + + spin_lock(&audit_contid_list_lock); + list_for_each_entry_rcu(cont, &audit_contid_hash[h], list) + if (cont->id == contid) { + /* task injection to existing container */ + if (current == cont->owner) { + refcount_inc(&cont->refcount); + newcont = cont; + } else { + rc = -ENOTUNIQ; + goto conterror; + } + } + if (!newcont) { + newcont = kmalloc(sizeof(struct audit_cont), GFP_ATOMIC); + if (newcont) { + INIT_LIST_HEAD(&newcont->list); + newcont->id = contid; + get_task_struct(current); + newcont->owner = current; + refcount_set(&newcont->refcount, 1); + list_add_rcu(&newcont->list, &audit_contid_hash[h]); + } else { + rc = -ENOMEM; + goto conterror; + } + } + task->audit->cont = newcont; + audit_cont_put(oldcont); +conterror: + spin_unlock(&audit_contid_list_lock); + } task_unlock(task); if (!audit_enabled) diff --git a/kernel/audit.h b/kernel/audit.h index 16bd03b88e0d..e4a31aa92dfe 100644 --- a/kernel/audit.h +++ b/kernel/audit.h @@ -211,6 +211,14 @@ static inline int audit_hash_ino(u32 ino) return (ino & (AUDIT_INODE_BUCKETS-1)); } +#define AUDIT_CONTID_BUCKETS 32 +extern struct list_head audit_contid_hash[AUDIT_CONTID_BUCKETS]; + +static inline int audit_hash_contid(u64 contid) +{ + return (contid & (AUDIT_CONTID_BUCKETS-1)); +} + /* Indicates that audit should log the full pathname. */ #define AUDIT_NAME_FULL -1 From patchwork Thu Sep 19 01:22:22 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Guy Briggs X-Patchwork-Id: 11151393 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 70AB01745 for ; Thu, 19 Sep 2019 01:24:29 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 57FE42196F for ; Thu, 19 Sep 2019 01:24:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731880AbfISBYY (ORCPT ); Wed, 18 Sep 2019 21:24:24 -0400 Received: from mx1.redhat.com ([209.132.183.28]:55756 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726359AbfISBYY (ORCPT ); Wed, 18 Sep 2019 21:24:24 -0400 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 744B03082131; Thu, 19 Sep 2019 01:24:18 +0000 (UTC) Received: from madcap2.tricolour.ca (ovpn-112-19.phx2.redhat.com [10.3.112.19]) by smtp.corp.redhat.com (Postfix) with ESMTP id CEE7560C44; Thu, 19 Sep 2019 01:24:05 +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, dwalsh@redhat.com, mpatel@redhat.com, Richard Guy Briggs Subject: [PATCH ghak90 V7 05/21] audit: log drop of contid on exit of last task Date: Wed, 18 Sep 2019 21:22:22 -0400 Message-Id: <71b75f54342f32f176c2b6d94584f2a666964e68.1568834524.git.rgb@redhat.com> In-Reply-To: References: In-Reply-To: References: X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.42]); Thu, 19 Sep 2019 01:24:23 +0000 (UTC) Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org Since we are tracking the life of each audit container indentifier, we can match the creation event with the destruction event. Log the destruction of the audit container identifier when the last process in that container exits. Signed-off-by: Richard Guy Briggs --- kernel/audit.c | 32 ++++++++++++++++++++++++++++++++ kernel/audit.h | 2 ++ kernel/auditsc.c | 2 ++ 3 files changed, 36 insertions(+) diff --git a/kernel/audit.c b/kernel/audit.c index ea0899130cc1..53d13d638c63 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -2503,6 +2503,38 @@ int audit_set_contid(struct task_struct *task, u64 contid) return rc; } +void audit_log_container_drop(void) +{ + struct audit_buffer *ab; + uid_t uid; + struct tty_struct *tty; + char comm[sizeof(current->comm)]; + + if (!current->audit || !current->audit->cont || + refcount_read(¤t->audit->cont->refcount) > 1) + return; + ab = audit_log_start(audit_context(), GFP_KERNEL, AUDIT_CONTAINER_OP); + if (!ab) + return; + + uid = from_kuid(&init_user_ns, task_uid(current)); + tty = audit_get_tty(); + audit_log_format(ab, + "op=drop opid=%d contid=%llu old-contid=%llu pid=%d uid=%u auid=%u tty=%s ses=%u", + task_tgid_nr(current), audit_get_contid(current), + audit_get_contid(current), task_tgid_nr(current), uid, + from_kuid(&init_user_ns, audit_get_loginuid(current)), + tty ? tty_name(tty) : "(none)", + audit_get_sessionid(current)); + audit_put_tty(tty); + audit_log_task_context(ab); + audit_log_format(ab, " comm="); + audit_log_untrustedstring(ab, get_task_comm(comm, current)); + audit_log_d_path_exe(ab, current->mm); + audit_log_format(ab, " res=1"); + audit_log_end(ab); +} + /** * audit_log_end - end one audit record * @ab: the audit_buffer diff --git a/kernel/audit.h b/kernel/audit.h index e4a31aa92dfe..162de8366b32 100644 --- a/kernel/audit.h +++ b/kernel/audit.h @@ -255,6 +255,8 @@ extern void audit_log_d_path_exe(struct audit_buffer *ab, extern struct tty_struct *audit_get_tty(void); extern void audit_put_tty(struct tty_struct *tty); +extern void audit_log_container_drop(void); + /* audit watch/mark/tree functions */ #ifdef CONFIG_AUDITSYSCALL extern unsigned int audit_serial(void); diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 0e2d50533959..bd855794ad26 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -1568,6 +1568,8 @@ static void audit_log_exit(void) audit_log_proctitle(); + audit_log_container_drop(); + /* Send end of event record to help user space know we are finished */ ab = audit_log_start(context, GFP_KERNEL, AUDIT_EOE); if (ab) From patchwork Thu Sep 19 01:22:23 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Guy Briggs X-Patchwork-Id: 11151397 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id A7B001745 for ; Thu, 19 Sep 2019 01:24:46 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 9097521927 for ; Thu, 19 Sep 2019 01:24:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387457AbfISBYl (ORCPT ); Wed, 18 Sep 2019 21:24:41 -0400 Received: from mx1.redhat.com ([209.132.183.28]:55385 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726359AbfISBYk (ORCPT ); Wed, 18 Sep 2019 21:24:40 -0400 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 141B5C057F31; Thu, 19 Sep 2019 01:24:35 +0000 (UTC) Received: from madcap2.tricolour.ca (ovpn-112-19.phx2.redhat.com [10.3.112.19]) by smtp.corp.redhat.com (Postfix) with ESMTP id D1E7E60C18; Thu, 19 Sep 2019 01:24:18 +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, dwalsh@redhat.com, mpatel@redhat.com, Richard Guy Briggs Subject: [PATCH ghak90 V7 06/21] audit: contid limit of 32k imposed to avoid DoS Date: Wed, 18 Sep 2019 21:22:23 -0400 Message-Id: <230e91cd3e50a3d8015daac135c24c4c58cf0a21.1568834524.git.rgb@redhat.com> In-Reply-To: References: In-Reply-To: References: X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.32]); Thu, 19 Sep 2019 01:24:40 +0000 (UTC) Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org Set an arbitrary limit on the number of audit container identifiers to limit abuse. Signed-off-by: Richard Guy Briggs --- kernel/audit.c | 8 ++++++++ kernel/audit.h | 4 ++++ 2 files changed, 12 insertions(+) diff --git a/kernel/audit.c b/kernel/audit.c index 53d13d638c63..329916534dd2 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -139,6 +139,7 @@ struct audit_net { struct list_head audit_inode_hash[AUDIT_INODE_BUCKETS]; /* Hash for contid-based rules */ struct list_head audit_contid_hash[AUDIT_CONTID_BUCKETS]; +int audit_contid_count = 0; static struct kmem_cache *audit_buffer_cache; @@ -2384,6 +2385,7 @@ void audit_cont_put(struct audit_cont *cont) put_task_struct(cont->owner); list_del_rcu(&cont->list); kfree_rcu(cont, rcu); + audit_contid_count--; } } @@ -2456,6 +2458,11 @@ int audit_set_contid(struct task_struct *task, u64 contid) goto conterror; } } + /* Set max contids */ + if (audit_contid_count > AUDIT_CONTID_COUNT) { + rc = -ENOSPC; + goto conterror; + } if (!newcont) { newcont = kmalloc(sizeof(struct audit_cont), GFP_ATOMIC); if (newcont) { @@ -2465,6 +2472,7 @@ int audit_set_contid(struct task_struct *task, u64 contid) newcont->owner = current; refcount_set(&newcont->refcount, 1); list_add_rcu(&newcont->list, &audit_contid_hash[h]); + audit_contid_count++; } else { rc = -ENOMEM; goto conterror; diff --git a/kernel/audit.h b/kernel/audit.h index 162de8366b32..543f1334ba47 100644 --- a/kernel/audit.h +++ b/kernel/audit.h @@ -219,6 +219,10 @@ static inline int audit_hash_contid(u64 contid) return (contid & (AUDIT_CONTID_BUCKETS-1)); } +extern int audit_contid_count; + +#define AUDIT_CONTID_COUNT 1 << 16 + /* Indicates that audit should log the full pathname. */ #define AUDIT_NAME_FULL -1 From patchwork Thu Sep 19 01:22:24 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Guy Briggs X-Patchwork-Id: 11151403 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 0C56976 for ; Thu, 19 Sep 2019 01:24:53 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id DEB9E21925 for ; Thu, 19 Sep 2019 01:24:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387615AbfISBYr (ORCPT ); Wed, 18 Sep 2019 21:24:47 -0400 Received: from mx1.redhat.com ([209.132.183.28]:51352 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387561AbfISBYr (ORCPT ); Wed, 18 Sep 2019 21:24:47 -0400 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id E28493DE04; Thu, 19 Sep 2019 01:24:40 +0000 (UTC) Received: from madcap2.tricolour.ca (ovpn-112-19.phx2.redhat.com [10.3.112.19]) by smtp.corp.redhat.com (Postfix) with ESMTP id 71BED60C80; Thu, 19 Sep 2019 01:24:35 +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, dwalsh@redhat.com, mpatel@redhat.com, Richard Guy Briggs Subject: [PATCH ghak90 V7 07/21] audit: log container info of syscalls Date: Wed, 18 Sep 2019 21:22:24 -0400 Message-Id: <0c0cd13044a26d7e0a280efb7cbd39cfb5fdf4ed.1568834524.git.rgb@redhat.com> In-Reply-To: References: In-Reply-To: References: X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.29]); Thu, 19 Sep 2019 01:24:46 +0000 (UTC) Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org Create a new audit record AUDIT_CONTAINER_ID to document the audit container identifier of a process if it is present. Called from audit_log_exit(), syscalls are covered. A sample raw event: type=SYSCALL msg=audit(1519924845.499:257): arch=c000003e syscall=257 success=yes exit=3 a0=ffffff9c a1=56374e1cef30 a2=241 a3=1b6 items=2 ppid=606 pid=635 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts0 ses=3 comm="bash" exe="/usr/bin/bash" subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 key="tmpcontainerid" type=CWD msg=audit(1519924845.499:257): cwd="/root" type=PATH msg=audit(1519924845.499:257): item=0 name="/tmp/" inode=13863 dev=00:27 mode=041777 ouid=0 ogid=0 rdev=00:00 obj=system_u:object_r:tmp_t:s0 nametype= PARENT cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 type=PATH msg=audit(1519924845.499:257): item=1 name="/tmp/tmpcontainerid" inode=17729 dev=00:27 mode=0100644 ouid=0 ogid=0 rdev=00:00 obj=unconfined_u:object_r:user_tmp_t:s0 nametype=CREATE cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 type=PROCTITLE msg=audit(1519924845.499:257): proctitle=62617368002D6300736C65657020313B206563686F2074657374203E202F746D702F746D70636F6E7461696E65726964 type=CONTAINER_ID msg=audit(1519924845.499:257): contid=123458 Please see the github audit kernel issue for the main feature: https://github.com/linux-audit/audit-kernel/issues/90 Please see the github audit userspace issue for supporting additions: https://github.com/linux-audit/audit-userspace/issues/51 Please see the github audit testsuiite issue for the test case: https://github.com/linux-audit/audit-testsuite/issues/64 Please see the github audit wiki for the feature overview: https://github.com/linux-audit/audit-kernel/wiki/RFE-Audit-Container-ID Signed-off-by: Richard Guy Briggs Acked-by: Serge Hallyn Acked-by: Steve Grubb Acked-by: Neil Horman Reviewed-by: Ondrej Mosnacek --- include/linux/audit.h | 5 +++++ include/uapi/linux/audit.h | 1 + kernel/audit.c | 20 ++++++++++++++++++++ kernel/auditsc.c | 20 ++++++++++++++------ 4 files changed, 40 insertions(+), 6 deletions(-) diff --git a/include/linux/audit.h b/include/linux/audit.h index e317807cdd3e..0c18d8e30620 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -220,6 +220,8 @@ static inline u64 audit_get_contid(struct task_struct *tsk) extern void audit_cont_put(struct audit_cont *cont); +extern void audit_log_container_id(struct audit_context *context, u64 contid); + extern u32 audit_enabled; extern int audit_signal_info(int sig, struct task_struct *t); @@ -297,6 +299,9 @@ static inline struct audit_cont *audit_cont(struct task_struct *tsk) static inline void audit_cont_put(struct audit_cont *cont) { } +static inline void audit_log_container_id(struct audit_context *context, u64 contid) +{ } + #define audit_enabled AUDIT_OFF static inline int audit_signal_info(int sig, struct task_struct *t) diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h index 5d0ea2a6783e..4ed080f28b47 100644 --- a/include/uapi/linux/audit.h +++ b/include/uapi/linux/audit.h @@ -117,6 +117,7 @@ #define AUDIT_FANOTIFY 1331 /* Fanotify access decision */ #define AUDIT_TIME_INJOFFSET 1332 /* Timekeeping offset injected */ #define AUDIT_TIME_ADJNTPVAL 1333 /* NTP value adjustment */ +#define AUDIT_CONTAINER_ID 1334 /* Container ID */ #define AUDIT_AVC 1400 /* SE Linux avc denial or grant */ #define AUDIT_SELINUX_ERR 1401 /* Internal SE Linux Errors */ diff --git a/kernel/audit.c b/kernel/audit.c index 329916534dd2..adfb3e6a7f0c 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -2127,6 +2127,26 @@ void audit_log_session_info(struct audit_buffer *ab) audit_log_format(ab, "auid=%u ses=%u", auid, sessionid); } +/* + * audit_log_container_id - report container info + * @context: task or local context for record + * @contid: container ID to report + */ +void audit_log_container_id(struct audit_context *context, u64 contid) +{ + struct audit_buffer *ab; + + if (!audit_contid_valid(contid)) + return; + /* Generate AUDIT_CONTAINER_ID record with container ID */ + ab = audit_log_start(context, GFP_KERNEL, AUDIT_CONTAINER_ID); + if (!ab) + return; + audit_log_format(ab, "contid=%llu", contid); + audit_log_end(ab); +} +EXPORT_SYMBOL(audit_log_container_id); + void audit_log_key(struct audit_buffer *ab, char *key) { audit_log_format(ab, " key="); diff --git a/kernel/auditsc.c b/kernel/auditsc.c index bd855794ad26..ac438fcff807 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -1534,7 +1534,7 @@ static void audit_log_exit(void) for (aux = context->aux_pids; aux; aux = aux->next) { struct audit_aux_data_pids *axs = (void *)aux; - for (i = 0; i < axs->pid_count; i++) + for (i = 0; i < axs->pid_count; i++) { if (audit_log_pid_context(context, axs->target_pid[i], axs->target_auid[i], axs->target_uid[i], @@ -1542,14 +1542,20 @@ static void audit_log_exit(void) axs->target_sid[i], axs->target_comm[i])) call_panic = 1; + audit_log_container_id(context, axs->target_cid[i]); + } } - if (context->target_pid && - audit_log_pid_context(context, context->target_pid, - context->target_auid, context->target_uid, - context->target_sessionid, - context->target_sid, context->target_comm)) + if (context->target_pid) { + if (audit_log_pid_context(context, context->target_pid, + context->target_auid, + context->target_uid, + context->target_sessionid, + context->target_sid, + context->target_comm)) call_panic = 1; + audit_log_container_id(context, context->target_cid); + } if (context->pwd.dentry && context->pwd.mnt) { ab = audit_log_start(context, GFP_KERNEL, AUDIT_CWD); @@ -1568,6 +1574,8 @@ static void audit_log_exit(void) audit_log_proctitle(); + audit_log_container_id(context, audit_get_contid(current)); + audit_log_container_drop(); /* Send end of event record to help user space know we are finished */ From patchwork Thu Sep 19 01:22:25 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Guy Briggs X-Patchwork-Id: 11151411 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 38D05196C for ; Thu, 19 Sep 2019 01:25:14 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 16E3121929 for ; Thu, 19 Sep 2019 01:25:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387714AbfISBZJ (ORCPT ); Wed, 18 Sep 2019 21:25:09 -0400 Received: from mx1.redhat.com ([209.132.183.28]:54294 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387648AbfISBZI (ORCPT ); Wed, 18 Sep 2019 21:25:08 -0400 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id A9C6E5945E; Thu, 19 Sep 2019 01:25:03 +0000 (UTC) Received: from madcap2.tricolour.ca (ovpn-112-19.phx2.redhat.com [10.3.112.19]) by smtp.corp.redhat.com (Postfix) with ESMTP id 4C6F860C18; Thu, 19 Sep 2019 01:24:41 +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, dwalsh@redhat.com, mpatel@redhat.com, Richard Guy Briggs Subject: [PATCH ghak90 V7 08/21] audit: add contid support for signalling the audit daemon Date: Wed, 18 Sep 2019 21:22:25 -0400 Message-Id: <0850eaa785e2ff30c8c4818fd53e9544b34ed884.1568834524.git.rgb@redhat.com> In-Reply-To: References: In-Reply-To: References: X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Thu, 19 Sep 2019 01:25:08 +0000 (UTC) Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org Add audit container identifier support to the action of signalling the audit daemon. Since this would need to add an element to the audit_sig_info struct, a new record type AUDIT_SIGNAL_INFO2 was created with a new audit_sig_info2 struct. Corresponding support is required in the userspace code to reflect the new record request and reply type. An older userspace won't break since it won't know to request this record type. Signed-off-by: Richard Guy Briggs --- include/linux/audit.h | 7 +++++++ include/uapi/linux/audit.h | 1 + kernel/audit.c | 28 ++++++++++++++++++++++++++++ kernel/audit.h | 1 + security/selinux/nlmsgtab.c | 1 + 5 files changed, 38 insertions(+) diff --git a/include/linux/audit.h b/include/linux/audit.h index 0c18d8e30620..7b640c4da4ee 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -23,6 +23,13 @@ struct audit_sig_info { char ctx[0]; }; +struct audit_sig_info2 { + uid_t uid; + pid_t pid; + u64 cid; + char ctx[0]; +}; + struct audit_buffer; struct audit_context; struct inode; diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h index 4ed080f28b47..693ec6e0288b 100644 --- a/include/uapi/linux/audit.h +++ b/include/uapi/linux/audit.h @@ -72,6 +72,7 @@ #define AUDIT_SET_FEATURE 1018 /* Turn an audit feature on or off */ #define AUDIT_GET_FEATURE 1019 /* Get which features are enabled */ #define AUDIT_CONTAINER_OP 1020 /* Define the container id and info */ +#define AUDIT_SIGNAL_INFO2 1021 /* Get info auditd signal sender */ #define AUDIT_FIRST_USER_MSG 1100 /* Userspace messages mostly uninteresting to kernel */ #define AUDIT_USER_AVC 1107 /* We filter this differently */ diff --git a/kernel/audit.c b/kernel/audit.c index adfb3e6a7f0c..df3db29f5a8a 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -125,6 +125,7 @@ struct audit_net { kuid_t audit_sig_uid = INVALID_UID; pid_t audit_sig_pid = -1; u32 audit_sig_sid = 0; +u64 audit_sig_cid = AUDIT_CID_UNSET; /* Records can be lost in several ways: 0) [suppressed in audit_alloc] @@ -1094,6 +1095,7 @@ static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type) case AUDIT_ADD_RULE: case AUDIT_DEL_RULE: case AUDIT_SIGNAL_INFO: + case AUDIT_SIGNAL_INFO2: case AUDIT_TTY_GET: case AUDIT_TTY_SET: case AUDIT_TRIM: @@ -1257,6 +1259,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) struct audit_buffer *ab; u16 msg_type = nlh->nlmsg_type; struct audit_sig_info *sig_data; + struct audit_sig_info2 *sig_data2; char *ctx = NULL; u32 len; @@ -1516,6 +1519,30 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) sig_data, sizeof(*sig_data) + len); kfree(sig_data); break; + case AUDIT_SIGNAL_INFO2: + len = 0; + if (audit_sig_sid) { + err = security_secid_to_secctx(audit_sig_sid, &ctx, &len); + if (err) + return err; + } + sig_data2 = kmalloc(sizeof(*sig_data2) + len, GFP_KERNEL); + if (!sig_data2) { + if (audit_sig_sid) + security_release_secctx(ctx, len); + return -ENOMEM; + } + sig_data2->uid = from_kuid(&init_user_ns, audit_sig_uid); + sig_data2->pid = audit_sig_pid; + if (audit_sig_sid) { + memcpy(sig_data2->ctx, ctx, len); + security_release_secctx(ctx, len); + } + sig_data2->cid = audit_sig_cid; + audit_send_reply(skb, seq, AUDIT_SIGNAL_INFO2, 0, 0, + sig_data2, sizeof(*sig_data2) + len); + kfree(sig_data2); + break; case AUDIT_TTY_GET: { struct audit_tty_status s; unsigned int t; @@ -2384,6 +2411,7 @@ int audit_signal_info(int sig, struct task_struct *t) else audit_sig_uid = uid; security_task_getsecid(current, &audit_sig_sid); + audit_sig_cid = audit_get_contid(current); } return audit_signal_info_syscall(t); diff --git a/kernel/audit.h b/kernel/audit.h index 543f1334ba47..c9a118716ced 100644 --- a/kernel/audit.h +++ b/kernel/audit.h @@ -350,6 +350,7 @@ static inline int audit_signal_info_syscall(struct task_struct *t) extern pid_t audit_sig_pid; extern kuid_t audit_sig_uid; extern u32 audit_sig_sid; +extern u64 audit_sig_cid; extern int audit_filter(int msgtype, unsigned int listtype); diff --git a/security/selinux/nlmsgtab.c b/security/selinux/nlmsgtab.c index 58345ba0528e..bf21979e7737 100644 --- a/security/selinux/nlmsgtab.c +++ b/security/selinux/nlmsgtab.c @@ -132,6 +132,7 @@ struct nlmsg_perm { { AUDIT_DEL_RULE, NETLINK_AUDIT_SOCKET__NLMSG_WRITE }, { AUDIT_USER, NETLINK_AUDIT_SOCKET__NLMSG_RELAY }, { AUDIT_SIGNAL_INFO, NETLINK_AUDIT_SOCKET__NLMSG_READ }, + { AUDIT_SIGNAL_INFO2, NETLINK_AUDIT_SOCKET__NLMSG_READ }, { AUDIT_TRIM, NETLINK_AUDIT_SOCKET__NLMSG_WRITE }, { AUDIT_MAKE_EQUIV, NETLINK_AUDIT_SOCKET__NLMSG_WRITE }, { AUDIT_TTY_GET, NETLINK_AUDIT_SOCKET__NLMSG_READ }, From patchwork Thu Sep 19 01:22:26 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Guy Briggs X-Patchwork-Id: 11151419 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D34CE76 for ; Thu, 19 Sep 2019 01:25:40 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id B2FFC2196F for ; Thu, 19 Sep 2019 01:25:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731924AbfISBZf (ORCPT ); Wed, 18 Sep 2019 21:25:35 -0400 Received: from mx1.redhat.com ([209.132.183.28]:42350 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726257AbfISBZf (ORCPT ); Wed, 18 Sep 2019 21:25:35 -0400 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 6D7EF2A09B1; Thu, 19 Sep 2019 01:25:31 +0000 (UTC) Received: from madcap2.tricolour.ca (ovpn-112-19.phx2.redhat.com [10.3.112.19]) by smtp.corp.redhat.com (Postfix) with ESMTP id 0EB1B60C83; Thu, 19 Sep 2019 01:25:03 +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, dwalsh@redhat.com, mpatel@redhat.com, Richard Guy Briggs Subject: [PATCH ghak90 V7 09/21] audit: add support for non-syscall auxiliary records Date: Wed, 18 Sep 2019 21:22:26 -0400 Message-Id: In-Reply-To: References: In-Reply-To: References: X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Thu, 19 Sep 2019 01:25:34 +0000 (UTC) Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org Standalone audit records have the timestamp and serial number generated on the fly and as such are unique, making them standalone. This new function audit_alloc_local() generates a local audit context that will be used only for a standalone record and its auxiliary record(s). The context is discarded immediately after the local associated records are produced. Signed-off-by: Richard Guy Briggs Acked-by: Serge Hallyn Acked-by: Neil Horman Reviewed-by: Ondrej Mosnacek --- include/linux/audit.h | 8 ++++++++ kernel/audit.h | 1 + kernel/auditsc.c | 35 ++++++++++++++++++++++++++++++----- 3 files changed, 39 insertions(+), 5 deletions(-) diff --git a/include/linux/audit.h b/include/linux/audit.h index 7b640c4da4ee..e849058cb662 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -329,6 +329,8 @@ static inline int audit_signal_info(int sig, struct task_struct *t) /* These are defined in auditsc.c */ /* Public API */ +extern struct audit_context *audit_alloc_local(gfp_t gfpflags); +extern void audit_free_context(struct audit_context *context); 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); @@ -591,6 +593,12 @@ static inline void audit_ntp_log(const struct audit_ntp_data *ad) extern int audit_n_rules; extern int audit_signals; #else /* CONFIG_AUDITSYSCALL */ +static inline struct audit_context *audit_alloc_local(gfp_t gfpflags) +{ + return NULL; +} +static inline void audit_free_context(struct audit_context *context) +{ } static inline void audit_syscall_entry(int major, unsigned long a0, unsigned long a1, unsigned long a2, unsigned long a3) diff --git a/kernel/audit.h b/kernel/audit.h index c9a118716ced..1bba13bdffd0 100644 --- a/kernel/audit.h +++ b/kernel/audit.h @@ -98,6 +98,7 @@ struct audit_proctitle { struct audit_context { int dummy; /* must be the first element */ int in_syscall; /* 1 if task is in a syscall */ + bool local; /* local context needed */ enum audit_state state, current_state; unsigned int serial; /* serial number for record */ int major; /* syscall number */ diff --git a/kernel/auditsc.c b/kernel/auditsc.c index ac438fcff807..3138c88887c7 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -890,11 +890,13 @@ static inline void audit_free_aux(struct audit_context *context) } } -static inline struct audit_context *audit_alloc_context(enum audit_state state) +static inline struct audit_context *audit_alloc_context(enum audit_state state, + gfp_t gfpflags) { struct audit_context *context; - context = kzalloc(sizeof(*context), GFP_KERNEL); + /* We can be called in atomic context via audit_tg() */ + context = kzalloc(sizeof(*context), gfpflags); if (!context) return NULL; context->state = state; @@ -930,7 +932,8 @@ int audit_alloc_syscall(struct task_struct *tsk) return 0; } - if (!(context = audit_alloc_context(state))) { + context = audit_alloc_context(state, GFP_KERNEL); + if (!context) { kfree(key); audit_log_lost("out of memory in audit_alloc_syscall"); return -ENOMEM; @@ -942,8 +945,29 @@ int audit_alloc_syscall(struct task_struct *tsk) return 0; } -static inline void audit_free_context(struct audit_context *context) +struct audit_context *audit_alloc_local(gfp_t gfpflags) { + struct audit_context *context = NULL; + + if (!audit_ever_enabled) + goto out; /* Return if not auditing. */ + context = audit_alloc_context(AUDIT_RECORD_CONTEXT, gfpflags); + if (!context) { + audit_log_lost("out of memory in audit_alloc_local"); + goto out; + } + context->serial = audit_serial(); + ktime_get_coarse_real_ts64(&context->ctime); + context->local = true; +out: + return context; +} +EXPORT_SYMBOL(audit_alloc_local); + +void audit_free_context(struct audit_context *context) +{ + if (!context) + return; audit_free_module(context); audit_free_names(context); unroll_tree_refs(context, NULL, 0); @@ -954,6 +978,7 @@ static inline void audit_free_context(struct audit_context *context) audit_proctitle_free(context); kfree(context); } +EXPORT_SYMBOL(audit_free_context); static int audit_log_pid_context(struct audit_context *context, pid_t pid, kuid_t auid, kuid_t uid, unsigned int sessionid, @@ -2182,7 +2207,7 @@ void __audit_inode_child(struct inode *parent, int auditsc_get_stamp(struct audit_context *ctx, struct timespec64 *t, unsigned int *serial) { - if (!ctx->in_syscall) + if (!ctx->in_syscall && !ctx->local) return 0; if (!ctx->serial) ctx->serial = audit_serial(); From patchwork Thu Sep 19 01:22:27 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Guy Briggs X-Patchwork-Id: 11151425 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 4690D1745 for ; Thu, 19 Sep 2019 01:26:03 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 2FA7D206C2 for ; Thu, 19 Sep 2019 01:26:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731956AbfISBZ6 (ORCPT ); Wed, 18 Sep 2019 21:25:58 -0400 Received: from mx1.redhat.com ([209.132.183.28]:53330 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726257AbfISBZ5 (ORCPT ); Wed, 18 Sep 2019 21:25:57 -0400 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 8AFF47FDCD; Thu, 19 Sep 2019 01:25:52 +0000 (UTC) Received: from madcap2.tricolour.ca (ovpn-112-19.phx2.redhat.com [10.3.112.19]) by smtp.corp.redhat.com (Postfix) with ESMTP id CF49160F88; Thu, 19 Sep 2019 01:25:31 +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, dwalsh@redhat.com, mpatel@redhat.com, Richard Guy Briggs Subject: [PATCH ghak90 V7 10/21] audit: add containerid support for user records Date: Wed, 18 Sep 2019 21:22:27 -0400 Message-Id: In-Reply-To: References: In-Reply-To: References: X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.27]); Thu, 19 Sep 2019 01:25:57 +0000 (UTC) Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org Add audit container identifier auxiliary record to user event standalone records. Signed-off-by: Richard Guy Briggs Acked-by: Neil Horman Reviewed-by: Ondrej Mosnacek --- kernel/audit.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/kernel/audit.c b/kernel/audit.c index df3db29f5a8a..7cdb76b38966 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -1140,12 +1140,6 @@ static void audit_log_common_recv_msg(struct audit_context *context, audit_log_task_context(*ab); } -static inline void audit_log_user_recv_msg(struct audit_buffer **ab, - u16 msg_type) -{ - audit_log_common_recv_msg(NULL, ab, msg_type); -} - int is_audit_feature_set(int i) { return af.features & AUDIT_FEATURE_TO_MASK(i); @@ -1408,13 +1402,16 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) err = audit_filter(msg_type, AUDIT_FILTER_USER); if (err == 1) { /* match or error */ + struct audit_context *context; + err = 0; if (msg_type == AUDIT_USER_TTY) { err = tty_audit_push(); if (err) break; } - audit_log_user_recv_msg(&ab, msg_type); + context = audit_alloc_local(GFP_KERNEL); + audit_log_common_recv_msg(context, &ab, msg_type); if (msg_type != AUDIT_USER_TTY) audit_log_format(ab, " msg='%.*s'", AUDIT_MESSAGE_TEXT_MAX, @@ -1430,6 +1427,8 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) audit_log_n_untrustedstring(ab, data, size); } audit_log_end(ab); + audit_log_container_id(context, audit_get_contid(current)); + audit_free_context(context); } break; case AUDIT_ADD_RULE: From patchwork Thu Sep 19 01:22:28 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Guy Briggs X-Patchwork-Id: 11151427 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 2E54976 for ; Thu, 19 Sep 2019 01:26:10 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 0CC5121927 for ; Thu, 19 Sep 2019 01:26:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731804AbfISB0E (ORCPT ); Wed, 18 Sep 2019 21:26:04 -0400 Received: from mx1.redhat.com ([209.132.183.28]:49990 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726257AbfISB0E (ORCPT ); Wed, 18 Sep 2019 21:26:04 -0400 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 81C223084037; Thu, 19 Sep 2019 01:25:58 +0000 (UTC) Received: from madcap2.tricolour.ca (ovpn-112-19.phx2.redhat.com [10.3.112.19]) by smtp.corp.redhat.com (Postfix) with ESMTP id E686960C18; Thu, 19 Sep 2019 01:25:52 +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, dwalsh@redhat.com, mpatel@redhat.com, Richard Guy Briggs Subject: [PATCH ghak90 V7 11/21] audit: add containerid filtering Date: Wed, 18 Sep 2019 21:22:28 -0400 Message-Id: <633a524e221e73cf3d665e589d14c025dd0a3f10.1568834524.git.rgb@redhat.com> In-Reply-To: References: In-Reply-To: References: X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.40]); Thu, 19 Sep 2019 01:26:03 +0000 (UTC) Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org Implement audit container identifier filtering using the AUDIT_CONTID field name to send an 8-character string representing a u64 since the value field is only u32. Sending it as two u32 was considered, but gathering and comparing two fields was more complex. The feature indicator is AUDIT_FEATURE_BITMAP_CONTAINERID. Please see the github audit kernel issue for the contid filter feature: https://github.com/linux-audit/audit-kernel/issues/91 Please see the github audit userspace issue for filter additions: https://github.com/linux-audit/audit-userspace/issues/40 Please see the github audit testsuiite issue for the test case: https://github.com/linux-audit/audit-testsuite/issues/64 Please see the github audit wiki for the feature overview: https://github.com/linux-audit/audit-kernel/wiki/RFE-Audit-Container-ID Signed-off-by: Richard Guy Briggs Acked-by: Serge Hallyn Acked-by: Neil Horman Reviewed-by: Ondrej Mosnacek --- include/linux/audit.h | 1 + include/uapi/linux/audit.h | 5 ++++- kernel/audit.h | 1 + kernel/auditfilter.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ kernel/auditsc.c | 4 ++++ 5 files changed, 56 insertions(+), 1 deletion(-) diff --git a/include/linux/audit.h b/include/linux/audit.h index e849058cb662..575fff6ea7c9 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -69,6 +69,7 @@ struct audit_field { u32 type; union { u32 val; + u64 val64; kuid_t uid; kgid_t gid; struct { diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h index 693ec6e0288b..f34108759e8f 100644 --- a/include/uapi/linux/audit.h +++ b/include/uapi/linux/audit.h @@ -268,6 +268,7 @@ #define AUDIT_LOGINUID_SET 24 #define AUDIT_SESSIONID 25 /* Session ID */ #define AUDIT_FSTYPE 26 /* FileSystem Type */ +#define AUDIT_CONTID 27 /* Container ID */ /* These are ONLY useful when checking * at syscall exit time (AUDIT_AT_EXIT). */ @@ -349,6 +350,7 @@ enum { #define AUDIT_FEATURE_BITMAP_SESSIONID_FILTER 0x00000010 #define AUDIT_FEATURE_BITMAP_LOST_RESET 0x00000020 #define AUDIT_FEATURE_BITMAP_FILTER_FS 0x00000040 +#define AUDIT_FEATURE_BITMAP_CONTAINERID 0x00000080 #define AUDIT_FEATURE_BITMAP_ALL (AUDIT_FEATURE_BITMAP_BACKLOG_LIMIT | \ AUDIT_FEATURE_BITMAP_BACKLOG_WAIT_TIME | \ @@ -356,7 +358,8 @@ enum { AUDIT_FEATURE_BITMAP_EXCLUDE_EXTEND | \ AUDIT_FEATURE_BITMAP_SESSIONID_FILTER | \ AUDIT_FEATURE_BITMAP_LOST_RESET | \ - AUDIT_FEATURE_BITMAP_FILTER_FS) + AUDIT_FEATURE_BITMAP_FILTER_FS | \ + AUDIT_FEATURE_BITMAP_CONTAINERID) /* deprecated: AUDIT_VERSION_* */ #define AUDIT_VERSION_LATEST AUDIT_FEATURE_BITMAP_ALL diff --git a/kernel/audit.h b/kernel/audit.h index 1bba13bdffd0..c9b73abfd6a0 100644 --- a/kernel/audit.h +++ b/kernel/audit.h @@ -229,6 +229,7 @@ static inline int audit_hash_contid(u64 contid) extern int audit_match_class(int class, unsigned syscall); extern int audit_comparator(const u32 left, const u32 op, const u32 right); +extern int audit_comparator64(const u64 left, const u32 op, const u64 right); extern int audit_uid_comparator(kuid_t left, u32 op, kuid_t right); extern int audit_gid_comparator(kgid_t left, u32 op, kgid_t right); extern int parent_len(const char *path); diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index b0126e9c0743..9606f973fe33 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c @@ -399,6 +399,7 @@ static int audit_field_valid(struct audit_entry *entry, struct audit_field *f) case AUDIT_FILETYPE: case AUDIT_FIELD_COMPARE: case AUDIT_EXE: + case AUDIT_CONTID: /* only equal and not equal valid ops */ if (f->op != Audit_not_equal && f->op != Audit_equal) return -EINVAL; @@ -586,6 +587,14 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, } entry->rule.exe = audit_mark; break; + case AUDIT_CONTID: + if (f->val != sizeof(u64)) + goto exit_free; + str = audit_unpack_string(&bufp, &remain, f->val); + if (IS_ERR(str)) + goto exit_free; + f->val64 = ((u64 *)str)[0]; + break; } } @@ -668,6 +677,11 @@ static struct audit_rule_data *audit_krule_to_data(struct audit_krule *krule) data->buflen += data->values[i] = audit_pack_string(&bufp, audit_mark_path(krule->exe)); break; + case AUDIT_CONTID: + data->buflen += data->values[i] = sizeof(u64); + memcpy(bufp, &f->val64, sizeof(u64)); + bufp += sizeof(u64); + break; case AUDIT_LOGINUID_SET: if (krule->pflags & AUDIT_LOGINUID_LEGACY && !f->val) { data->fields[i] = AUDIT_LOGINUID; @@ -754,6 +768,10 @@ static int audit_compare_rule(struct audit_krule *a, struct audit_krule *b) if (!gid_eq(a->fields[i].gid, b->fields[i].gid)) return 1; break; + case AUDIT_CONTID: + if (a->fields[i].val64 != b->fields[i].val64) + return 1; + break; default: if (a->fields[i].val != b->fields[i].val) return 1; @@ -1211,6 +1229,30 @@ int audit_comparator(u32 left, u32 op, u32 right) } } +int audit_comparator64(u64 left, u32 op, u64 right) +{ + switch (op) { + case Audit_equal: + return (left == right); + case Audit_not_equal: + return (left != right); + case Audit_lt: + return (left < right); + case Audit_le: + return (left <= right); + case Audit_gt: + return (left > right); + case Audit_ge: + return (left >= right); + case Audit_bitmask: + return (left & right); + case Audit_bittest: + return ((left & right) == right); + default: + return 0; + } +} + int audit_uid_comparator(kuid_t left, u32 op, kuid_t right) { switch (op) { @@ -1345,6 +1387,10 @@ int audit_filter(int msgtype, unsigned int listtype) result = audit_comparator(audit_loginuid_set(current), f->op, f->val); break; + case AUDIT_CONTID: + result = audit_comparator64(audit_get_contid(current), + f->op, f->val64); + break; case AUDIT_MSGTYPE: result = audit_comparator(msgtype, f->op, f->val); break; diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 3138c88887c7..a658fe775b86 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -629,6 +629,10 @@ static int audit_filter_rules(struct task_struct *tsk, result = audit_comparator(ctx->sockaddr->ss_family, f->op, f->val); break; + case AUDIT_CONTID: + result = audit_comparator64(audit_get_contid(tsk), + f->op, f->val64); + break; case AUDIT_SUBJ_USER: case AUDIT_SUBJ_ROLE: case AUDIT_SUBJ_TYPE: From patchwork Thu Sep 19 01:22:29 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Guy Briggs X-Patchwork-Id: 11151431 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id DD3BB1745 for ; Thu, 19 Sep 2019 01:26:24 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id B2C3821A49 for ; Thu, 19 Sep 2019 01:26:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387743AbfISB0T (ORCPT ); Wed, 18 Sep 2019 21:26:19 -0400 Received: from mx1.redhat.com ([209.132.183.28]:24952 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726257AbfISB0T (ORCPT ); Wed, 18 Sep 2019 21:26:19 -0400 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 7C67D307CDEA; Thu, 19 Sep 2019 01:26:13 +0000 (UTC) Received: from madcap2.tricolour.ca (ovpn-112-19.phx2.redhat.com [10.3.112.19]) by smtp.corp.redhat.com (Postfix) with ESMTP id DE43160C5D; Thu, 19 Sep 2019 01:25:58 +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, dwalsh@redhat.com, mpatel@redhat.com, Richard Guy Briggs Subject: [PATCH ghak90 V7 12/21] audit: add support for containerid to network namespaces Date: Wed, 18 Sep 2019 21:22:29 -0400 Message-Id: <91315ac64b44bcad9dfc623fa7fefe67d7d2561b.1568834524.git.rgb@redhat.com> In-Reply-To: References: In-Reply-To: References: X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.49]); Thu, 19 Sep 2019 01:26:18 +0000 (UTC) Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org Audit events could happen in a network namespace outside of a task context due to packets received from the net that trigger an auditing rule prior to being associated with a running task. The network namespace could be in use by multiple containers by association to the tasks in that network namespace. We still want a way to attribute these events to any potential containers. Keep a list per network namespace to track these audit container identifiiers. Add/increment the audit container identifier on: - initial setting of the audit container identifier via /proc - clone/fork call that inherits an audit container identifier - unshare call that inherits an audit container identifier - setns call that inherits an audit container identifier Delete/decrement the audit container identifier on: - an inherited audit container identifier dropped when child set - process exit - unshare call that drops a net namespace - setns call that drops a net namespace Please see the github audit kernel issue for contid net support: https://github.com/linux-audit/audit-kernel/issues/92 Please see the github audit testsuiite issue for the test case: https://github.com/linux-audit/audit-testsuite/issues/64 Please see the github audit wiki for the feature overview: https://github.com/linux-audit/audit-kernel/wiki/RFE-Audit-Container-ID Signed-off-by: Richard Guy Briggs Acked-by: Neil Horman Reviewed-by: Ondrej Mosnacek --- include/linux/audit.h | 19 +++++++++++ kernel/audit.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++++-- kernel/nsproxy.c | 4 +++ 3 files changed, 108 insertions(+), 2 deletions(-) diff --git a/include/linux/audit.h b/include/linux/audit.h index 575fff6ea7c9..73e3ab38e3e0 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -13,6 +13,7 @@ #include #include /* LOOKUP_* */ #include +#include #define AUDIT_INO_UNSET ((unsigned long)-1) #define AUDIT_DEV_UNSET ((dev_t)-1) @@ -122,6 +123,13 @@ struct audit_task_info { extern struct audit_task_info init_struct_audit; +struct audit_contid { + struct list_head list; + u64 id; + refcount_t refcount; + struct rcu_head rcu; +}; + extern int is_audit_feature_set(int which); extern int __init audit_register_class(int class, unsigned *list); @@ -229,6 +237,10 @@ static inline u64 audit_get_contid(struct task_struct *tsk) extern void audit_cont_put(struct audit_cont *cont); extern void audit_log_container_id(struct audit_context *context, u64 contid); +extern void audit_netns_contid_add(struct net *net, u64 contid); +extern void audit_netns_contid_del(struct net *net, u64 contid); +extern void audit_switch_task_namespaces(struct nsproxy *ns, + struct task_struct *p); extern u32 audit_enabled; @@ -309,6 +321,13 @@ static inline void audit_cont_put(struct audit_cont *cont) static inline void audit_log_container_id(struct audit_context *context, u64 contid) { } +static inline void audit_netns_contid_add(struct net *net, u64 contid) +{ } +static inline void audit_netns_contid_del(struct net *net, u64 contid) +{ } +static inline void audit_switch_task_namespaces(struct nsproxy *ns, + struct task_struct *p) +{ } #define audit_enabled AUDIT_OFF diff --git a/kernel/audit.c b/kernel/audit.c index 7cdb76b38966..e0c27bc39925 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -59,6 +59,7 @@ #include #include #include +#include #include "audit.h" @@ -86,9 +87,13 @@ /** * struct audit_net - audit private network namespace data * @sk: communication socket + * @contid_list: audit container identifier list + * @contid_list_lock audit container identifier list lock */ struct audit_net { struct sock *sk; + struct list_head contid_list; + spinlock_t contid_list_lock; }; /** @@ -269,8 +274,11 @@ struct audit_task_info init_struct_audit = { void audit_free(struct task_struct *tsk) { struct audit_task_info *info = tsk->audit; + struct nsproxy *ns = tsk->nsproxy; audit_free_syscall(tsk); + if (ns) + audit_netns_contid_del(ns->net_ns, audit_get_contid(tsk)); /* Freeing the audit_task_info struct must be performed after * audit_log_exit() due to need for loginuid and sessionid. */ @@ -373,6 +381,75 @@ static struct sock *audit_get_sk(const struct net *net) return aunet->sk; } +void audit_netns_contid_add(struct net *net, u64 contid) +{ + struct audit_net *aunet; + struct list_head *contid_list; + struct audit_contid *cont; + + if (!net) + return; + if (!audit_contid_valid(contid)) + return; + aunet = net_generic(net, audit_net_id); + if (!aunet) + return; + contid_list = &aunet->contid_list; + spin_lock(&aunet->contid_list_lock); + list_for_each_entry_rcu(cont, contid_list, list) + if (cont->id == contid) { + refcount_inc(&cont->refcount); + goto out; + } + cont = kmalloc(sizeof(struct audit_contid), GFP_ATOMIC); + if (cont) { + INIT_LIST_HEAD(&cont->list); + cont->id = contid; + refcount_set(&cont->refcount, 1); + list_add_rcu(&cont->list, contid_list); + } +out: + spin_unlock(&aunet->contid_list_lock); +} + +void audit_netns_contid_del(struct net *net, u64 contid) +{ + struct audit_net *aunet; + struct list_head *contid_list; + struct audit_contid *cont = NULL; + + if (!net) + return; + if (!audit_contid_valid(contid)) + return; + aunet = net_generic(net, audit_net_id); + if (!aunet) + return; + contid_list = &aunet->contid_list; + spin_lock(&aunet->contid_list_lock); + list_for_each_entry_rcu(cont, contid_list, list) + if (cont->id == contid) { + if (refcount_dec_and_test(&cont->refcount)) { + list_del_rcu(&cont->list); + kfree_rcu(cont, rcu); + } + break; + } + spin_unlock(&aunet->contid_list_lock); +} + +void audit_switch_task_namespaces(struct nsproxy *ns, struct task_struct *p) +{ + u64 contid = audit_get_contid(p); + struct nsproxy *new = p->nsproxy; + + if (!audit_contid_valid(contid)) + return; + audit_netns_contid_del(ns->net_ns, contid); + if (new) + audit_netns_contid_add(new->net_ns, contid); +} + void audit_panic(const char *message) { switch (audit_failure) { @@ -1641,7 +1718,6 @@ static int __net_init audit_net_init(struct net *net) .flags = NL_CFG_F_NONROOT_RECV, .groups = AUDIT_NLGRP_MAX, }; - struct audit_net *aunet = net_generic(net, audit_net_id); aunet->sk = netlink_kernel_create(net, NETLINK_AUDIT, &cfg); @@ -1650,7 +1726,8 @@ static int __net_init audit_net_init(struct net *net) return -ENOMEM; } aunet->sk->sk_sndtimeo = MAX_SCHEDULE_TIMEOUT; - + INIT_LIST_HEAD(&aunet->contid_list); + spin_lock_init(&aunet->contid_list_lock); return 0; } @@ -2460,6 +2537,7 @@ int audit_set_contid(struct task_struct *task, u64 contid) uid_t uid; struct tty_struct *tty; char comm[sizeof(current->comm)]; + struct net *net = task->nsproxy->net_ns; task_lock(task); /* Can't set if audit disabled */ @@ -2530,6 +2608,11 @@ int audit_set_contid(struct task_struct *task, u64 contid) conterror: spin_unlock(&audit_contid_list_lock); } + if (!rc) { + if (audit_contid_valid(oldcontid)) + audit_netns_contid_del(net, oldcontid); + audit_netns_contid_add(net, contid); + } task_unlock(task); if (!audit_enabled) diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c index c815f58e6bc0..bbdb5bbf5446 100644 --- a/kernel/nsproxy.c +++ b/kernel/nsproxy.c @@ -23,6 +23,7 @@ #include #include #include +#include static struct kmem_cache *nsproxy_cachep; @@ -136,6 +137,7 @@ int copy_namespaces(unsigned long flags, struct task_struct *tsk) struct nsproxy *old_ns = tsk->nsproxy; struct user_namespace *user_ns = task_cred_xxx(tsk, user_ns); struct nsproxy *new_ns; + u64 contid = audit_get_contid(tsk); if (likely(!(flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC | CLONE_NEWPID | CLONE_NEWNET | @@ -163,6 +165,7 @@ int copy_namespaces(unsigned long flags, struct task_struct *tsk) return PTR_ERR(new_ns); tsk->nsproxy = new_ns; + audit_netns_contid_add(new_ns->net_ns, contid); return 0; } @@ -220,6 +223,7 @@ void switch_task_namespaces(struct task_struct *p, struct nsproxy *new) ns = p->nsproxy; p->nsproxy = new; task_unlock(p); + audit_switch_task_namespaces(ns, p); if (ns && atomic_dec_and_test(&ns->count)) free_nsproxy(ns); From patchwork Thu Sep 19 01:22:30 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Guy Briggs X-Patchwork-Id: 11151435 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D548E1745 for ; Thu, 19 Sep 2019 01:26:36 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id B3C8E21927 for ; Thu, 19 Sep 2019 01:26:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387803AbfISB02 (ORCPT ); Wed, 18 Sep 2019 21:26:28 -0400 Received: from mx1.redhat.com ([209.132.183.28]:48106 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387767AbfISB01 (ORCPT ); Wed, 18 Sep 2019 21:26:27 -0400 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 842A78A1C87; Thu, 19 Sep 2019 01:26:21 +0000 (UTC) Received: from madcap2.tricolour.ca (ovpn-112-19.phx2.redhat.com [10.3.112.19]) by smtp.corp.redhat.com (Postfix) with ESMTP id D971060C18; Thu, 19 Sep 2019 01:26:13 +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, dwalsh@redhat.com, mpatel@redhat.com, Richard Guy Briggs Subject: [PATCH ghak90 V7 13/21] audit: NETFILTER_PKT: record each container ID associated with a netNS Date: Wed, 18 Sep 2019 21:22:30 -0400 Message-Id: <18f14bfbffc30c53c2b1dd06694b69ef286f3b72.1568834524.git.rgb@redhat.com> In-Reply-To: References: In-Reply-To: References: X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.6.2 (mx1.redhat.com [10.5.110.69]); Thu, 19 Sep 2019 01:26:26 +0000 (UTC) Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org Add audit container identifier auxiliary record(s) to NETFILTER_PKT event standalone records. Iterate through all potential audit container identifiers associated with a network namespace. Signed-off-by: Richard Guy Briggs Acked-by: Neil Horman Reviewed-by: Ondrej Mosnacek --- include/linux/audit.h | 5 +++++ kernel/audit.c | 39 +++++++++++++++++++++++++++++++++++++++ net/netfilter/nft_log.c | 11 +++++++++-- net/netfilter/xt_AUDIT.c | 11 +++++++++-- 4 files changed, 62 insertions(+), 4 deletions(-) diff --git a/include/linux/audit.h b/include/linux/audit.h index 73e3ab38e3e0..dcd92f964120 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -241,6 +241,8 @@ static inline u64 audit_get_contid(struct task_struct *tsk) extern void audit_netns_contid_del(struct net *net, u64 contid); extern void audit_switch_task_namespaces(struct nsproxy *ns, struct task_struct *p); +extern void audit_log_netns_contid_list(struct net *net, + struct audit_context *context); extern u32 audit_enabled; @@ -328,6 +330,9 @@ static inline void audit_netns_contid_del(struct net *net, u64 contid) static inline void audit_switch_task_namespaces(struct nsproxy *ns, struct task_struct *p) { } +static inline void audit_log_netns_contid_list(struct net *net, + struct audit_context *context) +{ } #define audit_enabled AUDIT_OFF diff --git a/kernel/audit.c b/kernel/audit.c index e0c27bc39925..9ce7a1ec7a92 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -450,6 +450,45 @@ void audit_switch_task_namespaces(struct nsproxy *ns, struct task_struct *p) audit_netns_contid_add(new->net_ns, contid); } +/** + * audit_log_netns_contid_list - List contids for the given network namespace + * @net: the network namespace of interest + * @context: the audit context to use + * + * Description: + * Issues a CONTAINER_ID record with a CSV list of contids associated + * with a network namespace to accompany a NETFILTER_PKT record. + */ +void audit_log_netns_contid_list(struct net *net, struct audit_context *context) +{ + struct audit_buffer *ab = NULL; + struct audit_contid *cont; + struct audit_net *aunet; + + /* Generate AUDIT_CONTAINER_ID record with container ID CSV list */ + rcu_read_lock(); + aunet = net_generic(net, audit_net_id); + if (!aunet) + goto out; + list_for_each_entry_rcu(cont, &aunet->contid_list, list) { + if (!ab) { + ab = audit_log_start(context, GFP_ATOMIC, + AUDIT_CONTAINER_ID); + if (!ab) { + audit_log_lost("out of memory in audit_log_netns_contid_list"); + goto out; + } + audit_log_format(ab, "contid="); + } else + audit_log_format(ab, ","); + audit_log_format(ab, "%llu", cont->id); + } + audit_log_end(ab); +out: + rcu_read_unlock(); +} +EXPORT_SYMBOL(audit_log_netns_contid_list); + void audit_panic(const char *message) { switch (audit_failure) { diff --git a/net/netfilter/nft_log.c b/net/netfilter/nft_log.c index fe4831f2258f..98d1e7e1a83c 100644 --- a/net/netfilter/nft_log.c +++ b/net/netfilter/nft_log.c @@ -66,13 +66,16 @@ static void nft_log_eval_audit(const struct nft_pktinfo *pkt) struct sk_buff *skb = pkt->skb; struct audit_buffer *ab; int fam = -1; + struct audit_context *context; + struct net *net; if (!audit_enabled) return; - ab = audit_log_start(NULL, GFP_ATOMIC, AUDIT_NETFILTER_PKT); + context = audit_alloc_local(GFP_ATOMIC); + ab = audit_log_start(context, GFP_ATOMIC, AUDIT_NETFILTER_PKT); if (!ab) - return; + goto errout; audit_log_format(ab, "mark=%#x", skb->mark); @@ -99,6 +102,10 @@ static void nft_log_eval_audit(const struct nft_pktinfo *pkt) audit_log_format(ab, " saddr=? daddr=? proto=-1"); audit_log_end(ab); + net = xt_net(&pkt->xt); + audit_log_netns_contid_list(net, context); +errout: + audit_free_context(context); } static void nft_log_eval(const struct nft_expr *expr, diff --git a/net/netfilter/xt_AUDIT.c b/net/netfilter/xt_AUDIT.c index 9cdc16b0d0d8..ecf868a1abde 100644 --- a/net/netfilter/xt_AUDIT.c +++ b/net/netfilter/xt_AUDIT.c @@ -68,10 +68,13 @@ static bool audit_ip6(struct audit_buffer *ab, struct sk_buff *skb) { struct audit_buffer *ab; int fam = -1; + struct audit_context *context; + struct net *net; if (audit_enabled == AUDIT_OFF) - goto errout; - ab = audit_log_start(NULL, GFP_ATOMIC, AUDIT_NETFILTER_PKT); + goto out; + context = audit_alloc_local(GFP_ATOMIC); + ab = audit_log_start(context, GFP_ATOMIC, AUDIT_NETFILTER_PKT); if (ab == NULL) goto errout; @@ -101,7 +104,11 @@ static bool audit_ip6(struct audit_buffer *ab, struct sk_buff *skb) audit_log_end(ab); + net = xt_net(par); + audit_log_netns_contid_list(net, context); errout: + audit_free_context(context); +out: return XT_CONTINUE; } From patchwork Thu Sep 19 01:22:31 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Guy Briggs X-Patchwork-Id: 11151441 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id DC9201745 for ; Thu, 19 Sep 2019 01:26:47 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id C4B8F21929 for ; Thu, 19 Sep 2019 01:26:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387859AbfISB0m (ORCPT ); Wed, 18 Sep 2019 21:26:42 -0400 Received: from mx1.redhat.com ([209.132.183.28]:58708 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387790AbfISB0l (ORCPT ); Wed, 18 Sep 2019 21:26:41 -0400 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 5B3CE800DF1; Thu, 19 Sep 2019 01:26:36 +0000 (UTC) Received: from madcap2.tricolour.ca (ovpn-112-19.phx2.redhat.com [10.3.112.19]) by smtp.corp.redhat.com (Postfix) with ESMTP id D7E0C6107E; Thu, 19 Sep 2019 01:26:21 +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, dwalsh@redhat.com, mpatel@redhat.com, Richard Guy Briggs Subject: [PATCH ghak90 V7 14/21] audit: contid check descendancy and nesting Date: Wed, 18 Sep 2019 21:22:31 -0400 Message-Id: <16abf1b2aafeb5f1b8dae20b9a4836e54f959ca5.1568834524.git.rgb@redhat.com> In-Reply-To: References: In-Reply-To: References: X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.6.2 (mx1.redhat.com [10.5.110.67]); Thu, 19 Sep 2019 01:26:41 +0000 (UTC) Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org ?fixup! audit: convert to contid list to check for orch/engine ownership Require the target task to be a descendant of the container orchestrator/engine. You would only change the audit container ID from one set or inherited value to another if you were nesting containers. If changing the contid, the container orchestrator/engine must be a descendant and not same orchestrator as the one that set it so it is not possible to change the contid of another orchestrator's container. Signed-off-by: Richard Guy Briggs --- kernel/audit.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 62 insertions(+), 8 deletions(-) diff --git a/kernel/audit.c b/kernel/audit.c index 9ce7a1ec7a92..69fe1e9af7cb 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -2560,6 +2560,39 @@ static struct task_struct *audit_cont_owner(struct task_struct *tsk) } /* + * task_is_descendant - walk up a process family tree looking for a match + * @parent: the process to compare against while walking up from child + * @child: the process to start from while looking upwards for parent + * + * Returns 1 if child is a descendant of parent, 0 if not. + */ +static int task_is_descendant(struct task_struct *parent, + struct task_struct *child) +{ + int rc = 0; + struct task_struct *walker = child; + + if (!parent || !child) + return 0; + + rcu_read_lock(); + if (!thread_group_leader(parent)) + parent = rcu_dereference(parent->group_leader); + while (walker->pid > 0) { + if (!thread_group_leader(walker)) + walker = rcu_dereference(walker->group_leader); + if (walker == parent) { + rc = 1; + break; + } + walker = rcu_dereference(walker->real_parent); + } + rcu_read_unlock(); + + return rc; +} + +/* * audit_set_contid - set current task's audit contid * @task: target task * @contid: contid value @@ -2587,22 +2620,43 @@ int audit_set_contid(struct task_struct *task, u64 contid) oldcontid = audit_get_contid(task); read_lock(&tasklist_lock); /* Don't allow the contid to be unset */ - if (!audit_contid_valid(contid)) + if (!audit_contid_valid(contid)) { rc = -EINVAL; + goto unlock; + } /* Don't allow the contid to be set to the same value again */ - else if (contid == oldcontid) { + if (contid == oldcontid) { rc = -EADDRINUSE; + goto unlock; + } /* if we don't have caps, reject */ - else if (!capable(CAP_AUDIT_CONTROL)) + if (!capable(CAP_AUDIT_CONTROL)) { rc = -EPERM; - /* if task has children or is not single-threaded, deny */ - else if (!list_empty(&task->children)) + goto unlock; + } + /* if task has children, deny */ + if (!list_empty(&task->children)) { rc = -EBUSY; - else if (!(thread_group_leader(task) && thread_group_empty(task))) + goto unlock; + } + /* if task is not single-threaded, deny */ + if (!(thread_group_leader(task) && thread_group_empty(task))) { rc = -EALREADY; - /* if contid is already set, deny */ - else if (audit_contid_set(task)) + goto unlock; + } + /* if task is not descendant, block */ + if (task == current) { + rc = -EBADSLT; + goto unlock; + } + if (!task_is_descendant(current, task)) { + rc = -EXDEV; + goto unlock; + } + /* only allow contid setting again if nesting */ + if (audit_contid_set(task) && current == audit_cont_owner(task)) rc = -ECHILD; +unlock: read_unlock(&tasklist_lock); if (!rc) { struct audit_cont *oldcont = audit_cont(task); From patchwork Thu Sep 19 01:22:32 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Guy Briggs X-Patchwork-Id: 11151443 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id C365276 for ; Thu, 19 Sep 2019 01:26:52 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id A176F21927 for ; Thu, 19 Sep 2019 01:26:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387898AbfISB0r (ORCPT ); Wed, 18 Sep 2019 21:26:47 -0400 Received: from mx1.redhat.com ([209.132.183.28]:49254 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387882AbfISB0q (ORCPT ); Wed, 18 Sep 2019 21:26:46 -0400 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 3CBEA302C080; Thu, 19 Sep 2019 01:26:42 +0000 (UTC) Received: from madcap2.tricolour.ca (ovpn-112-19.phx2.redhat.com [10.3.112.19]) by smtp.corp.redhat.com (Postfix) with ESMTP id B6F5760C18; Thu, 19 Sep 2019 01:26:36 +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, dwalsh@redhat.com, mpatel@redhat.com, Richard Guy Briggs Subject: [PATCH ghak90 V7 15/21] sched: pull task_is_descendant into kernel/sched/core.c Date: Wed, 18 Sep 2019 21:22:32 -0400 Message-Id: In-Reply-To: References: In-Reply-To: References: X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.46]); Thu, 19 Sep 2019 01:26:46 +0000 (UTC) Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org Since the task_is_descendant() function is used in YAMA and in audit, pull the function into kernel/core/sched.c Signed-off-by: Richard Guy Briggs --- include/linux/sched.h | 3 +++ kernel/audit.c | 33 --------------------------------- kernel/sched/core.c | 33 +++++++++++++++++++++++++++++++++ security/yama/yama_lsm.c | 33 --------------------------------- 4 files changed, 36 insertions(+), 66 deletions(-) diff --git a/include/linux/sched.h b/include/linux/sched.h index a936d162513a..b251f018f4db 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1988,4 +1988,7 @@ static inline void rseq_syscall(struct pt_regs *regs) const struct cpumask *sched_trace_rd_span(struct root_domain *rd); +extern int task_is_descendant(struct task_struct *parent, + struct task_struct *child); + #endif diff --git a/kernel/audit.c b/kernel/audit.c index 69fe1e9af7cb..4fe7678304dd 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -2560,39 +2560,6 @@ static struct task_struct *audit_cont_owner(struct task_struct *tsk) } /* - * task_is_descendant - walk up a process family tree looking for a match - * @parent: the process to compare against while walking up from child - * @child: the process to start from while looking upwards for parent - * - * Returns 1 if child is a descendant of parent, 0 if not. - */ -static int task_is_descendant(struct task_struct *parent, - struct task_struct *child) -{ - int rc = 0; - struct task_struct *walker = child; - - if (!parent || !child) - return 0; - - rcu_read_lock(); - if (!thread_group_leader(parent)) - parent = rcu_dereference(parent->group_leader); - while (walker->pid > 0) { - if (!thread_group_leader(walker)) - walker = rcu_dereference(walker->group_leader); - if (walker == parent) { - rc = 1; - break; - } - walker = rcu_dereference(walker->real_parent); - } - rcu_read_unlock(); - - return rc; -} - -/* * audit_set_contid - set current task's audit contid * @task: target task * @contid: contid value diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 2b037f195473..7ba9e07381fa 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -7509,6 +7509,39 @@ void dump_cpu_task(int cpu) } /* + * task_is_descendant - walk up a process family tree looking for a match + * @parent: the process to compare against while walking up from child + * @child: the process to start from while looking upwards for parent + * + * Returns 1 if child is a descendant of parent, 0 if not. + */ +int task_is_descendant(struct task_struct *parent, + struct task_struct *child) +{ + int rc = 0; + struct task_struct *walker = child; + + if (!parent || !child) + return 0; + + rcu_read_lock(); + if (!thread_group_leader(parent)) + parent = rcu_dereference(parent->group_leader); + while (walker->pid > 0) { + if (!thread_group_leader(walker)) + walker = rcu_dereference(walker->group_leader); + if (walker == parent) { + rc = 1; + break; + } + walker = rcu_dereference(walker->real_parent); + } + rcu_read_unlock(); + + return rc; +} + +/* * Nice levels are multiplicative, with a gentle 10% change for every * nice level changed. I.e. when a CPU-bound task goes from nice 0 to * nice 1, it will get ~10% less CPU time than another CPU-bound task diff --git a/security/yama/yama_lsm.c b/security/yama/yama_lsm.c index 94dc346370b1..25eae205eae8 100644 --- a/security/yama/yama_lsm.c +++ b/security/yama/yama_lsm.c @@ -263,39 +263,6 @@ static int yama_task_prctl(int option, unsigned long arg2, unsigned long arg3, } /** - * task_is_descendant - walk up a process family tree looking for a match - * @parent: the process to compare against while walking up from child - * @child: the process to start from while looking upwards for parent - * - * Returns 1 if child is a descendant of parent, 0 if not. - */ -static int task_is_descendant(struct task_struct *parent, - struct task_struct *child) -{ - int rc = 0; - struct task_struct *walker = child; - - if (!parent || !child) - return 0; - - rcu_read_lock(); - if (!thread_group_leader(parent)) - parent = rcu_dereference(parent->group_leader); - while (walker->pid > 0) { - if (!thread_group_leader(walker)) - walker = rcu_dereference(walker->group_leader); - if (walker == parent) { - rc = 1; - break; - } - walker = rcu_dereference(walker->real_parent); - } - rcu_read_unlock(); - - return rc; -} - -/** * ptracer_exception_found - tracer registered as exception for this tracee * @tracer: the task_struct of the process attempting ptrace * @tracee: the task_struct of the process to be ptraced From patchwork Thu Sep 19 01:22:33 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Guy Briggs X-Patchwork-Id: 11151447 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 53C021745 for ; Thu, 19 Sep 2019 01:27:03 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 3BC0521927 for ; Thu, 19 Sep 2019 01:27:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387490AbfISB05 (ORCPT ); Wed, 18 Sep 2019 21:26:57 -0400 Received: from mx1.redhat.com ([209.132.183.28]:48960 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730815AbfISB05 (ORCPT ); Wed, 18 Sep 2019 21:26:57 -0400 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 5ADC28553F; Thu, 19 Sep 2019 01:26:56 +0000 (UTC) Received: from madcap2.tricolour.ca (ovpn-112-19.phx2.redhat.com [10.3.112.19]) by smtp.corp.redhat.com (Postfix) with ESMTP id 9C40460C80; Thu, 19 Sep 2019 01:26:42 +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, dwalsh@redhat.com, mpatel@redhat.com, Richard Guy Briggs Subject: [PATCH ghak90 V7 16/21] audit: add support for contid set/get by netlink Date: Wed, 18 Sep 2019 21:22:33 -0400 Message-Id: In-Reply-To: References: In-Reply-To: References: X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.28]); Thu, 19 Sep 2019 01:26:56 +0000 (UTC) Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org Add the ability to get and set the audit container identifier using an audit netlink message using message types AUDIT_SET_CONTID 1023 and AUDIT_GET_CONTID 1022 in addition to using the proc filesystem. The message format includes the data structure: struct audit_contid_status { pid_t pid; u64 id; }; Signed-off-by: Richard Guy Briggs --- include/uapi/linux/audit.h | 2 ++ kernel/audit.c | 40 ++++++++++++++++++++++++++++++++++++++++ kernel/audit.h | 5 +++++ 3 files changed, 47 insertions(+) diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h index f34108759e8f..e26729fc9943 100644 --- a/include/uapi/linux/audit.h +++ b/include/uapi/linux/audit.h @@ -73,6 +73,8 @@ #define AUDIT_GET_FEATURE 1019 /* Get which features are enabled */ #define AUDIT_CONTAINER_OP 1020 /* Define the container id and info */ #define AUDIT_SIGNAL_INFO2 1021 /* Get info auditd signal sender */ +#define AUDIT_GET_CONTID 1022 /* Get contid of a task */ +#define AUDIT_SET_CONTID 1023 /* Set contid of a task */ #define AUDIT_FIRST_USER_MSG 1100 /* Userspace messages mostly uninteresting to kernel */ #define AUDIT_USER_AVC 1107 /* We filter this differently */ diff --git a/kernel/audit.c b/kernel/audit.c index 4fe7678304dd..df92de20ed73 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -1216,6 +1216,8 @@ static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type) case AUDIT_TTY_SET: case AUDIT_TRIM: case AUDIT_MAKE_EQUIV: + case AUDIT_GET_CONTID: + case AUDIT_SET_CONTID: /* Only support auditd and auditctl in initial pid namespace * for now. */ if (task_active_pid_ns(current) != &init_pid_ns) @@ -1273,6 +1275,23 @@ static int audit_get_feature(struct sk_buff *skb) return 0; } +static int audit_get_contid_status(struct sk_buff *skb) +{ + struct nlmsghdr *nlh = nlmsg_hdr(skb); + u32 seq = nlh->nlmsg_seq; + void *data = nlmsg_data(nlh); + struct audit_contid_status cs; + + cs.pid = ((struct audit_contid_status *)data)->pid; + if (!cs.pid) + cs.pid = task_tgid_nr(current); + rcu_read_lock(); + cs.id = audit_get_contid(find_task_by_vpid(cs.pid)); + rcu_read_unlock(); + audit_send_reply(skb, seq, AUDIT_GET_CONTID, 0, 0, &cs, sizeof(cs)); + return 0; +} + static void audit_log_feature_change(int which, u32 old_feature, u32 new_feature, u32 old_lock, u32 new_lock, int res) { @@ -1700,6 +1719,27 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) audit_log_end(ab); break; } + case AUDIT_SET_CONTID: { + struct audit_contid_status *s = data; + struct task_struct *tsk; + + /* check if new data is valid */ + if (nlmsg_len(nlh) < sizeof(*s)) + return -EINVAL; + tsk = find_get_task_by_vpid(s->pid); + if (!tsk) + return -EINVAL; + + err = audit_set_contid(tsk, s->id); + put_task_struct(tsk); + return err; + break; + } + case AUDIT_GET_CONTID: + err = audit_get_contid_status(skb); + if (err) + return err; + break; default: err = -EINVAL; break; diff --git a/kernel/audit.h b/kernel/audit.h index c9b73abfd6a0..25732fbc47a4 100644 --- a/kernel/audit.h +++ b/kernel/audit.h @@ -224,6 +224,11 @@ static inline int audit_hash_contid(u64 contid) #define AUDIT_CONTID_COUNT 1 << 16 +struct audit_contid_status { + pid_t pid; + u64 id; +}; + /* Indicates that audit should log the full pathname. */ #define AUDIT_NAME_FULL -1 From patchwork Thu Sep 19 01:22:34 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Guy Briggs X-Patchwork-Id: 11151451 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 99EAA1745 for ; Thu, 19 Sep 2019 01:27:14 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 81E1D20644 for ; Thu, 19 Sep 2019 01:27:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387956AbfISB1H (ORCPT ); Wed, 18 Sep 2019 21:27:07 -0400 Received: from mx1.redhat.com ([209.132.183.28]:40756 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387927AbfISB1G (ORCPT ); Wed, 18 Sep 2019 21:27:06 -0400 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 9A8F8859FB; Thu, 19 Sep 2019 01:27:01 +0000 (UTC) Received: from madcap2.tricolour.ca (ovpn-112-19.phx2.redhat.com [10.3.112.19]) by smtp.corp.redhat.com (Postfix) with ESMTP id BB07260F88; Thu, 19 Sep 2019 01:26:56 +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, dwalsh@redhat.com, mpatel@redhat.com, Richard Guy Briggs Subject: [PATCH ghak90 V7 17/21] audit: add support for loginuid/sessionid set/get by netlink Date: Wed, 18 Sep 2019 21:22:34 -0400 Message-Id: <6cef16c2a019e61e49f4d62497b5ca8dab79b45f.1568834525.git.rgb@redhat.com> In-Reply-To: References: In-Reply-To: References: X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.26]); Thu, 19 Sep 2019 01:27:06 +0000 (UTC) Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org Add the ability to get and set the login uid and to get the session id using an audit netlink message using message types AUDIT_GET_LOGINUID 1024, AUDIT_SET_LOGINUID 1025 and AUDIT_GET_SESSIONID 1026 in addition to using the proc filesystem. Signed-off-by: Richard Guy Briggs --- include/uapi/linux/audit.h | 3 +++ kernel/audit.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h index e26729fc9943..eef42c8eea77 100644 --- a/include/uapi/linux/audit.h +++ b/include/uapi/linux/audit.h @@ -75,6 +75,9 @@ #define AUDIT_SIGNAL_INFO2 1021 /* Get info auditd signal sender */ #define AUDIT_GET_CONTID 1022 /* Get contid of a task */ #define AUDIT_SET_CONTID 1023 /* Set contid of a task */ +#define AUDIT_GET_LOGINUID 1024 /* Get loginuid of a task */ +#define AUDIT_SET_LOGINUID 1025 /* Set loginuid of a task */ +#define AUDIT_GET_SESSIONID 1026 /* Set sessionid of a task */ #define AUDIT_FIRST_USER_MSG 1100 /* Userspace messages mostly uninteresting to kernel */ #define AUDIT_USER_AVC 1107 /* We filter this differently */ diff --git a/kernel/audit.c b/kernel/audit.c index df92de20ed73..9e82de13d2eb 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -1184,6 +1184,15 @@ static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type) { int err = 0; + /* These messages can work outside the initial namespaces */ + switch (msg_type) { + case AUDIT_GET_LOGINUID: + case AUDIT_GET_SESSIONID: + return 0; + break; + default: /* do more checks below */ + break; + } /* Only support initial user namespace for now. */ /* * We return ECONNREFUSED because it tricks userspace into thinking @@ -1218,6 +1227,7 @@ static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type) case AUDIT_MAKE_EQUIV: case AUDIT_GET_CONTID: case AUDIT_SET_CONTID: + case AUDIT_SET_LOGINUID: /* Only support auditd and auditctl in initial pid namespace * for now. */ if (task_active_pid_ns(current) != &init_pid_ns) @@ -1292,6 +1302,33 @@ static int audit_get_contid_status(struct sk_buff *skb) return 0; } +struct audit_loginuid_status { uid_t loginuid; }; + +static int audit_get_loginuid_status(struct sk_buff *skb) +{ + u32 seq; + uid_t loginuid; + struct audit_loginuid_status ls; + + loginuid = from_kuid(current_user_ns(), audit_get_loginuid(current)); + ls.loginuid = loginuid; + + seq = nlmsg_hdr(skb)->nlmsg_seq; + audit_send_reply(skb, seq, AUDIT_GET_LOGINUID, 0, 0, &ls, sizeof(ls)); + return loginuid; +} + +static int audit_get_sessionid_status(struct sk_buff *skb) +{ + u32 seq; + struct audit_sessionid_status { u32 sessionid; }; + struct audit_sessionid_status ss = { audit_get_sessionid(current) }; + + seq = nlmsg_hdr(skb)->nlmsg_seq; + audit_send_reply(skb, seq, AUDIT_GET_SESSIONID, 0, 0, &ss, sizeof(ss)); + return audit_get_sessionid(current); +} + static void audit_log_feature_change(int which, u32 old_feature, u32 new_feature, u32 old_lock, u32 new_lock, int res) { @@ -1740,6 +1777,31 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) if (err) return err; break; + case AUDIT_SET_LOGINUID: { + uid_t *loginuid = data; + kuid_t kloginuid; + + /* check if new data is valid */ + if (nlmsg_len(nlh) < sizeof(u32)) + return -EINVAL; + + kloginuid = make_kuid(current_user_ns(), *loginuid); + if (!uid_valid(kloginuid)) + return -EINVAL; + + return audit_set_loginuid(kloginuid); + break; + } + case AUDIT_GET_LOGINUID: + err = audit_get_loginuid_status(skb); + if (err) + return err; + break; + case AUDIT_GET_SESSIONID: + err = audit_get_sessionid_status(skb); + if (err) + return err; + break; default: err = -EINVAL; break; From patchwork Thu Sep 19 01:22:35 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Guy Briggs X-Patchwork-Id: 11151459 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 8DADF1745 for ; Thu, 19 Sep 2019 01:27:30 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 61ADA21D56 for ; Thu, 19 Sep 2019 01:27:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387985AbfISB1T (ORCPT ); Wed, 18 Sep 2019 21:27:19 -0400 Received: from mx1.redhat.com ([209.132.183.28]:54074 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387682AbfISB1T (ORCPT ); Wed, 18 Sep 2019 21:27:19 -0400 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 4A90381DE0; Thu, 19 Sep 2019 01:27:18 +0000 (UTC) Received: from madcap2.tricolour.ca (ovpn-112-19.phx2.redhat.com [10.3.112.19]) by smtp.corp.redhat.com (Postfix) with ESMTP id 0468C60C5E; Thu, 19 Sep 2019 01:27:01 +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, dwalsh@redhat.com, mpatel@redhat.com, Richard Guy Briggs Subject: [PATCH ghak90 V7 18/21] audit: track container nesting Date: Wed, 18 Sep 2019 21:22:35 -0400 Message-Id: In-Reply-To: References: In-Reply-To: References: X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.25]); Thu, 19 Sep 2019 01:27:18 +0000 (UTC) Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org Track the parent container of a container to be able to filter and report nesting. Now that we have a way to track and check the parent container of a container, fixup other patches, or squash all nesting fixes together. fixup! audit: add container id fixup! audit: log drop of contid on exit of last task fixup! audit: log container info of syscalls fixup! audit: add containerid filtering fixup! audit: NETFILTER_PKT: record each container ID associated with a netNS fixup! audit: convert to contid list to check for orch/engine ownership softirq (for netfilter) audit: protect contid list lock from softirq Signed-off-by: Richard Guy Briggs --- include/linux/audit.h | 1 + kernel/audit.c | 67 ++++++++++++++++++++++++++++++++++++++++++--------- kernel/audit.h | 3 +++ kernel/auditfilter.c | 20 ++++++++++++++- kernel/auditsc.c | 2 +- 5 files changed, 79 insertions(+), 14 deletions(-) diff --git a/include/linux/audit.h b/include/linux/audit.h index dcd92f964120..1ce27af686ea 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -110,6 +110,7 @@ struct audit_cont { struct task_struct *owner; refcount_t refcount; struct rcu_head rcu; + struct audit_cont *parent; }; struct audit_task_info { diff --git a/kernel/audit.c b/kernel/audit.c index 9e82de13d2eb..848fd1c8c579 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -213,7 +213,7 @@ struct audit_reply { static struct kmem_cache *audit_task_cache; -static DEFINE_SPINLOCK(audit_contid_list_lock); +DEFINE_SPINLOCK(audit_contid_list_lock); void __init audit_task_init(void) { @@ -275,6 +275,7 @@ void audit_free(struct task_struct *tsk) { struct audit_task_info *info = tsk->audit; struct nsproxy *ns = tsk->nsproxy; + unsigned long flags; audit_free_syscall(tsk); if (ns) @@ -282,9 +283,9 @@ void audit_free(struct task_struct *tsk) /* Freeing the audit_task_info struct must be performed after * audit_log_exit() due to need for loginuid and sessionid. */ - spin_lock(&audit_contid_list_lock); + spin_lock_irqsave(&audit_contid_list_lock, flags); audit_cont_put(tsk->audit->cont); - spin_unlock(&audit_contid_list_lock); + spin_unlock_irqrestore(&audit_contid_list_lock, flags); info = tsk->audit; tsk->audit = NULL; kmem_cache_free(audit_task_cache, info); @@ -450,6 +451,7 @@ void audit_switch_task_namespaces(struct nsproxy *ns, struct task_struct *p) audit_netns_contid_add(new->net_ns, contid); } +void audit_log_contid(struct audit_buffer *ab, u64 contid); /** * audit_log_netns_contid_list - List contids for the given network namespace * @net: the network namespace of interest @@ -481,7 +483,7 @@ void audit_log_netns_contid_list(struct net *net, struct audit_context *context) audit_log_format(ab, "contid="); } else audit_log_format(ab, ","); - audit_log_format(ab, "%llu", cont->id); + audit_log_contid(ab, cont->id); } audit_log_end(ab); out: @@ -2371,6 +2373,36 @@ void audit_log_session_info(struct audit_buffer *ab) audit_log_format(ab, "auid=%u ses=%u", auid, sessionid); } +void audit_log_contid(struct audit_buffer *ab, u64 contid) +{ + struct audit_cont *cont = NULL; + struct audit_cont *prcont = NULL; + int h; + unsigned long flags; + + if (!audit_contid_valid(contid)) { + audit_log_format(ab, "%llu", contid); + return; + } + h = audit_hash_contid(contid); + spin_lock_irqsave(&audit_contid_list_lock, flags); + list_for_each_entry_rcu(cont, &audit_contid_hash[h], list) + if (cont->id == contid) + prcont = cont; + if (!prcont) { + audit_log_format(ab, "%llu", contid); + goto out; + } + while (prcont) { + audit_log_format(ab, "%llu", prcont->id); + prcont = prcont->parent; + if (prcont) + audit_log_format(ab, "^"); + } +out: + spin_unlock_irqrestore(&audit_contid_list_lock, flags); +} + /* * audit_log_container_id - report container info * @context: task or local context for record @@ -2386,7 +2418,8 @@ void audit_log_container_id(struct audit_context *context, u64 contid) ab = audit_log_start(context, GFP_KERNEL, AUDIT_CONTAINER_ID); if (!ab) return; - audit_log_format(ab, "contid=%llu", contid); + audit_log_format(ab, "contid="); + audit_log_contid(ab, contid); audit_log_end(ab); } EXPORT_SYMBOL(audit_log_container_id); @@ -2648,6 +2681,7 @@ void audit_cont_put(struct audit_cont *cont) return; if (refcount_dec_and_test(&cont->refcount)) { put_task_struct(cont->owner); + audit_cont_put(cont->parent); list_del_rcu(&cont->list); kfree_rcu(cont, rcu); audit_contid_count--; @@ -2732,8 +2766,9 @@ int audit_set_contid(struct task_struct *task, u64 contid) struct audit_cont *cont = NULL; struct audit_cont *newcont = NULL; int h = audit_hash_contid(contid); + unsigned long flags; - spin_lock(&audit_contid_list_lock); + spin_lock_irqsave(&audit_contid_list_lock, flags); list_for_each_entry_rcu(cont, &audit_contid_hash[h], list) if (cont->id == contid) { /* task injection to existing container */ @@ -2757,6 +2792,9 @@ int audit_set_contid(struct task_struct *task, u64 contid) newcont->id = contid; get_task_struct(current); newcont->owner = current; + newcont->parent = audit_cont(newcont->owner); + if (newcont->parent) + refcount_inc(&newcont->parent->refcount); refcount_set(&newcont->refcount, 1); list_add_rcu(&newcont->list, &audit_contid_hash[h]); audit_contid_count++; @@ -2768,7 +2806,7 @@ int audit_set_contid(struct task_struct *task, u64 contid) task->audit->cont = newcont; audit_cont_put(oldcont); conterror: - spin_unlock(&audit_contid_list_lock); + spin_unlock_irqrestore(&audit_contid_list_lock, flags); } if (!rc) { if (audit_contid_valid(oldcontid)) @@ -2786,9 +2824,12 @@ int audit_set_contid(struct task_struct *task, u64 contid) uid = from_kuid(&init_user_ns, task_uid(current)); tty = audit_get_tty(); + audit_log_format(ab, "op=set opid=%d contid=", task_tgid_nr(task)); + audit_log_contid(ab, contid); + audit_log_format(ab, " old-contid="); + audit_log_contid(ab, oldcontid); audit_log_format(ab, - "op=set opid=%d contid=%llu old-contid=%llu pid=%d uid=%u auid=%u tty=%s ses=%u", - task_tgid_nr(task), contid, oldcontid, + " pid=%d uid=%u auid=%u tty=%s ses=%u", task_tgid_nr(current), uid, from_kuid(&init_user_ns, audit_get_loginuid(current)), tty ? tty_name(tty) : "(none)", @@ -2819,10 +2860,12 @@ void audit_log_container_drop(void) uid = from_kuid(&init_user_ns, task_uid(current)); tty = audit_get_tty(); + audit_log_format(ab, "op=drop opid=%d contid=%llu old-contid=", + task_tgid_nr(current), AUDIT_CID_UNSET); + audit_log_contid(ab, audit_get_contid(current)); audit_log_format(ab, - "op=drop opid=%d contid=%llu old-contid=%llu pid=%d uid=%u auid=%u tty=%s ses=%u", - task_tgid_nr(current), audit_get_contid(current), - audit_get_contid(current), task_tgid_nr(current), uid, + " pid=%d uid=%u auid=%u tty=%s ses=%u", + task_tgid_nr(current), uid, from_kuid(&init_user_ns, audit_get_loginuid(current)), tty ? tty_name(tty) : "(none)", audit_get_sessionid(current)); diff --git a/kernel/audit.h b/kernel/audit.h index 25732fbc47a4..89b7de323c13 100644 --- a/kernel/audit.h +++ b/kernel/audit.h @@ -220,6 +220,8 @@ static inline int audit_hash_contid(u64 contid) return (contid & (AUDIT_CONTID_BUCKETS-1)); } +extern spinlock_t audit_contid_list_lock; + extern int audit_contid_count; #define AUDIT_CONTID_COUNT 1 << 16 @@ -235,6 +237,7 @@ struct audit_contid_status { extern int audit_match_class(int class, unsigned syscall); extern int audit_comparator(const u32 left, const u32 op, const u32 right); extern int audit_comparator64(const u64 left, const u32 op, const u64 right); +extern int audit_contid_comparator(const u64 left, const u32 op, const u64 right); extern int audit_uid_comparator(kuid_t left, u32 op, kuid_t right); extern int audit_gid_comparator(kgid_t left, u32 op, kgid_t right); extern int parent_len(const char *path); diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index 9606f973fe33..513d57d03637 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c @@ -1297,6 +1297,24 @@ int audit_gid_comparator(kgid_t left, u32 op, kgid_t right) } } +int audit_contid_comparator(u64 left, u32 op, u64 right) +{ + struct audit_cont *cont = NULL; + int h; + int result = 0; + unsigned long flags; + + h = audit_hash_contid(left); + spin_lock_irqsave(&audit_contid_list_lock, flags); + list_for_each_entry_rcu(cont, &audit_contid_hash[h], list) { + result = audit_comparator64(cont->id, op, right); + if (result) + break; + } + spin_unlock_irqrestore(&audit_contid_list_lock, flags); + return result; +} + /** * parent_len - find the length of the parent portion of a pathname * @path: pathname of which to determine length @@ -1388,7 +1406,7 @@ int audit_filter(int msgtype, unsigned int listtype) f->op, f->val); break; case AUDIT_CONTID: - result = audit_comparator64(audit_get_contid(current), + result = audit_contid_comparator(audit_get_contid(current), f->op, f->val64); break; case AUDIT_MSGTYPE: diff --git a/kernel/auditsc.c b/kernel/auditsc.c index a658fe775b86..6bf6d8b9dfd1 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -630,7 +630,7 @@ static int audit_filter_rules(struct task_struct *tsk, f->op, f->val); break; case AUDIT_CONTID: - result = audit_comparator64(audit_get_contid(tsk), + result = audit_contid_comparator(audit_get_contid(tsk), f->op, f->val64); break; case AUDIT_SUBJ_USER: From patchwork Thu Sep 19 01:22:36 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Guy Briggs X-Patchwork-Id: 11151457 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id AE4AA1745 for ; Thu, 19 Sep 2019 01:27:28 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 96A4621927 for ; Thu, 19 Sep 2019 01:27:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1732017AbfISB1Y (ORCPT ); Wed, 18 Sep 2019 21:27:24 -0400 Received: from mx1.redhat.com ([209.132.183.28]:45526 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727324AbfISB1X (ORCPT ); Wed, 18 Sep 2019 21:27:23 -0400 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 5638E307D971; Thu, 19 Sep 2019 01:27:23 +0000 (UTC) Received: from madcap2.tricolour.ca (ovpn-112-19.phx2.redhat.com [10.3.112.19]) by smtp.corp.redhat.com (Postfix) with ESMTP id A7B3460F88; Thu, 19 Sep 2019 01:27:18 +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, dwalsh@redhat.com, mpatel@redhat.com, Richard Guy Briggs Subject: [PATCH ghak90 V7 19/21] audit: check cont depth Date: Wed, 18 Sep 2019 21:22:36 -0400 Message-Id: <8cb68e43b55b1b0a021710402ded89444edaf13c.1568834525.git.rgb@redhat.com> In-Reply-To: References: In-Reply-To: References: X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.48]); Thu, 19 Sep 2019 01:27:23 +0000 (UTC) Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org Set an arbitrary limit on the depth of audit container identifier nesting to limit abuse. Signed-off-by: Richard Guy Briggs --- kernel/audit.c | 21 +++++++++++++++++++++ kernel/audit.h | 2 ++ 2 files changed, 23 insertions(+) diff --git a/kernel/audit.c b/kernel/audit.c index 848fd1c8c579..a70c9184e5d9 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -2667,6 +2667,22 @@ int audit_signal_info(int sig, struct task_struct *t) return audit_signal_info_syscall(t); } +static int audit_contid_depth(struct audit_cont *cont) +{ + struct audit_cont *parent; + int depth = 1; + + if (!cont) + return 0; + + parent = cont->parent; + while (parent) { + depth++; + parent = parent->parent; + } + return depth; +} + struct audit_cont *audit_cont(struct task_struct *tsk) { if (!tsk->audit || !tsk->audit->cont) @@ -2785,6 +2801,11 @@ int audit_set_contid(struct task_struct *task, u64 contid) rc = -ENOSPC; goto conterror; } + /* Set max contid depth */ + if (audit_contid_depth(audit_cont(current->real_parent)) >= AUDIT_CONTID_DEPTH) { + rc = -EMLINK; + goto conterror; + } if (!newcont) { newcont = kmalloc(sizeof(struct audit_cont), GFP_ATOMIC); if (newcont) { diff --git a/kernel/audit.h b/kernel/audit.h index 89b7de323c13..cb25341c1a0f 100644 --- a/kernel/audit.h +++ b/kernel/audit.h @@ -231,6 +231,8 @@ struct audit_contid_status { u64 id; }; +#define AUDIT_CONTID_DEPTH 5 + /* Indicates that audit should log the full pathname. */ #define AUDIT_NAME_FULL -1 From patchwork Thu Sep 19 01:22:37 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Guy Briggs X-Patchwork-Id: 11151463 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id EB3481745 for ; Thu, 19 Sep 2019 01:27:39 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id C8CDB2196E for ; Thu, 19 Sep 2019 01:27:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387682AbfISB1f (ORCPT ); Wed, 18 Sep 2019 21:27:35 -0400 Received: from mx1.redhat.com ([209.132.183.28]:3547 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1732041AbfISB1e (ORCPT ); Wed, 18 Sep 2019 21:27:34 -0400 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id C64FB308AA11; Thu, 19 Sep 2019 01:27:33 +0000 (UTC) Received: from madcap2.tricolour.ca (ovpn-112-19.phx2.redhat.com [10.3.112.19]) by smtp.corp.redhat.com (Postfix) with ESMTP id B4A2660F88; Thu, 19 Sep 2019 01:27:23 +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, dwalsh@redhat.com, mpatel@redhat.com, Richard Guy Briggs Subject: [PATCH ghak90 V7 20/21] audit: add capcontid to set contid outside init_user_ns Date: Wed, 18 Sep 2019 21:22:37 -0400 Message-Id: <214163d11a75126f610bcedfad67a4d89575dc77.1568834525.git.rgb@redhat.com> In-Reply-To: References: In-Reply-To: References: X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.41]); Thu, 19 Sep 2019 01:27:33 +0000 (UTC) Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org Provide a mechanism similar to CAP_AUDIT_CONTROL to explicitly give a process in a non-init user namespace the capability to set audit container identifiers. Use audit netlink message types AUDIT_GET_CAPCONTID 1027 and AUDIT_SET_CAPCONTID 1028. The message format includes the data structure: struct audit_capcontid_status { pid_t pid; u32 enable; }; Signed-off-by: Richard Guy Briggs --- include/linux/audit.h | 14 +++++++ include/uapi/linux/audit.h | 2 + kernel/audit.c | 98 +++++++++++++++++++++++++++++++++++++++++++++- kernel/audit.h | 5 +++ 4 files changed, 117 insertions(+), 2 deletions(-) diff --git a/include/linux/audit.h b/include/linux/audit.h index 1ce27af686ea..dcc53e62e266 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -117,6 +117,7 @@ struct audit_task_info { kuid_t loginuid; unsigned int sessionid; struct audit_cont *cont; + u32 capcontid; #ifdef CONFIG_AUDITSYSCALL struct audit_context *ctx; #endif @@ -224,6 +225,14 @@ static inline unsigned int audit_get_sessionid(struct task_struct *tsk) return tsk->audit->sessionid; } +static inline u32 audit_get_capcontid(struct task_struct *tsk) +{ + if (!tsk->audit) + return 0; + return tsk->audit->capcontid; +} + +extern int audit_set_capcontid(struct task_struct *tsk, u32 enable); extern int audit_set_contid(struct task_struct *tsk, u64 contid); static inline u64 audit_get_contid(struct task_struct *tsk) @@ -309,6 +318,11 @@ static inline unsigned int audit_get_sessionid(struct task_struct *tsk) return AUDIT_SID_UNSET; } +static inline u32 audit_get_capcontid(struct task_struct *tsk) +{ + return 0; +} + static inline u64 audit_get_contid(struct task_struct *tsk) { return AUDIT_CID_UNSET; diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h index eef42c8eea77..011b0a8ee9b2 100644 --- a/include/uapi/linux/audit.h +++ b/include/uapi/linux/audit.h @@ -78,6 +78,8 @@ #define AUDIT_GET_LOGINUID 1024 /* Get loginuid of a task */ #define AUDIT_SET_LOGINUID 1025 /* Set loginuid of a task */ #define AUDIT_GET_SESSIONID 1026 /* Set sessionid of a task */ +#define AUDIT_GET_CAPCONTID 1027 /* Get cap_contid of a task */ +#define AUDIT_SET_CAPCONTID 1028 /* Set cap_contid of a task */ #define AUDIT_FIRST_USER_MSG 1100 /* Userspace messages mostly uninteresting to kernel */ #define AUDIT_USER_AVC 1107 /* We filter this differently */ diff --git a/kernel/audit.c b/kernel/audit.c index a70c9184e5d9..7160da464849 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -1192,6 +1192,14 @@ static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type) case AUDIT_GET_SESSIONID: return 0; break; + case AUDIT_GET_CAPCONTID: + case AUDIT_SET_CAPCONTID: + case AUDIT_GET_CONTID: + case AUDIT_SET_CONTID: + if (!netlink_capable(skb, CAP_AUDIT_CONTROL) && !audit_get_capcontid(current)) + return -EPERM; + return 0; + break; default: /* do more checks below */ break; } @@ -1227,8 +1235,6 @@ static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type) case AUDIT_TTY_SET: case AUDIT_TRIM: case AUDIT_MAKE_EQUIV: - case AUDIT_GET_CONTID: - case AUDIT_SET_CONTID: case AUDIT_SET_LOGINUID: /* Only support auditd and auditctl in initial pid namespace * for now. */ @@ -1304,6 +1310,23 @@ static int audit_get_contid_status(struct sk_buff *skb) return 0; } +static int audit_get_capcontid_status(struct sk_buff *skb) +{ + struct nlmsghdr *nlh = nlmsg_hdr(skb); + u32 seq = nlh->nlmsg_seq; + void *data = nlmsg_data(nlh); + struct audit_capcontid_status cs; + + cs.pid = ((struct audit_capcontid_status *)data)->pid; + if (!cs.pid) + cs.pid = task_tgid_nr(current); + rcu_read_lock(); + cs.enable = audit_get_capcontid(find_task_by_vpid(cs.pid)); + rcu_read_unlock(); + audit_send_reply(skb, seq, AUDIT_GET_CAPCONTID, 0, 0, &cs, sizeof(cs)); + return 0; +} + struct audit_loginuid_status { uid_t loginuid; }; static int audit_get_loginuid_status(struct sk_buff *skb) @@ -1779,6 +1802,27 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) if (err) return err; break; + case AUDIT_SET_CAPCONTID: { + struct audit_capcontid_status *s = data; + struct task_struct *tsk; + + /* check if new data is valid */ + if (nlmsg_len(nlh) < sizeof(*s)) + return -EINVAL; + tsk = find_get_task_by_vpid(s->pid); + if (!tsk) + return -EINVAL; + + err = audit_set_capcontid(tsk, s->enable); + put_task_struct(tsk); + return err; + break; + } + case AUDIT_GET_CAPCONTID: + err = audit_get_capcontid_status(skb); + if (err) + return err; + break; case AUDIT_SET_LOGINUID: { uid_t *loginuid = data; kuid_t kloginuid; @@ -2711,6 +2755,56 @@ static struct task_struct *audit_cont_owner(struct task_struct *tsk) return NULL; } +int audit_set_capcontid(struct task_struct *task, u32 enable) +{ + u32 oldcapcontid; + int rc = 0; + struct audit_buffer *ab; + uid_t uid; + struct tty_struct *tty; + char comm[sizeof(current->comm)]; + + if (!task->audit) + return -ENOPROTOOPT; + oldcapcontid = audit_get_capcontid(task); + /* if task is not descendant, block */ + if (task == current) + rc = -EBADSLT; + else if (!task_is_descendant(current, task)) + rc = -EXDEV; + else if (current_user_ns() == &init_user_ns) { + if (!capable(CAP_AUDIT_CONTROL) && !audit_get_capcontid(current)) + rc = -EPERM; + } + if (!rc) + task->audit->capcontid = enable; + + if (!audit_enabled) + return rc; + + ab = audit_log_start(audit_context(), GFP_KERNEL, AUDIT_SET_CAPCONTID); + if (!ab) + return rc; + + uid = from_kuid(&init_user_ns, task_uid(current)); + tty = audit_get_tty(); + audit_log_format(ab, + "opid=%d capcontid=%u old-capcontid=%u pid=%d uid=%u auid=%u tty=%s ses=%u", + task_tgid_nr(task), enable, oldcapcontid, + task_tgid_nr(current), uid, + from_kuid(&init_user_ns, audit_get_loginuid(current)), + tty ? tty_name(tty) : "(none)", + audit_get_sessionid(current)); + audit_put_tty(tty); + audit_log_task_context(ab); + audit_log_format(ab, " comm="); + audit_log_untrustedstring(ab, get_task_comm(comm, current)); + audit_log_d_path_exe(ab, current->mm); + audit_log_format(ab, " res=%d", !rc); + audit_log_end(ab); + return rc; +} + /* * audit_set_contid - set current task's audit contid * @task: target task diff --git a/kernel/audit.h b/kernel/audit.h index cb25341c1a0f..ac4694e88485 100644 --- a/kernel/audit.h +++ b/kernel/audit.h @@ -231,6 +231,11 @@ struct audit_contid_status { u64 id; }; +struct audit_capcontid_status { + pid_t pid; + u32 enable; +}; + #define AUDIT_CONTID_DEPTH 5 /* Indicates that audit should log the full pathname. */ From patchwork Thu Sep 19 01:22:38 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Guy Briggs X-Patchwork-Id: 11151467 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 79E8A1745 for ; Thu, 19 Sep 2019 01:27:49 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 62DB021927 for ; Thu, 19 Sep 2019 01:27:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2388044AbfISB1m (ORCPT ); Wed, 18 Sep 2019 21:27:42 -0400 Received: from mx1.redhat.com ([209.132.183.28]:50522 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387591AbfISB1m (ORCPT ); Wed, 18 Sep 2019 21:27:42 -0400 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 066FE3084295; Thu, 19 Sep 2019 01:27:42 +0000 (UTC) Received: from madcap2.tricolour.ca (ovpn-112-19.phx2.redhat.com [10.3.112.19]) by smtp.corp.redhat.com (Postfix) with ESMTP id 31F5B6B49C; Thu, 19 Sep 2019 01:27:33 +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, dwalsh@redhat.com, mpatel@redhat.com, Richard Guy Briggs Subject: [PATCH ghak90 V7 21/21] audit: add proc interface for capcontid Date: Wed, 18 Sep 2019 21:22:38 -0400 Message-Id: <67a482f9dcde6362bbca2a2facb24a3d68e0c07a.1568834525.git.rgb@redhat.com> In-Reply-To: References: In-Reply-To: References: X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.40]); Thu, 19 Sep 2019 01:27:42 +0000 (UTC) Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org Add a /proc interface to capcontid for testing purposes. This isn't intended to be merged upstream. Container orchestrators/engines are expected to link to libaudit to use the functions audit_set_capcontid() and audit_get_capcontid. Signed-off-by: Richard Guy Briggs --- fs/proc/base.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/fs/proc/base.c b/fs/proc/base.c index 26091800180c..283ef8e006e7 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -1360,6 +1360,59 @@ static ssize_t proc_contid_write(struct file *file, const char __user *buf, .write = proc_contid_write, .llseek = generic_file_llseek, }; + +static ssize_t proc_capcontid_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + struct inode *inode = file_inode(file); + struct task_struct *task = get_proc_task(inode); + ssize_t length; + char tmpbuf[TMPBUFLEN]; + + if (!task) + return -ESRCH; + /* if we don't have caps, reject */ + if (!capable(CAP_AUDIT_CONTROL) && !audit_get_capcontid(current)) + return -EPERM; + length = scnprintf(tmpbuf, TMPBUFLEN, "%u", audit_get_capcontid(task)); + put_task_struct(task); + return simple_read_from_buffer(buf, count, ppos, tmpbuf, length); +} + +static ssize_t proc_capcontid_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + struct inode *inode = file_inode(file); + u32 capcontid; + int rv; + struct task_struct *task = get_proc_task(inode); + + if (!task) + return -ESRCH; + if (*ppos != 0) { + /* No partial writes. */ + put_task_struct(task); + return -EINVAL; + } + + rv = kstrtou32_from_user(buf, count, 10, &capcontid); + if (rv < 0) { + put_task_struct(task); + return rv; + } + + rv = audit_set_capcontid(task, capcontid); + put_task_struct(task); + if (rv < 0) + return rv; + return count; +} + +static const struct file_operations proc_capcontid_operations = { + .read = proc_capcontid_read, + .write = proc_capcontid_write, + .llseek = generic_file_llseek, +}; #endif #ifdef CONFIG_FAULT_INJECTION @@ -3121,6 +3174,7 @@ static int proc_stack_depth(struct seq_file *m, struct pid_namespace *ns, REG("loginuid", S_IWUSR|S_IRUGO, proc_loginuid_operations), REG("sessionid", S_IRUGO, proc_sessionid_operations), REG("audit_containerid", S_IWUSR|S_IRUSR, proc_contid_operations), + REG("audit_capcontainerid", S_IWUSR|S_IRUSR|S_IRUSR, proc_capcontid_operations), #endif #ifdef CONFIG_FAULT_INJECTION REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations), @@ -3522,6 +3576,7 @@ static int proc_tid_comm_permission(struct inode *inode, int mask) REG("loginuid", S_IWUSR|S_IRUGO, proc_loginuid_operations), REG("sessionid", S_IRUGO, proc_sessionid_operations), REG("audit_containerid", S_IWUSR|S_IRUSR, proc_contid_operations), + REG("audit_capcontainerid", S_IWUSR|S_IRUSR|S_IRUSR, proc_capcontid_operations), #endif #ifdef CONFIG_FAULT_INJECTION REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations),