aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Paris <eparis@redhat.com>2008-03-05 10:31:54 -0500
committerJames Morris <jmorris@namei.org>2008-03-05 16:40:53 -0500
commite0007529893c1c064be90bd21422ca0da4a0198e (patch)
treec2334ba940e682183a18d18972cf95bd3a3da46a
parent29e8c3c304b62f31b799565c9ee85d42bd163f80 (diff)
LSM/SELinux: Interfaces to allow FS to control mount options
Introduce new LSM interfaces to allow an FS to deal with their own mount options. This includes a new string parsing function exported from the LSM that an FS can use to get a security data blob and a new security data blob. This is particularly useful for an FS which uses binary mount data, like NFS, which does not pass strings into the vfs to be handled by the loaded LSM. Also fix a BUG() in both SELinux and SMACK when dealing with binary mount data. If the binary mount data is less than one page the copy_page() in security_sb_copy_data() can cause an illegal page fault and boom. Remove all NFSisms from the SELinux code since they were broken by past NFS changes. Signed-off-by: Eric Paris <eparis@redhat.com> Acked-by: Stephen Smalley <sds@tycho.nsa.gov> Acked-by: Casey Schaufler <casey@schaufler-ca.com> Signed-off-by: James Morris <jmorris@namei.org>
-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;