summaryrefslogtreecommitdiffstats
path: root/security/selinux
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2018-12-14 20:28:15 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2018-12-21 11:49:18 -0500
commitba6418623385abf19a6c15cf0b1cfaacfdf9afc8 (patch)
treef6ffef1eb1886b5b94677979ac03de3e5d48036c /security/selinux
parent84d8c4a5ef696ca96fa7a8d64db9222658b9d142 (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.c126
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
987static 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;
1022Einval:
1023 pr_warn(SEL_MOUNT_FAIL_MSG);
1024 kfree(s);
1025 return -EINVAL;
1026}
1027
987static int selinux_parse_opts_str(char *options, 1028static 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
1074out_err:
1075 if (opts)
1076 selinux_free_mnt_opts(opts);
1077 return rc;
1078} 1058}
1079 1059
1080static int show_sid(struct seq_file *m, u32 sid) 1060static int show_sid(struct seq_file *m, u32 sid)