Print this page
*** NO COMMENTS ***

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/fs/nfs/nfs_srv.c
          +++ new/usr/src/uts/common/fs/nfs/nfs_srv.c
↓ open down ↓ 318 lines elided ↑ open up ↑
 319  319          VN_RELE(vp);
 320  320  
 321  321          ns->ns_status = puterrno(error);
 322  322  }
 323  323  void *
 324  324  rfs_setattr_getfh(struct nfssaargs *args)
 325  325  {
 326  326          return (&args->saa_fh);
 327  327  }
 328  328  
      329 +/* Change and release @exip and @vpp only in success */
      330 +int
      331 +rfs_cross_mnt(vnode_t **vpp, struct exportinfo **exip)
      332 +{
      333 +        struct exportinfo *exi;
      334 +        vnode_t *vp;
      335 +        fid_t fid;
      336 +        int error;
      337 +
      338 +        vp = *vpp;
      339 +
      340 +        /* traverse() releases argument in success */
      341 +        VN_HOLD(*vpp);
      342 +
      343 +        if ((error = traverse(&vp)) != 0) {
      344 +                VN_RELE(*vpp);
      345 +                return (error);
      346 +        }
      347 +
      348 +        bzero(&fid, sizeof (fid));
      349 +        fid.fid_len = MAXFIDSZ;
      350 +        error = VOP_FID(vp, &fid, NULL);
      351 +        if (error) {
      352 +                VN_RELE(vp);
      353 +                return (error);
      354 +        }
      355 +
      356 +        exi = checkexport(&vp->v_vfsp->vfs_fsid, &fid);
      357 +        if (exi == NULL ||
      358 +            (exi->exi_export.ex_flags & EX_NOHIDE) == 0) {
      359 +                /* It is not error, just subdir is not exported
      360 +                 * or "nohide" is not set
      361 +                 */
      362 +                VN_RELE(vp);
      363 +        } else {
      364 +                /* go to submount */
      365 +                exi_rele(*exip);
      366 +                *exip = exi;
      367 +
      368 +                VN_RELE(*vpp);
      369 +                *vpp = vp;
      370 +        }
      371 +        return (0);
      372 +}
      373 +
 329  374  /*
 330  375   * Directory lookup.
 331  376   * Returns an fhandle and file attributes for file name in a directory.
 332  377   */
 333  378  /* ARGSUSED */
 334  379  void
 335  380  rfs_lookup(struct nfsdiropargs *da, struct nfsdiropres *dr,
 336  381          struct exportinfo *exi, struct svc_req *req, cred_t *cr)
 337  382  {
 338  383          int error;
↓ open down ↓ 53 lines elided ↑ open up ↑
 392  437  
 393  438          ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
 394  439          name = nfscmd_convname(ca, exi, da->da_name, NFSCMD_CONV_INBOUND,
 395  440              MAXPATHLEN);
 396  441  
 397  442          if (name == NULL) {
 398  443                  dr->dr_status = NFSERR_ACCES;
 399  444                  return;
 400  445          }
 401  446  
      447 +        exi_hold(exi);
      448 +
 402  449          /*
 403  450           * If the public filehandle is used then allow
 404  451           * a multi-component lookup, i.e. evaluate
 405  452           * a pathname and follow symbolic links if
 406  453           * necessary.
 407  454           *
 408  455           * This may result in a vnode in another filesystem
 409  456           * which is OK as long as the filesystem is exported.
 410  457           */
 411  458          if (PUBLIC_FH2(fhp)) {
      459 +                struct exportinfo *new;
      460 +
 412  461                  publicfh_flag = TRUE;
 413      -                error = rfs_publicfh_mclookup(name, dvp, cr, &vp, &exi,
      462 +                error = rfs_publicfh_mclookup(name, dvp, cr, &vp, &new,
 414  463                      &sec);
      464 +
      465 +                if (error == 0) {
      466 +                        exi_rele(exi);
      467 +                        exi = new;
      468 +                }
 415  469          } else {
 416  470                  /*
 417  471                   * Do a normal single component lookup.
 418  472                   */
 419  473                  error = VOP_LOOKUP(dvp, name, &vp, NULL, 0, NULL, cr,
 420  474                      NULL, NULL, NULL);
 421  475          }
 422  476  
 423  477          if (name != da->da_name)
 424  478                  kmem_free(name, MAXPATHLEN);
 425  479  
      480 +        if (error == 0 && vn_ismntpt(vp)) {
      481 +                error = rfs_cross_mnt(&vp, &exi);
      482 +                if (error)
      483 +                        VN_RELE(vp);
      484 +        }
 426  485  
 427  486          if (!error) {
 428  487                  va.va_mask = AT_ALL;    /* we want everything */
 429  488  
 430  489                  error = rfs4_delegated_getattr(vp, &va, 0, cr);
 431  490  
 432  491                  /* check for overflows */
 433  492                  if (!error) {
 434  493                          acl_perm(vp, exi, &va, cr);
 435  494                          error = vattr_to_nattr(&va, &dr->dr_attr);
↓ open down ↓ 8 lines elided ↑ open up ↑
 444  503                                              !chk_clnt_sec(exi, req))
 445  504                                                  auth_weak = TRUE;
 446  505                                  }
 447  506                          }
 448  507                  }
 449  508                  VN_RELE(vp);
 450  509          }
 451  510  
 452  511          VN_RELE(dvp);
 453  512  
 454      -        /*
 455      -         * If publicfh_flag is true then we have called rfs_publicfh_mclookup
 456      -         * and have obtained a new exportinfo in exi which needs to be
 457      -         * released. Note the the original exportinfo pointed to by exi
 458      -         * will be released by the caller, comon_dispatch.
      513 +        /* The passed argument exportinfo is released by the
      514 +         * caller, comon_dispatch
 459  515           */
 460      -        if (publicfh_flag && exi != NULL)
 461      -                exi_rele(exi);
      516 +        exi_rele(exi);
 462  517  
 463  518          /*
 464  519           * If it's public fh, no 0x81, and client's flavor is
 465  520           * invalid, set WebNFS status to WNFSERR_CLNT_FLAVOR now.
 466  521           * Then set RPC status to AUTH_TOOWEAK in common_dispatch.
 467  522           */
 468  523          if (auth_weak)
 469  524                  dr->dr_status = (enum nfsstat)WNFSERR_CLNT_FLAVOR;
 470  525          else
 471  526                  dr->dr_status = puterrno(error);
↓ open down ↓ 2532 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX