400 *exip = exi;
401
402 VN_RELE(*vpp);
403 *vpp = vp;
404 }
405
406 return (0);
407 }
408
409 /*
410 * Given mounted "dvp" and "exi", go upper mountpoint
411 * with dvp/exi correction
412 * Return 0 in success
413 */
414 int
415 rfs_climb_crossmnt(vnode_t **dvpp, struct exportinfo **exip, cred_t *cr)
416 {
417 struct exportinfo *exi;
418 vnode_t *dvp = *dvpp;
419
420 ASSERT3P((*exip)->exi_zone, ==, curzone);
421 ASSERT((dvp->v_flag & VROOT) || VN_IS_CURZONEROOT(dvp));
422
423 VN_HOLD(dvp);
424 dvp = untraverse(dvp);
425 exi = nfs_vptoexi(NULL, dvp, cr, NULL, NULL, FALSE);
426 if (exi == NULL) {
427 VN_RELE(dvp);
428 return (-1);
429 }
430
431 ASSERT3P(exi->exi_zone, ==, curzone);
432 exi_rele(*exip);
433 *exip = exi;
434 VN_RELE(*dvpp);
435 *dvpp = dvp;
436
437 return (0);
438 }
439 /*
440 * Directory lookup.
441 * Returns an fhandle and file attributes for file name in a directory.
442 */
443 /* ARGSUSED */
444 void
445 rfs_lookup(struct nfsdiropargs *da, struct nfsdiropres *dr,
446 struct exportinfo *exi, struct svc_req *req, cred_t *cr, bool_t ro)
447 {
448 int error;
449 vnode_t *dvp;
450 vnode_t *vp;
451 struct vattr va;
472 dr->dr_status = NFSERR_ACCES;
473 return;
474 }
475
476 /*
477 * Allow lookups from the root - the default
478 * location of the public filehandle.
479 */
480 if (exi != NULL && (exi->exi_export.ex_flags & EX_PUBLIC)) {
481 dvp = ZONE_ROOTVP();
482 VN_HOLD(dvp);
483 } else {
484 dvp = nfs_fhtovp(fhp, exi);
485 if (dvp == NULL) {
486 dr->dr_status = NFSERR_STALE;
487 return;
488 }
489 }
490
491 exi_hold(exi);
492 ASSERT3P(exi->exi_zone, ==, curzone);
493
494 /*
495 * Not allow lookup beyond root.
496 * If the filehandle matches a filehandle of the exi,
497 * then the ".." refers beyond the root of an exported filesystem.
498 */
499 if (strcmp(da->da_name, "..") == 0 &&
500 EQFID(&exi->exi_fid, (fid_t *)&fhp->fh_len)) {
501 if ((exi->exi_export.ex_flags & EX_NOHIDE) &&
502 ((dvp->v_flag & VROOT) || VN_IS_CURZONEROOT(dvp))) {
503 /*
504 * special case for ".." and 'nohide'exported root
505 */
506 if (rfs_climb_crossmnt(&dvp, &exi, cr) != 0) {
507 error = NFSERR_ACCES;
508 goto out;
509 }
510 } else {
511 error = NFSERR_NOENT;
512 goto out;
|
400 *exip = exi;
401
402 VN_RELE(*vpp);
403 *vpp = vp;
404 }
405
406 return (0);
407 }
408
409 /*
410 * Given mounted "dvp" and "exi", go upper mountpoint
411 * with dvp/exi correction
412 * Return 0 in success
413 */
414 int
415 rfs_climb_crossmnt(vnode_t **dvpp, struct exportinfo **exip, cred_t *cr)
416 {
417 struct exportinfo *exi;
418 vnode_t *dvp = *dvpp;
419
420 ASSERT3U((*exip)->exi_zoneid, ==, curzone->zone_id);
421 ASSERT((dvp->v_flag & VROOT) || VN_IS_CURZONEROOT(dvp));
422
423 VN_HOLD(dvp);
424 dvp = untraverse(dvp);
425 exi = nfs_vptoexi(NULL, dvp, cr, NULL, NULL, FALSE);
426 if (exi == NULL) {
427 VN_RELE(dvp);
428 return (-1);
429 }
430
431 ASSERT3U(exi->exi_zoneid, ==, curzone->zone_id);
432 exi_rele(*exip);
433 *exip = exi;
434 VN_RELE(*dvpp);
435 *dvpp = dvp;
436
437 return (0);
438 }
439 /*
440 * Directory lookup.
441 * Returns an fhandle and file attributes for file name in a directory.
442 */
443 /* ARGSUSED */
444 void
445 rfs_lookup(struct nfsdiropargs *da, struct nfsdiropres *dr,
446 struct exportinfo *exi, struct svc_req *req, cred_t *cr, bool_t ro)
447 {
448 int error;
449 vnode_t *dvp;
450 vnode_t *vp;
451 struct vattr va;
472 dr->dr_status = NFSERR_ACCES;
473 return;
474 }
475
476 /*
477 * Allow lookups from the root - the default
478 * location of the public filehandle.
479 */
480 if (exi != NULL && (exi->exi_export.ex_flags & EX_PUBLIC)) {
481 dvp = ZONE_ROOTVP();
482 VN_HOLD(dvp);
483 } else {
484 dvp = nfs_fhtovp(fhp, exi);
485 if (dvp == NULL) {
486 dr->dr_status = NFSERR_STALE;
487 return;
488 }
489 }
490
491 exi_hold(exi);
492 ASSERT3U(exi->exi_zoneid, ==, curzone->zone_id);
493
494 /*
495 * Not allow lookup beyond root.
496 * If the filehandle matches a filehandle of the exi,
497 * then the ".." refers beyond the root of an exported filesystem.
498 */
499 if (strcmp(da->da_name, "..") == 0 &&
500 EQFID(&exi->exi_fid, (fid_t *)&fhp->fh_len)) {
501 if ((exi->exi_export.ex_flags & EX_NOHIDE) &&
502 ((dvp->v_flag & VROOT) || VN_IS_CURZONEROOT(dvp))) {
503 /*
504 * special case for ".." and 'nohide'exported root
505 */
506 if (rfs_climb_crossmnt(&dvp, &exi, cr) != 0) {
507 error = NFSERR_ACCES;
508 goto out;
509 }
510 } else {
511 error = NFSERR_NOENT;
512 goto out;
|