diff options
author | Weston Andros Adamson <dros@netapp.com> | 2013-05-06 17:12:13 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2013-05-06 17:24:36 -0400 |
commit | d497ab975141666e674e7bd8729e00095ec23c9d (patch) | |
tree | 9847dd4431a960900dc7980eebafff3df57463b2 /fs/nfs | |
parent | c8b2d0bfd3370a5e19e64ddb23f8bc1276410b6c (diff) |
NFSv3: match sec= flavor against server list
Older linux clients match the 'sec=' mount option flavor against the server's
flavor list (if available) and return EPERM if the specified flavor or AUTH_NULL
(which "matches" any flavor) is not found.
Recent changes skip this step and allow the vfs mount even though no operations
will succeed, creating a 'dud' mount.
This patch reverts back to the old behavior of matching specified flavors
against the server list and also returns EPERM when no sec= is specified and
none of the flavors returned by the server are supported by the client.
Example of behavior change:
the server's /etc/exports:
/export/krb5 *(sec=krb5,rw,no_root_squash)
old client behavior:
$ uname -a
Linux one.apikia.fake 3.8.8-202.fc18.x86_64 #1 SMP Wed Apr 17 23:25:17 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux
$ sudo mount -v -o sec=sys,vers=3 zero:/export/krb5 /mnt
mount.nfs: timeout set for Sun May 5 17:32:04 2013
mount.nfs: trying text-based options 'sec=sys,vers=3,addr=192.168.100.10'
mount.nfs: prog 100003, trying vers=3, prot=6
mount.nfs: trying 192.168.100.10 prog 100003 vers 3 prot TCP port 2049
mount.nfs: prog 100005, trying vers=3, prot=17
mount.nfs: trying 192.168.100.10 prog 100005 vers 3 prot UDP port 20048
mount.nfs: mount(2): Permission denied
mount.nfs: access denied by server while mounting zero:/export/krb5
recently changed behavior:
$ uname -a
Linux one.apikia.fake 3.9.0-testing+ #2 SMP Fri May 3 20:29:32 EDT 2013 x86_64 x86_64 x86_64 GNU/Linux
$ sudo mount -v -o sec=sys,vers=3 zero:/export/krb5 /mnt
mount.nfs: timeout set for Sun May 5 17:37:17 2013
mount.nfs: trying text-based options 'sec=sys,vers=3,addr=192.168.100.10'
mount.nfs: prog 100003, trying vers=3, prot=6
mount.nfs: trying 192.168.100.10 prog 100003 vers 3 prot TCP port 2049
mount.nfs: prog 100005, trying vers=3, prot=17
mount.nfs: trying 192.168.100.10 prog 100005 vers 3 prot UDP port 20048
$ ls /mnt
ls: cannot open directory /mnt: Permission denied
$ sudo ls /mnt
ls: cannot open directory /mnt: Permission denied
$ sudo df /mnt
df: ‘/mnt’: Permission denied
df: no file systems processed
$ sudo umount /mnt
$
Signed-off-by: Weston Andros Adamson <dros@netapp.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/super.c | 48 |
1 files changed, 41 insertions, 7 deletions
diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 3bb8318f6d0c..b65001c0a119 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c | |||
@@ -1607,16 +1607,15 @@ out_security_failure: | |||
1607 | /* | 1607 | /* |
1608 | * Select a security flavor for this mount. The selected flavor | 1608 | * Select a security flavor for this mount. The selected flavor |
1609 | * is planted in args->auth_flavors[0]. | 1609 | * is planted in args->auth_flavors[0]. |
1610 | * | ||
1611 | * Returns 0 on success, -EACCES on failure. | ||
1610 | */ | 1612 | */ |
1611 | static void nfs_select_flavor(struct nfs_parsed_mount_data *args, | 1613 | static int nfs_select_flavor(struct nfs_parsed_mount_data *args, |
1612 | struct nfs_mount_request *request) | 1614 | struct nfs_mount_request *request) |
1613 | { | 1615 | { |
1614 | unsigned int i, count = *(request->auth_flav_len); | 1616 | unsigned int i, count = *(request->auth_flav_len); |
1615 | rpc_authflavor_t flavor; | 1617 | rpc_authflavor_t flavor; |
1616 | 1618 | ||
1617 | if (args->auth_flavors[0] != RPC_AUTH_MAXFLAVOR) | ||
1618 | goto out; | ||
1619 | |||
1620 | /* | 1619 | /* |
1621 | * The NFSv2 MNT operation does not return a flavor list. | 1620 | * The NFSv2 MNT operation does not return a flavor list. |
1622 | */ | 1621 | */ |
@@ -1631,6 +1630,25 @@ static void nfs_select_flavor(struct nfs_parsed_mount_data *args, | |||
1631 | goto out_default; | 1630 | goto out_default; |
1632 | 1631 | ||
1633 | /* | 1632 | /* |
1633 | * If the sec= mount option is used, the specified flavor or AUTH_NULL | ||
1634 | * must be in the list returned by the server. | ||
1635 | * | ||
1636 | * AUTH_NULL has a special meaning when it's in the server list - it | ||
1637 | * means that the server will ignore the rpc creds, so any flavor | ||
1638 | * can be used. | ||
1639 | */ | ||
1640 | if (args->auth_flavors[0] != RPC_AUTH_MAXFLAVOR) { | ||
1641 | for (i = 0; i < count; i++) { | ||
1642 | if (args->auth_flavors[0] == request->auth_flavs[i] || | ||
1643 | request->auth_flavs[i] == RPC_AUTH_NULL) | ||
1644 | goto out; | ||
1645 | } | ||
1646 | dfprintk(MOUNT, "NFS: auth flavor %d not supported by server\n", | ||
1647 | args->auth_flavors[0]); | ||
1648 | goto out_err; | ||
1649 | } | ||
1650 | |||
1651 | /* | ||
1634 | * RFC 2623, section 2.7 suggests we SHOULD prefer the | 1652 | * RFC 2623, section 2.7 suggests we SHOULD prefer the |
1635 | * flavor listed first. However, some servers list | 1653 | * flavor listed first. However, some servers list |
1636 | * AUTH_NULL first. Avoid ever choosing AUTH_NULL. | 1654 | * AUTH_NULL first. Avoid ever choosing AUTH_NULL. |
@@ -1650,12 +1668,29 @@ static void nfs_select_flavor(struct nfs_parsed_mount_data *args, | |||
1650 | } | 1668 | } |
1651 | } | 1669 | } |
1652 | 1670 | ||
1671 | /* | ||
1672 | * As a last chance, see if the server list contains AUTH_NULL - | ||
1673 | * if it does, use the default flavor. | ||
1674 | */ | ||
1675 | for (i = 0; i < count; i++) { | ||
1676 | if (request->auth_flavs[i] == RPC_AUTH_NULL) | ||
1677 | goto out_default; | ||
1678 | } | ||
1679 | |||
1680 | dfprintk(MOUNT, "NFS: no auth flavors in common with server\n"); | ||
1681 | goto out_err; | ||
1682 | |||
1653 | out_default: | 1683 | out_default: |
1654 | flavor = RPC_AUTH_UNIX; | 1684 | /* use default if flavor not already set */ |
1685 | flavor = (args->auth_flavors[0] == RPC_AUTH_MAXFLAVOR) ? | ||
1686 | RPC_AUTH_UNIX : args->auth_flavors[0]; | ||
1655 | out_set: | 1687 | out_set: |
1656 | args->auth_flavors[0] = flavor; | 1688 | args->auth_flavors[0] = flavor; |
1657 | out: | 1689 | out: |
1658 | dfprintk(MOUNT, "NFS: using auth flavor %d\n", args->auth_flavors[0]); | 1690 | dfprintk(MOUNT, "NFS: using auth flavor %d\n", args->auth_flavors[0]); |
1691 | return 0; | ||
1692 | out_err: | ||
1693 | return -EACCES; | ||
1659 | } | 1694 | } |
1660 | 1695 | ||
1661 | /* | 1696 | /* |
@@ -1718,8 +1753,7 @@ static int nfs_request_mount(struct nfs_parsed_mount_data *args, | |||
1718 | return status; | 1753 | return status; |
1719 | } | 1754 | } |
1720 | 1755 | ||
1721 | nfs_select_flavor(args, &request); | 1756 | return nfs_select_flavor(args, &request); |
1722 | return 0; | ||
1723 | } | 1757 | } |
1724 | 1758 | ||
1725 | struct dentry *nfs_try_mount(int flags, const char *dev_name, | 1759 | struct dentry *nfs_try_mount(int flags, const char *dev_name, |