#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>
enum {
Opt_error = -1,
- Opt_context = 1,
+ Opt_context = 0,
+ Opt_defcontext = 1,
Opt_fscontext = 2,
- Opt_defcontext = 3,
- Opt_rootcontext = 4,
- Opt_seclabel = 5,
+ Opt_rootcontext = 3,
+ Opt_seclabel = 4,
};
#define A(s, has_arg) {#s, sizeof(#s) - 1, Opt_##s, has_arg}
BUG_ON(!(oldsbsec->flags & SE_SBINITIALIZED));
/* if fs is reusing a sb, make sure that the contexts match */
- if (newsbsec->flags & SE_SBINITIALIZED)
+ if (newsbsec->flags & SE_SBINITIALIZED) {
+ if ((kern_flags & SECURITY_LSM_NATIVE_LABELS) && !set_context)
+ *set_kern_flags |= SECURITY_LSM_NATIVE_LABELS;
return selinux_cmp_sb_context(oldsb, newsb);
+ }
mutex_lock(&newsbsec->lock);
if (!rc) {
bool has_comma = context && strchr(context, ',');
+ seq_putc(m, '=');
if (has_comma)
seq_putc(m, '\"');
seq_escape(m, context, "\"\n\\");
}
if (sbsec->flags & SBLABEL_MNT) {
seq_putc(m, ',');
- seq_puts(m, LABELSUPP_STR);
+ seq_puts(m, SECLABEL_STR);
}
return 0;
}
FILESYSTEM__UNMOUNT, NULL);
}
+static int selinux_fs_context_dup(struct fs_context *fc,
+ struct fs_context *src_fc)
+{
+ const struct selinux_mnt_opts *src = src_fc->security;
+ struct selinux_mnt_opts *opts;
+
+ if (!src)
+ return 0;
+
+ fc->security = kzalloc(sizeof(struct selinux_mnt_opts), GFP_KERNEL);
+ if (!fc->security)
+ return -ENOMEM;
+
+ opts = fc->security;
+
+ if (src->fscontext) {
+ opts->fscontext = kstrdup(src->fscontext, GFP_KERNEL);
+ if (!opts->fscontext)
+ return -ENOMEM;
+ }
+ if (src->context) {
+ opts->context = kstrdup(src->context, GFP_KERNEL);
+ if (!opts->context)
+ return -ENOMEM;
+ }
+ if (src->rootcontext) {
+ opts->rootcontext = kstrdup(src->rootcontext, GFP_KERNEL);
+ if (!opts->rootcontext)
+ return -ENOMEM;
+ }
+ if (src->defcontext) {
+ opts->defcontext = kstrdup(src->defcontext, GFP_KERNEL);
+ if (!opts->defcontext)
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+static const struct fs_parameter_spec selinux_param_specs[] = {
+ fsparam_string(CONTEXT_STR, Opt_context),
+ fsparam_string(DEFCONTEXT_STR, Opt_defcontext),
+ fsparam_string(FSCONTEXT_STR, Opt_fscontext),
+ fsparam_string(ROOTCONTEXT_STR, Opt_rootcontext),
+ fsparam_flag (SECLABEL_STR, Opt_seclabel),
+ {}
+};
+
+static const struct fs_parameter_description selinux_fs_parameters = {
+ .name = "SELinux",
+ .specs = selinux_param_specs,
+};
+
+static int selinux_fs_context_parse_param(struct fs_context *fc,
+ struct fs_parameter *param)
+{
+ struct fs_parse_result result;
+ int opt, rc;
+
+ opt = fs_parse(fc, &selinux_fs_parameters, param, &result);
+ if (opt < 0)
+ return opt;
+
+ rc = selinux_add_opt(opt, param->string, &fc->security);
+ if (!rc) {
+ param->string = NULL;
+ rc = 1;
+ }
+ return rc;
+}
+
/* inode security operations */
static int selinux_inode_alloc_security(struct inode *inode)
return -EINVAL;
}
+ if (walk_size + len > addrlen)
+ return -EINVAL;
+
err = -EINVAL;
switch (optname) {
/* Bind checks */
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_dup, selinux_fs_context_dup),
+ LSM_HOOK_INIT(fs_context_parse_param, selinux_fs_context_parse_param),
+
LSM_HOOK_INIT(sb_alloc_security, selinux_sb_alloc_security),
LSM_HOOK_INIT(sb_free_security, selinux_sb_free_security),
LSM_HOOK_INIT(sb_eat_lsm_opts, selinux_sb_eat_lsm_opts),
else
pr_debug("SELinux: Starting in permissive mode\n");
+ fs_validate_description(&selinux_fs_parameters);
+
return 0;
}