Print this page
Revert exi_zone to exi_zoneid, and install exi_ne backpointer
Caution with use after exi_rele()
Be far more judicious in the use of curzone-using macros.
(Merge and extra asserts by danmcd.)
curzone reality check and teardown changes to use the RIGHT zone
Try to remove assumption that zone's root vnode is marked VROOT


 394         struct vattr *vap;
 395         struct vattr va;
 396         struct vattr *dvap;
 397         struct vattr dva;
 398         nfs_fh3 *fhp;
 399         struct sec_ol sec = {0, 0};
 400         bool_t publicfh_flag = FALSE, auth_weak = FALSE;
 401         struct sockaddr *ca;
 402         char *name = NULL;
 403 
 404         dvap = NULL;
 405 
 406         if (exi != NULL)
 407                 exi_hold(exi);
 408 
 409         /*
 410          * Allow lookups from the root - the default
 411          * location of the public filehandle.
 412          */
 413         if (exi != NULL && (exi->exi_export.ex_flags & EX_PUBLIC)) {

 414                 dvp = ZONE_ROOTVP();
 415                 VN_HOLD(dvp);
 416 
 417                 DTRACE_NFSV3_5(op__lookup__start, struct svc_req *, req,
 418                     cred_t *, cr, vnode_t *, dvp, struct exportinfo *, exi,
 419                     LOOKUP3args *, args);
 420         } else {
 421                 dvp = nfs3_fhtovp(&args->what.dir, exi);
 422 
 423                 DTRACE_NFSV3_5(op__lookup__start, struct svc_req *, req,
 424                     cred_t *, cr, vnode_t *, dvp, struct exportinfo *, exi,
 425                     LOOKUP3args *, args);
 426 
 427                 if (dvp == NULL) {
 428                         error = ESTALE;
 429                         goto out;
 430                 }
 431         }
 432 
 433         dva.va_mask = AT_ALL;
 434         dvap = VOP_GETATTR(dvp, &dva, 0, cr, NULL) ? NULL : &dva;
 435 
 436         if (args->what.name == nfs3nametoolong) {
 437                 resp->status = NFS3ERR_NAMETOOLONG;
 438                 goto out1;
 439         }
 440 
 441         if (args->what.name == NULL || *(args->what.name) == '\0') {
 442                 resp->status = NFS3ERR_ACCES;
 443                 goto out1;
 444         }
 445 
 446         fhp = &args->what.dir;

 447         if (strcmp(args->what.name, "..") == 0 &&
 448             EQFID(&exi->exi_fid, FH3TOFIDP(fhp))) {
 449                 if ((exi->exi_export.ex_flags & EX_NOHIDE) &&
 450                     (dvp->v_flag & VROOT)) {
 451                         /*
 452                          * special case for ".." and 'nohide'exported root
 453                          */
 454                         if (rfs_climb_crossmnt(&dvp, &exi, cr) != 0) {
 455                                 resp->status = NFS3ERR_ACCES;
 456                                 goto out1;
 457                         }
 458                 } else {
 459                         resp->status = NFS3ERR_NOENT;
 460                         goto out1;
 461                 }
 462         }
 463 
 464         ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
 465         name = nfscmd_convname(ca, exi, args->what.name,
 466             NFSCMD_CONV_INBOUND, MAXPATHLEN + 1);
 467 
 468         if (name == NULL) {
 469                 resp->status = NFS3ERR_ACCES;
 470                 goto out1;
 471         }
 472 
 473         /*
 474          * If the public filehandle is used then allow
 475          * a multi-component lookup
 476          */
 477         if (PUBLIC_FH3(&args->what.dir)) {
 478                 publicfh_flag = TRUE;
 479 
 480                 exi_rele(exi);

 481 
 482                 error = rfs_publicfh_mclookup(name, dvp, cr, &vp,
 483                     &exi, &sec);
 484 
 485                 /*
 486                  * Since WebNFS may bypass MOUNT, we need to ensure this
 487                  * request didn't come from an unlabeled admin_low client.
 488                  */
 489                 if (is_system_labeled() && error == 0) {
 490                         int             addr_type;
 491                         void            *ipaddr;
 492                         tsol_tpc_t      *tp;
 493 
 494                         if (ca->sa_family == AF_INET) {
 495                                 addr_type = IPV4_VERSION;
 496                                 ipaddr = &((struct sockaddr_in *)ca)->sin_addr;
 497                         } else if (ca->sa_family == AF_INET6) {
 498                                 addr_type = IPV6_VERSION;
 499                                 ipaddr = &((struct sockaddr_in6 *)
 500                                     ca)->sin6_addr;


 544 
 545         if (error)
 546                 goto out;
 547 
 548         if (sec.sec_flags & SEC_QUERY) {
 549                 error = makefh3_ol(&resp->resok.object, exi, sec.sec_index);
 550         } else {
 551                 error = makefh3(&resp->resok.object, vp, exi);
 552                 if (!error && publicfh_flag && !chk_clnt_sec(exi, req))
 553                         auth_weak = TRUE;
 554         }
 555 
 556         if (error) {
 557                 VN_RELE(vp);
 558                 goto out;
 559         }
 560 
 561         va.va_mask = AT_ALL;
 562         vap = rfs4_delegated_getattr(vp, &va, 0, cr) ? NULL : &va;
 563 
 564         exi_rele(exi);
 565         VN_RELE(vp);
 566 
 567         resp->status = NFS3_OK;
 568         vattr_to_post_op_attr(vap, &resp->resok.obj_attributes);
 569         vattr_to_post_op_attr(dvap, &resp->resok.dir_attributes);
 570 
 571         /*
 572          * If it's public fh, no 0x81, and client's flavor is
 573          * invalid, set WebNFS status to WNFSERR_CLNT_FLAVOR now.
 574          * Then set RPC status to AUTH_TOOWEAK in common_dispatch.
 575          */
 576         if (auth_weak)
 577                 resp->status = (enum nfsstat3)WNFSERR_CLNT_FLAVOR;
 578 
 579         DTRACE_NFSV3_5(op__lookup__done, struct svc_req *, req,
 580             cred_t *, cr, vnode_t *, dvp, struct exportinfo *, exi,
 581             LOOKUP3res *, resp);
 582         VN_RELE(dvp);

 583 
 584         return;
 585 
 586 out:
 587         if (curthread->t_flag & T_WOULDBLOCK) {
 588                 curthread->t_flag &= ~T_WOULDBLOCK;
 589                 resp->status = NFS3ERR_JUKEBOX;
 590         } else
 591                 resp->status = puterrno3(error);
 592 out1:
 593         DTRACE_NFSV3_5(op__lookup__done, struct svc_req *, req,
 594             cred_t *, cr, vnode_t *, dvp, struct exportinfo *, exi,
 595             LOOKUP3res *, resp);
 596 
 597         if (exi != NULL)
 598                 exi_rele(exi);
 599 
 600         if (dvp != NULL)
 601                 VN_RELE(dvp);
 602         vattr_to_post_op_attr(dvap, &resp->resfail.dir_attributes);


1316         mblk_t *m;
1317         struct iovec *iovp;
1318         int iovcnt;
1319         int ioflag;
1320         cred_t *savecred;
1321         int in_crit = 0;
1322         int rwlock_ret = -1;
1323         caller_context_t ct;
1324 
1325         vp = nfs3_fhtovp(&args->file, exi);
1326 
1327         DTRACE_NFSV3_5(op__write__start, struct svc_req *, req,
1328             cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
1329             WRITE3args *, args);
1330 
1331         if (vp == NULL) {
1332                 error = ESTALE;
1333                 goto err;
1334         }
1335 

1336         ns = nfs3_get_srv();

1337         if (is_system_labeled()) {
1338                 bslabel_t *clabel = req->rq_label;
1339 
1340                 ASSERT(clabel != NULL);
1341                 DTRACE_PROBE2(tx__rfs3__log__info__opwrite__clabel, char *,
1342                     "got client label from request(1)", struct svc_req *, req);
1343 
1344                 if (!blequal(&l_admin_low->tsl_label, clabel)) {
1345                         if (!do_rfs_label_check(clabel, vp, EQUALITY_CHECK,
1346                             exi)) {
1347                                 resp->status = NFS3ERR_ACCES;
1348                                 goto err1;
1349                         }
1350                 }
1351         }
1352 
1353         ct.cc_sysid = 0;
1354         ct.cc_pid = 0;
1355         ct.cc_caller_id = nfs3_srv_caller_id;
1356         ct.cc_flags = CC_DONTBLOCK;


2654                     "got client label from request(1)", struct svc_req *, req);
2655 
2656                 if (!blequal(&l_admin_low->tsl_label, clabel)) {
2657                         if (!do_rfs_label_check(clabel, vp, EQUALITY_CHECK,
2658                             exi)) {
2659                                 resp->status = NFS3ERR_ACCES;
2660                                 goto err1;
2661                         }
2662                 }
2663         }
2664 
2665         ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
2666         name = nfscmd_convname(ca, exi, args->object.name,
2667             NFSCMD_CONV_INBOUND, MAXPATHLEN + 1);
2668 
2669         if (name == NULL) {
2670                 resp->status = NFS3ERR_INVAL;
2671                 goto err1;
2672         }
2673 

2674         error = VOP_RMDIR(vp, name, ZONE_ROOTVP(), cr, NULL, 0);
2675 
2676         if (name != args->object.name)
2677                 kmem_free(name, MAXPATHLEN + 1);
2678 
2679         ava.va_mask = AT_ALL;
2680         avap = VOP_GETATTR(vp, &ava, 0, cr, NULL) ? NULL : &ava;
2681 
2682         /*
2683          * Force modified data and metadata out to stable storage.
2684          */
2685         (void) VOP_FSYNC(vp, 0, cr, NULL);
2686 
2687         if (error) {
2688                 /*
2689                  * System V defines rmdir to return EEXIST, not ENOTEMPTY,
2690                  * if the directory is not empty.  A System V NFS server
2691                  * needs to map NFS3ERR_EXIST to NFS3ERR_NOTEMPTY to transmit
2692                  * over the wire.
2693                  */


4116         vnode_t *vp;
4117         struct vattr *bvap;
4118         struct vattr bva;
4119         struct vattr *avap;
4120         struct vattr ava;
4121 
4122         bvap = NULL;
4123         avap = NULL;
4124 
4125         vp = nfs3_fhtovp(&args->file, exi);
4126 
4127         DTRACE_NFSV3_5(op__commit__start, struct svc_req *, req,
4128             cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
4129             COMMIT3args *, args);
4130 
4131         if (vp == NULL) {
4132                 error = ESTALE;
4133                 goto out;
4134         }
4135 

4136         ns = nfs3_get_srv();
4137         bva.va_mask = AT_ALL;
4138         error = VOP_GETATTR(vp, &bva, 0, cr, NULL);
4139 
4140         /*
4141          * If we can't get the attributes, then we can't do the
4142          * right access checking.  So, we'll fail the request.
4143          */
4144         if (error)
4145                 goto out;
4146 
4147         bvap = &bva;
4148 
4149         if (rdonly(ro, vp)) {
4150                 resp->status = NFS3ERR_ROFS;
4151                 goto out1;
4152         }
4153 
4154         if (vp->v_type != VREG) {
4155                 resp->status = NFS3ERR_INVAL;




 394         struct vattr *vap;
 395         struct vattr va;
 396         struct vattr *dvap;
 397         struct vattr dva;
 398         nfs_fh3 *fhp;
 399         struct sec_ol sec = {0, 0};
 400         bool_t publicfh_flag = FALSE, auth_weak = FALSE;
 401         struct sockaddr *ca;
 402         char *name = NULL;
 403 
 404         dvap = NULL;
 405 
 406         if (exi != NULL)
 407                 exi_hold(exi);
 408 
 409         /*
 410          * Allow lookups from the root - the default
 411          * location of the public filehandle.
 412          */
 413         if (exi != NULL && (exi->exi_export.ex_flags & EX_PUBLIC)) {
 414                 ASSERT3U(exi->exi_zoneid, ==, curzone->zone_id);
 415                 dvp = ZONE_ROOTVP();
 416                 VN_HOLD(dvp);
 417 
 418                 DTRACE_NFSV3_5(op__lookup__start, struct svc_req *, req,
 419                     cred_t *, cr, vnode_t *, dvp, struct exportinfo *, exi,
 420                     LOOKUP3args *, args);
 421         } else {
 422                 dvp = nfs3_fhtovp(&args->what.dir, exi);
 423 
 424                 DTRACE_NFSV3_5(op__lookup__start, struct svc_req *, req,
 425                     cred_t *, cr, vnode_t *, dvp, struct exportinfo *, exi,
 426                     LOOKUP3args *, args);
 427 
 428                 if (dvp == NULL) {
 429                         error = ESTALE;
 430                         goto out;
 431                 }
 432         }
 433 
 434         dva.va_mask = AT_ALL;
 435         dvap = VOP_GETATTR(dvp, &dva, 0, cr, NULL) ? NULL : &dva;
 436 
 437         if (args->what.name == nfs3nametoolong) {
 438                 resp->status = NFS3ERR_NAMETOOLONG;
 439                 goto out1;
 440         }
 441 
 442         if (args->what.name == NULL || *(args->what.name) == '\0') {
 443                 resp->status = NFS3ERR_ACCES;
 444                 goto out1;
 445         }
 446 
 447         fhp = &args->what.dir;
 448         ASSERT3U(curzone->zone_id, ==, exi->exi_zoneid); /* exi is non-NULL */
 449         if (strcmp(args->what.name, "..") == 0 &&
 450             EQFID(&exi->exi_fid, FH3TOFIDP(fhp))) {
 451                 if ((exi->exi_export.ex_flags & EX_NOHIDE) &&
 452                     ((dvp->v_flag & VROOT) || VN_IS_CURZONEROOT(dvp))) {
 453                         /*
 454                          * special case for ".." and 'nohide'exported root
 455                          */
 456                         if (rfs_climb_crossmnt(&dvp, &exi, cr) != 0) {
 457                                 resp->status = NFS3ERR_ACCES;
 458                                 goto out1;
 459                         }
 460                 } else {
 461                         resp->status = NFS3ERR_NOENT;
 462                         goto out1;
 463                 }
 464         }
 465 
 466         ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
 467         name = nfscmd_convname(ca, exi, args->what.name,
 468             NFSCMD_CONV_INBOUND, MAXPATHLEN + 1);
 469 
 470         if (name == NULL) {
 471                 resp->status = NFS3ERR_ACCES;
 472                 goto out1;
 473         }
 474 
 475         /*
 476          * If the public filehandle is used then allow
 477          * a multi-component lookup
 478          */
 479         if (PUBLIC_FH3(&args->what.dir)) {
 480                 publicfh_flag = TRUE;
 481 
 482                 exi_rele(exi);
 483                 exi = NULL;
 484 
 485                 error = rfs_publicfh_mclookup(name, dvp, cr, &vp,
 486                     &exi, &sec);
 487 
 488                 /*
 489                  * Since WebNFS may bypass MOUNT, we need to ensure this
 490                  * request didn't come from an unlabeled admin_low client.
 491                  */
 492                 if (is_system_labeled() && error == 0) {
 493                         int             addr_type;
 494                         void            *ipaddr;
 495                         tsol_tpc_t      *tp;
 496 
 497                         if (ca->sa_family == AF_INET) {
 498                                 addr_type = IPV4_VERSION;
 499                                 ipaddr = &((struct sockaddr_in *)ca)->sin_addr;
 500                         } else if (ca->sa_family == AF_INET6) {
 501                                 addr_type = IPV6_VERSION;
 502                                 ipaddr = &((struct sockaddr_in6 *)
 503                                     ca)->sin6_addr;


 547 
 548         if (error)
 549                 goto out;
 550 
 551         if (sec.sec_flags & SEC_QUERY) {
 552                 error = makefh3_ol(&resp->resok.object, exi, sec.sec_index);
 553         } else {
 554                 error = makefh3(&resp->resok.object, vp, exi);
 555                 if (!error && publicfh_flag && !chk_clnt_sec(exi, req))
 556                         auth_weak = TRUE;
 557         }
 558 
 559         if (error) {
 560                 VN_RELE(vp);
 561                 goto out;
 562         }
 563 
 564         va.va_mask = AT_ALL;
 565         vap = rfs4_delegated_getattr(vp, &va, 0, cr) ? NULL : &va;
 566 

 567         VN_RELE(vp);
 568 
 569         resp->status = NFS3_OK;
 570         vattr_to_post_op_attr(vap, &resp->resok.obj_attributes);
 571         vattr_to_post_op_attr(dvap, &resp->resok.dir_attributes);
 572 
 573         /*
 574          * If it's public fh, no 0x81, and client's flavor is
 575          * invalid, set WebNFS status to WNFSERR_CLNT_FLAVOR now.
 576          * Then set RPC status to AUTH_TOOWEAK in common_dispatch.
 577          */
 578         if (auth_weak)
 579                 resp->status = (enum nfsstat3)WNFSERR_CLNT_FLAVOR;
 580 
 581         DTRACE_NFSV3_5(op__lookup__done, struct svc_req *, req,
 582             cred_t *, cr, vnode_t *, dvp, struct exportinfo *, exi,
 583             LOOKUP3res *, resp);
 584         VN_RELE(dvp);
 585         exi_rele(exi);
 586 
 587         return;
 588 
 589 out:
 590         if (curthread->t_flag & T_WOULDBLOCK) {
 591                 curthread->t_flag &= ~T_WOULDBLOCK;
 592                 resp->status = NFS3ERR_JUKEBOX;
 593         } else
 594                 resp->status = puterrno3(error);
 595 out1:
 596         DTRACE_NFSV3_5(op__lookup__done, struct svc_req *, req,
 597             cred_t *, cr, vnode_t *, dvp, struct exportinfo *, exi,
 598             LOOKUP3res *, resp);
 599 
 600         if (exi != NULL)
 601                 exi_rele(exi);
 602 
 603         if (dvp != NULL)
 604                 VN_RELE(dvp);
 605         vattr_to_post_op_attr(dvap, &resp->resfail.dir_attributes);


1319         mblk_t *m;
1320         struct iovec *iovp;
1321         int iovcnt;
1322         int ioflag;
1323         cred_t *savecred;
1324         int in_crit = 0;
1325         int rwlock_ret = -1;
1326         caller_context_t ct;
1327 
1328         vp = nfs3_fhtovp(&args->file, exi);
1329 
1330         DTRACE_NFSV3_5(op__write__start, struct svc_req *, req,
1331             cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
1332             WRITE3args *, args);
1333 
1334         if (vp == NULL) {
1335                 error = ESTALE;
1336                 goto err;
1337         }
1338 
1339         ASSERT3U(curzone->zone_id, ==, exi->exi_zoneid); /* exi is non-NULL. */
1340         ns = nfs3_get_srv();
1341 
1342         if (is_system_labeled()) {
1343                 bslabel_t *clabel = req->rq_label;
1344 
1345                 ASSERT(clabel != NULL);
1346                 DTRACE_PROBE2(tx__rfs3__log__info__opwrite__clabel, char *,
1347                     "got client label from request(1)", struct svc_req *, req);
1348 
1349                 if (!blequal(&l_admin_low->tsl_label, clabel)) {
1350                         if (!do_rfs_label_check(clabel, vp, EQUALITY_CHECK,
1351                             exi)) {
1352                                 resp->status = NFS3ERR_ACCES;
1353                                 goto err1;
1354                         }
1355                 }
1356         }
1357 
1358         ct.cc_sysid = 0;
1359         ct.cc_pid = 0;
1360         ct.cc_caller_id = nfs3_srv_caller_id;
1361         ct.cc_flags = CC_DONTBLOCK;


2659                     "got client label from request(1)", struct svc_req *, req);
2660 
2661                 if (!blequal(&l_admin_low->tsl_label, clabel)) {
2662                         if (!do_rfs_label_check(clabel, vp, EQUALITY_CHECK,
2663                             exi)) {
2664                                 resp->status = NFS3ERR_ACCES;
2665                                 goto err1;
2666                         }
2667                 }
2668         }
2669 
2670         ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
2671         name = nfscmd_convname(ca, exi, args->object.name,
2672             NFSCMD_CONV_INBOUND, MAXPATHLEN + 1);
2673 
2674         if (name == NULL) {
2675                 resp->status = NFS3ERR_INVAL;
2676                 goto err1;
2677         }
2678 
2679         ASSERT3U(exi->exi_zoneid, ==, curzone->zone_id);
2680         error = VOP_RMDIR(vp, name, ZONE_ROOTVP(), cr, NULL, 0);
2681 
2682         if (name != args->object.name)
2683                 kmem_free(name, MAXPATHLEN + 1);
2684 
2685         ava.va_mask = AT_ALL;
2686         avap = VOP_GETATTR(vp, &ava, 0, cr, NULL) ? NULL : &ava;
2687 
2688         /*
2689          * Force modified data and metadata out to stable storage.
2690          */
2691         (void) VOP_FSYNC(vp, 0, cr, NULL);
2692 
2693         if (error) {
2694                 /*
2695                  * System V defines rmdir to return EEXIST, not ENOTEMPTY,
2696                  * if the directory is not empty.  A System V NFS server
2697                  * needs to map NFS3ERR_EXIST to NFS3ERR_NOTEMPTY to transmit
2698                  * over the wire.
2699                  */


4122         vnode_t *vp;
4123         struct vattr *bvap;
4124         struct vattr bva;
4125         struct vattr *avap;
4126         struct vattr ava;
4127 
4128         bvap = NULL;
4129         avap = NULL;
4130 
4131         vp = nfs3_fhtovp(&args->file, exi);
4132 
4133         DTRACE_NFSV3_5(op__commit__start, struct svc_req *, req,
4134             cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
4135             COMMIT3args *, args);
4136 
4137         if (vp == NULL) {
4138                 error = ESTALE;
4139                 goto out;
4140         }
4141 
4142         ASSERT3U(curzone->zone_id, ==, exi->exi_zoneid); /* exi is non-NULL. */
4143         ns = nfs3_get_srv();
4144         bva.va_mask = AT_ALL;
4145         error = VOP_GETATTR(vp, &bva, 0, cr, NULL);
4146 
4147         /*
4148          * If we can't get the attributes, then we can't do the
4149          * right access checking.  So, we'll fail the request.
4150          */
4151         if (error)
4152                 goto out;
4153 
4154         bvap = &bva;
4155 
4156         if (rdonly(ro, vp)) {
4157                 resp->status = NFS3ERR_ROFS;
4158                 goto out1;
4159         }
4160 
4161         if (vp->v_type != VREG) {
4162                 resp->status = NFS3ERR_INVAL;