diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2018-12-14 20:28:15 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2018-12-21 11:49:18 -0500 |
commit | ba6418623385abf19a6c15cf0b1cfaacfdf9afc8 (patch) | |
tree | f6ffef1eb1886b5b94677979ac03de3e5d48036c /security/selinux | |
parent | 84d8c4a5ef696ca96fa7a8d64db9222658b9d142 (diff) |
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: 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.c | 126 |
1 files changed, 53 insertions, 73 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 238907d69e8b..26ec7d67e15d 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -984,97 +984,77 @@ out: | |||
984 | return rc; | 984 | return rc; |
985 | } | 985 | } |
986 | 986 | ||
987 | static int selinux_add_opt(int token, const char *s, void **mnt_opts) | ||
988 | { | ||
989 | struct selinux_mnt_opts *opts = *mnt_opts; | ||
990 | |||
991 | if (!opts) { | ||
992 | opts = kzalloc(sizeof(struct selinux_mnt_opts), GFP_KERNEL); | ||
993 | if (!opts) | ||
994 | return -ENOMEM; | ||
995 | *mnt_opts = opts; | ||
996 | } | ||
997 | if (!s) | ||
998 | return -ENOMEM; | ||
999 | switch (token) { | ||
1000 | case Opt_context: | ||
1001 | if (opts->context || opts->defcontext) | ||
1002 | goto Einval; | ||
1003 | opts->context = s; | ||
1004 | break; | ||
1005 | case Opt_fscontext: | ||
1006 | if (opts->fscontext) | ||
1007 | goto Einval; | ||
1008 | opts->fscontext = s; | ||
1009 | break; | ||
1010 | case Opt_rootcontext: | ||
1011 | if (opts->rootcontext) | ||
1012 | goto Einval; | ||
1013 | opts->rootcontext = s; | ||
1014 | break; | ||
1015 | case Opt_defcontext: | ||
1016 | if (opts->context || opts->defcontext) | ||
1017 | goto Einval; | ||
1018 | opts->defcontext = s; | ||
1019 | break; | ||
1020 | } | ||
1021 | return 0; | ||
1022 | Einval: | ||
1023 | pr_warn(SEL_MOUNT_FAIL_MSG); | ||
1024 | kfree(s); | ||
1025 | return -EINVAL; | ||
1026 | } | ||
1027 | |||
987 | static int selinux_parse_opts_str(char *options, | 1028 | static int selinux_parse_opts_str(char *options, |
988 | void **mnt_opts) | 1029 | void **mnt_opts) |
989 | { | 1030 | { |
990 | struct selinux_mnt_opts *opts = *mnt_opts; | ||
991 | char *p; | 1031 | char *p; |
992 | int rc; | ||
993 | 1032 | ||
994 | /* Standard string-based options. */ | 1033 | /* Standard string-based options. */ |
995 | while ((p = strsep(&options, "|")) != NULL) { | 1034 | while ((p = strsep(&options, "|")) != NULL) { |
996 | int token; | 1035 | int token, rc; |
997 | substring_t args[MAX_OPT_ARGS]; | 1036 | substring_t args[MAX_OPT_ARGS]; |
1037 | const char *arg; | ||
998 | 1038 | ||
999 | if (!*p) | 1039 | if (!*p) |
1000 | continue; | 1040 | continue; |
1001 | 1041 | ||
1002 | token = match_token(p, tokens, args); | 1042 | token = match_token(p, tokens, args); |
1003 | 1043 | ||
1004 | if (!opts) { | 1044 | if (token == Opt_labelsupport) /* eaten and completely ignored */ |
1005 | opts = kzalloc(sizeof(struct selinux_mnt_opts), GFP_KERNEL); | 1045 | continue; |
1006 | if (!opts) | 1046 | arg = match_strdup(&args[0]); |
1007 | return -ENOMEM; | 1047 | rc = selinux_add_opt(token, arg, mnt_opts); |
1008 | } | 1048 | if (unlikely(rc)) { |
1009 | 1049 | kfree(arg); | |
1010 | switch (token) { | 1050 | if (*mnt_opts) { |
1011 | case Opt_context: | 1051 | selinux_free_mnt_opts(*mnt_opts); |
1012 | if (opts->context || opts->defcontext) { | 1052 | *mnt_opts = NULL; |
1013 | rc = -EINVAL; | ||
1014 | pr_warn(SEL_MOUNT_FAIL_MSG); | ||
1015 | goto out_err; | ||
1016 | } | ||
1017 | opts->context = match_strdup(&args[0]); | ||
1018 | if (!opts->context) { | ||
1019 | rc = -ENOMEM; | ||
1020 | goto out_err; | ||
1021 | } | ||
1022 | break; | ||
1023 | |||
1024 | case Opt_fscontext: | ||
1025 | if (opts->fscontext) { | ||
1026 | rc = -EINVAL; | ||
1027 | pr_warn(SEL_MOUNT_FAIL_MSG); | ||
1028 | goto out_err; | ||
1029 | } | ||
1030 | opts->fscontext = match_strdup(&args[0]); | ||
1031 | if (!opts->fscontext) { | ||
1032 | rc = -ENOMEM; | ||
1033 | goto out_err; | ||
1034 | } | ||
1035 | break; | ||
1036 | |||
1037 | case Opt_rootcontext: | ||
1038 | if (opts->rootcontext) { | ||
1039 | rc = -EINVAL; | ||
1040 | pr_warn(SEL_MOUNT_FAIL_MSG); | ||
1041 | goto out_err; | ||
1042 | } | ||
1043 | opts->rootcontext = match_strdup(&args[0]); | ||
1044 | if (!opts->rootcontext) { | ||
1045 | rc = -ENOMEM; | ||
1046 | goto out_err; | ||
1047 | } | ||
1048 | break; | ||
1049 | |||
1050 | case Opt_defcontext: | ||
1051 | if (opts->context || opts->defcontext) { | ||
1052 | rc = -EINVAL; | ||
1053 | pr_warn(SEL_MOUNT_FAIL_MSG); | ||
1054 | goto out_err; | ||
1055 | } | ||
1056 | opts->defcontext = match_strdup(&args[0]); | ||
1057 | if (!opts->defcontext) { | ||
1058 | rc = -ENOMEM; | ||
1059 | goto out_err; | ||
1060 | } | 1053 | } |
1061 | break; | 1054 | return rc; |
1062 | case Opt_labelsupport: | ||
1063 | break; | ||
1064 | default: | ||
1065 | rc = -EINVAL; | ||
1066 | pr_warn("SELinux: unknown mount option\n"); | ||
1067 | goto out_err; | ||
1068 | |||
1069 | } | 1055 | } |
1070 | } | 1056 | } |
1071 | *mnt_opts = opts; | ||
1072 | return 0; | 1057 | return 0; |
1073 | |||
1074 | out_err: | ||
1075 | if (opts) | ||
1076 | selinux_free_mnt_opts(opts); | ||
1077 | return rc; | ||
1078 | } | 1058 | } |
1079 | 1059 | ||
1080 | static int show_sid(struct seq_file *m, u32 sid) | 1060 | static int show_sid(struct seq_file *m, u32 sid) |