Commit b064eca2cf6440bf9d5843b24cc4010624031694
1 parent
3ddeb7c5c6
Exists in
master
and in
20 other branches
NFSv4: Send unmapped uid/gids to the server when using auth_sys
The new behaviour is enabled using the new module parameter 'nfs4_disable_idmapping'. Note that if the server rejects an unmapped uid or gid, then the client will automatically switch back to using the idmapper. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Showing 5 changed files with 55 additions and 9 deletions Side-by-side Diff
Documentation/kernel-parameters.txt
... | ... | @@ -1580,6 +1580,14 @@ |
1580 | 1580 | of returning the full 64-bit number. |
1581 | 1581 | The default is to return 64-bit inode numbers. |
1582 | 1582 | |
1583 | + nfs.nfs4_disable_idmapping= | |
1584 | + [NFSv4] When set, this option disables the NFSv4 | |
1585 | + idmapper on the client, but only if the mount | |
1586 | + is using the 'sec=sys' security flavour. This may | |
1587 | + make migration from legacy NFSv2/v3 systems easier | |
1588 | + provided that the server has the appropriate support. | |
1589 | + The default is to always enable NFSv4 idmapping. | |
1590 | + | |
1583 | 1591 | nmi_debug= [KNL,AVR32,SH] Specify one or more actions to take |
1584 | 1592 | when a NMI is triggered. |
1585 | 1593 | Format: [state][,regs][,debounce][,die] |
fs/nfs/client.c
... | ... | @@ -82,6 +82,11 @@ |
82 | 82 | #endif /* CONFIG_NFS_V4 */ |
83 | 83 | |
84 | 84 | /* |
85 | + * Turn off NFSv4 uid/gid mapping when using AUTH_SYS | |
86 | + */ | |
87 | +static int nfs4_disable_idmapping = 0; | |
88 | + | |
89 | +/* | |
85 | 90 | * RPC cruft for NFS |
86 | 91 | */ |
87 | 92 | static struct rpc_version *nfs_version[5] = { |
... | ... | @@ -1567,6 +1572,13 @@ |
1567 | 1572 | if (error < 0) |
1568 | 1573 | goto error; |
1569 | 1574 | |
1575 | + /* | |
1576 | + * Don't use NFS uid/gid mapping if we're using AUTH_SYS or lower | |
1577 | + * authentication. | |
1578 | + */ | |
1579 | + if (nfs4_disable_idmapping && data->auth_flavors[0] == RPC_AUTH_UNIX) | |
1580 | + server->caps |= NFS_CAP_UIDGID_NOMAP; | |
1581 | + | |
1570 | 1582 | if (data->rsize) |
1571 | 1583 | server->rsize = nfs_block_size(data->rsize, NULL); |
1572 | 1584 | if (data->wsize) |
... | ... | @@ -1984,4 +1996,8 @@ |
1984 | 1996 | } |
1985 | 1997 | |
1986 | 1998 | #endif /* CONFIG_PROC_FS */ |
1999 | + | |
2000 | +module_param(nfs4_disable_idmapping, bool, 0644); | |
2001 | +MODULE_PARM_DESC(nfs4_disable_idmapping, | |
2002 | + "Turn off NFSv4 idmapping when using 'sec=sys'"); |
fs/nfs/idmap.c
... | ... | @@ -61,6 +61,9 @@ |
61 | 61 | |
62 | 62 | #include <linux/slab.h> |
63 | 63 | #include <linux/cred.h> |
64 | +#include <linux/sunrpc/sched.h> | |
65 | +#include <linux/nfs4.h> | |
66 | +#include <linux/nfs_fs_sb.h> | |
64 | 67 | #include <linux/nfs_idmap.h> |
65 | 68 | #include <linux/keyctl.h> |
66 | 69 | #include <linux/key-type.h> |
67 | 70 | |
68 | 71 | |
... | ... | @@ -257,17 +260,20 @@ |
257 | 260 | |
258 | 261 | int nfs_map_uid_to_name(const struct nfs_server *server, __u32 uid, char *buf, size_t buflen) |
259 | 262 | { |
260 | - int ret; | |
261 | - ret = nfs_idmap_lookup_name(uid, "user", buf, buflen); | |
263 | + int ret = -EINVAL; | |
264 | + | |
265 | + if (!(server->caps & NFS_CAP_UIDGID_NOMAP)) | |
266 | + ret = nfs_idmap_lookup_name(uid, "user", buf, buflen); | |
262 | 267 | if (ret < 0) |
263 | 268 | ret = nfs_map_numeric_to_string(uid, buf, buflen); |
264 | 269 | return ret; |
265 | 270 | } |
266 | 271 | int nfs_map_gid_to_group(const struct nfs_server *server, __u32 gid, char *buf, size_t buflen) |
267 | 272 | { |
268 | - int ret; | |
273 | + int ret = -EINVAL; | |
269 | 274 | |
270 | - ret = nfs_idmap_lookup_name(gid, "group", buf, buflen); | |
275 | + if (!(server->caps & NFS_CAP_UIDGID_NOMAP)) | |
276 | + ret = nfs_idmap_lookup_name(gid, "group", buf, buflen); | |
271 | 277 | if (ret < 0) |
272 | 278 | ret = nfs_map_numeric_to_string(gid, buf, buflen); |
273 | 279 | return ret; |
274 | 280 | |
... | ... | @@ -750,9 +756,10 @@ |
750 | 756 | int nfs_map_uid_to_name(const struct nfs_server *server, __u32 uid, char *buf, size_t buflen) |
751 | 757 | { |
752 | 758 | struct idmap *idmap = server->nfs_client->cl_idmap; |
753 | - int ret; | |
759 | + int ret = -EINVAL; | |
754 | 760 | |
755 | - ret = nfs_idmap_name(idmap, &idmap->idmap_user_hash, uid, buf); | |
761 | + if (!(server->caps & NFS_CAP_UIDGID_NOMAP)) | |
762 | + ret = nfs_idmap_name(idmap, &idmap->idmap_user_hash, uid, buf); | |
756 | 763 | if (ret < 0) |
757 | 764 | ret = nfs_map_numeric_to_string(uid, buf, buflen); |
758 | 765 | return ret; |
759 | 766 | |
... | ... | @@ -760,9 +767,10 @@ |
760 | 767 | int nfs_map_gid_to_group(const struct nfs_server *server, __u32 uid, char *buf, size_t buflen) |
761 | 768 | { |
762 | 769 | struct idmap *idmap = server->nfs_client->cl_idmap; |
763 | - int ret; | |
770 | + int ret = -EINVAL; | |
764 | 771 | |
765 | - ret = nfs_idmap_name(idmap, &idmap->idmap_group_hash, uid, buf); | |
772 | + if (!(server->caps & NFS_CAP_UIDGID_NOMAP)) | |
773 | + ret = nfs_idmap_name(idmap, &idmap->idmap_group_hash, uid, buf); | |
766 | 774 | if (ret < 0) |
767 | 775 | ret = nfs_map_numeric_to_string(uid, buf, buflen); |
768 | 776 | return ret; |
fs/nfs/nfs4proc.c
... | ... | @@ -244,7 +244,7 @@ |
244 | 244 | /* This is the error handling routine for processes that are allowed |
245 | 245 | * to sleep. |
246 | 246 | */ |
247 | -static int nfs4_handle_exception(const struct nfs_server *server, int errorcode, struct nfs4_exception *exception) | |
247 | +static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struct nfs4_exception *exception) | |
248 | 248 | { |
249 | 249 | struct nfs_client *clp = server->nfs_client; |
250 | 250 | struct nfs4_state *state = exception->state; |
... | ... | @@ -296,6 +296,19 @@ |
296 | 296 | break; |
297 | 297 | case -NFS4ERR_OLD_STATEID: |
298 | 298 | exception->retry = 1; |
299 | + break; | |
300 | + case -NFS4ERR_BADOWNER: | |
301 | + /* The following works around a Linux server bug! */ | |
302 | + case -NFS4ERR_BADNAME: | |
303 | + if (server->caps & NFS_CAP_UIDGID_NOMAP) { | |
304 | + server->caps &= ~NFS_CAP_UIDGID_NOMAP; | |
305 | + exception->retry = 1; | |
306 | + printk(KERN_WARNING "NFS: v4 server %s " | |
307 | + "does not accept raw " | |
308 | + "uid/gids. " | |
309 | + "Reenabling the idmapper.\n", | |
310 | + server->nfs_client->cl_hostname); | |
311 | + } | |
299 | 312 | } |
300 | 313 | /* We failed to handle the error */ |
301 | 314 | return nfs4_map_errors(ret); |
include/linux/nfs_fs_sb.h