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