Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/selinux-2.6

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/selinux-2.6:
NFS: use new LSM interfaces to explicitly set mount options
LSM/SELinux: Interfaces to allow FS to control mount options

+276 -143
+3
fs/nfs/internal.h
··· 3 3 */ 4 4 5 5 #include <linux/mount.h> 6 + #include <linux/security.h> 6 7 7 8 struct nfs_string; 8 9 ··· 58 57 char *export_path; 59 58 int protocol; 60 59 } nfs_server; 60 + 61 + struct security_mnt_opts lsm_opts; 61 62 }; 62 63 63 64 /* client.c */
+62 -2
fs/nfs/super.c
··· 684 684 static int nfs_parse_mount_options(char *raw, 685 685 struct nfs_parsed_mount_data *mnt) 686 686 { 687 - char *p, *string; 687 + char *p, *string, *secdata; 688 688 unsigned short port = 0; 689 + int rc; 689 690 690 691 if (!raw) { 691 692 dfprintk(MOUNT, "NFS: mount options string was NULL.\n"); 692 693 return 1; 693 694 } 694 695 dfprintk(MOUNT, "NFS: nfs mount opts='%s'\n", raw); 696 + 697 + secdata = alloc_secdata(); 698 + if (!secdata) 699 + goto out_nomem; 700 + 701 + rc = security_sb_copy_data(raw, secdata); 702 + if (rc) 703 + goto out_security_failure; 704 + 705 + rc = security_sb_parse_opts_str(secdata, &mnt->lsm_opts); 706 + if (rc) 707 + goto out_security_failure; 708 + 709 + free_secdata(secdata); 695 710 696 711 while ((p = strsep(&raw, ",")) != NULL) { 697 712 substring_t args[MAX_OPT_ARGS]; ··· 1057 1042 out_nomem: 1058 1043 printk(KERN_INFO "NFS: not enough memory to parse option\n"); 1059 1044 return 0; 1060 - 1045 + out_security_failure: 1046 + free_secdata(secdata); 1047 + printk(KERN_INFO "NFS: security options invalid: %d\n", rc); 1048 + return 0; 1061 1049 out_unrec_vers: 1062 1050 printk(KERN_INFO "NFS: unrecognized NFS version number\n"); 1063 1051 return 0; ··· 1232 1214 args->namlen = data->namlen; 1233 1215 args->bsize = data->bsize; 1234 1216 args->auth_flavors[0] = data->pseudoflavor; 1217 + 1218 + /* 1219 + * The legacy version 6 binary mount data from userspace has a 1220 + * field used only to transport selinux information into the 1221 + * the kernel. To continue to support that functionality we 1222 + * have a touch of selinux knowledge here in the NFS code. The 1223 + * userspace code converted context=blah to just blah so we are 1224 + * converting back to the full string selinux understands. 1225 + */ 1226 + if (data->context[0]){ 1227 + #ifdef CONFIG_SECURITY_SELINUX 1228 + int rc; 1229 + char *opts_str = kmalloc(sizeof(data->context) + 8, GFP_KERNEL); 1230 + if (!opts_str) 1231 + return -ENOMEM; 1232 + strcpy(opts_str, "context="); 1233 + data->context[NFS_MAX_CONTEXT_LEN] = '\0'; 1234 + strcat(opts_str, &data->context[0]); 1235 + rc = security_sb_parse_opts_str(opts_str, &args->lsm_opts); 1236 + kfree(opts_str); 1237 + if (rc) 1238 + return rc; 1239 + #else 1240 + return -EINVAL; 1241 + #endif 1242 + } 1243 + 1235 1244 break; 1236 1245 default: { 1237 1246 unsigned int len; ··· 1521 1476 }; 1522 1477 int error; 1523 1478 1479 + security_init_mnt_opts(&data.lsm_opts); 1480 + 1524 1481 /* Validate the mount data */ 1525 1482 error = nfs_validate_mount_data(raw_data, &data, &mntfh, dev_name); 1526 1483 if (error < 0) ··· 1562 1515 goto error_splat_super; 1563 1516 } 1564 1517 1518 + error = security_sb_set_mnt_opts(s, &data.lsm_opts); 1519 + if (error) 1520 + goto error_splat_root; 1521 + 1565 1522 s->s_flags |= MS_ACTIVE; 1566 1523 mnt->mnt_sb = s; 1567 1524 mnt->mnt_root = mntroot; ··· 1574 1523 out: 1575 1524 kfree(data.nfs_server.hostname); 1576 1525 kfree(data.mount_server.hostname); 1526 + security_free_mnt_opts(&data.lsm_opts); 1577 1527 return error; 1578 1528 1579 1529 out_err_nosb: 1580 1530 nfs_free_server(server); 1581 1531 goto out; 1582 1532 1533 + error_splat_root: 1534 + dput(mntroot); 1583 1535 error_splat_super: 1584 1536 up_write(&s->s_umount); 1585 1537 deactivate_super(s); ··· 1661 1607 s->s_flags |= MS_ACTIVE; 1662 1608 mnt->mnt_sb = s; 1663 1609 mnt->mnt_root = mntroot; 1610 + 1611 + /* clone any lsm security options from the parent to the new sb */ 1612 + security_sb_clone_mnt_opts(data->sb, s); 1664 1613 1665 1614 dprintk("<-- nfs_xdev_get_sb() = 0\n"); 1666 1615 return 0; ··· 1907 1850 }; 1908 1851 int error; 1909 1852 1853 + security_init_mnt_opts(&data.lsm_opts); 1854 + 1910 1855 /* Validate the mount data */ 1911 1856 error = nfs4_validate_mount_data(raw_data, &data, dev_name); 1912 1857 if (error < 0) ··· 1957 1898 kfree(data.client_address); 1958 1899 kfree(data.nfs_server.export_path); 1959 1900 kfree(data.nfs_server.hostname); 1901 + security_free_mnt_opts(&data.lsm_opts); 1960 1902 return error; 1961 1903 1962 1904 out_free:
+2 -2
fs/super.c
··· 870 870 if (!mnt) 871 871 goto out; 872 872 873 - if (data) { 873 + if (data && !(type->fs_flags & FS_BINARY_MOUNTDATA)) { 874 874 secdata = alloc_secdata(); 875 875 if (!secdata) 876 876 goto out_mnt; 877 877 878 - error = security_sb_copy_data(type, data, secdata); 878 + error = security_sb_copy_data(data, secdata); 879 879 if (error) 880 880 goto out_free_secdata; 881 881 }
+74 -25
include/linux/security.h
··· 34 34 #include <linux/xfrm.h> 35 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 - 43 37 extern unsigned securebits; 44 38 45 39 struct ctl_table; ··· 107 113 #define LSM_UNSAFE_PTRACE_CAP 4 108 114 109 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 + } 110 142 111 143 /** 112 144 * struct security_operations - main security structure ··· 282 262 * @sb_get_mnt_opts: 283 263 * Get the security relevant mount options used for a superblock 284 264 * @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 265 + * @opts binary data structure containing all lsm mount data 288 266 * @sb_set_mnt_opts: 289 267 * Set the security relevant mount options used for a superblock 290 268 * @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 269 + * @opts binary data structure containing all lsm mount data 294 270 * @sb_clone_mnt_opts: 295 271 * Copy all security options from a given superblock to another 296 272 * @oldsb old superblock which contain information to clone 297 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 298 278 * 299 279 * Security hooks for inode operations. 300 280 * ··· 1258 1238 1259 1239 int (*sb_alloc_security) (struct super_block * sb); 1260 1240 void (*sb_free_security) (struct super_block * sb); 1261 - int (*sb_copy_data)(struct file_system_type *type, 1262 - void *orig, void *copy); 1241 + int (*sb_copy_data)(char *orig, char *copy); 1263 1242 int (*sb_kern_mount) (struct super_block *sb, void *data); 1264 1243 int (*sb_statfs) (struct dentry *dentry); 1265 1244 int (*sb_mount) (char *dev_name, struct nameidata * nd, ··· 1276 1257 void (*sb_post_pivotroot) (struct nameidata * old_nd, 1277 1258 struct nameidata * new_nd); 1278 1259 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); 1260 + struct security_mnt_opts *opts); 1261 + int (*sb_set_mnt_opts) (struct super_block *sb, 1262 + struct security_mnt_opts *opts); 1283 1263 void (*sb_clone_mnt_opts) (const struct super_block *oldsb, 1284 1264 struct super_block *newsb); 1265 + int (*sb_parse_opts_str) (char *options, struct security_mnt_opts *opts); 1285 1266 1286 1267 int (*inode_alloc_security) (struct inode *inode); 1287 1268 void (*inode_free_security) (struct inode *inode); ··· 1526 1507 int security_bprm_secureexec(struct linux_binprm *bprm); 1527 1508 int security_sb_alloc(struct super_block *sb); 1528 1509 void security_sb_free(struct super_block *sb); 1529 - int security_sb_copy_data(struct file_system_type *type, void *orig, void *copy); 1510 + int security_sb_copy_data(char *orig, char *copy); 1530 1511 int security_sb_kern_mount(struct super_block *sb, void *data); 1531 1512 int security_sb_statfs(struct dentry *dentry); 1532 1513 int security_sb_mount(char *dev_name, struct nameidata *nd, ··· 1539 1520 void security_sb_post_addmount(struct vfsmount *mnt, struct nameidata *mountpoint_nd); 1540 1521 int security_sb_pivotroot(struct nameidata *old_nd, struct nameidata *new_nd); 1541 1522 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); 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); 1546 1526 void security_sb_clone_mnt_opts(const struct super_block *oldsb, 1547 1527 struct super_block *newsb); 1528 + int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts); 1548 1529 1549 1530 int security_inode_alloc(struct inode *inode); 1550 1531 void security_inode_free(struct inode *inode); ··· 1654 1635 void security_release_secctx(char *secdata, u32 seclen); 1655 1636 1656 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 + } 1657 1648 1658 1649 /* 1659 1650 * This is the default capabilities functionality. Most of these functions ··· 1791 1762 static inline void security_sb_free (struct super_block *sb) 1792 1763 { } 1793 1764 1794 - static inline int security_sb_copy_data (struct file_system_type *type, 1795 - void *orig, void *copy) 1765 + static inline int security_sb_copy_data (char *orig, char *copy) 1796 1766 { 1797 1767 return 0; 1798 1768 } ··· 1847 1819 static inline void security_sb_post_pivotroot (struct nameidata *old_nd, 1848 1820 struct nameidata *new_nd) 1849 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 + } 1850 1843 1851 1844 static inline int security_inode_alloc (struct inode *inode) 1852 1845 {
+13 -10
security/dummy.c
··· 181 181 return; 182 182 } 183 183 184 - static int dummy_sb_copy_data (struct file_system_type *type, 185 - void *orig, void *copy) 184 + static int dummy_sb_copy_data (char *orig, char *copy) 186 185 { 187 186 return 0; 188 187 } ··· 244 245 return; 245 246 } 246 247 247 - static int dummy_sb_get_mnt_opts(const struct super_block *sb, char ***mount_options, 248 - int **flags, int *num_opts) 248 + static int dummy_sb_get_mnt_opts(const struct super_block *sb, 249 + struct security_mnt_opts *opts) 249 250 { 250 - *mount_options = NULL; 251 - *flags = NULL; 252 - *num_opts = 0; 251 + security_init_mnt_opts(opts); 253 252 return 0; 254 253 } 255 254 256 - static int dummy_sb_set_mnt_opts(struct super_block *sb, char **mount_options, 257 - int *flags, int num_opts) 255 + static int dummy_sb_set_mnt_opts(struct super_block *sb, 256 + struct security_mnt_opts *opts) 258 257 { 259 - if (unlikely(num_opts)) 258 + if (unlikely(opts->num_mnt_opts)) 260 259 return -EOPNOTSUPP; 261 260 return 0; 262 261 } ··· 263 266 struct super_block *newsb) 264 267 { 265 268 return; 269 + } 270 + 271 + static int dummy_sb_parse_opts_str(char *options, struct security_mnt_opts *opts) 272 + { 273 + return 0; 266 274 } 267 275 268 276 static int dummy_inode_alloc_security (struct inode *inode) ··· 1030 1028 set_to_dummy_if_null(ops, sb_get_mnt_opts); 1031 1029 set_to_dummy_if_null(ops, sb_set_mnt_opts); 1032 1030 set_to_dummy_if_null(ops, sb_clone_mnt_opts); 1031 + set_to_dummy_if_null(ops, sb_parse_opts_str); 1033 1032 set_to_dummy_if_null(ops, inode_alloc_security); 1034 1033 set_to_dummy_if_null(ops, inode_free_security); 1035 1034 set_to_dummy_if_null(ops, inode_init_security);
+15 -8
security/security.c
··· 244 244 security_ops->sb_free_security(sb); 245 245 } 246 246 247 - int security_sb_copy_data(struct file_system_type *type, void *orig, void *copy) 247 + int 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 } 251 + EXPORT_SYMBOL(security_sb_copy_data); 251 252 252 253 int security_sb_kern_mount(struct super_block *sb, void *data) 253 254 { ··· 307 306 } 308 307 309 308 int security_sb_get_mnt_opts(const struct super_block *sb, 310 - char ***mount_options, 311 - int **flags, int *num_opts) 309 + struct security_mnt_opts *opts) 312 310 { 313 - return security_ops->sb_get_mnt_opts(sb, mount_options, flags, num_opts); 311 + return security_ops->sb_get_mnt_opts(sb, opts); 314 312 } 315 313 316 314 int security_sb_set_mnt_opts(struct super_block *sb, 317 - char **mount_options, 318 - int *flags, int num_opts) 315 + struct security_mnt_opts *opts) 319 316 { 320 - return security_ops->sb_set_mnt_opts(sb, mount_options, flags, num_opts); 317 + return security_ops->sb_set_mnt_opts(sb, opts); 321 318 } 319 + EXPORT_SYMBOL(security_sb_set_mnt_opts); 322 320 323 321 void security_sb_clone_mnt_opts(const struct super_block *oldsb, 324 322 struct super_block *newsb) 325 323 { 326 324 security_ops->sb_clone_mnt_opts(oldsb, newsb); 327 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); 328 333 329 334 int security_inode_alloc(struct inode *inode) 330 335 {
+101 -88
security/selinux/hooks.c
··· 443 443 * mount options, or whatever. 444 444 */ 445 445 static int selinux_get_mnt_opts(const struct super_block *sb, 446 - char ***mount_options, int **mnt_opts_flags, 447 - int *num_opts) 446 + struct security_mnt_opts *opts) 448 447 { 449 448 int rc = 0, i; 450 449 struct superblock_security_struct *sbsec = sb->s_security; ··· 451 452 u32 len; 452 453 char tmp; 453 454 454 - *num_opts = 0; 455 - *mount_options = NULL; 456 - *mnt_opts_flags = NULL; 455 + security_init_mnt_opts(opts); 457 456 458 457 if (!sbsec->initialized) 459 458 return -EINVAL; ··· 467 470 /* count the number of mount options for this sb */ 468 471 for (i = 0; i < 8; i++) { 469 472 if (tmp & 0x01) 470 - (*num_opts)++; 473 + opts->num_mnt_opts++; 471 474 tmp >>= 1; 472 475 } 473 476 474 - *mount_options = kcalloc(*num_opts, sizeof(char *), GFP_ATOMIC); 475 - if (!*mount_options) { 477 + opts->mnt_opts = kcalloc(opts->num_mnt_opts, sizeof(char *), GFP_ATOMIC); 478 + if (!opts->mnt_opts) { 476 479 rc = -ENOMEM; 477 480 goto out_free; 478 481 } 479 482 480 - *mnt_opts_flags = kcalloc(*num_opts, sizeof(int), GFP_ATOMIC); 481 - if (!*mnt_opts_flags) { 483 + opts->mnt_opts_flags = kcalloc(opts->num_mnt_opts, sizeof(int), GFP_ATOMIC); 484 + if (!opts->mnt_opts_flags) { 482 485 rc = -ENOMEM; 483 486 goto out_free; 484 487 } ··· 488 491 rc = security_sid_to_context(sbsec->sid, &context, &len); 489 492 if (rc) 490 493 goto out_free; 491 - (*mount_options)[i] = context; 492 - (*mnt_opts_flags)[i++] = FSCONTEXT_MNT; 494 + opts->mnt_opts[i] = context; 495 + opts->mnt_opts_flags[i++] = FSCONTEXT_MNT; 493 496 } 494 497 if (sbsec->flags & CONTEXT_MNT) { 495 498 rc = security_sid_to_context(sbsec->mntpoint_sid, &context, &len); 496 499 if (rc) 497 500 goto out_free; 498 - (*mount_options)[i] = context; 499 - (*mnt_opts_flags)[i++] = CONTEXT_MNT; 501 + opts->mnt_opts[i] = context; 502 + opts->mnt_opts_flags[i++] = CONTEXT_MNT; 500 503 } 501 504 if (sbsec->flags & DEFCONTEXT_MNT) { 502 505 rc = security_sid_to_context(sbsec->def_sid, &context, &len); 503 506 if (rc) 504 507 goto out_free; 505 - (*mount_options)[i] = context; 506 - (*mnt_opts_flags)[i++] = DEFCONTEXT_MNT; 508 + opts->mnt_opts[i] = context; 509 + opts->mnt_opts_flags[i++] = DEFCONTEXT_MNT; 507 510 } 508 511 if (sbsec->flags & ROOTCONTEXT_MNT) { 509 512 struct inode *root = sbsec->sb->s_root->d_inode; ··· 512 515 rc = security_sid_to_context(isec->sid, &context, &len); 513 516 if (rc) 514 517 goto out_free; 515 - (*mount_options)[i] = context; 516 - (*mnt_opts_flags)[i++] = ROOTCONTEXT_MNT; 518 + opts->mnt_opts[i] = context; 519 + opts->mnt_opts_flags[i++] = ROOTCONTEXT_MNT; 517 520 } 518 521 519 - BUG_ON(i != *num_opts); 522 + BUG_ON(i != opts->num_mnt_opts); 520 523 521 524 return 0; 522 525 523 526 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; 527 + security_free_mnt_opts(opts); 533 528 return rc; 534 529 } 535 530 ··· 542 553 return 1; 543 554 return 0; 544 555 } 556 + 545 557 /* 546 558 * Allow filesystems with binary mount data to explicitly set mount point 547 559 * labeling information. 548 560 */ 549 - static int selinux_set_mnt_opts(struct super_block *sb, char **mount_options, 550 - int *flags, int num_opts) 561 + static int selinux_set_mnt_opts(struct super_block *sb, 562 + struct security_mnt_opts *opts) 551 563 { 552 564 int rc = 0, i; 553 565 struct task_security_struct *tsec = current->security; ··· 558 568 struct inode_security_struct *root_isec = inode->i_security; 559 569 u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0; 560 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; 561 574 562 575 mutex_lock(&sbsec->lock); 563 576 ··· 580 587 "the security server is initialized\n"); 581 588 goto out; 582 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; 583 605 584 606 /* 585 607 * parse the mount options, check if they are valid sids. ··· 800 792 mutex_unlock(&newsbsec->lock); 801 793 } 802 794 803 - /* 804 - * string mount options parsing and call set the sbsec 805 - */ 806 - static int superblock_doinit(struct super_block *sb, void *data) 795 + int selinux_parse_opts_str(char *options, struct security_mnt_opts *opts) 807 796 { 797 + char *p; 808 798 char *context = NULL, *defcontext = NULL; 809 799 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; 800 + int rc, num_mnt_opts = 0; 815 801 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 - } 802 + opts->num_mnt_opts = 0; 840 803 841 804 /* Standard string-based options. */ 842 805 while ((p = strsep(&options, "|")) != NULL) { ··· 880 901 } 881 902 } 882 903 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; 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; 899 913 } 900 914 901 - out: 902 - rc = selinux_set_mnt_opts(sb, mnt_opts, mnt_opts_flags, num_mnt_opts); 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 + 903 935 out_err: 904 936 kfree(context); 905 937 kfree(defcontext); 906 938 kfree(fscontext); 907 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); 908 967 return rc; 909 968 } 910 969 ··· 2270 2253 } 2271 2254 } 2272 2255 2273 - static int selinux_sb_copy_data(struct file_system_type *type, void *orig, void *copy) 2256 + static int selinux_sb_copy_data(char *orig, char *copy) 2274 2257 { 2275 2258 int fnosec, fsec, rc = 0; 2276 2259 char *in_save, *in_curr, *in_end; ··· 2279 2262 2280 2263 in_curr = orig; 2281 2264 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 2265 2289 2266 nosec = (char *)get_zeroed_page(GFP_KERNEL); 2290 2267 if (!nosec) { ··· 5262 5251 .sb_get_mnt_opts = selinux_get_mnt_opts, 5263 5252 .sb_set_mnt_opts = selinux_set_mnt_opts, 5264 5253 .sb_clone_mnt_opts = selinux_sb_clone_mnt_opts, 5254 + .sb_parse_opts_str = selinux_parse_opts_str, 5255 + 5265 5256 5266 5257 .inode_alloc_security = selinux_inode_alloc_security, 5267 5258 .inode_free_security = selinux_inode_free_security,
+5
security/selinux/include/security.h
··· 35 35 #define POLICYDB_VERSION_MAX POLICYDB_VERSION_POLCAP 36 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 + 38 43 struct netlbl_lsm_secattr; 39 44 40 45 extern int selinux_enabled;
+1 -8
security/smack/smack_lsm.c
··· 189 189 * Copy the Smack specific mount options out of the mount 190 190 * options list. 191 191 */ 192 - static int smack_sb_copy_data(struct file_system_type *type, void *orig, 193 - void *smackopts) 192 + static int smack_sb_copy_data(char *orig, char *smackopts) 194 193 { 195 194 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 195 203 196 otheropts = (char *)get_zeroed_page(GFP_KERNEL); 204 197 if (otheropts == NULL)