aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/super.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/super.c')
-rw-r--r--fs/nfs/super.c68
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,
684static int nfs_parse_mount_options(char *raw, 682static 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,
1042out_nomem: 1055out_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 1058out_security_failure:
1059 free_secdata(secdata);
1060 printk(KERN_INFO "NFS: security options invalid: %d\n", rc);
1061 return 0;
1046out_unrec_vers: 1062out_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,
1523out: 1572out:
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
1528out_err_nosb: 1578out_err_nosb:
1529 nfs_free_server(server); 1579 nfs_free_server(server);
1530 goto out; 1580 goto out;
1531 1581
1582error_splat_root:
1583 dput(mntroot);
1532error_splat_super: 1584error_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
1903out_free: 1961out_free: