394 *exip = exi;
395
396 VN_RELE(*vpp);
397 *vpp = vp;
398 }
399
400 return (0);
401 }
402
403 /*
404 * Given mounted "dvp" and "exi", go upper mountpoint
405 * with dvp/exi correction
406 * Return 0 in success
407 */
408 int
409 rfs_climb_crossmnt(vnode_t **dvpp, struct exportinfo **exip, cred_t *cr)
410 {
411 struct exportinfo *exi;
412 vnode_t *dvp = *dvpp;
413
414 ASSERT(dvp->v_flag & VROOT);
415
416 VN_HOLD(dvp);
417 dvp = untraverse(dvp);
418 exi = nfs_vptoexi(NULL, dvp, cr, NULL, NULL, FALSE);
419 if (exi == NULL) {
420 VN_RELE(dvp);
421 return (-1);
422 }
423
424 exi_rele(*exip);
425 *exip = exi;
426 VN_RELE(*dvpp);
427 *dvpp = dvp;
428
429 return (0);
430 }
431 /*
432 * Directory lookup.
433 * Returns an fhandle and file attributes for file name in a directory.
434 */
473 dvp = ZONE_ROOTVP();
474 VN_HOLD(dvp);
475 } else {
476 dvp = nfs_fhtovp(fhp, exi);
477 if (dvp == NULL) {
478 dr->dr_status = NFSERR_STALE;
479 return;
480 }
481 }
482
483 exi_hold(exi);
484
485 /*
486 * Not allow lookup beyond root.
487 * If the filehandle matches a filehandle of the exi,
488 * then the ".." refers beyond the root of an exported filesystem.
489 */
490 if (strcmp(da->da_name, "..") == 0 &&
491 EQFID(&exi->exi_fid, (fid_t *)&fhp->fh_len)) {
492 if ((exi->exi_export.ex_flags & EX_NOHIDE) &&
493 (dvp->v_flag & VROOT)) {
494 /*
495 * special case for ".." and 'nohide'exported root
496 */
497 if (rfs_climb_crossmnt(&dvp, &exi, cr) != 0) {
498 error = NFSERR_ACCES;
499 goto out;
500 }
501 } else {
502 error = NFSERR_NOENT;
503 goto out;
504 }
505 }
506
507 ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
508 name = nfscmd_convname(ca, exi, da->da_name, NFSCMD_CONV_INBOUND,
509 MAXPATHLEN);
510
511 if (name == NULL) {
512 error = NFSERR_ACCES;
513 goto out;
|
394 *exip = exi;
395
396 VN_RELE(*vpp);
397 *vpp = vp;
398 }
399
400 return (0);
401 }
402
403 /*
404 * Given mounted "dvp" and "exi", go upper mountpoint
405 * with dvp/exi correction
406 * Return 0 in success
407 */
408 int
409 rfs_climb_crossmnt(vnode_t **dvpp, struct exportinfo **exip, cred_t *cr)
410 {
411 struct exportinfo *exi;
412 vnode_t *dvp = *dvpp;
413
414 ASSERT((dvp->v_flag & VROOT) || VN_IS_CURZONEROOT(dvp));
415
416 VN_HOLD(dvp);
417 dvp = untraverse(dvp);
418 exi = nfs_vptoexi(NULL, dvp, cr, NULL, NULL, FALSE);
419 if (exi == NULL) {
420 VN_RELE(dvp);
421 return (-1);
422 }
423
424 exi_rele(*exip);
425 *exip = exi;
426 VN_RELE(*dvpp);
427 *dvpp = dvp;
428
429 return (0);
430 }
431 /*
432 * Directory lookup.
433 * Returns an fhandle and file attributes for file name in a directory.
434 */
473 dvp = ZONE_ROOTVP();
474 VN_HOLD(dvp);
475 } else {
476 dvp = nfs_fhtovp(fhp, exi);
477 if (dvp == NULL) {
478 dr->dr_status = NFSERR_STALE;
479 return;
480 }
481 }
482
483 exi_hold(exi);
484
485 /*
486 * Not allow lookup beyond root.
487 * If the filehandle matches a filehandle of the exi,
488 * then the ".." refers beyond the root of an exported filesystem.
489 */
490 if (strcmp(da->da_name, "..") == 0 &&
491 EQFID(&exi->exi_fid, (fid_t *)&fhp->fh_len)) {
492 if ((exi->exi_export.ex_flags & EX_NOHIDE) &&
493 ((dvp->v_flag & VROOT) || VN_IS_CURZONEROOT(dvp))) {
494 /*
495 * special case for ".." and 'nohide'exported root
496 */
497 if (rfs_climb_crossmnt(&dvp, &exi, cr) != 0) {
498 error = NFSERR_ACCES;
499 goto out;
500 }
501 } else {
502 error = NFSERR_NOENT;
503 goto out;
504 }
505 }
506
507 ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
508 name = nfscmd_convname(ca, exi, da->da_name, NFSCMD_CONV_INBOUND,
509 MAXPATHLEN);
510
511 if (name == NULL) {
512 error = NFSERR_ACCES;
513 goto out;
|