mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	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>
This commit is contained in:
		
							parent
							
								
									84d8c4a5ef
								
							
						
					
					
						commit
						ba64186233
					
				
					 1 changed files with 53 additions and 73 deletions
				
			
		| 
						 | 
				
			
			@ -984,97 +984,77 @@ static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
 | 
			
		|||
	return rc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int selinux_add_opt(int token, const char *s, void **mnt_opts)
 | 
			
		||||
{
 | 
			
		||||
	struct selinux_mnt_opts *opts = *mnt_opts;
 | 
			
		||||
 | 
			
		||||
	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)
 | 
			
		||||
			goto Einval;
 | 
			
		||||
		opts->context = s;
 | 
			
		||||
		break;
 | 
			
		||||
	case Opt_fscontext:
 | 
			
		||||
		if (opts->fscontext)
 | 
			
		||||
			goto Einval;
 | 
			
		||||
		opts->fscontext = s;
 | 
			
		||||
		break;
 | 
			
		||||
	case Opt_rootcontext:
 | 
			
		||||
		if (opts->rootcontext)
 | 
			
		||||
			goto Einval;
 | 
			
		||||
		opts->rootcontext = s;
 | 
			
		||||
		break;
 | 
			
		||||
	case Opt_defcontext:
 | 
			
		||||
		if (opts->context || opts->defcontext)
 | 
			
		||||
			goto Einval;
 | 
			
		||||
		opts->defcontext = s;
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
	return 0;
 | 
			
		||||
Einval:
 | 
			
		||||
	pr_warn(SEL_MOUNT_FAIL_MSG);
 | 
			
		||||
	kfree(s);
 | 
			
		||||
	return -EINVAL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int selinux_parse_opts_str(char *options,
 | 
			
		||||
				  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;
 | 
			
		||||
		int token, rc;
 | 
			
		||||
		substring_t args[MAX_OPT_ARGS];
 | 
			
		||||
		const char *arg;
 | 
			
		||||
 | 
			
		||||
		if (!*p)
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		token = match_token(p, tokens, args);
 | 
			
		||||
 | 
			
		||||
		if (!opts) {
 | 
			
		||||
			opts = kzalloc(sizeof(struct selinux_mnt_opts), GFP_KERNEL);
 | 
			
		||||
			if (!opts)
 | 
			
		||||
				return -ENOMEM;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		switch (token) {
 | 
			
		||||
		case Opt_context:
 | 
			
		||||
			if (opts->context || opts->defcontext) {
 | 
			
		||||
				rc = -EINVAL;
 | 
			
		||||
				pr_warn(SEL_MOUNT_FAIL_MSG);
 | 
			
		||||
				goto out_err;
 | 
			
		||||
		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;
 | 
			
		||||
			}
 | 
			
		||||
			opts->context = match_strdup(&args[0]);
 | 
			
		||||
			if (!opts->context) {
 | 
			
		||||
				rc = -ENOMEM;
 | 
			
		||||
				goto out_err;
 | 
			
		||||
			}
 | 
			
		||||
			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;
 | 
			
		||||
			}
 | 
			
		||||
			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;
 | 
			
		||||
			}
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		case Opt_defcontext:
 | 
			
		||||
			if (opts->context || opts->defcontext) {
 | 
			
		||||
				rc = -EINVAL;
 | 
			
		||||
				pr_warn(SEL_MOUNT_FAIL_MSG);
 | 
			
		||||
				goto out_err;
 | 
			
		||||
			}
 | 
			
		||||
			opts->defcontext = match_strdup(&args[0]);
 | 
			
		||||
			if (!opts->defcontext) {
 | 
			
		||||
				rc = -ENOMEM;
 | 
			
		||||
				goto out_err;
 | 
			
		||||
			}
 | 
			
		||||
			break;
 | 
			
		||||
		case Opt_labelsupport:
 | 
			
		||||
			break;
 | 
			
		||||
		default:
 | 
			
		||||
			rc = -EINVAL;
 | 
			
		||||
			pr_warn("SELinux:  unknown mount option\n");
 | 
			
		||||
			goto out_err;
 | 
			
		||||
 | 
			
		||||
			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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue