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