From patchwork Tue Feb 5 11:06:34 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ondrej Mosnacek X-Patchwork-Id: 10797321 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id BE46C6C2 for ; Tue, 5 Feb 2019 11:06:51 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id AE1942AC37 for ; Tue, 5 Feb 2019 11:06:51 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id A1BDD2B3E0; Tue, 5 Feb 2019 11:06:51 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 100822AC37 for ; Tue, 5 Feb 2019 11:06:51 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727966AbfBELGu (ORCPT ); Tue, 5 Feb 2019 06:06:50 -0500 Received: from mail-wm1-f65.google.com ([209.85.128.65]:51894 "EHLO mail-wm1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727613AbfBELGu (ORCPT ); Tue, 5 Feb 2019 06:06:50 -0500 Received: by mail-wm1-f65.google.com with SMTP id b11so3145003wmj.1 for ; Tue, 05 Feb 2019 03:06:48 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=qWCOjIpCOk81UALDGpP07aau3ZMFw3eCyGnAaDjo63o=; b=BigJFqTaJkG9fugW0BT+Ucutm71S94zE8lTqLrHPGBzeUXwRtJqOzqmiwuSzxgx46d og0PCD6V8rbexYcBvXYs1jPXuq/CIkDxb8MBQxqK87KSR7xBhG/BG2pEfxtflVYgOFX4 eSy25hmsIEcE/F+kiF6/D7CzH64MBT+H+MGmUTpYVBefesSGilkhCzQCboP2K0eQMKcW WG5/YSWzkJYiAB6pfhcPB3eFkuehRIR8eVOkIhhjVZm68G5D3Ii49ALUgs2tjpNRaTBz rkIaB7JIrFYU05R+I9SjMl8Rd4zO6miPYu0HGkfskjL0qGPFIc7Ddbj9AGESh5MO3TdP zNhg== X-Gm-Message-State: AHQUAuarHU4EEyNtALfRfmGiCVEbErBgmlm8Jw4kWu3R553No4VKtGek 26VTkRwrOQkywlmNDKBDM7SuJxcaSNQ= X-Google-Smtp-Source: AHgI3IZsOkMczuUcFhr9zTjKONnb8AuE1voIL/wtDRlbJgGf1zwsDVulUQwaM4qTHAxWxsoyFO4+LQ== X-Received: by 2002:a1c:c60e:: with SMTP id w14mr3510378wmf.18.1549364806986; Tue, 05 Feb 2019 03:06:46 -0800 (PST) Received: from localhost.localdomain.com (nat-pool-brq-t.redhat.com. [213.175.37.10]) by smtp.gmail.com with ESMTPSA id x186sm26067070wmg.41.2019.02.05.03.06.45 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 05 Feb 2019 03:06:46 -0800 (PST) From: Ondrej Mosnacek To: selinux@vger.kernel.org, Paul Moore Cc: Stephen Smalley , linux-security-module@vger.kernel.org, Casey Schaufler , Greg Kroah-Hartman , Tejun Heo , linux-fsdevel@vger.kernel.org, cgroups@vger.kernel.org, Ondrej Mosnacek Subject: [PATCH v5 1/5] selinux: try security xattr after genfs for kernfs filesystems Date: Tue, 5 Feb 2019 12:06:34 +0100 Message-Id: <20190205110638.30782-2-omosnace@redhat.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190205110638.30782-1-omosnace@redhat.com> References: <20190205110638.30782-1-omosnace@redhat.com> MIME-Version: 1.0 Sender: selinux-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: selinux@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Since kernfs supports the security xattr handlers, we can simply use these to determine the inode's context, dropping the need to update it from kernfs explicitly using a security_inode_notifysecctx() call. We achieve this by setting a new sbsec flag SE_SBGENFS_XATTR to all mounts that are known to use kernfs under the hood and then fetching the xattrs after determining the fallback genfs sid in inode_doinit_with_dentry() when this flag is set. This will allow implementing full security xattr support in kernfs and removing the ...notifysecctx() call in a subsequent patch. Signed-off-by: Ondrej Mosnacek --- security/selinux/hooks.c | 159 +++++++++++++++------------- security/selinux/include/security.h | 1 + 2 files changed, 88 insertions(+), 72 deletions(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 81e012c66d95..758a99d1086e 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -793,11 +793,13 @@ static int selinux_set_mnt_opts(struct super_block *sb, if (!strcmp(sb->s_type->name, "debugfs") || !strcmp(sb->s_type->name, "tracefs") || - !strcmp(sb->s_type->name, "sysfs") || - !strcmp(sb->s_type->name, "pstore") || + !strcmp(sb->s_type->name, "pstore")) + sbsec->flags |= SE_SBGENFS; + + if (!strcmp(sb->s_type->name, "sysfs") || !strcmp(sb->s_type->name, "cgroup") || !strcmp(sb->s_type->name, "cgroup2")) - sbsec->flags |= SE_SBGENFS; + sbsec->flags |= SE_SBGENFS | SE_SBGENFS_XATTR; if (!sbsec->behavior) { /* @@ -1392,6 +1394,71 @@ static int selinux_genfs_get_sid(struct dentry *dentry, return rc; } +static int inode_doinit_use_xattr(struct inode *inode, struct dentry *dentry, + u32 def_sid, u32 *sid) +{ +#define INITCONTEXTLEN 255 + char *context = NULL; + unsigned int len = 0; + int rc; + + *sid = def_sid; + + if (!(inode->i_opflags & IOP_XATTR)) + return 0; + + len = INITCONTEXTLEN; + context = kmalloc(len + 1, GFP_NOFS); + if (!context) + return -ENOMEM; + + context[len] = '\0'; + rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, context, len); + if (rc == -ERANGE) { + kfree(context); + + /* Need a larger buffer. Query for the right size. */ + rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, NULL, 0); + if (rc < 0) + return rc; + + len = rc; + context = kmalloc(len + 1, GFP_NOFS); + if (!context) + return -ENOMEM; + + context[len] = '\0'; + rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, + context, len); + } + if (rc < 0) { + kfree(context); + if (rc != -ENODATA) { + pr_warn("SELinux: %s: getxattr returned %d for dev=%s ino=%ld\n", + __func__, -rc, inode->i_sb->s_id, inode->i_ino); + return rc; + } + return 0; + } + + rc = security_context_to_sid_default(&selinux_state, context, rc, sid, + def_sid, GFP_NOFS); + if (rc) { + char *dev = inode->i_sb->s_id; + unsigned long ino = inode->i_ino; + + if (rc == -EINVAL) { + pr_notice_ratelimited("SELinux: inode=%lu on dev=%s was found to have an invalid context=%s. This indicates you may need to relabel the inode or the filesystem in question.\n", + ino, dev, context); + } else { + pr_warn("SELinux: %s: context_to_sid(%s) returned %d for dev=%s ino=%ld\n", + __func__, context, -rc, dev, ino); + } + } + kfree(context); + return 0; +} + /* The inode's security attributes must be initialized before first use. */ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry) { @@ -1401,8 +1468,6 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent u16 sclass; struct dentry *dentry; #define INITCONTEXTLEN 255 - char *context = NULL; - unsigned len = 0; int rc = 0; if (isec->initialized == LABEL_INITIALIZED) @@ -1470,72 +1535,11 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent goto out; } - len = INITCONTEXTLEN; - context = kmalloc(len+1, GFP_NOFS); - if (!context) { - rc = -ENOMEM; - dput(dentry); - goto out; - } - context[len] = '\0'; - rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, context, len); - if (rc == -ERANGE) { - kfree(context); - - /* Need a larger buffer. Query for the right size. */ - rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, NULL, 0); - if (rc < 0) { - dput(dentry); - goto out; - } - len = rc; - context = kmalloc(len+1, GFP_NOFS); - if (!context) { - rc = -ENOMEM; - dput(dentry); - goto out; - } - context[len] = '\0'; - rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, context, len); - } + rc = inode_doinit_use_xattr(inode, dentry, sbsec->def_sid, + &sid); dput(dentry); - if (rc < 0) { - if (rc != -ENODATA) { - pr_warn("SELinux: %s: getxattr returned " - "%d for dev=%s ino=%ld\n", __func__, - -rc, inode->i_sb->s_id, inode->i_ino); - kfree(context); - goto out; - } - /* Map ENODATA to the default file SID */ - sid = sbsec->def_sid; - rc = 0; - } else { - rc = security_context_to_sid_default(&selinux_state, - context, rc, &sid, - sbsec->def_sid, - GFP_NOFS); - if (rc) { - char *dev = inode->i_sb->s_id; - unsigned long ino = inode->i_ino; - - if (rc == -EINVAL) { - if (printk_ratelimit()) - pr_notice("SELinux: inode=%lu on dev=%s was found to have an invalid " - "context=%s. This indicates you may need to relabel the inode or the " - "filesystem in question.\n", ino, dev, context); - } else { - pr_warn("SELinux: %s: context_to_sid(%s) " - "returned %d for dev=%s ino=%ld\n", - __func__, context, -rc, dev, ino); - } - kfree(context); - /* Leave with the unlabeled SID */ - rc = 0; - break; - } - } - kfree(context); + if (rc) + goto out; break; case SECURITY_FS_USE_TASK: sid = task_sid; @@ -1586,9 +1590,20 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent goto out; rc = selinux_genfs_get_sid(dentry, sclass, sbsec->flags, &sid); - dput(dentry); - if (rc) + if (rc) { + dput(dentry); goto out; + } + + if (sbsec->flags & SE_SBGENFS_XATTR) { + rc = inode_doinit_use_xattr(inode, dentry, + sid, &sid); + if (rc) { + dput(dentry); + goto out; + } + } + dput(dentry); } break; } diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index f68fb25b5702..6e5928f951da 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h @@ -58,6 +58,7 @@ #define SE_SBINITIALIZED 0x0100 #define SE_SBPROC 0x0200 #define SE_SBGENFS 0x0400 +#define SE_SBGENFS_XATTR 0x0800 #define CONTEXT_STR "context=" #define FSCONTEXT_STR "fscontext=" From patchwork Tue Feb 5 11:06:35 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ondrej Mosnacek X-Patchwork-Id: 10797329 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 916D913B4 for ; Tue, 5 Feb 2019 11:06:54 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 82FBD2B3DE for ; Tue, 5 Feb 2019 11:06:54 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 76F2F2B3E0; Tue, 5 Feb 2019 11:06:54 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C30992B3DE for ; Tue, 5 Feb 2019 11:06:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727250AbfBELGx (ORCPT ); Tue, 5 Feb 2019 06:06:53 -0500 Received: from mail-wr1-f66.google.com ([209.85.221.66]:41143 "EHLO mail-wr1-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727783AbfBELGv (ORCPT ); Tue, 5 Feb 2019 06:06:51 -0500 Received: by mail-wr1-f66.google.com with SMTP id x10so3101891wrs.8 for ; Tue, 05 Feb 2019 03:06:49 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=6QMYjOe+pf/wWcR8iZ9VPRtgN1hVQge8pFTdDf7ePKo=; b=Bdb7YY4ClVwh9PMVZxHox+DQuWk9w04sB2viMLQMCe2IoFHZqD/10KMqObVlWaEfib 7JuxrOHTQw9ulrePoTA+aZN6hhJkF3D0BN49husJzsURPSEJedN4R+Od7JxtwPJ0/QZc YD04k8ua2inWc0Ic+BB3UVEKv89Eoo4aR/YV/D5K05cjlXq58lWDe38obEiNg1o1nwpx 5vo9h0i50oCwvKOzQVcrKfg8AaFRib7h/sGCGIoiftEne2J4VStSfUB0q24h+lKV7V6e StyCsjA+dFY64ONuGWfcDVH3zQyPCD2hMlLMFNy0Gyo1oU3J7tmnBZAhajuH5hVPGDVm T7Eg== X-Gm-Message-State: AHQUAuaGjYjJQSTOJAV5I9yfrvs+b6QbqyBSw2aRwubpp/q+rYlFZy5R 9nRQ4iJNKPZMC8olQZELjxQtjmXMpsY= X-Google-Smtp-Source: AHgI3IYF8rpCCtwIQzRAWMg+yUamNHk5c9bqFPJXzGURnchbFgUzKlre7abvYHc4clFxIRxndBjNCw== X-Received: by 2002:a5d:6710:: with SMTP id o16mr3326395wru.152.1549364808394; Tue, 05 Feb 2019 03:06:48 -0800 (PST) Received: from localhost.localdomain.com (nat-pool-brq-t.redhat.com. [213.175.37.10]) by smtp.gmail.com with ESMTPSA id x186sm26067070wmg.41.2019.02.05.03.06.47 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 05 Feb 2019 03:06:47 -0800 (PST) From: Ondrej Mosnacek To: selinux@vger.kernel.org, Paul Moore Cc: Stephen Smalley , linux-security-module@vger.kernel.org, Casey Schaufler , Greg Kroah-Hartman , Tejun Heo , linux-fsdevel@vger.kernel.org, cgroups@vger.kernel.org, Ondrej Mosnacek Subject: [PATCH v5 2/5] kernfs: use simple_xattrs for security attributes Date: Tue, 5 Feb 2019 12:06:35 +0100 Message-Id: <20190205110638.30782-3-omosnace@redhat.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190205110638.30782-1-omosnace@redhat.com> References: <20190205110638.30782-1-omosnace@redhat.com> MIME-Version: 1.0 Sender: selinux-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: selinux@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Replace the special handling of security xattrs with simple_xattrs, as is already done for the trusted xattrs. This simplifies the code and allows LSMs to use more than just a single xattr to do their business. Signed-off-by: Ondrej Mosnacek --- fs/kernfs/dir.c | 7 ++- fs/kernfs/inode.c | 100 +++++++++++++++--------------------- fs/kernfs/kernfs-internal.h | 5 +- 3 files changed, 46 insertions(+), 66 deletions(-) diff --git a/fs/kernfs/dir.c b/fs/kernfs/dir.c index 4ca0b5c18192..ad7e3356bcc5 100644 --- a/fs/kernfs/dir.c +++ b/fs/kernfs/dir.c @@ -532,11 +532,10 @@ void kernfs_put(struct kernfs_node *kn) kfree_const(kn->name); if (kn->iattr) { - if (kn->iattr->ia_secdata) - security_release_secctx(kn->iattr->ia_secdata, - kn->iattr->ia_secdata_len); - simple_xattrs_free(&kn->iattr->xattrs); + simple_xattrs_free(&kn->iattr->xattrs_trusted); + simple_xattrs_free(&kn->iattr->xattrs_security); } + kfree(kn->iattr); spin_lock(&kernfs_idr_lock); idr_remove(&root->ino_idr, kn->id.ino); diff --git a/fs/kernfs/inode.c b/fs/kernfs/inode.c index 80cebcd94c90..f0e2cb4379c0 100644 --- a/fs/kernfs/inode.c +++ b/fs/kernfs/inode.c @@ -56,7 +56,8 @@ static struct kernfs_iattrs *kernfs_iattrs(struct kernfs_node *kn) iattrs->ia_mtime = iattrs->ia_atime; iattrs->ia_ctime = iattrs->ia_atime; - simple_xattrs_init(&kn->iattr->xattrs); + simple_xattrs_init(&kn->iattr->xattrs_trusted); + simple_xattrs_init(&kn->iattr->xattrs_security); out_unlock: ret = kn->iattr; mutex_unlock(&iattr_mutex); @@ -135,33 +136,31 @@ out: return error; } -static int kernfs_node_setsecdata(struct kernfs_iattrs *attrs, void **secdata, - u32 *secdata_len) -{ - void *old_secdata; - size_t old_secdata_len; - - old_secdata = attrs->ia_secdata; - old_secdata_len = attrs->ia_secdata_len; - - attrs->ia_secdata = *secdata; - attrs->ia_secdata_len = *secdata_len; - - *secdata = old_secdata; - *secdata_len = old_secdata_len; - return 0; -} - ssize_t kernfs_iop_listxattr(struct dentry *dentry, char *buf, size_t size) { struct kernfs_node *kn = kernfs_dentry_node(dentry); + struct inode *inode = d_inode(dentry); struct kernfs_iattrs *attrs; + ssize_t ret, length = 0; attrs = kernfs_iattrs(kn); if (!attrs) return -ENOMEM; - return simple_xattr_list(d_inode(dentry), &attrs->xattrs, buf, size); + ret = simple_xattr_list(inode, &attrs->xattrs_trusted, buf, size); + if (ret < 0) + return ret; + length += ret; + + buf += ret; + size -= ret; + + ret = simple_xattr_list(inode, &attrs->xattrs_security, buf, size); + if (ret < 0) + return ret; + length += ret; + + return length; } static inline void set_default_inode_attr(struct inode *inode, umode_t mode) @@ -186,15 +185,12 @@ static void kernfs_refresh_inode(struct kernfs_node *kn, struct inode *inode) struct kernfs_iattrs *attrs = kn->iattr; inode->i_mode = kn->mode; - if (attrs) { + if (attrs) /* * kernfs_node has non-default attributes get them from * persistent copy in kernfs_node. */ set_inode_attr(inode, &attrs->ia_iattr); - security_inode_notifysecctx(inode, attrs->ia_secdata, - attrs->ia_secdata_len); - } if (kernfs_type(kn) == KERNFS_DIR) set_nlink(inode, kn->dir.subdirs + 2); @@ -305,19 +301,29 @@ int kernfs_iop_permission(struct inode *inode, int mask) return generic_permission(inode, mask); } +static const struct xattr_handler kernfs_trusted_xattr_handler; +static const struct xattr_handler kernfs_security_xattr_handler; + static int kernfs_xattr_get(const struct xattr_handler *handler, struct dentry *unused, struct inode *inode, const char *suffix, void *value, size_t size) { - const char *name = xattr_full_name(handler, suffix); struct kernfs_node *kn = inode->i_private; struct kernfs_iattrs *attrs; + struct simple_xattrs *xattrs; attrs = kernfs_iattrs(kn); if (!attrs) return -ENOMEM; - return simple_xattr_get(&attrs->xattrs, name, value, size); + if (handler == &kernfs_trusted_xattr_handler) + xattrs = &attrs->xattrs_trusted; + else if (handler == &kernfs_security_xattr_handler) + xattrs = &attrs->xattrs_security; + else + return -EINVAL; + + return simple_xattr_get(xattrs, suffix, value, size); } static int kernfs_xattr_set(const struct xattr_handler *handler, @@ -325,15 +331,22 @@ static int kernfs_xattr_set(const struct xattr_handler *handler, const char *suffix, const void *value, size_t size, int flags) { - const char *name = xattr_full_name(handler, suffix); struct kernfs_node *kn = inode->i_private; struct kernfs_iattrs *attrs; + struct simple_xattrs *xattrs; attrs = kernfs_iattrs(kn); if (!attrs) return -ENOMEM; - return simple_xattr_set(&attrs->xattrs, name, value, size, flags); + if (handler == &kernfs_trusted_xattr_handler) + xattrs = &attrs->xattrs_trusted; + else if (handler == &kernfs_security_xattr_handler) + xattrs = &attrs->xattrs_security; + else + return -EINVAL; + + return simple_xattr_set(xattrs, suffix, value, size, flags); } static const struct xattr_handler kernfs_trusted_xattr_handler = { @@ -342,41 +355,10 @@ static const struct xattr_handler kernfs_trusted_xattr_handler = { .set = kernfs_xattr_set, }; -static int kernfs_security_xattr_set(const struct xattr_handler *handler, - struct dentry *unused, struct inode *inode, - const char *suffix, const void *value, - size_t size, int flags) -{ - struct kernfs_node *kn = inode->i_private; - struct kernfs_iattrs *attrs; - void *secdata; - u32 secdata_len = 0; - int error; - - attrs = kernfs_iattrs(kn); - if (!attrs) - return -ENOMEM; - - error = security_inode_setsecurity(inode, suffix, value, size, flags); - if (error) - return error; - error = security_inode_getsecctx(inode, &secdata, &secdata_len); - if (error) - return error; - - mutex_lock(&kernfs_mutex); - error = kernfs_node_setsecdata(attrs, &secdata, &secdata_len); - mutex_unlock(&kernfs_mutex); - - if (secdata) - security_release_secctx(secdata, secdata_len); - return error; -} - static const struct xattr_handler kernfs_security_xattr_handler = { .prefix = XATTR_SECURITY_PREFIX, .get = kernfs_xattr_get, - .set = kernfs_security_xattr_set, + .set = kernfs_xattr_set, }; const struct xattr_handler *kernfs_xattr_handlers[] = { diff --git a/fs/kernfs/kernfs-internal.h b/fs/kernfs/kernfs-internal.h index 3d83b114bb08..93bf1dcd0306 100644 --- a/fs/kernfs/kernfs-internal.h +++ b/fs/kernfs/kernfs-internal.h @@ -20,10 +20,9 @@ struct kernfs_iattrs { struct iattr ia_iattr; - void *ia_secdata; - u32 ia_secdata_len; - struct simple_xattrs xattrs; + struct simple_xattrs xattrs_trusted; + struct simple_xattrs xattrs_security; }; /* +1 to avoid triggering overflow warning when negating it */ From patchwork Tue Feb 5 11:06:36 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ondrej Mosnacek X-Patchwork-Id: 10797347 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 455C56C2 for ; Tue, 5 Feb 2019 11:06:59 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 36F762AC37 for ; Tue, 5 Feb 2019 11:06:59 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 2A7F42B403; Tue, 5 Feb 2019 11:06:59 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B33502AC37 for ; Tue, 5 Feb 2019 11:06:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727735AbfBELG5 (ORCPT ); Tue, 5 Feb 2019 06:06:57 -0500 Received: from mail-wm1-f65.google.com ([209.85.128.65]:52304 "EHLO mail-wm1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727613AbfBELGw (ORCPT ); Tue, 5 Feb 2019 06:06:52 -0500 Received: by mail-wm1-f65.google.com with SMTP id m1so3138987wml.2 for ; Tue, 05 Feb 2019 03:06:50 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=nXKwAbEZfoxXrwUQ8rLT22YtPLuVavDsba7+2hRLZ3I=; b=udSgMmtiJLF9BapOU3YO1uJJ9VGxHVBLEsHadLTnf8qchP3uw2G/smh98pG1ffBYkZ y8ZRP2MrZ+bKtz8Vr1LB7ALv+/7eOVhUz1aRghKArBlCNtJmW3klc1krBbLm6BUsonDD /0P9FUeOUNSwWrKd62GhMI5u87lez1Jt4Pz17c71VZj8DaObl8/kkQ6iv0aC1FG5uQRG AiAn66vFVGgcL0L92/miZk9VYL0t1wIT0bTj4fIoR9T2lj0eWmleCzW4jc4lMYWkyA0E sbWG90vM/dGsgbWaZwYU/J8Em2EHsOdW/W5lqygWud4/PqNiGOdeIMrt78cqMdTLtiXb PfOA== X-Gm-Message-State: AHQUAuZV72bz+yAXT7tHl/Ok42dcPElTaDZP7E9/kSKzXvaX/HI2ID7E w0+Dk01ONBt68KaJT9GeNtV6NwQ83zc= X-Google-Smtp-Source: AHgI3IaAYUGEenLV/qz0PhHBKBRLpJTMK4BSilxFhZkBoiEzpKmgqEAXm7i1G+PsfAPW1vyjGNl8kA== X-Received: by 2002:a1c:488b:: with SMTP id v133mr3419464wma.31.1549364809489; Tue, 05 Feb 2019 03:06:49 -0800 (PST) Received: from localhost.localdomain.com (nat-pool-brq-t.redhat.com. [213.175.37.10]) by smtp.gmail.com with ESMTPSA id x186sm26067070wmg.41.2019.02.05.03.06.48 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 05 Feb 2019 03:06:48 -0800 (PST) From: Ondrej Mosnacek To: selinux@vger.kernel.org, Paul Moore Cc: Stephen Smalley , linux-security-module@vger.kernel.org, Casey Schaufler , Greg Kroah-Hartman , Tejun Heo , linux-fsdevel@vger.kernel.org, cgroups@vger.kernel.org, Ondrej Mosnacek Subject: [PATCH v5 3/5] LSM: add new hook for kernfs node initialization Date: Tue, 5 Feb 2019 12:06:36 +0100 Message-Id: <20190205110638.30782-4-omosnace@redhat.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190205110638.30782-1-omosnace@redhat.com> References: <20190205110638.30782-1-omosnace@redhat.com> MIME-Version: 1.0 Sender: selinux-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: selinux@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This patch introduces a new security hook that is intended for initializing the security data for newly created kernfs nodes, which provide a way of storing a non-default security context, but need to operate independently from mounts (and therefore may not have an associated inode at the moment of creation). The main motivation is to allow kernfs nodes to inherit the context of the parent under SELinux, similar to the behavior of security_inode_init_security(). Other LSMs may implement their own logic for handling the creation of new nodes. The interface of the new hook provides the following to the LSM: * a qstr containing the name of the new node * inode attributes of the parent node (directory) * initial inode attributes (struct iattr + simple_xattrs) of the new node Signed-off-by: Ondrej Mosnacek --- include/linux/lsm_hooks.h | 22 ++++++++++++++++++++++ include/linux/security.h | 14 ++++++++++++++ security/security.c | 10 ++++++++++ 3 files changed, 46 insertions(+) diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index 9a0bdf91e646..558bbc0ff125 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -429,6 +429,21 @@ * to abort the copy up. Note that the caller is responsible for reading * and writing the xattrs as this hook is merely a filter. * + * Security hooks for kernfs node operations + * + * @kernfs_init_security + * Initialize the security context of a newlycreated kernfs node based + * on its own and its parent's attributes. The security context (or other + * LSM metadata) should be stored in @secattr as extended attributes. + * The hook MAY NOT add/modify attributes in @dir_secattr; it should be + * treated as a read-only list of attributes. + * + * @qstr contains the last path component of the new node. + * @dir_iattr contains the inode attributes of the parent node. + * @dir_secattr is the list of security xattrs of the parent node. + * @iattr contains the inode attributes of the new node. + * @secattr is the list of security xattrs of the new node. + * * Security hooks for file operations * * @file_permission: @@ -1558,6 +1573,12 @@ union security_list_options { int (*inode_copy_up)(struct dentry *src, struct cred **new); int (*inode_copy_up_xattr)(const char *name); + int (*kernfs_init_security)(const struct qstr *qstr, + const struct iattr *dir_iattr, + struct simple_xattrs *dir_secattr, + const struct iattr *iattr, + struct simple_xattrs *secattr); + int (*file_permission)(struct file *file, int mask); int (*file_alloc_security)(struct file *file); void (*file_free_security)(struct file *file); @@ -1858,6 +1879,7 @@ struct security_hook_heads { struct hlist_head inode_getsecid; struct hlist_head inode_copy_up; struct hlist_head inode_copy_up_xattr; + struct hlist_head kernfs_init_security; struct hlist_head file_permission; struct hlist_head file_alloc_security; struct hlist_head file_free_security; diff --git a/include/linux/security.h b/include/linux/security.h index dbfb5a66babb..581944d1e61e 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -51,6 +51,7 @@ struct fown_struct; struct file_operations; struct msg_msg; struct xattr; +struct simple_xattrs; struct xfrm_sec_ctx; struct mm_struct; @@ -291,6 +292,11 @@ int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer void security_inode_getsecid(struct inode *inode, u32 *secid); int security_inode_copy_up(struct dentry *src, struct cred **new); int security_inode_copy_up_xattr(const char *name); +int security_kernfs_init_security(const struct qstr *qstr, + const struct iattr *dir_iattr, + struct simple_xattrs *dir_secattr, + const struct iattr *iattr, + struct simple_xattrs *secattr); int security_file_permission(struct file *file, int mask); int security_file_alloc(struct file *file); void security_file_free(struct file *file); @@ -783,6 +789,14 @@ static inline int security_inode_copy_up(struct dentry *src, struct cred **new) return 0; } +static inline int security_kernfs_init_security( + const struct qstr *qstr, const struct iattr *dir_iattr, + struct simple_xattrs *dir_secattr, const struct iattr *iattr, + struct simple_xattrs *secattr) +{ + return 0; +} + static inline int security_inode_copy_up_xattr(const char *name) { return -EOPNOTSUPP; diff --git a/security/security.c b/security/security.c index f1b8d2587639..836e0822874a 100644 --- a/security/security.c +++ b/security/security.c @@ -892,6 +892,16 @@ int security_inode_copy_up_xattr(const char *name) } EXPORT_SYMBOL(security_inode_copy_up_xattr); +int security_kernfs_init_security(const struct qstr *qstr, + const struct iattr *dir_iattr, + struct simple_xattrs *dir_secattr, + const struct iattr *iattr, + struct simple_xattrs *secattr) +{ + return call_int_hook(kernfs_init_security, 0, qstr, dir_iattr, + dir_secattr, iattr, secattr); +} + int security_file_permission(struct file *file, int mask) { int ret; From patchwork Tue Feb 5 11:06:37 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ondrej Mosnacek X-Patchwork-Id: 10797333 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 31954186D for ; Tue, 5 Feb 2019 11:06:55 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 22D0C2AC37 for ; Tue, 5 Feb 2019 11:06:55 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 173022B403; Tue, 5 Feb 2019 11:06:55 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B4A852AC37 for ; Tue, 5 Feb 2019 11:06:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727337AbfBELGy (ORCPT ); Tue, 5 Feb 2019 06:06:54 -0500 Received: from mail-wm1-f67.google.com ([209.85.128.67]:38556 "EHLO mail-wm1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728020AbfBELGx (ORCPT ); Tue, 5 Feb 2019 06:06:53 -0500 Received: by mail-wm1-f67.google.com with SMTP id m22so3159554wml.3 for ; Tue, 05 Feb 2019 03:06:51 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=3/UgfA2b1LMjP8l3IHGLgf3GGlVLs/lH9BS+aBvDM2I=; b=HT4cjD/hsm2o3hbrufJtuhtRKc5n7FGch34YsD7+OJ5uD1bzuRD70BQcUgQFoaI8lF WzP1EjYemOMm3nElPqQu+Grt3pMbukRtfwrig3SA4znVelM2o3rq8pv6joAPP8hnPFww CGPPact4RVnNeBe+VQ+A/IsEdBTNP+W8KL6RdWuZb8gdGwwpw79ogC92Rc+rx4flYZfW Mtr2GhCToTrw4gyX9YHJE4Ar32dMCRW2EJ7ZYQAqQEAnBGz1Of3CvGrT0/G2VE6Egd9C WIW9ryswrLDnR3SX484p9/J/26K0nPukEfvqHwZj8jrnywTq2+dnbFOEBMfmOLIpmrPT 8k8g== X-Gm-Message-State: AHQUAua44S48r1PTa76PzmSbe3M44mGrTzzfHSdCcbNqZWzABowGDMWe 5Op58Mi63jlVDqvO2o9oVj4ItwNViBQ= X-Google-Smtp-Source: AHgI3IY6xruLh9iK67l00gygLYpeYDFM92ZbgXYOFgp4iHRp6OAiiXLZ3IHgyfyB1lbVxiclA/BSaw== X-Received: by 2002:a1c:1902:: with SMTP id 2mr3388784wmz.150.1549364810864; Tue, 05 Feb 2019 03:06:50 -0800 (PST) Received: from localhost.localdomain.com (nat-pool-brq-t.redhat.com. [213.175.37.10]) by smtp.gmail.com with ESMTPSA id x186sm26067070wmg.41.2019.02.05.03.06.49 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 05 Feb 2019 03:06:49 -0800 (PST) From: Ondrej Mosnacek To: selinux@vger.kernel.org, Paul Moore Cc: Stephen Smalley , linux-security-module@vger.kernel.org, Casey Schaufler , Greg Kroah-Hartman , Tejun Heo , linux-fsdevel@vger.kernel.org, cgroups@vger.kernel.org, Ondrej Mosnacek Subject: [PATCH v5 4/5] selinux: implement the kernfs_init_security hook Date: Tue, 5 Feb 2019 12:06:37 +0100 Message-Id: <20190205110638.30782-5-omosnace@redhat.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190205110638.30782-1-omosnace@redhat.com> References: <20190205110638.30782-1-omosnace@redhat.com> MIME-Version: 1.0 Sender: selinux-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: selinux@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The hook applies the same logic as selinux_determine_inode_label(), with the exception of the super_block handling, which will be enforced on the actual inodes later by other hooks. Signed-off-by: Ondrej Mosnacek --- security/selinux/hooks.c | 62 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 758a99d1086e..e013cc02de50 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -3354,6 +3354,66 @@ static int selinux_inode_copy_up_xattr(const char *name) return -EOPNOTSUPP; } +/* kernfs node operations */ + +int selinux_kernfs_init_security(const struct qstr *qstr, + const struct iattr *dir_iattr, + struct simple_xattrs *dir_secattr, + const struct iattr *iattr, + struct simple_xattrs *secattr) +{ + const struct task_security_struct *tsec = current_security(); + u32 parent_sid, newsid, clen; + int rc; + char *context; + + rc = simple_xattr_get(dir_secattr, XATTR_SELINUX_SUFFIX, NULL, 0); + if (rc == -ENODATA) + return 0; + else if (rc < 0) + return rc; + + clen = (u32)rc; + context = kmalloc(clen, GFP_KERNEL); + if (!context) + return -ENOMEM; + + rc = simple_xattr_get(dir_secattr, XATTR_SELINUX_SUFFIX, context, clen); + if (rc < 0) { + kfree(context); + return rc; + } + + rc = security_context_to_sid(&selinux_state, context, clen, &parent_sid, + GFP_KERNEL); + kfree(context); + if (rc) + return rc; + + if (tsec->create_sid) { + newsid = tsec->create_sid; + } else { + u16 secclass = inode_mode_to_security_class(iattr->ia_mode); + + rc = security_transition_sid(&selinux_state, tsec->sid, + parent_sid, secclass, qstr, + &newsid); + if (rc) + return rc; + } + + rc = security_sid_to_context_force(&selinux_state, newsid, + &context, &clen); + if (rc) + return rc; + + rc = simple_xattr_set(secattr, XATTR_SELINUX_SUFFIX, context, clen, + XATTR_CREATE); + kfree(context); + return rc; +} + + /* file security operations */ static int selinux_revalidate_file_permission(struct file *file, int mask) @@ -6800,6 +6860,8 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = { LSM_HOOK_INIT(inode_copy_up, selinux_inode_copy_up), LSM_HOOK_INIT(inode_copy_up_xattr, selinux_inode_copy_up_xattr), + LSM_HOOK_INIT(kernfs_init_security, selinux_kernfs_init_security), + LSM_HOOK_INIT(file_permission, selinux_file_permission), LSM_HOOK_INIT(file_alloc_security, selinux_file_alloc_security), LSM_HOOK_INIT(file_free_security, selinux_file_free_security), From patchwork Tue Feb 5 11:06:38 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ondrej Mosnacek X-Patchwork-Id: 10797345 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 0DD2517FB for ; Tue, 5 Feb 2019 11:06:58 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id F2AEC2AC37 for ; Tue, 5 Feb 2019 11:06:57 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id E665C2B3E0; Tue, 5 Feb 2019 11:06:57 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 5ACF72B3DE for ; Tue, 5 Feb 2019 11:06:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728131AbfBELGy (ORCPT ); Tue, 5 Feb 2019 06:06:54 -0500 Received: from mail-wr1-f67.google.com ([209.85.221.67]:40197 "EHLO mail-wr1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728097AbfBELGy (ORCPT ); Tue, 5 Feb 2019 06:06:54 -0500 Received: by mail-wr1-f67.google.com with SMTP id p4so3113346wrt.7 for ; Tue, 05 Feb 2019 03:06:52 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=7b1bc6+meFmPqgAqo0J5mXXNpERkis1nOajyuz7TJZM=; b=PB1tDJ18iJC7Aiq6+HjL4BMC6RsAybf71foTH2OpYt//8vE2mCTzogNXJKfU0HKy3A bZ1CTmkAVpcwXKOSjSNRpbMdSpB+Gr+qDQHb9uLObX289eo6TzuzEWSjAkpkPSk9+mYI m2Mow0vzVxouQPbc6BhQQ9skcshOGOkXEdeDOmtfVVvYo/yGmMhfXU2NFX2dymLvjZWS 3+tKFEDDWQuGXPmiSylsM90OeZx2xxBRoB5eeaIghQaan1jo+K2Ixs7Avx3e0EPg06hu c56qn1ECAYgZ/nUom+UjFKRh7JMwWT9d9RvMjBz+3/slhDcHREXEL5M2BrzhOvyXg56s n0sQ== X-Gm-Message-State: AHQUAuZ22iDIInSPsvw+Y4J3KzwgDtrBSBFIO7R8LU7sHQWAJfKVvSb7 xDp6p2FbWoukJ5C+Ad3vpNPVqEs/U64= X-Google-Smtp-Source: AHgI3IbtPjz2TYWo6fiL5PDsWek1XUn3NMtS9U+1Kl6wcqIYcGoqXFKFA3FDY7v8qMdViPJ4nfh+Kw== X-Received: by 2002:adf:f692:: with SMTP id v18mr3010075wrp.229.1549364811965; Tue, 05 Feb 2019 03:06:51 -0800 (PST) Received: from localhost.localdomain.com (nat-pool-brq-t.redhat.com. [213.175.37.10]) by smtp.gmail.com with ESMTPSA id x186sm26067070wmg.41.2019.02.05.03.06.50 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 05 Feb 2019 03:06:51 -0800 (PST) From: Ondrej Mosnacek To: selinux@vger.kernel.org, Paul Moore Cc: Stephen Smalley , linux-security-module@vger.kernel.org, Casey Schaufler , Greg Kroah-Hartman , Tejun Heo , linux-fsdevel@vger.kernel.org, cgroups@vger.kernel.org, Ondrej Mosnacek Subject: [PATCH v5 5/5] kernfs: initialize security of newly created nodes Date: Tue, 5 Feb 2019 12:06:38 +0100 Message-Id: <20190205110638.30782-6-omosnace@redhat.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190205110638.30782-1-omosnace@redhat.com> References: <20190205110638.30782-1-omosnace@redhat.com> MIME-Version: 1.0 Sender: selinux-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: selinux@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Use the new security_kernfs_init_security() hook to allow LSMs to possibly assign a non-default security context to a newly created kernfs node based on the attributes of the new node and also its parent node. This fixes an issue with cgroupfs under SELinux, where newly created cgroup subdirectories/files would not inherit its parent's context if it had been set explicitly to a non-default value (other than the genfs context specified by the policy). This can be reproduced as follows (on Fedora/RHEL): # mkdir /sys/fs/cgroup/unified/test # # Need permissive to change the label under Fedora policy: # setenforce 0 # chcon -t container_file_t /sys/fs/cgroup/unified/test # ls -lZ /sys/fs/cgroup/unified total 0 -r--r--r--. 1 root root system_u:object_r:cgroup_t:s0 0 Jan 29 03:06 cgroup.controllers -rw-r--r--. 1 root root system_u:object_r:cgroup_t:s0 0 Jan 29 03:06 cgroup.max.depth -rw-r--r--. 1 root root system_u:object_r:cgroup_t:s0 0 Jan 29 03:06 cgroup.max.descendants -rw-r--r--. 1 root root system_u:object_r:cgroup_t:s0 0 Jan 29 03:06 cgroup.procs -r--r--r--. 1 root root system_u:object_r:cgroup_t:s0 0 Jan 29 03:06 cgroup.stat -rw-r--r--. 1 root root system_u:object_r:cgroup_t:s0 0 Jan 29 03:06 cgroup.subtree_control -rw-r--r--. 1 root root system_u:object_r:cgroup_t:s0 0 Jan 29 03:06 cgroup.threads drwxr-xr-x. 2 root root system_u:object_r:cgroup_t:s0 0 Jan 29 03:06 init.scope drwxr-xr-x. 26 root root system_u:object_r:cgroup_t:s0 0 Jan 29 03:21 system.slice drwxr-xr-x. 3 root root system_u:object_r:container_file_t:s0 0 Jan 29 03:15 test drwxr-xr-x. 3 root root system_u:object_r:cgroup_t:s0 0 Jan 29 03:06 user.slice # mkdir /sys/fs/cgroup/unified/test/subdir Actual result: # ls -ldZ /sys/fs/cgroup/unified/test/subdir drwxr-xr-x. 2 root root system_u:object_r:cgroup_t:s0 0 Jan 29 03:15 /sys/fs/cgroup/unified/test/subdir Expected result: # ls -ldZ /sys/fs/cgroup/unified/test/subdir drwxr-xr-x. 2 root root unconfined_u:object_r:container_file_t:s0 0 Jan 29 03:15 /sys/fs/cgroup/unified/test/subdir Link: https://github.com/SELinuxProject/selinux-kernel/issues/39 Signed-off-by: Ondrej Mosnacek --- fs/kernfs/dir.c | 57 +++++++++++++++++++++++++++++++++++-- fs/kernfs/inode.c | 25 +++++++++------- fs/kernfs/kernfs-internal.h | 2 ++ include/linux/xattr.h | 15 ++++++++++ 4 files changed, 86 insertions(+), 13 deletions(-) diff --git a/fs/kernfs/dir.c b/fs/kernfs/dir.c index ad7e3356bcc5..735a6d382d9d 100644 --- a/fs/kernfs/dir.c +++ b/fs/kernfs/dir.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "kernfs-internal.h" @@ -616,7 +617,53 @@ struct kernfs_node *kernfs_node_from_dentry(struct dentry *dentry) return NULL; } +static int kernfs_node_init_security(struct kernfs_node *parent, + struct kernfs_node *kn) +{ + struct simple_xattrs xattr_child, xattr_parent, *pxattr_parent; + struct iattr iattr_child, iattr_parent, *piattr_parent; + struct qstr q; + int ret; + + if (!parent->iattr) { + kernfs_iattr_init(&iattr_parent, parent); + simple_xattrs_init(&xattr_parent); + piattr_parent = &iattr_parent; + pxattr_parent = &xattr_parent; + } else { + piattr_parent = &parent->iattr->ia_iattr; + pxattr_parent = &parent->iattr->xattrs_security; + } + + kernfs_iattr_init(&iattr_child, kn); + simple_xattrs_init(&xattr_child); + + q.name = kn->name; + q.hash_len = hashlen_string(parent, kn->name); + + ret = security_kernfs_init_security(&q, piattr_parent, pxattr_parent, + &iattr_child, &xattr_child); + if (pxattr_parent == &xattr_parent) + simple_xattrs_free(&xattr_parent); + if (!ret && !simple_xattrs_empty(&xattr_child)) { + /* + * Child has new security xattrs, allocate its kernfs_iattrs + * and put our local xattrs in there. + */ + struct kernfs_iattrs *attrs = kernfs_iattrs(kn); + + if (!attrs) { + simple_xattrs_free(&xattr_child); + return -ENOMEM; + } + simple_xattrs_move(&attrs->xattrs_security, &xattr_child); + } + simple_xattrs_free(&xattr_child); + return ret; +} + static struct kernfs_node *__kernfs_new_node(struct kernfs_root *root, + struct kernfs_node *parent, const char *name, umode_t mode, kuid_t uid, kgid_t gid, unsigned flags) @@ -673,6 +720,12 @@ static struct kernfs_node *__kernfs_new_node(struct kernfs_root *root, goto err_out3; } + if (parent) { + ret = kernfs_node_init_security(parent, kn); + if (ret) + goto err_out3; + } + return kn; err_out3: @@ -691,7 +744,7 @@ struct kernfs_node *kernfs_new_node(struct kernfs_node *parent, { struct kernfs_node *kn; - kn = __kernfs_new_node(kernfs_root(parent), + kn = __kernfs_new_node(kernfs_root(parent), parent, name, mode, uid, gid, flags); if (kn) { kernfs_get(parent); @@ -961,7 +1014,7 @@ struct kernfs_root *kernfs_create_root(struct kernfs_syscall_ops *scops, INIT_LIST_HEAD(&root->supers); root->next_generation = 1; - kn = __kernfs_new_node(root, "", S_IFDIR | S_IRUGO | S_IXUGO, + kn = __kernfs_new_node(root, NULL, "", S_IFDIR | S_IRUGO | S_IXUGO, GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, KERNFS_DIR); if (!kn) { diff --git a/fs/kernfs/inode.c b/fs/kernfs/inode.c index f0e2cb4379c0..6a9084aecbe5 100644 --- a/fs/kernfs/inode.c +++ b/fs/kernfs/inode.c @@ -31,11 +31,22 @@ static const struct inode_operations kernfs_iops = { .listxattr = kernfs_iop_listxattr, }; -static struct kernfs_iattrs *kernfs_iattrs(struct kernfs_node *kn) +void kernfs_iattr_init(struct iattr *iattrs, struct kernfs_node *kn) +{ + /* assign default attributes */ + iattrs->ia_mode = kn->mode; + iattrs->ia_uid = GLOBAL_ROOT_UID; + iattrs->ia_gid = GLOBAL_ROOT_GID; + + ktime_get_real_ts64(&iattrs->ia_atime); + iattrs->ia_mtime = iattrs->ia_atime; + iattrs->ia_ctime = iattrs->ia_atime; +} + +struct kernfs_iattrs *kernfs_iattrs(struct kernfs_node *kn) { static DEFINE_MUTEX(iattr_mutex); struct kernfs_iattrs *ret; - struct iattr *iattrs; mutex_lock(&iattr_mutex); @@ -45,16 +56,8 @@ static struct kernfs_iattrs *kernfs_iattrs(struct kernfs_node *kn) kn->iattr = kzalloc(sizeof(struct kernfs_iattrs), GFP_KERNEL); if (!kn->iattr) goto out_unlock; - iattrs = &kn->iattr->ia_iattr; - - /* assign default attributes */ - iattrs->ia_mode = kn->mode; - iattrs->ia_uid = GLOBAL_ROOT_UID; - iattrs->ia_gid = GLOBAL_ROOT_GID; - ktime_get_real_ts64(&iattrs->ia_atime); - iattrs->ia_mtime = iattrs->ia_atime; - iattrs->ia_ctime = iattrs->ia_atime; + kernfs_iattr_init(&kn->iattr->ia_iattr, kn); simple_xattrs_init(&kn->iattr->xattrs_trusted); simple_xattrs_init(&kn->iattr->xattrs_security); diff --git a/fs/kernfs/kernfs-internal.h b/fs/kernfs/kernfs-internal.h index 93bf1dcd0306..ad80f438d8d4 100644 --- a/fs/kernfs/kernfs-internal.h +++ b/fs/kernfs/kernfs-internal.h @@ -90,6 +90,8 @@ int kernfs_iop_getattr(const struct path *path, struct kstat *stat, u32 request_mask, unsigned int query_flags); ssize_t kernfs_iop_listxattr(struct dentry *dentry, char *buf, size_t size); int __kernfs_setattr(struct kernfs_node *kn, const struct iattr *iattr); +void kernfs_iattr_init(struct iattr *iattrs, struct kernfs_node *kn); +struct kernfs_iattrs *kernfs_iattrs(struct kernfs_node *kn); /* * dir.c diff --git a/include/linux/xattr.h b/include/linux/xattr.h index 6dad031be3c2..05fc6812d554 100644 --- a/include/linux/xattr.h +++ b/include/linux/xattr.h @@ -108,4 +108,19 @@ ssize_t simple_xattr_list(struct inode *inode, struct simple_xattrs *xattrs, cha void simple_xattr_list_add(struct simple_xattrs *xattrs, struct simple_xattr *new_xattr); +static inline int simple_xattrs_empty(struct simple_xattrs *xattrs) +{ + return list_empty(&xattrs->head); +} + +/** + * Move the xattr list from @src to @dst, leaving @src empty. + */ +static inline void simple_xattrs_move(struct simple_xattrs *dst, + struct simple_xattrs *src) +{ + simple_xattrs_free(dst); + list_replace_init(&src->head, &dst->head); +} + #endif /* _LINUX_XATTR_H */