Commit c039bc3c authored by Al Viro's avatar Al Viro

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
...@@ -2299,6 +2299,7 @@ static int do_remount(struct path *path, int ms_flags, int sb_flags, ...@@ -2299,6 +2299,7 @@ static int do_remount(struct path *path, int ms_flags, int sb_flags,
int err; int err;
struct super_block *sb = path->mnt->mnt_sb; struct super_block *sb = path->mnt->mnt_sb;
struct mount *mnt = real_mount(path->mnt); struct mount *mnt = real_mount(path->mnt);
struct security_mnt_opts opts;
if (!check_mnt(mnt)) if (!check_mnt(mnt))
return -EINVAL; return -EINVAL;
...@@ -2309,7 +2310,23 @@ static int do_remount(struct path *path, int ms_flags, int sb_flags, ...@@ -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)) if (!can_change_locked_flags(mnt, mnt_flags))
return -EPERM; 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) if (err)
return err; return err;
......
...@@ -1462,7 +1462,8 @@ union security_list_options { ...@@ -1462,7 +1462,8 @@ union security_list_options {
int (*sb_alloc_security)(struct super_block *sb); int (*sb_alloc_security)(struct super_block *sb);
void (*sb_free_security)(struct super_block *sb); void (*sb_free_security)(struct super_block *sb);
int (*sb_copy_data)(char *orig, char *copy); 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, int (*sb_kern_mount)(struct super_block *sb, int flags,
struct security_mnt_opts *opts); struct security_mnt_opts *opts);
int (*sb_show_options)(struct seq_file *m, struct super_block *sb); int (*sb_show_options)(struct seq_file *m, struct super_block *sb);
......
...@@ -249,7 +249,7 @@ void security_bprm_committed_creds(struct linux_binprm *bprm); ...@@ -249,7 +249,7 @@ void security_bprm_committed_creds(struct linux_binprm *bprm);
int security_sb_alloc(struct super_block *sb); int security_sb_alloc(struct super_block *sb);
void security_sb_free(struct super_block *sb); void security_sb_free(struct super_block *sb);
int security_sb_copy_data(char *orig, char *copy); 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, int security_sb_kern_mount(struct super_block *sb, int flags,
struct security_mnt_opts *opts); struct security_mnt_opts *opts);
int security_sb_show_options(struct seq_file *m, struct super_block *sb); 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) ...@@ -561,7 +561,8 @@ static inline int security_sb_copy_data(char *orig, char *copy)
return 0; 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; return 0;
} }
......
...@@ -390,9 +390,10 @@ int security_sb_copy_data(char *orig, char *copy) ...@@ -390,9 +390,10 @@ int security_sb_copy_data(char *orig, char *copy)
} }
EXPORT_SYMBOL(security_sb_copy_data); 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, int security_sb_kern_mount(struct super_block *sb, int flags,
......
...@@ -2812,39 +2812,22 @@ static int selinux_sb_copy_data(char *orig, char *copy) ...@@ -2812,39 +2812,22 @@ static int selinux_sb_copy_data(char *orig, char *copy)
return rc; 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; int i, *flags;
struct security_mnt_opts opts; char **mount_options;
char *secdata, **mount_options;
struct superblock_security_struct *sbsec = sb->s_security; struct superblock_security_struct *sbsec = sb->s_security;
if (!(sbsec->flags & SE_SBINITIALIZED)) if (!(sbsec->flags & SE_SBINITIALIZED))
return 0; return 0;
if (!data) mount_options = opts->mnt_opts;
return 0; flags = opts->mnt_opts_flags;
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; for (i = 0; i < opts->num_mnt_opts; i++) {
flags = opts.mnt_opts_flags;
for (i = 0; i < opts.num_mnt_opts; i++) {
u32 sid; u32 sid;
int rc;
if (flags[i] == SBLABEL_MNT) if (flags[i] == SBLABEL_MNT)
continue; continue;
...@@ -2855,9 +2838,8 @@ static int selinux_sb_remount(struct super_block *sb, void *data) ...@@ -2855,9 +2838,8 @@ static int selinux_sb_remount(struct super_block *sb, void *data)
pr_warn("SELinux: security_context_str_to_sid" pr_warn("SELinux: security_context_str_to_sid"
"(%s) failed for (dev %s, type %s) errno=%d\n", "(%s) failed for (dev %s, type %s) errno=%d\n",
mount_options[i], sb->s_id, sb->s_type->name, rc); mount_options[i], sb->s_id, sb->s_type->name, rc);
goto out_free_opts; return rc;
} }
rc = -EINVAL;
switch (flags[i]) { switch (flags[i]) {
case FSCONTEXT_MNT: case FSCONTEXT_MNT:
if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid, sid)) if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid, sid))
...@@ -2880,21 +2862,16 @@ static int selinux_sb_remount(struct super_block *sb, void *data) ...@@ -2880,21 +2862,16 @@ static int selinux_sb_remount(struct super_block *sb, void *data)
goto out_bad_option; goto out_bad_option;
break; break;
default: 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: out_bad_option:
pr_warn("SELinux: unable to change security options " pr_warn("SELinux: unable to change security options "
"during remount (dev %s, type=%s)\n", sb->s_id, "during remount (dev %s, type=%s)\n", sb->s_id,
sb->s_type->name); sb->s_type->name);
goto out_free_opts; return -EINVAL;
} }
static int selinux_sb_kern_mount(struct super_block *sb, int flags, static int selinux_sb_kern_mount(struct super_block *sb, int flags,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment