LCOV - code coverage report
Current view: top level - fs/nfs - nfs4idmap.c (source / functions) Hit Total Coverage
Test: gcov_data_raspi2_real_modules_combined.info Lines: 16 278 5.8 %
Date: 2020-09-30 20:25:40 Functions: 1 29 3.4 %
Branches: 4 154 2.6 %

           Branch data     Line data    Source code
       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                 :            : 
      57                 :            : static const struct cred *id_resolver_cache;
      58                 :            : static struct key_type key_type_id_resolver_legacy;
      59                 :            : 
      60                 :            : struct 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                 :            : 
      67                 :            : struct 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                 :            : 
      75                 :            : static struct user_namespace *idmap_userns(const struct idmap *idmap)
      76                 :            : {
      77   [ #  #  #  #  :          0 :         if (idmap && idmap->cred)
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
      78                 :          0 :                 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                 :            :  */
      88                 :          0 : void nfs_fattr_init_names(struct nfs_fattr *fattr,
      89                 :            :                 struct nfs4_string *owner_name,
      90                 :            :                 struct nfs4_string *group_name)
      91                 :            : {
      92                 :          0 :         fattr->owner_name = owner_name;
      93                 :          0 :         fattr->group_name = group_name;
      94                 :          0 : }
      95                 :            : 
      96                 :            : static void nfs_fattr_free_owner_name(struct nfs_fattr *fattr)
      97                 :            : {
      98                 :          0 :         fattr->valid &= ~NFS_ATTR_FATTR_OWNER_NAME;
      99                 :          0 :         kfree(fattr->owner_name->data);
     100                 :            : }
     101                 :            : 
     102                 :            : static void nfs_fattr_free_group_name(struct nfs_fattr *fattr)
     103                 :            : {
     104                 :          0 :         fattr->valid &= ~NFS_ATTR_FATTR_GROUP_NAME;
     105                 :          0 :         kfree(fattr->group_name->data);
     106                 :            : }
     107                 :            : 
     108                 :          0 : static bool nfs_fattr_map_owner_name(struct nfs_server *server, struct nfs_fattr *fattr)
     109                 :            : {
     110                 :          0 :         struct nfs4_string *owner = fattr->owner_name;
     111                 :            :         kuid_t uid;
     112                 :            : 
     113         [ #  # ]:          0 :         if (!(fattr->valid & NFS_ATTR_FATTR_OWNER_NAME))
     114                 :            :                 return false;
     115         [ #  # ]:          0 :         if (nfs_map_name_to_uid(server, owner->data, owner->len, &uid) == 0) {
     116                 :          0 :                 fattr->uid = uid;
     117                 :          0 :                 fattr->valid |= NFS_ATTR_FATTR_OWNER;
     118                 :            :         }
     119                 :            :         return true;
     120                 :            : }
     121                 :            : 
     122                 :          0 : static bool nfs_fattr_map_group_name(struct nfs_server *server, struct nfs_fattr *fattr)
     123                 :            : {
     124                 :          0 :         struct nfs4_string *group = fattr->group_name;
     125                 :            :         kgid_t gid;
     126                 :            : 
     127         [ #  # ]:          0 :         if (!(fattr->valid & NFS_ATTR_FATTR_GROUP_NAME))
     128                 :            :                 return false;
     129         [ #  # ]:          0 :         if (nfs_map_group_to_gid(server, group->data, group->len, &gid) == 0) {
     130                 :          0 :                 fattr->gid = gid;
     131                 :          0 :                 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                 :            :  */
     140                 :          0 : void nfs_fattr_free_names(struct nfs_fattr *fattr)
     141                 :            : {
     142         [ #  # ]:          0 :         if (fattr->valid & NFS_ATTR_FATTR_OWNER_NAME)
     143                 :            :                 nfs_fattr_free_owner_name(fattr);
     144         [ #  # ]:          0 :         if (fattr->valid & NFS_ATTR_FATTR_GROUP_NAME)
     145                 :            :                 nfs_fattr_free_group_name(fattr);
     146                 :          0 : }
     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                 :            :  */
     156                 :          0 : void nfs_fattr_map_and_free_names(struct nfs_server *server, struct nfs_fattr *fattr)
     157                 :            : {
     158         [ #  # ]:          0 :         if (nfs_fattr_map_owner_name(server, fattr))
     159                 :            :                 nfs_fattr_free_owner_name(fattr);
     160         [ #  # ]:          0 :         if (nfs_fattr_map_group_name(server, fattr))
     161                 :            :                 nfs_fattr_free_group_name(fattr);
     162                 :          0 : }
     163                 :            : 
     164                 :          0 : int nfs_map_string_to_numeric(const char *name, size_t namelen, __u32 *res)
     165                 :            : {
     166                 :            :         unsigned long val;
     167                 :            :         char buf[16];
     168                 :            : 
     169   [ #  #  #  # ]:          0 :         if (memchr(name, '@', namelen) != NULL || namelen >= sizeof(buf))
     170                 :            :                 return 0;
     171                 :          0 :         memcpy(buf, name, namelen);
     172                 :          0 :         buf[namelen] = '\0';
     173         [ #  # ]:          0 :         if (kstrtoul(buf, 0, &val) != 0)
     174                 :            :                 return 0;
     175                 :          0 :         *res = val;
     176                 :          0 :         return 1;
     177                 :            : }
     178                 :            : EXPORT_SYMBOL_GPL(nfs_map_string_to_numeric);
     179                 :            : 
     180                 :            : static int nfs_map_numeric_to_string(__u32 id, char *buf, size_t buflen)
     181                 :            : {
     182                 :          0 :         return snprintf(buf, buflen, "%u", id);
     183                 :            : }
     184                 :            : 
     185                 :            : static 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                 :            : 
     196                 :        207 : int nfs_idmap_init(void)
     197                 :            : {
     198                 :            :         struct cred *cred;
     199                 :            :         struct key *keyring;
     200                 :            :         int ret = 0;
     201                 :            : 
     202                 :        207 :         printk(KERN_NOTICE "NFS: Registering the %s key type\n",
     203                 :            :                 key_type_id_resolver.name);
     204                 :            : 
     205                 :        207 :         cred = prepare_kernel_cred(NULL);
     206         [ +  - ]:        207 :         if (!cred)
     207                 :            :                 return -ENOMEM;
     208                 :            : 
     209                 :        207 :         keyring = keyring_alloc(".id_resolver",
     210                 :        207 :                                 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         [ -  + ]:        207 :         if (IS_ERR(keyring)) {
     215                 :            :                 ret = PTR_ERR(keyring);
     216                 :          0 :                 goto failed_put_cred;
     217                 :            :         }
     218                 :            : 
     219                 :        207 :         ret = register_key_type(&key_type_id_resolver);
     220         [ +  - ]:        207 :         if (ret < 0)
     221                 :            :                 goto failed_put_key;
     222                 :            : 
     223                 :        207 :         ret = register_key_type(&key_type_id_resolver_legacy);
     224         [ +  - ]:        207 :         if (ret < 0)
     225                 :            :                 goto failed_reg_legacy;
     226                 :            : 
     227                 :        207 :         set_bit(KEY_FLAG_ROOT_CAN_CLEAR, &keyring->flags);
     228                 :        207 :         cred->thread_keyring = keyring;
     229                 :        207 :         cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING;
     230                 :        207 :         id_resolver_cache = cred;
     231                 :        207 :         return 0;
     232                 :            : 
     233                 :            : failed_reg_legacy:
     234                 :          0 :         unregister_key_type(&key_type_id_resolver);
     235                 :            : failed_put_key:
     236                 :          0 :         key_put(keyring);
     237                 :            : failed_put_cred:
     238                 :          0 :         put_cred(cred);
     239                 :          0 :         return ret;
     240                 :            : }
     241                 :            : 
     242                 :          0 : void nfs_idmap_quit(void)
     243                 :            : {
     244                 :          0 :         key_revoke(id_resolver_cache->thread_keyring);
     245                 :          0 :         unregister_key_type(&key_type_id_resolver);
     246                 :          0 :         unregister_key_type(&key_type_id_resolver_legacy);
     247                 :          0 :         put_cred(id_resolver_cache);
     248                 :          0 : }
     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                 :            :  */
     257                 :          0 : static 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                 :          0 :         size_t desclen = typelen + namelen + 2;
     262                 :            : 
     263                 :          0 :         *desc = kmalloc(desclen, GFP_KERNEL);
     264         [ #  # ]:          0 :         if (!*desc)
     265                 :            :                 return -ENOMEM;
     266                 :            : 
     267                 :            :         cp = *desc;
     268                 :          0 :         memcpy(cp, type, typelen);
     269                 :          0 :         cp += typelen;
     270                 :          0 :         *cp++ = ':';
     271                 :            : 
     272                 :          0 :         memcpy(cp, name, namelen);
     273                 :          0 :         cp += namelen;
     274                 :          0 :         *cp = '\0';
     275                 :          0 :         return desclen;
     276                 :            : }
     277                 :            : 
     278                 :          0 : static 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                 :          0 :         ret = nfs_idmap_get_desc(name, namelen, type, strlen(type), &desc);
     286         [ #  # ]:          0 :         if (ret < 0)
     287                 :          0 :                 return ERR_PTR(ret);
     288                 :            : 
     289   [ #  #  #  # ]:          0 :         if (!idmap->cred || idmap->cred->user_ns == &init_user_ns)
     290                 :          0 :                 rkey = request_key(&key_type_id_resolver, desc, "");
     291         [ #  # ]:          0 :         if (IS_ERR(rkey)) {
     292                 :          0 :                 mutex_lock(&idmap->idmap_mutex);
     293                 :          0 :                 rkey = request_key_with_auxdata(&key_type_id_resolver_legacy,
     294                 :            :                                                 desc, NULL, "", 0, idmap);
     295                 :          0 :                 mutex_unlock(&idmap->idmap_mutex);
     296                 :            :         }
     297         [ #  # ]:          0 :         if (!IS_ERR(rkey))
     298                 :          0 :                 set_bit(KEY_FLAG_ROOT_CAN_INVAL, &rkey->flags);
     299                 :            : 
     300                 :          0 :         kfree(desc);
     301                 :          0 :         return rkey;
     302                 :            : }
     303                 :            : 
     304                 :          0 : static 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                 :          0 :         saved_cred = override_creds(id_resolver_cache);
     314                 :          0 :         rkey = nfs_idmap_request_key(name, namelen, type, idmap);
     315                 :          0 :         revert_creds(saved_cred);
     316                 :            : 
     317         [ #  # ]:          0 :         if (IS_ERR(rkey)) {
     318                 :            :                 ret = PTR_ERR(rkey);
     319                 :          0 :                 goto out;
     320                 :            :         }
     321                 :            : 
     322                 :            :         rcu_read_lock();
     323                 :          0 :         rkey->perm |= KEY_USR_VIEW;
     324                 :            : 
     325                 :          0 :         ret = key_validate(rkey);
     326         [ #  # ]:          0 :         if (ret < 0)
     327                 :            :                 goto out_up;
     328                 :            : 
     329                 :            :         payload = user_key_payload_rcu(rkey);
     330         [ #  # ]:          0 :         if (IS_ERR_OR_NULL(payload)) {
     331                 :            :                 ret = PTR_ERR(payload);
     332                 :          0 :                 goto out_up;
     333                 :            :         }
     334                 :            : 
     335                 :          0 :         ret = payload->datalen;
     336         [ #  # ]:          0 :         if (ret > 0 && ret <= data_size)
     337                 :          0 :                 memcpy(data, payload->data, ret);
     338                 :            :         else
     339                 :            :                 ret = -EINVAL;
     340                 :            : 
     341                 :            : out_up:
     342                 :            :         rcu_read_unlock();
     343                 :          0 :         key_put(rkey);
     344                 :            : out:
     345                 :          0 :         return ret;
     346                 :            : }
     347                 :            : 
     348                 :            : /* ID -> Name */
     349                 :          0 : static 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                 :          0 :         ret = nfs_idmap_get_key(id_str, id_len, type, buf, buflen, idmap);
     358         [ #  # ]:          0 :         if (ret < 0)
     359                 :            :                 return -EINVAL;
     360                 :          0 :         return ret;
     361                 :            : }
     362                 :            : 
     363                 :            : /* Name -> ID */
     364                 :          0 : static 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                 :          0 :         data_size = nfs_idmap_get_key(name, namelen, type, id_str, NFS_UINT_MAXLEN, idmap);
     373         [ #  # ]:          0 :         if (data_size <= 0) {
     374                 :            :                 ret = -EINVAL;
     375                 :            :         } else {
     376                 :            :                 ret = kstrtol(id_str, 10, &id_long);
     377         [ #  # ]:          0 :                 if (!ret)
     378                 :          0 :                         *id = (__u32)id_long;
     379                 :            :         }
     380                 :          0 :         return ret;
     381                 :            : }
     382                 :            : 
     383                 :            : /* idmap classic begins here */
     384                 :            : 
     385                 :            : enum {
     386                 :            :         Opt_find_uid, Opt_find_gid, Opt_find_user, Opt_find_group, Opt_find_err
     387                 :            : };
     388                 :            : 
     389                 :            : static 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                 :            : 
     397                 :            : static int nfs_idmap_legacy_upcall(struct key *, void *);
     398                 :            : static ssize_t idmap_pipe_downcall(struct file *, const char __user *,
     399                 :            :                                    size_t);
     400                 :            : static void idmap_release_pipe(struct inode *);
     401                 :            : static void idmap_pipe_destroy_msg(struct rpc_pipe_msg *);
     402                 :            : 
     403                 :            : static 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                 :            : 
     410                 :            : static 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                 :            : 
     422                 :          0 : static void nfs_idmap_pipe_destroy(struct dentry *dir,
     423                 :            :                 struct rpc_pipe_dir_object *pdo)
     424                 :            : {
     425                 :          0 :         struct idmap *idmap = pdo->pdo_data;
     426                 :          0 :         struct rpc_pipe *pipe = idmap->idmap_pipe;
     427                 :            : 
     428         [ #  # ]:          0 :         if (pipe->dentry) {
     429                 :          0 :                 rpc_unlink(pipe->dentry);
     430                 :          0 :                 pipe->dentry = NULL;
     431                 :            :         }
     432                 :          0 : }
     433                 :            : 
     434                 :          0 : static int nfs_idmap_pipe_create(struct dentry *dir,
     435                 :            :                 struct rpc_pipe_dir_object *pdo)
     436                 :            : {
     437                 :          0 :         struct idmap *idmap = pdo->pdo_data;
     438                 :          0 :         struct rpc_pipe *pipe = idmap->idmap_pipe;
     439                 :            :         struct dentry *dentry;
     440                 :            : 
     441                 :          0 :         dentry = rpc_mkpipe_dentry(dir, "idmap", idmap, pipe);
     442         [ #  # ]:          0 :         if (IS_ERR(dentry))
     443                 :          0 :                 return PTR_ERR(dentry);
     444                 :          0 :         pipe->dentry = dentry;
     445                 :          0 :         return 0;
     446                 :            : }
     447                 :            : 
     448                 :            : static 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                 :            : 
     453                 :            : int
     454                 :          0 : nfs_idmap_new(struct nfs_client *clp)
     455                 :            : {
     456                 :            :         struct idmap *idmap;
     457                 :            :         struct rpc_pipe *pipe;
     458                 :            :         int error;
     459                 :            : 
     460                 :          0 :         idmap = kzalloc(sizeof(*idmap), GFP_KERNEL);
     461         [ #  # ]:          0 :         if (idmap == NULL)
     462                 :            :                 return -ENOMEM;
     463                 :            : 
     464                 :          0 :         mutex_init(&idmap->idmap_mutex);
     465                 :          0 :         idmap->cred = get_cred(clp->cl_rpcclient->cl_cred);
     466                 :            : 
     467                 :          0 :         rpc_init_pipe_dir_object(&idmap->idmap_pdo,
     468                 :            :                         &nfs_idmap_pipe_dir_object_ops,
     469                 :            :                         idmap);
     470                 :            : 
     471                 :          0 :         pipe = rpc_mkpipe_data(&idmap_upcall_ops, 0);
     472         [ #  # ]:          0 :         if (IS_ERR(pipe)) {
     473                 :            :                 error = PTR_ERR(pipe);
     474                 :          0 :                 goto err;
     475                 :            :         }
     476                 :          0 :         idmap->idmap_pipe = pipe;
     477                 :            : 
     478                 :          0 :         error = rpc_add_pipe_dir_object(clp->cl_net,
     479                 :          0 :                         &clp->cl_rpcclient->cl_pipedir_objects,
     480                 :            :                         &idmap->idmap_pdo);
     481         [ #  # ]:          0 :         if (error)
     482                 :            :                 goto err_destroy_pipe;
     483                 :            : 
     484                 :          0 :         clp->cl_idmap = idmap;
     485                 :          0 :         return 0;
     486                 :            : err_destroy_pipe:
     487                 :          0 :         rpc_destroy_pipe_data(idmap->idmap_pipe);
     488                 :            : err:
     489                 :          0 :         put_cred(idmap->cred);
     490                 :          0 :         kfree(idmap);
     491                 :          0 :         return error;
     492                 :            : }
     493                 :            : 
     494                 :            : void
     495                 :          0 : nfs_idmap_delete(struct nfs_client *clp)
     496                 :            : {
     497                 :          0 :         struct idmap *idmap = clp->cl_idmap;
     498                 :            : 
     499         [ #  # ]:          0 :         if (!idmap)
     500                 :          0 :                 return;
     501                 :          0 :         clp->cl_idmap = NULL;
     502                 :          0 :         rpc_remove_pipe_dir_object(clp->cl_net,
     503                 :          0 :                         &clp->cl_rpcclient->cl_pipedir_objects,
     504                 :            :                         &idmap->idmap_pdo);
     505                 :          0 :         rpc_destroy_pipe_data(idmap->idmap_pipe);
     506                 :          0 :         put_cred(idmap->cred);
     507                 :          0 :         kfree(idmap);
     508                 :            : }
     509                 :            : 
     510                 :          0 : static 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                 :          0 :         im->im_type = IDMAP_TYPE_GROUP;
     518                 :          0 :         token = match_token(desc, nfs_idmap_tokens, &substr);
     519                 :            : 
     520   [ #  #  #  #  :          0 :         switch (token) {
                      # ]
     521                 :            :         case Opt_find_uid:
     522                 :          0 :                 im->im_type = IDMAP_TYPE_USER;
     523                 :            :                 /* Fall through */
     524                 :            :         case Opt_find_gid:
     525                 :          0 :                 im->im_conv = IDMAP_CONV_NAMETOID;
     526                 :          0 :                 ret = match_strlcpy(im->im_name, &substr, IDMAP_NAMESZ);
     527                 :          0 :                 break;
     528                 :            : 
     529                 :            :         case Opt_find_user:
     530                 :          0 :                 im->im_type = IDMAP_TYPE_USER;
     531                 :            :                 /* Fall through */
     532                 :            :         case Opt_find_group:
     533                 :          0 :                 im->im_conv = IDMAP_CONV_IDTONAME;
     534                 :          0 :                 ret = match_int(&substr, &im->im_id);
     535         [ #  # ]:          0 :                 if (ret)
     536                 :            :                         goto out;
     537                 :            :                 break;
     538                 :            : 
     539                 :            :         default:
     540                 :            :                 ret = -EINVAL;
     541                 :            :                 goto out;
     542                 :            :         }
     543                 :            : 
     544                 :          0 :         msg->data = im;
     545                 :          0 :         msg->len  = sizeof(struct idmap_msg);
     546                 :            : 
     547                 :            : out:
     548                 :          0 :         return ret;
     549                 :            : }
     550                 :            : 
     551                 :            : static bool
     552                 :          0 : nfs_idmap_prepare_pipe_upcall(struct idmap *idmap,
     553                 :            :                 struct idmap_legacy_upcalldata *data)
     554                 :            : {
     555         [ #  # ]:          0 :         if (idmap->idmap_upcall_data != NULL) {
     556         [ #  # ]:          0 :                 WARN_ON_ONCE(1);
     557                 :            :                 return false;
     558                 :            :         }
     559                 :          0 :         idmap->idmap_upcall_data = data;
     560                 :          0 :         return true;
     561                 :            : }
     562                 :            : 
     563                 :            : static void
     564                 :          0 : nfs_idmap_complete_pipe_upcall_locked(struct idmap *idmap, int ret)
     565                 :            : {
     566                 :          0 :         struct key *authkey = idmap->idmap_upcall_data->authkey;
     567                 :            : 
     568                 :          0 :         kfree(idmap->idmap_upcall_data);
     569                 :          0 :         idmap->idmap_upcall_data = NULL;
     570                 :          0 :         complete_request_key(authkey, ret);
     571                 :          0 :         key_put(authkey);
     572                 :          0 : }
     573                 :            : 
     574                 :            : static void
     575                 :            : nfs_idmap_abort_pipe_upcall(struct idmap *idmap, int ret)
     576                 :            : {
     577   [ #  #  #  #  :          0 :         if (idmap->idmap_upcall_data != NULL)
                   #  # ]
     578                 :          0 :                 nfs_idmap_complete_pipe_upcall_locked(idmap, ret);
     579                 :            : }
     580                 :            : 
     581                 :          0 : static 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                 :          0 :         struct key *key = rka->target_key;
     589                 :            :         int ret = -ENOKEY;
     590                 :            : 
     591         [ #  # ]:          0 :         if (!aux)
     592                 :            :                 goto out1;
     593                 :            : 
     594                 :            :         /* msg and im are freed in idmap_pipe_destroy_msg */
     595                 :            :         ret = -ENOMEM;
     596                 :          0 :         data = kzalloc(sizeof(*data), GFP_KERNEL);
     597         [ #  # ]:          0 :         if (!data)
     598                 :            :                 goto out1;
     599                 :            : 
     600                 :          0 :         msg = &data->pipe_msg;
     601                 :          0 :         im = &data->idmap_msg;
     602                 :          0 :         data->idmap = idmap;
     603                 :          0 :         data->authkey = key_get(authkey);
     604                 :            : 
     605                 :          0 :         ret = nfs_idmap_prepare_message(key->description, idmap, im, msg);
     606         [ #  # ]:          0 :         if (ret < 0)
     607                 :            :                 goto out2;
     608                 :            : 
     609                 :            :         ret = -EAGAIN;
     610         [ #  # ]:          0 :         if (!nfs_idmap_prepare_pipe_upcall(idmap, data))
     611                 :            :                 goto out2;
     612                 :            : 
     613                 :          0 :         ret = rpc_queue_upcall(idmap->idmap_pipe, msg);
     614         [ #  # ]:          0 :         if (ret < 0)
     615                 :            :                 nfs_idmap_abort_pipe_upcall(idmap, ret);
     616                 :            : 
     617                 :          0 :         return ret;
     618                 :            : out2:
     619                 :          0 :         kfree(data);
     620                 :            : out1:
     621                 :          0 :         complete_request_key(authkey, ret);
     622                 :          0 :         return ret;
     623                 :            : }
     624                 :            : 
     625                 :            : static int nfs_idmap_instantiate(struct key *key, struct key *authkey, char *data, size_t datalen)
     626                 :            : {
     627                 :          0 :         return key_instantiate_and_link(key, data, datalen,
     628                 :          0 :                                         id_resolver_cache->thread_keyring,
     629                 :            :                                         authkey);
     630                 :            : }
     631                 :            : 
     632                 :          0 : static 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         [ #  # ]:          0 :         if (upcall->im_type != im->im_type || upcall->im_conv != im->im_conv)
     642                 :            :                 goto out;
     643      [ #  #  # ]:          0 :         switch (im->im_conv) {
     644                 :            :         case IDMAP_CONV_NAMETOID:
     645         [ #  # ]:          0 :                 if (strcmp(upcall->im_name, im->im_name) != 0)
     646                 :            :                         break;
     647                 :            :                 /* Note: here we store the NUL terminator too */
     648                 :          0 :                 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                 :          0 :                 break;
     652                 :            :         case IDMAP_CONV_IDTONAME:
     653         [ #  # ]:          0 :                 if (upcall->im_id != im->im_id)
     654                 :            :                         break;
     655                 :          0 :                 len = strlen(im->im_name);
     656                 :            :                 ret = nfs_idmap_instantiate(key, authkey, im->im_name, len);
     657                 :          0 :                 break;
     658                 :            :         default:
     659                 :            :                 ret = -EINVAL;
     660                 :            :         }
     661                 :            : out:
     662                 :          0 :         return ret;
     663                 :            : }
     664                 :            : 
     665                 :            : static ssize_t
     666                 :          0 : idmap_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                 :          0 :         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         [ #  # ]:          0 :         if (idmap->idmap_upcall_data == NULL)
     681                 :            :                 goto out_noupcall;
     682                 :            : 
     683                 :          0 :         authkey = idmap->idmap_upcall_data->authkey;
     684                 :            :         rka = get_request_key_auth(authkey);
     685                 :            : 
     686         [ #  # ]:          0 :         if (mlen != sizeof(im)) {
     687                 :            :                 ret = -ENOSPC;
     688                 :            :                 goto out;
     689                 :            :         }
     690                 :            : 
     691         [ #  # ]:          0 :         if (copy_from_user(&im, src, mlen) != 0) {
     692                 :            :                 ret = -EFAULT;
     693                 :            :                 goto out;
     694                 :            :         }
     695                 :            : 
     696         [ #  # ]:          0 :         if (!(im.im_status & IDMAP_STATUS_SUCCESS)) {
     697                 :            :                 ret = -ENOKEY;
     698                 :            :                 goto out;
     699                 :            :         }
     700                 :            : 
     701                 :          0 :         namelen_in = strnlen(im.im_name, IDMAP_NAMESZ);
     702         [ #  # ]:          0 :         if (namelen_in == 0 || namelen_in == IDMAP_NAMESZ) {
     703                 :            :                 ret = -EINVAL;
     704                 :            :                 goto out;
     705                 :            : }
     706                 :            : 
     707                 :          0 :         ret = nfs_idmap_read_and_verify_message(&im,
     708                 :          0 :                         &idmap->idmap_upcall_data->idmap_msg,
     709                 :            :                         rka->target_key, authkey);
     710         [ #  # ]:          0 :         if (ret >= 0) {
     711                 :          0 :                 key_set_timeout(rka->target_key, nfs_idmap_cache_timeout);
     712                 :          0 :                 ret = mlen;
     713                 :            :         }
     714                 :            : 
     715                 :            : out:
     716                 :          0 :         nfs_idmap_complete_pipe_upcall_locked(idmap, ret);
     717                 :            : out_noupcall:
     718                 :          0 :         return ret;
     719                 :            : }
     720                 :            : 
     721                 :            : static void
     722                 :          0 : idmap_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                 :          0 :         struct idmap *idmap = data->idmap;
     728                 :            : 
     729         [ #  # ]:          0 :         if (msg->errno)
     730                 :            :                 nfs_idmap_abort_pipe_upcall(idmap, msg->errno);
     731                 :          0 : }
     732                 :            : 
     733                 :            : static void
     734                 :          0 : idmap_release_pipe(struct inode *inode)
     735                 :            : {
     736                 :            :         struct rpc_inode *rpci = RPC_I(inode);
     737                 :          0 :         struct idmap *idmap = (struct idmap *)rpci->private;
     738                 :            : 
     739                 :            :         nfs_idmap_abort_pipe_upcall(idmap, -EPIPE);
     740                 :          0 : }
     741                 :            : 
     742                 :          0 : int nfs_map_name_to_uid(const struct nfs_server *server, const char *name, size_t namelen, kuid_t *uid)
     743                 :            : {
     744                 :          0 :         struct idmap *idmap = server->nfs_client->cl_idmap;
     745                 :          0 :         __u32 id = -1;
     746                 :            :         int ret = 0;
     747                 :            : 
     748         [ #  # ]:          0 :         if (!nfs_map_string_to_numeric(name, namelen, &id))
     749                 :          0 :                 ret = nfs_idmap_lookup_id(name, namelen, "uid", &id, idmap);
     750         [ #  # ]:          0 :         if (ret == 0) {
     751                 :          0 :                 *uid = make_kuid(idmap_userns(idmap), id);
     752         [ #  # ]:          0 :                 if (!uid_valid(*uid))
     753                 :            :                         ret = -ERANGE;
     754                 :            :         }
     755                 :          0 :         trace_nfs4_map_name_to_uid(name, namelen, id, ret);
     756                 :          0 :         return ret;
     757                 :            : }
     758                 :            : 
     759                 :          0 : int nfs_map_group_to_gid(const struct nfs_server *server, const char *name, size_t namelen, kgid_t *gid)
     760                 :            : {
     761                 :          0 :         struct idmap *idmap = server->nfs_client->cl_idmap;
     762                 :          0 :         __u32 id = -1;
     763                 :            :         int ret = 0;
     764                 :            : 
     765         [ #  # ]:          0 :         if (!nfs_map_string_to_numeric(name, namelen, &id))
     766                 :          0 :                 ret = nfs_idmap_lookup_id(name, namelen, "gid", &id, idmap);
     767         [ #  # ]:          0 :         if (ret == 0) {
     768                 :          0 :                 *gid = make_kgid(idmap_userns(idmap), id);
     769         [ #  # ]:          0 :                 if (!gid_valid(*gid))
     770                 :            :                         ret = -ERANGE;
     771                 :            :         }
     772                 :          0 :         trace_nfs4_map_group_to_gid(name, namelen, id, ret);
     773                 :          0 :         return ret;
     774                 :            : }
     775                 :            : 
     776                 :          0 : int nfs_map_uid_to_name(const struct nfs_server *server, kuid_t uid, char *buf, size_t buflen)
     777                 :            : {
     778                 :          0 :         struct idmap *idmap = server->nfs_client->cl_idmap;
     779                 :            :         int ret = -EINVAL;
     780                 :            :         __u32 id;
     781                 :            : 
     782                 :          0 :         id = from_kuid_munged(idmap_userns(idmap), uid);
     783         [ #  # ]:          0 :         if (!(server->caps & NFS_CAP_UIDGID_NOMAP))
     784                 :          0 :                 ret = nfs_idmap_lookup_name(id, "user", buf, buflen, idmap);
     785         [ #  # ]:          0 :         if (ret < 0)
     786                 :            :                 ret = nfs_map_numeric_to_string(id, buf, buflen);
     787                 :          0 :         trace_nfs4_map_uid_to_name(buf, ret, id, ret);
     788                 :          0 :         return ret;
     789                 :            : }
     790                 :          0 : int nfs_map_gid_to_group(const struct nfs_server *server, kgid_t gid, char *buf, size_t buflen)
     791                 :            : {
     792                 :          0 :         struct idmap *idmap = server->nfs_client->cl_idmap;
     793                 :            :         int ret = -EINVAL;
     794                 :            :         __u32 id;
     795                 :            : 
     796                 :          0 :         id = from_kgid_munged(idmap_userns(idmap), gid);
     797         [ #  # ]:          0 :         if (!(server->caps & NFS_CAP_UIDGID_NOMAP))
     798                 :          0 :                 ret = nfs_idmap_lookup_name(id, "group", buf, buflen, idmap);
     799         [ #  # ]:          0 :         if (ret < 0)
     800                 :            :                 ret = nfs_map_numeric_to_string(id, buf, buflen);
     801                 :          0 :         trace_nfs4_map_gid_to_group(buf, ret, id, ret);
     802                 :          0 :         return ret;
     803                 :            : }

Generated by: LCOV version 1.14