aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/super.c
diff options
context:
space:
mode:
authorSage Weil <sage@inktank.com>2013-08-15 14:11:45 -0400
committerSage Weil <sage@inktank.com>2013-08-15 14:11:45 -0400
commitee3e542fec6e69bc9fb668698889a37d93950ddf (patch)
treee74ee766a4764769ef1d3d45d266b4dea64101d3 /fs/nfs/super.c
parentfe2a801b50c0bb8039d627e5ae1fec249d10ff39 (diff)
parentf1d6e17f540af37bb1891480143669ba7636c4cf (diff)
Merge remote-tracking branch 'linus/master' into testing
Diffstat (limited to 'fs/nfs/super.c')
-rw-r--r--fs/nfs/super.c203
1 files changed, 119 insertions, 84 deletions
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 2d7525fbcf25..f6db66d8f647 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++) {
1660 struct rpcsec_gss_info info;
1661
1662 flavor = request->auth_flavs[i];
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 }
1673
1674 /*
1675 * As a last chance, see if the server list contains AUTH_NULL -
1676 * if it does, use the default flavor.
1677 */
1678 for (i = 0; i < count; i++) { 1633 for (i = 0; i < count; i++) {
1679 if (request->auth_flavs[i] == RPC_AUTH_NULL) 1634 if (args->auth_flavors[0] == server_authlist[i] ||
1680 goto out_default; 1635 server_authlist[i] == RPC_AUTH_NULL)
1636 goto out;
1681 } 1637 }
1682 1638
1683 dfprintk(MOUNT, "NFS: no auth flavors in common with server\n"); 1639 dfprintk(MOUNT, "NFS: auth flavor %u not supported by server\n",
1684 goto out_err; 1640 args->auth_flavors[0]);
1641 return -EACCES;
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
@@ -2447,6 +2478,10 @@ struct dentry *nfs_fs_mount_common(struct nfs_server *server,
2447 if (server->flags & NFS_MOUNT_NOAC) 2478 if (server->flags & NFS_MOUNT_NOAC)
2448 sb_mntdata.mntflags |= MS_SYNCHRONOUS; 2479 sb_mntdata.mntflags |= MS_SYNCHRONOUS;
2449 2480
2481 if (mount_info->cloned != NULL && mount_info->cloned->sb != NULL)
2482 if (mount_info->cloned->sb->s_flags & MS_SYNCHRONOUS)
2483 sb_mntdata.mntflags |= MS_SYNCHRONOUS;
2484
2450 /* Get a superblock - note that we may end up sharing one that already exists */ 2485 /* Get a superblock - note that we may end up sharing one that already exists */
2451 s = sget(nfs_mod->nfs_fs, compare_super, nfs_set_super, flags, &sb_mntdata); 2486 s = sget(nfs_mod->nfs_fs, compare_super, nfs_set_super, flags, &sb_mntdata);
2452 if (IS_ERR(s)) { 2487 if (IS_ERR(s)) {