From: David Howells <dhowells@redhat.com>
To: James Morris <jmorris@namei.org>
Cc: David Howells <dhowells@redhat.com>,
Linus Torvalds <torvalds@osdl.org>, Andrew Morton <akpm@osdl.org>,
Stephen Smalley <sds@tycho.nsa.gov>,
trond.myklebust@fys.uio.no, selinux@tycho.nsa.gov,
linux-kernel@vger.kernel.org, aviro@redhat.com,
steved@redhat.com
Subject: Re: [PATCH 12/19] CacheFiles: Permit a process's create SID to be overridden
Date: Wed, 15 Nov 2006 13:50:44 +0000 [thread overview]
Message-ID: <24555.1163598644@redhat.com> (raw)
In-Reply-To: <XMMS.LNX.4.64.0611141618300.25022@d.namei>
James Morris <jmorris@namei.org> wrote:
> The ability to set this needs to be mediated via MAC policy.
Something like this, you mean?
David
---
security/selinux/hooks.c | 12 +++-
security/dummy.c | 2 -
include/linux/security.h | 9 ++-
fs/cachefiles/cf-bind.c | 3 +
fs/cachefiles/cf-daemon.c | 16 +++--
fs/cachefiles/cf-interface.c | 40 ++++++++-----
fs/cachefiles/cf-security.c | 36 +++++++++++
fs/cachefiles/cf-security.h | 134 ++++++++++++++++++++++++++++++++++++++++++
fs/cachefiles/internal.h | 61 +------------------
9 files changed, 225 insertions(+), 88 deletions(-)
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 3a52698..5bfae9b 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -4559,13 +4559,19 @@ static u32 selinux_get_fscreate_secid(vo
return tsec->create_sid;
}
-static u32 selinux_set_fscreate_secid(u32 secid)
+static int selinux_set_fscreate_secid(u32 secid, u32 *oldsecid)
{
struct task_security_struct *tsec = current->security;
- u32 oldsid = tsec->create_sid;
+ int error;
+
+ error = task_has_perm(current, current, PROCESS__SETFSCREATE);
+ if (error < 0)
+ return error;
+ if (oldsecid)
+ *oldsecid = tsec->create_sid;
tsec->create_sid = secid;
- return oldsid;
+ return 0;
}
static u32 selinux_act_as_secid(u32 secid)
diff --git a/security/dummy.c b/security/dummy.c
index 30096ec..471b369 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -937,7 +937,7 @@ static u32 dummy_get_fscreate_secid(void
return 0;
}
-static u32 dummy_set_fscreate_secid(u32 secid)
+static int dummy_set_fscreate_secid(u32 secid, u32 *oldsecid)
{
return 0;
}
diff --git a/include/linux/security.h b/include/linux/security.h
index 8cfeefc..7aa86a3 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -1160,6 +1160,7 @@ #ifdef CONFIG_SECURITY
* @set_fscreate_secid:
* Set the current FS security ID.
* @secid contains the security ID to set.
+ * @oldsecid points to where the old security ID will be placed (or NULL).
*
* @act_as_secid:
* Set the security ID as which to act, returning the security ID as which
@@ -1363,7 +1364,7 @@ struct security_operations {
int (*secid_to_secctx)(u32 secid, char **secdata, u32 *seclen);
void (*release_secctx)(char *secdata, u32 seclen);
u32 (*get_fscreate_secid)(void);
- u32 (*set_fscreate_secid)(u32 secid);
+ int (*set_fscreate_secid)(u32 secid, u32 *oldsecid);
u32 (*act_as_secid)(u32 secid);
u32 (*act_as_self)(void);
int (*cachefiles_get_secid)(u32 secid, u32 *modsecid);
@@ -2174,9 +2175,9 @@ static inline u32 security_get_fscreate_
return security_ops->get_fscreate_secid();
}
-static inline u32 security_set_fscreate_secid(u32 secid)
+static inline int security_set_fscreate_secid(u32 secid, u32 *oldsecid)
{
- return security_ops->set_fscreate_secid(secid);
+ return security_ops->set_fscreate_secid(secid, oldsecid);
}
static inline u32 security_act_as_secid(u32 secid)
@@ -2884,7 +2885,7 @@ static inline u32 security_get_fscreate_
return 0;
}
-static inline u32 security_set_fscreate_secid(u32 secid)
+static inline int security_set_fscreate_secid(u32 secid, u32 *oldsecid)
{
return 0;
}
diff --git a/fs/cachefiles/cf-bind.c b/fs/cachefiles/cf-bind.c
index 0c055a9..c8e68a4 100644
--- a/fs/cachefiles/cf-bind.c
+++ b/fs/cachefiles/cf-bind.c
@@ -226,6 +226,8 @@ static int cachefiles_daemon_add_cache(s
MAJOR(fsdef->dentry->d_sb->s_dev),
MINOR(fsdef->dentry->d_sb->s_dev));
+ set_bit(CACHEFILES_FSCACHE_INITED, &cache->flags);
+
ret = fscache_add_cache(&cache->cache, &fsdef->fscache, cache->tag);
if (ret < 0)
goto error_add_cache;
@@ -273,6 +275,7 @@ void cachefiles_daemon_unbind(struct cac
cache->cache.identifier);
fscache_withdraw_cache(&cache->cache);
+ clear_bit(CACHEFILES_FSCACHE_INITED, &cache->flags);
}
if (cache->cache.fsdef)
diff --git a/fs/cachefiles/cf-daemon.c b/fs/cachefiles/cf-daemon.c
index 86cf23b..a1888ee 100644
--- a/fs/cachefiles/cf-daemon.c
+++ b/fs/cachefiles/cf-daemon.c
@@ -562,9 +562,11 @@ static int cachefiles_daemon_cull(struct
if (!S_ISDIR(dir->d_inode->i_mode))
goto notdir;
- cachefiles_begin_secure(cache, &secctx);
- ret = cachefiles_cull(cache, dir, args);
- cachefiles_end_secure(cache, &secctx);
+ ret = cachefiles_begin_secure(cache, &secctx);
+ if (ret == 0) {
+ ret = cachefiles_cull(cache, dir, args);
+ cachefiles_end_secure(cache, &secctx);
+ }
dput(dir);
_leave(" = %d", ret);
@@ -654,9 +656,11 @@ static int cachefiles_daemon_inuse(struc
if (!S_ISDIR(dir->d_inode->i_mode))
goto notdir;
- cachefiles_begin_secure(cache, &secctx);
- ret = cachefiles_check_in_use(cache, dir, args);
- cachefiles_end_secure(cache, &secctx);
+ ret = cachefiles_begin_secure(cache, &secctx);
+ if (ret == 0) {
+ ret = cachefiles_check_in_use(cache, dir, args);
+ cachefiles_end_secure(cache, &secctx);
+ }
dput(dir);
_leave(" = %d", ret);
diff --git a/fs/cachefiles/cf-interface.c b/fs/cachefiles/cf-interface.c
index e96e63a..6ce14f5 100644
--- a/fs/cachefiles/cf-interface.c
+++ b/fs/cachefiles/cf-interface.c
@@ -93,7 +93,9 @@ static struct fscache_object *cachefiles
auxdata->type = cookie->def->type;
/* look up the key, creating any missing bits */
- cachefiles_begin_secure(cache, &secctx);
+ ret = cachefiles_begin_secure(cache, &secctx);
+ if (ret < 0)
+ goto lookup_failed;
ret = cachefiles_walk_to_object(parent, object, key, auxdata);
cachefiles_end_secure(cache, &secctx);
if (ret < 0)
@@ -186,9 +188,10 @@ static void cachefiles_update_object(str
object = container_of(_object, struct cachefiles_object, fscache);
cache = container_of(object->fscache.cache, struct cachefiles_cache, cache);
- cachefiles_begin_secure(cache, &secctx);
- //cachefiles_tree_update_object(super, object);
- cachefiles_end_secure(cache, &secctx);
+ if (cachefiles_begin_secure(cache, &secctx) == 0) {
+ //cachefiles_tree_update_object(super, object);
+ cachefiles_end_secure(cache, &secctx);
+ }
}
/*
@@ -199,6 +202,7 @@ static void cachefiles_put_object(struct
struct cachefiles_secctx secctx;
struct cachefiles_object *object;
struct cachefiles_cache *cache;
+ int ret;
ASSERT(_object);
@@ -224,9 +228,11 @@ #endif
_object != cache->cache.fsdef
) {
_debug("- retire object %p", object);
- cachefiles_begin_secure(cache, &secctx);
- cachefiles_delete_object(cache, object);
- cachefiles_end_secure(cache, &secctx);
+ ret = cachefiles_begin_secure(cache, &secctx);
+ if (ret == 0) {
+ cachefiles_delete_object(cache, object);
+ cachefiles_end_secure(cache, &secctx);
+ }
}
/* close the filesystem stuff attached to the object */
@@ -269,9 +275,11 @@ static void cachefiles_sync_cache(struct
/* make sure all pages pinned by operations on behalf of the netfs are
* written to disc */
- cachefiles_begin_secure(cache, &secctx);
- ret = fsync_super(cache->mnt->mnt_sb);
- cachefiles_end_secure(cache, &secctx);
+ ret = cachefiles_begin_secure(cache, &secctx);
+ if (ret == 0) {
+ ret = fsync_super(cache->mnt->mnt_sb);
+ cachefiles_end_secure(cache, &secctx);
+ }
if (ret == -EIO)
cachefiles_io_error(cache,
@@ -308,11 +316,13 @@ static int cachefiles_set_i_size(struct
newattrs.ia_size = i_size;
newattrs.ia_valid = ATTR_SIZE;
- cachefiles_begin_secure(cache, &secctx);
- mutex_lock(&object->backer->d_inode->i_mutex);
- ret = notify_change(object->backer, &newattrs);
- mutex_unlock(&object->backer->d_inode->i_mutex);
- cachefiles_end_secure(cache, &secctx);
+ ret = cachefiles_begin_secure(cache, &secctx);
+ if (ret == 0) {
+ mutex_lock(&object->backer->d_inode->i_mutex);
+ ret = notify_change(object->backer, &newattrs);
+ mutex_unlock(&object->backer->d_inode->i_mutex);
+ cachefiles_end_secure(cache, &secctx);
+ }
if (ret == -EIO) {
cachefiles_io_error_obj(object, "Size set failed");
diff --git a/fs/cachefiles/cf-security.c b/fs/cachefiles/cf-security.c
index e070bb3..6d294da 100644
--- a/fs/cachefiles/cf-security.c
+++ b/fs/cachefiles/cf-security.c
@@ -105,3 +105,39 @@ error:
_leave(" = %d", ret);
return ret;
}
+
+/*
+ * deal with failure to change the file creation security ID
+ */
+int cachefiles_begin_secure_failed(struct cachefiles_cache *cache, int ret)
+{
+ kerror("Unable to enter secure region in process %d (error %d)",
+ current->pid, ret);
+
+ if (test_bit(CACHEFILES_FSCACHE_INITED, &cache->flags))
+ fscache_io_error(&cache->cache);
+ set_bit(CACHEFILES_DEAD, &cache->flags);
+ security_act_as_self();
+ return ret;
+}
+
+/*
+ * deal with failure to restore the file creation security ID
+ */
+void cachefiles_end_secure_failed(struct cachefiles_cache *cache,
+ const struct cachefiles_secctx *ctx,
+ int ret)
+{
+ printk(KERN_ERR "CacheFiles: ERROR:"
+ " Failed to restore file creation security ID %x on process %d"
+ " (error %d)\n",
+ ctx->fscreate_secid, current->pid, ret);
+ printk(KERN_ERR "CacheFiles: Killing process %d\n", current->pid);
+
+ if (test_bit(CACHEFILES_FSCACHE_INITED, &cache->flags))
+ fscache_io_error(&cache->cache);
+ set_bit(CACHEFILES_DEAD, &cache->flags);
+
+ /* this process cannot be allowed to continue */
+ force_sig(SIGKILL, current);
+}
diff --git a/fs/cachefiles/cf-security.h b/fs/cachefiles/cf-security.h
new file mode 100644
index 0000000..a1dd74c
--- /dev/null
+++ b/fs/cachefiles/cf-security.h
@@ -0,0 +1,134 @@
+/* LSM security context manipulation
+ *
+ * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+/*
+ * saved security context
+ */
+struct cachefiles_secctx {
+ uid_t fsuid; /* save for current->fsuid */
+ gid_t fsgid; /* save for current->fsgid */
+#ifdef CONFIG_SECURITY
+ u32 fscreate_secid; /* save for current fscreate security ID */
+#endif
+};
+
+#ifndef CONFIG_SECURITY
+#define cachefiles_get_security_ID(cache) (0)
+#define cachefiles_determine_cache_secid(cache, root) (0)
+#define cachefiles_set_fscreate_secid(cache) do {} while(0)
+
+/*
+ * attempt to enter the cachefiles security context
+ */
+static inline int cachefiles_begin_secure(struct cachefiles_cache *cache,
+ struct cachefiles_secctx *ctx)
+{
+ ctx->fsuid = current->fsuid;
+ ctx->fsgid = current->fsgid;
+ current->fsuid = 0;
+ current->fsgid = 0;
+ return 0;
+}
+
+#define cachefiles_begin_secure_nofs(cache, ctx) \
+ cachefiles_begin_secure(cache, ctx)
+
+/*
+ * attempt to leave the cachefiles security context
+ */
+static inline void cachefiles_end_secure(struct cachefiles_cache *cache,
+ const struct cachefiles_secctx *ctx)
+{
+ current->fsuid = ctx->fsuid;
+ current->fsgid = ctx->fsgid;
+}
+
+#else /* !CONFIG_SECURITY */
+
+extern int cachefiles_get_security_ID(struct cachefiles_cache *cache);
+extern int cachefiles_determine_cache_secid(struct cachefiles_cache *cache,
+ struct dentry *root);
+extern int cachefiles_begin_secure_failed(struct cachefiles_cache *cache,
+ int ret);
+extern void cachefiles_end_secure_failed(struct cachefiles_cache *cache,
+ const struct cachefiles_secctx *ctx,
+ int ret);
+
+/*
+ * attempt to set the file creation security ID
+ */
+static inline int cachefiles_set_fscreate_secid(struct cachefiles_cache *cache)
+{
+ int ret;
+
+ ret = security_set_fscreate_secid(cache->cache_secid, NULL);
+ if (unlikely(ret < 0))
+ return cachefiles_begin_secure_failed(cache, ret);
+ return 0;
+}
+
+/*
+ * enter the cachefiles security context without changing the file creation
+ * security ID
+ */
+static inline void cachefiles_begin_secure_nofs(struct cachefiles_cache *cache,
+ struct cachefiles_secctx *ctx)
+{
+ security_act_as_secid(cache->access_secid);
+ ctx->fscreate_secid = security_get_fscreate_secid();
+ ctx->fsuid = current->fsuid;
+ ctx->fsgid = current->fsgid;
+ current->fsuid = 0;
+ current->fsgid = 0;
+}
+
+/*
+ * attempt to enter the cachefiles security context
+ */
+static inline int cachefiles_begin_secure(struct cachefiles_cache *cache,
+ struct cachefiles_secctx *ctx)
+{
+ int ret;
+
+ security_act_as_secid(cache->access_secid);
+ ret = security_set_fscreate_secid(cache->cache_secid,
+ &ctx->fscreate_secid);
+ if (unlikely(ret < 0))
+ return cachefiles_begin_secure_failed(cache, ret);
+
+ ctx->fsuid = current->fsuid;
+ ctx->fsgid = current->fsgid;
+ current->fsuid = 0;
+ current->fsgid = 0;
+ return 0;
+}
+
+/*
+ * attempt to leave the cachefiles security context
+ */
+static inline void cachefiles_end_secure(struct cachefiles_cache *cache,
+ const struct cachefiles_secctx *ctx)
+{
+ int ret;
+
+ current->fsuid = ctx->fsuid;
+ current->fsgid = ctx->fsgid;
+
+ /* restoring the file creation security ID might fail, but there's
+ * nothing we can do about it if it does */
+ ret = security_set_fscreate_secid(ctx->fscreate_secid, NULL);
+ if (unlikely(ret < 0))
+ cachefiles_end_secure_failed(cache, ctx, ret);
+
+ security_act_as_self();
+}
+
+#endif /* !CONFIG_SECURITY */
diff --git a/fs/cachefiles/internal.h b/fs/cachefiles/internal.h
index 4715de5..16727fc 100644
--- a/fs/cachefiles/internal.h
+++ b/fs/cachefiles/internal.h
@@ -102,6 +102,7 @@ #define CACHEFILES_READY 0 /* T if cach
#define CACHEFILES_DEAD 1 /* T if cache dead */
#define CACHEFILES_CULLING 2 /* T if cull engaged */
#define CACHEFILES_STATE_CHANGED 3 /* T if state changed (poll trigger) */
+#define CACHEFILES_FSCACHE_INITED 4 /* T if fscache_init_cache() has been called */
char *rootdirname; /* name of cache root directory */
char *tag; /* cache binding tag */
};
@@ -189,65 +190,7 @@ extern int cachefiles_check_in_use(struc
/*
* cf-security.c
*/
-#ifdef CONFIG_SECURITY
-extern int cachefiles_get_security_ID(struct cachefiles_cache *cache);
-extern int cachefiles_determine_cache_secid(struct cachefiles_cache *cache,
- struct dentry *root);
-static inline
-void cachefiles_set_fscreate_secid(struct cachefiles_cache *cache)
-{
- security_set_fscreate_secid(cache->cache_secid);
-}
-#else
-#define cachefiles_get_security_ID(cache) (0)
-#define cachefiles_determine_cache_secid(cache, root) (0)
-#define cachefiles_set_fscreate_secid(cache) do {} while(0)
-#endif
-
-struct cachefiles_secctx {
- uid_t fsuid; /* save for current->fsuid */
- gid_t fsgid; /* save for current->fsgid */
-#ifdef CONFIG_SECURITY
- u32 fscreate_secid; /* save for current fscreate security ID */
-#endif
-};
-
-static inline void cachefiles_begin_secure_nofs(struct cachefiles_cache *cache,
- struct cachefiles_secctx *ctx)
-{
-#ifdef CONFIG_SECURITY
- security_act_as_secid(cache->access_secid);
- ctx->fscreate_secid = security_get_fscreate_secid();
-#endif
- ctx->fsuid = current->fsuid;
- ctx->fsgid = current->fsgid;
- current->fsuid = 0;
- current->fsgid = 0;
-}
-
-static inline void cachefiles_begin_secure(struct cachefiles_cache *cache,
- struct cachefiles_secctx *ctx)
-{
-#ifdef CONFIG_SECURITY
- security_act_as_secid(cache->access_secid);
- ctx->fscreate_secid = security_set_fscreate_secid(cache->cache_secid);
-#endif
- ctx->fsuid = current->fsuid;
- ctx->fsgid = current->fsgid;
- current->fsuid = 0;
- current->fsgid = 0;
-}
-
-static inline void cachefiles_end_secure(struct cachefiles_cache *cache,
- const struct cachefiles_secctx *ctx)
-{
- current->fsuid = ctx->fsuid;
- current->fsgid = ctx->fsgid;
-#ifdef CONFIG_SECURITY
- security_set_fscreate_secid(ctx->fscreate_secid);
- security_act_as_self();
-#endif
-}
+#include "cf-security.h"
/*
* cf-xattr.c
--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.
WARNING: multiple messages have this Message-ID (diff)
From: David Howells <dhowells@redhat.com>
To: James Morris <jmorris@namei.org>
Cc: David Howells <dhowells@redhat.com>,
Linus Torvalds <torvalds@osdl.org>, Andrew Morton <akpm@osdl.org>,
Stephen Smalley <sds@tycho.nsa.gov>,
trond.myklebust@fys.uio.no, selinux@tycho.nsa.gov,
linux-kernel@vger.kernel.org, aviro@redhat.com,
steved@redhat.com
Subject: Re: [PATCH 12/19] CacheFiles: Permit a process's create SID to be overridden
Date: Wed, 15 Nov 2006 13:50:44 +0000 [thread overview]
Message-ID: <24555.1163598644@redhat.com> (raw)
In-Reply-To: <XMMS.LNX.4.64.0611141618300.25022@d.namei>
James Morris <jmorris@namei.org> wrote:
> The ability to set this needs to be mediated via MAC policy.
Something like this, you mean?
David
---
security/selinux/hooks.c | 12 +++-
security/dummy.c | 2 -
include/linux/security.h | 9 ++-
fs/cachefiles/cf-bind.c | 3 +
fs/cachefiles/cf-daemon.c | 16 +++--
fs/cachefiles/cf-interface.c | 40 ++++++++-----
fs/cachefiles/cf-security.c | 36 +++++++++++
fs/cachefiles/cf-security.h | 134 ++++++++++++++++++++++++++++++++++++++++++
fs/cachefiles/internal.h | 61 +------------------
9 files changed, 225 insertions(+), 88 deletions(-)
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 3a52698..5bfae9b 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -4559,13 +4559,19 @@ static u32 selinux_get_fscreate_secid(vo
return tsec->create_sid;
}
-static u32 selinux_set_fscreate_secid(u32 secid)
+static int selinux_set_fscreate_secid(u32 secid, u32 *oldsecid)
{
struct task_security_struct *tsec = current->security;
- u32 oldsid = tsec->create_sid;
+ int error;
+
+ error = task_has_perm(current, current, PROCESS__SETFSCREATE);
+ if (error < 0)
+ return error;
+ if (oldsecid)
+ *oldsecid = tsec->create_sid;
tsec->create_sid = secid;
- return oldsid;
+ return 0;
}
static u32 selinux_act_as_secid(u32 secid)
diff --git a/security/dummy.c b/security/dummy.c
index 30096ec..471b369 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -937,7 +937,7 @@ static u32 dummy_get_fscreate_secid(void
return 0;
}
-static u32 dummy_set_fscreate_secid(u32 secid)
+static int dummy_set_fscreate_secid(u32 secid, u32 *oldsecid)
{
return 0;
}
diff --git a/include/linux/security.h b/include/linux/security.h
index 8cfeefc..7aa86a3 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -1160,6 +1160,7 @@ #ifdef CONFIG_SECURITY
* @set_fscreate_secid:
* Set the current FS security ID.
* @secid contains the security ID to set.
+ * @oldsecid points to where the old security ID will be placed (or NULL).
*
* @act_as_secid:
* Set the security ID as which to act, returning the security ID as which
@@ -1363,7 +1364,7 @@ struct security_operations {
int (*secid_to_secctx)(u32 secid, char **secdata, u32 *seclen);
void (*release_secctx)(char *secdata, u32 seclen);
u32 (*get_fscreate_secid)(void);
- u32 (*set_fscreate_secid)(u32 secid);
+ int (*set_fscreate_secid)(u32 secid, u32 *oldsecid);
u32 (*act_as_secid)(u32 secid);
u32 (*act_as_self)(void);
int (*cachefiles_get_secid)(u32 secid, u32 *modsecid);
@@ -2174,9 +2175,9 @@ static inline u32 security_get_fscreate_
return security_ops->get_fscreate_secid();
}
-static inline u32 security_set_fscreate_secid(u32 secid)
+static inline int security_set_fscreate_secid(u32 secid, u32 *oldsecid)
{
- return security_ops->set_fscreate_secid(secid);
+ return security_ops->set_fscreate_secid(secid, oldsecid);
}
static inline u32 security_act_as_secid(u32 secid)
@@ -2884,7 +2885,7 @@ static inline u32 security_get_fscreate_
return 0;
}
-static inline u32 security_set_fscreate_secid(u32 secid)
+static inline int security_set_fscreate_secid(u32 secid, u32 *oldsecid)
{
return 0;
}
diff --git a/fs/cachefiles/cf-bind.c b/fs/cachefiles/cf-bind.c
index 0c055a9..c8e68a4 100644
--- a/fs/cachefiles/cf-bind.c
+++ b/fs/cachefiles/cf-bind.c
@@ -226,6 +226,8 @@ static int cachefiles_daemon_add_cache(s
MAJOR(fsdef->dentry->d_sb->s_dev),
MINOR(fsdef->dentry->d_sb->s_dev));
+ set_bit(CACHEFILES_FSCACHE_INITED, &cache->flags);
+
ret = fscache_add_cache(&cache->cache, &fsdef->fscache, cache->tag);
if (ret < 0)
goto error_add_cache;
@@ -273,6 +275,7 @@ void cachefiles_daemon_unbind(struct cac
cache->cache.identifier);
fscache_withdraw_cache(&cache->cache);
+ clear_bit(CACHEFILES_FSCACHE_INITED, &cache->flags);
}
if (cache->cache.fsdef)
diff --git a/fs/cachefiles/cf-daemon.c b/fs/cachefiles/cf-daemon.c
index 86cf23b..a1888ee 100644
--- a/fs/cachefiles/cf-daemon.c
+++ b/fs/cachefiles/cf-daemon.c
@@ -562,9 +562,11 @@ static int cachefiles_daemon_cull(struct
if (!S_ISDIR(dir->d_inode->i_mode))
goto notdir;
- cachefiles_begin_secure(cache, &secctx);
- ret = cachefiles_cull(cache, dir, args);
- cachefiles_end_secure(cache, &secctx);
+ ret = cachefiles_begin_secure(cache, &secctx);
+ if (ret == 0) {
+ ret = cachefiles_cull(cache, dir, args);
+ cachefiles_end_secure(cache, &secctx);
+ }
dput(dir);
_leave(" = %d", ret);
@@ -654,9 +656,11 @@ static int cachefiles_daemon_inuse(struc
if (!S_ISDIR(dir->d_inode->i_mode))
goto notdir;
- cachefiles_begin_secure(cache, &secctx);
- ret = cachefiles_check_in_use(cache, dir, args);
- cachefiles_end_secure(cache, &secctx);
+ ret = cachefiles_begin_secure(cache, &secctx);
+ if (ret == 0) {
+ ret = cachefiles_check_in_use(cache, dir, args);
+ cachefiles_end_secure(cache, &secctx);
+ }
dput(dir);
_leave(" = %d", ret);
diff --git a/fs/cachefiles/cf-interface.c b/fs/cachefiles/cf-interface.c
index e96e63a..6ce14f5 100644
--- a/fs/cachefiles/cf-interface.c
+++ b/fs/cachefiles/cf-interface.c
@@ -93,7 +93,9 @@ static struct fscache_object *cachefiles
auxdata->type = cookie->def->type;
/* look up the key, creating any missing bits */
- cachefiles_begin_secure(cache, &secctx);
+ ret = cachefiles_begin_secure(cache, &secctx);
+ if (ret < 0)
+ goto lookup_failed;
ret = cachefiles_walk_to_object(parent, object, key, auxdata);
cachefiles_end_secure(cache, &secctx);
if (ret < 0)
@@ -186,9 +188,10 @@ static void cachefiles_update_object(str
object = container_of(_object, struct cachefiles_object, fscache);
cache = container_of(object->fscache.cache, struct cachefiles_cache, cache);
- cachefiles_begin_secure(cache, &secctx);
- //cachefiles_tree_update_object(super, object);
- cachefiles_end_secure(cache, &secctx);
+ if (cachefiles_begin_secure(cache, &secctx) == 0) {
+ //cachefiles_tree_update_object(super, object);
+ cachefiles_end_secure(cache, &secctx);
+ }
}
/*
@@ -199,6 +202,7 @@ static void cachefiles_put_object(struct
struct cachefiles_secctx secctx;
struct cachefiles_object *object;
struct cachefiles_cache *cache;
+ int ret;
ASSERT(_object);
@@ -224,9 +228,11 @@ #endif
_object != cache->cache.fsdef
) {
_debug("- retire object %p", object);
- cachefiles_begin_secure(cache, &secctx);
- cachefiles_delete_object(cache, object);
- cachefiles_end_secure(cache, &secctx);
+ ret = cachefiles_begin_secure(cache, &secctx);
+ if (ret == 0) {
+ cachefiles_delete_object(cache, object);
+ cachefiles_end_secure(cache, &secctx);
+ }
}
/* close the filesystem stuff attached to the object */
@@ -269,9 +275,11 @@ static void cachefiles_sync_cache(struct
/* make sure all pages pinned by operations on behalf of the netfs are
* written to disc */
- cachefiles_begin_secure(cache, &secctx);
- ret = fsync_super(cache->mnt->mnt_sb);
- cachefiles_end_secure(cache, &secctx);
+ ret = cachefiles_begin_secure(cache, &secctx);
+ if (ret == 0) {
+ ret = fsync_super(cache->mnt->mnt_sb);
+ cachefiles_end_secure(cache, &secctx);
+ }
if (ret == -EIO)
cachefiles_io_error(cache,
@@ -308,11 +316,13 @@ static int cachefiles_set_i_size(struct
newattrs.ia_size = i_size;
newattrs.ia_valid = ATTR_SIZE;
- cachefiles_begin_secure(cache, &secctx);
- mutex_lock(&object->backer->d_inode->i_mutex);
- ret = notify_change(object->backer, &newattrs);
- mutex_unlock(&object->backer->d_inode->i_mutex);
- cachefiles_end_secure(cache, &secctx);
+ ret = cachefiles_begin_secure(cache, &secctx);
+ if (ret == 0) {
+ mutex_lock(&object->backer->d_inode->i_mutex);
+ ret = notify_change(object->backer, &newattrs);
+ mutex_unlock(&object->backer->d_inode->i_mutex);
+ cachefiles_end_secure(cache, &secctx);
+ }
if (ret == -EIO) {
cachefiles_io_error_obj(object, "Size set failed");
diff --git a/fs/cachefiles/cf-security.c b/fs/cachefiles/cf-security.c
index e070bb3..6d294da 100644
--- a/fs/cachefiles/cf-security.c
+++ b/fs/cachefiles/cf-security.c
@@ -105,3 +105,39 @@ error:
_leave(" = %d", ret);
return ret;
}
+
+/*
+ * deal with failure to change the file creation security ID
+ */
+int cachefiles_begin_secure_failed(struct cachefiles_cache *cache, int ret)
+{
+ kerror("Unable to enter secure region in process %d (error %d)",
+ current->pid, ret);
+
+ if (test_bit(CACHEFILES_FSCACHE_INITED, &cache->flags))
+ fscache_io_error(&cache->cache);
+ set_bit(CACHEFILES_DEAD, &cache->flags);
+ security_act_as_self();
+ return ret;
+}
+
+/*
+ * deal with failure to restore the file creation security ID
+ */
+void cachefiles_end_secure_failed(struct cachefiles_cache *cache,
+ const struct cachefiles_secctx *ctx,
+ int ret)
+{
+ printk(KERN_ERR "CacheFiles: ERROR:"
+ " Failed to restore file creation security ID %x on process %d"
+ " (error %d)\n",
+ ctx->fscreate_secid, current->pid, ret);
+ printk(KERN_ERR "CacheFiles: Killing process %d\n", current->pid);
+
+ if (test_bit(CACHEFILES_FSCACHE_INITED, &cache->flags))
+ fscache_io_error(&cache->cache);
+ set_bit(CACHEFILES_DEAD, &cache->flags);
+
+ /* this process cannot be allowed to continue */
+ force_sig(SIGKILL, current);
+}
diff --git a/fs/cachefiles/cf-security.h b/fs/cachefiles/cf-security.h
new file mode 100644
index 0000000..a1dd74c
--- /dev/null
+++ b/fs/cachefiles/cf-security.h
@@ -0,0 +1,134 @@
+/* LSM security context manipulation
+ *
+ * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+/*
+ * saved security context
+ */
+struct cachefiles_secctx {
+ uid_t fsuid; /* save for current->fsuid */
+ gid_t fsgid; /* save for current->fsgid */
+#ifdef CONFIG_SECURITY
+ u32 fscreate_secid; /* save for current fscreate security ID */
+#endif
+};
+
+#ifndef CONFIG_SECURITY
+#define cachefiles_get_security_ID(cache) (0)
+#define cachefiles_determine_cache_secid(cache, root) (0)
+#define cachefiles_set_fscreate_secid(cache) do {} while(0)
+
+/*
+ * attempt to enter the cachefiles security context
+ */
+static inline int cachefiles_begin_secure(struct cachefiles_cache *cache,
+ struct cachefiles_secctx *ctx)
+{
+ ctx->fsuid = current->fsuid;
+ ctx->fsgid = current->fsgid;
+ current->fsuid = 0;
+ current->fsgid = 0;
+ return 0;
+}
+
+#define cachefiles_begin_secure_nofs(cache, ctx) \
+ cachefiles_begin_secure(cache, ctx)
+
+/*
+ * attempt to leave the cachefiles security context
+ */
+static inline void cachefiles_end_secure(struct cachefiles_cache *cache,
+ const struct cachefiles_secctx *ctx)
+{
+ current->fsuid = ctx->fsuid;
+ current->fsgid = ctx->fsgid;
+}
+
+#else /* !CONFIG_SECURITY */
+
+extern int cachefiles_get_security_ID(struct cachefiles_cache *cache);
+extern int cachefiles_determine_cache_secid(struct cachefiles_cache *cache,
+ struct dentry *root);
+extern int cachefiles_begin_secure_failed(struct cachefiles_cache *cache,
+ int ret);
+extern void cachefiles_end_secure_failed(struct cachefiles_cache *cache,
+ const struct cachefiles_secctx *ctx,
+ int ret);
+
+/*
+ * attempt to set the file creation security ID
+ */
+static inline int cachefiles_set_fscreate_secid(struct cachefiles_cache *cache)
+{
+ int ret;
+
+ ret = security_set_fscreate_secid(cache->cache_secid, NULL);
+ if (unlikely(ret < 0))
+ return cachefiles_begin_secure_failed(cache, ret);
+ return 0;
+}
+
+/*
+ * enter the cachefiles security context without changing the file creation
+ * security ID
+ */
+static inline void cachefiles_begin_secure_nofs(struct cachefiles_cache *cache,
+ struct cachefiles_secctx *ctx)
+{
+ security_act_as_secid(cache->access_secid);
+ ctx->fscreate_secid = security_get_fscreate_secid();
+ ctx->fsuid = current->fsuid;
+ ctx->fsgid = current->fsgid;
+ current->fsuid = 0;
+ current->fsgid = 0;
+}
+
+/*
+ * attempt to enter the cachefiles security context
+ */
+static inline int cachefiles_begin_secure(struct cachefiles_cache *cache,
+ struct cachefiles_secctx *ctx)
+{
+ int ret;
+
+ security_act_as_secid(cache->access_secid);
+ ret = security_set_fscreate_secid(cache->cache_secid,
+ &ctx->fscreate_secid);
+ if (unlikely(ret < 0))
+ return cachefiles_begin_secure_failed(cache, ret);
+
+ ctx->fsuid = current->fsuid;
+ ctx->fsgid = current->fsgid;
+ current->fsuid = 0;
+ current->fsgid = 0;
+ return 0;
+}
+
+/*
+ * attempt to leave the cachefiles security context
+ */
+static inline void cachefiles_end_secure(struct cachefiles_cache *cache,
+ const struct cachefiles_secctx *ctx)
+{
+ int ret;
+
+ current->fsuid = ctx->fsuid;
+ current->fsgid = ctx->fsgid;
+
+ /* restoring the file creation security ID might fail, but there's
+ * nothing we can do about it if it does */
+ ret = security_set_fscreate_secid(ctx->fscreate_secid, NULL);
+ if (unlikely(ret < 0))
+ cachefiles_end_secure_failed(cache, ctx, ret);
+
+ security_act_as_self();
+}
+
+#endif /* !CONFIG_SECURITY */
diff --git a/fs/cachefiles/internal.h b/fs/cachefiles/internal.h
index 4715de5..16727fc 100644
--- a/fs/cachefiles/internal.h
+++ b/fs/cachefiles/internal.h
@@ -102,6 +102,7 @@ #define CACHEFILES_READY 0 /* T if cach
#define CACHEFILES_DEAD 1 /* T if cache dead */
#define CACHEFILES_CULLING 2 /* T if cull engaged */
#define CACHEFILES_STATE_CHANGED 3 /* T if state changed (poll trigger) */
+#define CACHEFILES_FSCACHE_INITED 4 /* T if fscache_init_cache() has been called */
char *rootdirname; /* name of cache root directory */
char *tag; /* cache binding tag */
};
@@ -189,65 +190,7 @@ extern int cachefiles_check_in_use(struc
/*
* cf-security.c
*/
-#ifdef CONFIG_SECURITY
-extern int cachefiles_get_security_ID(struct cachefiles_cache *cache);
-extern int cachefiles_determine_cache_secid(struct cachefiles_cache *cache,
- struct dentry *root);
-static inline
-void cachefiles_set_fscreate_secid(struct cachefiles_cache *cache)
-{
- security_set_fscreate_secid(cache->cache_secid);
-}
-#else
-#define cachefiles_get_security_ID(cache) (0)
-#define cachefiles_determine_cache_secid(cache, root) (0)
-#define cachefiles_set_fscreate_secid(cache) do {} while(0)
-#endif
-
-struct cachefiles_secctx {
- uid_t fsuid; /* save for current->fsuid */
- gid_t fsgid; /* save for current->fsgid */
-#ifdef CONFIG_SECURITY
- u32 fscreate_secid; /* save for current fscreate security ID */
-#endif
-};
-
-static inline void cachefiles_begin_secure_nofs(struct cachefiles_cache *cache,
- struct cachefiles_secctx *ctx)
-{
-#ifdef CONFIG_SECURITY
- security_act_as_secid(cache->access_secid);
- ctx->fscreate_secid = security_get_fscreate_secid();
-#endif
- ctx->fsuid = current->fsuid;
- ctx->fsgid = current->fsgid;
- current->fsuid = 0;
- current->fsgid = 0;
-}
-
-static inline void cachefiles_begin_secure(struct cachefiles_cache *cache,
- struct cachefiles_secctx *ctx)
-{
-#ifdef CONFIG_SECURITY
- security_act_as_secid(cache->access_secid);
- ctx->fscreate_secid = security_set_fscreate_secid(cache->cache_secid);
-#endif
- ctx->fsuid = current->fsuid;
- ctx->fsgid = current->fsgid;
- current->fsuid = 0;
- current->fsgid = 0;
-}
-
-static inline void cachefiles_end_secure(struct cachefiles_cache *cache,
- const struct cachefiles_secctx *ctx)
-{
- current->fsuid = ctx->fsuid;
- current->fsgid = ctx->fsgid;
-#ifdef CONFIG_SECURITY
- security_set_fscreate_secid(ctx->fscreate_secid);
- security_act_as_self();
-#endif
-}
+#include "cf-security.h"
/*
* cf-xattr.c
next prev parent reply other threads:[~2006-11-15 13:50 UTC|newest]
Thread overview: 101+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-11-14 20:06 [PATCH 00/19] Permit filesystem local caching and NFS superblock sharing David Howells
2006-11-14 20:06 ` David Howells
2006-11-14 20:06 ` [PATCH 02/19] FS-Cache: Provide a filesystem-specific sync'able page bit David Howells
2006-11-14 20:06 ` David Howells
2006-11-14 20:06 ` [PATCH 03/19] FS-Cache: Release page->private after failed readahead David Howells
2006-11-14 20:06 ` David Howells
2006-11-14 20:06 ` [PATCH 04/19] FS-Cache: Make kAFS use FS-Cache David Howells
2006-11-14 20:06 ` David Howells
2006-11-14 20:06 ` [PATCH 05/19] NFS: Use local caching David Howells
2006-11-14 20:06 ` David Howells
2006-11-15 12:38 ` Steve Dickson
2006-11-15 15:09 ` Trond Myklebust
2006-11-15 16:00 ` David Howells
2006-11-15 16:00 ` David Howells
2006-11-15 16:52 ` Trond Myklebust
2006-11-15 17:07 ` David Howells
2006-11-15 17:07 ` David Howells
2006-11-15 17:53 ` Trond Myklebust
2006-11-14 20:06 ` [PATCH 06/19] FS-Cache: NFS: Only obtain cache cookies on file open, not on inode read David Howells
2006-11-14 20:06 ` David Howells
2006-11-15 11:23 ` Steve Dickson
2006-11-14 20:06 ` [PATCH 07/19] CacheFiles: Add missing copy_page export for ia64 David Howells
2006-11-14 20:06 ` David Howells
2006-11-14 20:06 ` [PATCH 08/19] CacheFiles: Add a function to write a single page of data to an inode David Howells
2006-11-14 20:06 ` David Howells
2006-11-14 20:06 ` [PATCH 09/19] CacheFiles: Permit the page lock state to be monitored David Howells
2006-11-14 20:06 ` David Howells
2006-11-14 20:06 ` [PATCH 10/19] CacheFiles: Export things for CacheFiles David Howells
2006-11-14 20:06 ` David Howells
2006-11-14 20:06 ` [PATCH 12/19] CacheFiles: Permit a process's create SID to be overridden David Howells
2006-11-14 20:06 ` David Howells
2006-11-14 21:19 ` James Morris
2006-11-14 21:19 ` James Morris
2006-11-15 12:26 ` David Howells
2006-11-15 12:26 ` David Howells
2006-11-15 16:19 ` James Morris
2006-11-15 16:19 ` James Morris
2006-11-15 16:23 ` David Howells
2006-11-15 16:23 ` David Howells
2006-11-15 17:52 ` Karl MacMillan
2006-11-15 17:52 ` Karl MacMillan
2006-11-15 18:21 ` David Howells
2006-11-15 18:21 ` David Howells
2006-11-15 19:09 ` David Howells
2006-11-15 19:09 ` David Howells
2006-11-15 19:11 ` David Howells
2006-11-15 19:11 ` David Howells
2006-11-20 18:49 ` Stephen Smalley
2006-11-20 18:49 ` Stephen Smalley
2006-11-15 13:50 ` David Howells [this message]
2006-11-15 13:50 ` David Howells
2006-11-15 16:22 ` James Morris
2006-11-15 16:22 ` James Morris
2006-11-15 17:54 ` Karl MacMillan
2006-11-15 17:54 ` Karl MacMillan
2006-11-20 18:41 ` Stephen Smalley
2006-11-20 18:41 ` Stephen Smalley
2006-11-20 19:56 ` Karl MacMillan
2006-11-20 19:56 ` Karl MacMillan
2006-11-20 22:29 ` James Morris
2006-11-20 22:29 ` James Morris
2006-11-14 20:06 ` [PATCH 13/19] CacheFiles: Add an act-as SID override in task_security_struct David Howells
2006-11-14 20:06 ` David Howells
2006-11-14 20:06 ` [PATCH 14/19] CacheFiles: Permit an inode's security ID to be obtained David Howells
2006-11-14 20:06 ` David Howells
2006-11-14 20:06 ` [PATCH 15/19] CacheFiles: Get the SID under which the CacheFiles module should operate David Howells
2006-11-14 20:06 ` David Howells
2006-11-14 20:06 ` [PATCH 16/19] CacheFiles: Deal with LSM when accessing the cache David Howells
2006-11-14 20:06 ` David Howells
2006-11-14 21:27 ` James Morris
2006-11-14 21:27 ` James Morris
2006-11-14 20:06 ` [PATCH 17/19] CacheFiles: Use the VFS wrappers for inode ops David Howells
2006-11-14 20:06 ` David Howells
2006-11-14 20:07 ` [PATCH 18/19] CacheFiles: Use VFS lookup services David Howells
2006-11-14 20:07 ` [PATCH 19/19] CacheFiles: Permit daemon to probe inuseness of a cache file David Howells
2006-11-14 20:07 ` David Howells
2006-11-15 15:52 ` Christoph Hellwig
2006-11-15 16:10 ` David Howells
2006-11-15 16:10 ` David Howells
2006-11-15 10:10 ` [PATCH 20/19] CacheFiles: Use secid not sid lest confusion arise with session IDs David Howells
2006-11-15 10:10 ` David Howells
2006-11-15 13:17 ` [PATCH 21/19] CacheFiles: Set the file creation security ID whilst binding the cache David Howells
2006-11-15 13:17 ` David Howells
2006-11-15 13:23 ` [PATCH 22/19] FS-Cache: NFS: Rename NFS_INO_CACHEABLE David Howells
2006-11-15 13:23 ` David Howells
2006-11-15 16:42 ` [PATCH 23/19] FS-Cache: NFS: Don't invoke FS-Cache from nfs_zap_caches() David Howells
2006-11-15 16:42 ` David Howells
2006-11-15 16:51 ` [PATCH 24/19] FS-Cache: NFS: Remove old support for R/W caching David Howells
2006-11-15 16:51 ` David Howells
2006-11-15 17:22 ` [PATCH 25/19] FS-Cache: NFS: Wait in releasepage() if FS-Cache is busy and __GFP_WAIT is set David Howells
2006-11-15 17:22 ` David Howells
2006-11-17 10:01 ` [PATCH 26/19] CacheFiles: Don't include linux/proc_fs.h David Howells
2006-11-17 10:01 ` David Howells
2006-11-23 13:10 ` [PATCH 27/19] FS-Cache: Apply the PG_checked -> PG_fs_misc conversion to Ext4 David Howells
2006-11-23 13:10 ` David Howells
2006-11-23 13:17 ` [PATCH 28/19] FS-Cache: NFS: Handle caching being disabled correctly David Howells
2006-11-23 13:17 ` David Howells
2006-11-23 20:13 ` [PATCH 29/19] CacheFiles: Remove old obsolete cull function David Howells
2006-11-23 20:13 ` David Howells
2006-11-29 16:47 ` [PATCH 30/19] CacheFiles: Fix the allocate_page() op David Howells
2006-11-29 16:47 ` David Howells
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=24555.1163598644@redhat.com \
--to=dhowells@redhat.com \
--cc=akpm@osdl.org \
--cc=aviro@redhat.com \
--cc=jmorris@namei.org \
--cc=linux-kernel@vger.kernel.org \
--cc=sds@tycho.nsa.gov \
--cc=selinux@tycho.nsa.gov \
--cc=steved@redhat.com \
--cc=torvalds@osdl.org \
--cc=trond.myklebust@fys.uio.no \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.