aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Paris <eparis@redhat.com>2011-03-03 16:09:14 -0500
committerEric Paris <eparis@redhat.com>2011-03-03 16:12:27 -0500
commitff36fe2c845cab2102e4826c1ffa0a6ebf487c65 (patch)
treed61f4c65bc51e6455f0cb5a3d03fab41d0f83169
parent2ad18bdf3b8f84c85c7da7e4de365f7c5701fb3f (diff)
LSM: Pass -o remount options to the LSM
The VFS mount code passes the mount options to the LSM. The LSM will remove options it understands from the data and the VFS will then pass the remaining options onto the underlying filesystem. This is how options like the SELinux context= work. The problem comes in that -o remount never calls into LSM code. So if you include an LSM specific option it will get passed to the filesystem and will cause the remount to fail. An example of where this is a problem is the 'seclabel' option. The SELinux LSM hook will print this word in /proc/mounts if the filesystem is being labeled using xattrs. If you pass this word on mount it will be silently stripped and ignored. But if you pass this word on remount the LSM never gets called and it will be passed to the FS. The FS doesn't know what seclabel means and thus should fail the mount. For example an ext3 fs mounted over loop # mount -o loop /tmp/fs /mnt/tmp # cat /proc/mounts | grep /mnt/tmp /dev/loop0 /mnt/tmp ext3 rw,seclabel,relatime,errors=continue,barrier=0,data=ordered 0 0 # mount -o remount /mnt/tmp mount: /mnt/tmp not mounted already, or bad option # dmesg EXT3-fs (loop0): error: unrecognized mount option "seclabel" or missing value This patch passes the remount mount options to an new LSM hook. Signed-off-by: Eric Paris <eparis@redhat.com> Reviewed-by: James Morris <jmorris@namei.org>
-rw-r--r--fs/namespace.c4
-rw-r--r--include/linux/security.h13
-rw-r--r--security/capability.c6
-rw-r--r--security/security.c5
4 files changed, 28 insertions, 0 deletions
diff --git a/fs/namespace.c b/fs/namespace.c
index 3ddfd9046c44..1b3f2ac59c5e 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -1800,6 +1800,10 @@ static int do_remount(struct path *path, int flags, int mnt_flags,
1800 if (path->dentry != path->mnt->mnt_root) 1800 if (path->dentry != path->mnt->mnt_root)
1801 return -EINVAL; 1801 return -EINVAL;
1802 1802
1803 err = security_sb_remount(sb, data);
1804 if (err)
1805 return err;
1806
1803 down_write(&sb->s_umount); 1807 down_write(&sb->s_umount);
1804 if (flags & MS_BIND) 1808 if (flags & MS_BIND)
1805 err = change_mount_flags(path->mnt, flags); 1809 err = change_mount_flags(path->mnt, flags);
diff --git a/include/linux/security.h b/include/linux/security.h
index 14167f2eb35a..d11ac43ecc49 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -268,6 +268,12 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
268 * @orig the original mount data copied from userspace. 268 * @orig the original mount data copied from userspace.
269 * @copy copied data which will be passed to the security module. 269 * @copy copied data which will be passed to the security module.
270 * Returns 0 if the copy was successful. 270 * Returns 0 if the copy was successful.
271 * @sb_remount:
272 * Extracts security system specifc mount options and verifys no changes
273 * are being made to those options.
274 * @sb superblock being remounted
275 * @data contains the filesystem-specific data.
276 * Return 0 if permission is granted.
271 * @sb_umount: 277 * @sb_umount:
272 * Check permission before the @mnt file system is unmounted. 278 * Check permission before the @mnt file system is unmounted.
273 * @mnt contains the mounted file system. 279 * @mnt contains the mounted file system.
@@ -1394,6 +1400,7 @@ struct security_operations {
1394 int (*sb_alloc_security) (struct super_block *sb); 1400 int (*sb_alloc_security) (struct super_block *sb);
1395 void (*sb_free_security) (struct super_block *sb); 1401 void (*sb_free_security) (struct super_block *sb);
1396 int (*sb_copy_data) (char *orig, char *copy); 1402 int (*sb_copy_data) (char *orig, char *copy);
1403 int (*sb_remount) (struct super_block *sb, void *data);
1397 int (*sb_kern_mount) (struct super_block *sb, int flags, void *data); 1404 int (*sb_kern_mount) (struct super_block *sb, int flags, void *data);
1398 int (*sb_show_options) (struct seq_file *m, struct super_block *sb); 1405 int (*sb_show_options) (struct seq_file *m, struct super_block *sb);
1399 int (*sb_statfs) (struct dentry *dentry); 1406 int (*sb_statfs) (struct dentry *dentry);
@@ -1676,6 +1683,7 @@ int security_bprm_secureexec(struct linux_binprm *bprm);
1676int security_sb_alloc(struct super_block *sb); 1683int security_sb_alloc(struct super_block *sb);
1677void security_sb_free(struct super_block *sb); 1684void security_sb_free(struct super_block *sb);
1678int security_sb_copy_data(char *orig, char *copy); 1685int security_sb_copy_data(char *orig, char *copy);
1686int security_sb_remount(struct super_block *sb, void *data);
1679int security_sb_kern_mount(struct super_block *sb, int flags, void *data); 1687int security_sb_kern_mount(struct super_block *sb, int flags, void *data);
1680int security_sb_show_options(struct seq_file *m, struct super_block *sb); 1688int security_sb_show_options(struct seq_file *m, struct super_block *sb);
1681int security_sb_statfs(struct dentry *dentry); 1689int security_sb_statfs(struct dentry *dentry);
@@ -1955,6 +1963,11 @@ static inline int security_sb_copy_data(char *orig, char *copy)
1955 return 0; 1963 return 0;
1956} 1964}
1957 1965
1966static inline int security_sb_remount(struct super_block *sb, void *data)
1967{
1968 return 0;
1969}
1970
1958static inline int security_sb_kern_mount(struct super_block *sb, int flags, void *data) 1971static inline int security_sb_kern_mount(struct super_block *sb, int flags, void *data)
1959{ 1972{
1960 return 0; 1973 return 0;
diff --git a/security/capability.c b/security/capability.c
index 85b67c8632df..ab3d807accc3 100644
--- a/security/capability.c
+++ b/security/capability.c
@@ -54,6 +54,11 @@ static int cap_sb_copy_data(char *orig, char *copy)
54 return 0; 54 return 0;
55} 55}
56 56
57static int cap_sb_remount(struct super_block *sb, void *data)
58{
59 return 0;
60}
61
57static int cap_sb_kern_mount(struct super_block *sb, int flags, void *data) 62static int cap_sb_kern_mount(struct super_block *sb, int flags, void *data)
58{ 63{
59 return 0; 64 return 0;
@@ -887,6 +892,7 @@ void __init security_fixup_ops(struct security_operations *ops)
887 set_to_cap_if_null(ops, sb_alloc_security); 892 set_to_cap_if_null(ops, sb_alloc_security);
888 set_to_cap_if_null(ops, sb_free_security); 893 set_to_cap_if_null(ops, sb_free_security);
889 set_to_cap_if_null(ops, sb_copy_data); 894 set_to_cap_if_null(ops, sb_copy_data);
895 set_to_cap_if_null(ops, sb_remount);
890 set_to_cap_if_null(ops, sb_kern_mount); 896 set_to_cap_if_null(ops, sb_kern_mount);
891 set_to_cap_if_null(ops, sb_show_options); 897 set_to_cap_if_null(ops, sb_show_options);
892 set_to_cap_if_null(ops, sb_statfs); 898 set_to_cap_if_null(ops, sb_statfs);
diff --git a/security/security.c b/security/security.c
index 8f28685ee0d9..b1d6134548bc 100644
--- a/security/security.c
+++ b/security/security.c
@@ -267,6 +267,11 @@ int security_sb_copy_data(char *orig, char *copy)
267} 267}
268EXPORT_SYMBOL(security_sb_copy_data); 268EXPORT_SYMBOL(security_sb_copy_data);
269 269
270int security_sb_remount(struct super_block *sb, void *data)
271{
272 return security_ops->sb_remount(sb, data);
273}
274
270int security_sb_kern_mount(struct super_block *sb, int flags, void *data) 275int security_sb_kern_mount(struct super_block *sb, int flags, void *data)
271{ 276{
272 return security_ops->sb_kern_mount(sb, flags, data); 277 return security_ops->sb_kern_mount(sb, flags, data);