aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/super.c4
-rw-r--r--include/linux/security.h99
-rw-r--r--security/dummy.c23
-rw-r--r--security/security.c23
-rw-r--r--security/selinux/hooks.c175
-rw-r--r--security/selinux/include/security.h5
-rw-r--r--security/smack/smack_lsm.c9
7 files changed, 204 insertions, 134 deletions
diff --git a/fs/super.c b/fs/super.c
index 88811f60c8de..010446d8c40a 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -870,12 +870,12 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void
870 if (!mnt) 870 if (!mnt)
871 goto out; 871 goto out;
872 872
873 if (data) { 873 if (data && !(type->fs_flags & FS_BINARY_MOUNTDATA)) {
874 secdata = alloc_secdata(); 874 secdata = alloc_secdata();
875 if (!secdata) 875 if (!secdata)
876 goto out_mnt; 876 goto out_mnt;
877 877
878 error = security_sb_copy_data(type, data, secdata); 878 error = security_sb_copy_data(data, secdata);
879 if (error) 879 if (error)
880 goto out_free_secdata; 880 goto out_free_secdata;
881 } 881 }
diff --git a/include/linux/security.h b/include/linux/security.h
index fe52cdeab0a6..b07357ca2137 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -34,12 +34,6 @@
34#include <linux/xfrm.h> 34#include <linux/xfrm.h>
35#include <net/flow.h> 35#include <net/flow.h>
36 36
37/* only a char in selinux superblock security struct flags */
38#define FSCONTEXT_MNT 0x01
39#define CONTEXT_MNT 0x02
40#define ROOTCONTEXT_MNT 0x04
41#define DEFCONTEXT_MNT 0x08
42
43extern unsigned securebits; 37extern unsigned securebits;
44 38
45struct ctl_table; 39struct ctl_table;
@@ -114,6 +108,32 @@ struct request_sock;
114 108
115#ifdef CONFIG_SECURITY 109#ifdef CONFIG_SECURITY
116 110
111struct security_mnt_opts {
112 char **mnt_opts;
113 int *mnt_opts_flags;
114 int num_mnt_opts;
115};
116
117static inline void security_init_mnt_opts(struct security_mnt_opts *opts)
118{
119 opts->mnt_opts = NULL;
120 opts->mnt_opts_flags = NULL;
121 opts->num_mnt_opts = 0;
122}
123
124static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
125{
126 int i;
127 if (opts->mnt_opts)
128 for(i = 0; i < opts->num_mnt_opts; i++)
129 kfree(opts->mnt_opts[i]);
130 kfree(opts->mnt_opts);
131 opts->mnt_opts = NULL;
132 kfree(opts->mnt_opts_flags);
133 opts->mnt_opts_flags = NULL;
134 opts->num_mnt_opts = 0;
135}
136
117/** 137/**
118 * struct security_operations - main security structure 138 * struct security_operations - main security structure
119 * 139 *
@@ -262,19 +282,19 @@ struct request_sock;
262 * @sb_get_mnt_opts: 282 * @sb_get_mnt_opts:
263 * Get the security relevant mount options used for a superblock 283 * Get the security relevant mount options used for a superblock
264 * @sb the superblock to get security mount options from 284 * @sb the superblock to get security mount options from
265 * @mount_options array for pointers to mount options 285 * @opts binary data structure containing all lsm mount data
266 * @mount_flags array of ints specifying what each mount options is
267 * @num_opts number of options in the arrays
268 * @sb_set_mnt_opts: 286 * @sb_set_mnt_opts:
269 * Set the security relevant mount options used for a superblock 287 * Set the security relevant mount options used for a superblock
270 * @sb the superblock to set security mount options for 288 * @sb the superblock to set security mount options for
271 * @mount_options array for pointers to mount options 289 * @opts binary data structure containing all lsm mount data
272 * @mount_flags array of ints specifying what each mount options is
273 * @num_opts number of options in the arrays
274 * @sb_clone_mnt_opts: 290 * @sb_clone_mnt_opts:
275 * Copy all security options from a given superblock to another 291 * Copy all security options from a given superblock to another
276 * @oldsb old superblock which contain information to clone 292 * @oldsb old superblock which contain information to clone
277 * @newsb new superblock which needs filled in 293 * @newsb new superblock which needs filled in
294 * @sb_parse_opts_str:
295 * Parse a string of security data filling in the opts structure
296 * @options string containing all mount options known by the LSM
297 * @opts binary data structure usable by the LSM
278 * 298 *
279 * Security hooks for inode operations. 299 * Security hooks for inode operations.
280 * 300 *
@@ -1238,8 +1258,7 @@ struct security_operations {
1238 1258
1239 int (*sb_alloc_security) (struct super_block * sb); 1259 int (*sb_alloc_security) (struct super_block * sb);
1240 void (*sb_free_security) (struct super_block * sb); 1260 void (*sb_free_security) (struct super_block * sb);
1241 int (*sb_copy_data)(struct file_system_type *type, 1261 int (*sb_copy_data)(char *orig, char *copy);
1242 void *orig, void *copy);
1243 int (*sb_kern_mount) (struct super_block *sb, void *data); 1262 int (*sb_kern_mount) (struct super_block *sb, void *data);
1244 int (*sb_statfs) (struct dentry *dentry); 1263 int (*sb_statfs) (struct dentry *dentry);
1245 int (*sb_mount) (char *dev_name, struct nameidata * nd, 1264 int (*sb_mount) (char *dev_name, struct nameidata * nd,
@@ -1257,12 +1276,12 @@ struct security_operations {
1257 void (*sb_post_pivotroot) (struct nameidata * old_nd, 1276 void (*sb_post_pivotroot) (struct nameidata * old_nd,
1258 struct nameidata * new_nd); 1277 struct nameidata * new_nd);
1259 int (*sb_get_mnt_opts) (const struct super_block *sb, 1278 int (*sb_get_mnt_opts) (const struct super_block *sb,
1260 char ***mount_options, int **flags, 1279 struct security_mnt_opts *opts);
1261 int *num_opts); 1280 int (*sb_set_mnt_opts) (struct super_block *sb,
1262 int (*sb_set_mnt_opts) (struct super_block *sb, char **mount_options, 1281 struct security_mnt_opts *opts);
1263 int *flags, int num_opts);
1264 void (*sb_clone_mnt_opts) (const struct super_block *oldsb, 1282 void (*sb_clone_mnt_opts) (const struct super_block *oldsb,
1265 struct super_block *newsb); 1283 struct super_block *newsb);
1284 int (*sb_parse_opts_str) (char *options, struct security_mnt_opts *opts);
1266 1285
1267 int (*inode_alloc_security) (struct inode *inode); 1286 int (*inode_alloc_security) (struct inode *inode);
1268 void (*inode_free_security) (struct inode *inode); 1287 void (*inode_free_security) (struct inode *inode);
@@ -1507,7 +1526,7 @@ int security_bprm_check(struct linux_binprm *bprm);
1507int security_bprm_secureexec(struct linux_binprm *bprm); 1526int security_bprm_secureexec(struct linux_binprm *bprm);
1508int security_sb_alloc(struct super_block *sb); 1527int security_sb_alloc(struct super_block *sb);
1509void security_sb_free(struct super_block *sb); 1528void security_sb_free(struct super_block *sb);
1510int security_sb_copy_data(struct file_system_type *type, void *orig, void *copy); 1529int security_sb_copy_data(char *orig, char *copy);
1511int security_sb_kern_mount(struct super_block *sb, void *data); 1530int security_sb_kern_mount(struct super_block *sb, void *data);
1512int security_sb_statfs(struct dentry *dentry); 1531int security_sb_statfs(struct dentry *dentry);
1513int security_sb_mount(char *dev_name, struct nameidata *nd, 1532int security_sb_mount(char *dev_name, struct nameidata *nd,
@@ -1520,12 +1539,12 @@ void security_sb_post_remount(struct vfsmount *mnt, unsigned long flags, void *d
1520void security_sb_post_addmount(struct vfsmount *mnt, struct nameidata *mountpoint_nd); 1539void security_sb_post_addmount(struct vfsmount *mnt, struct nameidata *mountpoint_nd);
1521int security_sb_pivotroot(struct nameidata *old_nd, struct nameidata *new_nd); 1540int security_sb_pivotroot(struct nameidata *old_nd, struct nameidata *new_nd);
1522void security_sb_post_pivotroot(struct nameidata *old_nd, struct nameidata *new_nd); 1541void security_sb_post_pivotroot(struct nameidata *old_nd, struct nameidata *new_nd);
1523int security_sb_get_mnt_opts(const struct super_block *sb, char ***mount_options, 1542int security_sb_get_mnt_opts(const struct super_block *sb,
1524 int **flags, int *num_opts); 1543 struct security_mnt_opts *opts);
1525int security_sb_set_mnt_opts(struct super_block *sb, char **mount_options, 1544int security_sb_set_mnt_opts(struct super_block *sb, struct security_mnt_opts *opts);
1526 int *flags, int num_opts);
1527void security_sb_clone_mnt_opts(const struct super_block *oldsb, 1545void security_sb_clone_mnt_opts(const struct super_block *oldsb,
1528 struct super_block *newsb); 1546 struct super_block *newsb);
1547int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts);
1529 1548
1530int security_inode_alloc(struct inode *inode); 1549int security_inode_alloc(struct inode *inode);
1531void security_inode_free(struct inode *inode); 1550void security_inode_free(struct inode *inode);
@@ -1635,6 +1654,16 @@ int security_secctx_to_secid(char *secdata, u32 seclen, u32 *secid);
1635void security_release_secctx(char *secdata, u32 seclen); 1654void security_release_secctx(char *secdata, u32 seclen);
1636 1655
1637#else /* CONFIG_SECURITY */ 1656#else /* CONFIG_SECURITY */
1657struct security_mnt_opts {
1658};
1659
1660static inline void security_init_mnt_opts(struct security_mnt_opts *opts)
1661{
1662}
1663
1664static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
1665{
1666}
1638 1667
1639/* 1668/*
1640 * This is the default capabilities functionality. Most of these functions 1669 * This is the default capabilities functionality. Most of these functions
@@ -1762,8 +1791,7 @@ static inline int security_sb_alloc (struct super_block *sb)
1762static inline void security_sb_free (struct super_block *sb) 1791static inline void security_sb_free (struct super_block *sb)
1763{ } 1792{ }
1764 1793
1765static inline int security_sb_copy_data (struct file_system_type *type, 1794static inline int security_sb_copy_data (char *orig, char *copy)
1766 void *orig, void *copy)
1767{ 1795{
1768 return 0; 1796 return 0;
1769} 1797}
@@ -1819,6 +1847,27 @@ static inline int security_sb_pivotroot (struct nameidata *old_nd,
1819static inline void security_sb_post_pivotroot (struct nameidata *old_nd, 1847static inline void security_sb_post_pivotroot (struct nameidata *old_nd,
1820 struct nameidata *new_nd) 1848 struct nameidata *new_nd)
1821{ } 1849{ }
1850static inline int security_sb_get_mnt_opts(const struct super_block *sb,
1851 struct security_mnt_opts *opts)
1852{
1853 security_init_mnt_opts(opts);
1854 return 0;
1855}
1856
1857static inline int security_sb_set_mnt_opts(struct super_block *sb,
1858 struct security_mnt_opts *opts)
1859{
1860 return 0;
1861}
1862
1863static inline void security_sb_clone_mnt_opts(const struct super_block *oldsb,
1864 struct super_block *newsb)
1865{ }
1866
1867static inline int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts)
1868{
1869 return 0;
1870}
1822 1871
1823static inline int security_inode_alloc (struct inode *inode) 1872static inline int security_inode_alloc (struct inode *inode)
1824{ 1873{
diff --git a/security/dummy.c b/security/dummy.c
index 649326bf64ea..78d8f92310a4 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -181,8 +181,7 @@ static void dummy_sb_free_security (struct super_block *sb)
181 return; 181 return;
182} 182}
183 183
184static int dummy_sb_copy_data (struct file_system_type *type, 184static int dummy_sb_copy_data (char *orig, char *copy)
185 void *orig, void *copy)
186{ 185{
187 return 0; 186 return 0;
188} 187}
@@ -245,19 +244,17 @@ static void dummy_sb_post_pivotroot (struct nameidata *old_nd, struct nameidata
245 return; 244 return;
246} 245}
247 246
248static int dummy_sb_get_mnt_opts(const struct super_block *sb, char ***mount_options, 247static int dummy_sb_get_mnt_opts(const struct super_block *sb,
249 int **flags, int *num_opts) 248 struct security_mnt_opts *opts)
250{ 249{
251 *mount_options = NULL; 250 security_init_mnt_opts(opts);
252 *flags = NULL;
253 *num_opts = 0;
254 return 0; 251 return 0;
255} 252}
256 253
257static int dummy_sb_set_mnt_opts(struct super_block *sb, char **mount_options, 254static int dummy_sb_set_mnt_opts(struct super_block *sb,
258 int *flags, int num_opts) 255 struct security_mnt_opts *opts)
259{ 256{
260 if (unlikely(num_opts)) 257 if (unlikely(opts->num_mnt_opts))
261 return -EOPNOTSUPP; 258 return -EOPNOTSUPP;
262 return 0; 259 return 0;
263} 260}
@@ -268,6 +265,11 @@ static void dummy_sb_clone_mnt_opts(const struct super_block *oldsb,
268 return; 265 return;
269} 266}
270 267
268static int dummy_sb_parse_opts_str(char *options, struct security_mnt_opts *opts)
269{
270 return 0;
271}
272
271static int dummy_inode_alloc_security (struct inode *inode) 273static int dummy_inode_alloc_security (struct inode *inode)
272{ 274{
273 return 0; 275 return 0;
@@ -1028,6 +1030,7 @@ void security_fixup_ops (struct security_operations *ops)
1028 set_to_dummy_if_null(ops, sb_get_mnt_opts); 1030 set_to_dummy_if_null(ops, sb_get_mnt_opts);
1029 set_to_dummy_if_null(ops, sb_set_mnt_opts); 1031 set_to_dummy_if_null(ops, sb_set_mnt_opts);
1030 set_to_dummy_if_null(ops, sb_clone_mnt_opts); 1032 set_to_dummy_if_null(ops, sb_clone_mnt_opts);
1033 set_to_dummy_if_null(ops, sb_parse_opts_str);
1031 set_to_dummy_if_null(ops, inode_alloc_security); 1034 set_to_dummy_if_null(ops, inode_alloc_security);
1032 set_to_dummy_if_null(ops, inode_free_security); 1035 set_to_dummy_if_null(ops, inode_free_security);
1033 set_to_dummy_if_null(ops, inode_init_security); 1036 set_to_dummy_if_null(ops, inode_init_security);
diff --git a/security/security.c b/security/security.c
index d15e56cbaade..b1387a6b416d 100644
--- a/security/security.c
+++ b/security/security.c
@@ -244,10 +244,11 @@ void security_sb_free(struct super_block *sb)
244 security_ops->sb_free_security(sb); 244 security_ops->sb_free_security(sb);
245} 245}
246 246
247int security_sb_copy_data(struct file_system_type *type, void *orig, void *copy) 247int security_sb_copy_data(char *orig, char *copy)
248{ 248{
249 return security_ops->sb_copy_data(type, orig, copy); 249 return security_ops->sb_copy_data(orig, copy);
250} 250}
251EXPORT_SYMBOL(security_sb_copy_data);
251 252
252int security_sb_kern_mount(struct super_block *sb, void *data) 253int security_sb_kern_mount(struct super_block *sb, void *data)
253{ 254{
@@ -306,24 +307,30 @@ void security_sb_post_pivotroot(struct nameidata *old_nd, struct nameidata *new_
306} 307}
307 308
308int security_sb_get_mnt_opts(const struct super_block *sb, 309int security_sb_get_mnt_opts(const struct super_block *sb,
309 char ***mount_options, 310 struct security_mnt_opts *opts)
310 int **flags, int *num_opts)
311{ 311{
312 return security_ops->sb_get_mnt_opts(sb, mount_options, flags, num_opts); 312 return security_ops->sb_get_mnt_opts(sb, opts);
313} 313}
314 314
315int security_sb_set_mnt_opts(struct super_block *sb, 315int security_sb_set_mnt_opts(struct super_block *sb,
316 char **mount_options, 316 struct security_mnt_opts *opts)
317 int *flags, int num_opts)
318{ 317{
319 return security_ops->sb_set_mnt_opts(sb, mount_options, flags, num_opts); 318 return security_ops->sb_set_mnt_opts(sb, opts);
320} 319}
320EXPORT_SYMBOL(security_sb_set_mnt_opts);
321 321
322void security_sb_clone_mnt_opts(const struct super_block *oldsb, 322void security_sb_clone_mnt_opts(const struct super_block *oldsb,
323 struct super_block *newsb) 323 struct super_block *newsb)
324{ 324{
325 security_ops->sb_clone_mnt_opts(oldsb, newsb); 325 security_ops->sb_clone_mnt_opts(oldsb, newsb);
326} 326}
327EXPORT_SYMBOL(security_sb_clone_mnt_opts);
328
329int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts)
330{
331 return security_ops->sb_parse_opts_str(options, opts);
332}
333EXPORT_SYMBOL(security_sb_parse_opts_str);
327 334
328int security_inode_alloc(struct inode *inode) 335int security_inode_alloc(struct inode *inode)
329{ 336{
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 75c2e99bfb81..4bf4807f2d44 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -443,8 +443,7 @@ out:
443 * mount options, or whatever. 443 * mount options, or whatever.
444 */ 444 */
445static int selinux_get_mnt_opts(const struct super_block *sb, 445static int selinux_get_mnt_opts(const struct super_block *sb,
446 char ***mount_options, int **mnt_opts_flags, 446 struct security_mnt_opts *opts)
447 int *num_opts)
448{ 447{
449 int rc = 0, i; 448 int rc = 0, i;
450 struct superblock_security_struct *sbsec = sb->s_security; 449 struct superblock_security_struct *sbsec = sb->s_security;
@@ -452,9 +451,7 @@ static int selinux_get_mnt_opts(const struct super_block *sb,
452 u32 len; 451 u32 len;
453 char tmp; 452 char tmp;
454 453
455 *num_opts = 0; 454 security_init_mnt_opts(opts);
456 *mount_options = NULL;
457 *mnt_opts_flags = NULL;
458 455
459 if (!sbsec->initialized) 456 if (!sbsec->initialized)
460 return -EINVAL; 457 return -EINVAL;
@@ -470,18 +467,18 @@ static int selinux_get_mnt_opts(const struct super_block *sb,
470 /* count the number of mount options for this sb */ 467 /* count the number of mount options for this sb */
471 for (i = 0; i < 8; i++) { 468 for (i = 0; i < 8; i++) {
472 if (tmp & 0x01) 469 if (tmp & 0x01)
473 (*num_opts)++; 470 opts->num_mnt_opts++;
474 tmp >>= 1; 471 tmp >>= 1;
475 } 472 }
476 473
477 *mount_options = kcalloc(*num_opts, sizeof(char *), GFP_ATOMIC); 474 opts->mnt_opts = kcalloc(opts->num_mnt_opts, sizeof(char *), GFP_ATOMIC);
478 if (!*mount_options) { 475 if (!opts->mnt_opts) {
479 rc = -ENOMEM; 476 rc = -ENOMEM;
480 goto out_free; 477 goto out_free;
481 } 478 }
482 479
483 *mnt_opts_flags = kcalloc(*num_opts, sizeof(int), GFP_ATOMIC); 480 opts->mnt_opts_flags = kcalloc(opts->num_mnt_opts, sizeof(int), GFP_ATOMIC);
484 if (!*mnt_opts_flags) { 481 if (!opts->mnt_opts_flags) {
485 rc = -ENOMEM; 482 rc = -ENOMEM;
486 goto out_free; 483 goto out_free;
487 } 484 }
@@ -491,22 +488,22 @@ static int selinux_get_mnt_opts(const struct super_block *sb,
491 rc = security_sid_to_context(sbsec->sid, &context, &len); 488 rc = security_sid_to_context(sbsec->sid, &context, &len);
492 if (rc) 489 if (rc)
493 goto out_free; 490 goto out_free;
494 (*mount_options)[i] = context; 491 opts->mnt_opts[i] = context;
495 (*mnt_opts_flags)[i++] = FSCONTEXT_MNT; 492 opts->mnt_opts_flags[i++] = FSCONTEXT_MNT;
496 } 493 }
497 if (sbsec->flags & CONTEXT_MNT) { 494 if (sbsec->flags & CONTEXT_MNT) {
498 rc = security_sid_to_context(sbsec->mntpoint_sid, &context, &len); 495 rc = security_sid_to_context(sbsec->mntpoint_sid, &context, &len);
499 if (rc) 496 if (rc)
500 goto out_free; 497 goto out_free;
501 (*mount_options)[i] = context; 498 opts->mnt_opts[i] = context;
502 (*mnt_opts_flags)[i++] = CONTEXT_MNT; 499 opts->mnt_opts_flags[i++] = CONTEXT_MNT;
503 } 500 }
504 if (sbsec->flags & DEFCONTEXT_MNT) { 501 if (sbsec->flags & DEFCONTEXT_MNT) {
505 rc = security_sid_to_context(sbsec->def_sid, &context, &len); 502 rc = security_sid_to_context(sbsec->def_sid, &context, &len);
506 if (rc) 503 if (rc)
507 goto out_free; 504 goto out_free;
508 (*mount_options)[i] = context; 505 opts->mnt_opts[i] = context;
509 (*mnt_opts_flags)[i++] = DEFCONTEXT_MNT; 506 opts->mnt_opts_flags[i++] = DEFCONTEXT_MNT;
510 } 507 }
511 if (sbsec->flags & ROOTCONTEXT_MNT) { 508 if (sbsec->flags & ROOTCONTEXT_MNT) {
512 struct inode *root = sbsec->sb->s_root->d_inode; 509 struct inode *root = sbsec->sb->s_root->d_inode;
@@ -515,24 +512,16 @@ static int selinux_get_mnt_opts(const struct super_block *sb,
515 rc = security_sid_to_context(isec->sid, &context, &len); 512 rc = security_sid_to_context(isec->sid, &context, &len);
516 if (rc) 513 if (rc)
517 goto out_free; 514 goto out_free;
518 (*mount_options)[i] = context; 515 opts->mnt_opts[i] = context;
519 (*mnt_opts_flags)[i++] = ROOTCONTEXT_MNT; 516 opts->mnt_opts_flags[i++] = ROOTCONTEXT_MNT;
520 } 517 }
521 518
522 BUG_ON(i != *num_opts); 519 BUG_ON(i != opts->num_mnt_opts);
523 520
524 return 0; 521 return 0;
525 522
526out_free: 523out_free:
527 /* don't leak context string if security_sid_to_context had an error */ 524 security_free_mnt_opts(opts);
528 if (*mount_options && i)
529 for (; i > 0; i--)
530 kfree((*mount_options)[i-1]);
531 kfree(*mount_options);
532 *mount_options = NULL;
533 kfree(*mnt_opts_flags);
534 *mnt_opts_flags = NULL;
535 *num_opts = 0;
536 return rc; 525 return rc;
537} 526}
538 527
@@ -553,12 +542,13 @@ static int bad_option(struct superblock_security_struct *sbsec, char flag,
553 return 1; 542 return 1;
554 return 0; 543 return 0;
555} 544}
545
556/* 546/*
557 * Allow filesystems with binary mount data to explicitly set mount point 547 * Allow filesystems with binary mount data to explicitly set mount point
558 * labeling information. 548 * labeling information.
559 */ 549 */
560static int selinux_set_mnt_opts(struct super_block *sb, char **mount_options, 550static int selinux_set_mnt_opts(struct super_block *sb,
561 int *flags, int num_opts) 551 struct security_mnt_opts *opts)
562{ 552{
563 int rc = 0, i; 553 int rc = 0, i;
564 struct task_security_struct *tsec = current->security; 554 struct task_security_struct *tsec = current->security;
@@ -568,6 +558,9 @@ static int selinux_set_mnt_opts(struct super_block *sb, char **mount_options,
568 struct inode_security_struct *root_isec = inode->i_security; 558 struct inode_security_struct *root_isec = inode->i_security;
569 u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0; 559 u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0;
570 u32 defcontext_sid = 0; 560 u32 defcontext_sid = 0;
561 char **mount_options = opts->mnt_opts;
562 int *flags = opts->mnt_opts_flags;
563 int num_opts = opts->num_mnt_opts;
571 564
572 mutex_lock(&sbsec->lock); 565 mutex_lock(&sbsec->lock);
573 566
@@ -589,6 +582,21 @@ static int selinux_set_mnt_opts(struct super_block *sb, char **mount_options,
589 } 582 }
590 583
591 /* 584 /*
585 * Binary mount data FS will come through this function twice. Once
586 * from an explicit call and once from the generic calls from the vfs.
587 * Since the generic VFS calls will not contain any security mount data
588 * we need to skip the double mount verification.
589 *
590 * This does open a hole in which we will not notice if the first
591 * mount using this sb set explict options and a second mount using
592 * this sb does not set any security options. (The first options
593 * will be used for both mounts)
594 */
595 if (sbsec->initialized && (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)
596 && (num_opts == 0))
597 goto out;
598
599 /*
592 * parse the mount options, check if they are valid sids. 600 * parse the mount options, check if they are valid sids.
593 * also check if someone is trying to mount the same sb more 601 * also check if someone is trying to mount the same sb more
594 * than once with different security options. 602 * than once with different security options.
@@ -792,43 +800,14 @@ static void selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
792 mutex_unlock(&newsbsec->lock); 800 mutex_unlock(&newsbsec->lock);
793} 801}
794 802
795/* 803int selinux_parse_opts_str(char *options, struct security_mnt_opts *opts)
796 * string mount options parsing and call set the sbsec
797 */
798static int superblock_doinit(struct super_block *sb, void *data)
799{ 804{
805 char *p;
800 char *context = NULL, *defcontext = NULL; 806 char *context = NULL, *defcontext = NULL;
801 char *fscontext = NULL, *rootcontext = NULL; 807 char *fscontext = NULL, *rootcontext = NULL;
802 int rc = 0; 808 int rc, num_mnt_opts = 0;
803 char *p, *options = data;
804 /* selinux only know about a fixed number of mount options */
805 char *mnt_opts[NUM_SEL_MNT_OPTS];
806 int mnt_opts_flags[NUM_SEL_MNT_OPTS], num_mnt_opts = 0;
807
808 if (!data)
809 goto out;
810 809
811 /* with the nfs patch this will become a goto out; */ 810 opts->num_mnt_opts = 0;
812 if (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA) {
813 const char *name = sb->s_type->name;
814 /* NFS we understand. */
815 if (!strcmp(name, "nfs")) {
816 struct nfs_mount_data *d = data;
817
818 if (d->version != NFS_MOUNT_VERSION)
819 goto out;
820
821 if (d->context[0]) {
822 context = kstrdup(d->context, GFP_KERNEL);
823 if (!context) {
824 rc = -ENOMEM;
825 goto out;
826 }
827 }
828 goto build_flags;
829 } else
830 goto out;
831 }
832 811
833 /* Standard string-based options. */ 812 /* Standard string-based options. */
834 while ((p = strsep(&options, "|")) != NULL) { 813 while ((p = strsep(&options, "|")) != NULL) {
@@ -901,26 +880,37 @@ static int superblock_doinit(struct super_block *sb, void *data)
901 } 880 }
902 } 881 }
903 882
904build_flags: 883 rc = -ENOMEM;
884 opts->mnt_opts = kcalloc(NUM_SEL_MNT_OPTS, sizeof(char *), GFP_ATOMIC);
885 if (!opts->mnt_opts)
886 goto out_err;
887
888 opts->mnt_opts_flags = kcalloc(NUM_SEL_MNT_OPTS, sizeof(int), GFP_ATOMIC);
889 if (!opts->mnt_opts_flags) {
890 kfree(opts->mnt_opts);
891 goto out_err;
892 }
893
905 if (fscontext) { 894 if (fscontext) {
906 mnt_opts[num_mnt_opts] = fscontext; 895 opts->mnt_opts[num_mnt_opts] = fscontext;
907 mnt_opts_flags[num_mnt_opts++] = FSCONTEXT_MNT; 896 opts->mnt_opts_flags[num_mnt_opts++] = FSCONTEXT_MNT;
908 } 897 }
909 if (context) { 898 if (context) {
910 mnt_opts[num_mnt_opts] = context; 899 opts->mnt_opts[num_mnt_opts] = context;
911 mnt_opts_flags[num_mnt_opts++] = CONTEXT_MNT; 900 opts->mnt_opts_flags[num_mnt_opts++] = CONTEXT_MNT;
912 } 901 }
913 if (rootcontext) { 902 if (rootcontext) {
914 mnt_opts[num_mnt_opts] = rootcontext; 903 opts->mnt_opts[num_mnt_opts] = rootcontext;
915 mnt_opts_flags[num_mnt_opts++] = ROOTCONTEXT_MNT; 904 opts->mnt_opts_flags[num_mnt_opts++] = ROOTCONTEXT_MNT;
916 } 905 }
917 if (defcontext) { 906 if (defcontext) {
918 mnt_opts[num_mnt_opts] = defcontext; 907 opts->mnt_opts[num_mnt_opts] = defcontext;
919 mnt_opts_flags[num_mnt_opts++] = DEFCONTEXT_MNT; 908 opts->mnt_opts_flags[num_mnt_opts++] = DEFCONTEXT_MNT;
920 } 909 }
921 910
922out: 911 opts->num_mnt_opts = num_mnt_opts;
923 rc = selinux_set_mnt_opts(sb, mnt_opts, mnt_opts_flags, num_mnt_opts); 912 return 0;
913
924out_err: 914out_err:
925 kfree(context); 915 kfree(context);
926 kfree(defcontext); 916 kfree(defcontext);
@@ -928,6 +918,33 @@ out_err:
928 kfree(rootcontext); 918 kfree(rootcontext);
929 return rc; 919 return rc;
930} 920}
921/*
922 * string mount options parsing and call set the sbsec
923 */
924static int superblock_doinit(struct super_block *sb, void *data)
925{
926 int rc = 0;
927 char *options = data;
928 struct security_mnt_opts opts;
929
930 security_init_mnt_opts(&opts);
931
932 if (!data)
933 goto out;
934
935 BUG_ON(sb->s_type->fs_flags & FS_BINARY_MOUNTDATA);
936
937 rc = selinux_parse_opts_str(options, &opts);
938 if (rc)
939 goto out_err;
940
941out:
942 rc = selinux_set_mnt_opts(sb, &opts);
943
944out_err:
945 security_free_mnt_opts(&opts);
946 return rc;
947}
931 948
932static inline u16 inode_mode_to_security_class(umode_t mode) 949static inline u16 inode_mode_to_security_class(umode_t mode)
933{ 950{
@@ -2253,7 +2270,7 @@ static inline void take_selinux_option(char **to, char *from, int *first,
2253 } 2270 }
2254} 2271}
2255 2272
2256static int selinux_sb_copy_data(struct file_system_type *type, void *orig, void *copy) 2273static int selinux_sb_copy_data(char *orig, char *copy)
2257{ 2274{
2258 int fnosec, fsec, rc = 0; 2275 int fnosec, fsec, rc = 0;
2259 char *in_save, *in_curr, *in_end; 2276 char *in_save, *in_curr, *in_end;
@@ -2263,12 +2280,6 @@ static int selinux_sb_copy_data(struct file_system_type *type, void *orig, void
2263 in_curr = orig; 2280 in_curr = orig;
2264 sec_curr = copy; 2281 sec_curr = copy;
2265 2282
2266 /* Binary mount data: just copy */
2267 if (type->fs_flags & FS_BINARY_MOUNTDATA) {
2268 copy_page(sec_curr, in_curr);
2269 goto out;
2270 }
2271
2272 nosec = (char *)get_zeroed_page(GFP_KERNEL); 2283 nosec = (char *)get_zeroed_page(GFP_KERNEL);
2273 if (!nosec) { 2284 if (!nosec) {
2274 rc = -ENOMEM; 2285 rc = -ENOMEM;
@@ -5251,6 +5262,8 @@ static struct security_operations selinux_ops = {
5251 .sb_get_mnt_opts = selinux_get_mnt_opts, 5262 .sb_get_mnt_opts = selinux_get_mnt_opts,
5252 .sb_set_mnt_opts = selinux_set_mnt_opts, 5263 .sb_set_mnt_opts = selinux_set_mnt_opts,
5253 .sb_clone_mnt_opts = selinux_sb_clone_mnt_opts, 5264 .sb_clone_mnt_opts = selinux_sb_clone_mnt_opts,
5265 .sb_parse_opts_str = selinux_parse_opts_str,
5266
5254 5267
5255 .inode_alloc_security = selinux_inode_alloc_security, 5268 .inode_alloc_security = selinux_inode_alloc_security,
5256 .inode_free_security = selinux_inode_free_security, 5269 .inode_free_security = selinux_inode_free_security,
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
index 837ce420d2f6..f7d2f03781f2 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -35,6 +35,11 @@
35#define POLICYDB_VERSION_MAX POLICYDB_VERSION_POLCAP 35#define POLICYDB_VERSION_MAX POLICYDB_VERSION_POLCAP
36#endif 36#endif
37 37
38#define CONTEXT_MNT 0x01
39#define FSCONTEXT_MNT 0x02
40#define ROOTCONTEXT_MNT 0x04
41#define DEFCONTEXT_MNT 0x08
42
38struct netlbl_lsm_secattr; 43struct netlbl_lsm_secattr;
39 44
40extern int selinux_enabled; 45extern int selinux_enabled;
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 770eb067e165..0241fd359675 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -189,17 +189,10 @@ static void smack_sb_free_security(struct super_block *sb)
189 * Copy the Smack specific mount options out of the mount 189 * Copy the Smack specific mount options out of the mount
190 * options list. 190 * options list.
191 */ 191 */
192static int smack_sb_copy_data(struct file_system_type *type, void *orig, 192static int smack_sb_copy_data(char *orig, char *smackopts)
193 void *smackopts)
194{ 193{
195 char *cp, *commap, *otheropts, *dp; 194 char *cp, *commap, *otheropts, *dp;
196 195
197 /* Binary mount data: just copy */
198 if (type->fs_flags & FS_BINARY_MOUNTDATA) {
199 copy_page(smackopts, orig);
200 return 0;
201 }
202
203 otheropts = (char *)get_zeroed_page(GFP_KERNEL); 196 otheropts = (char *)get_zeroed_page(GFP_KERNEL);
204 if (otheropts == NULL) 197 if (otheropts == NULL)
205 return -ENOMEM; 198 return -ENOMEM;