Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c039bc3c authored by Al Viro's avatar Al Viro
Browse files

LSM: lift extracting and parsing LSM options into the caller of ->sb_remount()



This paves the way for retaining the LSM options from a common filesystem
mount context during a mount parameter parsing phase to be instituted prior
to actual mount/reconfiguration actions.

Reviewed-by: default avatarDavid Howells <dhowells@redhat.com>
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 6be8750b
Loading
Loading
Loading
Loading
+18 −1
Original line number Diff line number Diff line
@@ -2299,6 +2299,7 @@ static int do_remount(struct path *path, int ms_flags, int sb_flags,
	int err;
	struct super_block *sb = path->mnt->mnt_sb;
	struct mount *mnt = real_mount(path->mnt);
	struct security_mnt_opts opts;

	if (!check_mnt(mnt))
		return -EINVAL;
@@ -2309,7 +2310,23 @@ static int do_remount(struct path *path, int ms_flags, int sb_flags,
	if (!can_change_locked_flags(mnt, mnt_flags))
		return -EPERM;

	err = security_sb_remount(sb, data);
	security_init_mnt_opts(&opts);
	if (data && !(sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)) {
		char *secdata = alloc_secdata();
		if (!secdata)
			return -ENOMEM;
		err = security_sb_copy_data(data, secdata);
		if (err) {
			free_secdata(secdata);
			return err;
		}
		err = security_sb_parse_opts_str(secdata, &opts);
		free_secdata(secdata);
		if (err)
			return err;
	}
	err = security_sb_remount(sb, &opts);
	security_free_mnt_opts(&opts);
	if (err)
		return err;

+2 −1
Original line number Diff line number Diff line
@@ -1462,7 +1462,8 @@ union security_list_options {
	int (*sb_alloc_security)(struct super_block *sb);
	void (*sb_free_security)(struct super_block *sb);
	int (*sb_copy_data)(char *orig, char *copy);
	int (*sb_remount)(struct super_block *sb, void *data);
	int (*sb_remount)(struct super_block *sb,
			  struct security_mnt_opts *opts);
	int (*sb_kern_mount)(struct super_block *sb, int flags,
			     struct security_mnt_opts *opts);
	int (*sb_show_options)(struct seq_file *m, struct super_block *sb);
+3 −2
Original line number Diff line number Diff line
@@ -249,7 +249,7 @@ void security_bprm_committed_creds(struct linux_binprm *bprm);
int security_sb_alloc(struct super_block *sb);
void security_sb_free(struct super_block *sb);
int security_sb_copy_data(char *orig, char *copy);
int security_sb_remount(struct super_block *sb, void *data);
int security_sb_remount(struct super_block *sb, struct security_mnt_opts *opts);
int security_sb_kern_mount(struct super_block *sb, int flags,
			   struct security_mnt_opts *opts);
int security_sb_show_options(struct seq_file *m, struct super_block *sb);
@@ -561,7 +561,8 @@ static inline int security_sb_copy_data(char *orig, char *copy)
	return 0;
}

static inline int security_sb_remount(struct super_block *sb, void *data)
static inline int security_sb_remount(struct super_block *sb,
				      struct security_mnt_opts *opts)
{
	return 0;
}
+3 −2
Original line number Diff line number Diff line
@@ -390,9 +390,10 @@ int security_sb_copy_data(char *orig, char *copy)
}
EXPORT_SYMBOL(security_sb_copy_data);

int security_sb_remount(struct super_block *sb, void *data)
int security_sb_remount(struct super_block *sb,
			struct security_mnt_opts *opts)
{
	return call_int_hook(sb_remount, 0, sb, data);
	return call_int_hook(sb_remount, 0, sb, opts);
}

int security_sb_kern_mount(struct super_block *sb, int flags,
+12 −35
Original line number Diff line number Diff line
@@ -2812,39 +2812,22 @@ static int selinux_sb_copy_data(char *orig, char *copy)
	return rc;
}

static int selinux_sb_remount(struct super_block *sb, void *data)
static int selinux_sb_remount(struct super_block *sb,
			      struct security_mnt_opts *opts)
{
	int rc, i, *flags;
	struct security_mnt_opts opts;
	char *secdata, **mount_options;
	int i, *flags;
	char **mount_options;
	struct superblock_security_struct *sbsec = sb->s_security;

	if (!(sbsec->flags & SE_SBINITIALIZED))
		return 0;

	if (!data)
		return 0;

	if (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)
		return 0;

	security_init_mnt_opts(&opts);
	secdata = alloc_secdata();
	if (!secdata)
		return -ENOMEM;
	rc = selinux_sb_copy_data(data, secdata);
	if (rc)
		goto out_free_secdata;

	rc = selinux_parse_opts_str(secdata, &opts);
	if (rc)
		goto out_free_secdata;

	mount_options = opts.mnt_opts;
	flags = opts.mnt_opts_flags;
	mount_options = opts->mnt_opts;
	flags = opts->mnt_opts_flags;

	for (i = 0; i < opts.num_mnt_opts; i++) {
	for (i = 0; i < opts->num_mnt_opts; i++) {
		u32 sid;
		int rc;

		if (flags[i] == SBLABEL_MNT)
			continue;
@@ -2855,9 +2838,8 @@ static int selinux_sb_remount(struct super_block *sb, void *data)
			pr_warn("SELinux: security_context_str_to_sid"
			       "(%s) failed for (dev %s, type %s) errno=%d\n",
			       mount_options[i], sb->s_id, sb->s_type->name, rc);
			goto out_free_opts;
			return rc;
		}
		rc = -EINVAL;
		switch (flags[i]) {
		case FSCONTEXT_MNT:
			if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid, sid))
@@ -2880,21 +2862,16 @@ static int selinux_sb_remount(struct super_block *sb, void *data)
				goto out_bad_option;
			break;
		default:
			goto out_free_opts;
			return -EINVAL;
		}
	}
	return 0;

	rc = 0;
out_free_opts:
	security_free_mnt_opts(&opts);
out_free_secdata:
	free_secdata(secdata);
	return rc;
out_bad_option:
	pr_warn("SELinux: unable to change security options "
	       "during remount (dev %s, type=%s)\n", sb->s_id,
	       sb->s_type->name);
	goto out_free_opts;
	return -EINVAL;
}

static int selinux_sb_kern_mount(struct super_block *sb, int flags,