summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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),