diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 0d79a88f4de9..e4f84f013b57 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -1686,6 +1686,12 @@ bytes respectively. Such letter suffixes can also be entirely omitted. The default is to send the implementation identification information. + nfsd.nfs4_disable_idmapping= + [NFSv4] When set to the default of '1', the NFSv4 + server will return only numeric uids and gids to + clients using auth_sys, and will accept numeric uids + and gids from such clients. This is intended to ease + migration from NFSv2/v3. objlayoutdriver.osd_login_prog= [NFS] [OBJLAYOUT] sets the pathname to the program which diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c index 94096273cd6c..69ca9c5bb600 100644 --- a/fs/nfsd/nfs4idmap.c +++ b/fs/nfsd/nfs4idmap.c @@ -40,6 +40,14 @@ #include "idmap.h" #include "nfsd.h" +/* + * Turn off idmapping when using AUTH_SYS. + */ +static bool nfs4_disable_idmapping = true; +module_param(nfs4_disable_idmapping, bool, 0644); +MODULE_PARM_DESC(nfs4_disable_idmapping, + "Turn off server's NFSv4 idmapping when using 'sec=sys'"); + /* * Cache entry */ @@ -561,28 +569,65 @@ idmap_id_to_name(struct svc_rqst *rqstp, int type, uid_t id, char *name) return ret; } +static bool +numeric_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen, uid_t *id) +{ + int ret; + char buf[11]; + + if (namelen + 1 > sizeof(buf)) + /* too long to represent a 32-bit id: */ + return false; + /* Just to make sure it's null-terminated: */ + memcpy(buf, name, namelen); + buf[namelen] = '\0'; + ret = strict_strtoul(name, 10, (unsigned long *)id); + return ret == 0; +} + +static __be32 +do_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen, uid_t *id) +{ + if (nfs4_disable_idmapping && rqstp->rq_flavor < RPC_AUTH_GSS) + if (numeric_name_to_id(rqstp, type, name, namelen, id)) + return 0; + /* + * otherwise, fall through and try idmapping, for + * backwards compatibility with clients sending names: + */ + return idmap_name_to_id(rqstp, type, name, namelen, id); +} + +static int +do_id_to_name(struct svc_rqst *rqstp, int type, uid_t id, char *name) +{ + if (nfs4_disable_idmapping && rqstp->rq_flavor < RPC_AUTH_GSS) + return sprintf(name, "%u", id); + return idmap_id_to_name(rqstp, type, id, name); +} + __be32 nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name, size_t namelen, __u32 *id) { - return idmap_name_to_id(rqstp, IDMAP_TYPE_USER, name, namelen, id); + return do_name_to_id(rqstp, IDMAP_TYPE_USER, name, namelen, id); } __be32 nfsd_map_name_to_gid(struct svc_rqst *rqstp, const char *name, size_t namelen, __u32 *id) { - return idmap_name_to_id(rqstp, IDMAP_TYPE_GROUP, name, namelen, id); + return do_name_to_id(rqstp, IDMAP_TYPE_GROUP, name, namelen, id); } int nfsd_map_uid_to_name(struct svc_rqst *rqstp, __u32 id, char *name) { - return idmap_id_to_name(rqstp, IDMAP_TYPE_USER, id, name); + return do_id_to_name(rqstp, IDMAP_TYPE_USER, id, name); } int nfsd_map_gid_to_name(struct svc_rqst *rqstp, __u32 id, char *name) { - return idmap_id_to_name(rqstp, IDMAP_TYPE_GROUP, id, name); + return do_id_to_name(rqstp, IDMAP_TYPE_GROUP, id, name); }