summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2018-12-13 13:41:47 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2018-12-21 11:48:34 -0500
commit204cc0ccf1d49c6292aeef4c8edd1b3d10ff933c (patch)
treeb372464222a21a2a0356fde8421eb86cb991a378
parente3489f8974e178d723259a842a1e61708dd7dc1e (diff)
LSM: hide struct security_mnt_opts from any generic code
Keep void * instead, allocate on demand (in parse_str_opts, at the moment). Eventually both selinux and smack will be better off with private structures with several strings in those, rather than this "counter and two pointers to dynamically allocated arrays" ugliness. This commit allows to do that at leisure, without disrupting anything outside of given module. Changes: * instead of struct security_mnt_opt use an opaque pointer initialized to NULL. * security_sb_eat_lsm_opts(), security_sb_parse_opts_str() and security_free_mnt_opts() take it as var argument (i.e. as void **); call sites are unchanged. * security_sb_set_mnt_opts() and security_sb_remount() take it by value (i.e. as void *). * new method: ->sb_free_mnt_opts(). Takes void *, does whatever freeing that needs to be done. * ->sb_set_mnt_opts() and ->sb_remount() might get NULL as mnt_opts argument, meaning "empty". Reviewed-by: David Howells <dhowells@redhat.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--fs/btrfs/super.c10
-rw-r--r--fs/namespace.c9
-rw-r--r--fs/nfs/internal.h2
-rw-r--r--fs/nfs/super.c6
-rw-r--r--fs/super.c12
-rw-r--r--include/linux/lsm_hooks.h11
-rw-r--r--include/linux/security.h43
-rw-r--r--security/security.c27
-rw-r--r--security/selinux/hooks.c52
-rw-r--r--security/smack/smack_lsm.c38
10 files changed, 118 insertions, 92 deletions
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index 3b04e7735b5f..e90c4616ed6a 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -1472,14 +1472,13 @@ static struct dentry *btrfs_mount_root(struct file_system_type *fs_type,
1472 struct btrfs_device *device = NULL; 1472 struct btrfs_device *device = NULL;
1473 struct btrfs_fs_devices *fs_devices = NULL; 1473 struct btrfs_fs_devices *fs_devices = NULL;
1474 struct btrfs_fs_info *fs_info = NULL; 1474 struct btrfs_fs_info *fs_info = NULL;
1475 struct security_mnt_opts new_sec_opts; 1475 void *new_sec_opts = NULL;
1476 fmode_t mode = FMODE_READ; 1476 fmode_t mode = FMODE_READ;
1477 int error = 0; 1477 int error = 0;
1478 1478
1479 if (!(flags & SB_RDONLY)) 1479 if (!(flags & SB_RDONLY))
1480 mode |= FMODE_WRITE; 1480 mode |= FMODE_WRITE;
1481 1481
1482 security_init_mnt_opts(&new_sec_opts);
1483 if (data) { 1482 if (data) {
1484 error = security_sb_eat_lsm_opts(data, &new_sec_opts); 1483 error = security_sb_eat_lsm_opts(data, &new_sec_opts);
1485 if (error) 1484 if (error)
@@ -1551,7 +1550,7 @@ static struct dentry *btrfs_mount_root(struct file_system_type *fs_type,
1551 error = btrfs_fill_super(s, fs_devices, data); 1550 error = btrfs_fill_super(s, fs_devices, data);
1552 } 1551 }
1553 if (!error) 1552 if (!error)
1554 error = security_sb_set_mnt_opts(s, &new_sec_opts, 0, NULL); 1553 error = security_sb_set_mnt_opts(s, new_sec_opts, 0, NULL);
1555 security_free_mnt_opts(&new_sec_opts); 1554 security_free_mnt_opts(&new_sec_opts);
1556 if (error) { 1555 if (error) {
1557 deactivate_locked_super(s); 1556 deactivate_locked_super(s);
@@ -1724,12 +1723,11 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data)
1724 btrfs_remount_prepare(fs_info); 1723 btrfs_remount_prepare(fs_info);
1725 1724
1726 if (data) { 1725 if (data) {
1727 struct security_mnt_opts new_sec_opts; 1726 void *new_sec_opts = NULL;
1728 1727
1729 security_init_mnt_opts(&new_sec_opts);
1730 ret = security_sb_eat_lsm_opts(data, &new_sec_opts); 1728 ret = security_sb_eat_lsm_opts(data, &new_sec_opts);
1731 if (!ret) 1729 if (!ret)
1732 ret = security_sb_remount(sb, &new_sec_opts); 1730 ret = security_sb_remount(sb, new_sec_opts);
1733 security_free_mnt_opts(&new_sec_opts); 1731 security_free_mnt_opts(&new_sec_opts);
1734 if (ret) 1732 if (ret)
1735 goto restore; 1733 goto restore;
diff --git a/fs/namespace.c b/fs/namespace.c
index 39aca7b69c2e..badfd287358c 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -2299,7 +2299,7 @@ static int do_remount(struct path *path, int ms_flags, int sb_flags,
2299 int err; 2299 int err;
2300 struct super_block *sb = path->mnt->mnt_sb; 2300 struct super_block *sb = path->mnt->mnt_sb;
2301 struct mount *mnt = real_mount(path->mnt); 2301 struct mount *mnt = real_mount(path->mnt);
2302 struct security_mnt_opts opts; 2302 void *sec_opts = NULL;
2303 2303
2304 if (!check_mnt(mnt)) 2304 if (!check_mnt(mnt))
2305 return -EINVAL; 2305 return -EINVAL;
@@ -2310,14 +2310,13 @@ static int do_remount(struct path *path, int ms_flags, int sb_flags,
2310 if (!can_change_locked_flags(mnt, mnt_flags)) 2310 if (!can_change_locked_flags(mnt, mnt_flags))
2311 return -EPERM; 2311 return -EPERM;
2312 2312
2313 security_init_mnt_opts(&opts);
2314 if (data && !(sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)) { 2313 if (data && !(sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)) {
2315 err = security_sb_eat_lsm_opts(data, &opts); 2314 err = security_sb_eat_lsm_opts(data, &sec_opts);
2316 if (err) 2315 if (err)
2317 return err; 2316 return err;
2318 } 2317 }
2319 err = security_sb_remount(sb, &opts); 2318 err = security_sb_remount(sb, sec_opts);
2320 security_free_mnt_opts(&opts); 2319 security_free_mnt_opts(&sec_opts);
2321 if (err) 2320 if (err)
2322 return err; 2321 return err;
2323 2322
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 8357ff69962f..97e1dcefe561 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -123,7 +123,7 @@ struct nfs_parsed_mount_data {
123 unsigned short protocol; 123 unsigned short protocol;
124 } nfs_server; 124 } nfs_server;
125 125
126 struct security_mnt_opts lsm_opts; 126 void *lsm_opts;
127 struct net *net; 127 struct net *net;
128}; 128};
129 129
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 300bdd1d4a09..1943de8f9d29 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -929,7 +929,7 @@ static struct nfs_parsed_mount_data *nfs_alloc_parsed_mount_data(void)
929 data->minorversion = 0; 929 data->minorversion = 0;
930 data->need_mount = true; 930 data->need_mount = true;
931 data->net = current->nsproxy->net_ns; 931 data->net = current->nsproxy->net_ns;
932 security_init_mnt_opts(&data->lsm_opts); 932 data->lsm_opts = NULL;
933 } 933 }
934 return data; 934 return data;
935} 935}
@@ -2294,7 +2294,7 @@ nfs_remount(struct super_block *sb, int *flags, char *raw_data)
2294 /* compare new mount options with old ones */ 2294 /* compare new mount options with old ones */
2295 error = nfs_compare_remount_data(nfss, data); 2295 error = nfs_compare_remount_data(nfss, data);
2296 if (!error) 2296 if (!error)
2297 error = security_sb_remount(sb, &data->lsm_opts); 2297 error = security_sb_remount(sb, data->lsm_opts);
2298out: 2298out:
2299 nfs_free_parsed_mount_data(data); 2299 nfs_free_parsed_mount_data(data);
2300 return error; 2300 return error;
@@ -2534,7 +2534,7 @@ int nfs_set_sb_security(struct super_block *s, struct dentry *mntroot,
2534 if (NFS_SB(s)->caps & NFS_CAP_SECURITY_LABEL) 2534 if (NFS_SB(s)->caps & NFS_CAP_SECURITY_LABEL)
2535 kflags |= SECURITY_LSM_NATIVE_LABELS; 2535 kflags |= SECURITY_LSM_NATIVE_LABELS;
2536 2536
2537 error = security_sb_set_mnt_opts(s, &mount_info->parsed->lsm_opts, 2537 error = security_sb_set_mnt_opts(s, mount_info->parsed->lsm_opts,
2538 kflags, &kflags_out); 2538 kflags, &kflags_out);
2539 if (error) 2539 if (error)
2540 goto err; 2540 goto err;
diff --git a/fs/super.c b/fs/super.c
index 1f75fe312597..a5511c4ba69b 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -1247,12 +1247,10 @@ mount_fs(struct file_system_type *type, int flags, const char *name, void *data)
1247 struct dentry *root; 1247 struct dentry *root;
1248 struct super_block *sb; 1248 struct super_block *sb;
1249 int error = -ENOMEM; 1249 int error = -ENOMEM;
1250 struct security_mnt_opts opts; 1250 void *sec_opts = NULL;
1251
1252 security_init_mnt_opts(&opts);
1253 1251
1254 if (data && !(type->fs_flags & FS_BINARY_MOUNTDATA)) { 1252 if (data && !(type->fs_flags & FS_BINARY_MOUNTDATA)) {
1255 error = security_sb_eat_lsm_opts(data, &opts); 1253 error = security_sb_eat_lsm_opts(data, &sec_opts);
1256 if (error) 1254 if (error)
1257 return ERR_PTR(error); 1255 return ERR_PTR(error);
1258 } 1256 }
@@ -1275,7 +1273,7 @@ mount_fs(struct file_system_type *type, int flags, const char *name, void *data)
1275 smp_wmb(); 1273 smp_wmb();
1276 sb->s_flags |= SB_BORN; 1274 sb->s_flags |= SB_BORN;
1277 1275
1278 error = security_sb_set_mnt_opts(sb, &opts, 0, NULL); 1276 error = security_sb_set_mnt_opts(sb, sec_opts, 0, NULL);
1279 if (error) 1277 if (error)
1280 goto out_sb; 1278 goto out_sb;
1281 1279
@@ -1295,13 +1293,13 @@ mount_fs(struct file_system_type *type, int flags, const char *name, void *data)
1295 "negative value (%lld)\n", type->name, sb->s_maxbytes); 1293 "negative value (%lld)\n", type->name, sb->s_maxbytes);
1296 1294
1297 up_write(&sb->s_umount); 1295 up_write(&sb->s_umount);
1298 security_free_mnt_opts(&opts); 1296 security_free_mnt_opts(&sec_opts);
1299 return root; 1297 return root;
1300out_sb: 1298out_sb:
1301 dput(root); 1299 dput(root);
1302 deactivate_locked_super(sb); 1300 deactivate_locked_super(sb);
1303out_free_secdata: 1301out_free_secdata:
1304 security_free_mnt_opts(&opts); 1302 security_free_mnt_opts(&sec_opts);
1305 return ERR_PTR(error); 1303 return ERR_PTR(error);
1306} 1304}
1307 1305
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index c418909c178c..a9c541f5732e 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -1461,9 +1461,9 @@ union security_list_options {
1461 1461
1462 int (*sb_alloc_security)(struct super_block *sb); 1462 int (*sb_alloc_security)(struct super_block *sb);
1463 void (*sb_free_security)(struct super_block *sb); 1463 void (*sb_free_security)(struct super_block *sb);
1464 int (*sb_eat_lsm_opts)(char *orig, struct security_mnt_opts *opts); 1464 void (*sb_free_mnt_opts)(void *mnt_opts);
1465 int (*sb_remount)(struct super_block *sb, 1465 int (*sb_eat_lsm_opts)(char *orig, void **mnt_opts);
1466 struct security_mnt_opts *opts); 1466 int (*sb_remount)(struct super_block *sb, void *mnt_opts);
1467 int (*sb_kern_mount)(struct super_block *sb); 1467 int (*sb_kern_mount)(struct super_block *sb);
1468 int (*sb_show_options)(struct seq_file *m, struct super_block *sb); 1468 int (*sb_show_options)(struct seq_file *m, struct super_block *sb);
1469 int (*sb_statfs)(struct dentry *dentry); 1469 int (*sb_statfs)(struct dentry *dentry);
@@ -1472,14 +1472,14 @@ union security_list_options {
1472 int (*sb_umount)(struct vfsmount *mnt, int flags); 1472 int (*sb_umount)(struct vfsmount *mnt, int flags);
1473 int (*sb_pivotroot)(const struct path *old_path, const struct path *new_path); 1473 int (*sb_pivotroot)(const struct path *old_path, const struct path *new_path);
1474 int (*sb_set_mnt_opts)(struct super_block *sb, 1474 int (*sb_set_mnt_opts)(struct super_block *sb,
1475 struct security_mnt_opts *opts, 1475 void *mnt_opts,
1476 unsigned long kern_flags, 1476 unsigned long kern_flags,
1477 unsigned long *set_kern_flags); 1477 unsigned long *set_kern_flags);
1478 int (*sb_clone_mnt_opts)(const struct super_block *oldsb, 1478 int (*sb_clone_mnt_opts)(const struct super_block *oldsb,
1479 struct super_block *newsb, 1479 struct super_block *newsb,
1480 unsigned long kern_flags, 1480 unsigned long kern_flags,
1481 unsigned long *set_kern_flags); 1481 unsigned long *set_kern_flags);
1482 int (*sb_parse_opts_str)(char *options, struct security_mnt_opts *opts); 1482 int (*sb_parse_opts_str)(char *options, void **mnt_opts);
1483 int (*dentry_init_security)(struct dentry *dentry, int mode, 1483 int (*dentry_init_security)(struct dentry *dentry, int mode,
1484 const struct qstr *name, void **ctx, 1484 const struct qstr *name, void **ctx,
1485 u32 *ctxlen); 1485 u32 *ctxlen);
@@ -1801,6 +1801,7 @@ struct security_hook_heads {
1801 struct hlist_head bprm_committed_creds; 1801 struct hlist_head bprm_committed_creds;
1802 struct hlist_head sb_alloc_security; 1802 struct hlist_head sb_alloc_security;
1803 struct hlist_head sb_free_security; 1803 struct hlist_head sb_free_security;
1804 struct hlist_head sb_free_mnt_opts;
1804 struct hlist_head sb_eat_lsm_opts; 1805 struct hlist_head sb_eat_lsm_opts;
1805 struct hlist_head sb_remount; 1806 struct hlist_head sb_remount;
1806 struct hlist_head sb_kern_mount; 1807 struct hlist_head sb_kern_mount;
diff --git a/include/linux/security.h b/include/linux/security.h
index d00093363570..4bca0be95b7a 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -192,26 +192,6 @@ int call_lsm_notifier(enum lsm_event event, void *data);
192int register_lsm_notifier(struct notifier_block *nb); 192int register_lsm_notifier(struct notifier_block *nb);
193int unregister_lsm_notifier(struct notifier_block *nb); 193int unregister_lsm_notifier(struct notifier_block *nb);
194 194
195static inline void security_init_mnt_opts(struct security_mnt_opts *opts)
196{
197 opts->mnt_opts = NULL;
198 opts->mnt_opts_flags = NULL;
199 opts->num_mnt_opts = 0;
200}
201
202static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
203{
204 int i;
205 if (opts->mnt_opts)
206 for (i = 0; i < opts->num_mnt_opts; i++)
207 kfree(opts->mnt_opts[i]);
208 kfree(opts->mnt_opts);
209 opts->mnt_opts = NULL;
210 kfree(opts->mnt_opts_flags);
211 opts->mnt_opts_flags = NULL;
212 opts->num_mnt_opts = 0;
213}
214
215/* prototypes */ 195/* prototypes */
216extern int security_init(void); 196extern int security_init(void);
217 197
@@ -248,8 +228,9 @@ void security_bprm_committing_creds(struct linux_binprm *bprm);
248void security_bprm_committed_creds(struct linux_binprm *bprm); 228void security_bprm_committed_creds(struct linux_binprm *bprm);
249int security_sb_alloc(struct super_block *sb); 229int security_sb_alloc(struct super_block *sb);
250void security_sb_free(struct super_block *sb); 230void security_sb_free(struct super_block *sb);
251int security_sb_eat_lsm_opts(char *options, struct security_mnt_opts *opts); 231void security_free_mnt_opts(void **mnt_opts);
252int security_sb_remount(struct super_block *sb, struct security_mnt_opts *opts); 232int security_sb_eat_lsm_opts(char *options, void **mnt_opts);
233int security_sb_remount(struct super_block *sb, void *mnt_opts);
253int security_sb_kern_mount(struct super_block *sb); 234int security_sb_kern_mount(struct super_block *sb);
254int security_sb_show_options(struct seq_file *m, struct super_block *sb); 235int security_sb_show_options(struct seq_file *m, struct super_block *sb);
255int security_sb_statfs(struct dentry *dentry); 236int security_sb_statfs(struct dentry *dentry);
@@ -258,14 +239,14 @@ int security_sb_mount(const char *dev_name, const struct path *path,
258int security_sb_umount(struct vfsmount *mnt, int flags); 239int security_sb_umount(struct vfsmount *mnt, int flags);
259int security_sb_pivotroot(const struct path *old_path, const struct path *new_path); 240int security_sb_pivotroot(const struct path *old_path, const struct path *new_path);
260int security_sb_set_mnt_opts(struct super_block *sb, 241int security_sb_set_mnt_opts(struct super_block *sb,
261 struct security_mnt_opts *opts, 242 void *mnt_opts,
262 unsigned long kern_flags, 243 unsigned long kern_flags,
263 unsigned long *set_kern_flags); 244 unsigned long *set_kern_flags);
264int security_sb_clone_mnt_opts(const struct super_block *oldsb, 245int security_sb_clone_mnt_opts(const struct super_block *oldsb,
265 struct super_block *newsb, 246 struct super_block *newsb,
266 unsigned long kern_flags, 247 unsigned long kern_flags,
267 unsigned long *set_kern_flags); 248 unsigned long *set_kern_flags);
268int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts); 249int security_sb_parse_opts_str(char *options, void **mnt_opts);
269int security_dentry_init_security(struct dentry *dentry, int mode, 250int security_dentry_init_security(struct dentry *dentry, int mode,
270 const struct qstr *name, void **ctx, 251 const struct qstr *name, void **ctx,
271 u32 *ctxlen); 252 u32 *ctxlen);
@@ -421,11 +402,7 @@ static inline int unregister_lsm_notifier(struct notifier_block *nb)
421 return 0; 402 return 0;
422} 403}
423 404
424static inline void security_init_mnt_opts(struct security_mnt_opts *opts) 405static inline void security_free_mnt_opts(void **mnt_opts)
425{
426}
427
428static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
429{ 406{
430} 407}
431 408
@@ -556,13 +533,13 @@ static inline void security_sb_free(struct super_block *sb)
556{ } 533{ }
557 534
558static inline int security_sb_eat_lsm_opts(char *options, 535static inline int security_sb_eat_lsm_opts(char *options,
559 struct security_mnt_opts *opts) 536 void **mnt_opts)
560{ 537{
561 return 0; 538 return 0;
562} 539}
563 540
564static inline int security_sb_remount(struct super_block *sb, 541static inline int security_sb_remount(struct super_block *sb,
565 struct security_mnt_opts *opts) 542 void *mnt_opts)
566{ 543{
567 return 0; 544 return 0;
568} 545}
@@ -602,7 +579,7 @@ static inline int security_sb_pivotroot(const struct path *old_path,
602} 579}
603 580
604static inline int security_sb_set_mnt_opts(struct super_block *sb, 581static inline int security_sb_set_mnt_opts(struct super_block *sb,
605 struct security_mnt_opts *opts, 582 void *mnt_opts,
606 unsigned long kern_flags, 583 unsigned long kern_flags,
607 unsigned long *set_kern_flags) 584 unsigned long *set_kern_flags)
608{ 585{
@@ -617,7 +594,7 @@ static inline int security_sb_clone_mnt_opts(const struct super_block *oldsb,
617 return 0; 594 return 0;
618} 595}
619 596
620static inline int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts) 597static inline int security_sb_parse_opts_str(char *options, void **mnt_opts)
621{ 598{
622 return 0; 599 return 0;
623} 600}
diff --git a/security/security.c b/security/security.c
index feb18c925349..b7a5a0051807 100644
--- a/security/security.c
+++ b/security/security.c
@@ -384,16 +384,25 @@ void security_sb_free(struct super_block *sb)
384 call_void_hook(sb_free_security, sb); 384 call_void_hook(sb_free_security, sb);
385} 385}
386 386
387int security_sb_eat_lsm_opts(char *options, struct security_mnt_opts *opts) 387void security_free_mnt_opts(void **mnt_opts)
388{ 388{
389 return call_int_hook(sb_eat_lsm_opts, 0, options, opts); 389 if (!*mnt_opts)
390 return;
391 call_void_hook(sb_free_mnt_opts, *mnt_opts);
392 *mnt_opts = NULL;
393}
394EXPORT_SYMBOL(security_free_mnt_opts);
395
396int security_sb_eat_lsm_opts(char *options, void **mnt_opts)
397{
398 return call_int_hook(sb_eat_lsm_opts, 0, options, mnt_opts);
390} 399}
391EXPORT_SYMBOL(security_sb_eat_lsm_opts); 400EXPORT_SYMBOL(security_sb_eat_lsm_opts);
392 401
393int security_sb_remount(struct super_block *sb, 402int security_sb_remount(struct super_block *sb,
394 struct security_mnt_opts *opts) 403 void *mnt_opts)
395{ 404{
396 return call_int_hook(sb_remount, 0, sb, opts); 405 return call_int_hook(sb_remount, 0, sb, mnt_opts);
397} 406}
398EXPORT_SYMBOL(security_sb_remount); 407EXPORT_SYMBOL(security_sb_remount);
399 408
@@ -429,13 +438,13 @@ int security_sb_pivotroot(const struct path *old_path, const struct path *new_pa
429} 438}
430 439
431int security_sb_set_mnt_opts(struct super_block *sb, 440int security_sb_set_mnt_opts(struct super_block *sb,
432 struct security_mnt_opts *opts, 441 void *mnt_opts,
433 unsigned long kern_flags, 442 unsigned long kern_flags,
434 unsigned long *set_kern_flags) 443 unsigned long *set_kern_flags)
435{ 444{
436 return call_int_hook(sb_set_mnt_opts, 445 return call_int_hook(sb_set_mnt_opts,
437 opts->num_mnt_opts ? -EOPNOTSUPP : 0, sb, 446 mnt_opts ? -EOPNOTSUPP : 0, sb,
438 opts, kern_flags, set_kern_flags); 447 mnt_opts, kern_flags, set_kern_flags);
439} 448}
440EXPORT_SYMBOL(security_sb_set_mnt_opts); 449EXPORT_SYMBOL(security_sb_set_mnt_opts);
441 450
@@ -449,9 +458,9 @@ int security_sb_clone_mnt_opts(const struct super_block *oldsb,
449} 458}
450EXPORT_SYMBOL(security_sb_clone_mnt_opts); 459EXPORT_SYMBOL(security_sb_clone_mnt_opts);
451 460
452int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts) 461int security_sb_parse_opts_str(char *options, void **mnt_opts)
453{ 462{
454 return call_int_hook(sb_parse_opts_str, 0, options, opts); 463 return call_int_hook(sb_parse_opts_str, 0, options, mnt_opts);
455} 464}
456EXPORT_SYMBOL(security_sb_parse_opts_str); 465EXPORT_SYMBOL(security_sb_parse_opts_str);
457 466
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 11cf2feb27b3..caf7ca7abfc1 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -433,6 +433,19 @@ static void superblock_free_security(struct super_block *sb)
433 kfree(sbsec); 433 kfree(sbsec);
434} 434}
435 435
436static void selinux_free_mnt_opts(void *mnt_opts)
437{
438 struct security_mnt_opts *opts = mnt_opts;
439 int i;
440
441 if (opts->mnt_opts)
442 for (i = 0; i < opts->num_mnt_opts; i++)
443 kfree(opts->mnt_opts[i]);
444 kfree(opts->mnt_opts);
445 kfree(opts->mnt_opts_flags);
446 kfree(opts);
447}
448
436static inline int inode_doinit(struct inode *inode) 449static inline int inode_doinit(struct inode *inode)
437{ 450{
438 return inode_doinit_with_dentry(inode, NULL); 451 return inode_doinit_with_dentry(inode, NULL);
@@ -616,7 +629,7 @@ static int bad_option(struct superblock_security_struct *sbsec, char flag,
616 * labeling information. 629 * labeling information.
617 */ 630 */
618static int selinux_set_mnt_opts(struct super_block *sb, 631static int selinux_set_mnt_opts(struct super_block *sb,
619 struct security_mnt_opts *opts, 632 void *mnt_opts,
620 unsigned long kern_flags, 633 unsigned long kern_flags,
621 unsigned long *set_kern_flags) 634 unsigned long *set_kern_flags)
622{ 635{
@@ -628,9 +641,10 @@ static int selinux_set_mnt_opts(struct super_block *sb,
628 struct inode_security_struct *root_isec; 641 struct inode_security_struct *root_isec;
629 u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0; 642 u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0;
630 u32 defcontext_sid = 0; 643 u32 defcontext_sid = 0;
631 char **mount_options = opts->mnt_opts; 644 struct security_mnt_opts *opts = mnt_opts;
632 int *flags = opts->mnt_opts_flags; 645 char **mount_options = opts ? opts->mnt_opts : NULL;
633 int num_opts = opts->num_mnt_opts; 646 int *flags = opts ? opts->mnt_opts_flags : NULL;
647 int num_opts = opts ? opts->num_mnt_opts : 0;
634 648
635 mutex_lock(&sbsec->lock); 649 mutex_lock(&sbsec->lock);
636 650
@@ -982,12 +996,20 @@ out:
982} 996}
983 997
984static int selinux_parse_opts_str(char *options, 998static int selinux_parse_opts_str(char *options,
985 struct security_mnt_opts *opts) 999 void **mnt_opts)
986{ 1000{
987 char *p; 1001 char *p;
988 char *context = NULL, *defcontext = NULL; 1002 char *context = NULL, *defcontext = NULL;
989 char *fscontext = NULL, *rootcontext = NULL; 1003 char *fscontext = NULL, *rootcontext = NULL;
990 int rc, num_mnt_opts = 0; 1004 int rc, num_mnt_opts = 0;
1005 struct security_mnt_opts *opts = *mnt_opts;
1006
1007 if (!opts) {
1008 opts = kzalloc(sizeof(struct security_mnt_opts), GFP_KERNEL);
1009 *mnt_opts = opts;
1010 if (!opts)
1011 return -ENOMEM;
1012 }
991 1013
992 opts->num_mnt_opts = 0; 1014 opts->num_mnt_opts = 0;
993 1015
@@ -1094,7 +1116,7 @@ static int selinux_parse_opts_str(char *options,
1094 return 0; 1116 return 0;
1095 1117
1096out_err: 1118out_err:
1097 security_free_mnt_opts(opts); 1119 security_free_mnt_opts(mnt_opts);
1098 kfree(context); 1120 kfree(context);
1099 kfree(defcontext); 1121 kfree(defcontext);
1100 kfree(fscontext); 1122 kfree(fscontext);
@@ -2714,7 +2736,7 @@ out:
2714 return rc; 2736 return rc;
2715} 2737}
2716 2738
2717static int selinux_sb_eat_lsm_opts(char *options, struct security_mnt_opts *opts) 2739static int selinux_sb_eat_lsm_opts(char *options, void **mnt_opts)
2718{ 2740{
2719 char *s = (char *)get_zeroed_page(GFP_KERNEL); 2741 char *s = (char *)get_zeroed_page(GFP_KERNEL);
2720 int err; 2742 int err;
@@ -2723,14 +2745,14 @@ static int selinux_sb_eat_lsm_opts(char *options, struct security_mnt_opts *opts
2723 return -ENOMEM; 2745 return -ENOMEM;
2724 err = selinux_sb_copy_data(options, s); 2746 err = selinux_sb_copy_data(options, s);
2725 if (!err) 2747 if (!err)
2726 err = selinux_parse_opts_str(s, opts); 2748 err = selinux_parse_opts_str(s, mnt_opts);
2727 free_page((unsigned long)s); 2749 free_page((unsigned long)s);
2728 return err; 2750 return err;
2729} 2751}
2730 2752
2731static int selinux_sb_remount(struct super_block *sb, 2753static int selinux_sb_remount(struct super_block *sb, void *mnt_opts)
2732 struct security_mnt_opts *opts)
2733{ 2754{
2755 struct security_mnt_opts *opts = mnt_opts;
2734 int i, *flags; 2756 int i, *flags;
2735 char **mount_options; 2757 char **mount_options;
2736 struct superblock_security_struct *sbsec = sb->s_security; 2758 struct superblock_security_struct *sbsec = sb->s_security;
@@ -2738,6 +2760,9 @@ static int selinux_sb_remount(struct super_block *sb,
2738 if (!(sbsec->flags & SE_SBINITIALIZED)) 2760 if (!(sbsec->flags & SE_SBINITIALIZED))
2739 return 0; 2761 return 0;
2740 2762
2763 if (!opts)
2764 return 0;
2765
2741 mount_options = opts->mnt_opts; 2766 mount_options = opts->mnt_opts;
2742 flags = opts->mnt_opts_flags; 2767 flags = opts->mnt_opts_flags;
2743 2768
@@ -6782,6 +6807,7 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
6782 LSM_HOOK_INIT(sb_alloc_security, selinux_sb_alloc_security), 6807 LSM_HOOK_INIT(sb_alloc_security, selinux_sb_alloc_security),
6783 LSM_HOOK_INIT(sb_free_security, selinux_sb_free_security), 6808 LSM_HOOK_INIT(sb_free_security, selinux_sb_free_security),
6784 LSM_HOOK_INIT(sb_eat_lsm_opts, selinux_sb_eat_lsm_opts), 6809 LSM_HOOK_INIT(sb_eat_lsm_opts, selinux_sb_eat_lsm_opts),
6810 LSM_HOOK_INIT(sb_free_mnt_opts, selinux_free_mnt_opts),
6785 LSM_HOOK_INIT(sb_remount, selinux_sb_remount), 6811 LSM_HOOK_INIT(sb_remount, selinux_sb_remount),
6786 LSM_HOOK_INIT(sb_kern_mount, selinux_sb_kern_mount), 6812 LSM_HOOK_INIT(sb_kern_mount, selinux_sb_kern_mount),
6787 LSM_HOOK_INIT(sb_show_options, selinux_sb_show_options), 6813 LSM_HOOK_INIT(sb_show_options, selinux_sb_show_options),
@@ -7051,11 +7077,7 @@ static __init int selinux_init(void)
7051 7077
7052static void delayed_superblock_init(struct super_block *sb, void *unused) 7078static void delayed_superblock_init(struct super_block *sb, void *unused)
7053{ 7079{
7054 struct security_mnt_opts opts; 7080 selinux_set_mnt_opts(sb, NULL, 0, NULL);
7055
7056 security_init_mnt_opts(&opts);
7057 selinux_set_mnt_opts(sb, &opts, 0, NULL);
7058 security_free_mnt_opts(&opts);
7059} 7081}
7060 7082
7061void selinux_complete_init(void) 7083void selinux_complete_init(void)
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 835cca277c2a..81a8112975d4 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -567,6 +567,19 @@ static void smack_sb_free_security(struct super_block *sb)
567 sb->s_security = NULL; 567 sb->s_security = NULL;
568} 568}
569 569
570static void smack_free_mnt_opts(void *mnt_opts)
571{
572 struct security_mnt_opts *opts = mnt_opts;
573 int i;
574
575 if (opts->mnt_opts)
576 for (i = 0; i < opts->num_mnt_opts; i++)
577 kfree(opts->mnt_opts[i]);
578 kfree(opts->mnt_opts);
579 kfree(opts->mnt_opts_flags);
580 kfree(opts);
581}
582
570/** 583/**
571 * smack_sb_copy_data - copy mount options data for processing 584 * smack_sb_copy_data - copy mount options data for processing
572 * @orig: where to start 585 * @orig: where to start
@@ -624,8 +637,9 @@ static int smack_sb_copy_data(char *orig, char *smackopts)
624 * converts Smack specific mount options to generic security option format 637 * converts Smack specific mount options to generic security option format
625 */ 638 */
626static int smack_parse_opts_str(char *options, 639static int smack_parse_opts_str(char *options,
627 struct security_mnt_opts *opts) 640 void **mnt_opts)
628{ 641{
642 struct security_mnt_opts *opts = *mnt_opts;
629 char *p; 643 char *p;
630 char *fsdefault = NULL; 644 char *fsdefault = NULL;
631 char *fsfloor = NULL; 645 char *fsfloor = NULL;
@@ -636,11 +650,17 @@ static int smack_parse_opts_str(char *options,
636 int num_mnt_opts = 0; 650 int num_mnt_opts = 0;
637 int token; 651 int token;
638 652
639 opts->num_mnt_opts = 0;
640
641 if (!options) 653 if (!options)
642 return 0; 654 return 0;
643 655
656 if (!opts) {
657 opts = kzalloc(sizeof(struct security_mnt_opts), GFP_KERNEL);
658 *mnt_opts = opts;
659 if (!opts)
660 return -ENOMEM;
661 }
662 opts->num_mnt_opts = 0;
663
644 while ((p = strsep(&options, ",")) != NULL) { 664 while ((p = strsep(&options, ",")) != NULL) {
645 substring_t args[MAX_OPT_ARGS]; 665 substring_t args[MAX_OPT_ARGS];
646 666
@@ -735,11 +755,11 @@ out_err:
735 kfree(fshat); 755 kfree(fshat);
736 kfree(fsroot); 756 kfree(fsroot);
737 kfree(fstransmute); 757 kfree(fstransmute);
738 security_free_mnt_opts(opts); 758 security_free_mnt_opts(mnt_opts);
739 return rc; 759 return rc;
740} 760}
741 761
742static int smack_sb_eat_lsm_opts(char *options, struct security_mnt_opts *opts) 762static int smack_sb_eat_lsm_opts(char *options, void **mnt_opts)
743{ 763{
744 char *s = (char *)get_zeroed_page(GFP_KERNEL); 764 char *s = (char *)get_zeroed_page(GFP_KERNEL);
745 int err; 765 int err;
@@ -748,7 +768,7 @@ static int smack_sb_eat_lsm_opts(char *options, struct security_mnt_opts *opts)
748 return -ENOMEM; 768 return -ENOMEM;
749 err = smack_sb_copy_data(options, s); 769 err = smack_sb_copy_data(options, s);
750 if (!err) 770 if (!err)
751 err = smack_parse_opts_str(s, opts); 771 err = smack_parse_opts_str(s, mnt_opts);
752 free_page((unsigned long)s); 772 free_page((unsigned long)s);
753 return err; 773 return err;
754} 774}
@@ -766,7 +786,7 @@ static int smack_sb_eat_lsm_opts(char *options, struct security_mnt_opts *opts)
766 * labels. 786 * labels.
767 */ 787 */
768static int smack_set_mnt_opts(struct super_block *sb, 788static int smack_set_mnt_opts(struct super_block *sb,
769 struct security_mnt_opts *opts, 789 void *mnt_opts,
770 unsigned long kern_flags, 790 unsigned long kern_flags,
771 unsigned long *set_kern_flags) 791 unsigned long *set_kern_flags)
772{ 792{
@@ -776,7 +796,8 @@ static int smack_set_mnt_opts(struct super_block *sb,
776 struct inode_smack *isp; 796 struct inode_smack *isp;
777 struct smack_known *skp; 797 struct smack_known *skp;
778 int i; 798 int i;
779 int num_opts = opts->num_mnt_opts; 799 struct security_mnt_opts *opts = mnt_opts;
800 int num_opts = opts ? opts->num_mnt_opts : 0;
780 int transmute = 0; 801 int transmute = 0;
781 802
782 if (sp->smk_flags & SMK_SB_INITIALIZED) 803 if (sp->smk_flags & SMK_SB_INITIALIZED)
@@ -4651,6 +4672,7 @@ static struct security_hook_list smack_hooks[] __lsm_ro_after_init = {
4651 4672
4652 LSM_HOOK_INIT(sb_alloc_security, smack_sb_alloc_security), 4673 LSM_HOOK_INIT(sb_alloc_security, smack_sb_alloc_security),
4653 LSM_HOOK_INIT(sb_free_security, smack_sb_free_security), 4674 LSM_HOOK_INIT(sb_free_security, smack_sb_free_security),
4675 LSM_HOOK_INIT(sb_free_mnt_opts, smack_free_mnt_opts),
4654 LSM_HOOK_INIT(sb_eat_lsm_opts, smack_sb_eat_lsm_opts), 4676 LSM_HOOK_INIT(sb_eat_lsm_opts, smack_sb_eat_lsm_opts),
4655 LSM_HOOK_INIT(sb_statfs, smack_sb_statfs), 4677 LSM_HOOK_INIT(sb_statfs, smack_sb_statfs),
4656 LSM_HOOK_INIT(sb_set_mnt_opts, smack_set_mnt_opts), 4678 LSM_HOOK_INIT(sb_set_mnt_opts, smack_set_mnt_opts),