Commit 505b050f authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'mount.part1' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs

Pull vfs mount API prep from Al Viro:
 "Mount API prereqs.

  Mostly that's LSM mount options cleanups. There are several minor
  fixes in there, but nothing earth-shattering (leaks on failure exits,
  mostly)"

* 'mount.part1' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (27 commits)
  mount_fs: suppress MAC on MS_SUBMOUNT as well as MS_KERNMOUNT
  smack: rewrite smack_sb_eat_lsm_opts()
  smack: get rid of match_token()
  smack: take the guts of smack_parse_opts_str() into a new helper
  LSM: new method: ->sb_add_mnt_opt()
  selinux: rewrite selinux_sb_eat_lsm_opts()
  selinux: regularize Opt_... names a bit
  selinux: switch away from match_token()
  selinux: new helper - selinux_add_opt()
  LSM: bury struct security_mnt_opts
  smack: switch to private smack_mnt_opts
  selinux: switch to private struct selinux_mnt_opts
  LSM: hide struct security_mnt_opts from any generic code
  selinux: kill selinux_sb_get_mnt_opts()
  LSM: turn sb_eat_lsm_opts() into a method
  nfs_remount(): don't leak, don't ignore LSM options quietly
  btrfs: sanitize security_mnt_opts use
  selinux; don't open-code a loop in sb_finish_set_opts()
  LSM: split ->sb_set_mnt_opts() out of ->sb_kern_mount()
  new helper: security_sb_eat_lsm_opts()
  ...
