From: David Howells <dhowells@redhat.com>
To: viro@zeniv.linux.org.uk
Cc: Paul Moore <paul@paul-moore.com>,
Stephen Smalley <sds@tycho.nsa.gov>,
selinux@tycho.nsa.gov, linux-security-module@vger.kernel.org,
torvalds@linux-foundation.org, dhowells@redhat.com,
linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH 09/38] selinux: Implement the new mount API LSM hooks [ver #10]
Date: Fri, 27 Jul 2018 18:32:23 +0100 [thread overview]
Message-ID: <153271274305.9458.13602378603425233117.stgit@warthog.procyon.org.uk> (raw)
In-Reply-To: <153271267980.9458.7640156373438016898.stgit@warthog.procyon.org.uk>
Implement the new mount API LSM hooks for SELinux. At some point the old
hooks will need to be removed.
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: Paul Moore <paul@paul-moore.com>
cc: Stephen Smalley <sds@tycho.nsa.gov>
cc: selinux@tycho.nsa.gov
cc: linux-security-module@vger.kernel.org
---
security/selinux/hooks.c | 290 ++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 290 insertions(+)
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index ef0428311a5c..9774d1f0e99f 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -48,6 +48,8 @@
#include <linux/fdtable.h>
#include <linux/namei.h>
#include <linux/mount.h>
+#include <linux/fs_context.h>
+#include <linux/fs_parser.h>
#include <linux/netfilter_ipv4.h>
#include <linux/netfilter_ipv6.h>
#include <linux/tty.h>
@@ -446,6 +448,7 @@ enum {
Opt_rootcontext = 4,
Opt_labelsupport = 5,
Opt_nextmntopt = 6,
+ nr__selinux_params
};
#define NUM_SEL_MNT_OPTS (Opt_nextmntopt - 1)
@@ -2974,6 +2977,285 @@ static int selinux_umount(struct vfsmount *mnt, int flags)
FILESYSTEM__UNMOUNT, NULL);
}
+/* fsopen mount context operations */
+
+static int selinux_fs_context_alloc(struct fs_context *fc,
+ struct dentry *reference)
+{
+ struct security_mnt_opts *opts;
+
+ opts = kzalloc(sizeof(*opts), GFP_KERNEL);
+ if (!opts)
+ return -ENOMEM;
+
+ fc->security = opts;
+ return 0;
+}
+
+static int selinux_fs_context_dup(struct fs_context *fc,
+ struct fs_context *src_fc)
+{
+ const struct security_mnt_opts *src = src_fc->security;
+ struct security_mnt_opts *opts;
+ int i, n;
+
+ opts = kzalloc(sizeof(*opts), GFP_KERNEL);
+ if (!opts)
+ return -ENOMEM;
+ fc->security = opts;
+
+ if (!src || !src->num_mnt_opts)
+ return 0;
+ n = opts->num_mnt_opts = src->num_mnt_opts;
+
+ if (src->mnt_opts) {
+ opts->mnt_opts = kcalloc(n, sizeof(char *), GFP_KERNEL);
+ if (!opts->mnt_opts)
+ return -ENOMEM;
+
+ for (i = 0; i < n; i++) {
+ if (src->mnt_opts[i]) {
+ opts->mnt_opts[i] = kstrdup(src->mnt_opts[i],
+ GFP_KERNEL);
+ if (!opts->mnt_opts[i])
+ return -ENOMEM;
+ }
+ }
+ }
+
+ if (src->mnt_opts_flags) {
+ opts->mnt_opts_flags = kmemdup(src->mnt_opts_flags,
+ n * sizeof(int), GFP_KERNEL);
+ if (!opts->mnt_opts_flags)
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static void selinux_fs_context_free(struct fs_context *fc)
+{
+ struct security_mnt_opts *opts = fc->security;
+
+ if (opts) {
+ security_free_mnt_opts(opts);
+ fc->security = NULL;
+ }
+}
+
+static const struct fs_parameter_spec selinux_param_specs[nr__selinux_params] = {
+ [Opt_context] = { fs_param_is_string },
+ [Opt_defcontext] = { fs_param_is_string },
+ [Opt_fscontext] = { fs_param_is_string },
+ [Opt_labelsupport] = { fs_param_takes_no_value },
+ [Opt_rootcontext] = { fs_param_is_string },
+};
+
+static const struct constant_table selinux_param_keys[] = {
+ { CONTEXT_STR, Opt_context },
+ { DEFCONTEXT_STR, Opt_defcontext },
+ { FSCONTEXT_STR, Opt_fscontext },
+ { ROOTCONTEXT_STR, Opt_rootcontext },
+ { LABELSUPP_STR, Opt_labelsupport },
+};
+
+static const struct fs_parameter_description selinux_fs_parameters = {
+ .name = "SELinux",
+ .nr_params = nr__selinux_params,
+ .nr_keys = ARRAY_SIZE(selinux_param_keys),
+ .keys = selinux_param_keys,
+ .specs = selinux_param_specs,
+ .ignore_unknown = true,
+};
+
+static int selinux_fs_context_parse_param(struct fs_context *fc,
+ struct fs_parameter *param)
+{
+ struct security_mnt_opts *opts = fc->security;
+ struct fs_parse_result result;
+ unsigned int have;
+ char **oo;
+ int ret, ctx, i, *of;
+
+ ret = fs_parse(fc, &selinux_fs_parameters, param, &result);
+ if (ret <= 0)
+ return ret; /* Note: 0 indicates no match */
+
+ have = 0;
+ for (i = 0; i < opts->num_mnt_opts; i++)
+ have |= 1 << opts->mnt_opts_flags[i];
+ if (have & (1 << result.key))
+ return -EINVAL;
+
+ switch (result.key) {
+ case Opt_context:
+ if (have & (1 << Opt_defcontext))
+ goto incompatible;
+ ctx = CONTEXT_MNT;
+ goto copy_context_string;
+
+ case Opt_fscontext:
+ ctx = FSCONTEXT_MNT;
+ goto copy_context_string;
+
+ case Opt_rootcontext:
+ ctx = ROOTCONTEXT_MNT;
+ goto copy_context_string;
+
+ case Opt_defcontext:
+ if (have & (1 << Opt_context))
+ goto incompatible;
+ ctx = DEFCONTEXT_MNT;
+ goto copy_context_string;
+
+ case Opt_labelsupport:
+ return 1;
+
+ default:
+ return -EINVAL;
+ }
+
+copy_context_string:
+ if (opts->num_mnt_opts > 3)
+ return -EINVAL;
+
+ of = krealloc(opts->mnt_opts_flags,
+ (opts->num_mnt_opts + 1) * sizeof(int), GFP_KERNEL);
+ if (!of)
+ return -ENOMEM;
+ of[opts->num_mnt_opts] = 0;
+ opts->mnt_opts_flags = of;
+
+ oo = krealloc(opts->mnt_opts,
+ (opts->num_mnt_opts + 1) * sizeof(char *), GFP_KERNEL);
+ if (!oo)
+ return -ENOMEM;
+ oo[opts->num_mnt_opts] = NULL;
+ opts->mnt_opts = oo;
+
+ opts->mnt_opts[opts->num_mnt_opts] = param->string;
+ opts->mnt_opts_flags[opts->num_mnt_opts] = ctx;
+ opts->num_mnt_opts++;
+ param->string = NULL;
+ return 1;
+
+incompatible:
+ return -EINVAL;
+}
+
+/*
+ * Validate the security parameters supplied for a reconfiguration/remount
+ * event.
+ */
+static int selinux_validate_for_sb_reconfigure(struct fs_context *fc)
+{
+ struct super_block *sb = fc->root->d_sb;
+ struct superblock_security_struct *sbsec = sb->s_security;
+ struct security_mnt_opts *opts = fc->security;
+ int rc, i, *flags;
+ char **mount_options;
+
+ if (!(sbsec->flags & SE_SBINITIALIZED))
+ return 0;
+
+ mount_options = opts->mnt_opts;
+ flags = opts->mnt_opts_flags;
+
+ for (i = 0; i < opts->num_mnt_opts; i++) {
+ u32 sid;
+
+ if (flags[i] == SBLABEL_MNT)
+ continue;
+
+ rc = security_context_str_to_sid(&selinux_state, mount_options[i],
+ &sid, GFP_KERNEL);
+ if (rc) {
+ pr_warn("SELinux: security_context_str_to_sid"
+ "(%s) failed for (dev %s, type %s) errno=%d\n",
+ mount_options[i], sb->s_id, sb->s_type->name, rc);
+ goto inval;
+ }
+
+ switch (flags[i]) {
+ case FSCONTEXT_MNT:
+ if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid, sid))
+ goto bad_option;
+ break;
+ case CONTEXT_MNT:
+ if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid, sid))
+ goto bad_option;
+ break;
+ case ROOTCONTEXT_MNT: {
+ struct inode_security_struct *root_isec;
+ root_isec = backing_inode_security(sb->s_root);
+
+ if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid, sid))
+ goto bad_option;
+ break;
+ }
+ case DEFCONTEXT_MNT:
+ if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid, sid))
+ goto bad_option;
+ break;
+ default:
+ goto inval;
+ }
+ }
+
+ rc = 0;
+out:
+ return rc;
+
+bad_option:
+ pr_warn("SELinux: unable to change security options "
+ "during remount (dev %s, type=%s)\n",
+ sb->s_id, sb->s_type->name);
+inval:
+ rc = -EINVAL;
+ goto out;
+}
+
+/*
+ * Validate the security context assembled from the option data supplied to
+ * mount.
+ */
+static int selinux_fs_context_validate(struct fs_context *fc)
+{
+ if (fc->purpose == FS_CONTEXT_FOR_RECONFIGURE)
+ return selinux_validate_for_sb_reconfigure(fc);
+ return 0;
+}
+
+/*
+ * Set the security context on a superblock.
+ */
+static int selinux_sb_get_tree(struct fs_context *fc)
+{
+ const struct cred *cred = current_cred();
+ struct common_audit_data ad;
+ int rc;
+
+ rc = selinux_set_mnt_opts(fc->root->d_sb, fc->security, 0, NULL);
+ if (rc)
+ return rc;
+
+ /* Allow all mounts performed by the kernel */
+ if (fc->purpose == FS_CONTEXT_FOR_KERNEL_MOUNT)
+ return 0;
+
+ ad.type = LSM_AUDIT_DATA_DENTRY;
+ ad.u.dentry = fc->root;
+ return superblock_has_perm(cred, fc->root->d_sb, FILESYSTEM__MOUNT, &ad);
+}
+
+static int selinux_sb_mountpoint(struct fs_context *fc, struct path *mountpoint,
+ unsigned int mnt_flags)
+{
+ const struct cred *cred = current_cred();
+
+ return path_has_perm(cred, mountpoint, FILE__MOUNTON);
+}
+
/* inode security operations */
static int selinux_inode_alloc_security(struct inode *inode)
@@ -6906,6 +7188,14 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
LSM_HOOK_INIT(bprm_committing_creds, selinux_bprm_committing_creds),
LSM_HOOK_INIT(bprm_committed_creds, selinux_bprm_committed_creds),
+ LSM_HOOK_INIT(fs_context_alloc, selinux_fs_context_alloc),
+ LSM_HOOK_INIT(fs_context_dup, selinux_fs_context_dup),
+ LSM_HOOK_INIT(fs_context_free, selinux_fs_context_free),
+ LSM_HOOK_INIT(fs_context_parse_param, selinux_fs_context_parse_param),
+ LSM_HOOK_INIT(fs_context_validate, selinux_fs_context_validate),
+ LSM_HOOK_INIT(sb_get_tree, selinux_sb_get_tree),
+ LSM_HOOK_INIT(sb_mountpoint, selinux_sb_mountpoint),
+
LSM_HOOK_INIT(sb_alloc_security, selinux_sb_alloc_security),
LSM_HOOK_INIT(sb_free_security, selinux_sb_free_security),
LSM_HOOK_INIT(sb_copy_data, selinux_sb_copy_data),
next prev parent reply other threads:[~2018-07-27 18:55 UTC|newest]
Thread overview: 98+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-07-27 17:31 [PATCH 00/38] VFS: Introduce filesystem context [ver #10] David Howells
2018-07-27 17:31 ` [PATCH 01/38] vfs: syscall: Add open_tree(2) to reference or clone a mount " David Howells
2018-07-27 17:31 ` [PATCH 02/38] vfs: syscall: Add move_mount(2) to move mounts around " David Howells
2018-07-27 17:31 ` [PATCH 03/38] teach move_mount(2) to work with OPEN_TREE_CLONE " David Howells
2018-07-27 17:31 ` [PATCH 04/38] vfs: Suppress MS_* flag defs within the kernel unless explicitly enabled " David Howells
2018-07-27 17:31 ` [PATCH 05/38] vfs: Introduce the basic header for the new mount API's filesystem context " David Howells
2018-07-27 17:32 ` [PATCH 06/38] vfs: Introduce logging functions " David Howells
2018-07-27 17:32 ` [PATCH 07/38] vfs: Add configuration parser helpers " David Howells
2018-07-27 17:32 ` [PATCH 08/38] vfs: Add LSM hooks for the new mount API " David Howells
2018-07-27 17:32 ` David Howells [this message]
2018-07-27 17:32 ` [PATCH 10/38] smack: Implement filesystem context security hooks " David Howells
2018-07-27 17:32 ` [PATCH 11/38] apparmor: Implement security hooks for the new mount API " David Howells
2018-07-27 17:32 ` [PATCH 12/38] vfs: Pass key and value into LSM and FS and provide a helper parser " David Howells
2018-07-27 17:32 ` [PATCH 13/38] tomoyo: Implement security hooks for the new mount API " David Howells
2018-07-28 2:29 ` Tetsuo Handa
2018-07-30 10:49 ` David Howells
2018-07-27 17:32 ` [PATCH 14/38] vfs: Separate changing mount flags full remount " David Howells
2018-07-27 17:33 ` [PATCH 15/38] vfs: Implement a filesystem superblock creation/configuration context " David Howells
2018-07-27 17:33 ` [PATCH 16/38] vfs: Remove unused code after filesystem context changes " David Howells
2018-07-27 17:33 ` [PATCH 17/38] procfs: Move proc_fill_super() to fs/proc/root.c " David Howells
2018-07-27 17:33 ` [PATCH 18/38] proc: Add fs_context support to procfs " David Howells
2018-07-27 17:33 ` [PATCH 19/38] ipc: Convert mqueue fs to fs_context " David Howells
2018-07-27 17:33 ` [PATCH 20/38] cpuset: Use " David Howells
2018-07-27 17:33 ` [PATCH 21/38] kernfs, sysfs, cgroup, intel_rdt: Support " David Howells
2018-07-27 17:33 ` [PATCH 22/38] hugetlbfs: Convert to " David Howells
2018-07-27 17:33 ` [PATCH 23/38] vfs: Remove kern_mount_data() " David Howells
2018-07-27 17:34 ` [PATCH 24/38] vfs: Provide documentation for new mount API " David Howells
2018-07-27 17:34 ` [PATCH 25/38] Make anon_inodes unconditional " David Howells
2018-07-27 20:04 ` Randy Dunlap
2018-07-30 10:52 ` David Howells
2018-07-27 17:34 ` [PATCH 26/38] vfs: syscall: Add fsopen() to prepare for superblock creation " David Howells
2018-07-27 17:34 ` [PATCH 27/38] vfs: Implement logging through fs_context " David Howells
2018-07-27 17:34 ` [PATCH 28/38] vfs: Add some logging to the core users of the fs_context log " David Howells
2018-07-27 17:34 ` [PATCH 29/38] vfs: syscall: Add fsconfig() for configuring and managing a context " David Howells
2018-07-27 19:42 ` Andy Lutomirski
2018-07-27 21:51 ` David Howells
2018-07-27 21:57 ` Andy Lutomirski
2018-07-27 22:27 ` David Howells
2018-07-27 22:32 ` Jann Horn
2018-07-29 8:50 ` David Howells
2018-07-29 11:14 ` Jann Horn
2018-07-30 12:32 ` David Howells
2018-07-27 17:34 ` [PATCH 30/38] vfs: syscall: Add fsmount() to create a mount for a superblock " David Howells
2018-07-27 19:27 ` Andy Lutomirski
2018-07-27 19:43 ` Andy Lutomirski
2018-07-27 22:09 ` David Howells
2018-07-27 22:06 ` David Howells
2018-07-27 17:34 ` [PATCH 31/38] vfs: syscall: Add fspick() to select a superblock for reconfiguration " David Howells
2018-07-27 17:34 ` [PATCH 32/38] afs: Add fs_context support " David Howells
2018-07-27 17:35 ` [PATCH 33/38] afs: Use fs_context to pass parameters over automount " David Howells
2018-07-27 17:35 ` [PATCH 34/38] vfs: syscall: Add fsinfo() to query filesystem information " David Howells
2018-07-27 19:35 ` Andy Lutomirski
2018-07-27 22:12 ` David Howells
2018-07-27 23:14 ` Jann Horn
2018-07-27 23:49 ` David Howells
2018-07-28 0:14 ` Anton Altaparmakov
2018-07-27 23:51 ` David Howells
2018-07-27 23:58 ` Jann Horn
2018-07-28 0:08 ` David Howells
2018-07-30 14:48 ` David Howells
2018-07-31 4:16 ` Al Viro
2018-07-31 12:39 ` David Howells
2018-07-31 13:20 ` David Howells
2018-07-31 23:49 ` Darrick J. Wong
2018-08-01 1:07 ` David Howells
2018-07-27 17:35 ` [PATCH 35/38] afs: Add fsinfo support " David Howells
2018-07-27 17:35 ` [PATCH 36/38] vfs: Add a sample program for the new mount API " David Howells
2018-07-29 11:37 ` Pavel Machek
2018-07-30 12:23 ` David Howells
2018-07-30 14:31 ` Pavel Machek
2018-07-30 18:08 ` Matthew Wilcox
2018-07-30 18:16 ` Pavel Machek
2018-07-30 18:18 ` Linus Torvalds
2018-07-30 18:38 ` Matthew Wilcox
2018-07-30 18:59 ` Linus Torvalds
2018-07-30 19:49 ` Matthew Wilcox
2018-07-30 21:02 ` Theodore Y. Ts'o
2018-07-30 21:23 ` Pavel Machek
2018-07-30 23:58 ` Matthew Wilcox
2018-07-31 0:58 ` Theodore Y. Ts'o
2018-07-31 9:40 ` Pavel Machek
2018-07-31 10:11 ` David Howells
2018-07-31 11:34 ` Pavel Machek
2018-07-31 12:07 ` Matthew Wilcox
2018-07-31 12:28 ` Pavel Machek
2018-07-31 13:33 ` Al Viro
2018-07-31 13:00 ` David Howells
2018-07-31 19:39 ` Pavel Machek
2018-07-31 21:00 ` David Howells
2018-07-31 21:21 ` Linus Torvalds
2018-07-31 21:38 ` David Howells
2018-07-30 20:47 ` Pavel Machek
2018-07-30 15:33 ` David Howells
2018-07-30 17:30 ` Pavel Machek
2018-07-30 17:54 ` Linus Torvalds
2018-07-30 18:16 ` Pavel Machek
2018-07-27 17:35 ` [PATCH 37/38] vfs: Allow fsinfo() to query what's in an fs_context " David Howells
2018-07-27 17:35 ` [PATCH 38/38] vfs: Allow fsinfo() to be used to query an fs parameter description " 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=153271274305.9458.13602378603425233117.stgit@warthog.procyon.org.uk \
--to=dhowells@redhat.com \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-security-module@vger.kernel.org \
--cc=paul@paul-moore.com \
--cc=sds@tycho.nsa.gov \
--cc=selinux@tycho.nsa.gov \
--cc=torvalds@linux-foundation.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).