Print this page
Caution with use after exi_rele()
Be far more judicious in the use of curzone-using macros.


 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;


 462                 }
 463         }
 464 
 465         ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
 466         name = nfscmd_convname(ca, exi, args->what.name,
 467             NFSCMD_CONV_INBOUND, MAXPATHLEN + 1);
 468 
 469         if (name == NULL) {
 470                 resp->status = NFS3ERR_ACCES;
 471                 goto out1;
 472         }
 473 
 474         /*
 475          * If the public filehandle is used then allow
 476          * a multi-component lookup
 477          */
 478         if (PUBLIC_FH3(&args->what.dir)) {
 479                 publicfh_flag = TRUE;
 480 
 481                 exi_rele(exi);

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


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

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


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

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




 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;


 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);


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                  */