From patchwork Fri May 21 21:49:48 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Moore X-Patchwork-Id: 12273819 X-Patchwork-Delegate: paul@paul-moore.com Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.7 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1BF6DC4707A for ; Fri, 21 May 2021 21:49:52 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id EDCF0613DB for ; Fri, 21 May 2021 21:49:51 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229659AbhEUVvO (ORCPT ); Fri, 21 May 2021 17:51:14 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56852 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229639AbhEUVvO (ORCPT ); Fri, 21 May 2021 17:51:14 -0400 Received: from mail-qk1-x72d.google.com (mail-qk1-x72d.google.com [IPv6:2607:f8b0:4864:20::72d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 823A8C0613CE for ; Fri, 21 May 2021 14:49:50 -0700 (PDT) Received: by mail-qk1-x72d.google.com with SMTP id i5so14066071qkf.12 for ; Fri, 21 May 2021 14:49:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=paul-moore-com.20150623.gappssmtp.com; s=20150623; h=subject:from:to:date:message-id:in-reply-to:references:user-agent :mime-version:content-transfer-encoding; bh=MBgujV95p1ux4Z0lQ9e0ZsZFW8/3ifOLJEoE9gqJeMM=; b=U2b3Zd+j5EzMt39NJhIRBTUjL6a/2ULPAOS0G9blnCFUtPHx+N6w/5XYs9Q6R+tY7k BSfuTxTuhBah3uqm6NghrCArr6VPdkpAkRWk1KahVd6SLBCEeSWv52Flg8MJoIAu94mb mdjXQ169V7BcOfqq3TsKaX1JcRwo5KbGDKUFFKXDMCYMXHXD9CF8mj5etUQPHJInRyFH 1bIu5++aqEoXm06i1YB3UXfArMrAr82oiKMxaqUtfmRk9I/kLYG22iAOsRTrs5fBHFpY UU/U2I0XQq2bniX0JvZa6mLWPcrb9AmcajOCugNn6zBJKvBc59fuDC8fFcq33OCABiHZ 3luw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:subject:from:to:date:message-id:in-reply-to :references:user-agent:mime-version:content-transfer-encoding; bh=MBgujV95p1ux4Z0lQ9e0ZsZFW8/3ifOLJEoE9gqJeMM=; b=Zr53q5ZbFELU/Qd6kVflhhHZbVkffLt06y/I8wskwDZmd6wM5B0TCJVk/C/dBYvqa9 bV0dBBu4WhWY8jZ/HIlAiW62cTeOK6NatNdw8bGIGzRyL+P+Ua/BjpoZeABN3Ui59Map 35CVHtPZA5jhXdcKLjbUQsEfHVzMCv2AoM1iQaOsWPm4uBJCvOiO37B4UanaS+LZRtmy ibw4+Er4xTB5eiI723DR3ZtCHuyiYdXMzj3blNNJiNb2Ya2pK1qrOt2Y/j0+vjLDCf3+ kApqyVBHyHH1GayazgwVjQLvns1m3rWYGr6e/68iINceu0KbGVuwO/zKjJC9QM8Q/PCw It8w== X-Gm-Message-State: AOAM532fQPAHlcEUnHPaYyKWH12aydDr1wPegdfOJopCQ7kRrJBaSxJg SpKUiQDUhix4gVJPF0xy5/5p X-Google-Smtp-Source: ABdhPJwn8C4xL0zpucZBFF5ean2xcuT6W4lWFjyGg7ttG5YcnmiHmwRIugTnSIxvJ/VQeKF2EftkhQ== X-Received: by 2002:a37:2714:: with SMTP id n20mr14357489qkn.434.1621633789468; Fri, 21 May 2021 14:49:49 -0700 (PDT) Received: from localhost (pool-96-237-52-188.bstnma.fios.verizon.net. [96.237.52.188]) by smtp.gmail.com with ESMTPSA id b17sm5068340qtb.78.2021.05.21.14.49.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 21 May 2021 14:49:49 -0700 (PDT) Subject: [RFC PATCH 1/9] audit: prepare audit_context for use in calling contexts beyond syscalls From: Paul Moore To: linux-security-module@vger.kernel.org, selinux@vger.kernel.org, linux-audit@redhat.com, io-uring@vger.kernel.org, linux-fsdevel@vger.kernel.org, Kumar Kartikeya Dwivedi , Jens Axboe , Alexander Viro Date: Fri, 21 May 2021 17:49:48 -0400 Message-ID: <162163378838.8379.13998476482108256664.stgit@sifl> In-Reply-To: <162163367115.8379.8459012634106035341.stgit@sifl> References: <162163367115.8379.8459012634106035341.stgit@sifl> User-Agent: StGit/1.1 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: selinux@vger.kernel.org WARNING - This is a work in progress and should not be merged anywhere important. It is almost surely not complete, and while it probably compiles it likely hasn't been booted and will do terrible things. You have been warned. This patch cleans up some of our audit_context handling by abstracting out the reset and return code fixup handling to dedicated functions. Not only does this help make things easier to read and inspect, it allows for easier reuse be future patches. We also convert the simple audit_context->in_syscall flag into an enum which can be used to by future patches to indicate a calling context other than the syscall context. Thanks to Richard Guy Briggs for review and feedback. Acked-by: Richard Guy Briggs Signed-off-by: Paul Moore --- kernel/audit.h | 5 + kernel/auditsc.c | 255 +++++++++++++++++++++++++++++++++++------------------- 2 files changed, 167 insertions(+), 93 deletions(-) diff --git a/kernel/audit.h b/kernel/audit.h index 1522e100fd17..fba180de5912 100644 --- a/kernel/audit.h +++ b/kernel/audit.h @@ -97,7 +97,10 @@ struct audit_proctitle { /* The per-task audit context. */ struct audit_context { int dummy; /* must be the first element */ - int in_syscall; /* 1 if task is in a syscall */ + enum { + AUDIT_CTX_UNUSED, /* audit_context is currently unused */ + AUDIT_CTX_SYSCALL, /* in use by syscall */ + } context; 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 175ef6f3ea4e..cc89e9f9a753 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -909,10 +909,80 @@ static inline void audit_free_aux(struct audit_context *context) context->aux = aux->next; kfree(aux); } + context->aux = NULL; while ((aux = context->aux_pids)) { context->aux_pids = aux->next; kfree(aux); } + context->aux_pids = NULL; +} + +/** + * audit_reset_context - reset a audit_context structure + * @ctx: the audit_context to reset + * + * All fields in the audit_context will be reset to an initial state, all + * references held by fields will be dropped, and private memory will be + * released. When this function returns the audit_context will be suitable + * for reuse, so long as the passed context is not NULL or a dummy context. + */ +static void audit_reset_context(struct audit_context *ctx) +{ + if (!ctx) + return; + + /* if ctx is non-null, reset the "ctx->state" regardless */ + ctx->context = AUDIT_CTX_UNUSED; + if (ctx->dummy) + return; + + /* + * NOTE: It shouldn't matter in what order we release the fields, so + * release them in the order in which they appear in the struct; + * this gives us some hope of quickly making sure we are + * resetting the audit_context properly. + * + * Other things worth mentioning: + * - we don't reset "dummy" + * - we don't reset "state", we do reset "current_state" + * - we preserver "filterkey" if "state" is AUDIT_RECORD_CONTEXT + * - much of this is likely overkill, but play it safe for now + * - we really need to work on improving the audit_context struct + */ + + ctx->current_state = ctx->state; + ctx->serial = 0; + ctx->major = 0; + ctx->ctime = (struct timespec64){ .tv_sec = 0, .tv_nsec = 0 }; + memset(ctx->argv, 0, sizeof(ctx->argv)); + ctx->return_code = 0; + ctx->prio = (ctx->state == AUDIT_RECORD_CONTEXT ? ~0ULL : 0); + ctx->return_valid = AUDITSC_INVALID; + audit_free_names(ctx); + if (ctx->state != AUDIT_RECORD_CONTEXT) { + kfree(ctx->filterkey); + ctx->filterkey = NULL; + } + audit_free_aux(ctx); + kfree(ctx->sockaddr); + ctx->sockaddr = NULL; + ctx->sockaddr_len = 0; + ctx->pid = ctx->ppid = 0; + ctx->uid = ctx->euid = ctx->suid = ctx->fsuid = KUIDT_INIT(0); + ctx->gid = ctx->egid = ctx->sgid = ctx->fsgid = KGIDT_INIT(0); + ctx->personality = 0; + ctx->arch = 0; + ctx->target_pid = 0; + ctx->target_auid = ctx->target_uid = KUIDT_INIT(0); + ctx->target_sessionid = 0; + ctx->target_sid = 0; + ctx->target_comm[0] = '\0'; + unroll_tree_refs(ctx, NULL, 0); + WARN_ON(!list_empty(&ctx->killed_trees)); + ctx->type = 0; + audit_free_module(ctx); + ctx->fds[0] = -1; + audit_proctitle_free(ctx); } static inline struct audit_context *audit_alloc_context(enum audit_state state) @@ -922,6 +992,7 @@ static inline struct audit_context *audit_alloc_context(enum audit_state state) context = kzalloc(sizeof(*context), GFP_KERNEL); if (!context) return NULL; + context->context = AUDIT_CTX_UNUSED; context->state = state; context->prio = state == AUDIT_RECORD_CONTEXT ? ~0ULL : 0; INIT_LIST_HEAD(&context->killed_trees); @@ -947,7 +1018,7 @@ int audit_alloc(struct task_struct *tsk) char *key = NULL; if (likely(!audit_ever_enabled)) - return 0; /* Return if not auditing. */ + return 0; state = audit_filter_task(tsk, &key); if (state == AUDIT_DISABLED) { @@ -969,14 +1040,10 @@ int audit_alloc(struct task_struct *tsk) static inline void audit_free_context(struct audit_context *context) { - audit_free_module(context); - audit_free_names(context); - unroll_tree_refs(context, NULL, 0); + /* resetting is extra work, but it is likely just noise */ + audit_reset_context(context); free_tree_refs(context); - audit_free_aux(context); kfree(context->filterkey); - kfree(context->sockaddr); - audit_proctitle_free(context); kfree(context); } @@ -1479,29 +1546,35 @@ static void audit_log_exit(void) context->personality = current->personality; - ab = audit_log_start(context, GFP_KERNEL, AUDIT_SYSCALL); - if (!ab) - return; /* audit_panic has been called */ - audit_log_format(ab, "arch=%x syscall=%d", - context->arch, context->major); - if (context->personality != PER_LINUX) - audit_log_format(ab, " per=%lx", context->personality); - if (context->return_valid != AUDITSC_INVALID) - audit_log_format(ab, " success=%s exit=%ld", - (context->return_valid==AUDITSC_SUCCESS)?"yes":"no", - context->return_code); - - audit_log_format(ab, - " a0=%lx a1=%lx a2=%lx a3=%lx items=%d", - context->argv[0], - context->argv[1], - context->argv[2], - context->argv[3], - context->name_count); - - audit_log_task_info(ab); - audit_log_key(ab, context->filterkey); - audit_log_end(ab); + switch (context->context) { + case AUDIT_CTX_SYSCALL: + ab = audit_log_start(context, GFP_KERNEL, AUDIT_SYSCALL); + if (!ab) + return; + audit_log_format(ab, "arch=%x syscall=%d", + context->arch, context->major); + if (context->personality != PER_LINUX) + audit_log_format(ab, " per=%lx", context->personality); + if (context->return_valid != AUDITSC_INVALID) + audit_log_format(ab, " success=%s exit=%ld", + (context->return_valid == AUDITSC_SUCCESS ? + "yes" : "no"), + context->return_code); + audit_log_format(ab, + " a0=%lx a1=%lx a2=%lx a3=%lx items=%d", + context->argv[0], + context->argv[1], + context->argv[2], + context->argv[3], + context->name_count); + audit_log_task_info(ab); + audit_log_key(ab, context->filterkey); + audit_log_end(ab); + break; + default: + BUG(); + break; + } for (aux = context->aux; aux; aux = aux->next) { @@ -1591,14 +1664,15 @@ static void audit_log_exit(void) audit_log_name(context, n, NULL, i++, &call_panic); } - audit_log_proctitle(); + if (context->context == AUDIT_CTX_SYSCALL) + audit_log_proctitle(); /* Send end of event record to help user space know we are finished */ ab = audit_log_start(context, GFP_KERNEL, AUDIT_EOE); if (ab) audit_log_end(ab); if (call_panic) - audit_panic("error converting sid to string"); + audit_panic("error in audit_log_exit()"); } /** @@ -1614,6 +1688,7 @@ void __audit_free(struct task_struct *tsk) if (!context) return; + /* this may generate CONFIG_CHANGE records */ if (!list_empty(&context->killed_trees)) audit_kill_trees(context); @@ -1622,7 +1697,8 @@ void __audit_free(struct task_struct *tsk) * random task_struct that doesn't doesn't have any meaningful data we * need to log via audit_log_exit(). */ - if (tsk == current && !context->dummy && context->in_syscall) { + if (tsk == current && !context->dummy && + context->context == AUDIT_CTX_SYSCALL) { context->return_valid = AUDITSC_INVALID; context->return_code = 0; @@ -1636,6 +1712,34 @@ void __audit_free(struct task_struct *tsk) audit_free_context(context); } +/** + * audit_return_fixup - fixup the return codes in the audit_context + * @ctx: the audit_context + * @success: true/false value to indicate if the operation succeeded or not + * @code: operation return code + * + * We need to fixup the return code in the audit logs if the actual return + * codes are later going to be fixed by the arch specific signal handlers. + */ +static void audit_return_fixup(struct audit_context *ctx, + int success, long code) +{ + /* + * This is actually a test for: + * (rc == ERESTARTSYS ) || (rc == ERESTARTNOINTR) || + * (rc == ERESTARTNOHAND) || (rc == ERESTART_RESTARTBLOCK) + * + * but is faster than a bunch of || + */ + if (unlikely(code <= -ERESTARTSYS) && + (code >= -ERESTART_RESTARTBLOCK) && + (code != -ENOIOCTLCMD)) + ctx->return_code = -EINTR; + else + ctx->return_code = code; + ctx->return_valid = (success ? AUDITSC_SUCCESS : AUDITSC_FAILURE); +} + /** * __audit_syscall_entry - fill in an audit record at syscall entry * @major: major syscall type (function) @@ -1661,7 +1765,12 @@ void __audit_syscall_entry(int major, unsigned long a1, unsigned long a2, if (!audit_enabled || !context) return; - BUG_ON(context->in_syscall || context->name_count); + WARN_ON(context->context != AUDIT_CTX_UNUSED); + WARN_ON(context->name_count); + if (context->context != AUDIT_CTX_UNUSED || context->name_count) { + audit_panic("unrecoverable error in audit_syscall_entry()"); + return; + } state = context->state; if (state == AUDIT_DISABLED) @@ -1680,10 +1789,8 @@ void __audit_syscall_entry(int major, unsigned long a1, unsigned long a2, context->argv[1] = a2; context->argv[2] = a3; context->argv[3] = a4; - context->serial = 0; - context->in_syscall = 1; + context->context = AUDIT_CTX_SYSCALL; context->current_state = state; - context->ppid = 0; ktime_get_coarse_real_ts64(&context->ctime); } @@ -1700,63 +1807,27 @@ void __audit_syscall_entry(int major, unsigned long a1, unsigned long a2, */ void __audit_syscall_exit(int success, long return_code) { - struct audit_context *context; + struct audit_context *context = audit_context(); - context = audit_context(); - if (!context) - return; + if (!context || context->dummy || + context->context != AUDIT_CTX_SYSCALL) + goto out; + /* this may generate CONFIG_CHANGE records */ if (!list_empty(&context->killed_trees)) audit_kill_trees(context); - if (!context->dummy && context->in_syscall) { - if (success) - context->return_valid = AUDITSC_SUCCESS; - else - context->return_valid = AUDITSC_FAILURE; - - /* - * we need to fix up the return code in the audit logs if the - * actual return codes are later going to be fixed up by the - * arch specific signal handlers - * - * This is actually a test for: - * (rc == ERESTARTSYS ) || (rc == ERESTARTNOINTR) || - * (rc == ERESTARTNOHAND) || (rc == ERESTART_RESTARTBLOCK) - * - * but is faster than a bunch of || - */ - if (unlikely(return_code <= -ERESTARTSYS) && - (return_code >= -ERESTART_RESTARTBLOCK) && - (return_code != -ENOIOCTLCMD)) - context->return_code = -EINTR; - else - context->return_code = return_code; - - audit_filter_syscall(current, context); - audit_filter_inodes(current, context); - if (context->current_state == AUDIT_RECORD_CONTEXT) - audit_log_exit(); - } + /* run through both filters to ensure we set the filterkey properly */ + audit_filter_syscall(current, context); + audit_filter_inodes(current, context); + if (context->current_state < AUDIT_RECORD_CONTEXT) + goto out; - context->in_syscall = 0; - context->prio = context->state == AUDIT_RECORD_CONTEXT ? ~0ULL : 0; + audit_return_fixup(context, success, return_code); + audit_log_exit(); - audit_free_module(context); - audit_free_names(context); - unroll_tree_refs(context, NULL, 0); - audit_free_aux(context); - context->aux = NULL; - context->aux_pids = NULL; - context->target_pid = 0; - context->target_sid = 0; - context->sockaddr_len = 0; - context->type = 0; - context->fds[0] = -1; - if (context->state != AUDIT_RECORD_CONTEXT) { - kfree(context->filterkey); - context->filterkey = NULL; - } +out: + audit_reset_context(context); } static inline void handle_one(const struct inode *inode) @@ -1905,7 +1976,7 @@ void __audit_getname(struct filename *name) struct audit_context *context = audit_context(); struct audit_names *n; - if (!context->in_syscall) + if (context->context == AUDIT_CTX_UNUSED) return; n = audit_alloc_name(context, AUDIT_TYPE_UNKNOWN); @@ -1977,7 +2048,7 @@ void __audit_inode(struct filename *name, const struct dentry *dentry, struct list_head *list = &audit_filter_list[AUDIT_FILTER_FS]; int i; - if (!context->in_syscall) + if (context->context == AUDIT_CTX_UNUSED) return; rcu_read_lock(); @@ -2095,7 +2166,7 @@ void __audit_inode_child(struct inode *parent, struct list_head *list = &audit_filter_list[AUDIT_FILTER_FS]; int i; - if (!context->in_syscall) + if (context->context == AUDIT_CTX_UNUSED) return; rcu_read_lock(); @@ -2194,7 +2265,7 @@ EXPORT_SYMBOL_GPL(__audit_inode_child); int auditsc_get_stamp(struct audit_context *ctx, struct timespec64 *t, unsigned int *serial) { - if (!ctx->in_syscall) + if (ctx->context == AUDIT_CTX_UNUSED) return 0; if (!ctx->serial) ctx->serial = audit_serial(); @@ -2686,7 +2757,7 @@ void audit_seccomp_actions_logged(const char *names, const char *old_names, struct list_head *audit_killed_trees(void) { struct audit_context *ctx = audit_context(); - if (likely(!ctx || !ctx->in_syscall)) + if (likely(!ctx || ctx->context == AUDIT_CTX_UNUSED)) return NULL; return &ctx->killed_trees; } From patchwork Fri May 21 21:49:54 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Moore X-Patchwork-Id: 12273821 X-Patchwork-Delegate: paul@paul-moore.com Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.7 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4F90AC47080 for ; Fri, 21 May 2021 21:50:01 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 33940613EE for ; Fri, 21 May 2021 21:50:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229689AbhEUVvY (ORCPT ); Fri, 21 May 2021 17:51:24 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56886 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229589AbhEUVvV (ORCPT ); Fri, 21 May 2021 17:51:21 -0400 Received: from mail-qt1-x82f.google.com (mail-qt1-x82f.google.com [IPv6:2607:f8b0:4864:20::82f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 970D7C06138A for ; Fri, 21 May 2021 14:49:56 -0700 (PDT) Received: by mail-qt1-x82f.google.com with SMTP id c10so16385456qtx.10 for ; Fri, 21 May 2021 14:49:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=paul-moore-com.20150623.gappssmtp.com; s=20150623; h=subject:from:to:date:message-id:in-reply-to:references:user-agent :mime-version:content-transfer-encoding; bh=iSgpRj5Hour/3hkupmwfN57A0GGiHh5LrLcjvy8Df9M=; b=FpppsknsJkRe81xvMu4/QCONpbLkpBw3JH5aZo571BJNmn1fEVhtLxPigKEQuY1GCT b59HE4o2HYdXDtgz2MIPTaS2FNJZqlQSVAX0Ebbe7RCrJaWJHDusuHl+W2yGKZeBfJRQ pV/DO7QeO77kyHYeb2DXC5MI2UNmhbrRMTGMuCnjsu6SsSTRUdln6ElC4pCmpQIlUlZy h3VY7frstLdC+gMynU+oNcHLxKC4ZfmVe4+waQmuq9EZlQUo0lDiNhTv3blC+O/fhQkm TPx+h3maEqSZEysKvDLVImITOEhGf0qAiHIF2n4zaUkALq6zGMYn57hfFlIEO0Ktjo5V +/fw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:subject:from:to:date:message-id:in-reply-to :references:user-agent:mime-version:content-transfer-encoding; bh=iSgpRj5Hour/3hkupmwfN57A0GGiHh5LrLcjvy8Df9M=; b=RGVsJnU0k1zl1oVlUQMcVOd39ky7XPcoWeohplVjJt7Dfvg3y3C5NBfNJsMNR34L4I ee+xRfiyhEAGwHXP0+giD0Zc7bmiFScU8/THLNMySSFvrBkJoHZ7GDfYLlCxeGfroCfH 5eMnMDe7Jl+nS4YR62D4jDpLBJdS01Q1JMEo0z711xLZEz4+O5Jff227sM4pUUKrlrq2 7kl2DsKfKh7GiET5RUpnaik5Ak1Q3LDSJfQuV80VKVd2YZhf4ydQWErGpz9EXxEIpuCJ UwfISg95E1xNe5Ly8bIq8QB7dOPlkMj82pkTqyDj7xCmIcaa/sWCaMUmfXr094uPh04P yFHQ== X-Gm-Message-State: AOAM533I+z01zrOX7yg4lMCokqETvhM67+zGTdBT+4LnOGdUV/A6x7yC qUPER5Our0D5rkCcSLz9MXdo X-Google-Smtp-Source: ABdhPJy85UtPENJaxrKmwNe2zbfXnR93Kqk0nmsG7uyr1nwIqQlZAV9n9ccNl0ey9XmuCZ3KVV/qDg== X-Received: by 2002:ac8:795a:: with SMTP id r26mr14178923qtt.382.1621633795602; Fri, 21 May 2021 14:49:55 -0700 (PDT) Received: from localhost (pool-96-237-52-188.bstnma.fios.verizon.net. [96.237.52.188]) by smtp.gmail.com with ESMTPSA id f19sm6022512qkg.70.2021.05.21.14.49.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 21 May 2021 14:49:55 -0700 (PDT) Subject: [RFC PATCH 2/9] audit,io_uring,io-wq: add some basic audit support to io_uring From: Paul Moore To: linux-security-module@vger.kernel.org, selinux@vger.kernel.org, linux-audit@redhat.com, io-uring@vger.kernel.org, linux-fsdevel@vger.kernel.org, Kumar Kartikeya Dwivedi , Jens Axboe , Alexander Viro Date: Fri, 21 May 2021 17:49:54 -0400 Message-ID: <162163379461.8379.9691291608621179559.stgit@sifl> In-Reply-To: <162163367115.8379.8459012634106035341.stgit@sifl> References: <162163367115.8379.8459012634106035341.stgit@sifl> User-Agent: StGit/1.1 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: selinux@vger.kernel.org WARNING - This is a work in progress and should not be merged anywhere important. It is almost surely not complete, and while it probably compiles it likely hasn't been booted and will do terrible things. You have been warned. This patch adds basic auditing to io_uring operations, regardless of their context. This is accomplished by allocating audit_context structures for the io-wq worker and io_uring SQPOLL kernel threads as well as explicitly auditing the io_uring operations in io_issue_sqe(). The io_uring operations are audited using a new AUDIT_URINGOP record, an example is shown below: % Thanks to Richard Guy Briggs for review and feedback. Signed-off-by: Paul Moore --- fs/io-wq.c | 4 + fs/io_uring.c | 11 +++ include/linux/audit.h | 17 ++++ include/uapi/linux/audit.h | 1 kernel/audit.h | 2 + kernel/auditsc.c | 173 ++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 208 insertions(+) diff --git a/fs/io-wq.c b/fs/io-wq.c index 5361a9b4b47b..8af09a3336e0 100644 --- a/fs/io-wq.c +++ b/fs/io-wq.c @@ -16,6 +16,7 @@ #include #include #include +#include #include "io-wq.h" @@ -535,6 +536,8 @@ static int io_wqe_worker(void *data) snprintf(buf, sizeof(buf), "iou-wrk-%d", wq->task->pid); set_task_comm(current, buf); + audit_alloc_kernel(current); + while (!test_bit(IO_WQ_BIT_EXIT, &wq->state)) { long ret; @@ -573,6 +576,7 @@ static int io_wqe_worker(void *data) raw_spin_unlock_irq(&wqe->lock); } + audit_free(current); io_worker_exit(worker); return 0; } diff --git a/fs/io_uring.c b/fs/io_uring.c index e481ac8a757a..e9941d1ad8fd 100644 --- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -78,6 +78,7 @@ #include #include #include +#include #define CREATE_TRACE_POINTS #include @@ -6105,6 +6106,9 @@ static int io_issue_sqe(struct io_kiocb *req, unsigned int issue_flags) if (req->work.creds && req->work.creds != current_cred()) creds = override_creds(req->work.creds); + if (req->opcode < IORING_OP_LAST) + audit_uring_entry(req->opcode); + switch (req->opcode) { case IORING_OP_NOP: ret = io_nop(req, issue_flags); @@ -6211,6 +6215,9 @@ static int io_issue_sqe(struct io_kiocb *req, unsigned int issue_flags) break; } + if (req->opcode < IORING_OP_LAST) + audit_uring_exit(!ret, ret); + if (creds) revert_creds(creds); @@ -6827,6 +6834,8 @@ static int io_sq_thread(void *data) set_cpus_allowed_ptr(current, cpu_online_mask); current->flags |= PF_NO_SETAFFINITY; + audit_alloc_kernel(current); + mutex_lock(&sqd->lock); /* a user may had exited before the thread started */ io_run_task_work_head(&sqd->park_task_work); @@ -6916,6 +6925,8 @@ static int io_sq_thread(void *data) io_run_task_work_head(&sqd->park_task_work); mutex_unlock(&sqd->lock); + audit_free(current); + complete(&sqd->exited); do_exit(0); } diff --git a/include/linux/audit.h b/include/linux/audit.h index 82b7c1116a85..6a0c013bc7de 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -286,7 +286,10 @@ 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 int audit_alloc_kernel(struct task_struct *task); extern void __audit_free(struct task_struct *task); +extern void __audit_uring_entry(u8 op); +extern void __audit_uring_exit(int success, long code); 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); @@ -323,6 +326,16 @@ static inline void audit_free(struct task_struct *task) if (unlikely(task->audit_context)) __audit_free(task); } +static inline void audit_uring_entry(u8 op) +{ + if (unlikely(audit_context())) + __audit_uring_entry(op); +} +static inline void audit_uring_exit(int success, long code) +{ + if (unlikely(audit_context())) + __audit_uring_exit(success, code); +} static inline void audit_syscall_entry(int major, unsigned long a0, unsigned long a1, unsigned long a2, unsigned long a3) @@ -554,6 +567,10 @@ static inline int audit_alloc(struct task_struct *task) { return 0; } +static inline int audit_alloc_kernel(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, diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h index cd2d8279a5e4..b26e0c435e8b 100644 --- a/include/uapi/linux/audit.h +++ b/include/uapi/linux/audit.h @@ -118,6 +118,7 @@ #define AUDIT_TIME_ADJNTPVAL 1333 /* NTP value adjustment */ #define AUDIT_BPF 1334 /* BPF subsystem */ #define AUDIT_EVENT_LISTENER 1335 /* Task joined multicast read socket */ +#define AUDIT_URINGOP 1336 /* io_uring operation */ #define AUDIT_AVC 1400 /* SE Linux avc denial or grant */ #define AUDIT_SELINUX_ERR 1401 /* Internal SE Linux Errors */ diff --git a/kernel/audit.h b/kernel/audit.h index fba180de5912..50de827497ca 100644 --- a/kernel/audit.h +++ b/kernel/audit.h @@ -100,10 +100,12 @@ struct audit_context { enum { AUDIT_CTX_UNUSED, /* audit_context is currently unused */ AUDIT_CTX_SYSCALL, /* in use by syscall */ + AUDIT_CTX_URING, /* in use by io_uring */ } context; enum audit_state state, current_state; unsigned int serial; /* serial number for record */ int major; /* syscall number */ + int uring_op; /* uring operation */ struct timespec64 ctime; /* time of syscall entry */ unsigned long argv[4]; /* syscall arguments */ long return_code;/* syscall return code */ diff --git a/kernel/auditsc.c b/kernel/auditsc.c index cc89e9f9a753..729849d41631 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -953,6 +953,7 @@ static void audit_reset_context(struct audit_context *ctx) ctx->current_state = ctx->state; ctx->serial = 0; ctx->major = 0; + ctx->uring_op = 0; ctx->ctime = (struct timespec64){ .tv_sec = 0, .tv_nsec = 0 }; memset(ctx->argv, 0, sizeof(ctx->argv)); ctx->return_code = 0; @@ -1038,6 +1039,31 @@ int audit_alloc(struct task_struct *tsk) return 0; } +/** + * audit_alloc_kernel - allocate an audit_context for a kernel task + * @tsk: the kernel task + * + * Similar to the audit_alloc() function, but intended for kernel private + * threads. Returns zero on success, negative values on failure. + */ +int audit_alloc_kernel(struct task_struct *tsk) +{ + /* + * At the moment we are just going to call into audit_alloc() to + * simplify the code, but there two things to keep in mind with this + * approach: + * + * 1. Filtering internal kernel tasks is a bit laughable in almost all + * cases, but there is at least one case where there is a benefit: + * the '-a task,never' case allows the admin to effectively disable + * task auditing at runtime. + * + * 2. The {set,clear}_task_syscall_work() ops likely have zero effect + * on these internal kernel tasks, but they probably don't hurt either. + */ + return audit_alloc(tsk); +} + static inline void audit_free_context(struct audit_context *context) { /* resetting is extra work, but it is likely just noise */ @@ -1536,6 +1562,52 @@ static void audit_log_proctitle(void) audit_log_end(ab); } +/** + * audit_log_uring - generate a AUDIT_URINGOP record + * @ctx: the audit context + */ +static void audit_log_uring(struct audit_context *ctx) +{ + struct audit_buffer *ab; + const struct cred *cred; + + /* + * TODO: What do we log here? I'm tossing in a few things to start the + * conversation, but additional thought needs to go into this. + */ + + ab = audit_log_start(ctx, GFP_KERNEL, AUDIT_URINGOP); + if (!ab) + return; + cred = current_cred(); + audit_log_format(ab, "uring_op=%d", ctx->uring_op); + if (ctx->return_valid != AUDITSC_INVALID) + audit_log_format(ab, " success=%s exit=%ld", + (ctx->return_valid == AUDITSC_SUCCESS ? + "yes" : "no"), + ctx->return_code); + audit_log_format(ab, + " items=%d" + " ppid=%d pid=%d auid=%u uid=%u gid=%u" + " euid=%u suid=%u fsuid=%u" + " egid=%u sgid=%u fsgid=%u", + ctx->name_count, + task_ppid_nr(current), + task_tgid_nr(current), + from_kuid(&init_user_ns, audit_get_loginuid(current)), + from_kuid(&init_user_ns, cred->uid), + from_kgid(&init_user_ns, cred->gid), + from_kuid(&init_user_ns, cred->euid), + from_kuid(&init_user_ns, cred->suid), + from_kuid(&init_user_ns, cred->fsuid), + from_kgid(&init_user_ns, cred->egid), + from_kgid(&init_user_ns, cred->sgid), + from_kgid(&init_user_ns, cred->fsgid)); + audit_log_task_context(ab); + audit_log_key(ab, ctx->filterkey); + audit_log_end(ab); +} + static void audit_log_exit(void) { int i, call_panic = 0; @@ -1571,6 +1643,9 @@ static void audit_log_exit(void) audit_log_key(ab, context->filterkey); audit_log_end(ab); break; + case AUDIT_CTX_URING: + audit_log_uring(context); + break; default: BUG(); break; @@ -1740,6 +1815,104 @@ static void audit_return_fixup(struct audit_context *ctx, ctx->return_valid = (success ? AUDITSC_SUCCESS : AUDITSC_FAILURE); } +/** + * __audit_uring_entry - prepare the kernel task's audit context for io_uring + * @op: the io_uring opcode + * + * This is similar to audit_syscall_entry() but is intended for use by io_uring + * operations. + */ +void __audit_uring_entry(u8 op) +{ + struct audit_context *ctx = audit_context(); + + if (!audit_enabled || !ctx || ctx->state == AUDIT_DISABLED) + return; + + /* + * NOTE: It's possible that we can be called from the process' context + * before it returns to userspace, and before audit_syscall_exit() + * is called. In this case there is not much to do, just record + * the io_uring details and return. + */ + ctx->uring_op = op; + if (ctx->context == AUDIT_CTX_SYSCALL) + return; + + ctx->dummy = !audit_n_rules; + if (!ctx->dummy && ctx->state == AUDIT_BUILD_CONTEXT) + ctx->prio = 0; + + ctx->arch = syscall_get_arch(current); + ctx->context = AUDIT_CTX_URING; + ctx->current_state = ctx->state; + ktime_get_coarse_real_ts64(&ctx->ctime); +} + +/** + * __audit_uring_exit - wrap up the kernel task's audit context after io_uring + * @success: true/false value to indicate if the operation succeeded or not + * @code: operation return code + * + * This is similar to audit_syscall_exit() but is intended for use by io_uring + * operations. + */ +void __audit_uring_exit(int success, long code) +{ + struct audit_context *ctx = audit_context(); + + /* + * TODO: At some point we will likely want to filter on io_uring ops + * and other things similar to what we do for syscalls, but that + * is something for another day; just record what we can here. + */ + + if (!ctx || ctx->dummy) + goto out; + if (ctx->context == AUDIT_CTX_SYSCALL) { + /* + * NOTE: See the note in __audit_uring_entry() about the case + * where we may be called from process context before we + * return to userspace via audit_syscall_exit(). In this + * case we simply emit a URINGOP record and bail, the + * normal syscall exit handling will take care of + * everything else. + * It is also worth mentioning that when we are called, + * the current process creds may differ from the creds + * used during the normal syscall processing; keep that + * in mind if/when we move the record generation code. + */ + + /* + * We need to filter on the syscall info here to decide if we + * should emit a URINGOP record. I know it seems odd but this + * solves the problem where users have a filter to block *all* + * syscall records in the "exit" filter; we want to preserve + * the behavior here. + */ + audit_filter_syscall(current, ctx); + audit_filter_inodes(current, ctx); + if (ctx->current_state != AUDIT_RECORD_CONTEXT) + return; + + audit_log_uring(ctx); + return; + } + + /* this may generate CONFIG_CHANGE records */ + if (!list_empty(&ctx->killed_trees)) + audit_kill_trees(ctx); + + audit_filter_inodes(current, ctx); + if (ctx->current_state != AUDIT_RECORD_CONTEXT) + goto out; + audit_return_fixup(ctx, success, code); + audit_log_exit(); + +out: + audit_reset_context(ctx); +} + /** * __audit_syscall_entry - fill in an audit record at syscall entry * @major: major syscall type (function) From patchwork Fri May 21 21:50:00 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Moore X-Patchwork-Id: 12273823 X-Patchwork-Delegate: paul@paul-moore.com Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 36A65C04FF3 for ; Fri, 21 May 2021 21:50:05 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 1BECA613EA for ; Fri, 21 May 2021 21:50:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229634AbhEUVv1 (ORCPT ); Fri, 21 May 2021 17:51:27 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56920 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229693AbhEUVv0 (ORCPT ); Fri, 21 May 2021 17:51:26 -0400 Received: from mail-qt1-x831.google.com (mail-qt1-x831.google.com [IPv6:2607:f8b0:4864:20::831]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 961C6C061574 for ; Fri, 21 May 2021 14:50:02 -0700 (PDT) Received: by mail-qt1-x831.google.com with SMTP id g8so8885191qtp.4 for ; Fri, 21 May 2021 14:50:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=paul-moore-com.20150623.gappssmtp.com; s=20150623; h=subject:from:to:date:message-id:in-reply-to:references:user-agent :mime-version:content-transfer-encoding; bh=f09L8q774yElps/q7XGUKb4sfj1FooPKo1rTwaATVjY=; b=znVcls6DkVB0sVL6+jD/9JcWr4lkoF/HyhjCDR7szM/mtlcELz5tjynwyvADsaeGjJ Ci2ZtktqdQ7vvAHG1CkmU+JYeu8VskETW6DKJLrZC+AJ7gCBEKCtx5lBAfBs7soiX0un VSX4OhKcQ59USVuY3Mg8EmSpc7+09aWtrqR/2nogTANEz57o8MP5acAV8J3AkOhIYWR6 mRYJuxpkX4TG7NBxpMvcjB+0Ibl+aSyGFL+7KxBf3VKvwF4K1BUGSzWscUpnPOJXPQ7G F5Kb9PuJ/awOhVz17CLccVCBrJiePX4RhA74wRaXJutgnHX5NMdqM8BbBKLHP4ooNk8B 8ABQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:subject:from:to:date:message-id:in-reply-to :references:user-agent:mime-version:content-transfer-encoding; bh=f09L8q774yElps/q7XGUKb4sfj1FooPKo1rTwaATVjY=; b=ayg5kZEKl1VbJimAEzkjig/w4i22IPviGZHKB1fIyMeFv4x8BkQh3HPfEpYgBHETt+ VcxjR+yhUZbMdjdZWMFnSW/JrkAPYalIn2dRcE/V8i4qyeT8cfV9hZwuvXLHi1kBHeu1 M+SzHAo1yxkXeN8qhiwU/p1theqPw+LwFZLtRqPx7/zkL4IeNEncWCItI2IXUNEzVt5Z A8XwHy9Ja0mJ1sCIHUzKU1aLITAKf05lVnfwqOduSr5nwTyXr7e0CyTfNQTLm/w53c95 J99Fz740dxhV+ODJC/cP/QgbdfYZ/XWFOxV5YY1PcMIpt0z21nuDnZ01Mo9xZdKTKlyo t8QA== X-Gm-Message-State: AOAM532GMPASsH9k2suIFJgtnNzvOULOko3ip8GZ+V3lkTwFKU7l1Cht gbj4v8SM1qkiO7F/ooOW1cVr X-Google-Smtp-Source: ABdhPJxuLAQxlJc3vlIKo5MhSE0jYBBMFo/5T/BQwD64uE91fX+g/jksNikqD/j2cApaI8yZp4SBOA== X-Received: by 2002:a05:622a:144b:: with SMTP id v11mr14090251qtx.372.1621633801743; Fri, 21 May 2021 14:50:01 -0700 (PDT) Received: from localhost (pool-96-237-52-188.bstnma.fios.verizon.net. [96.237.52.188]) by smtp.gmail.com with ESMTPSA id s20sm5846297qke.2.2021.05.21.14.50.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 21 May 2021 14:50:01 -0700 (PDT) Subject: [RFC PATCH 3/9] audit: dev/test patch to force io_uring auditing From: Paul Moore To: linux-security-module@vger.kernel.org, selinux@vger.kernel.org, linux-audit@redhat.com, io-uring@vger.kernel.org, linux-fsdevel@vger.kernel.org, Kumar Kartikeya Dwivedi , Jens Axboe , Alexander Viro Date: Fri, 21 May 2021 17:50:00 -0400 Message-ID: <162163380070.8379.13984065725601277137.stgit@sifl> In-Reply-To: <162163367115.8379.8459012634106035341.stgit@sifl> References: <162163367115.8379.8459012634106035341.stgit@sifl> User-Agent: StGit/1.1 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: selinux@vger.kernel.org WARNING - This patch is intended only to aid in the initial dev/test of the audit/io_uring support, it is not intended to be merged. With this patch, you can emit io_uring operation audit records with the following commands (the first clears any blocking rules): % auditctl -D % auditctl -a exit,always -S io_uring_enter Signed-off-by: DO NOT COMMIT --- kernel/auditsc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 729849d41631..d8aa2c690bf9 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -1898,6 +1898,10 @@ void __audit_uring_exit(int success, long code) audit_log_uring(ctx); return; } +#if 1 + /* XXX - temporary hack to force record generation */ + ctx->current_state = AUDIT_RECORD_CONTEXT; +#endif /* this may generate CONFIG_CHANGE records */ if (!list_empty(&ctx->killed_trees)) From patchwork Fri May 21 21:50:06 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Moore X-Patchwork-Id: 12273825 X-Patchwork-Delegate: paul@paul-moore.com Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.7 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 51F49C04FF3 for ; Fri, 21 May 2021 21:50:10 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 37AD1613DB for ; Fri, 21 May 2021 21:50:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229589AbhEUVvc (ORCPT ); Fri, 21 May 2021 17:51:32 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56952 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229503AbhEUVvc (ORCPT ); Fri, 21 May 2021 17:51:32 -0400 Received: from mail-qk1-x72d.google.com (mail-qk1-x72d.google.com [IPv6:2607:f8b0:4864:20::72d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C7342C06138A for ; Fri, 21 May 2021 14:50:08 -0700 (PDT) Received: by mail-qk1-x72d.google.com with SMTP id 82so9930925qki.8 for ; Fri, 21 May 2021 14:50:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=paul-moore-com.20150623.gappssmtp.com; s=20150623; h=subject:from:to:date:message-id:in-reply-to:references:user-agent :mime-version:content-transfer-encoding; bh=QUVDejUd0QVU/Z8Kg6BDyRzNOClvT48b9vJMJlEEAYU=; b=c0LniHduGCV7osELXKSi8Y7kTaA+YrOJgBGm3A54YFyvwbzfmoOyRmFNjLHukJqatK lJo5bv4R/B9k3KppXBKPyLFLP9nslxfiSW9ya3Ub6OyU2o+mcprcAQgB253Fjou1ncLD o5GshWgPxEDIqMIsadd6vw+RcYs0NbKjeTdhcsjIFh8Apts0c54EHtWybxaL+dFhslaw h2B00lTRKLZCX+2fJBVJvEMEikLt12LkNRg47b6Yuu4ZFp86MM4wBxFMHPtzFMfJn9TE RSCjekeXGuW13cZRfCmmWXRmba/Kk1V+m7LaIbAzBr1HOKr9R77LzFCZn2zNEcH0EPfv yAlg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:subject:from:to:date:message-id:in-reply-to :references:user-agent:mime-version:content-transfer-encoding; bh=QUVDejUd0QVU/Z8Kg6BDyRzNOClvT48b9vJMJlEEAYU=; b=RXOhmmUappWOWMBOGzqTfxVhMBW8JLgSB/ZSds9igkKQ9eSHUE4BNLkvVCZ/DrwJlQ Gdszqcd+YzAwhFbWX+Rk069nbgLP0sUXzK/nnQV40cGBGJ5oyxqFLJk7Q2jLSdo9+rHl 79ky9q/KvkW6hFHklzmgYBePJRyYCY3QkaMDVHBflladk8SUxr3fQBdrZosFrge4Mo7c 4eXigJAa0CLeXLwm40Onycfw70q5aHHfQU1sXwihLmDw0sZCkTqiFfk0fnYIOjh5P+5j QqCfV2eCC3tYLfwDtxbb0SYcJXpezSHFFxaMi30XGJPqoBsu0DuPRPSiiBah01aY0fNE P0VQ== X-Gm-Message-State: AOAM5324Sr3crf+T034SLNK5F3iasFi+ehbIldfvbwbDhFNvyHtmKOBR QWdPklYyJLgxtWbXpSu1tbBn X-Google-Smtp-Source: ABdhPJxPTzsGFJkxhfKEg5HzgXuCEPzB3MK2hNWDMjSEOoq7brugPuxmQltgnePH6/vH3GsF3vbdYQ== X-Received: by 2002:a05:620a:68e:: with SMTP id f14mr15645958qkh.306.1621633807902; Fri, 21 May 2021 14:50:07 -0700 (PDT) Received: from localhost (pool-96-237-52-188.bstnma.fios.verizon.net. [96.237.52.188]) by smtp.gmail.com with ESMTPSA id 7sm6228437qtu.38.2021.05.21.14.50.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 21 May 2021 14:50:07 -0700 (PDT) Subject: [RFC PATCH 4/9] audit: add filtering for io_uring records From: Paul Moore To: linux-security-module@vger.kernel.org, selinux@vger.kernel.org, linux-audit@redhat.com, io-uring@vger.kernel.org, linux-fsdevel@vger.kernel.org, Kumar Kartikeya Dwivedi , Jens Axboe , Alexander Viro Date: Fri, 21 May 2021 17:50:06 -0400 Message-ID: <162163380685.8379.17381053199011043757.stgit@sifl> In-Reply-To: <162163367115.8379.8459012634106035341.stgit@sifl> References: <162163367115.8379.8459012634106035341.stgit@sifl> User-Agent: StGit/1.1 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: selinux@vger.kernel.org WARNING - This is a work in progress and should not be merged anywhere important. It is almost surely not complete, and while it probably compiles it likely hasn't been booted and will do terrible things. You have been warned. This patch adds basic audit io_uring filtering, using as much of the existing audit filtering infrastructure as possible. In order to do this we reuse the audit filter rule's syscall mask for the io_uring operation and we create a new filter for io_uring operations as AUDIT_FILTER_URING_EXIT/audit_filter_list[7]. Signed-off-by: Paul Moore --- include/uapi/linux/audit.h | 3 +- kernel/auditfilter.c | 4 ++- kernel/auditsc.c | 65 ++++++++++++++++++++++++++++++++++---------- 3 files changed, 55 insertions(+), 17 deletions(-) diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h index b26e0c435e8b..621eb3c1076e 100644 --- a/include/uapi/linux/audit.h +++ b/include/uapi/linux/audit.h @@ -167,8 +167,9 @@ #define AUDIT_FILTER_EXCLUDE 0x05 /* Apply rule before record creation */ #define AUDIT_FILTER_TYPE AUDIT_FILTER_EXCLUDE /* obsolete misleading naming */ #define AUDIT_FILTER_FS 0x06 /* Apply rule at __audit_inode_child */ +#define AUDIT_FILTER_URING_EXIT 0x07 /* Apply rule at io_uring op exit */ -#define AUDIT_NR_FILTERS 7 +#define AUDIT_NR_FILTERS 8 #define AUDIT_FILTER_PREPEND 0x10 /* Prepend to front of list */ diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index db2c6b59dfc3..c21119c00504 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c @@ -44,7 +44,8 @@ struct list_head audit_filter_list[AUDIT_NR_FILTERS] = { LIST_HEAD_INIT(audit_filter_list[4]), LIST_HEAD_INIT(audit_filter_list[5]), LIST_HEAD_INIT(audit_filter_list[6]), -#if AUDIT_NR_FILTERS != 7 + LIST_HEAD_INIT(audit_filter_list[7]), +#if AUDIT_NR_FILTERS != 8 #error Fix audit_filter_list initialiser #endif }; @@ -56,6 +57,7 @@ static struct list_head audit_rules_list[AUDIT_NR_FILTERS] = { LIST_HEAD_INIT(audit_rules_list[4]), LIST_HEAD_INIT(audit_rules_list[5]), LIST_HEAD_INIT(audit_rules_list[6]), + LIST_HEAD_INIT(audit_rules_list[7]), }; DEFINE_MUTEX(audit_filter_mutex); diff --git a/kernel/auditsc.c b/kernel/auditsc.c index d8aa2c690bf9..4f6ab34020fb 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -799,6 +799,35 @@ static int audit_in_mask(const struct audit_krule *rule, unsigned long val) return rule->mask[word] & bit; } +/** + * audit_filter_uring - apply filters to an io_uring operation + * @tsk: associated task + * @ctx: audit context + */ +static void audit_filter_uring(struct task_struct *tsk, + struct audit_context *ctx) +{ + struct audit_entry *e; + enum audit_state state; + + if (auditd_test_task(tsk)) + return; + + rcu_read_lock(); + list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_URING_EXIT], + list) { + if (audit_in_mask(&e->rule, ctx->uring_op) && + audit_filter_rules(tsk, &e->rule, ctx, NULL, &state, + false)) { + rcu_read_unlock(); + ctx->current_state = state; + return; + } + } + rcu_read_unlock(); + return; +} + /* At syscall exit time, this filter is called if the audit_state is * not low enough that auditing cannot take place, but is also not * high enough that we already know we have to write an audit record @@ -1754,7 +1783,7 @@ static void audit_log_exit(void) * __audit_free - free a per-task audit context * @tsk: task whose audit context block to free * - * Called from copy_process and do_exit + * Called from copy_process, do_exit, and the io_uring code */ void __audit_free(struct task_struct *tsk) { @@ -1772,15 +1801,21 @@ void __audit_free(struct task_struct *tsk) * random task_struct that doesn't doesn't have any meaningful data we * need to log via audit_log_exit(). */ - if (tsk == current && !context->dummy && - context->context == AUDIT_CTX_SYSCALL) { + if (tsk == current && !context->dummy) { context->return_valid = AUDITSC_INVALID; context->return_code = 0; - - audit_filter_syscall(tsk, context); - audit_filter_inodes(tsk, context); - if (context->current_state == AUDIT_RECORD_CONTEXT) - audit_log_exit(); + if (context->context == AUDIT_CTX_SYSCALL) { + audit_filter_syscall(tsk, context); + audit_filter_inodes(tsk, context); + if (context->current_state == AUDIT_RECORD_CONTEXT) + audit_log_exit(); + } else if (context->context == AUDIT_CTX_URING) { + /* TODO: verify this case is real and valid */ + audit_filter_uring(tsk, context); + audit_filter_inodes(tsk, context); + if (context->current_state == AUDIT_RECORD_CONTEXT) + audit_log_uring(context); + } } audit_set_context(tsk, NULL); @@ -1861,12 +1896,6 @@ void __audit_uring_exit(int success, long code) { struct audit_context *ctx = audit_context(); - /* - * TODO: At some point we will likely want to filter on io_uring ops - * and other things similar to what we do for syscalls, but that - * is something for another day; just record what we can here. - */ - if (!ctx || ctx->dummy) goto out; if (ctx->context == AUDIT_CTX_SYSCALL) { @@ -1891,6 +1920,8 @@ void __audit_uring_exit(int success, long code) * the behavior here. */ audit_filter_syscall(current, ctx); + if (ctx->current_state != AUDIT_RECORD_CONTEXT) + audit_filter_uring(current, ctx); audit_filter_inodes(current, ctx); if (ctx->current_state != AUDIT_RECORD_CONTEXT) return; @@ -1899,7 +1930,9 @@ void __audit_uring_exit(int success, long code) return; } #if 1 - /* XXX - temporary hack to force record generation */ + /* XXX - temporary hack to force record generation, we are leaving this + * enabled, but if you want to actually test the filtering you + * need to disable this #if/#endif block */ ctx->current_state = AUDIT_RECORD_CONTEXT; #endif @@ -1907,6 +1940,8 @@ void __audit_uring_exit(int success, long code) if (!list_empty(&ctx->killed_trees)) audit_kill_trees(ctx); + /* run through both filters to ensure we set the filterkey properly */ + audit_filter_uring(current, ctx); audit_filter_inodes(current, ctx); if (ctx->current_state != AUDIT_RECORD_CONTEXT) goto out; From patchwork Fri May 21 21:50:13 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Moore X-Patchwork-Id: 12273827 X-Patchwork-Delegate: paul@paul-moore.com Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.7 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 30249C04FF3 for ; Fri, 21 May 2021 21:50:18 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 115B7613EC for ; Fri, 21 May 2021 21:50:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229807AbhEUVvk (ORCPT ); Fri, 21 May 2021 17:51:40 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56990 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229788AbhEUVvj (ORCPT ); Fri, 21 May 2021 17:51:39 -0400 Received: from mail-qk1-x72d.google.com (mail-qk1-x72d.google.com [IPv6:2607:f8b0:4864:20::72d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D0F60C0613CE for ; Fri, 21 May 2021 14:50:14 -0700 (PDT) Received: by mail-qk1-x72d.google.com with SMTP id q10so21316652qkc.5 for ; Fri, 21 May 2021 14:50:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=paul-moore-com.20150623.gappssmtp.com; s=20150623; h=subject:from:to:date:message-id:in-reply-to:references:user-agent :mime-version:content-transfer-encoding; bh=28mYvehEs3z/GlPu07ZO2sTO/B+ImH7rTZVJRJkmPL8=; b=Nwfv7Q2at28cE+jagIqyX6lb2QffXOuIGBUgUidmj7Gz40wtourKAYeXYgPYR6Xw1n uMlU4WffCbgxYYjPuSlFLu67tw5bzcTwjROX6p/zZH/CZvQEY/1+d43IOYExYZYYAKHJ CSD6w3qd7xZt/1/yDM7knZriGR5PVGurboSxksToizm9/AqQW8FYKBAs99EB06SgpM97 i9DWti8EqWUYNLq9BxP4uXaHh4P8Q7WdpLP+8OYQfjBcHBcU6Z7e+mjZioiyiNQKfFBu aDffx8f7+xDByl4NCU10Q+7idvAHnJpb+4flJG2UacyK6YTKaE8I++ppG16HGdJLdyuP bdoQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:subject:from:to:date:message-id:in-reply-to :references:user-agent:mime-version:content-transfer-encoding; bh=28mYvehEs3z/GlPu07ZO2sTO/B+ImH7rTZVJRJkmPL8=; b=FEf9g8UyXT97DOWJni6ks731wtp8Jq94Wd2KnmNZZYsahV0eEubsrOagy0vpbDs2qP NqQDZjrictm0XL6ADMy8XUHEYs5TBGOD230QY2elYjiYujVzeStAIHeCsMo+K/GF9OYk YFzCemTgmTVARVLgGMoudg8vHVGmUPBC8iHFkRyv5hb85zCWFdao9FOZspxRl9xj6sYT J7hUWEmtTZ+yXjDIk20Nydrv3DdJV1NBOKEBv0FXgC2bH0A1za3d6MIEzcbqBfqZvtgj 0lIDuhX/E27yGy0EuX3wgZuuDIMePk89O4u75NnMsGl3+1Vi1vHW+j5BDOtRp8VrNuwS niBQ== X-Gm-Message-State: AOAM53210ccgt6VZqqtidLWx0dh0S7BAAG1DXZZunX41Drpsynuafh09 9bsUWl/qBu9mkTUKXDu6yAAo X-Google-Smtp-Source: ABdhPJw1qyLOwhzI8W3DdhQMHzc0FJSlmc5dyhRENQ524cEnIhZRftnlrl97sOqARFzzskecC3kRRQ== X-Received: by 2002:ae9:ef55:: with SMTP id d82mr15041516qkg.3.1621633813979; Fri, 21 May 2021 14:50:13 -0700 (PDT) Received: from localhost (pool-96-237-52-188.bstnma.fios.verizon.net. [96.237.52.188]) by smtp.gmail.com with ESMTPSA id l10sm5680954qtn.28.2021.05.21.14.50.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 21 May 2021 14:50:13 -0700 (PDT) Subject: [RFC PATCH 5/9] fs: add anon_inode_getfile_secure() similar to anon_inode_getfd_secure() From: Paul Moore To: linux-security-module@vger.kernel.org, selinux@vger.kernel.org, linux-audit@redhat.com, io-uring@vger.kernel.org, linux-fsdevel@vger.kernel.org, Kumar Kartikeya Dwivedi , Jens Axboe , Alexander Viro Date: Fri, 21 May 2021 17:50:13 -0400 Message-ID: <162163381300.8379.4882128125504754351.stgit@sifl> In-Reply-To: <162163367115.8379.8459012634106035341.stgit@sifl> References: <162163367115.8379.8459012634106035341.stgit@sifl> User-Agent: StGit/1.1 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: selinux@vger.kernel.org Extending the secure anonymous inode support to other subsystems requires that we have a secure anon_inode_getfile() variant in addition to the existing secure anon_inode_getfd() variant. Thankfully we can reuse the existing __anon_inode_getfile() function and just wrap it with the proper arguments. Signed-off-by: Paul Moore --- fs/anon_inodes.c | 29 +++++++++++++++++++++++++++++ include/linux/anon_inodes.h | 4 ++++ 2 files changed, 33 insertions(+) diff --git a/fs/anon_inodes.c b/fs/anon_inodes.c index a280156138ed..e0c3e33c4177 100644 --- a/fs/anon_inodes.c +++ b/fs/anon_inodes.c @@ -148,6 +148,35 @@ struct file *anon_inode_getfile(const char *name, } EXPORT_SYMBOL_GPL(anon_inode_getfile); +/** + * anon_inode_getfile_secure - Like anon_inode_getfile(), but creates a new + * !S_PRIVATE anon inode rather than reuse the + * singleton anon inode and calls the + * inode_init_security_anon() LSM hook. This + * allows for both the inode to have its own + * security context and for the LSM to enforce + * policy on the inode's creation. + * + * @name: [in] name of the "class" of the new file + * @fops: [in] file operations for the new file + * @priv: [in] private data for the new file (will be file's private_data) + * @flags: [in] flags + * @context_inode: + * [in] the logical relationship with the new inode (optional) + * + * The LSM may use @context_inode in inode_init_security_anon(), but a + * reference to it is not held. Returns the newly created file* or an error + * pointer. See the anon_inode_getfile() documentation for more information. + */ +struct file *anon_inode_getfile_secure(const char *name, + const struct file_operations *fops, + void *priv, int flags, + const struct inode *context_inode) +{ + return __anon_inode_getfile(name, fops, priv, flags, + context_inode, true); +} + static int __anon_inode_getfd(const char *name, const struct file_operations *fops, void *priv, int flags, diff --git a/include/linux/anon_inodes.h b/include/linux/anon_inodes.h index 71881a2b6f78..5deaddbd7927 100644 --- a/include/linux/anon_inodes.h +++ b/include/linux/anon_inodes.h @@ -15,6 +15,10 @@ struct inode; struct file *anon_inode_getfile(const char *name, const struct file_operations *fops, void *priv, int flags); +struct file *anon_inode_getfile_secure(const char *name, + const struct file_operations *fops, + void *priv, int flags, + const struct inode *context_inode); int anon_inode_getfd(const char *name, const struct file_operations *fops, void *priv, int flags); int anon_inode_getfd_secure(const char *name, From patchwork Fri May 21 21:50:19 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Moore X-Patchwork-Id: 12273829 X-Patchwork-Delegate: paul@paul-moore.com Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.7 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id D0FE5C4707E for ; Fri, 21 May 2021 21:50:25 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id B6009613EC for ; Fri, 21 May 2021 21:50:25 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229555AbhEUVvr (ORCPT ); Fri, 21 May 2021 17:51:47 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57004 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229845AbhEUVvp (ORCPT ); Fri, 21 May 2021 17:51:45 -0400 Received: from mail-qk1-x735.google.com (mail-qk1-x735.google.com [IPv6:2607:f8b0:4864:20::735]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1F835C061574 for ; Fri, 21 May 2021 14:50:21 -0700 (PDT) Received: by mail-qk1-x735.google.com with SMTP id 76so21265932qkn.13 for ; Fri, 21 May 2021 14:50:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=paul-moore-com.20150623.gappssmtp.com; s=20150623; h=subject:from:to:date:message-id:in-reply-to:references:user-agent :mime-version:content-transfer-encoding; bh=NjQYheEqysYNaQjd+p06Inp4wH1U0otC+/CD13zo/Yk=; b=E5Spd5BKGx4yGEPJpQdD/aaQk7CvtceJrlp3Y2VBNOQHP0pgw4dR/8GV/BnhsK0OLB Ea/veQB1VRgASbTR43L4D4LUuapmWtrvt+fMLKiBcTv0xJJ5cWYPLybP7YT4c4+wCyda X0Jra5oRwQLf63pOQP/4dWDgjq215xGj9WN4EsGjIUrWlr5uboOzbvrqjHsi6HJPlQvA fUev5VZSdt/m7c+ufV/pWApmZdxobj461G9Dm4KpexmfBxI6qwVnhIcA+DTVmwx8rOZk EtD8xsveATZ4614xXmMi/AfjpKDdbqvouBmv8PZeay9O5C7XJclSBBLuZqXV49JXi8i8 6W0A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:subject:from:to:date:message-id:in-reply-to :references:user-agent:mime-version:content-transfer-encoding; bh=NjQYheEqysYNaQjd+p06Inp4wH1U0otC+/CD13zo/Yk=; b=OMFQccPABjvqBY6fDTPCRq5D+PHKO5M0vhfYqIqswq/d9Prtwycf+JYAkcDHbIpt5o 5K8qAeqy2bKRHkzvNHyX/jrqtnY1aacoj1qVBzMxWq+7kC+sJIZyNvSPBgd2KeChQ87a yQADpHM0DFUz7aEzR32mHPvd2C4nf3O/bAi9kLQz3V7DRKealIyIzTqBTNotgWS/T+dm 7Nrl21CLUZXGdzWgxkbcs8/teOcqcoNhuNgHC3VWAhqVebjkyaW81qWsSjGTcmapN0x4 by3jXnmTRVQZlk8esGNW6dDGemL8UDk9GRNSpFmyoWui0NC5YTArrHVRvnCBbGHKhY7Y LgSQ== X-Gm-Message-State: AOAM533T56eHnKEZeK8tGDS6QJg7d28QHcn+5fSeaymgPZJp8Tzbb0go c4l8e0EPORW+oELqAnRkNlkJ X-Google-Smtp-Source: ABdhPJynsuaNUC820jY3H2esnoh6KFBANq11zEi3mooubWaHHh6CD0Vbo03pwFPQ4w5+8t77DR4J0g== X-Received: by 2002:a37:9003:: with SMTP id s3mr14830045qkd.86.1621633820257; Fri, 21 May 2021 14:50:20 -0700 (PDT) Received: from localhost (pool-96-237-52-188.bstnma.fios.verizon.net. [96.237.52.188]) by smtp.gmail.com with ESMTPSA id e19sm5357823qtr.45.2021.05.21.14.50.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 21 May 2021 14:50:19 -0700 (PDT) Subject: [RFC PATCH 6/9] io_uring: convert io_uring to the secure anon inode interface From: Paul Moore To: linux-security-module@vger.kernel.org, selinux@vger.kernel.org, linux-audit@redhat.com, io-uring@vger.kernel.org, linux-fsdevel@vger.kernel.org, Kumar Kartikeya Dwivedi , Jens Axboe , Alexander Viro Date: Fri, 21 May 2021 17:50:19 -0400 Message-ID: <162163381908.8379.10800711368185383459.stgit@sifl> In-Reply-To: <162163367115.8379.8459012634106035341.stgit@sifl> References: <162163367115.8379.8459012634106035341.stgit@sifl> User-Agent: StGit/1.1 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: selinux@vger.kernel.org Converting io_uring's anonymous inode to the secure anon inode API enables LSMs to enforce policy on the io_uring anonymous inodes if they chose to do so. This is an important first step towards providing the necessary mechanisms so that LSMs can apply security policy to io_uring operations. Signed-off-by: Paul Moore --- fs/io_uring.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/io_uring.c b/fs/io_uring.c index e9941d1ad8fd..6ff769c9b7d3 100644 --- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -9562,8 +9562,8 @@ static struct file *io_uring_get_file(struct io_ring_ctx *ctx) return ERR_PTR(ret); #endif - file = anon_inode_getfile("[io_uring]", &io_uring_fops, ctx, - O_RDWR | O_CLOEXEC); + file = anon_inode_getfile_secure("[io_uring]", &io_uring_fops, ctx, + O_RDWR | O_CLOEXEC, NULL); #if defined(CONFIG_UNIX) if (IS_ERR(file)) { sock_release(ctx->ring_sock); From patchwork Fri May 21 21:50:25 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Moore X-Patchwork-Id: 12273831 X-Patchwork-Delegate: paul@paul-moore.com Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.7 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id DC992C04FF3 for ; Fri, 21 May 2021 21:50:34 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id C3549613DB for ; Fri, 21 May 2021 21:50:34 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229906AbhEUVvx (ORCPT ); Fri, 21 May 2021 17:51:53 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57054 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229623AbhEUVvv (ORCPT ); Fri, 21 May 2021 17:51:51 -0400 Received: from mail-qk1-x72f.google.com (mail-qk1-x72f.google.com [IPv6:2607:f8b0:4864:20::72f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 44434C0613CE for ; Fri, 21 May 2021 14:50:27 -0700 (PDT) Received: by mail-qk1-x72f.google.com with SMTP id j189so486686qkf.2 for ; Fri, 21 May 2021 14:50:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=paul-moore-com.20150623.gappssmtp.com; s=20150623; h=subject:from:to:date:message-id:in-reply-to:references:user-agent :mime-version:content-transfer-encoding; bh=w/wVrpbDddYGmYeIa/lLX6dIKPrH+Jy0d/XtOIIDKZ4=; b=eRM6JjYnEkTKlC5+Rcn1SAsvA+8BTinFm9H0FGGNLtE1SosLuwcraNaf4/GKtlm4fA eh+Q9g+w0J7nqnbedMg8bA90YJO962ZyK94UlBG+JvMTMnMJiAxeO1bRKSS8xIkRAnzJ emE02GOFRujDtOzaraq3j/B/mgKssR4tmH32edRJRcOJ2JOcbMtfgTcbs4nWyu7nDPnh zvZw/ZSAwpiUCJTFMdSl1vF5fRDXjJ5xZbDb6GWYibHT/Q61I5SctgJgJFFMmKGWkVnb 3PPwSCtTJV8MMfqFdr8aCtSOvCq3Rt3evdTxTm1gatM2WayzgEbuj4J0QOybNJNOKbfL rHow== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:subject:from:to:date:message-id:in-reply-to :references:user-agent:mime-version:content-transfer-encoding; bh=w/wVrpbDddYGmYeIa/lLX6dIKPrH+Jy0d/XtOIIDKZ4=; b=LYxd8D4SOpznjaZ2DNc4ItOr2kT5X/EfCNObKqjIEB8PfyIpV9y+NI5RiBb3YDAhsq kzX6OwrblfykdB5Iv62/JLN+3v2GwvjBA0PJ9t6qx9tyqAHd+qZ4iwdN8scFgKJ3LjOf xTg70IEAcBct0eflzh4QUyEA+TZzaMJ/fR7997YrDuu0W1j44syGskiCQNl1z93dMDYH 3HfA78M1UyNCEhZI5bJom9AcLf+s3u98d/tSpRPDRCcMLnzovpD9duV/qeN3spGjprEY 7X8Qy5axmbOnXbIISdi0dVz845QrS+WxHkxONze5lWcRtzNOixefcP1ab3Kxq8tQOPVa bnxg== X-Gm-Message-State: AOAM531KWNVjAS1dDe5aNl6vJGP2f0xByyNMc77unmELA6PBpESDPXEA XEikfz803o5U2HyEocpxs9eM X-Google-Smtp-Source: ABdhPJwWzC4oZBG5HfZ1Iz9QNRxVUdN7xK1qmDS/h0WKeKH6FTnP7rKaStU6OaFthZnDrlpJSMvAzw== X-Received: by 2002:a05:620a:a4c:: with SMTP id j12mr12187144qka.33.1621633826362; Fri, 21 May 2021 14:50:26 -0700 (PDT) Received: from localhost (pool-96-237-52-188.bstnma.fios.verizon.net. [96.237.52.188]) by smtp.gmail.com with ESMTPSA id m67sm5909208qkd.108.2021.05.21.14.50.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 21 May 2021 14:50:25 -0700 (PDT) Subject: [RFC PATCH 7/9] lsm,io_uring: add LSM hooks to io_uring From: Paul Moore To: linux-security-module@vger.kernel.org, selinux@vger.kernel.org, linux-audit@redhat.com, io-uring@vger.kernel.org, linux-fsdevel@vger.kernel.org, Kumar Kartikeya Dwivedi , Jens Axboe , Alexander Viro Date: Fri, 21 May 2021 17:50:25 -0400 Message-ID: <162163382536.8379.3124023175473604584.stgit@sifl> In-Reply-To: <162163367115.8379.8459012634106035341.stgit@sifl> References: <162163367115.8379.8459012634106035341.stgit@sifl> User-Agent: StGit/1.1 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: selinux@vger.kernel.org WARNING - This is a work in progress, this patch, including the description, may be incomplete or even incorrect. You have been warned. A full expalantion of io_uring is beyond the scope of this commit description, but in summary it is an asynchronous I/O mechanism which allows for I/O requests and the resulting data to be queued in memory mapped "rings" which are shared between the kernel and userspace. Optionally, io_uring offers the ability for applications to spawn kernel threads to dequeue I/O requests from the ring and submit the requests in the kernel, helping to minimize the syscall overhead. Rings are accessed in userspace by memory mapping a file descriptor provided by the io_uring_setup(2), and can be shared between applications as one might do with any open file descriptor. Finally, process credentials can be registered with a given ring and any process with access to that ring can submit I/O requests using any of the registered credentials. While the io_uring functionality is widely recognized as offering a vastly improved, and high performing asynchronous I/O mechanism, its ability to allow processes to submit I/O requests with credentials other than its own presents a challenge to LSMs. When a process creates a new io_uring ring the ring's credentials are inhertied from the calling process; if this ring is shared with another process operating with different credentials there is the potential to bypass the LSMs security policy. Similarly, registering credentials with a given ring allows any process with access to that ring to submit I/O requests with those credentials. In an effort to allow LSMs to apply security policy to io_uring I/O operations, this patch adds two new LSM hooks. These hooks, in conjunction with the LSM anonymous inode support previously submitted, allow an LSM to apply access control policy to the sharing of io_uring rings as well as any io_uring credential changes requested by a process. The new LSM hooks are described below: * int security_uring_override_creds(cred) Controls if the current task, executing an io_uring operation, is allowed to override it's credentials with @cred. In cases where the current task is a user application, the current credentials will be those of the user application. In cases where the current task is a kernel thread servicing io_uring requests the current credentials will be those of the io_uring ring (inherited from the process that created the ring). * int security_uring_sqpoll(void) Controls if the current task is allowed to create an io_uring polling thread (IORING_SETUP_SQPOLL). Without a SQPOLL thread in the kernel processes must submit I/O requests via io_uring_enter(2) which allows us to compare any requested credential changes against the application making the request. With a SQPOLL thread, we can no longer compare requested credential changes against the application making the request, the comparison is made against the ring's credentials. Signed-off-by: Paul Moore --- fs/io_uring.c | 10 ++++++++++ include/linux/lsm_hook_defs.h | 5 +++++ include/linux/lsm_hooks.h | 13 +++++++++++++ include/linux/security.h | 16 ++++++++++++++++ security/security.c | 12 ++++++++++++ 5 files changed, 56 insertions(+) diff --git a/fs/io_uring.c b/fs/io_uring.c index 6ff769c9b7d3..d18a594c4c6e 100644 --- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -79,6 +79,7 @@ #include #include #include +#include #define CREATE_TRACE_POINTS #include @@ -6537,6 +6538,11 @@ static int io_init_req(struct io_ring_ctx *ctx, struct io_kiocb *req, if (!req->work.creds) return -EINVAL; get_cred(req->work.creds); + ret = security_uring_override_creds(req->work.creds); + if (ret) { + put_cred(req->work.creds); + return ret; + } } state = &ctx->submit_state; @@ -7963,6 +7969,10 @@ static int io_sq_offload_create(struct io_ring_ctx *ctx, struct io_sq_data *sqd; bool attached; + ret = security_uring_sqpoll(); + if (ret) + return ret; + sqd = io_get_sq_data(p, &attached); if (IS_ERR(sqd)) { ret = PTR_ERR(sqd); diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h index 04c01794de83..88971b3da3c0 100644 --- a/include/linux/lsm_hook_defs.h +++ b/include/linux/lsm_hook_defs.h @@ -403,3 +403,8 @@ LSM_HOOK(void, LSM_RET_VOID, perf_event_free, struct perf_event *event) LSM_HOOK(int, 0, perf_event_read, struct perf_event *event) LSM_HOOK(int, 0, perf_event_write, struct perf_event *event) #endif /* CONFIG_PERF_EVENTS */ + +#ifdef CONFIG_IO_URING +LSM_HOOK(int, 0, uring_override_creds, const struct cred *new) +LSM_HOOK(int, 0, uring_sqpoll, void) +#endif /* CONFIG_IO_URING */ diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index 5c4c5c0602cb..0eb0ae95c4c4 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -1557,6 +1557,19 @@ * Read perf_event security info if allowed. * @perf_event_write: * Write perf_event security info if allowed. + * + * Security hooks for io_uring + * + * @uring_override_creds: + * Check if the current task, executing an io_uring operation, is allowed + * to override it's credentials with @new. + * + * @new: the new creds to use + * + * @uring_sqpoll: + * Check whether the current task is allowed to spawn a io_uring polling + * thread (IORING_SETUP_SQPOLL). + * */ union security_list_options { #define LSM_HOOK(RET, DEFAULT, NAME, ...) RET (*NAME)(__VA_ARGS__); diff --git a/include/linux/security.h b/include/linux/security.h index 06f7c50ce77f..263a744c839f 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -2037,4 +2037,20 @@ static inline int security_perf_event_write(struct perf_event *event) #endif /* CONFIG_SECURITY */ #endif /* CONFIG_PERF_EVENTS */ +#ifdef CONFIG_IO_URING +#ifdef CONFIG_SECURITY +extern int security_uring_override_creds(const struct cred *new); +extern int security_uring_sqpoll(void); +#else +static inline int security_uring_override_creds(const struct cred *new) +{ + return 0; +} +static inline int security_uring_sqpoll(void) +{ + return 0; +} +#endif /* CONFIG_SECURITY */ +#endif /* CONFIG_IO_URING */ + #endif /* ! __LINUX_SECURITY_H */ diff --git a/security/security.c b/security/security.c index b38155b2de83..3d6b3a2cacf5 100644 --- a/security/security.c +++ b/security/security.c @@ -2624,3 +2624,15 @@ int security_perf_event_write(struct perf_event *event) return call_int_hook(perf_event_write, 0, event); } #endif /* CONFIG_PERF_EVENTS */ + +#ifdef CONFIG_IO_URING +int security_uring_override_creds(const struct cred *new) +{ + return call_int_hook(uring_override_creds, 0, new); +} + +int security_uring_sqpoll(void) +{ + return call_int_hook(uring_sqpoll, 0); +} +#endif /* CONFIG_IO_URING */ From patchwork Fri May 21 21:50:31 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Moore X-Patchwork-Id: 12273833 X-Patchwork-Delegate: paul@paul-moore.com Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.7 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7E6B1C47083 for ; Fri, 21 May 2021 21:50:36 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 670A2613EE for ; Fri, 21 May 2021 21:50:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229907AbhEUVv7 (ORCPT ); Fri, 21 May 2021 17:51:59 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57092 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229937AbhEUVv5 (ORCPT ); Fri, 21 May 2021 17:51:57 -0400 Received: from mail-qk1-x72e.google.com (mail-qk1-x72e.google.com [IPv6:2607:f8b0:4864:20::72e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 681E1C06138D for ; Fri, 21 May 2021 14:50:33 -0700 (PDT) Received: by mail-qk1-x72e.google.com with SMTP id i67so21300892qkc.4 for ; Fri, 21 May 2021 14:50:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=paul-moore-com.20150623.gappssmtp.com; s=20150623; h=subject:from:to:date:message-id:in-reply-to:references:user-agent :mime-version:content-transfer-encoding; bh=nqTYSxcbdFhLeehGXcGD2BgJgX1rjG2Wtkqyf5lYwxs=; b=bCFSuOY106xTmbrlMmlMrtItsMWp3Hrouloy7nRctAo9P0YrEyWroH4Ep1Wjx4QIiv UMEuUWBpuTHsO7andG1cDqSvIm5IK+x1RgyHplBq8wnv1ZpWWO016Qp2B5dCKcita4Ih 5jLyY8pFF1+7i33CjNYLETuFBSlX0txwhjTvm8kQh9dFZnrad8MBgrlvJ2Y882UKwLJz vBtWK/ECSTO3lm1kzFQDCa+YS2zoravl75Ym/ZrQ6yW0gxDhyJeBeGom1foDF7bQW6Vt vs3Bp/Iwjp4Fj1raR1G0++c8ebRn1pMYE5JpNeJG+IUXEjzW+qVY9VoV5qkQN70LTEMj Z2NQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:subject:from:to:date:message-id:in-reply-to :references:user-agent:mime-version:content-transfer-encoding; bh=nqTYSxcbdFhLeehGXcGD2BgJgX1rjG2Wtkqyf5lYwxs=; b=nd1PSwgQ+zlS7+b1BMuVU8Wk19iJ70Vq/PoFSmkHooKLZU30FvOXatkDClqnjTxiNg aT0gDXNUuHDqUDKdoq2q0qoeEEs8dllLse1j/glv6Reef5B0+7e5Pyha/nR38kinpmrD Pmw2FpwK60MXTKfDq8xGr2YD7W7PE80D7g2DyLw6oQd4Y4nS7Sj2ECRnPKlTV2V+cTEB ffyY5BPD2H8FiQtZ38Uk0RqMGXhXVrJTvIbF0dFKsSYowWmA3ovk2civDzxXh0d8OBic solnSVCDGTs9CWz4FfP7BPPADKIzpAlmpo6/JvwIdzaWOPyGikaG08JLrn1hS0EgxRQK mpXw== X-Gm-Message-State: AOAM531kfT3X4/GChzU+MShYn6/ABNeJ2f7Yw+wCKeh+PP053Q9Pds5z jlc4S/RyOdQKOlzavPik95oW X-Google-Smtp-Source: ABdhPJzzqQ3A/ENC4p3Z2YDJQeOswRLu6mmSuT0tmeMEw4hgI4BgJLg6GP2bt6rxQX4t1+reaZa3rA== X-Received: by 2002:a05:620a:4090:: with SMTP id f16mr15272263qko.225.1621633832501; Fri, 21 May 2021 14:50:32 -0700 (PDT) Received: from localhost (pool-96-237-52-188.bstnma.fios.verizon.net. [96.237.52.188]) by smtp.gmail.com with ESMTPSA id e5sm5317173qtg.96.2021.05.21.14.50.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 21 May 2021 14:50:32 -0700 (PDT) Subject: [RFC PATCH 8/9] selinux: add support for the io_uring access controls From: Paul Moore To: linux-security-module@vger.kernel.org, selinux@vger.kernel.org, linux-audit@redhat.com, io-uring@vger.kernel.org, linux-fsdevel@vger.kernel.org, Kumar Kartikeya Dwivedi , Jens Axboe , Alexander Viro Date: Fri, 21 May 2021 17:50:31 -0400 Message-ID: <162163383147.8379.1567341725602837940.stgit@sifl> In-Reply-To: <162163367115.8379.8459012634106035341.stgit@sifl> References: <162163367115.8379.8459012634106035341.stgit@sifl> User-Agent: StGit/1.1 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: selinux@vger.kernel.org WARNING - This is a work in progress, this patch, including the description, may be incomplete or even incorrect. You have been warned. This patch implements two new io_uring access controls, specifically support for controlling the io_uring "personalities" and IORING_SETUP_SQPOLL. Controlling the sharing of io_urings themselves is handled via the normal file/inode labeling and sharing mechanisms. The io_uring { override_creds } permission restricts which domains the subject domain can use to override it's own credentials. Granting a domain the io_uring { override_creds } permission allows it to impersonate another domain in io_uring operations. The io_uring { sqpoll } permission restricts which domains can create asynchronous io_uring polling threads. This is important from a security perspective as operations queued by this asynchronous thread inherit the credentials of the thread creator by default; if an io_uring is shared across process/domain boundaries this could result in one domain impersonating another. Controlling the creation of sqpoll threads, and the sharing of io_urings across processes, allow policy authors to restrict the ability of one domain to impersonate another via io_uring. As a quick summary, this patch adds a new object class with two permissions: io_uring { override_creds sqpoll } These permissions can be seen in the two simple policy statements below: allow domA_t domB_t : io_uring { override_creds }; allow domA_t self : io_uring { sqpoll }; Signed-off-by: Paul Moore --- security/selinux/hooks.c | 67 +++++++++++++++++++++++++++++++++++ security/selinux/include/classmap.h | 2 + 2 files changed, 69 insertions(+) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index eaea837d89d1..696130972e4d 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -7115,6 +7115,68 @@ static int selinux_perf_event_write(struct perf_event *event) } #endif +#ifdef CONFIG_IO_URING + +#if 1 +/* XXX - dump_creds() is for debugging only, remove before committing */ +static void dump_creds(const struct cred *cred) +{ + u32 secid; + char *ctx = NULL; + unsigned int ctx_len = 0; + + security_cred_getsecid(cred, &secid); + if (secid) + security_secid_to_secctx(secid, &ctx, &ctx_len); + + printk(KERN_ERR "CRED: ->security is %s\n", (ctx ? : "(error)")); + + if (ctx) + security_release_secctx(ctx, ctx_len); +} +#endif + +/** + * selinux_uring_override_creds - check the requested cred override + * @new: the target creds + * + * Check to see if the current task is allowed to override it's credentials + * to service an io_uring operation. + */ +int selinux_uring_override_creds(const struct cred *new) +{ +#if 1 + /* XXX - debug only code, remove before committing */ + pr_err("PMD: selinux_uring_override_creds()\n"); + pr_err("PMD: >>> CURRENT\n"); + dump_creds(current_cred()); + pr_err("PMD: >>> NEW\n"); + dump_creds(new); +#endif + return avc_has_perm(&selinux_state, current_sid(), cred_sid(new), + SECCLASS_IO_URING, IO_URING__OVERRIDE_CREDS, NULL); +} + +/** + * selinux_uring_sqpoll - check if a io_uring polling thread can be created + * + * Check to see if the current task is allowed to create a new io_uring + * kernel polling thread. + */ +int selinux_uring_sqpoll(void) +{ + int sid = current_sid(); +#if 1 + /* XXX - debug only code, remove before committing */ + pr_err("PMD: selinux_uring_sqpoll()\n"); + pr_err("PMD: >>> CURRENT\n"); + dump_creds(current_cred()); +#endif + return avc_has_perm(&selinux_state, sid, sid, + SECCLASS_IO_URING, IO_URING__SQPOLL, NULL); +} +#endif /* CONFIG_IO_URING */ + /* * IMPORTANT NOTE: When adding new hooks, please be careful to keep this order: * 1. any hooks that don't belong to (2.) or (3.) below, @@ -7353,6 +7415,11 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = { LSM_HOOK_INIT(perf_event_write, selinux_perf_event_write), #endif +#ifdef CONFIG_IO_URING + LSM_HOOK_INIT(uring_override_creds, selinux_uring_override_creds), + LSM_HOOK_INIT(uring_sqpoll, selinux_uring_sqpoll), +#endif + LSM_HOOK_INIT(locked_down, selinux_lockdown), /* diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h index 62d19bccf3de..3314ad72279d 100644 --- a/security/selinux/include/classmap.h +++ b/security/selinux/include/classmap.h @@ -252,6 +252,8 @@ struct security_class_mapping secclass_map[] = { { "integrity", "confidentiality", NULL } }, { "anon_inode", { COMMON_FILE_PERMS, NULL } }, + { "io_uring", + { "override_creds", "sqpoll", NULL } }, { NULL } }; From patchwork Fri May 21 21:50:37 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Moore X-Patchwork-Id: 12273835 X-Patchwork-Delegate: paul@paul-moore.com Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.7 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 94B5DC04FF3 for ; Fri, 21 May 2021 21:50:40 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 7943D613EA for ; Fri, 21 May 2021 21:50:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229921AbhEUVwD (ORCPT ); Fri, 21 May 2021 17:52:03 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57122 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229915AbhEUVwD (ORCPT ); Fri, 21 May 2021 17:52:03 -0400 Received: from mail-qk1-x72d.google.com (mail-qk1-x72d.google.com [IPv6:2607:f8b0:4864:20::72d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 90A3EC0613CE for ; Fri, 21 May 2021 14:50:39 -0700 (PDT) Received: by mail-qk1-x72d.google.com with SMTP id v8so21349761qkv.1 for ; Fri, 21 May 2021 14:50:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=paul-moore-com.20150623.gappssmtp.com; s=20150623; h=subject:from:to:date:message-id:in-reply-to:references:user-agent :mime-version:content-transfer-encoding; bh=yVODgsBH3pwJySxgTtmB98vfatsbGIZ28oW0IWdkpT0=; b=y0fBY74DDWd7J2Q4LAZ8Tc+S4IeIm0ggxMFDvuLxRMwxE4pBi5YQBOJb0yVHgNCjw/ 6nXTDhdi237ivx9OpFxTaSt/2w0iOl5KaPuinDGmWlVHyOd7eh+AjdQCE6TfppiXA1qw LiqA51F2Iji/7K4YBZqYJ6Jp3NMKsLAP/zlozfNFomva6gAUX0B3D0Rj7BviOlZga5fz qRdiUDzGr928A7t5cuzs8jxkLCfqqLd8UOFcH0J8HKrsYx4tgSDOcPII0hN8iO4TXTrm Vdoi2lzlO1NwBXvypm8t69RMAW+j40GzHN4PFkD789xwDPx0IIrJSlbaKk8KCBY7Iodj VKKQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:subject:from:to:date:message-id:in-reply-to :references:user-agent:mime-version:content-transfer-encoding; bh=yVODgsBH3pwJySxgTtmB98vfatsbGIZ28oW0IWdkpT0=; b=HjZ2utoOotbX1C8MmXz4JCG6k4Hx6gN0Poo9aIgTk5nk7C4t7zVgwk+uC0llbQbdiG B4R8DB4X0bcBXXobS4D91/869lIlCkjx0Q9rR6xleHCzdBCqE008RCyb36syv50vfjBE 8MKZTzxIN8upYBzTLJ++1bEJ6K1KNJHgujhO1ThSrKamIs6v1LmPzaeHgHS7+nyz09kT UiWOvuTv9uVjWLwnZt1cWPFaxLcXaMF4ldjeX5Rb2/kwq5JjEsXgXIcbvrzQu8i4IEPQ AESn4UFg+dTWQnNUu/salzSjNMDgTUJ8xlcLk5AFPmjh4d460kKk88IgFKf4uOJBR3KH DPrw== X-Gm-Message-State: AOAM533yOn7S3aD4+fCQTD1vQnxOmKc4nThu35DYbrZ3PA62eJWnLJXv OGmE8J5Ov6lv6jRFcGASUCsN X-Google-Smtp-Source: ABdhPJy8CbcdNgRZ+79GQ7zlutlj5Jo5vuvLZxS0af1cMkIKs15miDkHS/LPNWRaK6XS5ozPHjj0Fg== X-Received: by 2002:a37:ac0d:: with SMTP id e13mr11837998qkm.426.1621633838636; Fri, 21 May 2021 14:50:38 -0700 (PDT) Received: from localhost (pool-96-237-52-188.bstnma.fios.verizon.net. [96.237.52.188]) by smtp.gmail.com with ESMTPSA id h8sm4914383qtp.46.2021.05.21.14.50.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 21 May 2021 14:50:38 -0700 (PDT) Subject: [RFC PATCH 9/9] Smack: Brutalist io_uring support with debug From: Paul Moore To: linux-security-module@vger.kernel.org, selinux@vger.kernel.org, linux-audit@redhat.com, io-uring@vger.kernel.org, linux-fsdevel@vger.kernel.org, Kumar Kartikeya Dwivedi , Jens Axboe , Alexander Viro Date: Fri, 21 May 2021 17:50:37 -0400 Message-ID: <162163383761.8379.7421085717625472402.stgit@sifl> In-Reply-To: <162163367115.8379.8459012634106035341.stgit@sifl> References: <162163367115.8379.8459012634106035341.stgit@sifl> User-Agent: StGit/1.1 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: selinux@vger.kernel.org From: Casey Schaufler Add Smack privilege checks for io_uring. Use CAP_MAC_OVERRIDE for the override_creds case and CAP_MAC_ADMIN for creating a polling thread. These choices are based on conjecture regarding the intent of the surrounding code. Signed-off-by: Casey Schaufler Signed-off-by: Paul Moore --- security/smack/smack_lsm.c | 64 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 223a6da0e6dc..f6423c0096e9 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -4691,6 +4691,66 @@ static int smack_dentry_create_files_as(struct dentry *dentry, int mode, return 0; } +#ifdef CONFIG_IO_URING +/** + * smack_uring_override_creds - Is io_uring cred override allowed? + * @new: the target creds + * + * Check to see if the current task is allowed to override it's credentials + * to service an io_uring operation. + */ +int smack_uring_override_creds(const struct cred *new) +{ + struct task_smack *tsp = smack_cred(current_cred()); + struct task_smack *nsp = smack_cred(new); + +#if 1 + if (tsp->smk_task == nsp->smk_task) + pr_info("%s: Smack matches %s\n", __func__, + tsp->smk_task->smk_known); + else + pr_info("%s: Smack override check %s to %s\n", __func__, + tsp->smk_task->smk_known, nsp->smk_task->smk_known); +#endif + /* + * Allow the degenerate case where the new Smack value is + * the same as the current Smack value. + */ + if (tsp->smk_task == nsp->smk_task) + return 0; + +#if 1 + pr_info("%s: Smack sqpoll %s\n", __func__, + smack_privileged_cred(CAP_MAC_OVERRIDE, current_cred()) ? + "ok by Smack" : "disallowed (No CAP_MAC_OVERRIDE)"); +#endif + if (smack_privileged_cred(CAP_MAC_OVERRIDE, current_cred())) + return 0; + + return -EPERM; +} + +/** + * smack_uring_sqpoll - check if a io_uring polling thread can be created + * + * Check to see if the current task is allowed to create a new io_uring + * kernel polling thread. + */ +int smack_uring_sqpoll(void) +{ +#if 1 + pr_info("%s: Smack new ring %s\n", __func__, + smack_privileged_cred(CAP_MAC_ADMIN, current_cred()) ? + "ok by Smack" : "disallowed (No CAP_MAC_ADMIN)"); +#endif + if (smack_privileged_cred(CAP_MAC_ADMIN, current_cred())) + return 0; + + return -EPERM; +} + +#endif /* CONFIG_IO_URING */ + struct lsm_blob_sizes smack_blob_sizes __lsm_ro_after_init = { .lbs_cred = sizeof(struct task_smack), .lbs_file = sizeof(struct smack_known *), @@ -4843,6 +4903,10 @@ static struct security_hook_list smack_hooks[] __lsm_ro_after_init = { LSM_HOOK_INIT(inode_copy_up, smack_inode_copy_up), LSM_HOOK_INIT(inode_copy_up_xattr, smack_inode_copy_up_xattr), LSM_HOOK_INIT(dentry_create_files_as, smack_dentry_create_files_as), +#ifdef CONFIG_IO_URING + LSM_HOOK_INIT(uring_override_creds, smack_uring_override_creds), + LSM_HOOK_INIT(uring_sqpoll, smack_uring_sqpoll), +#endif };