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