LCOV - code coverage report
Current view: top level - fs/nfs - fs_context.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 0 680 0.0 %
Date: 2022-04-01 13:59:58 Functions: 0 12 0.0 %
Branches: 0 296 0.0 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0-only
       2                 :            : /*
       3                 :            :  * linux/fs/nfs/fs_context.c
       4                 :            :  *
       5                 :            :  * Copyright (C) 1992 Rick Sladkey
       6                 :            :  * Conversion to new mount api Copyright (C) David Howells
       7                 :            :  *
       8                 :            :  * NFS mount handling.
       9                 :            :  *
      10                 :            :  * Split from fs/nfs/super.c by David Howells <dhowells@redhat.com>
      11                 :            :  */
      12                 :            : 
      13                 :            : #include <linux/module.h>
      14                 :            : #include <linux/fs.h>
      15                 :            : #include <linux/fs_context.h>
      16                 :            : #include <linux/fs_parser.h>
      17                 :            : #include <linux/nfs_fs.h>
      18                 :            : #include <linux/nfs_mount.h>
      19                 :            : #include <linux/nfs4_mount.h>
      20                 :            : #include "nfs.h"
      21                 :            : #include "internal.h"
      22                 :            : 
      23                 :            : #define NFSDBG_FACILITY         NFSDBG_MOUNT
      24                 :            : 
      25                 :            : #if IS_ENABLED(CONFIG_NFS_V3)
      26                 :            : #define NFS_DEFAULT_VERSION 3
      27                 :            : #else
      28                 :            : #define NFS_DEFAULT_VERSION 2
      29                 :            : #endif
      30                 :            : 
      31                 :            : #define NFS_MAX_CONNECTIONS 16
      32                 :            : 
      33                 :            : enum nfs_param {
      34                 :            :         Opt_ac,
      35                 :            :         Opt_acdirmax,
      36                 :            :         Opt_acdirmin,
      37                 :            :         Opt_acl,
      38                 :            :         Opt_acregmax,
      39                 :            :         Opt_acregmin,
      40                 :            :         Opt_actimeo,
      41                 :            :         Opt_addr,
      42                 :            :         Opt_bg,
      43                 :            :         Opt_bsize,
      44                 :            :         Opt_clientaddr,
      45                 :            :         Opt_cto,
      46                 :            :         Opt_fg,
      47                 :            :         Opt_fscache,
      48                 :            :         Opt_fscache_flag,
      49                 :            :         Opt_hard,
      50                 :            :         Opt_intr,
      51                 :            :         Opt_local_lock,
      52                 :            :         Opt_lock,
      53                 :            :         Opt_lookupcache,
      54                 :            :         Opt_migration,
      55                 :            :         Opt_minorversion,
      56                 :            :         Opt_mountaddr,
      57                 :            :         Opt_mounthost,
      58                 :            :         Opt_mountport,
      59                 :            :         Opt_mountproto,
      60                 :            :         Opt_mountvers,
      61                 :            :         Opt_namelen,
      62                 :            :         Opt_nconnect,
      63                 :            :         Opt_port,
      64                 :            :         Opt_posix,
      65                 :            :         Opt_proto,
      66                 :            :         Opt_rdirplus,
      67                 :            :         Opt_rdma,
      68                 :            :         Opt_resvport,
      69                 :            :         Opt_retrans,
      70                 :            :         Opt_retry,
      71                 :            :         Opt_rsize,
      72                 :            :         Opt_sec,
      73                 :            :         Opt_sharecache,
      74                 :            :         Opt_sloppy,
      75                 :            :         Opt_soft,
      76                 :            :         Opt_softerr,
      77                 :            :         Opt_softreval,
      78                 :            :         Opt_source,
      79                 :            :         Opt_tcp,
      80                 :            :         Opt_timeo,
      81                 :            :         Opt_udp,
      82                 :            :         Opt_v,
      83                 :            :         Opt_vers,
      84                 :            :         Opt_wsize,
      85                 :            : };
      86                 :            : 
      87                 :            : enum {
      88                 :            :         Opt_local_lock_all,
      89                 :            :         Opt_local_lock_flock,
      90                 :            :         Opt_local_lock_none,
      91                 :            :         Opt_local_lock_posix,
      92                 :            : };
      93                 :            : 
      94                 :            : static const struct constant_table nfs_param_enums_local_lock[] = {
      95                 :            :         { "all",              Opt_local_lock_all },
      96                 :            :         { "flock",    Opt_local_lock_flock },
      97                 :            :         { "none",             Opt_local_lock_none },
      98                 :            :         {}
      99                 :            : };
     100                 :            : 
     101                 :            : enum {
     102                 :            :         Opt_lookupcache_all,
     103                 :            :         Opt_lookupcache_none,
     104                 :            :         Opt_lookupcache_positive,
     105                 :            : };
     106                 :            : 
     107                 :            : static const struct constant_table nfs_param_enums_lookupcache[] = {
     108                 :            :         { "all",              Opt_lookupcache_all },
     109                 :            :         { "none",             Opt_lookupcache_none },
     110                 :            :         { "pos",              Opt_lookupcache_positive },
     111                 :            :         { "positive",         Opt_lookupcache_positive },
     112                 :            :         {}
     113                 :            : };
     114                 :            : 
     115                 :            : static const struct fs_parameter_spec nfs_fs_parameters[] = {
     116                 :            :         fsparam_flag_no("ac",         Opt_ac),
     117                 :            :         fsparam_u32   ("acdirmax",    Opt_acdirmax),
     118                 :            :         fsparam_u32   ("acdirmin",    Opt_acdirmin),
     119                 :            :         fsparam_flag_no("acl",                Opt_acl),
     120                 :            :         fsparam_u32   ("acregmax",    Opt_acregmax),
     121                 :            :         fsparam_u32   ("acregmin",    Opt_acregmin),
     122                 :            :         fsparam_u32   ("actimeo",     Opt_actimeo),
     123                 :            :         fsparam_string("addr",                Opt_addr),
     124                 :            :         fsparam_flag  ("bg",          Opt_bg),
     125                 :            :         fsparam_u32   ("bsize",               Opt_bsize),
     126                 :            :         fsparam_string("clientaddr",  Opt_clientaddr),
     127                 :            :         fsparam_flag_no("cto",                Opt_cto),
     128                 :            :         fsparam_flag  ("fg",          Opt_fg),
     129                 :            :         fsparam_flag_no("fsc",                Opt_fscache_flag),
     130                 :            :         fsparam_string("fsc",         Opt_fscache),
     131                 :            :         fsparam_flag  ("hard",                Opt_hard),
     132                 :            :         __fsparam(NULL, "intr",               Opt_intr,
     133                 :            :                   fs_param_neg_with_no|fs_param_deprecated, NULL),
     134                 :            :         fsparam_enum  ("local_lock",  Opt_local_lock, nfs_param_enums_local_lock),
     135                 :            :         fsparam_flag_no("lock",               Opt_lock),
     136                 :            :         fsparam_enum  ("lookupcache", Opt_lookupcache, nfs_param_enums_lookupcache),
     137                 :            :         fsparam_flag_no("migration",  Opt_migration),
     138                 :            :         fsparam_u32   ("minorversion",        Opt_minorversion),
     139                 :            :         fsparam_string("mountaddr",   Opt_mountaddr),
     140                 :            :         fsparam_string("mounthost",   Opt_mounthost),
     141                 :            :         fsparam_u32   ("mountport",   Opt_mountport),
     142                 :            :         fsparam_string("mountproto",  Opt_mountproto),
     143                 :            :         fsparam_u32   ("mountvers",   Opt_mountvers),
     144                 :            :         fsparam_u32   ("namlen",      Opt_namelen),
     145                 :            :         fsparam_u32   ("nconnect",    Opt_nconnect),
     146                 :            :         fsparam_string("nfsvers",     Opt_vers),
     147                 :            :         fsparam_u32   ("port",                Opt_port),
     148                 :            :         fsparam_flag_no("posix",      Opt_posix),
     149                 :            :         fsparam_string("proto",               Opt_proto),
     150                 :            :         fsparam_flag_no("rdirplus",   Opt_rdirplus),
     151                 :            :         fsparam_flag  ("rdma",                Opt_rdma),
     152                 :            :         fsparam_flag_no("resvport",   Opt_resvport),
     153                 :            :         fsparam_u32   ("retrans",     Opt_retrans),
     154                 :            :         fsparam_string("retry",               Opt_retry),
     155                 :            :         fsparam_u32   ("rsize",               Opt_rsize),
     156                 :            :         fsparam_string("sec",         Opt_sec),
     157                 :            :         fsparam_flag_no("sharecache", Opt_sharecache),
     158                 :            :         fsparam_flag  ("sloppy",      Opt_sloppy),
     159                 :            :         fsparam_flag  ("soft",                Opt_soft),
     160                 :            :         fsparam_flag  ("softerr",     Opt_softerr),
     161                 :            :         fsparam_flag  ("softreval",   Opt_softreval),
     162                 :            :         fsparam_string("source",      Opt_source),
     163                 :            :         fsparam_flag  ("tcp",         Opt_tcp),
     164                 :            :         fsparam_u32   ("timeo",               Opt_timeo),
     165                 :            :         fsparam_flag  ("udp",         Opt_udp),
     166                 :            :         fsparam_flag  ("v2",          Opt_v),
     167                 :            :         fsparam_flag  ("v3",          Opt_v),
     168                 :            :         fsparam_flag  ("v4",          Opt_v),
     169                 :            :         fsparam_flag  ("v4.0",                Opt_v),
     170                 :            :         fsparam_flag  ("v4.1",                Opt_v),
     171                 :            :         fsparam_flag  ("v4.2",                Opt_v),
     172                 :            :         fsparam_string("vers",                Opt_vers),
     173                 :            :         fsparam_u32   ("wsize",               Opt_wsize),
     174                 :            :         {}
     175                 :            : };
     176                 :            : 
     177                 :            : enum {
     178                 :            :         Opt_vers_2,
     179                 :            :         Opt_vers_3,
     180                 :            :         Opt_vers_4,
     181                 :            :         Opt_vers_4_0,
     182                 :            :         Opt_vers_4_1,
     183                 :            :         Opt_vers_4_2,
     184                 :            : };
     185                 :            : 
     186                 :            : static const struct constant_table nfs_vers_tokens[] = {
     187                 :            :         { "2",                Opt_vers_2 },
     188                 :            :         { "3",                Opt_vers_3 },
     189                 :            :         { "4",                Opt_vers_4 },
     190                 :            :         { "4.0",      Opt_vers_4_0 },
     191                 :            :         { "4.1",      Opt_vers_4_1 },
     192                 :            :         { "4.2",      Opt_vers_4_2 },
     193                 :            : };
     194                 :            : 
     195                 :            : enum {
     196                 :            :         Opt_xprt_rdma,
     197                 :            :         Opt_xprt_rdma6,
     198                 :            :         Opt_xprt_tcp,
     199                 :            :         Opt_xprt_tcp6,
     200                 :            :         Opt_xprt_udp,
     201                 :            :         Opt_xprt_udp6,
     202                 :            :         nr__Opt_xprt
     203                 :            : };
     204                 :            : 
     205                 :            : static const struct constant_table nfs_xprt_protocol_tokens[nr__Opt_xprt] = {
     206                 :            :         { "rdma",     Opt_xprt_rdma },
     207                 :            :         { "rdma6",    Opt_xprt_rdma6 },
     208                 :            :         { "tcp",      Opt_xprt_tcp },
     209                 :            :         { "tcp6",     Opt_xprt_tcp6 },
     210                 :            :         { "udp",      Opt_xprt_udp },
     211                 :            :         { "udp6",     Opt_xprt_udp6 },
     212                 :            : };
     213                 :            : 
     214                 :            : enum {
     215                 :            :         Opt_sec_krb5,
     216                 :            :         Opt_sec_krb5i,
     217                 :            :         Opt_sec_krb5p,
     218                 :            :         Opt_sec_lkey,
     219                 :            :         Opt_sec_lkeyi,
     220                 :            :         Opt_sec_lkeyp,
     221                 :            :         Opt_sec_none,
     222                 :            :         Opt_sec_spkm,
     223                 :            :         Opt_sec_spkmi,
     224                 :            :         Opt_sec_spkmp,
     225                 :            :         Opt_sec_sys,
     226                 :            :         nr__Opt_sec
     227                 :            : };
     228                 :            : 
     229                 :            : static const struct constant_table nfs_secflavor_tokens[] = {
     230                 :            :         { "krb5",     Opt_sec_krb5 },
     231                 :            :         { "krb5i",    Opt_sec_krb5i },
     232                 :            :         { "krb5p",    Opt_sec_krb5p },
     233                 :            :         { "lkey",     Opt_sec_lkey },
     234                 :            :         { "lkeyi",    Opt_sec_lkeyi },
     235                 :            :         { "lkeyp",    Opt_sec_lkeyp },
     236                 :            :         { "none",     Opt_sec_none },
     237                 :            :         { "null",     Opt_sec_none },
     238                 :            :         { "spkm3",    Opt_sec_spkm },
     239                 :            :         { "spkm3i",   Opt_sec_spkmi },
     240                 :            :         { "spkm3p",   Opt_sec_spkmp },
     241                 :            :         { "sys",      Opt_sec_sys },
     242                 :            : };
     243                 :            : 
     244                 :            : /*
     245                 :            :  * Sanity-check a server address provided by the mount command.
     246                 :            :  *
     247                 :            :  * Address family must be initialized, and address must not be
     248                 :            :  * the ANY address for that family.
     249                 :            :  */
     250                 :          0 : static int nfs_verify_server_address(struct sockaddr *addr)
     251                 :            : {
     252                 :          0 :         switch (addr->sa_family) {
     253                 :          0 :         case AF_INET: {
     254                 :          0 :                 struct sockaddr_in *sa = (struct sockaddr_in *)addr;
     255                 :          0 :                 return sa->sin_addr.s_addr != htonl(INADDR_ANY);
     256                 :            :         }
     257                 :          0 :         case AF_INET6: {
     258                 :          0 :                 struct in6_addr *sa = &((struct sockaddr_in6 *)addr)->sin6_addr;
     259                 :          0 :                 return !ipv6_addr_any(sa);
     260                 :            :         }
     261                 :            :         }
     262                 :            : 
     263                 :            :         dfprintk(MOUNT, "NFS: Invalid IP address specified\n");
     264                 :            :         return 0;
     265                 :            : }
     266                 :            : 
     267                 :            : /*
     268                 :            :  * Sanity check the NFS transport protocol.
     269                 :            :  *
     270                 :            :  */
     271                 :          0 : static void nfs_validate_transport_protocol(struct nfs_fs_context *ctx)
     272                 :            : {
     273                 :          0 :         switch (ctx->nfs_server.protocol) {
     274                 :            :         case XPRT_TRANSPORT_UDP:
     275                 :            :         case XPRT_TRANSPORT_TCP:
     276                 :            :         case XPRT_TRANSPORT_RDMA:
     277                 :            :                 break;
     278                 :          0 :         default:
     279                 :          0 :                 ctx->nfs_server.protocol = XPRT_TRANSPORT_TCP;
     280                 :            :         }
     281                 :            : }
     282                 :            : 
     283                 :            : /*
     284                 :            :  * For text based NFSv2/v3 mounts, the mount protocol transport default
     285                 :            :  * settings should depend upon the specified NFS transport.
     286                 :            :  */
     287                 :          0 : static void nfs_set_mount_transport_protocol(struct nfs_fs_context *ctx)
     288                 :            : {
     289         [ #  # ]:          0 :         nfs_validate_transport_protocol(ctx);
     290                 :            : 
     291         [ #  # ]:          0 :         if (ctx->mount_server.protocol == XPRT_TRANSPORT_UDP ||
     292                 :            :             ctx->mount_server.protocol == XPRT_TRANSPORT_TCP)
     293                 :            :                         return;
     294      [ #  #  # ]:          0 :         switch (ctx->nfs_server.protocol) {
     295                 :          0 :         case XPRT_TRANSPORT_UDP:
     296                 :          0 :                 ctx->mount_server.protocol = XPRT_TRANSPORT_UDP;
     297                 :          0 :                 break;
     298                 :          0 :         case XPRT_TRANSPORT_TCP:
     299                 :            :         case XPRT_TRANSPORT_RDMA:
     300                 :          0 :                 ctx->mount_server.protocol = XPRT_TRANSPORT_TCP;
     301                 :            :         }
     302                 :          0 : }
     303                 :            : 
     304                 :            : /*
     305                 :            :  * Add 'flavor' to 'auth_info' if not already present.
     306                 :            :  * Returns true if 'flavor' ends up in the list, false otherwise
     307                 :            :  */
     308                 :            : static int nfs_auth_info_add(struct fs_context *fc,
     309                 :            :                              struct nfs_auth_info *auth_info,
     310                 :            :                              rpc_authflavor_t flavor)
     311                 :            : {
     312                 :            :         unsigned int i;
     313                 :            :         unsigned int max_flavor_len = ARRAY_SIZE(auth_info->flavors);
     314                 :            : 
     315                 :            :         /* make sure this flavor isn't already in the list */
     316                 :            :         for (i = 0; i < auth_info->flavor_len; i++) {
     317                 :            :                 if (flavor == auth_info->flavors[i])
     318                 :            :                         return 0;
     319                 :            :         }
     320                 :            : 
     321                 :            :         if (auth_info->flavor_len + 1 >= max_flavor_len)
     322                 :            :                 return nfs_invalf(fc, "NFS: too many sec= flavors");
     323                 :            : 
     324                 :            :         auth_info->flavors[auth_info->flavor_len++] = flavor;
     325                 :            :         return 0;
     326                 :            : }
     327                 :            : 
     328                 :            : /*
     329                 :            :  * Parse the value of the 'sec=' option.
     330                 :            :  */
     331                 :            : static int nfs_parse_security_flavors(struct fs_context *fc,
     332                 :            :                                       struct fs_parameter *param)
     333                 :            : {
     334                 :            :         struct nfs_fs_context *ctx = nfs_fc2context(fc);
     335                 :            :         rpc_authflavor_t pseudoflavor;
     336                 :            :         char *string = param->string, *p;
     337                 :            :         int ret;
     338                 :            : 
     339                 :            :         dfprintk(MOUNT, "NFS: parsing %s=%s option\n", param->key, param->string);
     340                 :            : 
     341                 :            :         while ((p = strsep(&string, ":")) != NULL) {
     342                 :            :                 if (!*p)
     343                 :            :                         continue;
     344                 :            :                 switch (lookup_constant(nfs_secflavor_tokens, p, -1)) {
     345                 :            :                 case Opt_sec_none:
     346                 :            :                         pseudoflavor = RPC_AUTH_NULL;
     347                 :            :                         break;
     348                 :            :                 case Opt_sec_sys:
     349                 :            :                         pseudoflavor = RPC_AUTH_UNIX;
     350                 :            :                         break;
     351                 :            :                 case Opt_sec_krb5:
     352                 :            :                         pseudoflavor = RPC_AUTH_GSS_KRB5;
     353                 :            :                         break;
     354                 :            :                 case Opt_sec_krb5i:
     355                 :            :                         pseudoflavor = RPC_AUTH_GSS_KRB5I;
     356                 :            :                         break;
     357                 :            :                 case Opt_sec_krb5p:
     358                 :            :                         pseudoflavor = RPC_AUTH_GSS_KRB5P;
     359                 :            :                         break;
     360                 :            :                 case Opt_sec_lkey:
     361                 :            :                         pseudoflavor = RPC_AUTH_GSS_LKEY;
     362                 :            :                         break;
     363                 :            :                 case Opt_sec_lkeyi:
     364                 :            :                         pseudoflavor = RPC_AUTH_GSS_LKEYI;
     365                 :            :                         break;
     366                 :            :                 case Opt_sec_lkeyp:
     367                 :            :                         pseudoflavor = RPC_AUTH_GSS_LKEYP;
     368                 :            :                         break;
     369                 :            :                 case Opt_sec_spkm:
     370                 :            :                         pseudoflavor = RPC_AUTH_GSS_SPKM;
     371                 :            :                         break;
     372                 :            :                 case Opt_sec_spkmi:
     373                 :            :                         pseudoflavor = RPC_AUTH_GSS_SPKMI;
     374                 :            :                         break;
     375                 :            :                 case Opt_sec_spkmp:
     376                 :            :                         pseudoflavor = RPC_AUTH_GSS_SPKMP;
     377                 :            :                         break;
     378                 :            :                 default:
     379                 :            :                         return nfs_invalf(fc, "NFS: sec=%s option not recognized", p);
     380                 :            :                 }
     381                 :            : 
     382                 :            :                 ret = nfs_auth_info_add(fc, &ctx->auth_info, pseudoflavor);
     383                 :            :                 if (ret < 0)
     384                 :            :                         return ret;
     385                 :            :         }
     386                 :            : 
     387                 :            :         return 0;
     388                 :            : }
     389                 :            : 
     390                 :          0 : static int nfs_parse_version_string(struct fs_context *fc,
     391                 :            :                                     const char *string)
     392                 :            : {
     393                 :          0 :         struct nfs_fs_context *ctx = nfs_fc2context(fc);
     394                 :            : 
     395                 :          0 :         ctx->flags &= ~NFS_MOUNT_VER3;
     396   [ #  #  #  #  :          0 :         switch (lookup_constant(nfs_vers_tokens, string, -1)) {
                #  #  # ]
     397                 :          0 :         case Opt_vers_2:
     398                 :          0 :                 ctx->version = 2;
     399                 :          0 :                 break;
     400                 :          0 :         case Opt_vers_3:
     401                 :          0 :                 ctx->flags |= NFS_MOUNT_VER3;
     402                 :          0 :                 ctx->version = 3;
     403                 :          0 :                 break;
     404                 :          0 :         case Opt_vers_4:
     405                 :            :                 /* Backward compatibility option. In future,
     406                 :            :                  * the mount program should always supply
     407                 :            :                  * a NFSv4 minor version number.
     408                 :            :                  */
     409                 :          0 :                 ctx->version = 4;
     410                 :          0 :                 break;
     411                 :          0 :         case Opt_vers_4_0:
     412                 :          0 :                 ctx->version = 4;
     413                 :          0 :                 ctx->minorversion = 0;
     414                 :          0 :                 break;
     415                 :          0 :         case Opt_vers_4_1:
     416                 :          0 :                 ctx->version = 4;
     417                 :          0 :                 ctx->minorversion = 1;
     418                 :          0 :                 break;
     419                 :          0 :         case Opt_vers_4_2:
     420                 :          0 :                 ctx->version = 4;
     421                 :          0 :                 ctx->minorversion = 2;
     422                 :          0 :                 break;
     423                 :          0 :         default:
     424                 :          0 :                 return nfs_invalf(fc, "NFS: Unsupported NFS version");
     425                 :            :         }
     426                 :            :         return 0;
     427                 :            : }
     428                 :            : 
     429                 :            : /*
     430                 :            :  * Parse a single mount parameter.
     431                 :            :  */
     432                 :          0 : static int nfs_fs_context_parse_param(struct fs_context *fc,
     433                 :            :                                       struct fs_parameter *param)
     434                 :            : {
     435                 :          0 :         struct fs_parse_result result;
     436                 :          0 :         struct nfs_fs_context *ctx = nfs_fc2context(fc);
     437                 :          0 :         unsigned short protofamily, mountfamily;
     438                 :          0 :         unsigned int len;
     439                 :          0 :         int ret, opt;
     440                 :            : 
     441                 :          0 :         dfprintk(MOUNT, "NFS:   parsing nfs mount option '%s'\n", param->key);
     442                 :            : 
     443                 :          0 :         opt = fs_parse(fc, nfs_fs_parameters, param, &result);
     444         [ #  # ]:          0 :         if (opt < 0)
     445         [ #  # ]:          0 :                 return ctx->sloppy ? 1 : opt;
     446                 :            : 
     447   [ #  #  #  #  :          0 :         switch (opt) {
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
     448                 :          0 :         case Opt_source:
     449         [ #  # ]:          0 :                 if (fc->source)
     450                 :          0 :                         return nfs_invalf(fc, "NFS: Multiple sources not supported");
     451                 :          0 :                 fc->source = param->string;
     452                 :          0 :                 param->string = NULL;
     453                 :          0 :                 break;
     454                 :            : 
     455                 :            :                 /*
     456                 :            :                  * boolean options:  foo/nofoo
     457                 :            :                  */
     458                 :          0 :         case Opt_soft:
     459                 :          0 :                 ctx->flags |= NFS_MOUNT_SOFT;
     460                 :          0 :                 ctx->flags &= ~NFS_MOUNT_SOFTERR;
     461                 :          0 :                 break;
     462                 :          0 :         case Opt_softerr:
     463                 :          0 :                 ctx->flags |= NFS_MOUNT_SOFTERR | NFS_MOUNT_SOFTREVAL;
     464                 :          0 :                 ctx->flags &= ~NFS_MOUNT_SOFT;
     465                 :          0 :                 break;
     466                 :          0 :         case Opt_hard:
     467                 :          0 :                 ctx->flags &= ~(NFS_MOUNT_SOFT |
     468                 :            :                                 NFS_MOUNT_SOFTERR |
     469                 :            :                                 NFS_MOUNT_SOFTREVAL);
     470                 :          0 :                 break;
     471                 :          0 :         case Opt_softreval:
     472         [ #  # ]:          0 :                 if (result.negated)
     473                 :          0 :                         ctx->flags &= ~NFS_MOUNT_SOFTREVAL;
     474                 :            :                 else
     475                 :          0 :                         ctx->flags &= NFS_MOUNT_SOFTREVAL;
     476                 :            :                 break;
     477                 :          0 :         case Opt_posix:
     478         [ #  # ]:          0 :                 if (result.negated)
     479                 :          0 :                         ctx->flags &= ~NFS_MOUNT_POSIX;
     480                 :            :                 else
     481                 :          0 :                         ctx->flags |= NFS_MOUNT_POSIX;
     482                 :            :                 break;
     483                 :          0 :         case Opt_cto:
     484         [ #  # ]:          0 :                 if (result.negated)
     485                 :          0 :                         ctx->flags |= NFS_MOUNT_NOCTO;
     486                 :            :                 else
     487                 :          0 :                         ctx->flags &= ~NFS_MOUNT_NOCTO;
     488                 :            :                 break;
     489                 :          0 :         case Opt_ac:
     490         [ #  # ]:          0 :                 if (result.negated)
     491                 :          0 :                         ctx->flags |= NFS_MOUNT_NOAC;
     492                 :            :                 else
     493                 :          0 :                         ctx->flags &= ~NFS_MOUNT_NOAC;
     494                 :            :                 break;
     495                 :          0 :         case Opt_lock:
     496         [ #  # ]:          0 :                 if (result.negated) {
     497                 :          0 :                         ctx->flags |= NFS_MOUNT_NONLM;
     498                 :          0 :                         ctx->flags |= (NFS_MOUNT_LOCAL_FLOCK | NFS_MOUNT_LOCAL_FCNTL);
     499                 :            :                 } else {
     500                 :          0 :                         ctx->flags &= ~NFS_MOUNT_NONLM;
     501                 :          0 :                         ctx->flags &= ~(NFS_MOUNT_LOCAL_FLOCK | NFS_MOUNT_LOCAL_FCNTL);
     502                 :            :                 }
     503                 :            :                 break;
     504                 :          0 :         case Opt_udp:
     505                 :          0 :                 ctx->flags &= ~NFS_MOUNT_TCP;
     506                 :          0 :                 ctx->nfs_server.protocol = XPRT_TRANSPORT_UDP;
     507                 :          0 :                 break;
     508                 :          0 :         case Opt_tcp:
     509                 :          0 :                 ctx->flags |= NFS_MOUNT_TCP;
     510                 :          0 :                 ctx->nfs_server.protocol = XPRT_TRANSPORT_TCP;
     511                 :          0 :                 break;
     512                 :          0 :         case Opt_rdma:
     513                 :          0 :                 ctx->flags |= NFS_MOUNT_TCP; /* for side protocols */
     514                 :          0 :                 ctx->nfs_server.protocol = XPRT_TRANSPORT_RDMA;
     515                 :          0 :                 xprt_load_transport(param->key);
     516                 :          0 :                 break;
     517                 :          0 :         case Opt_acl:
     518         [ #  # ]:          0 :                 if (result.negated)
     519                 :          0 :                         ctx->flags |= NFS_MOUNT_NOACL;
     520                 :            :                 else
     521                 :          0 :                         ctx->flags &= ~NFS_MOUNT_NOACL;
     522                 :            :                 break;
     523                 :          0 :         case Opt_rdirplus:
     524         [ #  # ]:          0 :                 if (result.negated)
     525                 :          0 :                         ctx->flags |= NFS_MOUNT_NORDIRPLUS;
     526                 :            :                 else
     527                 :          0 :                         ctx->flags &= ~NFS_MOUNT_NORDIRPLUS;
     528                 :            :                 break;
     529                 :          0 :         case Opt_sharecache:
     530         [ #  # ]:          0 :                 if (result.negated)
     531                 :          0 :                         ctx->flags |= NFS_MOUNT_UNSHARED;
     532                 :            :                 else
     533                 :          0 :                         ctx->flags &= ~NFS_MOUNT_UNSHARED;
     534                 :            :                 break;
     535                 :          0 :         case Opt_resvport:
     536         [ #  # ]:          0 :                 if (result.negated)
     537                 :          0 :                         ctx->flags |= NFS_MOUNT_NORESVPORT;
     538                 :            :                 else
     539                 :          0 :                         ctx->flags &= ~NFS_MOUNT_NORESVPORT;
     540                 :            :                 break;
     541                 :          0 :         case Opt_fscache_flag:
     542         [ #  # ]:          0 :                 if (result.negated)
     543                 :          0 :                         ctx->options &= ~NFS_OPTION_FSCACHE;
     544                 :            :                 else
     545                 :          0 :                         ctx->options |= NFS_OPTION_FSCACHE;
     546                 :          0 :                 kfree(ctx->fscache_uniq);
     547                 :          0 :                 ctx->fscache_uniq = NULL;
     548                 :          0 :                 break;
     549                 :          0 :         case Opt_fscache:
     550                 :          0 :                 ctx->options |= NFS_OPTION_FSCACHE;
     551                 :          0 :                 kfree(ctx->fscache_uniq);
     552                 :          0 :                 ctx->fscache_uniq = param->string;
     553                 :          0 :                 param->string = NULL;
     554                 :          0 :                 break;
     555                 :          0 :         case Opt_migration:
     556         [ #  # ]:          0 :                 if (result.negated)
     557                 :          0 :                         ctx->options &= ~NFS_OPTION_MIGRATION;
     558                 :            :                 else
     559                 :          0 :                         ctx->options |= NFS_OPTION_MIGRATION;
     560                 :            :                 break;
     561                 :            : 
     562                 :            :                 /*
     563                 :            :                  * options that take numeric values
     564                 :            :                  */
     565                 :          0 :         case Opt_port:
     566         [ #  # ]:          0 :                 if (result.uint_32 > USHRT_MAX)
     567                 :          0 :                         goto out_of_bounds;
     568                 :          0 :                 ctx->nfs_server.port = result.uint_32;
     569                 :          0 :                 break;
     570                 :          0 :         case Opt_rsize:
     571                 :          0 :                 ctx->rsize = result.uint_32;
     572                 :          0 :                 break;
     573                 :          0 :         case Opt_wsize:
     574                 :          0 :                 ctx->wsize = result.uint_32;
     575                 :          0 :                 break;
     576                 :          0 :         case Opt_bsize:
     577                 :          0 :                 ctx->bsize = result.uint_32;
     578                 :          0 :                 break;
     579                 :          0 :         case Opt_timeo:
     580         [ #  # ]:          0 :                 if (result.uint_32 < 1 || result.uint_32 > INT_MAX)
     581                 :          0 :                         goto out_of_bounds;
     582                 :          0 :                 ctx->timeo = result.uint_32;
     583                 :          0 :                 break;
     584                 :          0 :         case Opt_retrans:
     585         [ #  # ]:          0 :                 if (result.uint_32 > INT_MAX)
     586                 :          0 :                         goto out_of_bounds;
     587                 :          0 :                 ctx->retrans = result.uint_32;
     588                 :          0 :                 break;
     589                 :          0 :         case Opt_acregmin:
     590                 :          0 :                 ctx->acregmin = result.uint_32;
     591                 :          0 :                 break;
     592                 :          0 :         case Opt_acregmax:
     593                 :          0 :                 ctx->acregmax = result.uint_32;
     594                 :          0 :                 break;
     595                 :          0 :         case Opt_acdirmin:
     596                 :          0 :                 ctx->acdirmin = result.uint_32;
     597                 :          0 :                 break;
     598                 :          0 :         case Opt_acdirmax:
     599                 :          0 :                 ctx->acdirmax = result.uint_32;
     600                 :          0 :                 break;
     601                 :          0 :         case Opt_actimeo:
     602                 :          0 :                 ctx->acregmin = result.uint_32;
     603                 :          0 :                 ctx->acregmax = result.uint_32;
     604                 :          0 :                 ctx->acdirmin = result.uint_32;
     605                 :          0 :                 ctx->acdirmax = result.uint_32;
     606                 :          0 :                 break;
     607                 :          0 :         case Opt_namelen:
     608                 :          0 :                 ctx->namlen = result.uint_32;
     609                 :          0 :                 break;
     610                 :          0 :         case Opt_mountport:
     611         [ #  # ]:          0 :                 if (result.uint_32 > USHRT_MAX)
     612                 :          0 :                         goto out_of_bounds;
     613                 :          0 :                 ctx->mount_server.port = result.uint_32;
     614                 :          0 :                 break;
     615                 :          0 :         case Opt_mountvers:
     616         [ #  # ]:          0 :                 if (result.uint_32 < NFS_MNT_VERSION ||
     617                 :            :                     result.uint_32 > NFS_MNT3_VERSION)
     618                 :          0 :                         goto out_of_bounds;
     619                 :          0 :                 ctx->mount_server.version = result.uint_32;
     620                 :          0 :                 break;
     621                 :          0 :         case Opt_minorversion:
     622         [ #  # ]:          0 :                 if (result.uint_32 > NFS4_MAX_MINOR_VERSION)
     623                 :          0 :                         goto out_of_bounds;
     624                 :          0 :                 ctx->minorversion = result.uint_32;
     625                 :          0 :                 break;
     626                 :            : 
     627                 :            :                 /*
     628                 :            :                  * options that take text values
     629                 :            :                  */
     630                 :          0 :         case Opt_v:
     631                 :          0 :                 ret = nfs_parse_version_string(fc, param->key + 1);
     632                 :          0 :                 if (ret < 0)
     633                 :            :                         return ret;
     634                 :            :                 break;
     635                 :          0 :         case Opt_vers:
     636                 :          0 :                 ret = nfs_parse_version_string(fc, param->string);
     637                 :          0 :                 if (ret < 0)
     638                 :            :                         return ret;
     639                 :            :                 break;
     640                 :          0 :         case Opt_sec:
     641                 :          0 :                 ret = nfs_parse_security_flavors(fc, param);
     642                 :          0 :                 if (ret < 0)
     643                 :            :                         return ret;
     644                 :            :                 break;
     645                 :            : 
     646                 :          0 :         case Opt_proto:
     647                 :          0 :                 protofamily = AF_INET;
     648                 :          0 :                 switch (lookup_constant(nfs_xprt_protocol_tokens, param->string, -1)) {
     649                 :          0 :                 case Opt_xprt_udp6:
     650                 :          0 :                         protofamily = AF_INET6;
     651                 :            :                         /* fall through */
     652                 :          0 :                 case Opt_xprt_udp:
     653                 :          0 :                         ctx->flags &= ~NFS_MOUNT_TCP;
     654                 :          0 :                         ctx->nfs_server.protocol = XPRT_TRANSPORT_UDP;
     655                 :          0 :                         break;
     656                 :          0 :                 case Opt_xprt_tcp6:
     657                 :          0 :                         protofamily = AF_INET6;
     658                 :            :                         /* fall through */
     659                 :          0 :                 case Opt_xprt_tcp:
     660                 :          0 :                         ctx->flags |= NFS_MOUNT_TCP;
     661                 :          0 :                         ctx->nfs_server.protocol = XPRT_TRANSPORT_TCP;
     662                 :          0 :                         break;
     663                 :          0 :                 case Opt_xprt_rdma6:
     664                 :          0 :                         protofamily = AF_INET6;
     665                 :            :                         /* fall through */
     666                 :          0 :                 case Opt_xprt_rdma:
     667                 :            :                         /* vector side protocols to TCP */
     668                 :          0 :                         ctx->flags |= NFS_MOUNT_TCP;
     669                 :          0 :                         ctx->nfs_server.protocol = XPRT_TRANSPORT_RDMA;
     670                 :          0 :                         xprt_load_transport(param->string);
     671                 :          0 :                         break;
     672                 :          0 :                 default:
     673                 :          0 :                         return nfs_invalf(fc, "NFS: Unrecognized transport protocol");
     674                 :            :                 }
     675                 :            : 
     676                 :          0 :                 ctx->protofamily = protofamily;
     677                 :          0 :                 break;
     678                 :            : 
     679                 :          0 :         case Opt_mountproto:
     680                 :          0 :                 mountfamily = AF_INET;
     681                 :          0 :                 switch (lookup_constant(nfs_xprt_protocol_tokens, param->string, -1)) {
     682                 :          0 :                 case Opt_xprt_udp6:
     683                 :          0 :                         mountfamily = AF_INET6;
     684                 :            :                         /* fall through */
     685                 :          0 :                 case Opt_xprt_udp:
     686                 :          0 :                         ctx->mount_server.protocol = XPRT_TRANSPORT_UDP;
     687                 :          0 :                         break;
     688                 :          0 :                 case Opt_xprt_tcp6:
     689                 :          0 :                         mountfamily = AF_INET6;
     690                 :            :                         /* fall through */
     691                 :          0 :                 case Opt_xprt_tcp:
     692                 :          0 :                         ctx->mount_server.protocol = XPRT_TRANSPORT_TCP;
     693                 :          0 :                         break;
     694                 :          0 :                 case Opt_xprt_rdma: /* not used for side protocols */
     695                 :            :                 default:
     696                 :          0 :                         return nfs_invalf(fc, "NFS: Unrecognized transport protocol");
     697                 :            :                 }
     698                 :          0 :                 ctx->mountfamily = mountfamily;
     699                 :          0 :                 break;
     700                 :            : 
     701                 :          0 :         case Opt_addr:
     702                 :          0 :                 len = rpc_pton(fc->net_ns, param->string, param->size,
     703                 :            :                                &ctx->nfs_server.address,
     704                 :            :                                sizeof(ctx->nfs_server._address));
     705         [ #  # ]:          0 :                 if (len == 0)
     706                 :          0 :                         goto out_invalid_address;
     707                 :          0 :                 ctx->nfs_server.addrlen = len;
     708                 :          0 :                 break;
     709                 :          0 :         case Opt_clientaddr:
     710                 :          0 :                 kfree(ctx->client_address);
     711                 :          0 :                 ctx->client_address = param->string;
     712                 :          0 :                 param->string = NULL;
     713                 :          0 :                 break;
     714                 :          0 :         case Opt_mounthost:
     715                 :          0 :                 kfree(ctx->mount_server.hostname);
     716                 :          0 :                 ctx->mount_server.hostname = param->string;
     717                 :          0 :                 param->string = NULL;
     718                 :          0 :                 break;
     719                 :          0 :         case Opt_mountaddr:
     720                 :          0 :                 len = rpc_pton(fc->net_ns, param->string, param->size,
     721                 :            :                                &ctx->mount_server.address,
     722                 :            :                                sizeof(ctx->mount_server._address));
     723         [ #  # ]:          0 :                 if (len == 0)
     724                 :          0 :                         goto out_invalid_address;
     725                 :          0 :                 ctx->mount_server.addrlen = len;
     726                 :          0 :                 break;
     727                 :          0 :         case Opt_nconnect:
     728         [ #  # ]:          0 :                 if (result.uint_32 < 1 || result.uint_32 > NFS_MAX_CONNECTIONS)
     729                 :          0 :                         goto out_of_bounds;
     730                 :          0 :                 ctx->nfs_server.nconnect = result.uint_32;
     731                 :          0 :                 break;
     732                 :          0 :         case Opt_lookupcache:
     733   [ #  #  #  # ]:          0 :                 switch (result.uint_32) {
     734                 :          0 :                 case Opt_lookupcache_all:
     735                 :          0 :                         ctx->flags &= ~(NFS_MOUNT_LOOKUP_CACHE_NONEG|NFS_MOUNT_LOOKUP_CACHE_NONE);
     736                 :          0 :                         break;
     737                 :          0 :                 case Opt_lookupcache_positive:
     738                 :          0 :                         ctx->flags &= ~NFS_MOUNT_LOOKUP_CACHE_NONE;
     739                 :          0 :                         ctx->flags |= NFS_MOUNT_LOOKUP_CACHE_NONEG;
     740                 :          0 :                         break;
     741                 :          0 :                 case Opt_lookupcache_none:
     742                 :          0 :                         ctx->flags |= NFS_MOUNT_LOOKUP_CACHE_NONEG|NFS_MOUNT_LOOKUP_CACHE_NONE;
     743                 :          0 :                         break;
     744                 :          0 :                 default:
     745                 :          0 :                         goto out_invalid_value;
     746                 :            :                 }
     747                 :            :                 break;
     748                 :          0 :         case Opt_local_lock:
     749   [ #  #  #  #  :          0 :                 switch (result.uint_32) {
                      # ]
     750                 :          0 :                 case Opt_local_lock_all:
     751                 :          0 :                         ctx->flags |= (NFS_MOUNT_LOCAL_FLOCK |
     752                 :            :                                        NFS_MOUNT_LOCAL_FCNTL);
     753                 :          0 :                         break;
     754                 :          0 :                 case Opt_local_lock_flock:
     755                 :          0 :                         ctx->flags |= NFS_MOUNT_LOCAL_FLOCK;
     756                 :          0 :                         break;
     757                 :          0 :                 case Opt_local_lock_posix:
     758                 :          0 :                         ctx->flags |= NFS_MOUNT_LOCAL_FCNTL;
     759                 :          0 :                         break;
     760                 :          0 :                 case Opt_local_lock_none:
     761                 :          0 :                         ctx->flags &= ~(NFS_MOUNT_LOCAL_FLOCK |
     762                 :            :                                         NFS_MOUNT_LOCAL_FCNTL);
     763                 :          0 :                         break;
     764                 :          0 :                 default:
     765                 :          0 :                         goto out_invalid_value;
     766                 :            :                 }
     767                 :            :                 break;
     768                 :            : 
     769                 :            :                 /*
     770                 :            :                  * Special options
     771                 :            :                  */
     772                 :          0 :         case Opt_sloppy:
     773                 :          0 :                 ctx->sloppy = true;
     774                 :          0 :                 dfprintk(MOUNT, "NFS:   relaxing parsing rules\n");
     775                 :          0 :                 break;
     776                 :            :         }
     777                 :            : 
     778                 :            :         return 0;
     779                 :            : 
     780                 :          0 : out_invalid_value:
     781                 :          0 :         return nfs_invalf(fc, "NFS: Bad mount option value specified");
     782                 :          0 : out_invalid_address:
     783                 :          0 :         return nfs_invalf(fc, "NFS: Bad IP address specified");
     784                 :          0 : out_of_bounds:
     785                 :          0 :         return nfs_invalf(fc, "NFS: Value for '%s' out of range", param->key);
     786                 :            : }
     787                 :            : 
     788                 :            : /*
     789                 :            :  * Split fc->source into "hostname:export_path".
     790                 :            :  *
     791                 :            :  * The leftmost colon demarks the split between the server's hostname
     792                 :            :  * and the export path.  If the hostname starts with a left square
     793                 :            :  * bracket, then it may contain colons.
     794                 :            :  *
     795                 :            :  * Note: caller frees hostname and export path, even on error.
     796                 :            :  */
     797                 :          0 : static int nfs_parse_source(struct fs_context *fc,
     798                 :            :                             size_t maxnamlen, size_t maxpathlen)
     799                 :            : {
     800         [ #  # ]:          0 :         struct nfs_fs_context *ctx = nfs_fc2context(fc);
     801                 :          0 :         const char *dev_name = fc->source;
     802                 :          0 :         size_t len;
     803                 :          0 :         const char *end;
     804                 :            : 
     805   [ #  #  #  # ]:          0 :         if (unlikely(!dev_name || !*dev_name)) {
     806                 :            :                 dfprintk(MOUNT, "NFS: device name not specified\n");
     807                 :            :                 return -EINVAL;
     808                 :            :         }
     809                 :            : 
     810                 :            :         /* Is the host name protected with square brakcets? */
     811         [ #  # ]:          0 :         if (*dev_name == '[') {
     812                 :          0 :                 end = strchr(++dev_name, ']');
     813   [ #  #  #  # ]:          0 :                 if (end == NULL || end[1] != ':')
     814                 :          0 :                         goto out_bad_devname;
     815                 :            : 
     816                 :          0 :                 len = end - dev_name;
     817                 :          0 :                 end++;
     818                 :            :         } else {
     819                 :          0 :                 const char *comma;
     820                 :            : 
     821                 :          0 :                 end = strchr(dev_name, ':');
     822         [ #  # ]:          0 :                 if (end == NULL)
     823                 :          0 :                         goto out_bad_devname;
     824                 :          0 :                 len = end - dev_name;
     825                 :            : 
     826                 :            :                 /* kill possible hostname list: not supported */
     827                 :          0 :                 comma = memchr(dev_name, ',', len);
     828         [ #  # ]:          0 :                 if (comma)
     829                 :          0 :                         len = comma - dev_name;
     830                 :            :         }
     831                 :            : 
     832         [ #  # ]:          0 :         if (len > maxnamlen)
     833                 :          0 :                 goto out_hostname;
     834                 :            : 
     835                 :          0 :         kfree(ctx->nfs_server.hostname);
     836                 :            : 
     837                 :            :         /* N.B. caller will free nfs_server.hostname in all cases */
     838                 :          0 :         ctx->nfs_server.hostname = kmemdup_nul(dev_name, len, GFP_KERNEL);
     839         [ #  # ]:          0 :         if (!ctx->nfs_server.hostname)
     840                 :          0 :                 goto out_nomem;
     841                 :          0 :         len = strlen(++end);
     842         [ #  # ]:          0 :         if (len > maxpathlen)
     843                 :          0 :                 goto out_path;
     844                 :          0 :         ctx->nfs_server.export_path = kmemdup_nul(end, len, GFP_KERNEL);
     845         [ #  # ]:          0 :         if (!ctx->nfs_server.export_path)
     846                 :          0 :                 goto out_nomem;
     847                 :            : 
     848                 :            :         dfprintk(MOUNT, "NFS: MNTPATH: '%s'\n", ctx->nfs_server.export_path);
     849                 :            :         return 0;
     850                 :            : 
     851                 :          0 : out_bad_devname:
     852                 :          0 :         return nfs_invalf(fc, "NFS: device name not in host:path format");
     853                 :          0 : out_nomem:
     854                 :          0 :         nfs_errorf(fc, "NFS: not enough memory to parse device name");
     855                 :          0 :         return -ENOMEM;
     856                 :            : out_hostname:
     857                 :          0 :         nfs_errorf(fc, "NFS: server hostname too long");
     858                 :          0 :         return -ENAMETOOLONG;
     859                 :            : out_path:
     860                 :          0 :         nfs_errorf(fc, "NFS: export pathname too long");
     861                 :          0 :         return -ENAMETOOLONG;
     862                 :            : }
     863                 :            : 
     864                 :          0 : static inline bool is_remount_fc(struct fs_context *fc)
     865                 :            : {
     866                 :          0 :         return fc->root != NULL;
     867                 :            : }
     868                 :            : 
     869                 :            : /*
     870                 :            :  * Parse monolithic NFS2/NFS3 mount data
     871                 :            :  * - fills in the mount root filehandle
     872                 :            :  *
     873                 :            :  * For option strings, user space handles the following behaviors:
     874                 :            :  *
     875                 :            :  * + DNS: mapping server host name to IP address ("addr=" option)
     876                 :            :  *
     877                 :            :  * + failure mode: how to behave if a mount request can't be handled
     878                 :            :  *   immediately ("fg/bg" option)
     879                 :            :  *
     880                 :            :  * + retry: how often to retry a mount request ("retry=" option)
     881                 :            :  *
     882                 :            :  * + breaking back: trying proto=udp after proto=tcp, v2 after v3,
     883                 :            :  *   mountproto=tcp after mountproto=udp, and so on
     884                 :            :  */
     885                 :          0 : static int nfs23_parse_monolithic(struct fs_context *fc,
     886                 :            :                                   struct nfs_mount_data *data)
     887                 :            : {
     888         [ #  # ]:          0 :         struct nfs_fs_context *ctx = nfs_fc2context(fc);
     889                 :          0 :         struct nfs_fh *mntfh = ctx->mntfh;
     890                 :          0 :         struct sockaddr *sap = (struct sockaddr *)&ctx->nfs_server.address;
     891                 :          0 :         int extra_flags = NFS_MOUNT_LEGACY_INTERFACE;
     892                 :            : 
     893         [ #  # ]:          0 :         if (data == NULL)
     894                 :          0 :                 goto out_no_data;
     895                 :            : 
     896                 :          0 :         ctx->version = NFS_DEFAULT_VERSION;
     897   [ #  #  #  #  :          0 :         switch (data->version) {
                #  #  # ]
     898                 :          0 :         case 1:
     899                 :          0 :                 data->namlen = 0; /* fall through */
     900                 :          0 :         case 2:
     901                 :          0 :                 data->bsize = 0; /* fall through */
     902                 :          0 :         case 3:
     903         [ #  # ]:          0 :                 if (data->flags & NFS_MOUNT_VER3)
     904                 :          0 :                         goto out_no_v3;
     905                 :          0 :                 data->root.size = NFS2_FHSIZE;
     906                 :          0 :                 memcpy(data->root.data, data->old_root.data, NFS2_FHSIZE);
     907                 :            :                 /* Turn off security negotiation */
     908                 :          0 :                 extra_flags |= NFS_MOUNT_SECFLAVOUR;
     909                 :            :                 /* fall through */
     910                 :          0 :         case 4:
     911         [ #  # ]:          0 :                 if (data->flags & NFS_MOUNT_SECFLAVOUR)
     912                 :          0 :                         goto out_no_sec;
     913                 :            :                 /* fall through */
     914                 :            :         case 5:
     915                 :          0 :                 memset(data->context, 0, sizeof(data->context));
     916                 :            :                 /* fall through */
     917                 :          0 :         case 6:
     918         [ #  # ]:          0 :                 if (data->flags & NFS_MOUNT_VER3) {
     919         [ #  # ]:          0 :                         if (data->root.size > NFS3_FHSIZE || data->root.size == 0)
     920                 :          0 :                                 goto out_invalid_fh;
     921                 :          0 :                         mntfh->size = data->root.size;
     922                 :          0 :                         ctx->version = 3;
     923                 :            :                 } else {
     924                 :          0 :                         mntfh->size = NFS2_FHSIZE;
     925                 :          0 :                         ctx->version = 2;
     926                 :            :                 }
     927                 :            : 
     928                 :            : 
     929                 :          0 :                 memcpy(mntfh->data, data->root.data, mntfh->size);
     930         [ #  # ]:          0 :                 if (mntfh->size < sizeof(mntfh->data))
     931                 :          0 :                         memset(mntfh->data + mntfh->size, 0,
     932                 :            :                                sizeof(mntfh->data) - mntfh->size);
     933                 :            : 
     934                 :            :                 /*
     935                 :            :                  * Translate to nfs_fs_context, which nfs_fill_super
     936                 :            :                  * can deal with.
     937                 :            :                  */
     938                 :          0 :                 ctx->flags   = data->flags & NFS_MOUNT_FLAGMASK;
     939                 :          0 :                 ctx->flags   |= extra_flags;
     940                 :          0 :                 ctx->rsize   = data->rsize;
     941                 :          0 :                 ctx->wsize   = data->wsize;
     942                 :          0 :                 ctx->timeo   = data->timeo;
     943                 :          0 :                 ctx->retrans = data->retrans;
     944                 :          0 :                 ctx->acregmin        = data->acregmin;
     945                 :          0 :                 ctx->acregmax        = data->acregmax;
     946                 :          0 :                 ctx->acdirmin        = data->acdirmin;
     947                 :          0 :                 ctx->acdirmax        = data->acdirmax;
     948                 :          0 :                 ctx->need_mount      = false;
     949                 :            : 
     950                 :          0 :                 memcpy(sap, &data->addr, sizeof(data->addr));
     951                 :          0 :                 ctx->nfs_server.addrlen = sizeof(data->addr);
     952                 :          0 :                 ctx->nfs_server.port = ntohs(data->addr.sin_port);
     953   [ #  #  #  # ]:          0 :                 if (sap->sa_family != AF_INET ||
     954                 :            :                     !nfs_verify_server_address(sap))
     955                 :          0 :                         goto out_no_address;
     956                 :            : 
     957         [ #  # ]:          0 :                 if (!(data->flags & NFS_MOUNT_TCP))
     958                 :          0 :                         ctx->nfs_server.protocol = XPRT_TRANSPORT_UDP;
     959                 :            :                 /* N.B. caller will free nfs_server.hostname in all cases */
     960                 :          0 :                 ctx->nfs_server.hostname = kstrdup(data->hostname, GFP_KERNEL);
     961         [ #  # ]:          0 :                 if (!ctx->nfs_server.hostname)
     962                 :          0 :                         goto out_nomem;
     963                 :            : 
     964                 :          0 :                 ctx->namlen          = data->namlen;
     965                 :          0 :                 ctx->bsize           = data->bsize;
     966                 :            : 
     967         [ #  # ]:          0 :                 if (data->flags & NFS_MOUNT_SECFLAVOUR)
     968                 :          0 :                         ctx->selected_flavor = data->pseudoflavor;
     969                 :            :                 else
     970                 :          0 :                         ctx->selected_flavor = RPC_AUTH_UNIX;
     971                 :            : 
     972         [ #  # ]:          0 :                 if (!(data->flags & NFS_MOUNT_NONLM))
     973                 :          0 :                         ctx->flags &= ~(NFS_MOUNT_LOCAL_FLOCK|
     974                 :            :                                          NFS_MOUNT_LOCAL_FCNTL);
     975                 :            :                 else
     976                 :          0 :                         ctx->flags |= (NFS_MOUNT_LOCAL_FLOCK|
     977                 :            :                                         NFS_MOUNT_LOCAL_FCNTL);
     978                 :            : 
     979                 :            :                 /*
     980                 :            :                  * The legacy version 6 binary mount data from userspace has a
     981                 :            :                  * field used only to transport selinux information into the
     982                 :            :                  * the kernel.  To continue to support that functionality we
     983                 :            :                  * have a touch of selinux knowledge here in the NFS code. The
     984                 :            :                  * userspace code converted context=blah to just blah so we are
     985                 :            :                  * converting back to the full string selinux understands.
     986                 :            :                  */
     987         [ #  # ]:          0 :                 if (data->context[0]){
     988                 :            : #ifdef CONFIG_SECURITY_SELINUX
     989                 :          0 :                         int ret;
     990                 :            : 
     991                 :          0 :                         data->context[NFS_MAX_CONTEXT_LEN] = '\0';
     992                 :          0 :                         ret = vfs_parse_fs_string(fc, "context",
     993                 :          0 :                                                   data->context, strlen(data->context));
     994         [ #  # ]:          0 :                         if (ret < 0)
     995                 :            :                                 return ret;
     996                 :            : #else
     997                 :            :                         return -EINVAL;
     998                 :            : #endif
     999                 :            :                 }
    1000                 :            : 
    1001                 :          0 :                 break;
    1002                 :          0 :         default:
    1003                 :          0 :                 goto generic;
    1004                 :            :         }
    1005                 :            : 
    1006                 :          0 :         ctx->skip_reconfig_option_check = true;
    1007                 :          0 :         return 0;
    1008                 :            : 
    1009                 :            : generic:
    1010                 :          0 :         return generic_parse_monolithic(fc, data);
    1011                 :            : 
    1012                 :            : out_no_data:
    1013         [ #  # ]:          0 :         if (is_remount_fc(fc)) {
    1014                 :          0 :                 ctx->skip_reconfig_option_check = true;
    1015                 :          0 :                 return 0;
    1016                 :            :         }
    1017                 :          0 :         return nfs_invalf(fc, "NFS: mount program didn't pass any mount data");
    1018                 :            : 
    1019                 :            : out_no_v3:
    1020                 :          0 :         return nfs_invalf(fc, "NFS: nfs_mount_data version does not support v3");
    1021                 :            : 
    1022                 :            : out_no_sec:
    1023                 :          0 :         return nfs_invalf(fc, "NFS: nfs_mount_data version supports only AUTH_SYS");
    1024                 :            : 
    1025                 :            : out_nomem:
    1026                 :          0 :         dfprintk(MOUNT, "NFS: not enough memory to handle mount options");
    1027                 :          0 :         return -ENOMEM;
    1028                 :            : 
    1029                 :            : out_no_address:
    1030                 :          0 :         return nfs_invalf(fc, "NFS: mount program didn't pass remote address");
    1031                 :            : 
    1032                 :            : out_invalid_fh:
    1033                 :          0 :         return nfs_invalf(fc, "NFS: invalid root filehandle");
    1034                 :            : }
    1035                 :            : 
    1036                 :            : #if IS_ENABLED(CONFIG_NFS_V4)
    1037                 :            : /*
    1038                 :            :  * Validate NFSv4 mount options
    1039                 :            :  */
    1040                 :          0 : static int nfs4_parse_monolithic(struct fs_context *fc,
    1041                 :            :                                  struct nfs4_mount_data *data)
    1042                 :            : {
    1043         [ #  # ]:          0 :         struct nfs_fs_context *ctx = nfs_fc2context(fc);
    1044                 :          0 :         struct sockaddr *sap = (struct sockaddr *)&ctx->nfs_server.address;
    1045                 :          0 :         char *c;
    1046                 :            : 
    1047         [ #  # ]:          0 :         if (data == NULL)
    1048                 :          0 :                 goto out_no_data;
    1049                 :            : 
    1050                 :          0 :         ctx->version = 4;
    1051                 :            : 
    1052         [ #  # ]:          0 :         switch (data->version) {
    1053                 :          0 :         case 1:
    1054         [ #  # ]:          0 :                 if (data->host_addrlen > sizeof(ctx->nfs_server.address))
    1055                 :          0 :                         goto out_no_address;
    1056         [ #  # ]:          0 :                 if (data->host_addrlen == 0)
    1057                 :          0 :                         goto out_no_address;
    1058                 :          0 :                 ctx->nfs_server.addrlen = data->host_addrlen;
    1059   [ #  #  #  # ]:          0 :                 if (copy_from_user(sap, data->host_addr, data->host_addrlen))
    1060                 :            :                         return -EFAULT;
    1061   [ #  #  #  #  :          0 :                 if (!nfs_verify_server_address(sap))
                      # ]
    1062                 :          0 :                         goto out_no_address;
    1063                 :          0 :                 ctx->nfs_server.port = ntohs(((struct sockaddr_in *)sap)->sin_port);
    1064                 :            : 
    1065         [ #  # ]:          0 :                 if (data->auth_flavourlen) {
    1066                 :          0 :                         rpc_authflavor_t pseudoflavor;
    1067         [ #  # ]:          0 :                         if (data->auth_flavourlen > 1)
    1068                 :          0 :                                 goto out_inval_auth;
    1069         [ #  # ]:          0 :                         if (copy_from_user(&pseudoflavor,
    1070                 :          0 :                                            data->auth_flavours,
    1071                 :            :                                            sizeof(pseudoflavor)))
    1072                 :          0 :                                 return -EFAULT;
    1073                 :          0 :                         ctx->selected_flavor = pseudoflavor;
    1074                 :            :                 } else
    1075                 :          0 :                         ctx->selected_flavor = RPC_AUTH_UNIX;
    1076                 :            : 
    1077                 :          0 :                 c = strndup_user(data->hostname.data, NFS4_MAXNAMLEN);
    1078         [ #  # ]:          0 :                 if (IS_ERR(c))
    1079                 :          0 :                         return PTR_ERR(c);
    1080                 :          0 :                 ctx->nfs_server.hostname = c;
    1081                 :            : 
    1082                 :          0 :                 c = strndup_user(data->mnt_path.data, NFS4_MAXPATHLEN);
    1083         [ #  # ]:          0 :                 if (IS_ERR(c))
    1084                 :          0 :                         return PTR_ERR(c);
    1085                 :          0 :                 ctx->nfs_server.export_path = c;
    1086                 :          0 :                 dfprintk(MOUNT, "NFS: MNTPATH: '%s'\n", c);
    1087                 :            : 
    1088                 :          0 :                 c = strndup_user(data->client_addr.data, 16);
    1089         [ #  # ]:          0 :                 if (IS_ERR(c))
    1090                 :          0 :                         return PTR_ERR(c);
    1091                 :          0 :                 ctx->client_address = c;
    1092                 :            : 
    1093                 :            :                 /*
    1094                 :            :                  * Translate to nfs_fs_context, which nfs_fill_super
    1095                 :            :                  * can deal with.
    1096                 :            :                  */
    1097                 :            : 
    1098                 :          0 :                 ctx->flags   = data->flags & NFS4_MOUNT_FLAGMASK;
    1099                 :          0 :                 ctx->rsize   = data->rsize;
    1100                 :          0 :                 ctx->wsize   = data->wsize;
    1101                 :          0 :                 ctx->timeo   = data->timeo;
    1102                 :          0 :                 ctx->retrans = data->retrans;
    1103                 :          0 :                 ctx->acregmin        = data->acregmin;
    1104                 :          0 :                 ctx->acregmax        = data->acregmax;
    1105                 :          0 :                 ctx->acdirmin        = data->acdirmin;
    1106                 :          0 :                 ctx->acdirmax        = data->acdirmax;
    1107                 :          0 :                 ctx->nfs_server.protocol = data->proto;
    1108         [ #  # ]:          0 :                 nfs_validate_transport_protocol(ctx);
    1109         [ #  # ]:          0 :                 if (ctx->nfs_server.protocol == XPRT_TRANSPORT_UDP)
    1110                 :          0 :                         goto out_invalid_transport_udp;
    1111                 :            : 
    1112                 :          0 :                 break;
    1113                 :          0 :         default:
    1114                 :          0 :                 goto generic;
    1115                 :            :         }
    1116                 :            : 
    1117                 :          0 :         ctx->skip_reconfig_option_check = true;
    1118                 :          0 :         return 0;
    1119                 :            : 
    1120                 :            : generic:
    1121                 :          0 :         return generic_parse_monolithic(fc, data);
    1122                 :            : 
    1123                 :            : out_no_data:
    1124         [ #  # ]:          0 :         if (is_remount_fc(fc)) {
    1125                 :          0 :                 ctx->skip_reconfig_option_check = true;
    1126                 :          0 :                 return 0;
    1127                 :            :         }
    1128                 :          0 :         return nfs_invalf(fc, "NFS4: mount program didn't pass any mount data");
    1129                 :            : 
    1130                 :            : out_inval_auth:
    1131                 :          0 :         return nfs_invalf(fc, "NFS4: Invalid number of RPC auth flavours %d",
    1132                 :            :                       data->auth_flavourlen);
    1133                 :            : 
    1134                 :          0 : out_no_address:
    1135                 :          0 :         return nfs_invalf(fc, "NFS4: mount program didn't pass remote address");
    1136                 :            : 
    1137                 :            : out_invalid_transport_udp:
    1138                 :          0 :         return nfs_invalf(fc, "NFSv4: Unsupported transport protocol udp");
    1139                 :            : }
    1140                 :            : #endif
    1141                 :            : 
    1142                 :            : /*
    1143                 :            :  * Parse a monolithic block of data from sys_mount().
    1144                 :            :  */
    1145                 :          0 : static int nfs_fs_context_parse_monolithic(struct fs_context *fc,
    1146                 :            :                                            void *data)
    1147                 :            : {
    1148         [ #  # ]:          0 :         if (fc->fs_type == &nfs_fs_type)
    1149                 :          0 :                 return nfs23_parse_monolithic(fc, data);
    1150                 :            : 
    1151                 :            : #if IS_ENABLED(CONFIG_NFS_V4)
    1152         [ #  # ]:          0 :         if (fc->fs_type == &nfs4_fs_type)
    1153                 :          0 :                 return nfs4_parse_monolithic(fc, data);
    1154                 :            : #endif
    1155                 :            : 
    1156                 :          0 :         return nfs_invalf(fc, "NFS: Unsupported monolithic data version");
    1157                 :            : }
    1158                 :            : 
    1159                 :            : /*
    1160                 :            :  * Validate the preparsed information in the config.
    1161                 :            :  */
    1162                 :          0 : static int nfs_fs_context_validate(struct fs_context *fc)
    1163                 :            : {
    1164         [ #  # ]:          0 :         struct nfs_fs_context *ctx = nfs_fc2context(fc);
    1165                 :          0 :         struct nfs_subversion *nfs_mod;
    1166                 :          0 :         struct sockaddr *sap = (struct sockaddr *)&ctx->nfs_server.address;
    1167                 :          0 :         int max_namelen = PAGE_SIZE;
    1168                 :          0 :         int max_pathlen = NFS_MAXPATHLEN;
    1169                 :          0 :         int port = 0;
    1170                 :          0 :         int ret;
    1171                 :            : 
    1172         [ #  # ]:          0 :         if (!fc->source)
    1173                 :          0 :                 goto out_no_device_name;
    1174                 :            : 
    1175                 :            :         /* Check for sanity first. */
    1176   [ #  #  #  # ]:          0 :         if (ctx->minorversion && ctx->version != 4)
    1177                 :          0 :                 goto out_minorversion_mismatch;
    1178                 :            : 
    1179         [ #  # ]:          0 :         if (ctx->options & NFS_OPTION_MIGRATION &&
    1180         [ #  # ]:          0 :             (ctx->version != 4 || ctx->minorversion != 0))
    1181                 :          0 :                 goto out_migration_misuse;
    1182                 :            : 
    1183                 :            :         /* Verify that any proto=/mountproto= options match the address
    1184                 :            :          * families in the addr=/mountaddr= options.
    1185                 :            :          */
    1186         [ #  # ]:          0 :         if (ctx->protofamily != AF_UNSPEC &&
    1187         [ #  # ]:          0 :             ctx->protofamily != ctx->nfs_server.address.sa_family)
    1188                 :          0 :                 goto out_proto_mismatch;
    1189                 :            : 
    1190         [ #  # ]:          0 :         if (ctx->mountfamily != AF_UNSPEC) {
    1191         [ #  # ]:          0 :                 if (ctx->mount_server.addrlen) {
    1192         [ #  # ]:          0 :                         if (ctx->mountfamily != ctx->mount_server.address.sa_family)
    1193                 :          0 :                                 goto out_mountproto_mismatch;
    1194                 :            :                 } else {
    1195         [ #  # ]:          0 :                         if (ctx->mountfamily != ctx->nfs_server.address.sa_family)
    1196                 :          0 :                                 goto out_mountproto_mismatch;
    1197                 :            :                 }
    1198                 :            :         }
    1199                 :            : 
    1200   [ #  #  #  #  :          0 :         if (!nfs_verify_server_address(sap))
                      # ]
    1201                 :          0 :                 goto out_no_address;
    1202                 :            : 
    1203         [ #  # ]:          0 :         if (ctx->version == 4) {
    1204                 :          0 :                 if (IS_ENABLED(CONFIG_NFS_V4)) {
    1205         [ #  # ]:          0 :                         if (ctx->nfs_server.protocol == XPRT_TRANSPORT_RDMA)
    1206                 :            :                                 port = NFS_RDMA_PORT;
    1207                 :            :                         else
    1208                 :          0 :                                 port = NFS_PORT;
    1209                 :          0 :                         max_namelen = NFS4_MAXNAMLEN;
    1210                 :          0 :                         max_pathlen = NFS4_MAXPATHLEN;
    1211         [ #  # ]:          0 :                         nfs_validate_transport_protocol(ctx);
    1212         [ #  # ]:          0 :                         if (ctx->nfs_server.protocol == XPRT_TRANSPORT_UDP)
    1213                 :          0 :                                 goto out_invalid_transport_udp;
    1214                 :          0 :                         ctx->flags &= ~(NFS_MOUNT_NONLM | NFS_MOUNT_NOACL |
    1215                 :            :                                         NFS_MOUNT_VER3 | NFS_MOUNT_LOCAL_FLOCK |
    1216                 :            :                                         NFS_MOUNT_LOCAL_FCNTL);
    1217                 :            :                 } else {
    1218                 :            :                         goto out_v4_not_compiled;
    1219                 :            :                 }
    1220                 :            :         } else {
    1221                 :          0 :                 nfs_set_mount_transport_protocol(ctx);
    1222                 :            : #ifdef CONFIG_NFS_DISABLE_UDP_SUPPORT
    1223         [ #  # ]:          0 :                if (ctx->nfs_server.protocol == XPRT_TRANSPORT_UDP)
    1224                 :          0 :                        goto out_invalid_transport_udp;
    1225                 :            : #endif
    1226         [ #  # ]:          0 :                 if (ctx->nfs_server.protocol == XPRT_TRANSPORT_RDMA)
    1227                 :          0 :                         port = NFS_RDMA_PORT;
    1228                 :            :         }
    1229                 :            : 
    1230         [ #  # ]:          0 :         nfs_set_port(sap, &ctx->nfs_server.port, port);
    1231                 :            : 
    1232                 :          0 :         ret = nfs_parse_source(fc, max_namelen, max_pathlen);
    1233         [ #  # ]:          0 :         if (ret < 0)
    1234                 :            :                 return ret;
    1235                 :            : 
    1236                 :            :         /* Load the NFS protocol module if we haven't done so yet */
    1237         [ #  # ]:          0 :         if (!ctx->nfs_mod) {
    1238                 :          0 :                 nfs_mod = get_nfs_version(ctx->version);
    1239         [ #  # ]:          0 :                 if (IS_ERR(nfs_mod)) {
    1240                 :          0 :                         ret = PTR_ERR(nfs_mod);
    1241                 :          0 :                         goto out_version_unavailable;
    1242                 :            :                 }
    1243                 :          0 :                 ctx->nfs_mod = nfs_mod;
    1244                 :            :         }
    1245                 :            : 
    1246                 :            :         /* Ensure the filesystem context has the correct fs_type */
    1247         [ #  # ]:          0 :         if (fc->fs_type != ctx->nfs_mod->nfs_fs) {
    1248                 :          0 :                 module_put(fc->fs_type->owner);
    1249                 :          0 :                 __module_get(ctx->nfs_mod->nfs_fs->owner);
    1250                 :          0 :                 fc->fs_type = ctx->nfs_mod->nfs_fs;
    1251                 :            :         }
    1252                 :            :         return 0;
    1253                 :            : 
    1254                 :            : out_no_device_name:
    1255                 :          0 :         return nfs_invalf(fc, "NFS: Device name not specified");
    1256                 :            : out_v4_not_compiled:
    1257                 :            :         nfs_errorf(fc, "NFS: NFSv4 is not compiled into kernel");
    1258                 :            :         return -EPROTONOSUPPORT;
    1259                 :          0 : out_invalid_transport_udp:
    1260                 :          0 :         return nfs_invalf(fc, "NFSv4: Unsupported transport protocol udp");
    1261                 :            : out_no_address:
    1262                 :          0 :         return nfs_invalf(fc, "NFS: mount program didn't pass remote address");
    1263                 :          0 : out_mountproto_mismatch:
    1264                 :          0 :         return nfs_invalf(fc, "NFS: Mount server address does not match mountproto= option");
    1265                 :            : out_proto_mismatch:
    1266                 :          0 :         return nfs_invalf(fc, "NFS: Server address does not match proto= option");
    1267                 :            : out_minorversion_mismatch:
    1268                 :          0 :         return nfs_invalf(fc, "NFS: Mount option vers=%u does not support minorversion=%u",
    1269                 :            :                           ctx->version, ctx->minorversion);
    1270                 :            : out_migration_misuse:
    1271                 :          0 :         return nfs_invalf(fc, "NFS: 'Migration' not supported for this NFS version");
    1272                 :            : out_version_unavailable:
    1273                 :          0 :         nfs_errorf(fc, "NFS: Version unavailable");
    1274                 :          0 :         return ret;
    1275                 :            : }
    1276                 :            : 
    1277                 :            : /*
    1278                 :            :  * Create an NFS superblock by the appropriate method.
    1279                 :            :  */
    1280                 :          0 : static int nfs_get_tree(struct fs_context *fc)
    1281                 :            : {
    1282                 :          0 :         struct nfs_fs_context *ctx = nfs_fc2context(fc);
    1283                 :          0 :         int err = nfs_fs_context_validate(fc);
    1284                 :            : 
    1285         [ #  # ]:          0 :         if (err)
    1286                 :            :                 return err;
    1287         [ #  # ]:          0 :         if (!ctx->internal)
    1288                 :          0 :                 return ctx->nfs_mod->rpc_ops->try_get_tree(fc);
    1289                 :            :         else
    1290                 :          0 :                 return nfs_get_tree_common(fc);
    1291                 :            : }
    1292                 :            : 
    1293                 :            : /*
    1294                 :            :  * Handle duplication of a configuration.  The caller copied *src into *sc, but
    1295                 :            :  * it can't deal with resource pointers in the filesystem context, so we have
    1296                 :            :  * to do that.  We need to clear pointers, copy data or get extra refs as
    1297                 :            :  * appropriate.
    1298                 :            :  */
    1299                 :          0 : static int nfs_fs_context_dup(struct fs_context *fc, struct fs_context *src_fc)
    1300                 :            : {
    1301                 :          0 :         struct nfs_fs_context *src = nfs_fc2context(src_fc), *ctx;
    1302                 :            : 
    1303                 :          0 :         ctx = kmemdup(src, sizeof(struct nfs_fs_context), GFP_KERNEL);
    1304         [ #  # ]:          0 :         if (!ctx)
    1305                 :            :                 return -ENOMEM;
    1306                 :            : 
    1307                 :          0 :         ctx->mntfh = nfs_alloc_fhandle();
    1308         [ #  # ]:          0 :         if (!ctx->mntfh) {
    1309                 :          0 :                 kfree(ctx);
    1310                 :          0 :                 return -ENOMEM;
    1311                 :            :         }
    1312                 :          0 :         nfs_copy_fh(ctx->mntfh, src->mntfh);
    1313                 :            : 
    1314                 :          0 :         __module_get(ctx->nfs_mod->owner);
    1315                 :          0 :         ctx->client_address          = NULL;
    1316                 :          0 :         ctx->mount_server.hostname   = NULL;
    1317                 :          0 :         ctx->nfs_server.export_path  = NULL;
    1318                 :          0 :         ctx->nfs_server.hostname     = NULL;
    1319                 :          0 :         ctx->fscache_uniq            = NULL;
    1320                 :          0 :         ctx->clone_data.fattr                = NULL;
    1321                 :          0 :         fc->fs_private = ctx;
    1322                 :          0 :         return 0;
    1323                 :            : }
    1324                 :            : 
    1325                 :          0 : static void nfs_fs_context_free(struct fs_context *fc)
    1326                 :            : {
    1327         [ #  # ]:          0 :         struct nfs_fs_context *ctx = nfs_fc2context(fc);
    1328                 :            : 
    1329         [ #  # ]:          0 :         if (ctx) {
    1330         [ #  # ]:          0 :                 if (ctx->server)
    1331                 :          0 :                         nfs_free_server(ctx->server);
    1332         [ #  # ]:          0 :                 if (ctx->nfs_mod)
    1333                 :          0 :                         put_nfs_version(ctx->nfs_mod);
    1334                 :          0 :                 kfree(ctx->client_address);
    1335                 :          0 :                 kfree(ctx->mount_server.hostname);
    1336                 :          0 :                 kfree(ctx->nfs_server.export_path);
    1337                 :          0 :                 kfree(ctx->nfs_server.hostname);
    1338                 :          0 :                 kfree(ctx->fscache_uniq);
    1339                 :          0 :                 nfs_free_fhandle(ctx->mntfh);
    1340                 :          0 :                 nfs_free_fattr(ctx->clone_data.fattr);
    1341                 :          0 :                 kfree(ctx);
    1342                 :            :         }
    1343                 :          0 : }
    1344                 :            : 
    1345                 :            : static const struct fs_context_operations nfs_fs_context_ops = {
    1346                 :            :         .free                   = nfs_fs_context_free,
    1347                 :            :         .dup                    = nfs_fs_context_dup,
    1348                 :            :         .parse_param            = nfs_fs_context_parse_param,
    1349                 :            :         .parse_monolithic       = nfs_fs_context_parse_monolithic,
    1350                 :            :         .get_tree               = nfs_get_tree,
    1351                 :            :         .reconfigure            = nfs_reconfigure,
    1352                 :            : };
    1353                 :            : 
    1354                 :            : /*
    1355                 :            :  * Prepare superblock configuration.  We use the namespaces attached to the
    1356                 :            :  * context.  This may be the current process's namespaces, or it may be a
    1357                 :            :  * container's namespaces.
    1358                 :            :  */
    1359                 :          0 : static int nfs_init_fs_context(struct fs_context *fc)
    1360                 :            : {
    1361                 :          0 :         struct nfs_fs_context *ctx;
    1362                 :            : 
    1363                 :          0 :         ctx = kzalloc(sizeof(struct nfs_fs_context), GFP_KERNEL);
    1364         [ #  # ]:          0 :         if (unlikely(!ctx))
    1365                 :            :                 return -ENOMEM;
    1366                 :            : 
    1367                 :          0 :         ctx->mntfh = nfs_alloc_fhandle();
    1368         [ #  # ]:          0 :         if (unlikely(!ctx->mntfh)) {
    1369                 :          0 :                 kfree(ctx);
    1370                 :          0 :                 return -ENOMEM;
    1371                 :            :         }
    1372                 :            : 
    1373                 :          0 :         ctx->protofamily     = AF_UNSPEC;
    1374                 :          0 :         ctx->mountfamily     = AF_UNSPEC;
    1375                 :          0 :         ctx->mount_server.port       = NFS_UNSPEC_PORT;
    1376                 :            : 
    1377         [ #  # ]:          0 :         if (fc->root) {
    1378                 :            :                 /* reconfigure, start with the current config */
    1379                 :          0 :                 struct nfs_server *nfss = fc->root->d_sb->s_fs_info;
    1380                 :          0 :                 struct net *net = nfss->nfs_client->cl_net;
    1381                 :            : 
    1382                 :          0 :                 ctx->flags           = nfss->flags;
    1383                 :          0 :                 ctx->rsize           = nfss->rsize;
    1384                 :          0 :                 ctx->wsize           = nfss->wsize;
    1385                 :          0 :                 ctx->retrans         = nfss->client->cl_timeout->to_retries;
    1386                 :          0 :                 ctx->selected_flavor = nfss->client->cl_auth->au_flavor;
    1387                 :          0 :                 ctx->acregmin                = nfss->acregmin / HZ;
    1388                 :          0 :                 ctx->acregmax                = nfss->acregmax / HZ;
    1389                 :          0 :                 ctx->acdirmin                = nfss->acdirmin / HZ;
    1390                 :          0 :                 ctx->acdirmax                = nfss->acdirmax / HZ;
    1391                 :          0 :                 ctx->timeo           = 10U * nfss->client->cl_timeout->to_initval / HZ;
    1392                 :          0 :                 ctx->nfs_server.port = nfss->port;
    1393                 :          0 :                 ctx->nfs_server.addrlen      = nfss->nfs_client->cl_addrlen;
    1394                 :          0 :                 ctx->version         = nfss->nfs_client->rpc_ops->version;
    1395                 :          0 :                 ctx->minorversion    = nfss->nfs_client->cl_minorversion;
    1396                 :            : 
    1397                 :          0 :                 memcpy(&ctx->nfs_server.address, &nfss->nfs_client->cl_addr,
    1398                 :            :                         ctx->nfs_server.addrlen);
    1399                 :            : 
    1400         [ #  # ]:          0 :                 if (fc->net_ns != net) {
    1401                 :          0 :                         put_net(fc->net_ns);
    1402                 :          0 :                         fc->net_ns = get_net(net);
    1403                 :            :                 }
    1404                 :            : 
    1405                 :          0 :                 ctx->nfs_mod = nfss->nfs_client->cl_nfs_mod;
    1406                 :          0 :                 __module_get(ctx->nfs_mod->owner);
    1407                 :            :         } else {
    1408                 :            :                 /* defaults */
    1409                 :          0 :                 ctx->timeo           = NFS_UNSPEC_TIMEO;
    1410                 :          0 :                 ctx->retrans         = NFS_UNSPEC_RETRANS;
    1411                 :          0 :                 ctx->acregmin                = NFS_DEF_ACREGMIN;
    1412                 :          0 :                 ctx->acregmax                = NFS_DEF_ACREGMAX;
    1413                 :          0 :                 ctx->acdirmin                = NFS_DEF_ACDIRMIN;
    1414                 :          0 :                 ctx->acdirmax                = NFS_DEF_ACDIRMAX;
    1415                 :          0 :                 ctx->nfs_server.port = NFS_UNSPEC_PORT;
    1416                 :          0 :                 ctx->nfs_server.protocol = XPRT_TRANSPORT_TCP;
    1417                 :          0 :                 ctx->selected_flavor = RPC_AUTH_MAXFLAVOR;
    1418                 :          0 :                 ctx->minorversion    = 0;
    1419                 :          0 :                 ctx->need_mount              = true;
    1420                 :            :         }
    1421                 :          0 :         fc->fs_private = ctx;
    1422                 :          0 :         fc->ops = &nfs_fs_context_ops;
    1423                 :          0 :         return 0;
    1424                 :            : }
    1425                 :            : 
    1426                 :            : struct file_system_type nfs_fs_type = {
    1427                 :            :         .owner                  = THIS_MODULE,
    1428                 :            :         .name                   = "nfs",
    1429                 :            :         .init_fs_context        = nfs_init_fs_context,
    1430                 :            :         .parameters             = nfs_fs_parameters,
    1431                 :            :         .kill_sb                = nfs_kill_super,
    1432                 :            :         .fs_flags               = FS_RENAME_DOES_D_MOVE|FS_BINARY_MOUNTDATA,
    1433                 :            : };
    1434                 :            : MODULE_ALIAS_FS("nfs");
    1435                 :            : EXPORT_SYMBOL_GPL(nfs_fs_type);
    1436                 :            : 
    1437                 :            : #if IS_ENABLED(CONFIG_NFS_V4)
    1438                 :            : struct file_system_type nfs4_fs_type = {
    1439                 :            :         .owner                  = THIS_MODULE,
    1440                 :            :         .name                   = "nfs4",
    1441                 :            :         .init_fs_context        = nfs_init_fs_context,
    1442                 :            :         .parameters             = nfs_fs_parameters,
    1443                 :            :         .kill_sb                = nfs_kill_super,
    1444                 :            :         .fs_flags               = FS_RENAME_DOES_D_MOVE|FS_BINARY_MOUNTDATA,
    1445                 :            : };
    1446                 :            : MODULE_ALIAS_FS("nfs4");
    1447                 :            : MODULE_ALIAS("nfs4");
    1448                 :            : EXPORT_SYMBOL_GPL(nfs4_fs_type);
    1449                 :            : #endif /* CONFIG_NFS_V4 */

Generated by: LCOV version 1.14