From: Andreas Gruenbacher <andreas.gruenbacher@gmail.com>
To: Alexander Viro <viro@zeniv.linux.org.uk>,
Christoph Hellwig <hch@infradead.org>,
Eric Paris <eparis@redhat.com>,
"Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com>,
linux-fsdevel@vger.kernel.org,
David Quigley <dpquigl@davequigley.com>,
"J. Bruce Fields" <bfields@fieldses.org>
Cc: linux-security-module@vger.kernel.org, cluster-devel@redhat.com
Subject: [RFC 10/11] selinux: Allow to invalidate an inode's security label
Date: Thu, 20 Aug 2015 20:19:57 +0200 [thread overview]
Message-ID: <1440094798-1411-11-git-send-email-agruenba@redhat.com> (raw)
In-Reply-To: <1440094798-1411-1-git-send-email-agruenba@redhat.com>
Add the LSM and SELinux infrastructure for invalidating inode->i_security and
for re-initializing it from inode_has_perm when necessary. In inode_has_perm,
we don't have access to a dentry, so file systems must implement iop->igetxattr
in order to be able to invalidate security labels.
Alternatively, we could add an inode operation called by inode_has_perm to
revalidate the security label of the inode on each call, but inode_has_perm is
called so frequently that the overhead seems excessive.
Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
---
include/linux/lsm_hooks.h | 6 +++++
include/linux/security.h | 5 +++++
security/selinux/hooks.c | 47 ++++++++++++++++++++++++++++++---------
security/selinux/include/objsec.h | 3 ++-
4 files changed, 49 insertions(+), 12 deletions(-)
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index 9429f05..9fe99d6 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -1261,6 +1261,10 @@
* audit_rule_init.
* @rule contains the allocated rule
*
+ * @inode_invalidate_secctx:
+ * Notify the security module that it must revalidate the security context
+ * of an inode before the next access.
+ *
* @inode_notifysecctx:
* Notify the security module of what the security context of an inode
* should be. Initializes the incore security context managed by the
@@ -1516,6 +1520,7 @@ union security_list_options {
int (*secctx_to_secid)(const char *secdata, u32 seclen, u32 *secid);
void (*release_secctx)(char *secdata, u32 seclen);
+ void (*inode_invalidate_secctx)(struct inode *inode);
int (*inode_notifysecctx)(struct inode *inode, void *ctx, u32 ctxlen);
int (*inode_setsecctx)(struct dentry *dentry, void *ctx, u32 ctxlen);
int (*inode_getsecctx)(struct inode *inode, void **ctx, u32 *ctxlen);
@@ -1757,6 +1762,7 @@ struct security_hook_heads {
struct list_head secid_to_secctx;
struct list_head secctx_to_secid;
struct list_head release_secctx;
+ struct list_head inode_invalidate_secctx;
struct list_head inode_notifysecctx;
struct list_head inode_setsecctx;
struct list_head inode_getsecctx;
diff --git a/include/linux/security.h b/include/linux/security.h
index 79d85dd..f50587d 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -353,6 +353,7 @@ int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen);
int security_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid);
void security_release_secctx(char *secdata, u32 seclen);
+int security_inode_invalidate_secctx(struct inode *inode);
int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen);
int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen);
int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen);
@@ -1093,6 +1094,10 @@ static inline void security_release_secctx(char *secdata, u32 seclen)
{
}
+static inline void security_inode_invalidate_secctx(struct inode *inode)
+{
+}
+
static inline int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen)
{
return -EOPNOTSUPP;
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 564079c..e80fcda 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -430,7 +430,7 @@ static int sb_finish_set_opts(struct super_block *sb)
rc = -EOPNOTSUPP;
goto out;
}
- rc = root_inode->i_op->getxattr(root, XATTR_NAME_SELINUX, NULL, 0);
+ rc = selinux_getxattr(root_inode, root, NULL, 0);
if (rc < 0 && rc != -ENODATA) {
if (rc == -EOPNOTSUPP)
printk(KERN_WARNING "SELinux: (dev %s, type "
@@ -1270,6 +1270,19 @@ static int selinux_genfs_get_sid(struct dentry *dentry,
return rc;
}
+static int selinux_getxattr(struct inode *inode, struct dentry *dentry,
+ char *context, unsigned int len)
+{
+ if (dentry)
+ return inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,
+ context, len);
+ else if (inode && inode->i_op->igetxattr)
+ return inode->i_op->igetxattr(inode, XATTR_NAME_SELINUX,
+ context, len);
+ else
+ return -EOPNOTSUPP;
+}
+
/* The inode's security attributes must be initialized before first use. */
static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry)
{
@@ -1282,11 +1295,11 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
unsigned len = 0;
int rc = 0;
- if (isec->initialized)
+ if (isec->initialized == 1)
goto out;
mutex_lock(&isec->lock);
- if (isec->initialized)
+ if (isec->initialized == 1)
goto out_unlock;
sbsec = inode->i_sb->s_security;
@@ -1319,7 +1332,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
/* Called from selinux_complete_init, try to find a dentry. */
dentry = d_find_alias(inode);
}
- if (!dentry) {
+ if (!dentry && !inode->i_op->igetxattr) {
/*
* this is can be hit on boot when a file is accessed
* before the policy is loaded. When we load policy we
@@ -1340,14 +1353,12 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
goto out_unlock;
}
context[len] = '\0';
- rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,
- context, len);
+ rc = selinux_getxattr(inode, dentry, context, len);
if (rc == -ERANGE) {
kfree(context);
/* Need a larger buffer. Query for the right size. */
- rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,
- NULL, 0);
+ rc = selinux_getxattr(inode, dentry, NULL, 0);
if (rc < 0) {
dput(dentry);
goto out_unlock;
@@ -1360,9 +1371,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
goto out_unlock;
}
context[len] = '\0';
- rc = inode->i_op->getxattr(dentry,
- XATTR_NAME_SELINUX,
- context, len);
+ rc = selinux_getxattr(inode, dentry, context, len);
}
dput(dentry);
if (rc < 0) {
@@ -1614,6 +1623,12 @@ static int inode_has_perm(const struct cred *cred,
sid = cred_sid(cred);
isec = inode->i_security;
+ if (isec->initialized == 2) {
+ inode_doinit(inode);
+ if (isec->initialized == 2)
+ return -EACCES;
+ }
+
return avc_has_perm(sid, isec->sid, isec->sclass, perms, adp);
}
@@ -5715,6 +5730,15 @@ static void selinux_release_secctx(char *secdata, u32 seclen)
kfree(secdata);
}
+static void selinux_inode_invalidate_secctx(struct inode *inode)
+{
+ struct inode_security_struct *isec = inode->i_security;
+
+ mutex_lock(&isec->lock);
+ isec->initialized = 2;
+ mutex_unlock(&isec->lock);
+}
+
/*
* called with inode->i_mutex locked
*/
@@ -5946,6 +5970,7 @@ static struct security_hook_list selinux_hooks[] = {
LSM_HOOK_INIT(secid_to_secctx, selinux_secid_to_secctx),
LSM_HOOK_INIT(secctx_to_secid, selinux_secctx_to_secid),
LSM_HOOK_INIT(release_secctx, selinux_release_secctx),
+ LSM_HOOK_INIT(inode_invalidate_secctx, selinux_inode_invalidate_secctx),
LSM_HOOK_INIT(inode_notifysecctx, selinux_inode_notifysecctx),
LSM_HOOK_INIT(inode_setsecctx, selinux_inode_setsecctx),
LSM_HOOK_INIT(inode_getsecctx, selinux_inode_getsecctx),
diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h
index 81fa718..5b13732 100644
--- a/security/selinux/include/objsec.h
+++ b/security/selinux/include/objsec.h
@@ -46,7 +46,8 @@ struct inode_security_struct {
u32 task_sid; /* SID of creating task */
u32 sid; /* SID of this object */
u16 sclass; /* security class of this object */
- unsigned char initialized; /* initialization flag */
+ unsigned char initialized; /* 0: not initialized, 1: initialized,
+ 2: needs revalidation */
struct mutex lock;
};
--
2.4.3
next prev parent reply other threads:[~2015-08-20 18:25 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-08-20 18:19 [RFC 00/11] Inode security label invalidation Andreas Gruenbacher
2015-08-20 18:19 ` [RFC 01/11] ubifs: Remove unused "security.*" xattr handler Andreas Gruenbacher
2015-08-20 18:19 ` [RFC 02/11] hfsplus: Remove unused xattr handler list operations Andreas Gruenbacher
2015-08-20 18:19 ` [RFC 03/11] 9p: Simplify the xattr handlers Andreas Gruenbacher
2015-08-20 18:19 ` [RFC 04/11] xattr handlers: Pass handler to operations instead of flags Andreas Gruenbacher
2015-08-20 18:19 ` [RFC 05/11] xattr handlers: Some simplifications Andreas Gruenbacher
2015-08-20 18:19 ` [RFC 06/11] lib: Move strcmp_prefix into string.c Andreas Gruenbacher
2015-08-20 18:19 ` [RFC 07/11] 9p: Stop using the generic xattr_handler infrastructure Andreas Gruenbacher
2015-08-21 6:46 ` Christoph Hellwig
2015-08-21 8:35 ` [Cluster-devel] " Steven Whitehouse
2015-08-20 18:19 ` [RFC 08/11] xattr: Pass inodes to xattr handlers instead of dentries Andreas Gruenbacher
2015-08-20 18:19 ` [RFC 09/11] vfs: Add igetxattr inode operation Andreas Gruenbacher
2015-08-21 6:48 ` Christoph Hellwig
2015-08-20 18:19 ` Andreas Gruenbacher [this message]
2015-08-20 18:19 ` [RFC 11/11] gfs2: Invalide security labels of inodes that go invalid Andreas Gruenbacher
2015-08-21 6:49 ` Christoph Hellwig
2015-08-21 9:25 ` [Cluster-devel] " Andreas Gruenbacher
2015-08-24 17:42 ` [RFC 00/11] Inode security label invalidation Stephen Smalley
2015-08-24 19:13 ` Andreas Grünbacher
2015-08-24 20:47 ` Eric Paris
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1440094798-1411-11-git-send-email-agruenba@redhat.com \
--to=andreas.gruenbacher@gmail.com \
--cc=aneesh.kumar@linux.vnet.ibm.com \
--cc=bfields@fieldses.org \
--cc=cluster-devel@redhat.com \
--cc=dpquigl@davequigley.com \
--cc=eparis@redhat.com \
--cc=hch@infradead.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-security-module@vger.kernel.org \
--cc=viro@zeniv.linux.org.uk \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).