parents 9b286efe 718c4303
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <linux/of_fdt.h> #include <linux/of_fdt.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/cache.h> #include <linux/cache.h>
#include <uapi/linux/mount.h>
#include <asm/sections.h> #include <asm/sections.h>
#include <asm/arcregs.h> #include <asm/arcregs.h>
#include <asm/tlb.h> #include <asm/tlb.h>
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include <linux/root_dev.h> #include <linux/root_dev.h>
#include <linux/screen_info.h> #include <linux/screen_info.h>
#include <linux/memblock.h> #include <linux/memblock.h>
#include <uapi/linux/mount.h>
#include <asm/setup.h> #include <asm/setup.h>
#include <asm/system_info.h> #include <asm/system_info.h>
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_fdt.h> #include <linux/of_fdt.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <uapi/linux/mount.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/page.h> #include <asm/page.h>
#include <asm/elf.h> #include <asm/elf.h>
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include <linux/kdebug.h> #include <linux/kdebug.h>
#include <linux/export.h> #include <linux/export.h>
#include <linux/start_kernel.h> #include <linux/start_kernel.h>
#include <uapi/linux/mount.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/processor.h> #include <asm/processor.h>
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/start_kernel.h> #include <linux/start_kernel.h>
#include <linux/memblock.h> #include <linux/memblock.h>
#include <uapi/linux/mount.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/processor.h> #include <asm/processor.h>
......
...@@ -50,6 +50,7 @@ ...@@ -50,6 +50,7 @@
#include <linux/kvm_para.h> #include <linux/kvm_para.h>
#include <linux/dma-contiguous.h> #include <linux/dma-contiguous.h>
#include <xen/xen.h> #include <xen/xen.h>
#include <uapi/linux/mount.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/kernel.h> #include <linux/kernel.h>
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/kthread.h> #include <linux/kthread.h>
#include <uapi/linux/mount.h>
#include "base.h" #include "base.h"
static struct task_struct *thread; static struct task_struct *thread;
......
...@@ -1144,9 +1144,6 @@ struct btrfs_fs_info { ...@@ -1144,9 +1144,6 @@ struct btrfs_fs_info {
struct mutex unused_bg_unpin_mutex; struct mutex unused_bg_unpin_mutex;
struct mutex delete_unused_bgs_mutex; struct mutex delete_unused_bgs_mutex;
/* For btrfs to record security options */
struct security_mnt_opts security_opts;
/* /*
* Chunks that can't be freed yet (under a trim/discard operation) * Chunks that can't be freed yet (under a trim/discard operation)
* and will be latter freed. Protected by fs_info->chunk_mutex. * and will be latter freed. Protected by fs_info->chunk_mutex.
...@@ -3021,7 +3018,6 @@ static inline void free_fs_info(struct btrfs_fs_info *fs_info) ...@@ -3021,7 +3018,6 @@ static inline void free_fs_info(struct btrfs_fs_info *fs_info)
kfree(fs_info->free_space_root); kfree(fs_info->free_space_root);
kfree(fs_info->super_copy); kfree(fs_info->super_copy);
kfree(fs_info->super_for_commit); kfree(fs_info->super_for_commit);
security_free_mnt_opts(&fs_info->security_opts);
kvfree(fs_info); kvfree(fs_info);
} }
......
...@@ -1458,56 +1458,6 @@ static struct dentry *mount_subvol(const char *subvol_name, u64 subvol_objectid, ...@@ -1458,56 +1458,6 @@ static struct dentry *mount_subvol(const char *subvol_name, u64 subvol_objectid,
return root; return root;
} }
static int parse_security_options(char *orig_opts,
struct security_mnt_opts *sec_opts)
{
char *secdata = NULL;
int ret = 0;
secdata = alloc_secdata();
if (!secdata)
return -ENOMEM;
ret = security_sb_copy_data(orig_opts, secdata);
if (ret) {
free_secdata(secdata);
return ret;
}
ret = security_sb_parse_opts_str(secdata, sec_opts);
free_secdata(secdata);
return ret;
}
static int setup_security_options(struct btrfs_fs_info *fs_info,
struct super_block *sb,
struct security_mnt_opts *sec_opts)
{
int ret = 0;
/*
* Call security_sb_set_mnt_opts() to check whether new sec_opts
* is valid.
*/
ret = security_sb_set_mnt_opts(sb, sec_opts, 0, NULL);
if (ret)
return ret;
#ifdef CONFIG_SECURITY
if (!fs_info->security_opts.num_mnt_opts) {
/* first time security setup, copy sec_opts to fs_info */
memcpy(&fs_info->security_opts, sec_opts, sizeof(*sec_opts));
} else {
/*
* Since SELinux (the only one supporting security_mnt_opts)
* does NOT support changing context during remount/mount of
* the same sb, this must be the same or part of the same
* security options, just free it.
*/
security_free_mnt_opts(sec_opts);
}
#endif
return ret;
}
/* /*
* Find a superblock for the given device / mount point. * Find a superblock for the given device / mount point.
* *
...@@ -1522,16 +1472,15 @@ static struct dentry *btrfs_mount_root(struct file_system_type *fs_type, ...@@ -1522,16 +1472,15 @@ static struct dentry *btrfs_mount_root(struct file_system_type *fs_type,
struct btrfs_device *device = NULL; struct btrfs_device *device = NULL;
struct btrfs_fs_devices *fs_devices = NULL; struct btrfs_fs_devices *fs_devices = NULL;
struct btrfs_fs_info *fs_info = NULL; struct btrfs_fs_info *fs_info = NULL;
struct security_mnt_opts new_sec_opts; void *new_sec_opts = NULL;
fmode_t mode = FMODE_READ; fmode_t mode = FMODE_READ;
int error = 0; int error = 0;
if (!(flags & SB_RDONLY)) if (!(flags & SB_RDONLY))
mode |= FMODE_WRITE; mode |= FMODE_WRITE;
security_init_mnt_opts(&new_sec_opts);
if (data) { if (data) {
error = parse_security_options(data, &new_sec_opts); error = security_sb_eat_lsm_opts(data, &new_sec_opts);
if (error) if (error)
return ERR_PTR(error); return ERR_PTR(error);
} }
...@@ -1550,7 +1499,6 @@ static struct dentry *btrfs_mount_root(struct file_system_type *fs_type, ...@@ -1550,7 +1499,6 @@ static struct dentry *btrfs_mount_root(struct file_system_type *fs_type,
fs_info->super_copy = kzalloc(BTRFS_SUPER_INFO_SIZE, GFP_KERNEL); fs_info->super_copy = kzalloc(BTRFS_SUPER_INFO_SIZE, GFP_KERNEL);
fs_info->super_for_commit = kzalloc(BTRFS_SUPER_INFO_SIZE, GFP_KERNEL); fs_info->super_for_commit = kzalloc(BTRFS_SUPER_INFO_SIZE, GFP_KERNEL);
security_init_mnt_opts(&fs_info->security_opts);
if (!fs_info->super_copy || !fs_info->super_for_commit) { if (!fs_info->super_copy || !fs_info->super_for_commit) {
error = -ENOMEM; error = -ENOMEM;
goto error_fs_info; goto error_fs_info;
...@@ -1601,16 +1549,12 @@ static struct dentry *btrfs_mount_root(struct file_system_type *fs_type, ...@@ -1601,16 +1549,12 @@ static struct dentry *btrfs_mount_root(struct file_system_type *fs_type,
btrfs_sb(s)->bdev_holder = fs_type; btrfs_sb(s)->bdev_holder = fs_type;
error = btrfs_fill_super(s, fs_devices, data); error = btrfs_fill_super(s, fs_devices, data);
} }
if (!error)
error = security_sb_set_mnt_opts(s, new_sec_opts, 0, NULL);
security_free_mnt_opts(&new_sec_opts);
if (error) { if (error) {
deactivate_locked_super(s); deactivate_locked_super(s);
goto error_sec_opts; return ERR_PTR(error);
}
fs_info = btrfs_sb(s);
error = setup_security_options(fs_info, s, &new_sec_opts);
if (error) {
deactivate_locked_super(s);
goto error_sec_opts;
} }
return dget(s->s_root); return dget(s->s_root);
...@@ -1779,19 +1723,15 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data) ...@@ -1779,19 +1723,15 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data)
btrfs_remount_prepare(fs_info); btrfs_remount_prepare(fs_info);
if (data) { if (data) {
struct security_mnt_opts new_sec_opts; void *new_sec_opts = NULL;
security_init_mnt_opts(&new_sec_opts); ret = security_sb_eat_lsm_opts(data, &new_sec_opts);
ret = parse_security_options(data, &new_sec_opts); if (!ret)
if (ret) ret = security_sb_remount(sb, new_sec_opts);
goto restore;
ret = setup_security_options(fs_info, sb,
&new_sec_opts);
if (ret) {
security_free_mnt_opts(&new_sec_opts); security_free_mnt_opts(&new_sec_opts);
if (ret)
goto restore; goto restore;
} }
}
ret = btrfs_parse_options(fs_info, data, *flags); ret = btrfs_parse_options(fs_info, data, *flags);
if (ret) if (ret)
......
...@@ -705,21 +705,18 @@ static int exofs_read_lookup_dev_table(struct exofs_sb_info *sbi, ...@@ -705,21 +705,18 @@ static int exofs_read_lookup_dev_table(struct exofs_sb_info *sbi,
/* /*
* Read the superblock from the OSD and fill in the fields * Read the superblock from the OSD and fill in the fields
*/ */
static int exofs_fill_super(struct super_block *sb, void *data, int silent) static int exofs_fill_super(struct super_block *sb,
struct exofs_mountopt *opts,
struct exofs_sb_info *sbi,
int silent)
{ {
struct inode *root; struct inode *root;
struct exofs_mountopt *opts = data;
struct exofs_sb_info *sbi; /*extended info */
struct osd_dev *od; /* Master device */ struct osd_dev *od; /* Master device */
struct exofs_fscb fscb; /*on-disk superblock info */ struct exofs_fscb fscb; /*on-disk superblock info */
struct ore_comp comp; struct ore_comp comp;
unsigned table_count; unsigned table_count;
int ret; int ret;
sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
if (!sbi)
return -ENOMEM;
/* use mount options to fill superblock */ /* use mount options to fill superblock */
if (opts->is_osdname) { if (opts->is_osdname) {
struct osd_dev_info odi = {.systemid_len = 0}; struct osd_dev_info odi = {.systemid_len = 0};
...@@ -863,7 +860,9 @@ static struct dentry *exofs_mount(struct file_system_type *type, ...@@ -863,7 +860,9 @@ static struct dentry *exofs_mount(struct file_system_type *type,
int flags, const char *dev_name, int flags, const char *dev_name,
void *data) void *data)
{ {
struct super_block *s;
struct exofs_mountopt opts; struct exofs_mountopt opts;
struct exofs_sb_info *sbi;
int ret; int ret;
ret = parse_options(data, &opts); ret = parse_options(data, &opts);
...@@ -872,9 +871,31 @@ static struct dentry *exofs_mount(struct file_system_type *type, ...@@ -872,9 +871,31 @@ static struct dentry *exofs_mount(struct file_system_type *type,
return ERR_PTR(ret); return ERR_PTR(ret);
} }
sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
if (!sbi) {
kfree(opts.dev_name);
return ERR_PTR(-ENOMEM);
}
s = sget(type, NULL, set_anon_super, flags, NULL);
if (IS_ERR(s)) {
kfree(opts.dev_name);
kfree(sbi);
return ERR_CAST(s);
}
if (!opts.dev_name) if (!opts.dev_name)
opts.dev_name = dev_name; opts.dev_name = dev_name;
return mount_nodev(type, flags, &opts, exofs_fill_super);
ret = exofs_fill_super(s, &opts, sbi, flags & SB_SILENT ? 1 : 0);
if (ret) {
deactivate_locked_super(s);
return ERR_PTR(ret);
}
s->s_flags |= SB_ACTIVE;
return dget(s->s_root);
} }
/* /*
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <linux/memblock.h> #include <linux/memblock.h>
#include <linux/task_work.h> #include <linux/task_work.h>
#include <linux/sched/task.h> #include <linux/sched/task.h>
#include <uapi/linux/mount.h>
#include "pnode.h" #include "pnode.h"
#include "internal.h" #include "internal.h"
...@@ -245,13 +246,9 @@ static struct mount *alloc_vfsmnt(const char *name) ...@@ -245,13 +246,9 @@ static struct mount *alloc_vfsmnt(const char *name)
* mnt_want/drop_write() will _keep_ the filesystem * mnt_want/drop_write() will _keep_ the filesystem
* r/w. * r/w.
*/ */
int __mnt_is_readonly(struct vfsmount *mnt) bool __mnt_is_readonly(struct vfsmount *mnt)
{ {
if (mnt->mnt_flags & MNT_READONLY) return (mnt->mnt_flags & MNT_READONLY) || sb_rdonly(mnt->mnt_sb);
return 1;
if (sb_rdonly(mnt->mnt_sb))
return 1;
return 0;
} }
EXPORT_SYMBOL_GPL(__mnt_is_readonly); EXPORT_SYMBOL_GPL(__mnt_is_readonly);
...@@ -507,11 +504,12 @@ static int mnt_make_readonly(struct mount *mnt) ...@@ -507,11 +504,12 @@ static int mnt_make_readonly(struct mount *mnt)
return ret; return ret;
} }
static void __mnt_unmake_readonly(struct mount *mnt) static int __mnt_unmake_readonly(struct mount *mnt)
{ {
lock_mount_hash(); lock_mount_hash();
mnt->mnt.mnt_flags &= ~MNT_READONLY; mnt->mnt.mnt_flags &= ~MNT_READONLY;
unlock_mount_hash(); unlock_mount_hash();
return 0;
} }
int sb_prepare_remount_readonly(struct super_block *sb) int sb_prepare_remount_readonly(struct super_block *sb)
...@@ -2215,21 +2213,91 @@ static int do_loopback(struct path *path, const char *old_name, ...@@ -2215,21 +2213,91 @@ static int do_loopback(struct path *path, const char *old_name,
return err; return err;
} }
static int change_mount_flags(struct vfsmount *mnt, int ms_flags) /*
* Don't allow locked mount flags to be cleared.
*
* No locks need to be held here while testing the various MNT_LOCK
* flags because those flags can never be cleared once they are set.
*/
static bool can_change_locked_flags(struct mount *mnt, unsigned int mnt_flags)
{
unsigned int fl = mnt->mnt.mnt_flags;
if ((fl & MNT_LOCK_READONLY) &&
!(mnt_flags & MNT_READONLY))
return false;
if ((fl & MNT_LOCK_NODEV) &&
!(mnt_flags & MNT_NODEV))
return false;
if ((fl & MNT_LOCK_NOSUID) &&
!(mnt_flags & MNT_NOSUID))
return false;
if ((fl & MNT_LOCK_NOEXEC) &&
!(mnt_flags & MNT_NOEXEC))
return false;
if ((fl & MNT_LOCK_ATIME) &&
((fl & MNT_ATIME_MASK) != (mnt_flags & MNT_ATIME_MASK)))
return false;
return true;
}
static int change_mount_ro_state(struct mount *mnt, unsigned int mnt_flags)
{ {
int error = 0; bool readonly_request = (mnt_flags & MNT_READONLY);
int readonly_request = 0;
if (ms_flags & MS_RDONLY) if (readonly_request == __mnt_is_readonly(&mnt->mnt))
readonly_request = 1;
if (readonly_request == __mnt_is_readonly(mnt))
return 0; return 0;
if (readonly_request) if (readonly_request)
error = mnt_make_readonly(real_mount(mnt)); return mnt_make_readonly(mnt);
else
__mnt_unmake_readonly(real_mount(mnt)); return __mnt_unmake_readonly(mnt);
return error; }
/*
* Update the user-settable attributes on a mount. The caller must hold
* sb->s_umount for writing.
*/
static void set_mount_attributes(struct mount *mnt, unsigned int mnt_flags)
{
lock_mount_hash();
mnt_flags |= mnt->mnt.mnt_flags & ~MNT_USER_SETTABLE_MASK;
mnt->mnt.mnt_flags = mnt_flags;
touch_mnt_namespace(mnt->mnt_ns);
unlock_mount_hash();
}
/*
* Handle reconfiguration of the mountpoint only without alteration of the
* superblock it refers to. This is triggered by specifying MS_REMOUNT|MS_BIND
* to mount(2).
*/
static int do_reconfigure_mnt(struct path *path, unsigned int mnt_flags)
{
struct super_block *sb = path->mnt->mnt_sb;
struct mount *mnt = real_mount(path->mnt);
int ret;
if (!check_mnt(mnt))
return -EINVAL;
if (path->dentry != mnt->mnt.mnt_root)
return -EINVAL;
if (!can_change_locked_flags(mnt, mnt_flags))
return -EPERM;
down_write(&sb->s_umount);
ret = change_mount_ro_state(mnt, mnt_flags);
if (ret == 0)
set_mount_attributes(mnt, mnt_flags);
up_write(&sb->s_umount);
return ret;
} }
/* /*
...@@ -2243,6 +2311,7 @@ static int do_remount(struct path *path, int ms_flags, int sb_flags, ...@@ -2243,6 +2311,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);
void *sec_opts = NULL;
if (!check_mnt(mnt)) if (!check_mnt(mnt))
return -EINVAL; return -EINVAL;
...@@ -2250,50 +2319,25 @@ static int do_remount(struct path *path, int ms_flags, int sb_flags, ...@@ -2250,50 +2319,25 @@ static int do_remount(struct path *path, int ms_flags, int sb_flags,
if (path->dentry != path->mnt->mnt_root) if (path->dentry != path->mnt->mnt_root)
return -EINVAL; return -EINVAL;
/* Don't allow changing of locked mnt flags. if (!can_change_locked_flags(mnt, mnt_flags))
*
* No locks need to be held here while testing the various
* MNT_LOCK flags because those flags can never be cleared
* once they are set.
*/
if ((mnt->mnt.mnt_flags & MNT_LOCK_READONLY) &&
!(mnt_flags & MNT_READONLY)) {
return -EPERM;
}
if ((mnt->mnt.mnt_flags & MNT_LOCK_NODEV) &&
!(mnt_flags & MNT_NODEV)) {
return -EPERM;
}
if ((mnt->mnt.mnt_flags & MNT_LOCK_NOSUID) &&
!(mnt_flags & MNT_NOSUID)) {
return -EPERM;
}
if ((mnt->mnt.mnt_flags & MNT_LOCK_NOEXEC) &&
!(mnt_flags & MNT_NOEXEC)) {
return -EPERM; return -EPERM;
}
if ((mnt->mnt.mnt_flags & MNT_LOCK_ATIME) &&
((mnt->mnt.mnt_flags & MNT_ATIME_MASK) != (mnt_flags & MNT_ATIME_MASK))) {
return -EPERM;
}
err = security_sb_remount(sb, data); if (data && !(sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)) {
err = security_sb_eat_lsm_opts(data, &sec_opts);
if (err)
return err;
}
err = security_sb_remount(sb, sec_opts);
security_free_mnt_opts(&sec_opts);
if (err) if (err)
return err; return err;
down_write(&sb->s_umount); down_write(&sb->s_umount);
if (ms_flags & MS_BIND)
err = change_mount_flags(path->mnt, ms_flags);
else if (!ns_capable(sb->s_user_ns, CAP_SYS_ADMIN))
err = -EPERM; err = -EPERM;
else if (ns_capable(sb->s_user_ns, CAP_SYS_ADMIN)) {
err = do_remount_sb(sb, sb_flags, data, 0); err = do_remount_sb(sb, sb_flags, data, 0);
if (!err) { if (!err)
lock_mount_hash(); set_mount_attributes(mnt, mnt_flags);
mnt_flags |= mnt->mnt.mnt_flags & ~MNT_USER_SETTABLE_MASK;
mnt->mnt.mnt_flags = mnt_flags;
touch_mnt_namespace(mnt->mnt_ns);
unlock_mount_hash();
} }
up_write(&sb->s_umount); up_write(&sb->s_umount);
return err; return err;
...@@ -2788,7 +2832,9 @@ long do_mount(const char *dev_name, const char __user *dir_name, ...@@ -2788,7 +2832,9 @@ long do_mount(const char *dev_name, const char __user *dir_name,
SB_LAZYTIME | SB_LAZYTIME |
SB_I_VERSION); SB_I_VERSION);
if (flags & MS_REMOUNT) if ((flags & (MS_REMOUNT | MS_BIND)) == (MS_REMOUNT | MS_BIND))
retval = do_reconfigure_mnt(&path, mnt_flags);
else if (flags & MS_REMOUNT)
retval = do_remount(&path, flags, sb_flags, mnt_flags, retval = do_remount(&path, flags, sb_flags, mnt_flags,
data_page); data_page);
else if (flags & MS_BIND) else if (flags & MS_BIND)
......
...@@ -123,7 +123,7 @@ struct nfs_parsed_mount_data { ...@@ -123,7 +123,7 @@ struct nfs_parsed_mount_data {
unsigned short protocol; unsigned short protocol;
} nfs_server; } nfs_server;
struct security_mnt_opts lsm_opts; void *lsm_opts;
struct net *net; struct net *net;
}; };
......
...@@ -929,7 +929,7 @@ static struct nfs_parsed_mount_data *nfs_alloc_parsed_mount_data(void) ...@@ -929,7 +929,7 @@ static struct nfs_parsed_mount_data *nfs_alloc_parsed_mount_data(void)
data->minorversion = 0; data->minorversion = 0;
data->need_mount = true; data->need_mount = true;
data->net = current->nsproxy->net_ns; data->net = current->nsproxy->net_ns;
security_init_mnt_opts(&data->lsm_opts); data->lsm_opts = NULL;
} }
return data; return data;
} }
...@@ -1206,7 +1206,7 @@ static int nfs_get_option_ul_bound(substring_t args[], unsigned long *option, ...@@ -1206,7 +1206,7 @@ static int nfs_get_option_ul_bound(substring_t args[], unsigned long *option,
static int nfs_parse_mount_options(char *raw, static int nfs_parse_mount_options(char *raw,
struct nfs_parsed_mount_data *mnt) struct nfs_parsed_mount_data *mnt)
{ {
char *p, *string, *secdata; char *p, *string;
int rc, sloppy = 0, invalid_option = 0; int rc, sloppy = 0, invalid_option = 0;
unsigned short protofamily = AF_UNSPEC; unsigned short protofamily = AF_UNSPEC;
unsigned short mountfamily = AF_UNSPEC; unsigned short mountfamily = AF_UNSPEC;
...@@ -1217,20 +1217,10 @@ static int nfs_parse_mount_options(char *raw, ...@@ -1217,20 +1217,10 @@ static int nfs_parse_mount_options(char *raw,
} }
dfprintk(MOUNT, "NFS: nfs mount opts='%s'\n", raw); dfprintk(MOUNT, "NFS: nfs mount opts='%s'\n", raw);
secdata = alloc_secdata(); rc = security_sb_eat_lsm_opts(raw, &mnt->lsm_opts);
if (!secdata)
goto out_nomem;
rc = security_sb_copy_data(raw, secdata);
if (rc)
goto out_security_failure;
rc = security_sb_parse_opts_str(secdata, &mnt->lsm_opts);
if (rc) if (rc)
goto out_security_failure; goto out_security_failure;
free_secdata(secdata);
while ((p = strsep(&raw, ",")) != NULL) { while ((p = strsep(&raw, ",")) != NULL) {
substring_t args[MAX_OPT_ARGS]; substring_t args[MAX_OPT_ARGS];
unsigned long option; unsigned long option;
...@@ -1682,7 +1672,6 @@ static int nfs_parse_mount_options(char *raw, ...@@ -1682,7 +1672,6 @@ static int nfs_parse_mount_options(char *raw,
printk(KERN_INFO "NFS: not enough memory to parse option\n"); printk(KERN_INFO "NFS: not enough memory to parse option\n");
return 0; return 0;
out_security_failure: out_security_failure:
free_secdata(secdata);
printk(KERN_INFO "NFS: security options invalid: %d\n", rc); printk(KERN_INFO "NFS: security options invalid: %d\n", rc);
return 0; return 0;
} }
...@@ -2081,14 +2070,9 @@ static int nfs23_validate_mount_data(void *options, ...@@ -2081,14 +2070,9 @@ static int nfs23_validate_mount_data(void *options,
if (data->context[0]){ if (data->context[0]){
#ifdef CONFIG_SECURITY_SELINUX #ifdef CONFIG_SECURITY_SELINUX
int rc; int rc;
char *opts_str = kmalloc(sizeof(data->context) + 8, GFP_KERNEL);
if (!opts_str)
return -ENOMEM;
strcpy(opts_str, "context=");
data->context[NFS_MAX_CONTEXT_LEN] = '\0'; data->context[NFS_MAX_CONTEXT_LEN] = '\0';
strcat(opts_str, &data->context[0]); rc = security_add_mnt_opt("context", data->context,
rc = security_sb_parse_opts_str(opts_str, &args->lsm_opts); strlen(data->context), &args->lsm_opts);
kfree(opts_str);
if (rc) if (rc)
return rc; return rc;
#else #else
...@@ -2271,7 +2255,7 @@ nfs_remount(struct super_block *sb, int *flags, char *raw_data) ...@@ -2271,7 +2255,7 @@ nfs_remount(struct super_block *sb, int *flags, char *raw_data)
options->version <= 6)))) options->version <= 6))))
return 0; return 0;
data = kzalloc(sizeof(*data), GFP_KERNEL); data = nfs_alloc_parsed_mount_data();
if (data == NULL) if (data == NULL)
return -ENOMEM; return -ENOMEM;
...@@ -2310,8 +2294,10 @@ nfs_remount(struct super_block *sb, int *flags, char *raw_data) ...@@ -2310,8 +2294,10 @@ nfs_remount(struct super_block *sb, int *flags, char *raw_data)
/* compare new mount options with old ones */ /* compare new mount options with old ones */
error = nfs_compare_remount_data(nfss, data); error = nfs_compare_remount_data(nfss, data);
if (!error)
error = security_sb_remount(sb, data->lsm_opts);
out: out:
kfree(data); nfs_free_parsed_mount_data(data);
return error; return error;
} }
EXPORT_SYMBOL_GPL(nfs_remount); EXPORT_SYMBOL_GPL(nfs_remount);
...@@ -2548,7 +2534,7 @@ int nfs_set_sb_security(struct super_block *s, struct dentry *mntroot, ...@@ -2548,7 +2534,7 @@ int nfs_set_sb_security(struct super_block *s, struct dentry *mntroot,
if (NFS_SB(s)->caps & NFS_CAP_SECURITY_LABEL) if (NFS_SB(s)->caps & NFS_CAP_SECURITY_LABEL)
kflags |= SECURITY_LSM_NATIVE_LABELS; kflags |= SECURITY_LSM_NATIVE_LABELS;
error = security_sb_set_mnt_opts(s, &mount_info->parsed->lsm_opts, error = security_sb_set_mnt_opts(s, mount_info->parsed->lsm_opts,
kflags, &kflags_out); kflags, &kflags_out);
if (error) if (error)
goto err; goto err;
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <linux/mount.h> #include <linux/mount.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/nsproxy.h> #include <linux/nsproxy.h>
#include <uapi/linux/mount.h>
#include "internal.h" #include "internal.h"
#include "pnode.h" #include "pnode.h"
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include <linux/fsnotify.h> #include <linux/fsnotify.h>
#include <linux/lockdep.h> #include <linux/lockdep.h>
#include <linux/user_namespace.h> #include <linux/user_namespace.h>
#include <uapi/linux/mount.h>
#include "internal.h" #include "internal.h"
static int thaw_super_locked(struct super_block *sb); static int thaw_super_locked(struct super_block *sb);
...@@ -1245,17 +1246,13 @@ mount_fs(struct file_system_type *type, int flags, const char *name, void *data) ...@@ -1245,17 +1246,13 @@ mount_fs(struct file_system_type *type, int flags, const char *name, void *data)
{ {
struct dentry *root; struct dentry *root;
struct super_block *sb; struct super_block *sb;
char *secdata = NULL;
int error = -ENOMEM; int error = -ENOMEM;
void *sec_opts = NULL;
if (data && !(type->fs_flags & FS_BINARY_MOUNTDATA)) { if (data && !(type->fs_flags & FS_BINARY_MOUNTDATA)) {
secdata = alloc_secdata(); error = security_sb_eat_lsm_opts(data, &sec_opts);
if (!secdata)
goto out;
error = security_sb_copy_data(data, secdata);
if (error) if (error)
goto out_free_secdata; return ERR_PTR(error);
} }
root = type->mount(type, flags, name, data); root = type->mount(type, flags, name, data);
...@@ -1276,10 +1273,16 @@ mount_fs(struct file_system_type *type, int flags, const char *name, void *data) ...@@ -1276,10 +1273,16 @@ mount_fs(struct file_system_type *type, int flags, const char *name, void *data)
smp_wmb(); smp_wmb();
sb->s_flags |= SB_BORN; sb->s_flags |= SB_BORN;
error = security_sb_kern_mount(sb, flags, secdata); error = security_sb_set_mnt_opts(sb, sec_opts, 0, NULL);
if (error) if (error)
goto out_sb; goto out_sb;
if (!(flags & (MS_KERNMOUNT|MS_SUBMOUNT))) {
error = security_sb_kern_mount(sb);
if (error)
goto out_sb;
}
/* /*
* filesystems should never set s_maxbytes larger than MAX_LFS_FILESIZE * filesystems should never set s_maxbytes larger than MAX_LFS_FILESIZE
* but s_maxbytes was an unsigned long long for many releases. Throw * but s_maxbytes was an unsigned long long for many releases. Throw
...@@ -1290,14 +1293,13 @@ mount_fs(struct file_system_type *type, int flags, const char *name, void *data) ...@@ -1290,14 +1293,13 @@ mount_fs(struct file_system_type *type, int flags, const char *name, void *data)
"negative value (%lld)\n", type->name, sb->s_maxbytes); "negative value (%lld)\n", type->name, sb->s_maxbytes);
up_write(&sb->s_umount); up_write(&sb->s_umount);
free_secdata(secdata); security_free_mnt_opts(&sec_opts);
return root; return root;
out_sb: out_sb:
dput(root); dput(root);
deactivate_locked_super(sb); deactivate_locked_super(sb);
out_free_secdata: out_free_secdata:
free_secdata(secdata); security_free_mnt_opts(&sec_opts);
out:
return ERR_PTR(error); return ERR_PTR(error);
} }
......
...@@ -1461,9 +1461,10 @@ union security_list_options { ...@@ -1461,9 +1461,10 @@ 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); void (*sb_free_mnt_opts)(void *mnt_opts);
int (*sb_remount)(struct super_block *sb, void *data); int (*sb_eat_lsm_opts)(char *orig, void **mnt_opts);
int (*sb_kern_mount)(struct super_block *sb, int flags, void *data); int (*sb_remount)(struct super_block *sb, void *mnt_opts);
int (*sb_kern_mount)(struct super_block *sb);
int (*sb_show_options)(struct seq_file *m, struct super_block *sb); int (*sb_show_options)(struct seq_file *m, struct super_block *sb);
int (*sb_statfs)(struct dentry *dentry); int (*sb_statfs)(struct dentry *dentry);
int (*sb_mount)(const char *dev_name, const struct path *path, int (*sb_mount)(const char *dev_name, const struct path *path,
...@@ -1471,14 +1472,15 @@ union security_list_options { ...@@ -1471,14 +1472,15 @@ union security_list_options {
int (*sb_umount)(struct vfsmount *mnt, int flags); int (*sb_umount)(struct vfsmount *mnt, int flags);
int (*sb_pivotroot)(const struct path *old_path, const struct path *new_path); int (*sb_pivotroot)(const struct path *old_path, const struct path *new_path);
int (*sb_set_mnt_opts)(struct super_block *sb, int (*sb_set_mnt_opts)(struct super_block *sb,
struct security_mnt_opts *opts, void *mnt_opts,
unsigned long kern_flags, unsigned long kern_flags,
unsigned long *set_kern_flags); unsigned long *set_kern_flags);
int (*sb_clone_mnt_opts)(const struct super_block *oldsb, int (*sb_clone_mnt_opts)(const struct super_block *oldsb,
struct super_block *newsb, struct super_block *newsb,
unsigned long kern_flags, unsigned long kern_flags,
unsigned long *set_kern_flags); unsigned long *set_kern_flags);
int (*sb_parse_opts_str)(char *options, struct security_mnt_opts *opts); int (*sb_add_mnt_opt)(const char *option, const char *val, int len,
void **mnt_opts);
int (*dentry_init_security)(struct dentry *dentry, int mode, int (*dentry_init_security)(struct dentry *dentry, int mode,
const struct qstr *name, void **ctx, const struct qstr *name, void **ctx,
u32 *ctxlen); u32 *ctxlen);
...@@ -1800,7 +1802,8 @@ struct security_hook_heads { ...@@ -1800,7 +1802,8 @@ struct security_hook_heads {
struct hlist_head bprm_committed_creds; struct hlist_head bprm_committed_creds;
struct hlist_head sb_alloc_security; struct hlist_head sb_alloc_security;
struct hlist_head sb_free_security; struct hlist_head sb_free_security;
struct hlist_head sb_copy_data; struct hlist_head sb_free_mnt_opts;
struct hlist_head sb_eat_lsm_opts;
struct hlist_head sb_remount; struct hlist_head sb_remount;
struct hlist_head sb_kern_mount; struct hlist_head sb_kern_mount;
struct hlist_head sb_show_options; struct hlist_head sb_show_options;
...@@ -1810,7 +1813,7 @@ struct security_hook_heads { ...@@ -1810,7 +1813,7 @@ struct security_hook_heads {
struct hlist_head sb_pivotroot; struct hlist_head sb_pivotroot;
struct hlist_head sb_set_mnt_opts; struct hlist_head sb_set_mnt_opts;
struct hlist_head sb_clone_mnt_opts; struct hlist_head sb_clone_mnt_opts;
struct hlist_head sb_parse_opts_str; struct hlist_head sb_add_mnt_opt;
struct hlist_head dentry_init_security; struct hlist_head dentry_init_security;
struct hlist_head dentry_create_files_as; struct hlist_head dentry_create_files_as;
#ifdef CONFIG_SECURITY_PATH #ifdef CONFIG_SECURITY_PATH
......
...@@ -81,7 +81,7 @@ extern void mnt_drop_write_file(struct file *file); ...@@ -81,7 +81,7 @@ extern void mnt_drop_write_file(struct file *file);
extern void mntput(struct vfsmount *mnt); extern void mntput(struct vfsmount *mnt);
extern struct vfsmount *mntget(struct vfsmount *mnt); extern struct vfsmount *mntget(struct vfsmount *mnt);
extern struct vfsmount *mnt_clone_internal(const struct path *path); extern struct vfsmount *mnt_clone_internal(const struct path *path);
extern int __mnt_is_readonly(struct vfsmount *mnt); extern bool __mnt_is_readonly(struct vfsmount *mnt);
extern bool mnt_may_suid(struct vfsmount *mnt); extern bool mnt_may_suid(struct vfsmount *mnt);
struct path; struct path;
......
...@@ -182,36 +182,10 @@ static inline const char *kernel_load_data_id_str(enum kernel_load_data_id id) ...@@ -182,36 +182,10 @@ static inline const char *kernel_load_data_id_str(enum kernel_load_data_id id)
#ifdef CONFIG_SECURITY #ifdef CONFIG_SECURITY
struct security_mnt_opts {
char **mnt_opts;
int *mnt_opts_flags;
int num_mnt_opts;
};
int call_lsm_notifier(enum lsm_event event, void *data); int call_lsm_notifier(enum lsm_event event, void *data);
int register_lsm_notifier(struct notifier_block *nb); int register_lsm_notifier(struct notifier_block *nb);
int unregister_lsm_notifier(struct notifier_block *nb); int unregister_lsm_notifier(struct notifier_block *nb);
static inline void security_init_mnt_opts(struct security_mnt_opts *opts)
{
opts->mnt_opts = NULL;
opts->mnt_opts_flags = NULL;
opts->num_mnt_opts = 0;
}
static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
{
int i;
if (opts->mnt_opts)
for (i = 0; i < opts->num_mnt_opts; i++)
kfree(opts->mnt_opts[i]);
kfree(opts->mnt_opts);
opts->mnt_opts = NULL;
kfree(opts->mnt_opts_flags);
opts->mnt_opts_flags = NULL;
opts->num_mnt_opts = 0;
}
/* prototypes */ /* prototypes */
extern int security_init(void); extern int security_init(void);
...@@ -248,9 +222,10 @@ void security_bprm_committing_creds(struct linux_binprm *bprm); ...@@ -248,9 +222,10 @@ void security_bprm_committing_creds(struct linux_binprm *bprm);
void security_bprm_committed_creds(struct linux_binprm *bprm); 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); void security_free_mnt_opts(void **mnt_opts);
int security_sb_remount(struct super_block *sb, void *data); int security_sb_eat_lsm_opts(char *options, void **mnt_opts);
int security_sb_kern_mount(struct super_block *sb, int flags, void *data); int security_sb_remount(struct super_block *sb, void *mnt_opts);
int security_sb_kern_mount(struct super_block *sb);
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);
int security_sb_statfs(struct dentry *dentry); int security_sb_statfs(struct dentry *dentry);
int security_sb_mount(const char *dev_name, const struct path *path, int security_sb_mount(const char *dev_name, const struct path *path,
...@@ -258,14 +233,15 @@ int security_sb_mount(const char *dev_name, const struct path *path, ...@@ -258,14 +233,15 @@ int security_sb_mount(const char *dev_name, const struct path *path,
int security_sb_umount(struct vfsmount *mnt, int flags); int security_sb_umount(struct vfsmount *mnt, int flags);
int security_sb_pivotroot(const struct path *old_path, const struct path *new_path); int security_sb_pivotroot(const struct path *old_path, const struct path *new_path);
int security_sb_set_mnt_opts(struct super_block *sb, int security_sb_set_mnt_opts(struct super_block *sb,
struct security_mnt_opts *opts, void *mnt_opts,
unsigned long kern_flags, unsigned long kern_flags,
unsigned long *set_kern_flags); unsigned long *set_kern_flags);
int security_sb_clone_mnt_opts(const struct super_block *oldsb, int security_sb_clone_mnt_opts(const struct super_block *oldsb,
struct super_block *newsb, struct super_block *newsb,
unsigned long kern_flags, unsigned long kern_flags,
unsigned long *set_kern_flags); unsigned long *set_kern_flags);
int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts); int security_add_mnt_opt(const char *option, const char *val,
int len, void **mnt_opts);
int security_dentry_init_security(struct dentry *dentry, int mode, int security_dentry_init_security(struct dentry *dentry, int mode,
const struct qstr *name, void **ctx, const struct qstr *name, void **ctx,
u32 *ctxlen); u32 *ctxlen);
...@@ -403,8 +379,6 @@ int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen); ...@@ -403,8 +379,6 @@ int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen);
int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen); int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen);
int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen); int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen);
#else /* CONFIG_SECURITY */ #else /* CONFIG_SECURITY */
struct security_mnt_opts {
};
static inline int call_lsm_notifier(enum lsm_event event, void *data) static inline int call_lsm_notifier(enum lsm_event event, void *data)
{ {
...@@ -421,11 +395,7 @@ static inline int unregister_lsm_notifier(struct notifier_block *nb) ...@@ -421,11 +395,7 @@ static inline int unregister_lsm_notifier(struct notifier_block *nb)
return 0; return 0;
} }
static inline void security_init_mnt_opts(struct security_mnt_opts *opts) static inline void security_free_mnt_opts(void **mnt_opts)
{
}
static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
{ {
} }
...@@ -555,17 +525,19 @@ static inline int security_sb_alloc(struct super_block *sb) ...@@ -555,17 +525,19 @@ static inline int security_sb_alloc(struct super_block *sb)
static inline void security_sb_free(struct super_block *sb) static inline void security_sb_free(struct super_block *sb)
{ } { }
static inline int security_sb_copy_data(char *orig, char *copy) static inline int security_sb_eat_lsm_opts(char *options,
void **mnt_opts)
{ {
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,
void *mnt_opts)
{ {
return 0; return 0;
} }
static inline int security_sb_kern_mount(struct super_block *sb, int flags, void *data) static inline int security_sb_kern_mount(struct super_block *sb)
{ {
return 0; return 0;
} }
...@@ -600,7 +572,7 @@ static inline int security_sb_pivotroot(const struct path *old_path, ...@@ -600,7 +572,7 @@ static inline int security_sb_pivotroot(const struct path *old_path,
} }
static inline int security_sb_set_mnt_opts(struct super_block *sb, static inline int security_sb_set_mnt_opts(struct super_block *sb,
struct security_mnt_opts *opts, void *mnt_opts,
unsigned long kern_flags, unsigned long kern_flags,
unsigned long *set_kern_flags) unsigned long *set_kern_flags)
{ {
...@@ -615,7 +587,8 @@ static inline int security_sb_clone_mnt_opts(const struct super_block *oldsb, ...@@ -615,7 +587,8 @@ static inline int security_sb_clone_mnt_opts(const struct super_block *oldsb,
return 0; return 0;
} }
static inline int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts) static inline int security_add_mnt_opt(const char *option, const char *val,
int len, void **mnt_opts)
{ {
return 0; return 0;
} }
...@@ -1820,28 +1793,5 @@ static inline void security_bpf_prog_free(struct bpf_prog_aux *aux) ...@@ -1820,28 +1793,5 @@ static inline void security_bpf_prog_free(struct bpf_prog_aux *aux)
#endif /* CONFIG_SECURITY */ #endif /* CONFIG_SECURITY */
#endif /* CONFIG_BPF_SYSCALL */ #endif /* CONFIG_BPF_SYSCALL */
#ifdef CONFIG_SECURITY
static inline char *alloc_secdata(void)
{
return (char *)get_zeroed_page(GFP_KERNEL);
}
static inline void free_secdata(void *secdata)
{
free_page((unsigned long)secdata);
}
#else
static inline char *alloc_secdata(void)
{
return (char *)1;
}
static inline void free_secdata(void *secdata)
{ }
#endif /* CONFIG_SECURITY */
#endif /* ! __LINUX_SECURITY_H */ #endif /* ! __LINUX_SECURITY_H */
...@@ -14,6 +14,11 @@ ...@@ -14,6 +14,11 @@
#include <linux/ioctl.h> #include <linux/ioctl.h>
#include <linux/types.h> #include <linux/types.h>
/* Use of MS_* flags within the kernel is restricted to core mount(2) code. */
#if !defined(__KERNEL__)
#include <linux/mount.h>
#endif
/* /*
* It's silly to have NR_OPEN bigger than NR_FILE, but you can change * It's silly to have NR_OPEN bigger than NR_FILE, but you can change
* the file limit at runtime and only root can increase the per-process * the file limit at runtime and only root can increase the per-process
...@@ -101,57 +106,6 @@ struct inodes_stat_t { ...@@ -101,57 +106,6 @@ struct inodes_stat_t {
#define NR_FILE 8192 /* this can well be larger on a larger system */ #define NR_FILE 8192 /* this can well be larger on a larger system */
/*
* These are the fs-independent mount-flags: up to 32 flags are supported
*/
#define MS_RDONLY 1 /* Mount read-only */
#define MS_NOSUID 2 /* Ignore suid and sgid bits */
#define MS_NODEV 4 /* Disallow access to device special files */
#define MS_NOEXEC 8 /* Disallow program execution */
#define MS_SYNCHRONOUS 16 /* Writes are synced at once */
#define MS_REMOUNT 32 /* Alter flags of a mounted FS */
#define MS_MANDLOCK 64 /* Allow mandatory locks on an FS */
#define MS_DIRSYNC 128 /* Directory modifications are synchronous */
#define MS_NOATIME 1024 /* Do not update access times. */
#define MS_NODIRATIME 2048 /* Do not update directory access times */
#define MS_BIND 4096
#define MS_MOVE 8192
#define MS_REC 16384
#define MS_VERBOSE 32768 /* War is peace. Verbosity is silence.
MS_VERBOSE is deprecated. */
#define MS_SILENT 32768
#define MS_POSIXACL (1<<16) /* VFS does not apply the umask */
#define MS_UNBINDABLE (1<<17) /* change to unbindable */
#define MS_PRIVATE (1<<18) /* change to private */
#define MS_SLAVE (1<<19) /* change to slave */
#define MS_SHARED (1<<20) /* change to shared */
#define MS_RELATIME (1<<21) /* Update atime relative to mtime/ctime. */
#define MS_KERNMOUNT (1<<22) /* this is a kern_mount call */
#define MS_I_VERSION (1<<23) /* Update inode I_version field */
#define MS_STRICTATIME (1<<24) /* Always perform atime updates */
#define MS_LAZYTIME (1<<25) /* Update the on-disk [acm]times lazily */
/* These sb flags are internal to the kernel */
#define MS_SUBMOUNT (1<<26)
#define MS_NOREMOTELOCK (1<<27)
#define MS_NOSEC (1<<28)
#define MS_BORN (1<<29)
#define MS_ACTIVE (1<<30)
#define MS_NOUSER (1<<31)
/*
* Superblock flags that can be altered by MS_REMOUNT
*/
#define MS_RMT_MASK (MS_RDONLY|MS_SYNCHRONOUS|MS_MANDLOCK|MS_I_VERSION|\
MS_LAZYTIME)
/*
* Old magic mount flag and mask
*/
#define MS_MGC_VAL 0xC0ED0000
#define MS_MGC_MSK 0xffff0000
/* /*
* Structure for FS_IOC_FSGETXATTR[A] and FS_IOC_FSSETXATTR. * Structure for FS_IOC_FSGETXATTR[A] and FS_IOC_FSSETXATTR.
*/ */
......
#ifndef _UAPI_LINUX_MOUNT_H
#define _UAPI_LINUX_MOUNT_H
/*
* These are the fs-independent mount-flags: up to 32 flags are supported
*
* Usage of these is restricted within the kernel to core mount(2) code and
* callers of sys_mount() only. Filesystems should be using the SB_*
* equivalent instead.
*/
#define MS_RDONLY 1 /* Mount read-only */
#define MS_NOSUID 2 /* Ignore suid and sgid bits */
#define MS_NODEV 4 /* Disallow access to device special files */
#define MS_NOEXEC 8 /* Disallow program execution */
#define MS_SYNCHRONOUS 16 /* Writes are synced at once */
#define MS_REMOUNT 32 /* Alter flags of a mounted FS */
#define MS_MANDLOCK 64 /* Allow mandatory locks on an FS */
#define MS_DIRSYNC 128 /* Directory modifications are synchronous */
#define MS_NOATIME 1024 /* Do not update access times. */
#define MS_NODIRATIME 2048 /* Do not update directory access times */
#define MS_BIND 4096
#define MS_MOVE 8192
#define MS_REC 16384
#define MS_VERBOSE 32768 /* War is peace. Verbosity is silence.
MS_VERBOSE is deprecated. */
#define MS_SILENT 32768
#define MS_POSIXACL (1<<16) /* VFS does not apply the umask */
#define MS_UNBINDABLE (1<<17) /* change to unbindable */
#define MS_PRIVATE (1<<18) /* change to private */
#define MS_SLAVE (1<<19) /* change to slave */
#define MS_SHARED (1<<20) /* change to shared */
#define MS_RELATIME (1<<21) /* Update atime relative to mtime/ctime. */
#define MS_KERNMOUNT (1<<22) /* this is a kern_mount call */
#define MS_I_VERSION (1<<23) /* Update inode I_version field */
#define MS_STRICTATIME (1<<24) /* Always perform atime updates */
#define MS_LAZYTIME (1<<25) /* Update the on-disk [acm]times lazily */
/* These sb flags are internal to the kernel */
#define MS_SUBMOUNT (1<<26)
#define MS_NOREMOTELOCK (1<<27)
#define MS_NOSEC (1<<28)
#define MS_BORN (1<<29)
#define MS_ACTIVE (1<<30)
#define MS_NOUSER (1<<31)
/*
* Superblock flags that can be altered by MS_REMOUNT
*/
#define MS_RMT_MASK (MS_RDONLY|MS_SYNCHRONOUS|MS_MANDLOCK|MS_I_VERSION|\
MS_LAZYTIME)
/*
* Old magic mount flag and mask
*/
#define MS_MGC_VAL 0xC0ED0000
#define MS_MGC_MSK 0xffff0000
#endif /* _UAPI_LINUX_MOUNT_H */
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <linux/nfs_fs.h> #include <linux/nfs_fs.h>
#include <linux/nfs_fs_sb.h> #include <linux/nfs_fs_sb.h>
#include <linux/nfs_mount.h> #include <linux/nfs_mount.h>
#include <uapi/linux/mount.h>
#include "do_mounts.h" #include "do_mounts.h"
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/freezer.h> #include <linux/freezer.h>
#include <linux/kmod.h> #include <linux/kmod.h>
#include <uapi/linux/mount.h>
#include "do_mounts.h" #include "do_mounts.h"
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <linux/netfilter_ipv4.h> #include <linux/netfilter_ipv4.h>
#include <linux/netfilter_ipv6.h> #include <linux/netfilter_ipv6.h>
#include <net/sock.h> #include <net/sock.h>
#include <uapi/linux/mount.h>
#include "include/apparmor.h" #include "include/apparmor.h"
#include "include/apparmorfs.h" #include "include/apparmorfs.h"
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/mount.h> #include <linux/mount.h>
#include <linux/namei.h> #include <linux/namei.h>
#include <uapi/linux/mount.h>
#include "include/apparmor.h" #include "include/apparmor.h"
#include "include/audit.h" #include "include/audit.h"
......
...@@ -384,20 +384,31 @@ void security_sb_free(struct super_block *sb) ...@@ -384,20 +384,31 @@ void security_sb_free(struct super_block *sb)
call_void_hook(sb_free_security, sb); call_void_hook(sb_free_security, sb);
} }
int security_sb_copy_data(char *orig, char *copy) void security_free_mnt_opts(void **mnt_opts)
{ {
return call_int_hook(sb_copy_data, 0, orig, copy); if (!*mnt_opts)
return;
call_void_hook(sb_free_mnt_opts, *mnt_opts);
*mnt_opts = NULL;
}
EXPORT_SYMBOL(security_free_mnt_opts);
int security_sb_eat_lsm_opts(char *options, void **mnt_opts)
{
return call_int_hook(sb_eat_lsm_opts, 0, options, mnt_opts);
} }
EXPORT_SYMBOL(security_sb_copy_data); EXPORT_SYMBOL(security_sb_eat_lsm_opts);
int security_sb_remount(struct super_block *sb, void *data) int security_sb_remount(struct super_block *sb,
void *mnt_opts)
{ {
return call_int_hook(sb_remount, 0, sb, data); return call_int_hook(sb_remount, 0, sb, mnt_opts);
} }
EXPORT_SYMBOL(security_sb_remount);
int security_sb_kern_mount(struct super_block *sb, int flags, void *data) int security_sb_kern_mount(struct super_block *sb)
{ {
return call_int_hook(sb_kern_mount, 0, sb, flags, data); return call_int_hook(sb_kern_mount, 0, sb);
} }
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)
...@@ -427,13 +438,13 @@ int security_sb_pivotroot(const struct path *old_path, const struct path *new_pa ...@@ -427,13 +438,13 @@ int security_sb_pivotroot(const struct path *old_path, const struct path *new_pa
} }
int security_sb_set_mnt_opts(struct super_block *sb, int security_sb_set_mnt_opts(struct super_block *sb,
struct security_mnt_opts *opts, void *mnt_opts,
unsigned long kern_flags, unsigned long kern_flags,
unsigned long *set_kern_flags) unsigned long *set_kern_flags)
{ {
return call_int_hook(sb_set_mnt_opts, return call_int_hook(sb_set_mnt_opts,
opts->num_mnt_opts ? -EOPNOTSUPP : 0, sb, mnt_opts ? -EOPNOTSUPP : 0, sb,
opts, kern_flags, set_kern_flags); mnt_opts, kern_flags, set_kern_flags);
} }
EXPORT_SYMBOL(security_sb_set_mnt_opts); EXPORT_SYMBOL(security_sb_set_mnt_opts);
...@@ -447,11 +458,13 @@ int security_sb_clone_mnt_opts(const struct super_block *oldsb, ...@@ -447,11 +458,13 @@ int security_sb_clone_mnt_opts(const struct super_block *oldsb,
} }
EXPORT_SYMBOL(security_sb_clone_mnt_opts); EXPORT_SYMBOL(security_sb_clone_mnt_opts);
int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts) int security_add_mnt_opt(const char *option, const char *val, int len,
void **mnt_opts)
{ {
return call_int_hook(sb_parse_opts_str, 0, options, opts); return call_int_hook(sb_add_mnt_opt, -EINVAL,
option, val, len, mnt_opts);
} }
EXPORT_SYMBOL(security_sb_parse_opts_str); EXPORT_SYMBOL(security_add_mnt_opt);
int security_inode_alloc(struct inode *inode) int security_inode_alloc(struct inode *inode)
{ {
......
This diff is collapsed.
This diff is collapsed.
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
*/ */
#include <linux/slab.h> #include <linux/slab.h>
#include <uapi/linux/mount.h>
#include "common.h" #include "common.h"
/* String table for special mount operations. */ /* String table for special mount operations. */
......
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