From patchwork Mon Jan 31 18:57:36 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Scott Mayhew X-Patchwork-Id: 12731048 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 Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 32C3BC433EF for ; Mon, 31 Jan 2022 18:57:43 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1358635AbiAaS5m (ORCPT ); Mon, 31 Jan 2022 13:57:42 -0500 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]:29960 "EHLO us-smtp-delivery-124.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1351034AbiAaS5m (ORCPT ); Mon, 31 Jan 2022 13:57:42 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1643655461; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=2BmqQTpP7Ti7sWEQodfvEZZ7tU/bhgco+sYObBtILqY=; b=hC3T+l9Kej87ESz7+9DvcTd/qyYrdGo9GunRZ6GMtZHwkrOkuId2g2e4agbc33TlqsQ6rK jp7Nieh/c55iWzr55FYN/B0sEBU6tJjePtxB9nAhxjbhshdRWWTq2VnP1LARy/+IbaQ3N2 79zI+vswZrrlDw/A4H6VX8jUyctprU4= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-384-HA6uXdRFNOSZ3IZgvoSnJw-1; Mon, 31 Jan 2022 13:57:39 -0500 X-MC-Unique: HA6uXdRFNOSZ3IZgvoSnJw-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 3362161282; Mon, 31 Jan 2022 18:57:38 +0000 (UTC) Received: from aion.usersys.redhat.com (unknown [10.22.17.55]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 01D7984A24; Mon, 31 Jan 2022 18:57:38 +0000 (UTC) Received: by aion.usersys.redhat.com (Postfix, from userid 1000) id 430211A001E; Mon, 31 Jan 2022 13:57:37 -0500 (EST) From: Scott Mayhew To: paul@paul-moore.com Cc: selinux@vger.kernel.org, linux-nfs@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 1/2] selinux: Fix selinux_sb_mnt_opts_compat() Date: Mon, 31 Jan 2022 13:57:36 -0500 Message-Id: <20220131185737.1640824-2-smayhew@redhat.com> In-Reply-To: <20220131185737.1640824-1-smayhew@redhat.com> References: <20220131185737.1640824-1-smayhew@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 Precedence: bulk List-ID: X-Mailing-List: selinux@vger.kernel.org selinux_sb_mnt_opts_compat() is called under the sb_lock spinlock and shouldn't be performing any memory allocations. Fix this by parsing the sids at the same time we're chopping up the security mount options string and then using the pre-parsed sids when doing the comparison. Fixes: cc274ae7763d ("selinux: fix sleeping function called from invalid context") Fixes: 69c4a42d72eb ("lsm,selinux: add new hook to compare new mount to an existing mount") Signed-off-by: Scott Mayhew --- security/selinux/hooks.c | 75 ++++++++++++++++++++++------------------ 1 file changed, 41 insertions(+), 34 deletions(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 5b6895e4fc29..9645ff982ca5 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -342,6 +342,10 @@ static void inode_free_security(struct inode *inode) struct selinux_mnt_opts { const char *fscontext, *context, *rootcontext, *defcontext; + u32 fscontext_sid; + u32 context_sid; + u32 rootcontext_sid; + u32 defcontext_sid; }; static void selinux_free_mnt_opts(void *mnt_opts) @@ -598,15 +602,14 @@ static int bad_option(struct superblock_security_struct *sbsec, char flag, return 0; } -static int parse_sid(struct super_block *sb, const char *s, u32 *sid, - gfp_t gfp) +static int parse_sid(struct super_block *sb, const char *s, u32 *sid) { int rc = security_context_str_to_sid(&selinux_state, s, - sid, gfp); + sid, GFP_KERNEL); if (rc) pr_warn("SELinux: security_context_str_to_sid" "(%s) failed for (dev %s, type %s) errno=%d\n", - s, sb->s_id, sb->s_type->name, rc); + s, sb ? sb->s_id : "?", sb ? sb->s_type->name : "?", rc); return rc; } @@ -673,8 +676,7 @@ static int selinux_set_mnt_opts(struct super_block *sb, */ if (opts) { if (opts->fscontext) { - rc = parse_sid(sb, opts->fscontext, &fscontext_sid, - GFP_KERNEL); + rc = parse_sid(sb, opts->fscontext, &fscontext_sid); if (rc) goto out; if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid, @@ -683,8 +685,7 @@ static int selinux_set_mnt_opts(struct super_block *sb, sbsec->flags |= FSCONTEXT_MNT; } if (opts->context) { - rc = parse_sid(sb, opts->context, &context_sid, - GFP_KERNEL); + rc = parse_sid(sb, opts->context, &context_sid); if (rc) goto out; if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid, @@ -693,8 +694,7 @@ static int selinux_set_mnt_opts(struct super_block *sb, sbsec->flags |= CONTEXT_MNT; } if (opts->rootcontext) { - rc = parse_sid(sb, opts->rootcontext, &rootcontext_sid, - GFP_KERNEL); + rc = parse_sid(sb, opts->rootcontext, &rootcontext_sid); if (rc) goto out; if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid, @@ -703,8 +703,7 @@ static int selinux_set_mnt_opts(struct super_block *sb, sbsec->flags |= ROOTCONTEXT_MNT; } if (opts->defcontext) { - rc = parse_sid(sb, opts->defcontext, &defcontext_sid, - GFP_KERNEL); + rc = parse_sid(sb, opts->defcontext, &defcontext_sid); if (rc) goto out; if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid, @@ -996,21 +995,29 @@ static int selinux_add_opt(int token, const char *s, void **mnt_opts) if (opts->context || opts->defcontext) goto err; opts->context = s; + if (selinux_initialized(&selinux_state)) + parse_sid(NULL, s, &opts->context_sid); break; case Opt_fscontext: if (opts->fscontext) goto err; opts->fscontext = s; + if (selinux_initialized(&selinux_state)) + parse_sid(NULL, s, &opts->fscontext_sid); break; case Opt_rootcontext: if (opts->rootcontext) goto err; opts->rootcontext = s; + if (selinux_initialized(&selinux_state)) + parse_sid(NULL, s, &opts->rootcontext_sid); break; case Opt_defcontext: if (opts->context || opts->defcontext) goto err; opts->defcontext = s; + if (selinux_initialized(&selinux_state)) + parse_sid(NULL, s, &opts->defcontext_sid); break; } @@ -2648,8 +2655,6 @@ static int selinux_sb_mnt_opts_compat(struct super_block *sb, void *mnt_opts) { struct selinux_mnt_opts *opts = mnt_opts; struct superblock_security_struct *sbsec = sb->s_security; - u32 sid; - int rc; /* * Superblock not initialized (i.e. no options) - reject if any @@ -2666,34 +2671,36 @@ static int selinux_sb_mnt_opts_compat(struct super_block *sb, void *mnt_opts) return (sbsec->flags & SE_MNTMASK) ? 1 : 0; if (opts->fscontext) { - rc = parse_sid(sb, opts->fscontext, &sid, GFP_NOWAIT); - if (rc) + if (opts->fscontext_sid == SECSID_NULL) return 1; - if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid, sid)) + else if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid, + opts->fscontext_sid)) return 1; } if (opts->context) { - rc = parse_sid(sb, opts->context, &sid, GFP_NOWAIT); - if (rc) + if (opts->context_sid == SECSID_NULL) return 1; - if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid, sid)) + else if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid, + opts->context_sid)) return 1; } if (opts->rootcontext) { - struct inode_security_struct *root_isec; - - root_isec = backing_inode_security(sb->s_root); - rc = parse_sid(sb, opts->rootcontext, &sid, GFP_NOWAIT); - if (rc) - return 1; - if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid, sid)) + if (opts->rootcontext_sid == SECSID_NULL) return 1; + else { + struct inode_security_struct *root_isec; + + root_isec = backing_inode_security(sb->s_root); + if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid, + opts->rootcontext_sid)) + return 1; + } } if (opts->defcontext) { - rc = parse_sid(sb, opts->defcontext, &sid, GFP_NOWAIT); - if (rc) + if (opts->defcontext_sid == SECSID_NULL) return 1; - if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid, sid)) + else if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid, + opts->defcontext_sid)) return 1; } return 0; @@ -2713,14 +2720,14 @@ static int selinux_sb_remount(struct super_block *sb, void *mnt_opts) return 0; if (opts->fscontext) { - rc = parse_sid(sb, opts->fscontext, &sid, GFP_KERNEL); + rc = parse_sid(sb, opts->fscontext, &sid); if (rc) return rc; if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid, sid)) goto out_bad_option; } if (opts->context) { - rc = parse_sid(sb, opts->context, &sid, GFP_KERNEL); + rc = parse_sid(sb, opts->context, &sid); if (rc) return rc; if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid, sid)) @@ -2729,14 +2736,14 @@ static int selinux_sb_remount(struct super_block *sb, void *mnt_opts) if (opts->rootcontext) { struct inode_security_struct *root_isec; root_isec = backing_inode_security(sb->s_root); - rc = parse_sid(sb, opts->rootcontext, &sid, GFP_KERNEL); + rc = parse_sid(sb, opts->rootcontext, &sid); if (rc) return rc; if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid, sid)) goto out_bad_option; } if (opts->defcontext) { - rc = parse_sid(sb, opts->defcontext, &sid, GFP_KERNEL); + rc = parse_sid(sb, opts->defcontext, &sid); if (rc) return rc; if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid, sid)) From patchwork Mon Jan 31 18:57:37 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Scott Mayhew X-Patchwork-Id: 12731049 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 Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 08EF8C4332F for ; Mon, 31 Jan 2022 18:57:45 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1358715AbiAaS5o (ORCPT ); Mon, 31 Jan 2022 13:57:44 -0500 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]:24760 "EHLO us-smtp-delivery-124.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1358697AbiAaS5n (ORCPT ); Mon, 31 Jan 2022 13:57:43 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1643655462; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=ed3hVQ48RMb2MFp4ZsSa5NSDyBIXulmD20K/MbtpUpk=; b=Hjp8pr/M4hObhqvH4IMDc1tbYx25Uo/q5bzYJC8jSsBXJgxYMj2UJKarrYwQK/eXEOtiIF o6z6ZDKXQw5VS6pwJE9iQv+05k2cQRHMdtKySQJkREbDbCjpVfcov8nfLWI/TNNiqRHdy4 SHKMxeiGTK2BKEssuV1nr07ocjM0Zs4= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-384-1llfo-CJMBG_0whZZL0v8w-1; Mon, 31 Jan 2022 13:57:39 -0500 X-MC-Unique: 1llfo-CJMBG_0whZZL0v8w-1 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 3BEA81091DA9; Mon, 31 Jan 2022 18:57:38 +0000 (UTC) Received: from aion.usersys.redhat.com (unknown [10.22.17.55]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 04CF038E05; Mon, 31 Jan 2022 18:57:38 +0000 (UTC) Received: by aion.usersys.redhat.com (Postfix, from userid 1000) id 460891A0021; Mon, 31 Jan 2022 13:57:37 -0500 (EST) From: Scott Mayhew To: paul@paul-moore.com Cc: selinux@vger.kernel.org, linux-nfs@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 2/2] selinux: try to use preparsed sid before calling parse_sid() Date: Mon, 31 Jan 2022 13:57:37 -0500 Message-Id: <20220131185737.1640824-3-smayhew@redhat.com> In-Reply-To: <20220131185737.1640824-1-smayhew@redhat.com> References: <20220131185737.1640824-1-smayhew@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 Precedence: bulk List-ID: X-Mailing-List: selinux@vger.kernel.org Avoid unnecessary parsing of sids that have already been parsed via selinux_sb_eat_lsm_opts(). Signed-off-by: Scott Mayhew --- security/selinux/hooks.c | 88 +++++++++++++++++++++++++++------------- 1 file changed, 59 insertions(+), 29 deletions(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 9645ff982ca5..05d24b7a68cf 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -676,36 +676,48 @@ static int selinux_set_mnt_opts(struct super_block *sb, */ if (opts) { if (opts->fscontext) { - rc = parse_sid(sb, opts->fscontext, &fscontext_sid); - if (rc) - goto out; + if (opts->fscontext_sid == SECSID_NULL) { + rc = parse_sid(sb, opts->fscontext, &fscontext_sid); + if (rc) + goto out; + } else + fscontext_sid = opts->fscontext_sid; if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid, fscontext_sid)) goto out_double_mount; sbsec->flags |= FSCONTEXT_MNT; } if (opts->context) { - rc = parse_sid(sb, opts->context, &context_sid); - if (rc) - goto out; + if (opts->context_sid == SECSID_NULL) { + rc = parse_sid(sb, opts->context, &context_sid); + if (rc) + goto out; + } else + context_sid = opts->context_sid; if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid, context_sid)) goto out_double_mount; sbsec->flags |= CONTEXT_MNT; } if (opts->rootcontext) { - rc = parse_sid(sb, opts->rootcontext, &rootcontext_sid); - if (rc) - goto out; + if (opts->rootcontext_sid == SECSID_NULL) { + rc = parse_sid(sb, opts->rootcontext, &rootcontext_sid); + if (rc) + goto out; + } else + rootcontext_sid = opts->rootcontext_sid; if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid, rootcontext_sid)) goto out_double_mount; sbsec->flags |= ROOTCONTEXT_MNT; } if (opts->defcontext) { - rc = parse_sid(sb, opts->defcontext, &defcontext_sid); - if (rc) - goto out; + if (opts->defcontext_sid == SECSID_NULL) { + rc = parse_sid(sb, opts->defcontext, &defcontext_sid); + if (rc) + goto out; + } else + defcontext_sid = opts->defcontext_sid; if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid, defcontext_sid)) goto out_double_mount; @@ -2710,7 +2722,6 @@ static int selinux_sb_remount(struct super_block *sb, void *mnt_opts) { struct selinux_mnt_opts *opts = mnt_opts; struct superblock_security_struct *sbsec = selinux_superblock(sb); - u32 sid; int rc; if (!(sbsec->flags & SE_SBINITIALIZED)) @@ -2720,33 +2731,48 @@ static int selinux_sb_remount(struct super_block *sb, void *mnt_opts) return 0; if (opts->fscontext) { - rc = parse_sid(sb, opts->fscontext, &sid); - if (rc) - return rc; - if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid, sid)) + if (opts->fscontext_sid == SECSID_NULL) { + rc = parse_sid(sb, opts->fscontext, + &opts->fscontext_sid); + if (rc) + return rc; + } + if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid, + opts->fscontext_sid)) goto out_bad_option; } if (opts->context) { - rc = parse_sid(sb, opts->context, &sid); - if (rc) - return rc; - if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid, sid)) + if (opts->context_sid == SECSID_NULL) { + rc = parse_sid(sb, opts->context, &opts->context_sid); + if (rc) + return rc; + } + if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid, + opts->context_sid)) goto out_bad_option; } if (opts->rootcontext) { struct inode_security_struct *root_isec; root_isec = backing_inode_security(sb->s_root); - rc = parse_sid(sb, opts->rootcontext, &sid); - if (rc) - return rc; - if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid, sid)) + if (opts->rootcontext_sid == SECSID_NULL) { + rc = parse_sid(sb, opts->rootcontext, + &opts->rootcontext_sid); + if (rc) + return rc; + } + if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid, + opts->rootcontext_sid)) goto out_bad_option; } if (opts->defcontext) { - rc = parse_sid(sb, opts->defcontext, &sid); - if (rc) - return rc; - if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid, sid)) + if (opts->defcontext_sid == SECSID_NULL) { + rc = parse_sid(sb, opts->defcontext, + &opts->defcontext_sid); + if (rc) + return rc; + } + if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid, + opts->defcontext_sid)) goto out_bad_option; } return 0; @@ -2844,6 +2870,10 @@ static int selinux_fs_context_dup(struct fs_context *fc, if (!opts->defcontext) return -ENOMEM; } + opts->fscontext_sid = src->fscontext_sid; + opts->context_sid = src->context_sid; + opts->rootcontext_sid = src->rootcontext_sid; + opts->defcontext_sid = src->defcontext_sid; return 0; }