* [PATCH v4 0/5] Allow the admin to turn off NFSv4 uid/gid mapping @ 2011-01-05 1:57 Trond Myklebust 2011-01-05 1:57 ` [PATCH v4 1/5] NFSv4: If the server sends us a numeric uid/gid then accept it Trond Myklebust 0 siblings, 1 reply; 6+ messages in thread From: Trond Myklebust @ 2011-01-05 1:57 UTC (permalink / raw) To: linux-nfs The following patches allow the admin to turn off NFSv4 uid/gid mapping if mounting using AUTH_SYS security. Minor changes w.r.t. first revision: - Added documentation in kernel-parameters.txt - Print a warning if an NFS4ERR_BADOWNER causes us to turn idmapping on again Changes w.r.t. second revision: - Ensure we propagate the NFS4ERR_BADOWNER up to the NFSv4 middle layers - Fix a typo in nfs4_handle_exception Changes w.r.t. third revision: - Work around a Linux server bug which causes pre-2.6.37 kernels to return NFS4ERR_BADNAME in cases where it should be returning NFS4ERR_BADOWNER. Trond Myklebust (5): NFSv4: If the server sends us a numeric uid/gid then accept it NFSv4: Send unmapped uid/gids to the server if the idmapper fails NFSv4: cleanup idmapper functions to take an nfs_server argument NFSv4: Propagate the error NFS4ERR_BADOWNER to nfs4_do_setattr NFSv4: Send unmapped uid/gids to the server when using auth_sys Documentation/kernel-parameters.txt | 8 +++ fs/nfs/client.c | 16 ++++++ fs/nfs/idmap.c | 87 +++++++++++++++++++++++++++------- fs/nfs/nfs4proc.c | 18 +++++++- fs/nfs/nfs4xdr.c | 20 +++----- include/linux/nfs_fs_sb.h | 1 + include/linux/nfs_idmap.h | 8 ++-- 7 files changed, 123 insertions(+), 35 deletions(-) -- 1.7.3.4 ^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v4 1/5] NFSv4: If the server sends us a numeric uid/gid then accept it 2011-01-05 1:57 [PATCH v4 0/5] Allow the admin to turn off NFSv4 uid/gid mapping Trond Myklebust @ 2011-01-05 1:57 ` Trond Myklebust 2011-01-05 1:57 ` [PATCH v4 2/5] NFSv4: Send unmapped uid/gids to the server if the idmapper fails Trond Myklebust 0 siblings, 1 reply; 6+ messages in thread From: Trond Myklebust @ 2011-01-05 1:57 UTC (permalink / raw) To: linux-nfs Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com> --- fs/nfs/idmap.c | 28 ++++++++++++++++++++++++++-- 1 files changed, 26 insertions(+), 2 deletions(-) diff --git a/fs/nfs/idmap.c b/fs/nfs/idmap.c index 1869688..cbe6e2f 100644 --- a/fs/nfs/idmap.c +++ b/fs/nfs/idmap.c @@ -33,6 +33,24 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include <linux/types.h> +#include <linux/string.h> +#include <linux/kernel.h> + +static int nfs_map_string_to_numeric(const char *name, size_t namelen, __u32 *res) +{ + unsigned long val; + char buf[16]; + + if (memchr(name, '@', namelen) != NULL || namelen >= sizeof(buf)) + return 0; + memcpy(buf, name, namelen); + buf[namelen] = '\0'; + if (strict_strtoul(buf, 0, &val) != 0) + return 0; + *res = val; + return 1; +} #ifdef CONFIG_NFS_USE_NEW_IDMAPPER @@ -42,7 +60,6 @@ #include <linux/keyctl.h> #include <linux/key-type.h> #include <linux/rcupdate.h> -#include <linux/kernel.h> #include <linux/err.h> #include <keys/user-type.h> @@ -221,11 +238,15 @@ static int nfs_idmap_lookup_id(const char *name, size_t namelen, int nfs_map_name_to_uid(struct nfs_client *clp, const char *name, size_t namelen, __u32 *uid) { + if (nfs_map_string_to_numeric(name, namelen, uid)) + return 0; return nfs_idmap_lookup_id(name, namelen, "uid", uid); } int nfs_map_group_to_gid(struct nfs_client *clp, const char *name, size_t namelen, __u32 *gid) { + if (nfs_map_string_to_numeric(name, namelen, gid)) + return 0; return nfs_idmap_lookup_id(name, namelen, "gid", gid); } @@ -243,7 +264,6 @@ int nfs_map_gid_to_group(struct nfs_client *clp, __u32 gid, char *buf, size_t bu #include <linux/module.h> #include <linux/mutex.h> #include <linux/init.h> -#include <linux/types.h> #include <linux/slab.h> #include <linux/socket.h> #include <linux/in.h> @@ -699,6 +719,8 @@ int nfs_map_name_to_uid(struct nfs_client *clp, const char *name, size_t namelen { struct idmap *idmap = clp->cl_idmap; + if (nfs_map_string_to_numeric(name, namelen, uid)) + return 0; return nfs_idmap_id(idmap, &idmap->idmap_user_hash, name, namelen, uid); } @@ -706,6 +728,8 @@ int nfs_map_group_to_gid(struct nfs_client *clp, const char *name, size_t namele { struct idmap *idmap = clp->cl_idmap; + if (nfs_map_string_to_numeric(name, namelen, uid)) + return 0; return nfs_idmap_id(idmap, &idmap->idmap_group_hash, name, namelen, uid); } -- 1.7.3.4 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v4 2/5] NFSv4: Send unmapped uid/gids to the server if the idmapper fails 2011-01-05 1:57 ` [PATCH v4 1/5] NFSv4: If the server sends us a numeric uid/gid then accept it Trond Myklebust @ 2011-01-05 1:57 ` Trond Myklebust 2011-01-05 1:57 ` [PATCH v4 3/5] NFSv4: cleanup idmapper functions to take an nfs_server argument Trond Myklebust 0 siblings, 1 reply; 6+ messages in thread From: Trond Myklebust @ 2011-01-05 1:57 UTC (permalink / raw) To: linux-nfs Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com> --- fs/nfs/idmap.c | 30 ++++++++++++++++++++++++++---- 1 files changed, 26 insertions(+), 4 deletions(-) diff --git a/fs/nfs/idmap.c b/fs/nfs/idmap.c index cbe6e2f..8518573 100644 --- a/fs/nfs/idmap.c +++ b/fs/nfs/idmap.c @@ -52,6 +52,11 @@ static int nfs_map_string_to_numeric(const char *name, size_t namelen, __u32 *re return 1; } +static int nfs_map_numeric_to_string(__u32 id, char *buf, size_t buflen) +{ + return snprintf(buf, buflen, "%u", id); +} + #ifdef CONFIG_NFS_USE_NEW_IDMAPPER #include <linux/slab.h> @@ -252,11 +257,20 @@ int nfs_map_group_to_gid(struct nfs_client *clp, const char *name, size_t namele int nfs_map_uid_to_name(struct nfs_client *clp, __u32 uid, char *buf, size_t buflen) { - return nfs_idmap_lookup_name(uid, "user", buf, buflen); + int ret; + ret = nfs_idmap_lookup_name(uid, "user", buf, buflen); + if (ret < 0) + ret = nfs_map_numeric_to_string(uid, buf, buflen); + return ret; } int nfs_map_gid_to_group(struct nfs_client *clp, __u32 gid, char *buf, size_t buflen) { - return nfs_idmap_lookup_name(gid, "group", buf, buflen); + int ret; + + ret = nfs_idmap_lookup_name(gid, "group", buf, buflen); + if (ret < 0) + ret = nfs_map_numeric_to_string(gid, buf, buflen); + return ret; } #else /* CONFIG_NFS_USE_NEW_IDMAPPER not defined */ @@ -736,14 +750,22 @@ int nfs_map_group_to_gid(struct nfs_client *clp, const char *name, size_t namele int nfs_map_uid_to_name(struct nfs_client *clp, __u32 uid, char *buf, size_t buflen) { struct idmap *idmap = clp->cl_idmap; + int ret; - return nfs_idmap_name(idmap, &idmap->idmap_user_hash, uid, buf); + ret = nfs_idmap_name(idmap, &idmap->idmap_user_hash, uid, buf); + if (ret < 0) + ret = nfs_map_numeric_to_string(uid, buf, buflen); + return ret; } int nfs_map_gid_to_group(struct nfs_client *clp, __u32 uid, char *buf, size_t buflen) { struct idmap *idmap = clp->cl_idmap; + int ret; - return nfs_idmap_name(idmap, &idmap->idmap_group_hash, uid, buf); + ret = nfs_idmap_name(idmap, &idmap->idmap_group_hash, uid, buf); + if (ret < 0) + ret = nfs_map_numeric_to_string(uid, buf, buflen); + return ret; } #endif /* CONFIG_NFS_USE_NEW_IDMAPPER */ -- 1.7.3.4 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v4 3/5] NFSv4: cleanup idmapper functions to take an nfs_server argument 2011-01-05 1:57 ` [PATCH v4 2/5] NFSv4: Send unmapped uid/gids to the server if the idmapper fails Trond Myklebust @ 2011-01-05 1:57 ` Trond Myklebust 2011-01-05 1:57 ` [PATCH v4 4/5] NFSv4: Propagate the error NFS4ERR_BADOWNER to nfs4_do_setattr Trond Myklebust 0 siblings, 1 reply; 6+ messages in thread From: Trond Myklebust @ 2011-01-05 1:57 UTC (permalink / raw) To: linux-nfs ...instead of the nfs_client. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com> --- fs/nfs/idmap.c | 24 ++++++++++++------------ fs/nfs/nfs4xdr.c | 18 ++++++++---------- include/linux/nfs_idmap.h | 8 ++++---- 3 files changed, 24 insertions(+), 26 deletions(-) diff --git a/fs/nfs/idmap.c b/fs/nfs/idmap.c index 8518573..e2d579d 100644 --- a/fs/nfs/idmap.c +++ b/fs/nfs/idmap.c @@ -241,21 +241,21 @@ static int nfs_idmap_lookup_id(const char *name, size_t namelen, return ret; } -int nfs_map_name_to_uid(struct nfs_client *clp, const char *name, size_t namelen, __u32 *uid) +int nfs_map_name_to_uid(const struct nfs_server *server, const char *name, size_t namelen, __u32 *uid) { if (nfs_map_string_to_numeric(name, namelen, uid)) return 0; return nfs_idmap_lookup_id(name, namelen, "uid", uid); } -int nfs_map_group_to_gid(struct nfs_client *clp, const char *name, size_t namelen, __u32 *gid) +int nfs_map_group_to_gid(const struct nfs_server *server, const char *name, size_t namelen, __u32 *gid) { if (nfs_map_string_to_numeric(name, namelen, gid)) return 0; return nfs_idmap_lookup_id(name, namelen, "gid", gid); } -int nfs_map_uid_to_name(struct nfs_client *clp, __u32 uid, char *buf, size_t buflen) +int nfs_map_uid_to_name(const struct nfs_server *server, __u32 uid, char *buf, size_t buflen) { int ret; ret = nfs_idmap_lookup_name(uid, "user", buf, buflen); @@ -263,7 +263,7 @@ int nfs_map_uid_to_name(struct nfs_client *clp, __u32 uid, char *buf, size_t buf ret = nfs_map_numeric_to_string(uid, buf, buflen); return ret; } -int nfs_map_gid_to_group(struct nfs_client *clp, __u32 gid, char *buf, size_t buflen) +int nfs_map_gid_to_group(const struct nfs_server *server, __u32 gid, char *buf, size_t buflen) { int ret; @@ -729,27 +729,27 @@ static unsigned int fnvhash32(const void *buf, size_t buflen) return hash; } -int nfs_map_name_to_uid(struct nfs_client *clp, const char *name, size_t namelen, __u32 *uid) +int nfs_map_name_to_uid(const struct nfs_server *server, const char *name, size_t namelen, __u32 *uid) { - struct idmap *idmap = clp->cl_idmap; + struct idmap *idmap = server->nfs_client->cl_idmap; if (nfs_map_string_to_numeric(name, namelen, uid)) return 0; return nfs_idmap_id(idmap, &idmap->idmap_user_hash, name, namelen, uid); } -int nfs_map_group_to_gid(struct nfs_client *clp, const char *name, size_t namelen, __u32 *uid) +int nfs_map_group_to_gid(const struct nfs_server *server, const char *name, size_t namelen, __u32 *uid) { - struct idmap *idmap = clp->cl_idmap; + struct idmap *idmap = server->nfs_client->cl_idmap; if (nfs_map_string_to_numeric(name, namelen, uid)) return 0; return nfs_idmap_id(idmap, &idmap->idmap_group_hash, name, namelen, uid); } -int nfs_map_uid_to_name(struct nfs_client *clp, __u32 uid, char *buf, size_t buflen) +int nfs_map_uid_to_name(const struct nfs_server *server, __u32 uid, char *buf, size_t buflen) { - struct idmap *idmap = clp->cl_idmap; + struct idmap *idmap = server->nfs_client->cl_idmap; int ret; ret = nfs_idmap_name(idmap, &idmap->idmap_user_hash, uid, buf); @@ -757,9 +757,9 @@ int nfs_map_uid_to_name(struct nfs_client *clp, __u32 uid, char *buf, size_t buf ret = nfs_map_numeric_to_string(uid, buf, buflen); return ret; } -int nfs_map_gid_to_group(struct nfs_client *clp, __u32 uid, char *buf, size_t buflen) +int nfs_map_gid_to_group(const struct nfs_server *server, __u32 uid, char *buf, size_t buflen) { - struct idmap *idmap = clp->cl_idmap; + struct idmap *idmap = server->nfs_client->cl_idmap; int ret; ret = nfs_idmap_name(idmap, &idmap->idmap_group_hash, uid, buf); diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 8e49688..bc205ab 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c @@ -844,7 +844,7 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const if (iap->ia_valid & ATTR_MODE) len += 4; if (iap->ia_valid & ATTR_UID) { - owner_namelen = nfs_map_uid_to_name(server->nfs_client, iap->ia_uid, owner_name, IDMAP_NAMESZ); + owner_namelen = nfs_map_uid_to_name(server, iap->ia_uid, owner_name, IDMAP_NAMESZ); if (owner_namelen < 0) { dprintk("nfs: couldn't resolve uid %d to string\n", iap->ia_uid); @@ -856,7 +856,7 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const len += 4 + (XDR_QUADLEN(owner_namelen) << 2); } if (iap->ia_valid & ATTR_GID) { - owner_grouplen = nfs_map_gid_to_group(server->nfs_client, iap->ia_gid, owner_group, IDMAP_NAMESZ); + owner_grouplen = nfs_map_gid_to_group(server, iap->ia_gid, owner_group, IDMAP_NAMESZ); if (owner_grouplen < 0) { dprintk("nfs: couldn't resolve gid %d to string\n", iap->ia_gid); @@ -3382,7 +3382,7 @@ out_overflow: } static int decode_attr_owner(struct xdr_stream *xdr, uint32_t *bitmap, - struct nfs_client *clp, uint32_t *uid, int may_sleep) + const struct nfs_server *server, uint32_t *uid, int may_sleep) { uint32_t len; __be32 *p; @@ -3402,7 +3402,7 @@ static int decode_attr_owner(struct xdr_stream *xdr, uint32_t *bitmap, if (!may_sleep) { /* do nothing */ } else if (len < XDR_MAX_NETOBJ) { - if (nfs_map_name_to_uid(clp, (char *)p, len, uid) == 0) + if (nfs_map_name_to_uid(server, (char *)p, len, uid) == 0) ret = NFS_ATTR_FATTR_OWNER; else dprintk("%s: nfs_map_name_to_uid failed!\n", @@ -3420,7 +3420,7 @@ out_overflow: } static int decode_attr_group(struct xdr_stream *xdr, uint32_t *bitmap, - struct nfs_client *clp, uint32_t *gid, int may_sleep) + const struct nfs_server *server, uint32_t *gid, int may_sleep) { uint32_t len; __be32 *p; @@ -3440,7 +3440,7 @@ static int decode_attr_group(struct xdr_stream *xdr, uint32_t *bitmap, if (!may_sleep) { /* do nothing */ } else if (len < XDR_MAX_NETOBJ) { - if (nfs_map_group_to_gid(clp, (char *)p, len, gid) == 0) + if (nfs_map_group_to_gid(server, (char *)p, len, gid) == 0) ret = NFS_ATTR_FATTR_GROUP; else dprintk("%s: nfs_map_group_to_gid failed!\n", @@ -3939,14 +3939,12 @@ static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap, goto xdr_error; fattr->valid |= status; - status = decode_attr_owner(xdr, bitmap, server->nfs_client, - &fattr->uid, may_sleep); + status = decode_attr_owner(xdr, bitmap, server, &fattr->uid, may_sleep); if (status < 0) goto xdr_error; fattr->valid |= status; - status = decode_attr_group(xdr, bitmap, server->nfs_client, - &fattr->gid, may_sleep); + status = decode_attr_group(xdr, bitmap, server, &fattr->gid, may_sleep); if (status < 0) goto xdr_error; fattr->valid |= status; diff --git a/include/linux/nfs_idmap.h b/include/linux/nfs_idmap.h index e8352dc..ee97767 100644 --- a/include/linux/nfs_idmap.h +++ b/include/linux/nfs_idmap.h @@ -96,10 +96,10 @@ void nfs_idmap_delete(struct nfs_client *); #endif /* CONFIG_NFS_USE_NEW_IDMAPPER */ -int nfs_map_name_to_uid(struct nfs_client *, const char *, size_t, __u32 *); -int nfs_map_group_to_gid(struct nfs_client *, const char *, size_t, __u32 *); -int nfs_map_uid_to_name(struct nfs_client *, __u32, char *, size_t); -int nfs_map_gid_to_group(struct nfs_client *, __u32, char *, size_t); +int nfs_map_name_to_uid(const struct nfs_server *, const char *, size_t, __u32 *); +int nfs_map_group_to_gid(const struct nfs_server *, const char *, size_t, __u32 *); +int nfs_map_uid_to_name(const struct nfs_server *, __u32, char *, size_t); +int nfs_map_gid_to_group(const struct nfs_server *, __u32, char *, size_t); extern unsigned int nfs_idmap_cache_timeout; #endif /* __KERNEL__ */ -- 1.7.3.4 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v4 4/5] NFSv4: Propagate the error NFS4ERR_BADOWNER to nfs4_do_setattr 2011-01-05 1:57 ` [PATCH v4 3/5] NFSv4: cleanup idmapper functions to take an nfs_server argument Trond Myklebust @ 2011-01-05 1:57 ` Trond Myklebust 2011-01-05 1:57 ` [PATCH v4 5/5] NFSv4: Send unmapped uid/gids to the server when using auth_sys Trond Myklebust 0 siblings, 1 reply; 6+ messages in thread From: Trond Myklebust @ 2011-01-05 1:57 UTC (permalink / raw) To: linux-nfs This will be required in order to switch uid/gid mapping back on if the admin has tried to disable it. Note that we also propagate NFS4ERR_BADNAME at the same time, in order to work around a Linux server bug. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com> --- fs/nfs/nfs4proc.c | 3 +++ fs/nfs/nfs4xdr.c | 2 -- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 2aede9c..39a2e3c 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -84,6 +84,9 @@ static int nfs4_map_errors(int err) switch (err) { case -NFS4ERR_RESOURCE: return -EREMOTEIO; + case -NFS4ERR_BADOWNER: + case -NFS4ERR_NAME: + return -EINVAL; default: dprintk("%s could not handle NFSv4 error %d\n", __func__, -err); diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index bc205ab..1de6b22 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c @@ -6174,8 +6174,6 @@ static struct { { NFS4ERR_DQUOT, -EDQUOT }, { NFS4ERR_STALE, -ESTALE }, { NFS4ERR_BADHANDLE, -EBADHANDLE }, - { NFS4ERR_BADOWNER, -EINVAL }, - { NFS4ERR_BADNAME, -EINVAL }, { NFS4ERR_BAD_COOKIE, -EBADCOOKIE }, { NFS4ERR_NOTSUPP, -ENOTSUPP }, { NFS4ERR_TOOSMALL, -ETOOSMALL }, -- 1.7.3.4 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v4 5/5] NFSv4: Send unmapped uid/gids to the server when using auth_sys 2011-01-05 1:57 ` [PATCH v4 4/5] NFSv4: Propagate the error NFS4ERR_BADOWNER to nfs4_do_setattr Trond Myklebust @ 2011-01-05 1:57 ` Trond Myklebust 0 siblings, 0 replies; 6+ messages in thread From: Trond Myklebust @ 2011-01-05 1:57 UTC (permalink / raw) To: linux-nfs 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> --- Documentation/kernel-parameters.txt | 8 ++++++++ fs/nfs/client.c | 16 ++++++++++++++++ fs/nfs/idmap.c | 21 +++++++++++++-------- fs/nfs/nfs4proc.c | 15 ++++++++++++++- include/linux/nfs_fs_sb.h | 1 + 5 files changed, 52 insertions(+), 9 deletions(-) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index cdd2a6e..51a74a3 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -1573,6 +1573,14 @@ and is between 256 and 4096 characters. It is defined in the file of returning the full 64-bit number. The default is to return 64-bit inode numbers. + nfs.nfs4_disable_idmapping= + [NFSv4] When set, this option disables the NFSv4 + idmapper on the client, but only if the mount + is using the 'sec=sys' security flavour. This may + make migration from legacy NFSv2/v3 systems easier + provided that the server has the appropriate support. + The default is to always enable NFSv4 idmapping. + nmi_debug= [KNL,AVR32,SH] Specify one or more actions to take when a NMI is triggered. Format: [state][,regs][,debounce][,die] diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 7908530..a6c0324 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c @@ -58,6 +58,11 @@ static LIST_HEAD(nfs_volume_list); static DECLARE_WAIT_QUEUE_HEAD(nfs_client_active_wq); /* + * Turn off NFSv4 uid/gid mapping when using AUTH_SYS + */ +static int nfs4_disable_idmapping = 0; + +/* * RPC cruft for NFS */ static struct rpc_version *nfs_version[5] = { @@ -1447,6 +1452,13 @@ static int nfs4_init_server(struct nfs_server *server, if (error < 0) goto error; + /* + * Don't use NFS uid/gid mapping if we're using AUTH_SYS or lower + * authentication. + */ + if (nfs4_disable_idmapping && data->auth_flavors[0] == RPC_AUTH_UNIX) + server->caps |= NFS_CAP_UIDGID_NOMAP; + if (data->rsize) server->rsize = nfs_block_size(data->rsize, NULL); if (data->wsize) @@ -1864,3 +1876,7 @@ void nfs_fs_proc_exit(void) } #endif /* CONFIG_PROC_FS */ + +module_param(nfs4_disable_idmapping, bool, 0644); +MODULE_PARM_DESC(nfs4_disable_idmapping, + "Turn off NFSv4 idmapping when using 'sec=sys'"); diff --git a/fs/nfs/idmap.c b/fs/nfs/idmap.c index e2d579d..ee4ab8f 100644 --- a/fs/nfs/idmap.c +++ b/fs/nfs/idmap.c @@ -257,17 +257,20 @@ int nfs_map_group_to_gid(const struct nfs_server *server, const char *name, size int nfs_map_uid_to_name(const struct nfs_server *server, __u32 uid, char *buf, size_t buflen) { - int ret; - ret = nfs_idmap_lookup_name(uid, "user", buf, buflen); + int ret = -EINVAL; + + if (!(server->caps & NFS_CAP_UIDGID_NOMAP)) + ret = nfs_idmap_lookup_name(uid, "user", buf, buflen); if (ret < 0) ret = nfs_map_numeric_to_string(uid, buf, buflen); return ret; } int nfs_map_gid_to_group(const struct nfs_server *server, __u32 gid, char *buf, size_t buflen) { - int ret; + int ret = -EINVAL; - ret = nfs_idmap_lookup_name(gid, "group", buf, buflen); + if (!(server->caps & NFS_CAP_UIDGID_NOMAP)) + ret = nfs_idmap_lookup_name(gid, "group", buf, buflen); if (ret < 0) ret = nfs_map_numeric_to_string(gid, buf, buflen); return ret; @@ -750,9 +753,10 @@ int nfs_map_group_to_gid(const struct nfs_server *server, const char *name, size int nfs_map_uid_to_name(const struct nfs_server *server, __u32 uid, char *buf, size_t buflen) { struct idmap *idmap = server->nfs_client->cl_idmap; - int ret; + int ret = -EINVAL; - ret = nfs_idmap_name(idmap, &idmap->idmap_user_hash, uid, buf); + if (!(server->caps & NFS_CAP_UIDGID_NOMAP)) + ret = nfs_idmap_name(idmap, &idmap->idmap_user_hash, uid, buf); if (ret < 0) ret = nfs_map_numeric_to_string(uid, buf, buflen); return ret; @@ -760,9 +764,10 @@ int nfs_map_uid_to_name(const struct nfs_server *server, __u32 uid, char *buf, s int nfs_map_gid_to_group(const struct nfs_server *server, __u32 uid, char *buf, size_t buflen) { struct idmap *idmap = server->nfs_client->cl_idmap; - int ret; + int ret = -EINVAL; - ret = nfs_idmap_name(idmap, &idmap->idmap_group_hash, uid, buf); + if (!(server->caps & NFS_CAP_UIDGID_NOMAP)) + ret = nfs_idmap_name(idmap, &idmap->idmap_group_hash, uid, buf); if (ret < 0) ret = nfs_map_numeric_to_string(uid, buf, buflen); return ret; diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 39a2e3c..e06b531 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -243,7 +243,7 @@ static int nfs4_delay(struct rpc_clnt *clnt, long *timeout) /* This is the error handling routine for processes that are allowed * to sleep. */ -static int nfs4_handle_exception(const struct nfs_server *server, int errorcode, struct nfs4_exception *exception) +static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struct nfs4_exception *exception) { struct nfs_client *clp = server->nfs_client; struct nfs4_state *state = exception->state; @@ -294,6 +294,19 @@ static int nfs4_handle_exception(const struct nfs_server *server, int errorcode, break; case -NFS4ERR_OLD_STATEID: exception->retry = 1; + break; + case -NFS4ERR_BADOWNER: + /* The following works around a Linux server bug! */ + case -NFS4ERR_BADNAME: + if (server->caps & NFS_CAP_UIDGID_NOMAP) { + server->caps &= ~NFS_CAP_UIDGID_NOMAP; + exception->retry = 1; + printk(KERN_WARNING "NFS: v4 server %s " + "does not accept raw " + "uid/gids. " + "Reenabling the idmapper.\n", + server->nfs_client->cl_hostname); + } } /* We failed to handle the error */ return nfs4_map_errors(ret); diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h index b197563..8fa77c6 100644 --- a/include/linux/nfs_fs_sb.h +++ b/include/linux/nfs_fs_sb.h @@ -180,6 +180,7 @@ struct nfs_server { #define NFS_CAP_CTIME (1U << 12) #define NFS_CAP_MTIME (1U << 13) #define NFS_CAP_POSIX_LOCK (1U << 14) +#define NFS_CAP_UIDGID_NOMAP (1U << 15) /* maximum number of slots to use */ -- 1.7.3.4 ^ permalink raw reply related [flat|nested] 6+ messages in thread
end of thread, other threads:[~2011-01-05 1:58 UTC | newest] Thread overview: 6+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2011-01-05 1:57 [PATCH v4 0/5] Allow the admin to turn off NFSv4 uid/gid mapping Trond Myklebust 2011-01-05 1:57 ` [PATCH v4 1/5] NFSv4: If the server sends us a numeric uid/gid then accept it Trond Myklebust 2011-01-05 1:57 ` [PATCH v4 2/5] NFSv4: Send unmapped uid/gids to the server if the idmapper fails Trond Myklebust 2011-01-05 1:57 ` [PATCH v4 3/5] NFSv4: cleanup idmapper functions to take an nfs_server argument Trond Myklebust 2011-01-05 1:57 ` [PATCH v4 4/5] NFSv4: Propagate the error NFS4ERR_BADOWNER to nfs4_do_setattr Trond Myklebust 2011-01-05 1:57 ` [PATCH v4 5/5] NFSv4: Send unmapped uid/gids to the server when using auth_sys Trond Myklebust
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).