Skip to content

Commit b064eca

Browse files
Trond MyklebustTrond Myklebust
authored andcommitted
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 <[email protected]>
1 parent 3ddeb7c commit b064eca

File tree

5 files changed

+55
-9
lines changed

5 files changed

+55
-9
lines changed

Documentation/kernel-parameters.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1580,6 +1580,14 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
15801580
of returning the full 64-bit number.
15811581
The default is to return 64-bit inode numbers.
15821582

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+
15831591
nmi_debug= [KNL,AVR32,SH] Specify one or more actions to take
15841592
when a NMI is triggered.
15851593
Format: [state][,regs][,debounce][,die]

fs/nfs/client.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,11 @@ static int nfs_get_cb_ident_idr(struct nfs_client *clp, int minorversion)
8181
}
8282
#endif /* CONFIG_NFS_V4 */
8383

84+
/*
85+
* Turn off NFSv4 uid/gid mapping when using AUTH_SYS
86+
*/
87+
static int nfs4_disable_idmapping = 0;
88+
8489
/*
8590
* RPC cruft for NFS
8691
*/
@@ -1567,6 +1572,13 @@ static int nfs4_init_server(struct nfs_server *server,
15671572
if (error < 0)
15681573
goto error;
15691574

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+
15701582
if (data->rsize)
15711583
server->rsize = nfs_block_size(data->rsize, NULL);
15721584
if (data->wsize)
@@ -1984,3 +1996,7 @@ void nfs_fs_proc_exit(void)
19841996
}
19851997

19861998
#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

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ static int nfs_map_numeric_to_string(__u32 id, char *buf, size_t buflen)
6161

6262
#include <linux/slab.h>
6363
#include <linux/cred.h>
64+
#include <linux/sunrpc/sched.h>
65+
#include <linux/nfs4.h>
66+
#include <linux/nfs_fs_sb.h>
6467
#include <linux/nfs_idmap.h>
6568
#include <linux/keyctl.h>
6669
#include <linux/key-type.h>
@@ -257,17 +260,20 @@ int nfs_map_group_to_gid(const struct nfs_server *server, const char *name, size
257260

258261
int nfs_map_uid_to_name(const struct nfs_server *server, __u32 uid, char *buf, size_t buflen)
259262
{
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);
262267
if (ret < 0)
263268
ret = nfs_map_numeric_to_string(uid, buf, buflen);
264269
return ret;
265270
}
266271
int nfs_map_gid_to_group(const struct nfs_server *server, __u32 gid, char *buf, size_t buflen)
267272
{
268-
int ret;
273+
int ret = -EINVAL;
269274

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);
271277
if (ret < 0)
272278
ret = nfs_map_numeric_to_string(gid, buf, buflen);
273279
return ret;
@@ -750,19 +756,21 @@ int nfs_map_group_to_gid(const struct nfs_server *server, const char *name, size
750756
int nfs_map_uid_to_name(const struct nfs_server *server, __u32 uid, char *buf, size_t buflen)
751757
{
752758
struct idmap *idmap = server->nfs_client->cl_idmap;
753-
int ret;
759+
int ret = -EINVAL;
754760

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);
756763
if (ret < 0)
757764
ret = nfs_map_numeric_to_string(uid, buf, buflen);
758765
return ret;
759766
}
760767
int nfs_map_gid_to_group(const struct nfs_server *server, __u32 uid, char *buf, size_t buflen)
761768
{
762769
struct idmap *idmap = server->nfs_client->cl_idmap;
763-
int ret;
770+
int ret = -EINVAL;
764771

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);
766774
if (ret < 0)
767775
ret = nfs_map_numeric_to_string(uid, buf, buflen);
768776
return ret;

fs/nfs/nfs4proc.c

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ static int nfs4_delay(struct rpc_clnt *clnt, long *timeout)
244244
/* This is the error handling routine for processes that are allowed
245245
* to sleep.
246246
*/
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)
248248
{
249249
struct nfs_client *clp = server->nfs_client;
250250
struct nfs4_state *state = exception->state;
@@ -296,6 +296,19 @@ static int nfs4_handle_exception(const struct nfs_server *server, int errorcode,
296296
break;
297297
case -NFS4ERR_OLD_STATEID:
298298
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+
}
299312
}
300313
/* We failed to handle the error */
301314
return nfs4_map_errors(ret);

include/linux/nfs_fs_sb.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ struct nfs_server {
177177
#define NFS_CAP_CTIME (1U << 12)
178178
#define NFS_CAP_MTIME (1U << 13)
179179
#define NFS_CAP_POSIX_LOCK (1U << 14)
180+
#define NFS_CAP_UIDGID_NOMAP (1U << 15)
180181

181182

182183
/* maximum number of slots to use */

0 commit comments

Comments
 (0)