linux/fs/nfs/nfs4namespace.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * linux/fs/nfs/nfs4namespace.c
   4 *
   5 * Copyright (C) 2005 Trond Myklebust <Trond.Myklebust@netapp.com>
   6 * - Modified by David Howells <dhowells@redhat.com>
   7 *
   8 * NFSv4 namespace
   9 */
  10
  11#include <linux/module.h>
  12#include <linux/dcache.h>
  13#include <linux/mount.h>
  14#include <linux/namei.h>
  15#include <linux/nfs_fs.h>
  16#include <linux/nfs_mount.h>
  17#include <linux/slab.h>
  18#include <linux/string.h>
  19#include <linux/sunrpc/clnt.h>
  20#include <linux/sunrpc/addr.h>
  21#include <linux/vfs.h>
  22#include <linux/inet.h>
  23#include "internal.h"
  24#include "nfs4_fs.h"
  25#include "nfs.h"
  26#include "dns_resolve.h"
  27
  28#define NFSDBG_FACILITY         NFSDBG_VFS
  29
  30/*
  31 * Work out the length that an NFSv4 path would render to as a standard posix
  32 * path, with a leading slash but no terminating slash.
  33 */
  34static ssize_t nfs4_pathname_len(const struct nfs4_pathname *pathname)
  35{
  36        ssize_t len = 0;
  37        int i;
  38
  39        for (i = 0; i < pathname->ncomponents; i++) {
  40                const struct nfs4_string *component = &pathname->components[i];
  41
  42                if (component->len > NAME_MAX)
  43                        goto too_long;
  44                len += 1 + component->len; /* Adding "/foo" */
  45                if (len > PATH_MAX)
  46                        goto too_long;
  47        }
  48        return len;
  49
  50too_long:
  51        return -ENAMETOOLONG;
  52}
  53
  54/*
  55 * Convert the NFSv4 pathname components into a standard posix path.
  56 */
  57static char *nfs4_pathname_string(const struct nfs4_pathname *pathname,
  58                                  unsigned short *_len)
  59{
  60        ssize_t len;
  61        char *buf, *p;
  62        int i;
  63
  64        len = nfs4_pathname_len(pathname);
  65        if (len < 0)
  66                return ERR_PTR(len);
  67        *_len = len;
  68
  69        p = buf = kmalloc(len + 1, GFP_KERNEL);
  70        if (!buf)
  71                return ERR_PTR(-ENOMEM);
  72
  73        for (i = 0; i < pathname->ncomponents; i++) {
  74                const struct nfs4_string *component = &pathname->components[i];
  75
  76                *p++ = '/';
  77                memcpy(p, component->data, component->len);
  78                p += component->len;
  79        }
  80
  81        *p = 0;
  82        return buf;
  83}
  84
  85/*
  86 * return the path component of "<server>:<path>"
  87 *  nfspath - the "<server>:<path>" string
  88 *  end - one past the last char that could contain "<server>:"
  89 * returns NULL on failure
  90 */
  91static char *nfs_path_component(const char *nfspath, const char *end)
  92{
  93        char *p;
  94
  95        if (*nfspath == '[') {
  96                /* parse [] escaped IPv6 addrs */
  97                p = strchr(nfspath, ']');
  98                if (p != NULL && ++p < end && *p == ':')
  99                        return p + 1;
 100        } else {
 101                /* otherwise split on first colon */
 102                p = strchr(nfspath, ':');
 103                if (p != NULL && p < end)
 104                        return p + 1;
 105        }
 106        return NULL;
 107}
 108
 109/*
 110 * Determine the mount path as a string
 111 */
 112static char *nfs4_path(struct dentry *dentry, char *buffer, ssize_t buflen)
 113{
 114        char *limit;
 115        char *path = nfs_path(&limit, dentry, buffer, buflen,
 116                              NFS_PATH_CANONICAL);
 117        if (!IS_ERR(path)) {
 118                char *path_component = nfs_path_component(path, limit);
 119                if (path_component)
 120                        return path_component;
 121        }
 122        return path;
 123}
 124
 125/*
 126 * Check that fs_locations::fs_root [RFC3530 6.3] is a prefix for what we
 127 * believe to be the server path to this dentry
 128 */
 129static int nfs4_validate_fspath(struct dentry *dentry,
 130                                const struct nfs4_fs_locations *locations,
 131                                struct nfs_fs_context *ctx)
 132{
 133        const char *path;
 134        char *fs_path;
 135        unsigned short len;
 136        char *buf;
 137        int n;
 138
 139        buf = kmalloc(4096, GFP_KERNEL);
 140        if (!buf)
 141                return -ENOMEM;
 142
 143        path = nfs4_path(dentry, buf, 4096);
 144        if (IS_ERR(path)) {
 145                kfree(buf);
 146                return PTR_ERR(path);
 147        }
 148
 149        fs_path = nfs4_pathname_string(&locations->fs_path, &len);
 150        if (IS_ERR(fs_path)) {
 151                kfree(buf);
 152                return PTR_ERR(fs_path);
 153        }
 154
 155        n = strncmp(path, fs_path, len);
 156        kfree(buf);
 157        kfree(fs_path);
 158        if (n != 0) {
 159                dprintk("%s: path %s does not begin with fsroot %s\n",
 160                        __func__, path, ctx->nfs_server.export_path);
 161                return -ENOENT;
 162        }
 163
 164        return 0;
 165}
 166
 167static size_t nfs_parse_server_name(char *string, size_t len,
 168                struct sockaddr *sa, size_t salen, struct net *net)
 169{
 170        ssize_t ret;
 171
 172        ret = rpc_pton(net, string, len, sa, salen);
 173        if (ret == 0) {
 174                ret = nfs_dns_resolve_name(net, string, len, sa, salen);
 175                if (ret < 0)
 176                        ret = 0;
 177        }
 178        return ret;
 179}
 180
 181/**
 182 * nfs_find_best_sec - Find a security mechanism supported locally
 183 * @clnt: pointer to rpc_clnt
 184 * @server: NFS server struct
 185 * @flavors: List of security tuples returned by SECINFO procedure
 186 *
 187 * Return an rpc client that uses the first security mechanism in
 188 * "flavors" that is locally supported.  The "flavors" array
 189 * is searched in the order returned from the server, per RFC 3530
 190 * recommendation and each flavor is checked for membership in the
 191 * sec= mount option list if it exists.
 192 *
 193 * Return -EPERM if no matching flavor is found in the array.
 194 *
 195 * Please call rpc_shutdown_client() when you are done with this rpc client.
 196 *
 197 */
 198static struct rpc_clnt *nfs_find_best_sec(struct rpc_clnt *clnt,
 199                                          struct nfs_server *server,
 200                                          struct nfs4_secinfo_flavors *flavors)
 201{
 202        rpc_authflavor_t pflavor;
 203        struct nfs4_secinfo4 *secinfo;
 204        unsigned int i;
 205
 206        for (i = 0; i < flavors->num_flavors; i++) {
 207                secinfo = &flavors->flavors[i];
 208
 209                switch (secinfo->flavor) {
 210                case RPC_AUTH_NULL:
 211                case RPC_AUTH_UNIX:
 212                case RPC_AUTH_GSS:
 213                        pflavor = rpcauth_get_pseudoflavor(secinfo->flavor,
 214                                                        &secinfo->flavor_info);
 215                        /* does the pseudoflavor match a sec= mount opt? */
 216                        if (pflavor != RPC_AUTH_MAXFLAVOR &&
 217                            nfs_auth_info_match(&server->auth_info, pflavor)) {
 218                                struct rpc_clnt *new;
 219                                struct rpc_cred *cred;
 220
 221                                /* Cloning creates an rpc_auth for the flavor */
 222                                new = rpc_clone_client_set_auth(clnt, pflavor);
 223                                if (IS_ERR(new))
 224                                        continue;
 225                                /**
 226                                * Check that the user actually can use the
 227                                * flavor. This is mostly for RPC_AUTH_GSS
 228                                * where cr_init obtains a gss context
 229                                */
 230                                cred = rpcauth_lookupcred(new->cl_auth, 0);
 231                                if (IS_ERR(cred)) {
 232                                        rpc_shutdown_client(new);
 233                                        continue;
 234                                }
 235                                put_rpccred(cred);
 236                                return new;
 237                        }
 238                }
 239        }
 240        return ERR_PTR(-EPERM);
 241}
 242
 243/**
 244 * nfs4_negotiate_security - in response to an NFS4ERR_WRONGSEC on lookup,
 245 * return an rpc_clnt that uses the best available security flavor with
 246 * respect to the secinfo flavor list and the sec= mount options.
 247 *
 248 * @clnt: RPC client to clone
 249 * @inode: directory inode
 250 * @name: lookup name
 251 *
 252 * Please call rpc_shutdown_client() when you are done with this rpc client.
 253 */
 254struct rpc_clnt *
 255nfs4_negotiate_security(struct rpc_clnt *clnt, struct inode *inode,
 256                                        const struct qstr *name)
 257{
 258        struct page *page;
 259        struct nfs4_secinfo_flavors *flavors;
 260        struct rpc_clnt *new;
 261        int err;
 262
 263        page = alloc_page(GFP_KERNEL);
 264        if (!page)
 265                return ERR_PTR(-ENOMEM);
 266
 267        flavors = page_address(page);
 268
 269        err = nfs4_proc_secinfo(inode, name, flavors);
 270        if (err < 0) {
 271                new = ERR_PTR(err);
 272                goto out;
 273        }
 274
 275        new = nfs_find_best_sec(clnt, NFS_SERVER(inode), flavors);
 276
 277out:
 278        put_page(page);
 279        return new;
 280}
 281
 282static int try_location(struct fs_context *fc,
 283                        const struct nfs4_fs_location *location)
 284{
 285        struct nfs_fs_context *ctx = nfs_fc2context(fc);
 286        unsigned int len, s;
 287        char *export_path, *source, *p;
 288        int ret = -ENOENT;
 289
 290        /* Allocate a buffer big enough to hold any of the hostnames plus a
 291         * terminating char and also a buffer big enough to hold the hostname
 292         * plus a colon plus the path.
 293         */
 294        len = 0;
 295        for (s = 0; s < location->nservers; s++) {
 296                const struct nfs4_string *buf = &location->servers[s];
 297                if (buf->len > len)
 298                        len = buf->len;
 299        }
 300
 301        kfree(ctx->nfs_server.hostname);
 302        ctx->nfs_server.hostname = kmalloc(len + 1, GFP_KERNEL);
 303        if (!ctx->nfs_server.hostname)
 304                return -ENOMEM;
 305
 306        export_path = nfs4_pathname_string(&location->rootpath,
 307                                           &ctx->nfs_server.export_path_len);
 308        if (IS_ERR(export_path))
 309                return PTR_ERR(export_path);
 310
 311        kfree(ctx->nfs_server.export_path);
 312        ctx->nfs_server.export_path = export_path;
 313
 314        source = kmalloc(len + 1 + ctx->nfs_server.export_path_len + 1,
 315                         GFP_KERNEL);
 316        if (!source)
 317                return -ENOMEM;
 318
 319        kfree(fc->source);
 320        fc->source = source;
 321        for (s = 0; s < location->nservers; s++) {
 322                const struct nfs4_string *buf = &location->servers[s];
 323
 324                if (memchr(buf->data, IPV6_SCOPE_DELIMITER, buf->len))
 325                        continue;
 326
 327                ctx->nfs_server.addrlen =
 328                        nfs_parse_server_name(buf->data, buf->len,
 329                                              &ctx->nfs_server.address,
 330                                              sizeof(ctx->nfs_server._address),
 331                                              fc->net_ns);
 332                if (ctx->nfs_server.addrlen == 0)
 333                        continue;
 334
 335                rpc_set_port(&ctx->nfs_server.address, NFS_PORT);
 336
 337                memcpy(ctx->nfs_server.hostname, buf->data, buf->len);
 338                ctx->nfs_server.hostname[buf->len] = '\0';
 339
 340                p = source;
 341                memcpy(p, buf->data, buf->len);
 342                p += buf->len;
 343                *p++ = ':';
 344                memcpy(p, ctx->nfs_server.export_path, ctx->nfs_server.export_path_len);
 345                p += ctx->nfs_server.export_path_len;
 346                *p = 0;
 347
 348                ret = nfs4_get_referral_tree(fc);
 349                if (ret == 0)
 350                        return 0;
 351        }
 352
 353        return ret;
 354}
 355
 356/**
 357 * nfs_follow_referral - set up mountpoint when hitting a referral on moved error
 358 * @fc: pointer to struct nfs_fs_context
 359 * @locations: array of NFSv4 server location information
 360 *
 361 */
 362static int nfs_follow_referral(struct fs_context *fc,
 363                               const struct nfs4_fs_locations *locations)
 364{
 365        struct nfs_fs_context *ctx = nfs_fc2context(fc);
 366        int loc, error;
 367
 368        if (locations == NULL || locations->nlocations <= 0)
 369                return -ENOENT;
 370
 371        dprintk("%s: referral at %pd2\n", __func__, ctx->clone_data.dentry);
 372
 373        /* Ensure fs path is a prefix of current dentry path */
 374        error = nfs4_validate_fspath(ctx->clone_data.dentry, locations, ctx);
 375        if (error < 0)
 376                return error;
 377
 378        error = -ENOENT;
 379        for (loc = 0; loc < locations->nlocations; loc++) {
 380                const struct nfs4_fs_location *location = &locations->locations[loc];
 381
 382                if (location == NULL || location->nservers <= 0 ||
 383                    location->rootpath.ncomponents == 0)
 384                        continue;
 385
 386                error = try_location(fc, location);
 387                if (error == 0)
 388                        return 0;
 389        }
 390
 391        return error;
 392}
 393
 394/*
 395 * nfs_do_refmount - handle crossing a referral on server
 396 * @dentry - dentry of referral
 397 *
 398 */
 399static int nfs_do_refmount(struct fs_context *fc, struct rpc_clnt *client)
 400{
 401        struct nfs_fs_context *ctx = nfs_fc2context(fc);
 402        struct dentry *dentry, *parent;
 403        struct nfs4_fs_locations *fs_locations = NULL;
 404        struct page *page;
 405        int err = -ENOMEM;
 406
 407        /* BUG_ON(IS_ROOT(dentry)); */
 408        page = alloc_page(GFP_KERNEL);
 409        if (!page)
 410                return -ENOMEM;
 411
 412        fs_locations = kmalloc(sizeof(struct nfs4_fs_locations), GFP_KERNEL);
 413        if (!fs_locations)
 414                goto out_free;
 415
 416        /* Get locations */
 417        dentry = ctx->clone_data.dentry;
 418        parent = dget_parent(dentry);
 419        dprintk("%s: getting locations for %pd2\n",
 420                __func__, dentry);
 421
 422        err = nfs4_proc_fs_locations(client, d_inode(parent), &dentry->d_name, fs_locations, page);
 423        dput(parent);
 424        if (err != 0)
 425                goto out_free_2;
 426
 427        err = -ENOENT;
 428        if (fs_locations->nlocations <= 0 ||
 429            fs_locations->fs_path.ncomponents <= 0)
 430                goto out_free_2;
 431
 432        err = nfs_follow_referral(fc, fs_locations);
 433out_free_2:
 434        kfree(fs_locations);
 435out_free:
 436        __free_page(page);
 437        return err;
 438}
 439
 440int nfs4_submount(struct fs_context *fc, struct nfs_server *server)
 441{
 442        struct nfs_fs_context *ctx = nfs_fc2context(fc);
 443        struct dentry *dentry = ctx->clone_data.dentry;
 444        struct dentry *parent = dget_parent(dentry);
 445        struct inode *dir = d_inode(parent);
 446        struct rpc_clnt *client;
 447        int ret;
 448
 449        /* Look it up again to get its attributes and sec flavor */
 450        client = nfs4_proc_lookup_mountpoint(dir, dentry, ctx->mntfh,
 451                                             ctx->clone_data.fattr);
 452        dput(parent);
 453        if (IS_ERR(client))
 454                return PTR_ERR(client);
 455
 456        ctx->selected_flavor = client->cl_auth->au_flavor;
 457        if (ctx->clone_data.fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL) {
 458                ret = nfs_do_refmount(fc, client);
 459        } else {
 460                ret = nfs_do_submount(fc);
 461        }
 462
 463        rpc_shutdown_client(client);
 464        return ret;
 465}
 466
 467/*
 468 * Try one location from the fs_locations array.
 469 *
 470 * Returns zero on success, or a negative errno value.
 471 */
 472static int nfs4_try_replacing_one_location(struct nfs_server *server,
 473                char *page, char *page2,
 474                const struct nfs4_fs_location *location)
 475{
 476        const size_t addr_bufsize = sizeof(struct sockaddr_storage);
 477        struct net *net = rpc_net_ns(server->client);
 478        struct sockaddr *sap;
 479        unsigned int s;
 480        size_t salen;
 481        int error;
 482
 483        sap = kmalloc(addr_bufsize, GFP_KERNEL);
 484        if (sap == NULL)
 485                return -ENOMEM;
 486
 487        error = -ENOENT;
 488        for (s = 0; s < location->nservers; s++) {
 489                const struct nfs4_string *buf = &location->servers[s];
 490                char *hostname;
 491
 492                if (buf->len <= 0 || buf->len > PAGE_SIZE)
 493                        continue;
 494
 495                if (memchr(buf->data, IPV6_SCOPE_DELIMITER, buf->len) != NULL)
 496                        continue;
 497
 498                salen = nfs_parse_server_name(buf->data, buf->len,
 499                                                sap, addr_bufsize, net);
 500                if (salen == 0)
 501                        continue;
 502                rpc_set_port(sap, NFS_PORT);
 503
 504                error = -ENOMEM;
 505                hostname = kmemdup_nul(buf->data, buf->len, GFP_KERNEL);
 506                if (hostname == NULL)
 507                        break;
 508
 509                error = nfs4_update_server(server, hostname, sap, salen, net);
 510                kfree(hostname);
 511                if (error == 0)
 512                        break;
 513        }
 514
 515        kfree(sap);
 516        return error;
 517}
 518
 519/**
 520 * nfs4_replace_transport - set up transport to destination server
 521 *
 522 * @server: export being migrated
 523 * @locations: fs_locations array
 524 *
 525 * Returns zero on success, or a negative errno value.
 526 *
 527 * The client tries all the entries in the "locations" array, in the
 528 * order returned by the server, until one works or the end of the
 529 * array is reached.
 530 */
 531int nfs4_replace_transport(struct nfs_server *server,
 532                           const struct nfs4_fs_locations *locations)
 533{
 534        char *page = NULL, *page2 = NULL;
 535        int loc, error;
 536
 537        error = -ENOENT;
 538        if (locations == NULL || locations->nlocations <= 0)
 539                goto out;
 540
 541        error = -ENOMEM;
 542        page = (char *) __get_free_page(GFP_USER);
 543        if (!page)
 544                goto out;
 545        page2 = (char *) __get_free_page(GFP_USER);
 546        if (!page2)
 547                goto out;
 548
 549        for (loc = 0; loc < locations->nlocations; loc++) {
 550                const struct nfs4_fs_location *location =
 551                                                &locations->locations[loc];
 552
 553                if (location == NULL || location->nservers <= 0 ||
 554                    location->rootpath.ncomponents == 0)
 555                        continue;
 556
 557                error = nfs4_try_replacing_one_location(server, page,
 558                                                        page2, location);
 559                if (error == 0)
 560                        break;
 561        }
 562
 563out:
 564        free_page((unsigned long)page);
 565        free_page((unsigned long)page2);
 566        return error;
 567}
 568