Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ba641862 authored by Al Viro's avatar Al Viro
Browse files

selinux: new helper - selinux_add_opt()



the guts of the loop in selinux_parse_opts_str() - takes one
(already recognized) option and adds it to growing selinux_mnt_opts.

Reviewed-by: default avatarDavid Howells <dhowells@redhat.com>
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 84d8c4a5
Loading
Loading
Loading
Loading
+53 −73
Original line number Diff line number Diff line
@@ -984,97 +984,77 @@ static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
	return rc;
}

static int selinux_parse_opts_str(char *options,
				  void **mnt_opts)
static int selinux_add_opt(int token, const char *s, void **mnt_opts)
{
	struct selinux_mnt_opts *opts = *mnt_opts;
	char *p;
	int rc;

	/* Standard string-based options. */
	while ((p = strsep(&options, "|")) != NULL) {
		int token;
		substring_t args[MAX_OPT_ARGS];

		if (!*p)
			continue;

		token = match_token(p, tokens, args);

	if (!opts) {
		opts = kzalloc(sizeof(struct selinux_mnt_opts), GFP_KERNEL);
		if (!opts)
			return -ENOMEM;
		*mnt_opts = opts;
	}

	if (!s)
		return -ENOMEM;
	switch (token) {
	case Opt_context:
			if (opts->context || opts->defcontext) {
				rc = -EINVAL;
				pr_warn(SEL_MOUNT_FAIL_MSG);
				goto out_err;
			}
			opts->context = match_strdup(&args[0]);
			if (!opts->context) {
				rc = -ENOMEM;
				goto out_err;
			}
		if (opts->context || opts->defcontext)
			goto Einval;
		opts->context = s;
		break;

	case Opt_fscontext:
			if (opts->fscontext) {
				rc = -EINVAL;
				pr_warn(SEL_MOUNT_FAIL_MSG);
				goto out_err;
			}
			opts->fscontext = match_strdup(&args[0]);
			if (!opts->fscontext) {
				rc = -ENOMEM;
				goto out_err;
			}
		if (opts->fscontext)
			goto Einval;
		opts->fscontext = s;
		break;

	case Opt_rootcontext:
			if (opts->rootcontext) {
				rc = -EINVAL;
				pr_warn(SEL_MOUNT_FAIL_MSG);
				goto out_err;
			}
			opts->rootcontext = match_strdup(&args[0]);
			if (!opts->rootcontext) {
				rc = -ENOMEM;
				goto out_err;
			}
		if (opts->rootcontext)
			goto Einval;
		opts->rootcontext = s;
		break;

	case Opt_defcontext:
			if (opts->context || opts->defcontext) {
				rc = -EINVAL;
				pr_warn(SEL_MOUNT_FAIL_MSG);
				goto out_err;
		if (opts->context || opts->defcontext)
			goto Einval;
		opts->defcontext = s;
		break;
	}
			opts->defcontext = match_strdup(&args[0]);
			if (!opts->defcontext) {
				rc = -ENOMEM;
				goto out_err;
	return 0;
Einval:
	pr_warn(SEL_MOUNT_FAIL_MSG);
	kfree(s);
	return -EINVAL;
}
			break;
		case Opt_labelsupport:
			break;
		default:
			rc = -EINVAL;
			pr_warn("SELinux:  unknown mount option\n");
			goto out_err;

static int selinux_parse_opts_str(char *options,
				  void **mnt_opts)
{
	char *p;

	/* Standard string-based options. */
	while ((p = strsep(&options, "|")) != NULL) {
		int token, rc;
		substring_t args[MAX_OPT_ARGS];
		const char *arg;

		if (!*p)
			continue;

		token = match_token(p, tokens, args);

		if (token == Opt_labelsupport)	/* eaten and completely ignored */
			continue;
		arg = match_strdup(&args[0]);
		rc = selinux_add_opt(token, arg, mnt_opts);
		if (unlikely(rc)) {
			kfree(arg);
			if (*mnt_opts) {
				selinux_free_mnt_opts(*mnt_opts);
				*mnt_opts = NULL;
			}
			return rc;
		}
	}
	*mnt_opts = opts;
	return 0;

out_err:
	if (opts)
		selinux_free_mnt_opts(opts);
	return rc;
}

static int show_sid(struct seq_file *m, u32 sid)