Commit 58002399 authored by Trond Myklebust's avatar Trond Myklebust Committed by Anna Schumaker

NFSv4: Convert the NFS client idmapper to use the container user namespace

When mapping NFS identities using the NFSv4 idmapper, we want to substitute
for the uids and gids that would normally go on the wire as part of a
NFSv3 request. So we use the same mapping in the NFSv4 upcall as we
use in the NFSv3 RPC call (i.e. the mapping stored in the rpc_clnt cred).
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@hammerspace.com>
Signed-off-by: default avatarAnna Schumaker <Anna.Schumaker@Netapp.com>
parent 264d948c
...@@ -69,8 +69,16 @@ struct idmap { ...@@ -69,8 +69,16 @@ struct idmap {
struct rpc_pipe *idmap_pipe; struct rpc_pipe *idmap_pipe;
struct idmap_legacy_upcalldata *idmap_upcall_data; struct idmap_legacy_upcalldata *idmap_upcall_data;
struct mutex idmap_mutex; struct mutex idmap_mutex;
const struct cred *cred;
}; };
static struct user_namespace *idmap_userns(const struct idmap *idmap)
{
if (idmap && idmap->cred)
return idmap->cred->user_ns;
return &init_user_ns;
}
/** /**
* nfs_fattr_init_names - initialise the nfs_fattr owner_name/group_name fields * nfs_fattr_init_names - initialise the nfs_fattr owner_name/group_name fields
* @fattr: fully initialised struct nfs_fattr * @fattr: fully initialised struct nfs_fattr
...@@ -271,14 +279,15 @@ static struct key *nfs_idmap_request_key(const char *name, size_t namelen, ...@@ -271,14 +279,15 @@ static struct key *nfs_idmap_request_key(const char *name, size_t namelen,
const char *type, struct idmap *idmap) const char *type, struct idmap *idmap)
{ {
char *desc; char *desc;
struct key *rkey; struct key *rkey = ERR_PTR(-EAGAIN);
ssize_t ret; ssize_t ret;
ret = nfs_idmap_get_desc(name, namelen, type, strlen(type), &desc); ret = nfs_idmap_get_desc(name, namelen, type, strlen(type), &desc);
if (ret < 0) if (ret < 0)
return ERR_PTR(ret); return ERR_PTR(ret);
rkey = request_key(&key_type_id_resolver, desc, ""); if (!idmap->cred || idmap->cred->user_ns == &init_user_ns)
rkey = request_key(&key_type_id_resolver, desc, "");
if (IS_ERR(rkey)) { if (IS_ERR(rkey)) {
mutex_lock(&idmap->idmap_mutex); mutex_lock(&idmap->idmap_mutex);
rkey = request_key_with_auxdata(&key_type_id_resolver_legacy, rkey = request_key_with_auxdata(&key_type_id_resolver_legacy,
...@@ -452,6 +461,9 @@ nfs_idmap_new(struct nfs_client *clp) ...@@ -452,6 +461,9 @@ nfs_idmap_new(struct nfs_client *clp)
if (idmap == NULL) if (idmap == NULL)
return -ENOMEM; return -ENOMEM;
mutex_init(&idmap->idmap_mutex);
idmap->cred = get_cred(clp->cl_rpcclient->cl_cred);
rpc_init_pipe_dir_object(&idmap->idmap_pdo, rpc_init_pipe_dir_object(&idmap->idmap_pdo,
&nfs_idmap_pipe_dir_object_ops, &nfs_idmap_pipe_dir_object_ops,
idmap); idmap);
...@@ -462,7 +474,6 @@ nfs_idmap_new(struct nfs_client *clp) ...@@ -462,7 +474,6 @@ nfs_idmap_new(struct nfs_client *clp)
goto err; goto err;
} }
idmap->idmap_pipe = pipe; idmap->idmap_pipe = pipe;
mutex_init(&idmap->idmap_mutex);
error = rpc_add_pipe_dir_object(clp->cl_net, error = rpc_add_pipe_dir_object(clp->cl_net,
&clp->cl_rpcclient->cl_pipedir_objects, &clp->cl_rpcclient->cl_pipedir_objects,
...@@ -475,6 +486,7 @@ nfs_idmap_new(struct nfs_client *clp) ...@@ -475,6 +486,7 @@ nfs_idmap_new(struct nfs_client *clp)
err_destroy_pipe: err_destroy_pipe:
rpc_destroy_pipe_data(idmap->idmap_pipe); rpc_destroy_pipe_data(idmap->idmap_pipe);
err: err:
put_cred(idmap->cred);
kfree(idmap); kfree(idmap);
return error; return error;
} }
...@@ -491,6 +503,7 @@ nfs_idmap_delete(struct nfs_client *clp) ...@@ -491,6 +503,7 @@ nfs_idmap_delete(struct nfs_client *clp)
&clp->cl_rpcclient->cl_pipedir_objects, &clp->cl_rpcclient->cl_pipedir_objects,
&idmap->idmap_pdo); &idmap->idmap_pdo);
rpc_destroy_pipe_data(idmap->idmap_pipe); rpc_destroy_pipe_data(idmap->idmap_pipe);
put_cred(idmap->cred);
kfree(idmap); kfree(idmap);
} }
...@@ -735,7 +748,7 @@ int nfs_map_name_to_uid(const struct nfs_server *server, const char *name, size_ ...@@ -735,7 +748,7 @@ int nfs_map_name_to_uid(const struct nfs_server *server, const char *name, size_
if (!nfs_map_string_to_numeric(name, namelen, &id)) if (!nfs_map_string_to_numeric(name, namelen, &id))
ret = nfs_idmap_lookup_id(name, namelen, "uid", &id, idmap); ret = nfs_idmap_lookup_id(name, namelen, "uid", &id, idmap);
if (ret == 0) { if (ret == 0) {
*uid = make_kuid(&init_user_ns, id); *uid = make_kuid(idmap_userns(idmap), id);
if (!uid_valid(*uid)) if (!uid_valid(*uid))
ret = -ERANGE; ret = -ERANGE;
} }
...@@ -752,7 +765,7 @@ int nfs_map_group_to_gid(const struct nfs_server *server, const char *name, size ...@@ -752,7 +765,7 @@ int nfs_map_group_to_gid(const struct nfs_server *server, const char *name, size
if (!nfs_map_string_to_numeric(name, namelen, &id)) if (!nfs_map_string_to_numeric(name, namelen, &id))
ret = nfs_idmap_lookup_id(name, namelen, "gid", &id, idmap); ret = nfs_idmap_lookup_id(name, namelen, "gid", &id, idmap);
if (ret == 0) { if (ret == 0) {
*gid = make_kgid(&init_user_ns, id); *gid = make_kgid(idmap_userns(idmap), id);
if (!gid_valid(*gid)) if (!gid_valid(*gid))
ret = -ERANGE; ret = -ERANGE;
} }
...@@ -766,7 +779,7 @@ int nfs_map_uid_to_name(const struct nfs_server *server, kuid_t uid, char *buf, ...@@ -766,7 +779,7 @@ int nfs_map_uid_to_name(const struct nfs_server *server, kuid_t uid, char *buf,
int ret = -EINVAL; int ret = -EINVAL;
__u32 id; __u32 id;
id = from_kuid(&init_user_ns, uid); id = from_kuid_munged(idmap_userns(idmap), uid);
if (!(server->caps & NFS_CAP_UIDGID_NOMAP)) if (!(server->caps & NFS_CAP_UIDGID_NOMAP))
ret = nfs_idmap_lookup_name(id, "user", buf, buflen, idmap); ret = nfs_idmap_lookup_name(id, "user", buf, buflen, idmap);
if (ret < 0) if (ret < 0)
...@@ -780,7 +793,7 @@ int nfs_map_gid_to_group(const struct nfs_server *server, kgid_t gid, char *buf, ...@@ -780,7 +793,7 @@ int nfs_map_gid_to_group(const struct nfs_server *server, kgid_t gid, char *buf,
int ret = -EINVAL; int ret = -EINVAL;
__u32 id; __u32 id;
id = from_kgid(&init_user_ns, gid); id = from_kgid_munged(idmap_userns(idmap), gid);
if (!(server->caps & NFS_CAP_UIDGID_NOMAP)) if (!(server->caps & NFS_CAP_UIDGID_NOMAP))
ret = nfs_idmap_lookup_name(id, "group", buf, buflen, idmap); ret = nfs_idmap_lookup_name(id, "group", buf, buflen, idmap);
if (ret < 0) if (ret < 0)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment