From: David Howells <dhowells@redhat.com>
To: viro@zeniv.linux.org.uk
Cc: dhowells@redhat.com, linux-fsdevel@vger.kernel.org,
linux-afs@lists.infradead.org, linux-kernel@vger.kernel.org
Subject: [PATCH 06/32] smack: Implement filesystem context security hooks [ver #8]
Date: Fri, 25 May 2018 01:06:02 +0100 [thread overview]
Message-ID: <152720676293.9073.18055792621625181589.stgit@warthog.procyon.org.uk> (raw)
In-Reply-To: <152720672288.9073.9868393448836301272.stgit@warthog.procyon.org.uk>
Implement filesystem context security hooks for the smack LSM.
Question: Should the ->fs_context_parse_source() hook be implemented to
check the labels on any source devices specified?
Signed-off-by: David Howells <dhowells@redhat.com>
cc: Casey Schaufler <casey@schaufler-ca.com>
cc: linux-security-module@vger.kernel.org
---
security/smack/smack_lsm.c | 309 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 309 insertions(+)
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 0b414836bebd..3c4dd21d511d 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -42,6 +42,7 @@
#include <linux/shm.h>
#include <linux/binfmts.h>
#include <linux/parser.h>
+#include <linux/fs_context.h>
#include "smack.h"
#define TRANS_TRUE "TRUE"
@@ -521,6 +522,307 @@ static int smack_syslog(int typefrom_file)
return rc;
}
+/*
+ * Mount context operations
+ */
+
+struct smack_fs_context {
+ union {
+ struct {
+ char *fsdefault;
+ char *fsfloor;
+ char *fshat;
+ char *fsroot;
+ char *fstransmute;
+ };
+ char *ptrs[5];
+
+ };
+ struct superblock_smack *sbsp;
+ struct inode_smack *isp;
+ bool transmute;
+};
+
+/**
+ * smack_fs_context_free - Free the security data from a filesystem context
+ * @fc: The filesystem context to be cleaned up.
+ */
+static void smack_fs_context_free(struct fs_context *fc)
+{
+ struct smack_fs_context *ctx = fc->security;
+ int i;
+
+ if (ctx) {
+ for (i = 0; i < ARRAY_SIZE(ctx->ptrs); i++)
+ kfree(ctx->ptrs[i]);
+ kfree(ctx->isp);
+ kfree(ctx->sbsp);
+ kfree(ctx);
+ fc->security = NULL;
+ }
+}
+
+/**
+ * smack_fs_context_alloc - Allocate security data for a filesystem context
+ * @fc: The filesystem context.
+ * @reference: Reference dentry (automount/reconfigure) or NULL
+ *
+ * Returns 0 on success or -ENOMEM on error.
+ */
+static int smack_fs_context_alloc(struct fs_context *fc,
+ struct dentry *reference)
+{
+ struct smack_fs_context *ctx;
+ struct superblock_smack *sbsp;
+ struct inode_smack *isp;
+ struct smack_known *skp;
+
+ ctx = kzalloc(sizeof(struct smack_fs_context), GFP_KERNEL);
+ if (!ctx)
+ goto nomem;
+ fc->security = ctx;
+
+ sbsp = kzalloc(sizeof(struct superblock_smack), GFP_KERNEL);
+ if (!sbsp)
+ goto nomem_free;
+ ctx->sbsp = sbsp;
+
+ isp = new_inode_smack(NULL);
+ if (!isp)
+ goto nomem_free;
+ ctx->isp = isp;
+
+ if (reference) {
+ if (reference->d_sb->s_security)
+ memcpy(sbsp, reference->d_sb->s_security, sizeof(*sbsp));
+ } else if (!smack_privileged(CAP_MAC_ADMIN)) {
+ /* Unprivileged mounts get root and default from the caller. */
+ skp = smk_of_current();
+ sbsp->smk_root = skp;
+ sbsp->smk_default = skp;
+ } else {
+ sbsp->smk_root = &smack_known_floor;
+ sbsp->smk_default = &smack_known_floor;
+ sbsp->smk_floor = &smack_known_floor;
+ sbsp->smk_hat = &smack_known_hat;
+ /* SMK_SB_INITIALIZED will be zero from kzalloc. */
+ }
+
+ return 0;
+
+nomem_free:
+ smack_fs_context_free(fc);
+nomem:
+ return -ENOMEM;
+}
+
+/**
+ * smack_fs_context_dup - Duplicate the security data on fs_context duplication
+ * @fc: The new filesystem context.
+ * @src_fc: The source filesystem context being duplicated.
+ *
+ * Returns 0 on success or -ENOMEM on error.
+ */
+static int smack_fs_context_dup(struct fs_context *fc,
+ struct fs_context *src_fc)
+{
+ struct smack_fs_context *dst, *src = src_fc->security;
+ int i;
+
+ dst = kzalloc(sizeof(struct smack_fs_context), GFP_KERNEL);
+ if (!dst)
+ goto nomem;
+ fc->security = dst;
+
+ dst->sbsp = kmemdup(src->sbsp, sizeof(struct superblock_smack),
+ GFP_KERNEL);
+ if (!dst->sbsp)
+ goto nomem_free;
+
+ for (i = 0; i < ARRAY_SIZE(dst->ptrs); i++) {
+ if (src->ptrs[i]) {
+ dst->ptrs[i] = kstrdup(src->ptrs[i], GFP_KERNEL);
+ if (!dst->ptrs[i])
+ goto nomem_free;
+ }
+ }
+
+ return 0;
+
+nomem_free:
+ smack_fs_context_free(fc);
+nomem:
+ return -ENOMEM;
+}
+
+/**
+ * smack_fs_context_parse_option - Parse a single mount option
+ * @fc: The new filesystem context being constructed.
+ * @opt: The option text buffer.
+ * @len: The length of the text.
+ *
+ * Returns 0 on success or -ENOMEM on error.
+ */
+static int smack_fs_context_parse_option(struct fs_context *fc, char *p, size_t len)
+{
+ struct smack_fs_context *ctx = fc->security;
+ substring_t args[MAX_OPT_ARGS];
+ int rc = -ENOMEM;
+ int token;
+
+ /* Unprivileged mounts don't get to specify Smack values. */
+ if (!smack_privileged(CAP_MAC_ADMIN))
+ return -EPERM;
+
+ token = match_token(p, smk_mount_tokens, args);
+ switch (token) {
+ case Opt_fsdefault:
+ if (ctx->fsdefault)
+ goto error_dup;
+ ctx->fsdefault = match_strdup(&args[0]);
+ if (!ctx->fsdefault)
+ goto error;
+ break;
+ case Opt_fsfloor:
+ if (ctx->fsfloor)
+ goto error_dup;
+ ctx->fsfloor = match_strdup(&args[0]);
+ if (!ctx->fsfloor)
+ goto error;
+ break;
+ case Opt_fshat:
+ if (ctx->fshat)
+ goto error_dup;
+ ctx->fshat = match_strdup(&args[0]);
+ if (!ctx->fshat)
+ goto error;
+ break;
+ case Opt_fsroot:
+ if (ctx->fsroot)
+ goto error_dup;
+ ctx->fsroot = match_strdup(&args[0]);
+ if (!ctx->fsroot)
+ goto error;
+ break;
+ case Opt_fstransmute:
+ if (ctx->fstransmute)
+ goto error_dup;
+ ctx->fstransmute = match_strdup(&args[0]);
+ if (!ctx->fstransmute)
+ goto error;
+ break;
+ default:
+ pr_warn("Smack: unknown mount option\n");
+ goto error_inval;
+ }
+
+ return 0;
+
+error_dup:
+ pr_warn("Smack: duplicate mount option\n");
+error_inval:
+ rc = -EINVAL;
+error:
+ return rc;
+}
+
+/**
+ * smack_fs_context_validate - Validate the filesystem context security data
+ * @fc: The filesystem context.
+ *
+ * Returns 0 on success or -ENOMEM on error.
+ */
+static int smack_fs_context_validate(struct fs_context *fc)
+{
+ struct smack_fs_context *ctx = fc->security;
+ struct superblock_smack *sbsp = ctx->sbsp;
+ struct inode_smack *isp = ctx->isp;
+ struct smack_known *skp;
+
+ if (ctx->fsdefault) {
+ skp = smk_import_entry(ctx->fsdefault, 0);
+ if (IS_ERR(skp))
+ return PTR_ERR(skp);
+ sbsp->smk_default = skp;
+ }
+
+ if (ctx->fsfloor) {
+ skp = smk_import_entry(ctx->fsfloor, 0);
+ if (IS_ERR(skp))
+ return PTR_ERR(skp);
+ sbsp->smk_floor = skp;
+ }
+
+ if (ctx->fshat) {
+ skp = smk_import_entry(ctx->fshat, 0);
+ if (IS_ERR(skp))
+ return PTR_ERR(skp);
+ sbsp->smk_hat = skp;
+ }
+
+ if (ctx->fsroot || ctx->fstransmute) {
+ skp = smk_import_entry(ctx->fstransmute ?: ctx->fsroot, 0);
+ if (IS_ERR(skp))
+ return PTR_ERR(skp);
+ sbsp->smk_root = skp;
+ ctx->transmute = !!ctx->fstransmute;
+ }
+
+ isp->smk_inode = sbsp->smk_root;
+ return 0;
+}
+
+/**
+ * smack_sb_get_tree - Assign the context to a newly created superblock
+ * @fc: The new filesystem context.
+ *
+ * Returns 0 on success or -ENOMEM on error.
+ */
+static int smack_sb_get_tree(struct fs_context *fc)
+{
+ struct smack_fs_context *ctx = fc->security;
+ struct superblock_smack *sbsp = ctx->sbsp;
+ struct dentry *root = fc->root;
+ struct inode *inode = d_backing_inode(root);
+ struct super_block *sb = root->d_sb;
+ struct inode_smack *isp;
+ bool transmute = ctx->transmute;
+
+ if (sb->s_security)
+ return 0;
+
+ if (!smack_privileged(CAP_MAC_ADMIN)) {
+ /*
+ * For a handful of fs types with no user-controlled
+ * backing store it's okay to trust security labels
+ * in the filesystem. The rest are untrusted.
+ */
+ if (fc->user_ns != &init_user_ns &&
+ sb->s_magic != SYSFS_MAGIC && sb->s_magic != TMPFS_MAGIC &&
+ sb->s_magic != RAMFS_MAGIC) {
+ transmute = true;
+ sbsp->smk_flags |= SMK_SB_UNTRUSTED;
+ }
+ }
+
+ sbsp->smk_flags |= SMK_SB_INITIALIZED;
+ sb->s_security = sbsp;
+ ctx->sbsp = NULL;
+
+ /* Initialize the root inode. */
+ isp = inode->i_security;
+ if (isp == NULL) {
+ isp = ctx->isp;
+ ctx->isp = NULL;
+ inode->i_security = isp;
+ } else
+ isp->smk_inode = sbsp->smk_root;
+
+ if (transmute)
+ isp->smk_flags |= SMK_INODE_TRANSMUTE;
+
+ return 0;
+}
/*
* Superblock Hooks.
@@ -4628,6 +4930,13 @@ static struct security_hook_list smack_hooks[] __lsm_ro_after_init = {
LSM_HOOK_INIT(ptrace_traceme, smack_ptrace_traceme),
LSM_HOOK_INIT(syslog, smack_syslog),
+ LSM_HOOK_INIT(fs_context_alloc, smack_fs_context_alloc),
+ LSM_HOOK_INIT(fs_context_dup, smack_fs_context_dup),
+ LSM_HOOK_INIT(fs_context_free, smack_fs_context_free),
+ LSM_HOOK_INIT(fs_context_parse_option, smack_fs_context_parse_option),
+ LSM_HOOK_INIT(fs_context_validate, smack_fs_context_validate),
+ LSM_HOOK_INIT(sb_get_tree, smack_sb_get_tree),
+
LSM_HOOK_INIT(sb_alloc_security, smack_sb_alloc_security),
LSM_HOOK_INIT(sb_free_security, smack_sb_free_security),
LSM_HOOK_INIT(sb_copy_data, smack_sb_copy_data),
next prev parent reply other threads:[~2018-05-25 0:13 UTC|newest]
Thread overview: 87+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-05-25 0:05 [PATCH 00/32] VFS: Introduce filesystem context [ver #8] David Howells
2018-05-25 0:05 ` [PATCH 01/32] VFS: Suppress MS_* flag defs within the kernel unless explicitly enabled " David Howells
2018-05-25 0:05 ` [PATCH 02/32] vfs: Provide documentation for new mount API " David Howells
2018-05-25 0:05 ` [PATCH 03/32] VFS: Introduce the basic header for the new mount API's filesystem context " David Howells
2018-05-31 23:11 ` Al Viro
2018-05-31 23:13 ` Al Viro
2018-05-25 0:05 ` [PATCH 04/32] VFS: Add LSM hooks for the new mount API " David Howells
2018-05-25 0:05 ` [PATCH 05/32] selinux: Implement the new mount API LSM hooks " David Howells
2018-05-25 0:06 ` David Howells [this message]
2018-05-25 0:06 ` [PATCH 07/32] apparmor: Implement security hooks for the new mount API " David Howells
2018-05-25 0:06 ` [PATCH 08/32] tomoyo: " David Howells
2018-05-25 0:06 ` [PATCH 09/32] VFS: Require specification of size of mount data for internal mounts " David Howells
2018-05-25 0:06 ` [PATCH 10/32] VFS: Implement a filesystem superblock creation/configuration context " David Howells
2018-06-07 19:50 ` Miklos Szeredi
2018-07-03 18:33 ` Eric Biggers
2018-07-03 21:53 ` David Howells
2018-07-03 21:58 ` Al Viro
2018-07-03 22:06 ` David Howells
2018-05-25 0:06 ` [PATCH 11/32] VFS: Remove unused code after filesystem context changes " David Howells
2018-05-25 0:06 ` [PATCH 12/32] procfs: Move proc_fill_super() to fs/proc/root.c " David Howells
2018-05-25 0:06 ` [PATCH 13/32] proc: Add fs_context support to procfs " David Howells
2018-05-25 0:06 ` [PATCH 14/32] ipc: Convert mqueue fs to fs_context " David Howells
2018-05-25 0:07 ` [PATCH 15/32] cpuset: Use " David Howells
2018-05-25 0:07 ` [PATCH 16/32] kernfs, sysfs, cgroup, intel_rdt: Support " David Howells
2018-06-21 18:47 ` [16/32] " Andrei Vagin
2018-06-22 12:52 ` David Howells
2018-06-22 15:30 ` Andrei Vagin
2018-06-22 16:57 ` Andrei Vagin
2018-06-23 23:34 ` David Howells
2018-05-25 0:07 ` [PATCH 17/32] hugetlbfs: Convert to " David Howells
2018-05-25 0:07 ` [PATCH 18/32] VFS: Remove kern_mount_data() " David Howells
2018-05-25 0:07 ` [PATCH 19/32] VFS: Implement fsopen() to prepare for a mount " David Howells
2018-05-31 21:25 ` Al Viro
2018-05-25 0:07 ` [PATCH 20/32] vfs: Make close() unmount the attached mount if so flagged " David Howells
2018-05-31 19:19 ` Al Viro
2018-05-31 19:26 ` Al Viro
2018-06-01 1:52 ` Al Viro
2018-06-01 3:18 ` Al Viro
2018-06-01 5:16 ` Al Viro
2018-05-25 0:07 ` [PATCH 21/32] VFS: Implement fsmount() to effect a pre-configured mount " David Howells
2018-06-04 15:05 ` Arnd Bergmann
2018-06-04 15:24 ` David Howells
2018-05-25 0:07 ` [PATCH 22/32] vfs: Provide an fspick() system call " David Howells
2018-05-25 0:07 ` [PATCH 23/32] VFS: Implement logging through fs_context " David Howells
2018-05-25 1:48 ` Joe Perches
2018-05-25 0:07 ` [PATCH 24/32] vfs: Add some logging to the core users of the fs_context log " David Howells
2018-05-25 0:08 ` [PATCH 25/32] afs: Add fs_context support " David Howells
2018-05-25 0:08 ` [PATCH 26/32] afs: Use fs_context to pass parameters over automount " David Howells
2018-06-07 1:58 ` Goldwyn Rodrigues
2018-06-07 20:45 ` David Howells
2018-05-25 0:08 ` [PATCH 27/32] vfs: Use a 'struct fd_cookie *' type for light fd handling " David Howells
2018-05-25 0:08 ` [PATCH 28/32] vfs: Store the fd_cookie in nameidata, not the dfd int " David Howells
2018-05-25 0:08 ` [PATCH 29/32] vfs: Don't mix FMODE_* flags with O_* flags " David Howells
2018-05-25 0:08 ` [PATCH 30/32] vfs: Allow cloning of a mount tree with open(O_PATH|O_CLONE_MOUNT) " David Howells
2018-06-01 6:26 ` Christoph Hellwig
2018-06-01 6:39 ` Al Viro
2018-06-01 8:27 ` David Howells
2018-06-02 3:09 ` Al Viro
2018-06-02 3:42 ` Al Viro
2018-06-02 4:04 ` Al Viro
2018-06-02 15:45 ` David Howells
2018-06-02 17:49 ` Al Viro
2018-06-03 0:55 ` [PATCH][RFC] open_tree(2) (was Re: [PATCH 30/32] vfs: Allow cloning of a mount tree with open(O_PATH|O_CLONE_MOUNT) [ver #8]) Al Viro
2018-06-04 10:34 ` Miklos Szeredi
2018-06-04 15:52 ` Al Viro
2018-06-04 15:59 ` Al Viro
2018-06-04 19:27 ` Miklos Szeredi
2018-06-04 15:27 ` David Howells
2018-06-04 17:16 ` Matthew Wilcox
2018-06-04 17:35 ` Al Viro
2018-06-04 19:38 ` Miklos Szeredi
2018-06-01 8:02 ` [PATCH 30/32] vfs: Allow cloning of a mount tree with open(O_PATH|O_CLONE_MOUNT) [ver #8] Amir Goldstein
2018-06-01 8:42 ` David Howells
2018-05-25 0:08 ` [PATCH 31/32] [RFC] fs: Add a move_mount() system call " David Howells
2018-05-31 21:20 ` Al Viro
2018-05-25 0:08 ` [PATCH 32/32] [RFC] fsinfo: Add a system call to allow querying of filesystem information " David Howells
2018-06-04 13:10 ` Arnd Bergmann
2018-06-04 15:01 ` David Howells
2018-06-04 16:00 ` Arnd Bergmann
2018-06-04 19:03 ` David Howells
2018-06-04 20:45 ` Arnd Bergmann
2018-05-31 20:56 ` Test program for move_mount() David Howells
2018-05-31 20:57 ` fsinfo test program David Howells
2018-06-15 4:18 ` [PATCH 00/32] VFS: Introduce filesystem context [ver #8] Eric W. Biederman
2018-06-18 20:30 ` David Howells
2018-06-18 21:33 ` Eric W. Biederman
2018-06-18 23:33 ` Theodore Y. Ts'o
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=152720676293.9073.18055792621625181589.stgit@warthog.procyon.org.uk \
--to=dhowells@redhat.com \
--cc=linux-afs@lists.infradead.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@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).