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>

authored by Eric Paris and committed by James Morris e0007529 29e8c3c3

+211 -141
+2 -2
fs/super.c
··· 870 if (!mnt) 871 goto out; 872 873 - if (data) { 874 secdata = alloc_secdata(); 875 if (!secdata) 876 goto out_mnt; 877 878 - error = security_sb_copy_data(type, data, secdata); 879 if (error) 880 goto out_free_secdata; 881 }
··· 870 if (!mnt) 871 goto out; 872 873 + if (data && !(type->fs_flags & FS_BINARY_MOUNTDATA)) { 874 secdata = alloc_secdata(); 875 if (!secdata) 876 goto out_mnt; 877 878 + error = security_sb_copy_data(data, secdata); 879 if (error) 880 goto out_free_secdata; 881 }
+74 -25
include/linux/security.h
··· 34 #include <linux/xfrm.h> 35 #include <net/flow.h> 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 - 43 extern unsigned securebits; 44 45 struct ctl_table; ··· 107 #define LSM_UNSAFE_PTRACE_CAP 4 108 109 #ifdef CONFIG_SECURITY 110 111 /** 112 * struct security_operations - main security structure ··· 282 * @sb_get_mnt_opts: 283 * Get the security relevant mount options used for a superblock 284 * @sb the superblock to get security mount options from 285 - * @mount_options array for pointers to mount options 286 - * @mount_flags array of ints specifying what each mount options is 287 - * @num_opts number of options in the arrays 288 * @sb_set_mnt_opts: 289 * Set the security relevant mount options used for a superblock 290 * @sb the superblock to set security mount options for 291 - * @mount_options array for pointers to mount options 292 - * @mount_flags array of ints specifying what each mount options is 293 - * @num_opts number of options in the arrays 294 * @sb_clone_mnt_opts: 295 * Copy all security options from a given superblock to another 296 * @oldsb old superblock which contain information to clone 297 * @newsb new superblock which needs filled in 298 * 299 * Security hooks for inode operations. 300 * ··· 1258 1259 int (*sb_alloc_security) (struct super_block * sb); 1260 void (*sb_free_security) (struct super_block * sb); 1261 - int (*sb_copy_data)(struct file_system_type *type, 1262 - void *orig, void *copy); 1263 int (*sb_kern_mount) (struct super_block *sb, void *data); 1264 int (*sb_statfs) (struct dentry *dentry); 1265 int (*sb_mount) (char *dev_name, struct nameidata * nd, ··· 1276 void (*sb_post_pivotroot) (struct nameidata * old_nd, 1277 struct nameidata * new_nd); 1278 int (*sb_get_mnt_opts) (const struct super_block *sb, 1279 - char ***mount_options, int **flags, 1280 - int *num_opts); 1281 - int (*sb_set_mnt_opts) (struct super_block *sb, char **mount_options, 1282 - int *flags, int num_opts); 1283 void (*sb_clone_mnt_opts) (const struct super_block *oldsb, 1284 struct super_block *newsb); 1285 1286 int (*inode_alloc_security) (struct inode *inode); 1287 void (*inode_free_security) (struct inode *inode); ··· 1526 int security_bprm_secureexec(struct linux_binprm *bprm); 1527 int security_sb_alloc(struct super_block *sb); 1528 void security_sb_free(struct super_block *sb); 1529 - int security_sb_copy_data(struct file_system_type *type, void *orig, void *copy); 1530 int security_sb_kern_mount(struct super_block *sb, void *data); 1531 int security_sb_statfs(struct dentry *dentry); 1532 int security_sb_mount(char *dev_name, struct nameidata *nd, ··· 1539 void security_sb_post_addmount(struct vfsmount *mnt, struct nameidata *mountpoint_nd); 1540 int security_sb_pivotroot(struct nameidata *old_nd, struct nameidata *new_nd); 1541 void security_sb_post_pivotroot(struct nameidata *old_nd, struct nameidata *new_nd); 1542 - int security_sb_get_mnt_opts(const struct super_block *sb, char ***mount_options, 1543 - int **flags, int *num_opts); 1544 - int security_sb_set_mnt_opts(struct super_block *sb, char **mount_options, 1545 - int *flags, int num_opts); 1546 void security_sb_clone_mnt_opts(const struct super_block *oldsb, 1547 struct super_block *newsb); 1548 1549 int security_inode_alloc(struct inode *inode); 1550 void security_inode_free(struct inode *inode); ··· 1654 void security_release_secctx(char *secdata, u32 seclen); 1655 1656 #else /* CONFIG_SECURITY */ 1657 1658 /* 1659 * This is the default capabilities functionality. Most of these functions ··· 1791 static inline void security_sb_free (struct super_block *sb) 1792 { } 1793 1794 - static inline int security_sb_copy_data (struct file_system_type *type, 1795 - void *orig, void *copy) 1796 { 1797 return 0; 1798 } ··· 1847 static inline void security_sb_post_pivotroot (struct nameidata *old_nd, 1848 struct nameidata *new_nd) 1849 { } 1850 1851 static inline int security_inode_alloc (struct inode *inode) 1852 {
··· 34 #include <linux/xfrm.h> 35 #include <net/flow.h> 36 37 extern unsigned securebits; 38 39 struct ctl_table; ··· 113 #define LSM_UNSAFE_PTRACE_CAP 4 114 115 #ifdef CONFIG_SECURITY 116 + 117 + struct security_mnt_opts { 118 + char **mnt_opts; 119 + int *mnt_opts_flags; 120 + int num_mnt_opts; 121 + }; 122 + 123 + static inline void security_init_mnt_opts(struct security_mnt_opts *opts) 124 + { 125 + opts->mnt_opts = NULL; 126 + opts->mnt_opts_flags = NULL; 127 + opts->num_mnt_opts = 0; 128 + } 129 + 130 + static inline void security_free_mnt_opts(struct security_mnt_opts *opts) 131 + { 132 + int i; 133 + if (opts->mnt_opts) 134 + for(i = 0; i < opts->num_mnt_opts; i++) 135 + kfree(opts->mnt_opts[i]); 136 + kfree(opts->mnt_opts); 137 + opts->mnt_opts = NULL; 138 + kfree(opts->mnt_opts_flags); 139 + opts->mnt_opts_flags = NULL; 140 + opts->num_mnt_opts = 0; 141 + } 142 143 /** 144 * struct security_operations - main security structure ··· 262 * @sb_get_mnt_opts: 263 * Get the security relevant mount options used for a superblock 264 * @sb the superblock to get security mount options from 265 + * @opts binary data structure containing all lsm mount data 266 * @sb_set_mnt_opts: 267 * Set the security relevant mount options used for a superblock 268 * @sb the superblock to set security mount options for 269 + * @opts binary data structure containing all lsm mount data 270 * @sb_clone_mnt_opts: 271 * Copy all security options from a given superblock to another 272 * @oldsb old superblock which contain information to clone 273 * @newsb new superblock which needs filled in 274 + * @sb_parse_opts_str: 275 + * Parse a string of security data filling in the opts structure 276 + * @options string containing all mount options known by the LSM 277 + * @opts binary data structure usable by the LSM 278 * 279 * Security hooks for inode operations. 280 * ··· 1238 1239 int (*sb_alloc_security) (struct super_block * sb); 1240 void (*sb_free_security) (struct super_block * sb); 1241 + int (*sb_copy_data)(char *orig, char *copy); 1242 int (*sb_kern_mount) (struct super_block *sb, void *data); 1243 int (*sb_statfs) (struct dentry *dentry); 1244 int (*sb_mount) (char *dev_name, struct nameidata * nd, ··· 1257 void (*sb_post_pivotroot) (struct nameidata * old_nd, 1258 struct nameidata * new_nd); 1259 int (*sb_get_mnt_opts) (const struct super_block *sb, 1260 + struct security_mnt_opts *opts); 1261 + int (*sb_set_mnt_opts) (struct super_block *sb, 1262 + struct security_mnt_opts *opts); 1263 void (*sb_clone_mnt_opts) (const struct super_block *oldsb, 1264 struct super_block *newsb); 1265 + int (*sb_parse_opts_str) (char *options, struct security_mnt_opts *opts); 1266 1267 int (*inode_alloc_security) (struct inode *inode); 1268 void (*inode_free_security) (struct inode *inode); ··· 1507 int security_bprm_secureexec(struct linux_binprm *bprm); 1508 int security_sb_alloc(struct super_block *sb); 1509 void security_sb_free(struct super_block *sb); 1510 + int security_sb_copy_data(char *orig, char *copy); 1511 int security_sb_kern_mount(struct super_block *sb, void *data); 1512 int security_sb_statfs(struct dentry *dentry); 1513 int security_sb_mount(char *dev_name, struct nameidata *nd, ··· 1520 void security_sb_post_addmount(struct vfsmount *mnt, struct nameidata *mountpoint_nd); 1521 int security_sb_pivotroot(struct nameidata *old_nd, struct nameidata *new_nd); 1522 void security_sb_post_pivotroot(struct nameidata *old_nd, struct nameidata *new_nd); 1523 + int security_sb_get_mnt_opts(const struct super_block *sb, 1524 + struct security_mnt_opts *opts); 1525 + int security_sb_set_mnt_opts(struct super_block *sb, struct security_mnt_opts *opts); 1526 void security_sb_clone_mnt_opts(const struct super_block *oldsb, 1527 struct super_block *newsb); 1528 + int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts); 1529 1530 int security_inode_alloc(struct inode *inode); 1531 void security_inode_free(struct inode *inode); ··· 1635 void security_release_secctx(char *secdata, u32 seclen); 1636 1637 #else /* CONFIG_SECURITY */ 1638 + struct security_mnt_opts { 1639 + }; 1640 + 1641 + static inline void security_init_mnt_opts(struct security_mnt_opts *opts) 1642 + { 1643 + } 1644 + 1645 + static inline void security_free_mnt_opts(struct security_mnt_opts *opts) 1646 + { 1647 + } 1648 1649 /* 1650 * This is the default capabilities functionality. Most of these functions ··· 1762 static inline void security_sb_free (struct super_block *sb) 1763 { } 1764 1765 + static inline int security_sb_copy_data (char *orig, char *copy) 1766 { 1767 return 0; 1768 } ··· 1819 static inline void security_sb_post_pivotroot (struct nameidata *old_nd, 1820 struct nameidata *new_nd) 1821 { } 1822 + static inline int security_sb_get_mnt_opts(const struct super_block *sb, 1823 + struct security_mnt_opts *opts) 1824 + { 1825 + security_init_mnt_opts(opts); 1826 + return 0; 1827 + } 1828 + 1829 + static inline int security_sb_set_mnt_opts(struct super_block *sb, 1830 + struct security_mnt_opts *opts) 1831 + { 1832 + return 0; 1833 + } 1834 + 1835 + static inline void security_sb_clone_mnt_opts(const struct super_block *oldsb, 1836 + struct super_block *newsb) 1837 + { } 1838 + 1839 + static inline int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts) 1840 + { 1841 + return 0; 1842 + } 1843 1844 static inline int security_inode_alloc (struct inode *inode) 1845 {
+13 -10
security/dummy.c
··· 181 return; 182 } 183 184 - static int dummy_sb_copy_data (struct file_system_type *type, 185 - void *orig, void *copy) 186 { 187 return 0; 188 } ··· 244 return; 245 } 246 247 - static int dummy_sb_get_mnt_opts(const struct super_block *sb, char ***mount_options, 248 - int **flags, int *num_opts) 249 { 250 - *mount_options = NULL; 251 - *flags = NULL; 252 - *num_opts = 0; 253 return 0; 254 } 255 256 - static int dummy_sb_set_mnt_opts(struct super_block *sb, char **mount_options, 257 - int *flags, int num_opts) 258 { 259 - if (unlikely(num_opts)) 260 return -EOPNOTSUPP; 261 return 0; 262 } ··· 263 struct super_block *newsb) 264 { 265 return; 266 } 267 268 static int dummy_inode_alloc_security (struct inode *inode) ··· 1030 set_to_dummy_if_null(ops, sb_get_mnt_opts); 1031 set_to_dummy_if_null(ops, sb_set_mnt_opts); 1032 set_to_dummy_if_null(ops, sb_clone_mnt_opts); 1033 set_to_dummy_if_null(ops, inode_alloc_security); 1034 set_to_dummy_if_null(ops, inode_free_security); 1035 set_to_dummy_if_null(ops, inode_init_security);
··· 181 return; 182 } 183 184 + static int dummy_sb_copy_data (char *orig, char *copy) 185 { 186 return 0; 187 } ··· 245 return; 246 } 247 248 + static int dummy_sb_get_mnt_opts(const struct super_block *sb, 249 + struct security_mnt_opts *opts) 250 { 251 + security_init_mnt_opts(opts); 252 return 0; 253 } 254 255 + static int dummy_sb_set_mnt_opts(struct super_block *sb, 256 + struct security_mnt_opts *opts) 257 { 258 + if (unlikely(opts->num_mnt_opts)) 259 return -EOPNOTSUPP; 260 return 0; 261 } ··· 266 struct super_block *newsb) 267 { 268 return; 269 + } 270 + 271 + static int dummy_sb_parse_opts_str(char *options, struct security_mnt_opts *opts) 272 + { 273 + return 0; 274 } 275 276 static int dummy_inode_alloc_security (struct inode *inode) ··· 1028 set_to_dummy_if_null(ops, sb_get_mnt_opts); 1029 set_to_dummy_if_null(ops, sb_set_mnt_opts); 1030 set_to_dummy_if_null(ops, sb_clone_mnt_opts); 1031 + set_to_dummy_if_null(ops, sb_parse_opts_str); 1032 set_to_dummy_if_null(ops, inode_alloc_security); 1033 set_to_dummy_if_null(ops, inode_free_security); 1034 set_to_dummy_if_null(ops, inode_init_security);
+15 -8
security/security.c
··· 244 security_ops->sb_free_security(sb); 245 } 246 247 - int security_sb_copy_data(struct file_system_type *type, void *orig, void *copy) 248 { 249 - return security_ops->sb_copy_data(type, orig, copy); 250 } 251 252 int security_sb_kern_mount(struct super_block *sb, void *data) 253 { ··· 307 } 308 309 int security_sb_get_mnt_opts(const struct super_block *sb, 310 - char ***mount_options, 311 - int **flags, int *num_opts) 312 { 313 - return security_ops->sb_get_mnt_opts(sb, mount_options, flags, num_opts); 314 } 315 316 int security_sb_set_mnt_opts(struct super_block *sb, 317 - char **mount_options, 318 - int *flags, int num_opts) 319 { 320 - return security_ops->sb_set_mnt_opts(sb, mount_options, flags, num_opts); 321 } 322 323 void security_sb_clone_mnt_opts(const struct super_block *oldsb, 324 struct super_block *newsb) 325 { 326 security_ops->sb_clone_mnt_opts(oldsb, newsb); 327 } 328 329 int security_inode_alloc(struct inode *inode) 330 {
··· 244 security_ops->sb_free_security(sb); 245 } 246 247 + int security_sb_copy_data(char *orig, char *copy) 248 { 249 + return security_ops->sb_copy_data(orig, copy); 250 } 251 + EXPORT_SYMBOL(security_sb_copy_data); 252 253 int security_sb_kern_mount(struct super_block *sb, void *data) 254 { ··· 306 } 307 308 int security_sb_get_mnt_opts(const struct super_block *sb, 309 + struct security_mnt_opts *opts) 310 { 311 + return security_ops->sb_get_mnt_opts(sb, opts); 312 } 313 314 int security_sb_set_mnt_opts(struct super_block *sb, 315 + struct security_mnt_opts *opts) 316 { 317 + return security_ops->sb_set_mnt_opts(sb, opts); 318 } 319 + EXPORT_SYMBOL(security_sb_set_mnt_opts); 320 321 void security_sb_clone_mnt_opts(const struct super_block *oldsb, 322 struct super_block *newsb) 323 { 324 security_ops->sb_clone_mnt_opts(oldsb, newsb); 325 } 326 + EXPORT_SYMBOL(security_sb_clone_mnt_opts); 327 + 328 + int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts) 329 + { 330 + return security_ops->sb_parse_opts_str(options, opts); 331 + } 332 + EXPORT_SYMBOL(security_sb_parse_opts_str); 333 334 int security_inode_alloc(struct inode *inode) 335 {
+101 -88
security/selinux/hooks.c
··· 443 * mount options, or whatever. 444 */ 445 static int selinux_get_mnt_opts(const struct super_block *sb, 446 - char ***mount_options, int **mnt_opts_flags, 447 - int *num_opts) 448 { 449 int rc = 0, i; 450 struct superblock_security_struct *sbsec = sb->s_security; ··· 451 u32 len; 452 char tmp; 453 454 - *num_opts = 0; 455 - *mount_options = NULL; 456 - *mnt_opts_flags = NULL; 457 458 if (!sbsec->initialized) 459 return -EINVAL; ··· 467 /* count the number of mount options for this sb */ 468 for (i = 0; i < 8; i++) { 469 if (tmp & 0x01) 470 - (*num_opts)++; 471 tmp >>= 1; 472 } 473 474 - *mount_options = kcalloc(*num_opts, sizeof(char *), GFP_ATOMIC); 475 - if (!*mount_options) { 476 rc = -ENOMEM; 477 goto out_free; 478 } 479 480 - *mnt_opts_flags = kcalloc(*num_opts, sizeof(int), GFP_ATOMIC); 481 - if (!*mnt_opts_flags) { 482 rc = -ENOMEM; 483 goto out_free; 484 } ··· 488 rc = security_sid_to_context(sbsec->sid, &context, &len); 489 if (rc) 490 goto out_free; 491 - (*mount_options)[i] = context; 492 - (*mnt_opts_flags)[i++] = FSCONTEXT_MNT; 493 } 494 if (sbsec->flags & CONTEXT_MNT) { 495 rc = security_sid_to_context(sbsec->mntpoint_sid, &context, &len); 496 if (rc) 497 goto out_free; 498 - (*mount_options)[i] = context; 499 - (*mnt_opts_flags)[i++] = CONTEXT_MNT; 500 } 501 if (sbsec->flags & DEFCONTEXT_MNT) { 502 rc = security_sid_to_context(sbsec->def_sid, &context, &len); 503 if (rc) 504 goto out_free; 505 - (*mount_options)[i] = context; 506 - (*mnt_opts_flags)[i++] = DEFCONTEXT_MNT; 507 } 508 if (sbsec->flags & ROOTCONTEXT_MNT) { 509 struct inode *root = sbsec->sb->s_root->d_inode; ··· 512 rc = security_sid_to_context(isec->sid, &context, &len); 513 if (rc) 514 goto out_free; 515 - (*mount_options)[i] = context; 516 - (*mnt_opts_flags)[i++] = ROOTCONTEXT_MNT; 517 } 518 519 - BUG_ON(i != *num_opts); 520 521 return 0; 522 523 out_free: 524 - /* don't leak context string if security_sid_to_context had an error */ 525 - if (*mount_options && i) 526 - for (; i > 0; i--) 527 - kfree((*mount_options)[i-1]); 528 - kfree(*mount_options); 529 - *mount_options = NULL; 530 - kfree(*mnt_opts_flags); 531 - *mnt_opts_flags = NULL; 532 - *num_opts = 0; 533 return rc; 534 } 535 ··· 542 return 1; 543 return 0; 544 } 545 /* 546 * Allow filesystems with binary mount data to explicitly set mount point 547 * labeling information. 548 */ 549 - static int selinux_set_mnt_opts(struct super_block *sb, char **mount_options, 550 - int *flags, int num_opts) 551 { 552 int rc = 0, i; 553 struct task_security_struct *tsec = current->security; ··· 558 struct inode_security_struct *root_isec = inode->i_security; 559 u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0; 560 u32 defcontext_sid = 0; 561 562 mutex_lock(&sbsec->lock); 563 ··· 580 "the security server is initialized\n"); 581 goto out; 582 } 583 584 /* 585 * parse the mount options, check if they are valid sids. ··· 800 mutex_unlock(&newsbsec->lock); 801 } 802 803 - /* 804 - * string mount options parsing and call set the sbsec 805 - */ 806 - static int superblock_doinit(struct super_block *sb, void *data) 807 { 808 char *context = NULL, *defcontext = NULL; 809 char *fscontext = NULL, *rootcontext = NULL; 810 - int rc = 0; 811 - char *p, *options = data; 812 - /* selinux only know about a fixed number of mount options */ 813 - char *mnt_opts[NUM_SEL_MNT_OPTS]; 814 - int mnt_opts_flags[NUM_SEL_MNT_OPTS], num_mnt_opts = 0; 815 816 - if (!data) 817 - goto out; 818 - 819 - /* with the nfs patch this will become a goto out; */ 820 - if (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA) { 821 - const char *name = sb->s_type->name; 822 - /* NFS we understand. */ 823 - if (!strcmp(name, "nfs")) { 824 - struct nfs_mount_data *d = data; 825 - 826 - if (d->version != NFS_MOUNT_VERSION) 827 - goto out; 828 - 829 - if (d->context[0]) { 830 - context = kstrdup(d->context, GFP_KERNEL); 831 - if (!context) { 832 - rc = -ENOMEM; 833 - goto out; 834 - } 835 - } 836 - goto build_flags; 837 - } else 838 - goto out; 839 - } 840 841 /* Standard string-based options. */ 842 while ((p = strsep(&options, "|")) != NULL) { ··· 880 } 881 } 882 883 - build_flags: 884 - if (fscontext) { 885 - mnt_opts[num_mnt_opts] = fscontext; 886 - mnt_opts_flags[num_mnt_opts++] = FSCONTEXT_MNT; 887 - } 888 - if (context) { 889 - mnt_opts[num_mnt_opts] = context; 890 - mnt_opts_flags[num_mnt_opts++] = CONTEXT_MNT; 891 - } 892 - if (rootcontext) { 893 - mnt_opts[num_mnt_opts] = rootcontext; 894 - mnt_opts_flags[num_mnt_opts++] = ROOTCONTEXT_MNT; 895 - } 896 - if (defcontext) { 897 - mnt_opts[num_mnt_opts] = defcontext; 898 - mnt_opts_flags[num_mnt_opts++] = DEFCONTEXT_MNT; 899 } 900 901 - out: 902 - rc = selinux_set_mnt_opts(sb, mnt_opts, mnt_opts_flags, num_mnt_opts); 903 out_err: 904 kfree(context); 905 kfree(defcontext); 906 kfree(fscontext); 907 kfree(rootcontext); 908 return rc; 909 } 910 ··· 2270 } 2271 } 2272 2273 - static int selinux_sb_copy_data(struct file_system_type *type, void *orig, void *copy) 2274 { 2275 int fnosec, fsec, rc = 0; 2276 char *in_save, *in_curr, *in_end; ··· 2279 2280 in_curr = orig; 2281 sec_curr = copy; 2282 - 2283 - /* Binary mount data: just copy */ 2284 - if (type->fs_flags & FS_BINARY_MOUNTDATA) { 2285 - copy_page(sec_curr, in_curr); 2286 - goto out; 2287 - } 2288 2289 nosec = (char *)get_zeroed_page(GFP_KERNEL); 2290 if (!nosec) { ··· 5262 .sb_get_mnt_opts = selinux_get_mnt_opts, 5263 .sb_set_mnt_opts = selinux_set_mnt_opts, 5264 .sb_clone_mnt_opts = selinux_sb_clone_mnt_opts, 5265 5266 .inode_alloc_security = selinux_inode_alloc_security, 5267 .inode_free_security = selinux_inode_free_security,
··· 443 * mount options, or whatever. 444 */ 445 static int selinux_get_mnt_opts(const struct super_block *sb, 446 + struct security_mnt_opts *opts) 447 { 448 int rc = 0, i; 449 struct superblock_security_struct *sbsec = sb->s_security; ··· 452 u32 len; 453 char tmp; 454 455 + security_init_mnt_opts(opts); 456 457 if (!sbsec->initialized) 458 return -EINVAL; ··· 470 /* count the number of mount options for this sb */ 471 for (i = 0; i < 8; i++) { 472 if (tmp & 0x01) 473 + opts->num_mnt_opts++; 474 tmp >>= 1; 475 } 476 477 + opts->mnt_opts = kcalloc(opts->num_mnt_opts, sizeof(char *), GFP_ATOMIC); 478 + if (!opts->mnt_opts) { 479 rc = -ENOMEM; 480 goto out_free; 481 } 482 483 + opts->mnt_opts_flags = kcalloc(opts->num_mnt_opts, sizeof(int), GFP_ATOMIC); 484 + if (!opts->mnt_opts_flags) { 485 rc = -ENOMEM; 486 goto out_free; 487 } ··· 491 rc = security_sid_to_context(sbsec->sid, &context, &len); 492 if (rc) 493 goto out_free; 494 + opts->mnt_opts[i] = context; 495 + opts->mnt_opts_flags[i++] = FSCONTEXT_MNT; 496 } 497 if (sbsec->flags & CONTEXT_MNT) { 498 rc = security_sid_to_context(sbsec->mntpoint_sid, &context, &len); 499 if (rc) 500 goto out_free; 501 + opts->mnt_opts[i] = context; 502 + opts->mnt_opts_flags[i++] = CONTEXT_MNT; 503 } 504 if (sbsec->flags & DEFCONTEXT_MNT) { 505 rc = security_sid_to_context(sbsec->def_sid, &context, &len); 506 if (rc) 507 goto out_free; 508 + opts->mnt_opts[i] = context; 509 + opts->mnt_opts_flags[i++] = DEFCONTEXT_MNT; 510 } 511 if (sbsec->flags & ROOTCONTEXT_MNT) { 512 struct inode *root = sbsec->sb->s_root->d_inode; ··· 515 rc = security_sid_to_context(isec->sid, &context, &len); 516 if (rc) 517 goto out_free; 518 + opts->mnt_opts[i] = context; 519 + opts->mnt_opts_flags[i++] = ROOTCONTEXT_MNT; 520 } 521 522 + BUG_ON(i != opts->num_mnt_opts); 523 524 return 0; 525 526 out_free: 527 + security_free_mnt_opts(opts); 528 return rc; 529 } 530 ··· 553 return 1; 554 return 0; 555 } 556 + 557 /* 558 * Allow filesystems with binary mount data to explicitly set mount point 559 * labeling information. 560 */ 561 + static int selinux_set_mnt_opts(struct super_block *sb, 562 + struct security_mnt_opts *opts) 563 { 564 int rc = 0, i; 565 struct task_security_struct *tsec = current->security; ··· 568 struct inode_security_struct *root_isec = inode->i_security; 569 u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0; 570 u32 defcontext_sid = 0; 571 + char **mount_options = opts->mnt_opts; 572 + int *flags = opts->mnt_opts_flags; 573 + int num_opts = opts->num_mnt_opts; 574 575 mutex_lock(&sbsec->lock); 576 ··· 587 "the security server is initialized\n"); 588 goto out; 589 } 590 + 591 + /* 592 + * Binary mount data FS will come through this function twice. Once 593 + * from an explicit call and once from the generic calls from the vfs. 594 + * Since the generic VFS calls will not contain any security mount data 595 + * we need to skip the double mount verification. 596 + * 597 + * This does open a hole in which we will not notice if the first 598 + * mount using this sb set explict options and a second mount using 599 + * this sb does not set any security options. (The first options 600 + * will be used for both mounts) 601 + */ 602 + if (sbsec->initialized && (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA) 603 + && (num_opts == 0)) 604 + goto out; 605 606 /* 607 * parse the mount options, check if they are valid sids. ··· 792 mutex_unlock(&newsbsec->lock); 793 } 794 795 + int selinux_parse_opts_str(char *options, struct security_mnt_opts *opts) 796 { 797 + char *p; 798 char *context = NULL, *defcontext = NULL; 799 char *fscontext = NULL, *rootcontext = NULL; 800 + int rc, num_mnt_opts = 0; 801 802 + opts->num_mnt_opts = 0; 803 804 /* Standard string-based options. */ 805 while ((p = strsep(&options, "|")) != NULL) { ··· 901 } 902 } 903 904 + rc = -ENOMEM; 905 + opts->mnt_opts = kcalloc(NUM_SEL_MNT_OPTS, sizeof(char *), GFP_ATOMIC); 906 + if (!opts->mnt_opts) 907 + goto out_err; 908 + 909 + opts->mnt_opts_flags = kcalloc(NUM_SEL_MNT_OPTS, sizeof(int), GFP_ATOMIC); 910 + if (!opts->mnt_opts_flags) { 911 + kfree(opts->mnt_opts); 912 + goto out_err; 913 } 914 915 + if (fscontext) { 916 + opts->mnt_opts[num_mnt_opts] = fscontext; 917 + opts->mnt_opts_flags[num_mnt_opts++] = FSCONTEXT_MNT; 918 + } 919 + if (context) { 920 + opts->mnt_opts[num_mnt_opts] = context; 921 + opts->mnt_opts_flags[num_mnt_opts++] = CONTEXT_MNT; 922 + } 923 + if (rootcontext) { 924 + opts->mnt_opts[num_mnt_opts] = rootcontext; 925 + opts->mnt_opts_flags[num_mnt_opts++] = ROOTCONTEXT_MNT; 926 + } 927 + if (defcontext) { 928 + opts->mnt_opts[num_mnt_opts] = defcontext; 929 + opts->mnt_opts_flags[num_mnt_opts++] = DEFCONTEXT_MNT; 930 + } 931 + 932 + opts->num_mnt_opts = num_mnt_opts; 933 + return 0; 934 + 935 out_err: 936 kfree(context); 937 kfree(defcontext); 938 kfree(fscontext); 939 kfree(rootcontext); 940 + return rc; 941 + } 942 + /* 943 + * string mount options parsing and call set the sbsec 944 + */ 945 + static int superblock_doinit(struct super_block *sb, void *data) 946 + { 947 + int rc = 0; 948 + char *options = data; 949 + struct security_mnt_opts opts; 950 + 951 + security_init_mnt_opts(&opts); 952 + 953 + if (!data) 954 + goto out; 955 + 956 + BUG_ON(sb->s_type->fs_flags & FS_BINARY_MOUNTDATA); 957 + 958 + rc = selinux_parse_opts_str(options, &opts); 959 + if (rc) 960 + goto out_err; 961 + 962 + out: 963 + rc = selinux_set_mnt_opts(sb, &opts); 964 + 965 + out_err: 966 + security_free_mnt_opts(&opts); 967 return rc; 968 } 969 ··· 2253 } 2254 } 2255 2256 + static int selinux_sb_copy_data(char *orig, char *copy) 2257 { 2258 int fnosec, fsec, rc = 0; 2259 char *in_save, *in_curr, *in_end; ··· 2262 2263 in_curr = orig; 2264 sec_curr = copy; 2265 2266 nosec = (char *)get_zeroed_page(GFP_KERNEL); 2267 if (!nosec) { ··· 5251 .sb_get_mnt_opts = selinux_get_mnt_opts, 5252 .sb_set_mnt_opts = selinux_set_mnt_opts, 5253 .sb_clone_mnt_opts = selinux_sb_clone_mnt_opts, 5254 + .sb_parse_opts_str = selinux_parse_opts_str, 5255 + 5256 5257 .inode_alloc_security = selinux_inode_alloc_security, 5258 .inode_free_security = selinux_inode_free_security,
+5
security/selinux/include/security.h
··· 35 #define POLICYDB_VERSION_MAX POLICYDB_VERSION_POLCAP 36 #endif 37 38 struct netlbl_lsm_secattr; 39 40 extern int selinux_enabled;
··· 35 #define POLICYDB_VERSION_MAX POLICYDB_VERSION_POLCAP 36 #endif 37 38 + #define CONTEXT_MNT 0x01 39 + #define FSCONTEXT_MNT 0x02 40 + #define ROOTCONTEXT_MNT 0x04 41 + #define DEFCONTEXT_MNT 0x08 42 + 43 struct netlbl_lsm_secattr; 44 45 extern int selinux_enabled;
+1 -8
security/smack/smack_lsm.c
··· 189 * Copy the Smack specific mount options out of the mount 190 * options list. 191 */ 192 - static int smack_sb_copy_data(struct file_system_type *type, void *orig, 193 - void *smackopts) 194 { 195 char *cp, *commap, *otheropts, *dp; 196 - 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); 204 if (otheropts == NULL)
··· 189 * Copy the Smack specific mount options out of the mount 190 * options list. 191 */ 192 + static int smack_sb_copy_data(char *orig, char *smackopts) 193 { 194 char *cp, *commap, *otheropts, *dp; 195 196 otheropts = (char *)get_zeroed_page(GFP_KERNEL); 197 if (otheropts == NULL)