summaryrefslogtreecommitdiffstats
path: root/security/selinux
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2018-12-14 22:44:50 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2018-12-21 11:49:28 -0500
commit169d68efb03b728588c209c682f14328eec485c0 (patch)
tree9d0f9587ee8d2863ecb558be1de2342f9aa6ee92 /security/selinux
parentba6418623385abf19a6c15cf0b1cfaacfdf9afc8 (diff)
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: David Howells <dhowells@redhat.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'security/selinux')
-rw-r--r--security/selinux/hooks.c82
1 files changed, 55 insertions, 27 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 26ec7d67e15d..8f2285cb9029 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -459,19 +459,41 @@ enum {
459 Opt_defcontext = 3, 459 Opt_defcontext = 3,
460 Opt_rootcontext = 4, 460 Opt_rootcontext = 4,
461 Opt_labelsupport = 5, 461 Opt_labelsupport = 5,
462 Opt_nextmntopt = 6,
463}; 462};
464 463
465#define NUM_SEL_MNT_OPTS (Opt_nextmntopt - 1) 464#define A(s, opt, has_arg) {s, sizeof(s) - 1, opt, has_arg}
466 465static struct {
467static const match_table_t tokens = { 466 const char *name;
468 {Opt_context, CONTEXT_STR "%s"}, 467 int len;
469 {Opt_fscontext, FSCONTEXT_STR "%s"}, 468 int opt;
470 {Opt_defcontext, DEFCONTEXT_STR "%s"}, 469 bool has_arg;
471 {Opt_rootcontext, ROOTCONTEXT_STR "%s"}, 470} tokens[] = {
472 {Opt_labelsupport, LABELSUPP_STR}, 471 A("context", Opt_context, true),
473 {Opt_error, NULL}, 472 A("fscontext", Opt_fscontext, true),
473 A("defcontext", Opt_defcontext, true),
474 A("rootcontext", Opt_rootcontext, true),
475 A("seclabel", Opt_labelsupport, false),
474}; 476};
477#undef A
478
479static int match_opt_prefix(char *s, int l, char **arg)
480{
481 int i;
482
483 for (i = 0; i < ARRAY_SIZE(tokens); i++) {
484 size_t len = tokens[i].len;
485 if (len > l || memcmp(s, tokens[i].name, len))
486 continue;
487 if (tokens[i].has_arg) {
488 if (len == l || s[len] != '=')
489 continue;
490 *arg = s + len + 1;
491 } else if (len != l)
492 continue;
493 return tokens[i].opt;
494 }
495 return Opt_error;
496}
475 497
476#define SEL_MOUNT_FAIL_MSG "SELinux: duplicate or incompatible mount options\n" 498#define SEL_MOUNT_FAIL_MSG "SELinux: duplicate or incompatible mount options\n"
477 499
@@ -988,6 +1010,9 @@ static int selinux_add_opt(int token, const char *s, void **mnt_opts)
988{ 1010{
989 struct selinux_mnt_opts *opts = *mnt_opts; 1011 struct selinux_mnt_opts *opts = *mnt_opts;
990 1012
1013 if (token == Opt_labelsupport) /* eaten and completely ignored */
1014 return 0;
1015
991 if (!opts) { 1016 if (!opts) {
992 opts = kzalloc(sizeof(struct selinux_mnt_opts), GFP_KERNEL); 1017 opts = kzalloc(sizeof(struct selinux_mnt_opts), GFP_KERNEL);
993 if (!opts) 1018 if (!opts)
@@ -1021,36 +1046,39 @@ static int selinux_add_opt(int token, const char *s, void **mnt_opts)
1021 return 0; 1046 return 0;
1022Einval: 1047Einval:
1023 pr_warn(SEL_MOUNT_FAIL_MSG); 1048 pr_warn(SEL_MOUNT_FAIL_MSG);
1024 kfree(s);
1025 return -EINVAL; 1049 return -EINVAL;
1026} 1050}
1027 1051
1028static int selinux_parse_opts_str(char *options, 1052static int selinux_parse_opts_str(char *options,
1029 void **mnt_opts) 1053 void **mnt_opts)
1030{ 1054{
1031 char *p; 1055 char *p = options, *next;
1056 int rc;
1032 1057
1033 /* Standard string-based options. */ 1058 /* Standard string-based options. */
1034 while ((p = strsep(&options, "|")) != NULL) { 1059 for (p = options; *p; p = next) {
1035 int token, rc; 1060 int token, len;
1036 substring_t args[MAX_OPT_ARGS]; 1061 char *arg = NULL;
1037 const char *arg;
1038 1062
1039 if (!*p) 1063 next = strchr(p, '|');
1040 continue; 1064 if (next) {
1041 1065 len = next++ - p;
1042 token = match_token(p, tokens, args); 1066 } else {
1067 len = strlen(p);
1068 next = p + len;
1069 }
1043 1070
1044 if (token == Opt_labelsupport) /* eaten and completely ignored */ 1071 if (!len)
1045 continue; 1072 continue;
1046 arg = match_strdup(&args[0]); 1073
1074 token = match_opt_prefix(p, len, &arg);
1075 if (arg)
1076 arg = kmemdup_nul(arg, p + len - arg, GFP_KERNEL);
1047 rc = selinux_add_opt(token, arg, mnt_opts); 1077 rc = selinux_add_opt(token, arg, mnt_opts);
1048 if (unlikely(rc)) { 1078 if (rc) {
1049 kfree(arg); 1079 kfree(arg);
1050 if (*mnt_opts) { 1080 selinux_free_mnt_opts(*mnt_opts);
1051 selinux_free_mnt_opts(*mnt_opts); 1081 *mnt_opts = NULL;
1052 *mnt_opts = NULL;
1053 }
1054 return rc; 1082 return rc;
1055 } 1083 }
1056 } 1084 }