diff options
Diffstat (limited to 'fs/nfs/super.c')
-rw-r--r-- | fs/nfs/super.c | 68 |
1 files changed, 63 insertions, 5 deletions
diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 1fb381843650..f9219024f31a 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c | |||
@@ -589,8 +589,6 @@ static void nfs_umount_begin(struct vfsmount *vfsmnt, int flags) | |||
589 | struct nfs_server *server = NFS_SB(vfsmnt->mnt_sb); | 589 | struct nfs_server *server = NFS_SB(vfsmnt->mnt_sb); |
590 | struct rpc_clnt *rpc; | 590 | struct rpc_clnt *rpc; |
591 | 591 | ||
592 | shrink_submounts(vfsmnt, &nfs_automount_list); | ||
593 | |||
594 | if (!(flags & MNT_FORCE)) | 592 | if (!(flags & MNT_FORCE)) |
595 | return; | 593 | return; |
596 | /* -EIO all pending I/O */ | 594 | /* -EIO all pending I/O */ |
@@ -632,7 +630,7 @@ static int nfs_verify_server_address(struct sockaddr *addr) | |||
632 | switch (addr->sa_family) { | 630 | switch (addr->sa_family) { |
633 | case AF_INET: { | 631 | case AF_INET: { |
634 | struct sockaddr_in *sa = (struct sockaddr_in *)addr; | 632 | struct sockaddr_in *sa = (struct sockaddr_in *)addr; |
635 | return sa->sin_addr.s_addr != INADDR_ANY; | 633 | return sa->sin_addr.s_addr != htonl(INADDR_ANY); |
636 | } | 634 | } |
637 | case AF_INET6: { | 635 | case AF_INET6: { |
638 | struct in6_addr *sa = &((struct sockaddr_in6 *)addr)->sin6_addr; | 636 | struct in6_addr *sa = &((struct sockaddr_in6 *)addr)->sin6_addr; |
@@ -684,8 +682,9 @@ static void nfs_parse_server_address(char *value, | |||
684 | static int nfs_parse_mount_options(char *raw, | 682 | static int nfs_parse_mount_options(char *raw, |
685 | struct nfs_parsed_mount_data *mnt) | 683 | struct nfs_parsed_mount_data *mnt) |
686 | { | 684 | { |
687 | char *p, *string; | 685 | char *p, *string, *secdata; |
688 | unsigned short port = 0; | 686 | unsigned short port = 0; |
687 | int rc; | ||
689 | 688 | ||
690 | if (!raw) { | 689 | if (!raw) { |
691 | dfprintk(MOUNT, "NFS: mount options string was NULL.\n"); | 690 | dfprintk(MOUNT, "NFS: mount options string was NULL.\n"); |
@@ -693,6 +692,20 @@ static int nfs_parse_mount_options(char *raw, | |||
693 | } | 692 | } |
694 | dfprintk(MOUNT, "NFS: nfs mount opts='%s'\n", raw); | 693 | dfprintk(MOUNT, "NFS: nfs mount opts='%s'\n", raw); |
695 | 694 | ||
695 | secdata = alloc_secdata(); | ||
696 | if (!secdata) | ||
697 | goto out_nomem; | ||
698 | |||
699 | rc = security_sb_copy_data(raw, secdata); | ||
700 | if (rc) | ||
701 | goto out_security_failure; | ||
702 | |||
703 | rc = security_sb_parse_opts_str(secdata, &mnt->lsm_opts); | ||
704 | if (rc) | ||
705 | goto out_security_failure; | ||
706 | |||
707 | free_secdata(secdata); | ||
708 | |||
696 | while ((p = strsep(&raw, ",")) != NULL) { | 709 | while ((p = strsep(&raw, ",")) != NULL) { |
697 | substring_t args[MAX_OPT_ARGS]; | 710 | substring_t args[MAX_OPT_ARGS]; |
698 | int option, token; | 711 | int option, token; |
@@ -1042,7 +1055,10 @@ static int nfs_parse_mount_options(char *raw, | |||
1042 | out_nomem: | 1055 | out_nomem: |
1043 | printk(KERN_INFO "NFS: not enough memory to parse option\n"); | 1056 | printk(KERN_INFO "NFS: not enough memory to parse option\n"); |
1044 | return 0; | 1057 | return 0; |
1045 | 1058 | out_security_failure: | |
1059 | free_secdata(secdata); | ||
1060 | printk(KERN_INFO "NFS: security options invalid: %d\n", rc); | ||
1061 | return 0; | ||
1046 | out_unrec_vers: | 1062 | out_unrec_vers: |
1047 | printk(KERN_INFO "NFS: unrecognized NFS version number\n"); | 1063 | printk(KERN_INFO "NFS: unrecognized NFS version number\n"); |
1048 | return 0; | 1064 | return 0; |
@@ -1214,6 +1230,33 @@ static int nfs_validate_mount_data(void *options, | |||
1214 | args->namlen = data->namlen; | 1230 | args->namlen = data->namlen; |
1215 | args->bsize = data->bsize; | 1231 | args->bsize = data->bsize; |
1216 | args->auth_flavors[0] = data->pseudoflavor; | 1232 | args->auth_flavors[0] = data->pseudoflavor; |
1233 | |||
1234 | /* | ||
1235 | * The legacy version 6 binary mount data from userspace has a | ||
1236 | * field used only to transport selinux information into the | ||
1237 | * the kernel. To continue to support that functionality we | ||
1238 | * have a touch of selinux knowledge here in the NFS code. The | ||
1239 | * userspace code converted context=blah to just blah so we are | ||
1240 | * converting back to the full string selinux understands. | ||
1241 | */ | ||
1242 | if (data->context[0]){ | ||
1243 | #ifdef CONFIG_SECURITY_SELINUX | ||
1244 | int rc; | ||
1245 | char *opts_str = kmalloc(sizeof(data->context) + 8, GFP_KERNEL); | ||
1246 | if (!opts_str) | ||
1247 | return -ENOMEM; | ||
1248 | strcpy(opts_str, "context="); | ||
1249 | data->context[NFS_MAX_CONTEXT_LEN] = '\0'; | ||
1250 | strcat(opts_str, &data->context[0]); | ||
1251 | rc = security_sb_parse_opts_str(opts_str, &args->lsm_opts); | ||
1252 | kfree(opts_str); | ||
1253 | if (rc) | ||
1254 | return rc; | ||
1255 | #else | ||
1256 | return -EINVAL; | ||
1257 | #endif | ||
1258 | } | ||
1259 | |||
1217 | break; | 1260 | break; |
1218 | default: { | 1261 | default: { |
1219 | unsigned int len; | 1262 | unsigned int len; |
@@ -1476,6 +1519,8 @@ static int nfs_get_sb(struct file_system_type *fs_type, | |||
1476 | }; | 1519 | }; |
1477 | int error; | 1520 | int error; |
1478 | 1521 | ||
1522 | security_init_mnt_opts(&data.lsm_opts); | ||
1523 | |||
1479 | /* Validate the mount data */ | 1524 | /* Validate the mount data */ |
1480 | error = nfs_validate_mount_data(raw_data, &data, &mntfh, dev_name); | 1525 | error = nfs_validate_mount_data(raw_data, &data, &mntfh, dev_name); |
1481 | if (error < 0) | 1526 | if (error < 0) |
@@ -1515,6 +1560,10 @@ static int nfs_get_sb(struct file_system_type *fs_type, | |||
1515 | goto error_splat_super; | 1560 | goto error_splat_super; |
1516 | } | 1561 | } |
1517 | 1562 | ||
1563 | error = security_sb_set_mnt_opts(s, &data.lsm_opts); | ||
1564 | if (error) | ||
1565 | goto error_splat_root; | ||
1566 | |||
1518 | s->s_flags |= MS_ACTIVE; | 1567 | s->s_flags |= MS_ACTIVE; |
1519 | mnt->mnt_sb = s; | 1568 | mnt->mnt_sb = s; |
1520 | mnt->mnt_root = mntroot; | 1569 | mnt->mnt_root = mntroot; |
@@ -1523,12 +1572,15 @@ static int nfs_get_sb(struct file_system_type *fs_type, | |||
1523 | out: | 1572 | out: |
1524 | kfree(data.nfs_server.hostname); | 1573 | kfree(data.nfs_server.hostname); |
1525 | kfree(data.mount_server.hostname); | 1574 | kfree(data.mount_server.hostname); |
1575 | security_free_mnt_opts(&data.lsm_opts); | ||
1526 | return error; | 1576 | return error; |
1527 | 1577 | ||
1528 | out_err_nosb: | 1578 | out_err_nosb: |
1529 | nfs_free_server(server); | 1579 | nfs_free_server(server); |
1530 | goto out; | 1580 | goto out; |
1531 | 1581 | ||
1582 | error_splat_root: | ||
1583 | dput(mntroot); | ||
1532 | error_splat_super: | 1584 | error_splat_super: |
1533 | up_write(&s->s_umount); | 1585 | up_write(&s->s_umount); |
1534 | deactivate_super(s); | 1586 | deactivate_super(s); |
@@ -1608,6 +1660,9 @@ static int nfs_xdev_get_sb(struct file_system_type *fs_type, int flags, | |||
1608 | mnt->mnt_sb = s; | 1660 | mnt->mnt_sb = s; |
1609 | mnt->mnt_root = mntroot; | 1661 | mnt->mnt_root = mntroot; |
1610 | 1662 | ||
1663 | /* clone any lsm security options from the parent to the new sb */ | ||
1664 | security_sb_clone_mnt_opts(data->sb, s); | ||
1665 | |||
1611 | dprintk("<-- nfs_xdev_get_sb() = 0\n"); | 1666 | dprintk("<-- nfs_xdev_get_sb() = 0\n"); |
1612 | return 0; | 1667 | return 0; |
1613 | 1668 | ||
@@ -1850,6 +1905,8 @@ static int nfs4_get_sb(struct file_system_type *fs_type, | |||
1850 | }; | 1905 | }; |
1851 | int error; | 1906 | int error; |
1852 | 1907 | ||
1908 | security_init_mnt_opts(&data.lsm_opts); | ||
1909 | |||
1853 | /* Validate the mount data */ | 1910 | /* Validate the mount data */ |
1854 | error = nfs4_validate_mount_data(raw_data, &data, dev_name); | 1911 | error = nfs4_validate_mount_data(raw_data, &data, dev_name); |
1855 | if (error < 0) | 1912 | if (error < 0) |
@@ -1898,6 +1955,7 @@ out: | |||
1898 | kfree(data.client_address); | 1955 | kfree(data.client_address); |
1899 | kfree(data.nfs_server.export_path); | 1956 | kfree(data.nfs_server.export_path); |
1900 | kfree(data.nfs_server.hostname); | 1957 | kfree(data.nfs_server.hostname); |
1958 | security_free_mnt_opts(&data.lsm_opts); | ||
1901 | return error; | 1959 | return error; |
1902 | 1960 | ||
1903 | out_free: | 1961 | out_free: |