aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/super.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-07-09 15:09:43 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-07-09 15:09:43 -0400
commitbe0c5d8c0bb0023e11f5c6d38e90f7b0f24edb64 (patch)
tree6d7a6e290f8ed2f2ca250965a8debdd9f02a9cc9 /fs/nfs/super.c
parent1f792dd1765e6f047ecd2d5f6a81f025b50d471a (diff)
parent959d921f5eb8878ea16049a7f6e9bcbb6dfbcb88 (diff)
Merge tag 'nfs-for-3.11-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
Pull NFS client updates from Trond Myklebust: "Feature highlights include: - Add basic client support for NFSv4.2 - Add basic client support for Labeled NFS (selinux for NFSv4.2) - Fix the use of credentials in NFSv4.1 stateful operations, and add support for NFSv4.1 state protection. Bugfix highlights: - Fix another NFSv4 open state recovery race - Fix an NFSv4.1 back channel session regression - Various rpc_pipefs races - Fix another issue with NFSv3 auth negotiation Please note that Labeled NFS does require some additional support from the security subsystem. The relevant changesets have all been reviewed and acked by James Morris." * tag 'nfs-for-3.11-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs: (54 commits) NFS: Set NFS_CS_MIGRATION for NFSv4 mounts NFSv4.1 Refactor nfs4_init_session and nfs4_init_channel_attrs nfs: have NFSv3 try server-specified auth flavors in turn nfs: have nfs_mount fake up a auth_flavs list when the server didn't provide it nfs: move server_authlist into nfs_try_mount_request nfs: refactor "need_mount" code out of nfs_try_mount SUNRPC: PipeFS MOUNT notification optimization for dying clients SUNRPC: split client creation routine into setup and registration SUNRPC: fix races on PipeFS UMOUNT notifications SUNRPC: fix races on PipeFS MOUNT notifications NFSv4.1 use pnfs_device maxcount for the objectlayout gdia_maxcount NFSv4.1 use pnfs_device maxcount for the blocklayout gdia_maxcount NFSv4.1 Fix gdia_maxcount calculation to fit in ca_maxresponsesize NFS: Improve legacy idmapping fallback NFSv4.1 end back channel session draining NFS: Apply v4.1 capabilities to v4.2 NFSv4.1: Clean up layout segment comparison helper names NFSv4.1: layout segment comparison helpers should take 'const' parameters NFSv4: Move the DNS resolver into the NFSv4 module rpc_pipefs: only set rpc_dentry_ops if d_op isn't already set ...
Diffstat (limited to 'fs/nfs/super.c')
-rw-r--r--fs/nfs/super.c199
1 files changed, 115 insertions, 84 deletions
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 2d7525fbcf25..71fdc0dfa0d2 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -269,7 +269,7 @@ static match_table_t nfs_local_lock_tokens = {
269 269
270enum { 270enum {
271 Opt_vers_2, Opt_vers_3, Opt_vers_4, Opt_vers_4_0, 271 Opt_vers_2, Opt_vers_3, Opt_vers_4, Opt_vers_4_0,
272 Opt_vers_4_1, 272 Opt_vers_4_1, Opt_vers_4_2,
273 273
274 Opt_vers_err 274 Opt_vers_err
275}; 275};
@@ -280,6 +280,7 @@ static match_table_t nfs_vers_tokens = {
280 { Opt_vers_4, "4" }, 280 { Opt_vers_4, "4" },
281 { Opt_vers_4_0, "4.0" }, 281 { Opt_vers_4_0, "4.0" },
282 { Opt_vers_4_1, "4.1" }, 282 { Opt_vers_4_1, "4.1" },
283 { Opt_vers_4_2, "4.2" },
283 284
284 { Opt_vers_err, NULL } 285 { Opt_vers_err, NULL }
285}; 286};
@@ -832,6 +833,7 @@ int nfs_show_stats(struct seq_file *m, struct dentry *root)
832 seq_printf(m, "\n\tnfsv4:\t"); 833 seq_printf(m, "\n\tnfsv4:\t");
833 seq_printf(m, "bm0=0x%x", nfss->attr_bitmask[0]); 834 seq_printf(m, "bm0=0x%x", nfss->attr_bitmask[0]);
834 seq_printf(m, ",bm1=0x%x", nfss->attr_bitmask[1]); 835 seq_printf(m, ",bm1=0x%x", nfss->attr_bitmask[1]);
836 seq_printf(m, ",bm2=0x%x", nfss->attr_bitmask[2]);
835 seq_printf(m, ",acl=0x%x", nfss->acl_bitmask); 837 seq_printf(m, ",acl=0x%x", nfss->acl_bitmask);
836 show_sessions(m, nfss); 838 show_sessions(m, nfss);
837 show_pnfs(m, nfss); 839 show_pnfs(m, nfss);
@@ -1097,6 +1099,10 @@ static int nfs_parse_version_string(char *string,
1097 mnt->version = 4; 1099 mnt->version = 4;
1098 mnt->minorversion = 1; 1100 mnt->minorversion = 1;
1099 break; 1101 break;
1102 case Opt_vers_4_2:
1103 mnt->version = 4;
1104 mnt->minorversion = 2;
1105 break;
1100 default: 1106 default:
1101 return 0; 1107 return 0;
1102 } 1108 }
@@ -1608,29 +1614,13 @@ out_security_failure:
1608} 1614}
1609 1615
1610/* 1616/*
1611 * Select a security flavor for this mount. The selected flavor 1617 * Ensure that the specified authtype in args->auth_flavors[0] is supported by
1612 * is planted in args->auth_flavors[0]. 1618 * the server. Returns 0 if it's ok, and -EACCES if not.
1613 *
1614 * Returns 0 on success, -EACCES on failure.
1615 */ 1619 */
1616static int nfs_select_flavor(struct nfs_parsed_mount_data *args, 1620static int nfs_verify_authflavor(struct nfs_parsed_mount_data *args,
1617 struct nfs_mount_request *request) 1621 rpc_authflavor_t *server_authlist, unsigned int count)
1618{ 1622{
1619 unsigned int i, count = *(request->auth_flav_len); 1623 unsigned int i;
1620 rpc_authflavor_t flavor;
1621
1622 /*
1623 * The NFSv2 MNT operation does not return a flavor list.
1624 */
1625 if (args->mount_server.version != NFS_MNT3_VERSION)
1626 goto out_default;
1627
1628 /*
1629 * Certain releases of Linux's mountd return an empty
1630 * flavor list in some cases.
1631 */
1632 if (count == 0)
1633 goto out_default;
1634 1624
1635 /* 1625 /*
1636 * If the sec= mount option is used, the specified flavor or AUTH_NULL 1626 * If the sec= mount option is used, the specified flavor or AUTH_NULL
@@ -1640,60 +1630,19 @@ static int nfs_select_flavor(struct nfs_parsed_mount_data *args,
1640 * means that the server will ignore the rpc creds, so any flavor 1630 * means that the server will ignore the rpc creds, so any flavor
1641 * can be used. 1631 * can be used.
1642 */ 1632 */
1643 if (args->auth_flavors[0] != RPC_AUTH_MAXFLAVOR) {
1644 for (i = 0; i < count; i++) {
1645 if (args->auth_flavors[0] == request->auth_flavs[i] ||
1646 request->auth_flavs[i] == RPC_AUTH_NULL)
1647 goto out;
1648 }
1649 dfprintk(MOUNT, "NFS: auth flavor %d not supported by server\n",
1650 args->auth_flavors[0]);
1651 goto out_err;
1652 }
1653
1654 /*
1655 * RFC 2623, section 2.7 suggests we SHOULD prefer the
1656 * flavor listed first. However, some servers list
1657 * AUTH_NULL first. Avoid ever choosing AUTH_NULL.
1658 */
1659 for (i = 0; i < count; i++) { 1633 for (i = 0; i < count; i++) {
1660 struct rpcsec_gss_info info; 1634 if (args->auth_flavors[0] == server_authlist[i] ||
1661 1635 server_authlist[i] == RPC_AUTH_NULL)
1662 flavor = request->auth_flavs[i]; 1636 goto out;
1663 switch (flavor) {
1664 case RPC_AUTH_UNIX:
1665 goto out_set;
1666 case RPC_AUTH_NULL:
1667 continue;
1668 default:
1669 if (rpcauth_get_gssinfo(flavor, &info) == 0)
1670 goto out_set;
1671 }
1672 } 1637 }
1673 1638
1674 /* 1639 dfprintk(MOUNT, "NFS: auth flavor %u not supported by server\n",
1675 * As a last chance, see if the server list contains AUTH_NULL - 1640 args->auth_flavors[0]);
1676 * if it does, use the default flavor. 1641 return -EACCES;
1677 */
1678 for (i = 0; i < count; i++) {
1679 if (request->auth_flavs[i] == RPC_AUTH_NULL)
1680 goto out_default;
1681 }
1682
1683 dfprintk(MOUNT, "NFS: no auth flavors in common with server\n");
1684 goto out_err;
1685 1642
1686out_default:
1687 /* use default if flavor not already set */
1688 flavor = (args->auth_flavors[0] == RPC_AUTH_MAXFLAVOR) ?
1689 RPC_AUTH_UNIX : args->auth_flavors[0];
1690out_set:
1691 args->auth_flavors[0] = flavor;
1692out: 1643out:
1693 dfprintk(MOUNT, "NFS: using auth flavor %d\n", args->auth_flavors[0]); 1644 dfprintk(MOUNT, "NFS: using auth flavor %u\n", args->auth_flavors[0]);
1694 return 0; 1645 return 0;
1695out_err:
1696 return -EACCES;
1697} 1646}
1698 1647
1699/* 1648/*
@@ -1701,10 +1650,10 @@ out_err:
1701 * corresponding to the provided path. 1650 * corresponding to the provided path.
1702 */ 1651 */
1703static int nfs_request_mount(struct nfs_parsed_mount_data *args, 1652static int nfs_request_mount(struct nfs_parsed_mount_data *args,
1704 struct nfs_fh *root_fh) 1653 struct nfs_fh *root_fh,
1654 rpc_authflavor_t *server_authlist,
1655 unsigned int *server_authlist_len)
1705{ 1656{
1706 rpc_authflavor_t server_authlist[NFS_MAX_SECFLAVORS];
1707 unsigned int server_authlist_len = ARRAY_SIZE(server_authlist);
1708 struct nfs_mount_request request = { 1657 struct nfs_mount_request request = {
1709 .sap = (struct sockaddr *) 1658 .sap = (struct sockaddr *)
1710 &args->mount_server.address, 1659 &args->mount_server.address,
@@ -1712,7 +1661,7 @@ static int nfs_request_mount(struct nfs_parsed_mount_data *args,
1712 .protocol = args->mount_server.protocol, 1661 .protocol = args->mount_server.protocol,
1713 .fh = root_fh, 1662 .fh = root_fh,
1714 .noresvport = args->flags & NFS_MOUNT_NORESVPORT, 1663 .noresvport = args->flags & NFS_MOUNT_NORESVPORT,
1715 .auth_flav_len = &server_authlist_len, 1664 .auth_flav_len = server_authlist_len,
1716 .auth_flavs = server_authlist, 1665 .auth_flavs = server_authlist,
1717 .net = args->net, 1666 .net = args->net,
1718 }; 1667 };
@@ -1756,24 +1705,92 @@ static int nfs_request_mount(struct nfs_parsed_mount_data *args,
1756 return status; 1705 return status;
1757 } 1706 }
1758 1707
1759 return nfs_select_flavor(args, &request); 1708 return 0;
1760} 1709}
1761 1710
1762struct dentry *nfs_try_mount(int flags, const char *dev_name, 1711static struct nfs_server *nfs_try_mount_request(struct nfs_mount_info *mount_info,
1763 struct nfs_mount_info *mount_info, 1712 struct nfs_subversion *nfs_mod)
1764 struct nfs_subversion *nfs_mod)
1765{ 1713{
1766 int status; 1714 int status;
1767 struct nfs_server *server; 1715 unsigned int i;
1716 bool tried_auth_unix = false;
1717 bool auth_null_in_list = false;
1718 struct nfs_server *server = ERR_PTR(-EACCES);
1719 struct nfs_parsed_mount_data *args = mount_info->parsed;
1720 rpc_authflavor_t authlist[NFS_MAX_SECFLAVORS];
1721 unsigned int authlist_len = ARRAY_SIZE(authlist);
1722
1723 status = nfs_request_mount(args, mount_info->mntfh, authlist,
1724 &authlist_len);
1725 if (status)
1726 return ERR_PTR(status);
1768 1727
1769 if (mount_info->parsed->need_mount) { 1728 /*
1770 status = nfs_request_mount(mount_info->parsed, mount_info->mntfh); 1729 * Was a sec= authflavor specified in the options? First, verify
1730 * whether the server supports it, and then just try to use it if so.
1731 */
1732 if (args->auth_flavors[0] != RPC_AUTH_MAXFLAVOR) {
1733 status = nfs_verify_authflavor(args, authlist, authlist_len);
1734 dfprintk(MOUNT, "NFS: using auth flavor %u\n", args->auth_flavors[0]);
1771 if (status) 1735 if (status)
1772 return ERR_PTR(status); 1736 return ERR_PTR(status);
1737 return nfs_mod->rpc_ops->create_server(mount_info, nfs_mod);
1738 }
1739
1740 /*
1741 * No sec= option was provided. RFC 2623, section 2.7 suggests we
1742 * SHOULD prefer the flavor listed first. However, some servers list
1743 * AUTH_NULL first. Avoid ever choosing AUTH_NULL.
1744 */
1745 for (i = 0; i < authlist_len; ++i) {
1746 rpc_authflavor_t flavor;
1747 struct rpcsec_gss_info info;
1748
1749 flavor = authlist[i];
1750 switch (flavor) {
1751 case RPC_AUTH_UNIX:
1752 tried_auth_unix = true;
1753 break;
1754 case RPC_AUTH_NULL:
1755 auth_null_in_list = true;
1756 continue;
1757 default:
1758 if (rpcauth_get_gssinfo(flavor, &info) != 0)
1759 continue;
1760 /* Fallthrough */
1761 }
1762 dfprintk(MOUNT, "NFS: attempting to use auth flavor %u\n", flavor);
1763 args->auth_flavors[0] = flavor;
1764 server = nfs_mod->rpc_ops->create_server(mount_info, nfs_mod);
1765 if (!IS_ERR(server))
1766 return server;
1773 } 1767 }
1774 1768
1775 /* Get a volume representation */ 1769 /*
1776 server = nfs_mod->rpc_ops->create_server(mount_info, nfs_mod); 1770 * Nothing we tried so far worked. At this point, give up if we've
1771 * already tried AUTH_UNIX or if the server's list doesn't contain
1772 * AUTH_NULL
1773 */
1774 if (tried_auth_unix || !auth_null_in_list)
1775 return server;
1776
1777 /* Last chance! Try AUTH_UNIX */
1778 dfprintk(MOUNT, "NFS: attempting to use auth flavor %u\n", RPC_AUTH_UNIX);
1779 args->auth_flavors[0] = RPC_AUTH_UNIX;
1780 return nfs_mod->rpc_ops->create_server(mount_info, nfs_mod);
1781}
1782
1783struct dentry *nfs_try_mount(int flags, const char *dev_name,
1784 struct nfs_mount_info *mount_info,
1785 struct nfs_subversion *nfs_mod)
1786{
1787 struct nfs_server *server;
1788
1789 if (mount_info->parsed->need_mount)
1790 server = nfs_try_mount_request(mount_info, nfs_mod);
1791 else
1792 server = nfs_mod->rpc_ops->create_server(mount_info, nfs_mod);
1793
1777 if (IS_ERR(server)) 1794 if (IS_ERR(server))
1778 return ERR_CAST(server); 1795 return ERR_CAST(server);
1779 1796
@@ -2412,7 +2429,21 @@ static int nfs_bdi_register(struct nfs_server *server)
2412int nfs_set_sb_security(struct super_block *s, struct dentry *mntroot, 2429int nfs_set_sb_security(struct super_block *s, struct dentry *mntroot,
2413 struct nfs_mount_info *mount_info) 2430 struct nfs_mount_info *mount_info)
2414{ 2431{
2415 return security_sb_set_mnt_opts(s, &mount_info->parsed->lsm_opts); 2432 int error;
2433 unsigned long kflags = 0, kflags_out = 0;
2434 if (NFS_SB(s)->caps & NFS_CAP_SECURITY_LABEL)
2435 kflags |= SECURITY_LSM_NATIVE_LABELS;
2436
2437 error = security_sb_set_mnt_opts(s, &mount_info->parsed->lsm_opts,
2438 kflags, &kflags_out);
2439 if (error)
2440 goto err;
2441
2442 if (NFS_SB(s)->caps & NFS_CAP_SECURITY_LABEL &&
2443 !(kflags_out & SECURITY_LSM_NATIVE_LABELS))
2444 NFS_SB(s)->caps &= ~NFS_CAP_SECURITY_LABEL;
2445err:
2446 return error;
2416} 2447}
2417EXPORT_SYMBOL_GPL(nfs_set_sb_security); 2448EXPORT_SYMBOL_GPL(nfs_set_sb_security);
2418 2449