Commit 169d68ef authored by Al Viro's avatar Al Viro

selinux: switch away from match_token()

It's not a good fit, unfortunately, and the next step will make it
even less so.  Open-code what we need here.
Reviewed-by: default avatarDavid Howells <dhowells@redhat.com>
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent ba641862
...@@ -459,19 +459,41 @@ enum { ...@@ -459,19 +459,41 @@ enum {
Opt_defcontext = 3, Opt_defcontext = 3,
Opt_rootcontext = 4, Opt_rootcontext = 4,
Opt_labelsupport = 5, Opt_labelsupport = 5,
Opt_nextmntopt = 6,
}; };
#define NUM_SEL_MNT_OPTS (Opt_nextmntopt - 1) #define A(s, opt, has_arg) {s, sizeof(s) - 1, opt, has_arg}
static struct {
static const match_table_t tokens = { const char *name;
{Opt_context, CONTEXT_STR "%s"}, int len;
{Opt_fscontext, FSCONTEXT_STR "%s"}, int opt;
{Opt_defcontext, DEFCONTEXT_STR "%s"}, bool has_arg;
{Opt_rootcontext, ROOTCONTEXT_STR "%s"}, } tokens[] = {
{Opt_labelsupport, LABELSUPP_STR}, A("context", Opt_context, true),
{Opt_error, NULL}, A("fscontext", Opt_fscontext, true),
A("defcontext", Opt_defcontext, true),
A("rootcontext", Opt_rootcontext, true),
A("seclabel", Opt_labelsupport, false),
}; };
#undef A
static int match_opt_prefix(char *s, int l, char **arg)
{
int i;
for (i = 0; i < ARRAY_SIZE(tokens); i++) {
size_t len = tokens[i].len;
if (len > l || memcmp(s, tokens[i].name, len))
continue;
if (tokens[i].has_arg) {
if (len == l || s[len] != '=')
continue;
*arg = s + len + 1;
} else if (len != l)
continue;
return tokens[i].opt;
}
return Opt_error;
}
#define SEL_MOUNT_FAIL_MSG "SELinux: duplicate or incompatible mount options\n" #define SEL_MOUNT_FAIL_MSG "SELinux: duplicate or incompatible mount options\n"
...@@ -988,6 +1010,9 @@ static int selinux_add_opt(int token, const char *s, void **mnt_opts) ...@@ -988,6 +1010,9 @@ static int selinux_add_opt(int token, const char *s, void **mnt_opts)
{ {
struct selinux_mnt_opts *opts = *mnt_opts; struct selinux_mnt_opts *opts = *mnt_opts;
if (token == Opt_labelsupport) /* eaten and completely ignored */
return 0;
if (!opts) { if (!opts) {
opts = kzalloc(sizeof(struct selinux_mnt_opts), GFP_KERNEL); opts = kzalloc(sizeof(struct selinux_mnt_opts), GFP_KERNEL);
if (!opts) if (!opts)
...@@ -1021,36 +1046,39 @@ static int selinux_add_opt(int token, const char *s, void **mnt_opts) ...@@ -1021,36 +1046,39 @@ static int selinux_add_opt(int token, const char *s, void **mnt_opts)
return 0; return 0;
Einval: Einval:
pr_warn(SEL_MOUNT_FAIL_MSG); pr_warn(SEL_MOUNT_FAIL_MSG);
kfree(s);
return -EINVAL; return -EINVAL;
} }
static int selinux_parse_opts_str(char *options, static int selinux_parse_opts_str(char *options,
void **mnt_opts) void **mnt_opts)
{ {
char *p; char *p = options, *next;
int rc;
/* Standard string-based options. */ /* Standard string-based options. */
while ((p = strsep(&options, "|")) != NULL) { for (p = options; *p; p = next) {
int token, rc; int token, len;
substring_t args[MAX_OPT_ARGS]; char *arg = NULL;
const char *arg;
if (!*p) next = strchr(p, '|');
continue; if (next) {
len = next++ - p;
token = match_token(p, tokens, args); } else {
len = strlen(p);
next = p + len;
}
if (token == Opt_labelsupport) /* eaten and completely ignored */ if (!len)
continue; continue;
arg = match_strdup(&args[0]);
token = match_opt_prefix(p, len, &arg);
if (arg)
arg = kmemdup_nul(arg, p + len - arg, GFP_KERNEL);
rc = selinux_add_opt(token, arg, mnt_opts); rc = selinux_add_opt(token, arg, mnt_opts);
if (unlikely(rc)) { if (rc) {
kfree(arg); kfree(arg);
if (*mnt_opts) { selinux_free_mnt_opts(*mnt_opts);
selinux_free_mnt_opts(*mnt_opts); *mnt_opts = NULL;
*mnt_opts = NULL;
}
return rc; return rc;
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment