Print this page
2988 nfssrv: need ability to go to submounts for v3 and v2 protocols
Portions contributed by: Marcel Telka <marcel.telka@nexenta.com>
Portions contributed by: Jean McCormack <jean.mccormack@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Alek Pinchuk <alek.pinchuk@nexenta.com>
Reviewed by: Dan Fields <dan.fields@nexenta.com>
Reviewed by: Dan McDonald <danmcd@joyent.com>
Change-Id: I6fdf110cc17e789353c4442b83a46cb80643456e

*** 380,389 **** --- 380,392 ---- struct sockaddr *ca; char *name = NULL; dvap = NULL; + if (exi != NULL) + exi_hold(exi); + /* * Allow lookups from the root - the default * location of the public filehandle. */ if (exi != NULL && (exi->exi_export.ex_flags & EX_PUBLIC)) {
*** 418,430 **** --- 421,444 ---- } fhp = &args->what.dir; if (strcmp(args->what.name, "..") == 0 && EQFID(&exi->exi_fid, FH3TOFIDP(fhp))) { + if ((exi->exi_export.ex_flags & EX_NOHIDE) && + (dvp->v_flag & VROOT)) { + /* + * special case for ".." and 'nohide'exported root + */ + if (rfs_climb_crossmnt(&dvp, &exi, cr) != 0) { + resp->status = NFS3ERR_ACCES; + goto out1; + } + } else { resp->status = NFS3ERR_NOENT; goto out1; } + } ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf; name = nfscmd_convname(ca, exi, args->what.name, NFSCMD_CONV_INBOUND, MAXPATHLEN + 1);
*** 437,450 **** * If the public filehandle is used then allow * a multi-component lookup */ if (PUBLIC_FH3(&args->what.dir)) { publicfh_flag = TRUE; error = rfs_publicfh_mclookup(name, dvp, cr, &vp, &exi, &sec); ! if (error && exi != NULL) ! exi_rele(exi); /* See comment below Re: publicfh_flag */ /* * Since WebNFS may bypass MOUNT, we need to ensure this * request didn't come from an unlabeled admin_low client. */ if (is_system_labeled() && error == 0) { --- 451,466 ---- * If the public filehandle is used then allow * a multi-component lookup */ if (PUBLIC_FH3(&args->what.dir)) { publicfh_flag = TRUE; + + exi_rele(exi); + error = rfs_publicfh_mclookup(name, dvp, cr, &vp, &exi, &sec); ! /* * Since WebNFS may bypass MOUNT, we need to ensure this * request didn't come from an unlabeled admin_low client. */ if (is_system_labeled() && error == 0) {
*** 462,473 **** } tp = find_tpc(ipaddr, addr_type, B_FALSE); if (tp == NULL || tp->tpc_tp.tp_doi != l_admin_low->tsl_doi || tp->tpc_tp.host_type != SUN_CIPSO) { - if (exi != NULL) - exi_rele(exi); VN_RELE(vp); error = EACCES; } if (tp != NULL) TPC_RELE(tp); --- 478,487 ----
*** 478,487 **** --- 492,507 ---- } if (name != args->what.name) kmem_free(name, MAXPATHLEN + 1); + if (error == 0 && vn_ismntpt(vp)) { + error = rfs_cross_mnt(&vp, &exi); + if (error) + VN_RELE(vp); + } + if (is_system_labeled() && error == 0) { bslabel_t *clabel = req->rq_label; ASSERT(clabel != NULL); DTRACE_PROBE2(tx__rfs3__log__info__oplookup__clabel, char *,
*** 488,499 **** "got client label from request(1)", struct svc_req *, req); if (!blequal(&l_admin_low->tsl_label, clabel)) { if (!do_rfs_label_check(clabel, dvp, DOMINANCE_CHECK, exi)) { - if (publicfh_flag && exi != NULL) - exi_rele(exi); VN_RELE(vp); error = EACCES; } } } --- 508,517 ----
*** 510,536 **** error = makefh3(&resp->resok.object, vp, exi); if (!error && publicfh_flag && !chk_clnt_sec(exi, req)) auth_weak = TRUE; } - /* - * If publicfh_flag is true then we have called rfs_publicfh_mclookup - * and have obtained a new exportinfo in exi which needs to be - * released. Note that the original exportinfo pointed to by exi - * will be released by the caller, common_dispatch. - */ - if (publicfh_flag) - exi_rele(exi); - if (error) { VN_RELE(vp); goto out; } va.va_mask = AT_ALL; vap = rfs4_delegated_getattr(vp, &va, 0, cr) ? NULL : &va; VN_RELE(vp); resp->status = NFS3_OK; vattr_to_post_op_attr(vap, &resp->resok.obj_attributes); vattr_to_post_op_attr(dvap, &resp->resok.dir_attributes); --- 528,546 ---- error = makefh3(&resp->resok.object, vp, exi); if (!error && publicfh_flag && !chk_clnt_sec(exi, req)) auth_weak = TRUE; } if (error) { VN_RELE(vp); goto out; } va.va_mask = AT_ALL; vap = rfs4_delegated_getattr(vp, &va, 0, cr) ? NULL : &va; + exi_rele(exi); VN_RELE(vp); resp->status = NFS3_OK; vattr_to_post_op_attr(vap, &resp->resok.obj_attributes); vattr_to_post_op_attr(dvap, &resp->resok.dir_attributes);
*** 554,563 **** --- 564,576 ---- curthread->t_flag &= ~T_WOULDBLOCK; resp->status = NFS3ERR_JUKEBOX; } else resp->status = puterrno3(error); out1: + if (exi != NULL) + exi_rele(exi); + DTRACE_NFSV3_4(op__lookup__done, struct svc_req *, req, cred_t *, cr, vnode_t *, dvp, LOOKUP3res *, resp); if (dvp != NULL) VN_RELE(dvp);
*** 3607,3623 **** --- 3620,3641 ---- /* Lie about the object type for a referral */ if (vn_is_nfs_reparse(nvp, cr)) nvap->va_type = VLNK; + if (vn_ismntpt(nvp)) { + infop[i].attr.attributes = FALSE; + infop[i].fh.handle_follows = FALSE; + } else { vattr_to_post_op_attr(nvap, &infop[i].attr); error = makefh3(&infop[i].fh.handle, nvp, exi); if (!error) infop[i].fh.handle_follows = TRUE; else infop[i].fh.handle_follows = FALSE; + } VN_RELE(nvp); dp = nextdp(dp); }