cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

nfs4idmap.c (20443B)


      1/*
      2 * fs/nfs/idmap.c
      3 *
      4 *  UID and GID to name mapping for clients.
      5 *
      6 *  Copyright (c) 2002 The Regents of the University of Michigan.
      7 *  All rights reserved.
      8 *
      9 *  Marius Aamodt Eriksen <marius@umich.edu>
     10 *
     11 *  Redistribution and use in source and binary forms, with or without
     12 *  modification, are permitted provided that the following conditions
     13 *  are met:
     14 *
     15 *  1. Redistributions of source code must retain the above copyright
     16 *     notice, this list of conditions and the following disclaimer.
     17 *  2. Redistributions in binary form must reproduce the above copyright
     18 *     notice, this list of conditions and the following disclaimer in the
     19 *     documentation and/or other materials provided with the distribution.
     20 *  3. Neither the name of the University nor the names of its
     21 *     contributors may be used to endorse or promote products derived
     22 *     from this software without specific prior written permission.
     23 *
     24 *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
     25 *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     26 *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     27 *  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     28 *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     29 *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     30 *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
     31 *  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
     32 *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
     33 *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     34 *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     35 */
     36#include <linux/types.h>
     37#include <linux/parser.h>
     38#include <linux/fs.h>
     39#include <net/net_namespace.h>
     40#include <linux/sunrpc/rpc_pipe_fs.h>
     41#include <linux/nfs_fs.h>
     42#include <linux/nfs_fs_sb.h>
     43#include <linux/key.h>
     44#include <linux/keyctl.h>
     45#include <linux/key-type.h>
     46#include <keys/user-type.h>
     47#include <keys/request_key_auth-type.h>
     48#include <linux/module.h>
     49#include <linux/user_namespace.h>
     50
     51#include "internal.h"
     52#include "netns.h"
     53#include "nfs4idmap.h"
     54#include "nfs4trace.h"
     55
     56#define NFS_UINT_MAXLEN 11
     57
     58static const struct cred *id_resolver_cache;
     59static struct key_type key_type_id_resolver_legacy;
     60
     61struct idmap_legacy_upcalldata {
     62	struct rpc_pipe_msg pipe_msg;
     63	struct idmap_msg idmap_msg;
     64	struct key	*authkey;
     65	struct idmap *idmap;
     66};
     67
     68struct idmap {
     69	struct rpc_pipe_dir_object idmap_pdo;
     70	struct rpc_pipe		*idmap_pipe;
     71	struct idmap_legacy_upcalldata *idmap_upcall_data;
     72	struct mutex		idmap_mutex;
     73	struct user_namespace	*user_ns;
     74};
     75
     76static struct user_namespace *idmap_userns(const struct idmap *idmap)
     77{
     78	if (idmap && idmap->user_ns)
     79		return idmap->user_ns;
     80	return &init_user_ns;
     81}
     82
     83/**
     84 * nfs_fattr_init_names - initialise the nfs_fattr owner_name/group_name fields
     85 * @fattr: fully initialised struct nfs_fattr
     86 * @owner_name: owner name string cache
     87 * @group_name: group name string cache
     88 */
     89void nfs_fattr_init_names(struct nfs_fattr *fattr,
     90		struct nfs4_string *owner_name,
     91		struct nfs4_string *group_name)
     92{
     93	fattr->owner_name = owner_name;
     94	fattr->group_name = group_name;
     95}
     96
     97static void nfs_fattr_free_owner_name(struct nfs_fattr *fattr)
     98{
     99	fattr->valid &= ~NFS_ATTR_FATTR_OWNER_NAME;
    100	kfree(fattr->owner_name->data);
    101}
    102
    103static void nfs_fattr_free_group_name(struct nfs_fattr *fattr)
    104{
    105	fattr->valid &= ~NFS_ATTR_FATTR_GROUP_NAME;
    106	kfree(fattr->group_name->data);
    107}
    108
    109static bool nfs_fattr_map_owner_name(struct nfs_server *server, struct nfs_fattr *fattr)
    110{
    111	struct nfs4_string *owner = fattr->owner_name;
    112	kuid_t uid;
    113
    114	if (!(fattr->valid & NFS_ATTR_FATTR_OWNER_NAME))
    115		return false;
    116	if (nfs_map_name_to_uid(server, owner->data, owner->len, &uid) == 0) {
    117		fattr->uid = uid;
    118		fattr->valid |= NFS_ATTR_FATTR_OWNER;
    119	}
    120	return true;
    121}
    122
    123static bool nfs_fattr_map_group_name(struct nfs_server *server, struct nfs_fattr *fattr)
    124{
    125	struct nfs4_string *group = fattr->group_name;
    126	kgid_t gid;
    127
    128	if (!(fattr->valid & NFS_ATTR_FATTR_GROUP_NAME))
    129		return false;
    130	if (nfs_map_group_to_gid(server, group->data, group->len, &gid) == 0) {
    131		fattr->gid = gid;
    132		fattr->valid |= NFS_ATTR_FATTR_GROUP;
    133	}
    134	return true;
    135}
    136
    137/**
    138 * nfs_fattr_free_names - free up the NFSv4 owner and group strings
    139 * @fattr: a fully initialised nfs_fattr structure
    140 */
    141void nfs_fattr_free_names(struct nfs_fattr *fattr)
    142{
    143	if (fattr->valid & NFS_ATTR_FATTR_OWNER_NAME)
    144		nfs_fattr_free_owner_name(fattr);
    145	if (fattr->valid & NFS_ATTR_FATTR_GROUP_NAME)
    146		nfs_fattr_free_group_name(fattr);
    147}
    148
    149/**
    150 * nfs_fattr_map_and_free_names - map owner/group strings into uid/gid and free
    151 * @server: pointer to the filesystem nfs_server structure
    152 * @fattr: a fully initialised nfs_fattr structure
    153 *
    154 * This helper maps the cached NFSv4 owner/group strings in fattr into
    155 * their numeric uid/gid equivalents, and then frees the cached strings.
    156 */
    157void nfs_fattr_map_and_free_names(struct nfs_server *server, struct nfs_fattr *fattr)
    158{
    159	if (nfs_fattr_map_owner_name(server, fattr))
    160		nfs_fattr_free_owner_name(fattr);
    161	if (nfs_fattr_map_group_name(server, fattr))
    162		nfs_fattr_free_group_name(fattr);
    163}
    164
    165int nfs_map_string_to_numeric(const char *name, size_t namelen, __u32 *res)
    166{
    167	unsigned long val;
    168	char buf[16];
    169
    170	if (memchr(name, '@', namelen) != NULL || namelen >= sizeof(buf))
    171		return 0;
    172	memcpy(buf, name, namelen);
    173	buf[namelen] = '\0';
    174	if (kstrtoul(buf, 0, &val) != 0)
    175		return 0;
    176	*res = val;
    177	return 1;
    178}
    179EXPORT_SYMBOL_GPL(nfs_map_string_to_numeric);
    180
    181static int nfs_map_numeric_to_string(__u32 id, char *buf, size_t buflen)
    182{
    183	return snprintf(buf, buflen, "%u", id);
    184}
    185
    186static struct key_type key_type_id_resolver = {
    187	.name		= "id_resolver",
    188	.preparse	= user_preparse,
    189	.free_preparse	= user_free_preparse,
    190	.instantiate	= generic_key_instantiate,
    191	.revoke		= user_revoke,
    192	.destroy	= user_destroy,
    193	.describe	= user_describe,
    194	.read		= user_read,
    195};
    196
    197int nfs_idmap_init(void)
    198{
    199	struct cred *cred;
    200	struct key *keyring;
    201	int ret = 0;
    202
    203	printk(KERN_NOTICE "NFS: Registering the %s key type\n",
    204		key_type_id_resolver.name);
    205
    206	cred = prepare_kernel_cred(NULL);
    207	if (!cred)
    208		return -ENOMEM;
    209
    210	keyring = keyring_alloc(".id_resolver",
    211				GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred,
    212				(KEY_POS_ALL & ~KEY_POS_SETATTR) |
    213				KEY_USR_VIEW | KEY_USR_READ,
    214				KEY_ALLOC_NOT_IN_QUOTA, NULL, NULL);
    215	if (IS_ERR(keyring)) {
    216		ret = PTR_ERR(keyring);
    217		goto failed_put_cred;
    218	}
    219
    220	ret = register_key_type(&key_type_id_resolver);
    221	if (ret < 0)
    222		goto failed_put_key;
    223
    224	ret = register_key_type(&key_type_id_resolver_legacy);
    225	if (ret < 0)
    226		goto failed_reg_legacy;
    227
    228	set_bit(KEY_FLAG_ROOT_CAN_CLEAR, &keyring->flags);
    229	cred->thread_keyring = keyring;
    230	cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING;
    231	id_resolver_cache = cred;
    232	return 0;
    233
    234failed_reg_legacy:
    235	unregister_key_type(&key_type_id_resolver);
    236failed_put_key:
    237	key_put(keyring);
    238failed_put_cred:
    239	put_cred(cred);
    240	return ret;
    241}
    242
    243void nfs_idmap_quit(void)
    244{
    245	key_revoke(id_resolver_cache->thread_keyring);
    246	unregister_key_type(&key_type_id_resolver);
    247	unregister_key_type(&key_type_id_resolver_legacy);
    248	put_cred(id_resolver_cache);
    249}
    250
    251/*
    252 * Assemble the description to pass to request_key()
    253 * This function will allocate a new string and update dest to point
    254 * at it.  The caller is responsible for freeing dest.
    255 *
    256 * On error 0 is returned.  Otherwise, the length of dest is returned.
    257 */
    258static ssize_t nfs_idmap_get_desc(const char *name, size_t namelen,
    259				const char *type, size_t typelen, char **desc)
    260{
    261	char *cp;
    262	size_t desclen = typelen + namelen + 2;
    263
    264	*desc = kmalloc(desclen, GFP_KERNEL);
    265	if (!*desc)
    266		return -ENOMEM;
    267
    268	cp = *desc;
    269	memcpy(cp, type, typelen);
    270	cp += typelen;
    271	*cp++ = ':';
    272
    273	memcpy(cp, name, namelen);
    274	cp += namelen;
    275	*cp = '\0';
    276	return desclen;
    277}
    278
    279static struct key *nfs_idmap_request_key(const char *name, size_t namelen,
    280					 const char *type, struct idmap *idmap)
    281{
    282	char *desc;
    283	struct key *rkey = ERR_PTR(-EAGAIN);
    284	ssize_t ret;
    285
    286	ret = nfs_idmap_get_desc(name, namelen, type, strlen(type), &desc);
    287	if (ret < 0)
    288		return ERR_PTR(ret);
    289
    290	if (!idmap->user_ns || idmap->user_ns == &init_user_ns)
    291		rkey = request_key(&key_type_id_resolver, desc, "");
    292	if (IS_ERR(rkey)) {
    293		mutex_lock(&idmap->idmap_mutex);
    294		rkey = request_key_with_auxdata(&key_type_id_resolver_legacy,
    295						desc, NULL, "", 0, idmap);
    296		mutex_unlock(&idmap->idmap_mutex);
    297	}
    298	if (!IS_ERR(rkey))
    299		set_bit(KEY_FLAG_ROOT_CAN_INVAL, &rkey->flags);
    300
    301	kfree(desc);
    302	return rkey;
    303}
    304
    305static ssize_t nfs_idmap_get_key(const char *name, size_t namelen,
    306				 const char *type, void *data,
    307				 size_t data_size, struct idmap *idmap)
    308{
    309	const struct cred *saved_cred;
    310	struct key *rkey;
    311	const struct user_key_payload *payload;
    312	ssize_t ret;
    313
    314	saved_cred = override_creds(id_resolver_cache);
    315	rkey = nfs_idmap_request_key(name, namelen, type, idmap);
    316	revert_creds(saved_cred);
    317
    318	if (IS_ERR(rkey)) {
    319		ret = PTR_ERR(rkey);
    320		goto out;
    321	}
    322
    323	rcu_read_lock();
    324	rkey->perm |= KEY_USR_VIEW;
    325
    326	ret = key_validate(rkey);
    327	if (ret < 0)
    328		goto out_up;
    329
    330	payload = user_key_payload_rcu(rkey);
    331	if (IS_ERR_OR_NULL(payload)) {
    332		ret = PTR_ERR(payload);
    333		goto out_up;
    334	}
    335
    336	ret = payload->datalen;
    337	if (ret > 0 && ret <= data_size)
    338		memcpy(data, payload->data, ret);
    339	else
    340		ret = -EINVAL;
    341
    342out_up:
    343	rcu_read_unlock();
    344	key_put(rkey);
    345out:
    346	return ret;
    347}
    348
    349/* ID -> Name */
    350static ssize_t nfs_idmap_lookup_name(__u32 id, const char *type, char *buf,
    351				     size_t buflen, struct idmap *idmap)
    352{
    353	char id_str[NFS_UINT_MAXLEN];
    354	int id_len;
    355	ssize_t ret;
    356
    357	id_len = nfs_map_numeric_to_string(id, id_str, sizeof(id_str));
    358	ret = nfs_idmap_get_key(id_str, id_len, type, buf, buflen, idmap);
    359	if (ret < 0)
    360		return -EINVAL;
    361	return ret;
    362}
    363
    364/* Name -> ID */
    365static int nfs_idmap_lookup_id(const char *name, size_t namelen, const char *type,
    366			       __u32 *id, struct idmap *idmap)
    367{
    368	char id_str[NFS_UINT_MAXLEN];
    369	long id_long;
    370	ssize_t data_size;
    371	int ret = 0;
    372
    373	data_size = nfs_idmap_get_key(name, namelen, type, id_str, NFS_UINT_MAXLEN, idmap);
    374	if (data_size <= 0) {
    375		ret = -EINVAL;
    376	} else {
    377		ret = kstrtol(id_str, 10, &id_long);
    378		if (!ret)
    379			*id = (__u32)id_long;
    380	}
    381	return ret;
    382}
    383
    384/* idmap classic begins here */
    385
    386enum {
    387	Opt_find_uid, Opt_find_gid, Opt_find_user, Opt_find_group, Opt_find_err
    388};
    389
    390static const match_table_t nfs_idmap_tokens = {
    391	{ Opt_find_uid, "uid:%s" },
    392	{ Opt_find_gid, "gid:%s" },
    393	{ Opt_find_user, "user:%s" },
    394	{ Opt_find_group, "group:%s" },
    395	{ Opt_find_err, NULL }
    396};
    397
    398static int nfs_idmap_legacy_upcall(struct key *, void *);
    399static ssize_t idmap_pipe_downcall(struct file *, const char __user *,
    400				   size_t);
    401static void idmap_release_pipe(struct inode *);
    402static void idmap_pipe_destroy_msg(struct rpc_pipe_msg *);
    403
    404static const struct rpc_pipe_ops idmap_upcall_ops = {
    405	.upcall		= rpc_pipe_generic_upcall,
    406	.downcall	= idmap_pipe_downcall,
    407	.release_pipe	= idmap_release_pipe,
    408	.destroy_msg	= idmap_pipe_destroy_msg,
    409};
    410
    411static struct key_type key_type_id_resolver_legacy = {
    412	.name		= "id_legacy",
    413	.preparse	= user_preparse,
    414	.free_preparse	= user_free_preparse,
    415	.instantiate	= generic_key_instantiate,
    416	.revoke		= user_revoke,
    417	.destroy	= user_destroy,
    418	.describe	= user_describe,
    419	.read		= user_read,
    420	.request_key	= nfs_idmap_legacy_upcall,
    421};
    422
    423static void nfs_idmap_pipe_destroy(struct dentry *dir,
    424		struct rpc_pipe_dir_object *pdo)
    425{
    426	struct idmap *idmap = pdo->pdo_data;
    427	struct rpc_pipe *pipe = idmap->idmap_pipe;
    428
    429	if (pipe->dentry) {
    430		rpc_unlink(pipe->dentry);
    431		pipe->dentry = NULL;
    432	}
    433}
    434
    435static int nfs_idmap_pipe_create(struct dentry *dir,
    436		struct rpc_pipe_dir_object *pdo)
    437{
    438	struct idmap *idmap = pdo->pdo_data;
    439	struct rpc_pipe *pipe = idmap->idmap_pipe;
    440	struct dentry *dentry;
    441
    442	dentry = rpc_mkpipe_dentry(dir, "idmap", idmap, pipe);
    443	if (IS_ERR(dentry))
    444		return PTR_ERR(dentry);
    445	pipe->dentry = dentry;
    446	return 0;
    447}
    448
    449static const struct rpc_pipe_dir_object_ops nfs_idmap_pipe_dir_object_ops = {
    450	.create = nfs_idmap_pipe_create,
    451	.destroy = nfs_idmap_pipe_destroy,
    452};
    453
    454int
    455nfs_idmap_new(struct nfs_client *clp)
    456{
    457	struct idmap *idmap;
    458	struct rpc_pipe *pipe;
    459	int error;
    460
    461	idmap = kzalloc(sizeof(*idmap), GFP_KERNEL);
    462	if (idmap == NULL)
    463		return -ENOMEM;
    464
    465	mutex_init(&idmap->idmap_mutex);
    466	idmap->user_ns = get_user_ns(clp->cl_rpcclient->cl_cred->user_ns);
    467
    468	rpc_init_pipe_dir_object(&idmap->idmap_pdo,
    469			&nfs_idmap_pipe_dir_object_ops,
    470			idmap);
    471
    472	pipe = rpc_mkpipe_data(&idmap_upcall_ops, 0);
    473	if (IS_ERR(pipe)) {
    474		error = PTR_ERR(pipe);
    475		goto err;
    476	}
    477	idmap->idmap_pipe = pipe;
    478
    479	error = rpc_add_pipe_dir_object(clp->cl_net,
    480			&clp->cl_rpcclient->cl_pipedir_objects,
    481			&idmap->idmap_pdo);
    482	if (error)
    483		goto err_destroy_pipe;
    484
    485	clp->cl_idmap = idmap;
    486	return 0;
    487err_destroy_pipe:
    488	rpc_destroy_pipe_data(idmap->idmap_pipe);
    489err:
    490	put_user_ns(idmap->user_ns);
    491	kfree(idmap);
    492	return error;
    493}
    494
    495void
    496nfs_idmap_delete(struct nfs_client *clp)
    497{
    498	struct idmap *idmap = clp->cl_idmap;
    499
    500	if (!idmap)
    501		return;
    502	clp->cl_idmap = NULL;
    503	rpc_remove_pipe_dir_object(clp->cl_net,
    504			&clp->cl_rpcclient->cl_pipedir_objects,
    505			&idmap->idmap_pdo);
    506	rpc_destroy_pipe_data(idmap->idmap_pipe);
    507	put_user_ns(idmap->user_ns);
    508	kfree(idmap);
    509}
    510
    511static int nfs_idmap_prepare_message(char *desc, struct idmap *idmap,
    512				     struct idmap_msg *im,
    513				     struct rpc_pipe_msg *msg)
    514{
    515	substring_t substr;
    516	int token, ret;
    517
    518	im->im_type = IDMAP_TYPE_GROUP;
    519	token = match_token(desc, nfs_idmap_tokens, &substr);
    520
    521	switch (token) {
    522	case Opt_find_uid:
    523		im->im_type = IDMAP_TYPE_USER;
    524		fallthrough;
    525	case Opt_find_gid:
    526		im->im_conv = IDMAP_CONV_NAMETOID;
    527		ret = match_strlcpy(im->im_name, &substr, IDMAP_NAMESZ);
    528		break;
    529
    530	case Opt_find_user:
    531		im->im_type = IDMAP_TYPE_USER;
    532		fallthrough;
    533	case Opt_find_group:
    534		im->im_conv = IDMAP_CONV_IDTONAME;
    535		ret = match_int(&substr, &im->im_id);
    536		if (ret)
    537			goto out;
    538		break;
    539
    540	default:
    541		ret = -EINVAL;
    542		goto out;
    543	}
    544
    545	msg->data = im;
    546	msg->len  = sizeof(struct idmap_msg);
    547
    548out:
    549	return ret;
    550}
    551
    552static bool
    553nfs_idmap_prepare_pipe_upcall(struct idmap *idmap,
    554		struct idmap_legacy_upcalldata *data)
    555{
    556	if (idmap->idmap_upcall_data != NULL) {
    557		WARN_ON_ONCE(1);
    558		return false;
    559	}
    560	idmap->idmap_upcall_data = data;
    561	return true;
    562}
    563
    564static void
    565nfs_idmap_complete_pipe_upcall_locked(struct idmap *idmap, int ret)
    566{
    567	struct key *authkey = idmap->idmap_upcall_data->authkey;
    568
    569	kfree(idmap->idmap_upcall_data);
    570	idmap->idmap_upcall_data = NULL;
    571	complete_request_key(authkey, ret);
    572	key_put(authkey);
    573}
    574
    575static void
    576nfs_idmap_abort_pipe_upcall(struct idmap *idmap, int ret)
    577{
    578	if (idmap->idmap_upcall_data != NULL)
    579		nfs_idmap_complete_pipe_upcall_locked(idmap, ret);
    580}
    581
    582static int nfs_idmap_legacy_upcall(struct key *authkey, void *aux)
    583{
    584	struct idmap_legacy_upcalldata *data;
    585	struct request_key_auth *rka = get_request_key_auth(authkey);
    586	struct rpc_pipe_msg *msg;
    587	struct idmap_msg *im;
    588	struct idmap *idmap = (struct idmap *)aux;
    589	struct key *key = rka->target_key;
    590	int ret = -ENOKEY;
    591
    592	if (!aux)
    593		goto out1;
    594
    595	/* msg and im are freed in idmap_pipe_destroy_msg */
    596	ret = -ENOMEM;
    597	data = kzalloc(sizeof(*data), GFP_KERNEL);
    598	if (!data)
    599		goto out1;
    600
    601	msg = &data->pipe_msg;
    602	im = &data->idmap_msg;
    603	data->idmap = idmap;
    604	data->authkey = key_get(authkey);
    605
    606	ret = nfs_idmap_prepare_message(key->description, idmap, im, msg);
    607	if (ret < 0)
    608		goto out2;
    609
    610	ret = -EAGAIN;
    611	if (!nfs_idmap_prepare_pipe_upcall(idmap, data))
    612		goto out2;
    613
    614	ret = rpc_queue_upcall(idmap->idmap_pipe, msg);
    615	if (ret < 0)
    616		nfs_idmap_abort_pipe_upcall(idmap, ret);
    617
    618	return ret;
    619out2:
    620	kfree(data);
    621out1:
    622	complete_request_key(authkey, ret);
    623	return ret;
    624}
    625
    626static int nfs_idmap_instantiate(struct key *key, struct key *authkey, char *data, size_t datalen)
    627{
    628	return key_instantiate_and_link(key, data, datalen,
    629					id_resolver_cache->thread_keyring,
    630					authkey);
    631}
    632
    633static int nfs_idmap_read_and_verify_message(struct idmap_msg *im,
    634		struct idmap_msg *upcall,
    635		struct key *key, struct key *authkey)
    636{
    637	char id_str[NFS_UINT_MAXLEN];
    638	size_t len;
    639	int ret = -ENOKEY;
    640
    641	/* ret = -ENOKEY */
    642	if (upcall->im_type != im->im_type || upcall->im_conv != im->im_conv)
    643		goto out;
    644	switch (im->im_conv) {
    645	case IDMAP_CONV_NAMETOID:
    646		if (strcmp(upcall->im_name, im->im_name) != 0)
    647			break;
    648		/* Note: here we store the NUL terminator too */
    649		len = 1 + nfs_map_numeric_to_string(im->im_id, id_str,
    650						    sizeof(id_str));
    651		ret = nfs_idmap_instantiate(key, authkey, id_str, len);
    652		break;
    653	case IDMAP_CONV_IDTONAME:
    654		if (upcall->im_id != im->im_id)
    655			break;
    656		len = strlen(im->im_name);
    657		ret = nfs_idmap_instantiate(key, authkey, im->im_name, len);
    658		break;
    659	default:
    660		ret = -EINVAL;
    661	}
    662out:
    663	return ret;
    664}
    665
    666static ssize_t
    667idmap_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
    668{
    669	struct request_key_auth *rka;
    670	struct rpc_inode *rpci = RPC_I(file_inode(filp));
    671	struct idmap *idmap = (struct idmap *)rpci->private;
    672	struct key *authkey;
    673	struct idmap_msg im;
    674	size_t namelen_in;
    675	int ret = -ENOKEY;
    676
    677	/* If instantiation is successful, anyone waiting for key construction
    678	 * will have been woken up and someone else may now have used
    679	 * idmap_key_cons - so after this point we may no longer touch it.
    680	 */
    681	if (idmap->idmap_upcall_data == NULL)
    682		goto out_noupcall;
    683
    684	authkey = idmap->idmap_upcall_data->authkey;
    685	rka = get_request_key_auth(authkey);
    686
    687	if (mlen != sizeof(im)) {
    688		ret = -ENOSPC;
    689		goto out;
    690	}
    691
    692	if (copy_from_user(&im, src, mlen) != 0) {
    693		ret = -EFAULT;
    694		goto out;
    695	}
    696
    697	if (!(im.im_status & IDMAP_STATUS_SUCCESS)) {
    698		ret = -ENOKEY;
    699		goto out;
    700	}
    701
    702	namelen_in = strnlen(im.im_name, IDMAP_NAMESZ);
    703	if (namelen_in == 0 || namelen_in == IDMAP_NAMESZ) {
    704		ret = -EINVAL;
    705		goto out;
    706}
    707
    708	ret = nfs_idmap_read_and_verify_message(&im,
    709			&idmap->idmap_upcall_data->idmap_msg,
    710			rka->target_key, authkey);
    711	if (ret >= 0) {
    712		key_set_timeout(rka->target_key, nfs_idmap_cache_timeout);
    713		ret = mlen;
    714	}
    715
    716out:
    717	nfs_idmap_complete_pipe_upcall_locked(idmap, ret);
    718out_noupcall:
    719	return ret;
    720}
    721
    722static void
    723idmap_pipe_destroy_msg(struct rpc_pipe_msg *msg)
    724{
    725	struct idmap_legacy_upcalldata *data = container_of(msg,
    726			struct idmap_legacy_upcalldata,
    727			pipe_msg);
    728	struct idmap *idmap = data->idmap;
    729
    730	if (msg->errno)
    731		nfs_idmap_abort_pipe_upcall(idmap, msg->errno);
    732}
    733
    734static void
    735idmap_release_pipe(struct inode *inode)
    736{
    737	struct rpc_inode *rpci = RPC_I(inode);
    738	struct idmap *idmap = (struct idmap *)rpci->private;
    739
    740	nfs_idmap_abort_pipe_upcall(idmap, -EPIPE);
    741}
    742
    743int nfs_map_name_to_uid(const struct nfs_server *server, const char *name, size_t namelen, kuid_t *uid)
    744{
    745	struct idmap *idmap = server->nfs_client->cl_idmap;
    746	__u32 id = -1;
    747	int ret = 0;
    748
    749	if (!nfs_map_string_to_numeric(name, namelen, &id))
    750		ret = nfs_idmap_lookup_id(name, namelen, "uid", &id, idmap);
    751	if (ret == 0) {
    752		*uid = make_kuid(idmap_userns(idmap), id);
    753		if (!uid_valid(*uid))
    754			ret = -ERANGE;
    755	}
    756	trace_nfs4_map_name_to_uid(name, namelen, id, ret);
    757	return ret;
    758}
    759
    760int nfs_map_group_to_gid(const struct nfs_server *server, const char *name, size_t namelen, kgid_t *gid)
    761{
    762	struct idmap *idmap = server->nfs_client->cl_idmap;
    763	__u32 id = -1;
    764	int ret = 0;
    765
    766	if (!nfs_map_string_to_numeric(name, namelen, &id))
    767		ret = nfs_idmap_lookup_id(name, namelen, "gid", &id, idmap);
    768	if (ret == 0) {
    769		*gid = make_kgid(idmap_userns(idmap), id);
    770		if (!gid_valid(*gid))
    771			ret = -ERANGE;
    772	}
    773	trace_nfs4_map_group_to_gid(name, namelen, id, ret);
    774	return ret;
    775}
    776
    777int nfs_map_uid_to_name(const struct nfs_server *server, kuid_t uid, char *buf, size_t buflen)
    778{
    779	struct idmap *idmap = server->nfs_client->cl_idmap;
    780	int ret = -EINVAL;
    781	__u32 id;
    782
    783	id = from_kuid_munged(idmap_userns(idmap), uid);
    784	if (!(server->caps & NFS_CAP_UIDGID_NOMAP))
    785		ret = nfs_idmap_lookup_name(id, "user", buf, buflen, idmap);
    786	if (ret < 0)
    787		ret = nfs_map_numeric_to_string(id, buf, buflen);
    788	trace_nfs4_map_uid_to_name(buf, ret, id, ret);
    789	return ret;
    790}
    791int nfs_map_gid_to_group(const struct nfs_server *server, kgid_t gid, char *buf, size_t buflen)
    792{
    793	struct idmap *idmap = server->nfs_client->cl_idmap;
    794	int ret = -EINVAL;
    795	__u32 id;
    796
    797	id = from_kgid_munged(idmap_userns(idmap), gid);
    798	if (!(server->caps & NFS_CAP_UIDGID_NOMAP))
    799		ret = nfs_idmap_lookup_name(id, "group", buf, buflen, idmap);
    800	if (ret < 0)
    801		ret = nfs_map_numeric_to_string(id, buf, buflen);
    802	trace_nfs4_map_gid_to_group(buf, ret, id, ret);
    803	return ret;
    804}