54 #include <nfs/nfs.h>
55 #include <nfs/export.h>
56 #include <nfs/nfs_cmd.h>
57
58 #include <sys/strsubr.h>
59
60 #include <sys/tsol/label.h>
61 #include <sys/tsol/tndb.h>
62
63 #include <sys/zone.h>
64
65 #include <inet/ip.h>
66 #include <inet/ip6.h>
67
68 /*
69 * These are the interface routines for the server side of the
70 * Network File System. See the NFS version 3 protocol specification
71 * for a description of this interface.
72 */
73
74 #ifdef DEBUG
75 int rfs3_do_pre_op_attr = 1;
76 int rfs3_do_post_op_attr = 1;
77 int rfs3_do_post_op_fh3 = 1;
78 #endif
79
80 static writeverf3 write3verf;
81
82 static int sattr3_to_vattr(sattr3 *, struct vattr *);
83 static int vattr_to_fattr3(struct vattr *, fattr3 *);
84 static int vattr_to_wcc_attr(struct vattr *, wcc_attr *);
85 static void vattr_to_pre_op_attr(struct vattr *, pre_op_attr *);
86 static void vattr_to_wcc_data(struct vattr *, struct vattr *, wcc_data *);
87 static int rdma_setup_read_data3(READ3args *, READ3resok *);
88
89 extern int nfs_loaned_buffers;
90
91 u_longlong_t nfs3_srv_caller_id;
92
93 /* ARGSUSED */
94 void
95 rfs3_getattr(GETATTR3args *args, GETATTR3res *resp, struct exportinfo *exi,
96 struct svc_req *req, cred_t *cr)
97 {
98 int error;
99 vnode_t *vp;
210 * delegated this file. If so, then we return JUKEBOX to
211 * allow the client to retrasmit its request.
212 */
213 if (vp->v_type == VREG && (ava.va_mask & AT_SIZE)) {
214 if (nbl_need_check(vp)) {
215 nbl_start_crit(vp, RW_READER);
216 in_crit = 1;
217 }
218 }
219
220 bva.va_mask = AT_ALL;
221 error = rfs4_delegated_getattr(vp, &bva, 0, cr);
222
223 /*
224 * If we can't get the attributes, then we can't do the
225 * right access checking. So, we'll fail the request.
226 */
227 if (error)
228 goto out;
229
230 #ifdef DEBUG
231 if (rfs3_do_pre_op_attr)
232 bvap = &bva;
233 #else
234 bvap = &bva;
235 #endif
236
237 if (rdonly(exi, req) || vn_is_readonly(vp)) {
238 resp->status = NFS3ERR_ROFS;
239 goto out1;
240 }
241
242 if (args->guard.check &&
243 (args->guard.obj_ctime.seconds != bva.va_ctime.tv_sec ||
244 args->guard.obj_ctime.nseconds != bva.va_ctime.tv_nsec)) {
245 resp->status = NFS3ERR_NOT_SYNC;
246 goto out1;
247 }
248
249 if (args->new_attributes.mtime.set_it == SET_TO_CLIENT_TIME)
250 flag = ATTR_UTIME;
251 else
252 flag = 0;
253
254 /*
255 * If the filesystem is exported with nosuid, then mask off
305 bf.l_type = F_WRLCK;
306 bf.l_whence = 0;
307 bf.l_start = (off64_t)ava.va_size;
308 bf.l_len = 0;
309 bf.l_sysid = 0;
310 bf.l_pid = 0;
311 error = VOP_SPACE(vp, F_FREESP, &bf, FWRITE,
312 (offset_t)ava.va_size, cr, &ct);
313 }
314 }
315
316 if (!error && ava.va_mask)
317 error = VOP_SETATTR(vp, &ava, flag, cr, &ct);
318
319 /* check if a monitor detected a delegation conflict */
320 if (error == EAGAIN && (ct.cc_flags & CC_WOULDBLOCK)) {
321 resp->status = NFS3ERR_JUKEBOX;
322 goto out1;
323 }
324
325 #ifdef DEBUG
326 if (rfs3_do_post_op_attr) {
327 ava.va_mask = AT_ALL;
328 avap = rfs4_delegated_getattr(vp, &ava, 0, cr) ? NULL : &ava;
329 } else
330 avap = NULL;
331 #else
332 ava.va_mask = AT_ALL;
333 avap = rfs4_delegated_getattr(vp, &ava, 0, cr) ? NULL : &ava;
334 #endif
335
336 /*
337 * Force modified metadata out to stable storage.
338 */
339 (void) VOP_FSYNC(vp, FNODSYNC, cr, &ct);
340
341 if (error)
342 goto out;
343
344 if (in_crit)
345 nbl_end_crit(vp);
346
347 resp->status = NFS3_OK;
348 vattr_to_wcc_data(bvap, avap, &resp->resok.obj_wcc);
349
350 DTRACE_NFSV3_4(op__setattr__done, struct svc_req *, req,
351 cred_t *, cr, vnode_t *, vp, SETATTR3res *, resp);
352
353 VN_RELE(vp);
354
404 * location of the public filehandle.
405 */
406 if (exi != NULL && (exi->exi_export.ex_flags & EX_PUBLIC)) {
407 dvp = rootdir;
408 VN_HOLD(dvp);
409
410 DTRACE_NFSV3_4(op__lookup__start, struct svc_req *, req,
411 cred_t *, cr, vnode_t *, dvp, LOOKUP3args *, args);
412 } else {
413 dvp = nfs3_fhtovp(&args->what.dir, exi);
414
415 DTRACE_NFSV3_4(op__lookup__start, struct svc_req *, req,
416 cred_t *, cr, vnode_t *, dvp, LOOKUP3args *, args);
417
418 if (dvp == NULL) {
419 error = ESTALE;
420 goto out;
421 }
422 }
423
424 #ifdef DEBUG
425 if (rfs3_do_pre_op_attr) {
426 dva.va_mask = AT_ALL;
427 dvap = VOP_GETATTR(dvp, &dva, 0, cr, NULL) ? NULL : &dva;
428 }
429 #else
430 dva.va_mask = AT_ALL;
431 dvap = VOP_GETATTR(dvp, &dva, 0, cr, NULL) ? NULL : &dva;
432 #endif
433
434 if (args->what.name == nfs3nametoolong) {
435 resp->status = NFS3ERR_NAMETOOLONG;
436 goto out1;
437 }
438
439 if (args->what.name == NULL || *(args->what.name) == '\0') {
440 resp->status = NFS3ERR_ACCES;
441 goto out1;
442 }
443
444 fhp = &args->what.dir;
445 if (strcmp(args->what.name, "..") == 0 &&
446 EQFID(&exi->exi_fid, FH3TOFIDP(fhp))) {
447 resp->status = NFS3ERR_NOENT;
448 goto out1;
449 }
450
451 ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
452 name = nfscmd_convname(ca, exi, args->what.name,
507
508 if (is_system_labeled() && error == 0) {
509 bslabel_t *clabel = req->rq_label;
510
511 ASSERT(clabel != NULL);
512 DTRACE_PROBE2(tx__rfs3__log__info__oplookup__clabel, char *,
513 "got client label from request(1)", struct svc_req *, req);
514
515 if (!blequal(&l_admin_low->tsl_label, clabel)) {
516 if (!do_rfs_label_check(clabel, dvp,
517 DOMINANCE_CHECK, exi)) {
518 if (publicfh_flag && exi != NULL)
519 exi_rele(exi);
520 VN_RELE(vp);
521 resp->status = NFS3ERR_ACCES;
522 error = 1;
523 }
524 }
525 }
526
527 #ifdef DEBUG
528 if (rfs3_do_post_op_attr) {
529 dva.va_mask = AT_ALL;
530 dvap = VOP_GETATTR(dvp, &dva, 0, cr, NULL) ? NULL : &dva;
531 } else
532 dvap = NULL;
533 #else
534 dva.va_mask = AT_ALL;
535 dvap = VOP_GETATTR(dvp, &dva, 0, cr, NULL) ? NULL : &dva;
536 #endif
537
538 if (error)
539 goto out;
540
541 if (sec.sec_flags & SEC_QUERY) {
542 error = makefh3_ol(&resp->resok.object, exi, sec.sec_index);
543 } else {
544 error = makefh3(&resp->resok.object, vp, exi);
545 if (!error && publicfh_flag && !chk_clnt_sec(exi, req))
546 auth_weak = TRUE;
547 }
548
549 if (error) {
550 VN_RELE(vp);
551 goto out;
552 }
553
554 /*
555 * If publicfh_flag is true then we have called rfs_publicfh_mclookup
556 * and have obtained a new exportinfo in exi which needs to be
557 * released. Note the the original exportinfo pointed to by exi
558 * will be released by the caller, common_dispatch.
559 */
560 if (publicfh_flag)
561 exi_rele(exi);
562
563 #ifdef DEBUG
564 if (rfs3_do_post_op_attr) {
565 va.va_mask = AT_ALL;
566 vap = rfs4_delegated_getattr(vp, &va, 0, cr) ? NULL : &va;
567 } else
568 vap = NULL;
569 #else
570 va.va_mask = AT_ALL;
571 vap = rfs4_delegated_getattr(vp, &va, 0, cr) ? NULL : &va;
572 #endif
573
574 VN_RELE(vp);
575
576 resp->status = NFS3_OK;
577 vattr_to_post_op_attr(vap, &resp->resok.obj_attributes);
578 vattr_to_post_op_attr(dvap, &resp->resok.dir_attributes);
579
580 /*
581 * If it's public fh, no 0x81, and client's flavor is
582 * invalid, set WebNFS status to WNFSERR_CLNT_FLAVOR now.
583 * Then set RPC status to AUTH_TOOWEAK in common_dispatch.
584 */
585 if (auth_weak)
586 resp->status = (enum nfsstat3)WNFSERR_CLNT_FLAVOR;
587
588 DTRACE_NFSV3_4(op__lookup__done, struct svc_req *, req,
589 cred_t *, cr, vnode_t *, dvp, LOOKUP3res *, resp);
590 VN_RELE(dvp);
591
592 return;
645 * to check write permissions for regular files and directories.
646 * Special files are interpreted by the client, so the underlying
647 * permissions are sent back to the client for interpretation.
648 */
649 if (rdonly(exi, req) && (vp->v_type == VREG || vp->v_type == VDIR))
650 checkwriteperm = 0;
651 else
652 checkwriteperm = 1;
653
654 /*
655 * We need the mode so that we can correctly determine access
656 * permissions relative to a mandatory lock file. Access to
657 * mandatory lock files is denied on the server, so it might
658 * as well be reflected to the server during the open.
659 */
660 va.va_mask = AT_MODE;
661 error = VOP_GETATTR(vp, &va, 0, cr, NULL);
662 if (error)
663 goto out;
664
665 #ifdef DEBUG
666 if (rfs3_do_post_op_attr)
667 vap = &va;
668 #else
669 vap = &va;
670 #endif
671
672 resp->resok.access = 0;
673
674 if (is_system_labeled()) {
675 bslabel_t *clabel = req->rq_label;
676
677 ASSERT(clabel != NULL);
678 DTRACE_PROBE2(tx__rfs3__log__info__opaccess__clabel, char *,
679 "got client label from request(1)", struct svc_req *, req);
680
681 if (!blequal(&l_admin_low->tsl_label, clabel)) {
682 if ((equal_label = do_rfs_label_check(clabel, vp,
683 EQUALITY_CHECK, exi)) == B_FALSE) {
684 dominant_label = do_rfs_label_check(clabel,
685 vp, DOMINANCE_CHECK, exi);
686 } else
687 dominant_label = B_TRUE;
688 admin_low_client = B_FALSE;
689 } else
690 admin_low_client = B_TRUE;
725 (args->access & ACCESS3_DELETE) && vp->v_type == VDIR) {
726 error = VOP_ACCESS(vp, VWRITE, 0, cr, NULL);
727 if (error) {
728 if (curthread->t_flag & T_WOULDBLOCK)
729 goto out;
730 } else if (!is_system_labeled() || admin_low_client ||
731 equal_label)
732 resp->resok.access |= ACCESS3_DELETE;
733 }
734 if (args->access & ACCESS3_EXECUTE) {
735 error = VOP_ACCESS(vp, VEXEC, 0, cr, NULL);
736 if (error) {
737 if (curthread->t_flag & T_WOULDBLOCK)
738 goto out;
739 } else if (!MANDLOCK(vp, va.va_mode) &&
740 (!is_system_labeled() || admin_low_client ||
741 dominant_label))
742 resp->resok.access |= ACCESS3_EXECUTE;
743 }
744
745 #ifdef DEBUG
746 if (rfs3_do_post_op_attr) {
747 va.va_mask = AT_ALL;
748 vap = rfs4_delegated_getattr(vp, &va, 0, cr) ? NULL : &va;
749 } else
750 vap = NULL;
751 #else
752 va.va_mask = AT_ALL;
753 vap = rfs4_delegated_getattr(vp, &va, 0, cr) ? NULL : &va;
754 #endif
755
756 resp->status = NFS3_OK;
757 vattr_to_post_op_attr(vap, &resp->resok.obj_attributes);
758
759 DTRACE_NFSV3_4(op__access__done, struct svc_req *, req,
760 cred_t *, cr, vnode_t *, vp, ACCESS3res *, resp);
761
762 VN_RELE(vp);
763
764 return;
765
766 out:
767 if (curthread->t_flag & T_WOULDBLOCK) {
768 curthread->t_flag &= ~T_WOULDBLOCK;
769 resp->status = NFS3ERR_JUKEBOX;
770 } else
771 resp->status = puterrno3(error);
772 DTRACE_NFSV3_4(op__access__done, struct svc_req *, req,
773 cred_t *, cr, vnode_t *, vp, ACCESS3res *, resp);
774 if (vp != NULL)
799 char *name = NULL;
800 int is_referral = 0;
801
802 vap = NULL;
803
804 vp = nfs3_fhtovp(&args->symlink, exi);
805
806 DTRACE_NFSV3_4(op__readlink__start, struct svc_req *, req,
807 cred_t *, cr, vnode_t *, vp, READLINK3args *, args);
808
809 if (vp == NULL) {
810 error = ESTALE;
811 goto out;
812 }
813
814 va.va_mask = AT_ALL;
815 error = VOP_GETATTR(vp, &va, 0, cr, NULL);
816 if (error)
817 goto out;
818
819 #ifdef DEBUG
820 if (rfs3_do_post_op_attr)
821 vap = &va;
822 #else
823 vap = &va;
824 #endif
825
826 /* We lied about the object type for a referral */
827 if (vn_is_nfs_reparse(vp, cr))
828 is_referral = 1;
829
830 if (vp->v_type != VLNK && !is_referral) {
831 resp->status = NFS3ERR_INVAL;
832 goto out1;
833 }
834
835 if (MANDLOCK(vp, va.va_mode)) {
836 resp->status = NFS3ERR_ACCES;
837 goto out1;
838 }
839
840 if (is_system_labeled()) {
841 bslabel_t *clabel = req->rq_label;
842
843 ASSERT(clabel != NULL);
844 DTRACE_PROBE2(tx__rfs3__log__info__opreadlink__clabel, char *,
872 kmem_free(s, strsz);
873 }
874
875 } else {
876
877 iov.iov_base = data;
878 iov.iov_len = MAXPATHLEN;
879 uio.uio_iov = &iov;
880 uio.uio_iovcnt = 1;
881 uio.uio_segflg = UIO_SYSSPACE;
882 uio.uio_extflg = UIO_COPY_CACHED;
883 uio.uio_loffset = 0;
884 uio.uio_resid = MAXPATHLEN;
885
886 error = VOP_READLINK(vp, &uio, cr, NULL);
887
888 if (!error)
889 *(data + MAXPATHLEN - uio.uio_resid) = '\0';
890 }
891
892 #ifdef DEBUG
893 if (rfs3_do_post_op_attr) {
894 va.va_mask = AT_ALL;
895 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
896 } else
897 vap = NULL;
898 #else
899 va.va_mask = AT_ALL;
900 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
901 #endif
902 /* Lie about object type again just to be consistent */
903 if (is_referral && vap != NULL)
904 vap->va_type = VLNK;
905
906 #if 0 /* notyet */
907 /*
908 * Don't do this. It causes local disk writes when just
909 * reading the file and the overhead is deemed larger
910 * than the benefit.
911 */
912 /*
913 * Force modified metadata out to stable storage.
914 */
915 (void) VOP_FSYNC(vp, FNODSYNC, cr, NULL);
916 #endif
917
918 if (error) {
919 kmem_free(data, MAXPATHLEN + 1);
920 goto out;
921 }
1060 error = VOP_RWLOCK(vp, V_WRITELOCK_FALSE, &ct);
1061
1062 /* check if a monitor detected a delegation conflict */
1063 if (error == EAGAIN && (ct.cc_flags & CC_WOULDBLOCK)) {
1064 resp->status = NFS3ERR_JUKEBOX;
1065 goto out1;
1066 }
1067
1068 need_rwunlock = 1;
1069
1070 va.va_mask = AT_ALL;
1071 error = VOP_GETATTR(vp, &va, 0, cr, &ct);
1072
1073 /*
1074 * If we can't get the attributes, then we can't do the
1075 * right access checking. So, we'll fail the request.
1076 */
1077 if (error)
1078 goto out;
1079
1080 #ifdef DEBUG
1081 if (rfs3_do_post_op_attr)
1082 vap = &va;
1083 #else
1084 vap = &va;
1085 #endif
1086
1087 if (vp->v_type != VREG) {
1088 resp->status = NFS3ERR_INVAL;
1089 goto out1;
1090 }
1091
1092 if (crgetuid(cr) != va.va_uid) {
1093 error = VOP_ACCESS(vp, VREAD, 0, cr, &ct);
1094 if (error) {
1095 if (curthread->t_flag & T_WOULDBLOCK)
1096 goto out;
1097 error = VOP_ACCESS(vp, VEXEC, 0, cr, &ct);
1098 if (error)
1099 goto out;
1100 }
1101 }
1102
1103 if (MANDLOCK(vp, va.va_mode)) {
1104 resp->status = NFS3ERR_ACCES;
1105 goto out1;
1215 if (error) {
1216 if (mp)
1217 freemsg(mp);
1218 /* check if a monitor detected a delegation conflict */
1219 if (error == EAGAIN && (ct.cc_flags & CC_WOULDBLOCK)) {
1220 resp->status = NFS3ERR_JUKEBOX;
1221 goto out1;
1222 }
1223 goto out;
1224 }
1225
1226 /* make mblk using zc buffers */
1227 if (loaned_buffers) {
1228 mp = uio_to_mblk(uiop);
1229 ASSERT(mp != NULL);
1230 }
1231
1232 va.va_mask = AT_ALL;
1233 error = VOP_GETATTR(vp, &va, 0, cr, &ct);
1234
1235 #ifdef DEBUG
1236 if (rfs3_do_post_op_attr) {
1237 if (error)
1238 vap = NULL;
1239 else
1240 vap = &va;
1241 } else
1242 vap = NULL;
1243 #else
1244 if (error)
1245 vap = NULL;
1246 else
1247 vap = &va;
1248 #endif
1249
1250 VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, &ct);
1251
1252 if (in_crit)
1253 nbl_end_crit(vp);
1254
1255 resp->status = NFS3_OK;
1256 vattr_to_post_op_attr(vap, &resp->resok.file_attributes);
1257 resp->resok.count = args->count - uiop->uio_resid;
1258 if (!error && offset + resp->resok.count == va.va_size)
1259 resp->resok.eof = TRUE;
1260 else
1261 resp->resok.eof = FALSE;
1262 resp->resok.data.data_len = resp->resok.count;
1263
1264 if (mp)
1265 rfs_rndup_mblks(mp, resp->resok.count, loaned_buffers);
1266
1267 resp->resok.data.mp = mp;
1268 resp->resok.size = (uint_t)args->count;
1402
1403 /* check if a monitor detected a delegation conflict */
1404 if (rwlock_ret == EAGAIN && (ct.cc_flags & CC_WOULDBLOCK)) {
1405 resp->status = NFS3ERR_JUKEBOX;
1406 rwlock_ret = -1;
1407 goto err1;
1408 }
1409
1410
1411 bva.va_mask = AT_ALL;
1412 error = VOP_GETATTR(vp, &bva, 0, cr, &ct);
1413
1414 /*
1415 * If we can't get the attributes, then we can't do the
1416 * right access checking. So, we'll fail the request.
1417 */
1418 if (error)
1419 goto err;
1420
1421 bvap = &bva;
1422 #ifdef DEBUG
1423 if (!rfs3_do_pre_op_attr)
1424 bvap = NULL;
1425 #endif
1426 avap = bvap;
1427
1428 if (args->count != args->data.data_len) {
1429 resp->status = NFS3ERR_INVAL;
1430 goto err1;
1431 }
1432
1433 if (rdonly(exi, req)) {
1434 resp->status = NFS3ERR_ROFS;
1435 goto err1;
1436 }
1437
1438 if (vp->v_type != VREG) {
1439 resp->status = NFS3ERR_INVAL;
1440 goto err1;
1441 }
1442
1443 if (crgetuid(cr) != bva.va_uid &&
1444 (error = VOP_ACCESS(vp, VWRITE, 0, cr, &ct)))
1445 goto err;
1517 * the cred of the current thread to be used if quota
1518 * checking is enabled.
1519 */
1520 savecred = curthread->t_cred;
1521 curthread->t_cred = cr;
1522 error = VOP_WRITE(vp, &uio, ioflag, cr, &ct);
1523 curthread->t_cred = savecred;
1524
1525 if (iovp != iov)
1526 kmem_free(iovp, sizeof (*iovp) * iovcnt);
1527
1528 /* check if a monitor detected a delegation conflict */
1529 if (error == EAGAIN && (ct.cc_flags & CC_WOULDBLOCK)) {
1530 resp->status = NFS3ERR_JUKEBOX;
1531 goto err1;
1532 }
1533
1534 ava.va_mask = AT_ALL;
1535 avap = VOP_GETATTR(vp, &ava, 0, cr, &ct) ? NULL : &ava;
1536
1537 #ifdef DEBUG
1538 if (!rfs3_do_post_op_attr)
1539 avap = NULL;
1540 #endif
1541
1542 if (error)
1543 goto err;
1544
1545 /*
1546 * If we were unable to get the V_WRITELOCK_TRUE, then we
1547 * may not have accurate after attrs, so check if
1548 * we have both attributes, they have a non-zero va_seq, and
1549 * va_seq has changed by exactly one,
1550 * if not, turn off the before attr.
1551 */
1552 if (rwlock_ret != V_WRITELOCK_TRUE) {
1553 if (bvap == NULL || avap == NULL ||
1554 bvap->va_seq == 0 || avap->va_seq == 0 ||
1555 avap->va_seq != (bvap->va_seq + 1)) {
1556 bvap = NULL;
1557 }
1558 }
1559
1560 resp->status = NFS3_OK;
1561 vattr_to_wcc_data(bvap, avap, &resp->resok.file_wcc);
1610 enum vcexcl excl;
1611 nfstime3 *mtime;
1612 len_t reqsize;
1613 bool_t trunc;
1614 struct sockaddr *ca;
1615 char *name = NULL;
1616
1617 dbvap = NULL;
1618 davap = NULL;
1619
1620 dvp = nfs3_fhtovp(&args->where.dir, exi);
1621
1622 DTRACE_NFSV3_4(op__create__start, struct svc_req *, req,
1623 cred_t *, cr, vnode_t *, dvp, CREATE3args *, args);
1624
1625 if (dvp == NULL) {
1626 error = ESTALE;
1627 goto out;
1628 }
1629
1630 #ifdef DEBUG
1631 if (rfs3_do_pre_op_attr) {
1632 dbva.va_mask = AT_ALL;
1633 dbvap = VOP_GETATTR(dvp, &dbva, 0, cr, NULL) ? NULL : &dbva;
1634 } else
1635 dbvap = NULL;
1636 #else
1637 dbva.va_mask = AT_ALL;
1638 dbvap = VOP_GETATTR(dvp, &dbva, 0, cr, NULL) ? NULL : &dbva;
1639 #endif
1640 davap = dbvap;
1641
1642 if (args->where.name == nfs3nametoolong) {
1643 resp->status = NFS3ERR_NAMETOOLONG;
1644 goto out1;
1645 }
1646
1647 if (args->where.name == NULL || *(args->where.name) == '\0') {
1648 resp->status = NFS3ERR_ACCES;
1649 goto out1;
1650 }
1651
1652 if (rdonly(exi, req)) {
1653 resp->status = NFS3ERR_ROFS;
1654 goto out1;
1655 }
1656
1657 if (is_system_labeled()) {
1658 bslabel_t *clabel = req->rq_label;
1659
1782 goto out1;
1783 }
1784
1785 /*
1786 * If the filesystem is exported with nosuid, then mask off
1787 * the setuid and setgid bits.
1788 */
1789 if (va.va_type == VREG && (exi->exi_export.ex_flags & EX_NOSUID))
1790 va.va_mode &= ~(VSUID | VSGID);
1791
1792 tryagain:
1793 /*
1794 * The file open mode used is VWRITE. If the client needs
1795 * some other semantic, then it should do the access checking
1796 * itself. It would have been nice to have the file open mode
1797 * passed as part of the arguments.
1798 */
1799 error = VOP_CREATE(dvp, name, &va, excl, VWRITE,
1800 &vp, cr, 0, NULL, NULL);
1801
1802 #ifdef DEBUG
1803 if (rfs3_do_post_op_attr) {
1804 dava.va_mask = AT_ALL;
1805 davap = VOP_GETATTR(dvp, &dava, 0, cr, NULL) ? NULL : &dava;
1806 } else
1807 davap = NULL;
1808 #else
1809 dava.va_mask = AT_ALL;
1810 davap = VOP_GETATTR(dvp, &dava, 0, cr, NULL) ? NULL : &dava;
1811 #endif
1812
1813 if (error) {
1814 /*
1815 * If we got something other than file already exists
1816 * then just return this error. Otherwise, we got
1817 * EEXIST. If we were doing a GUARDED create, then
1818 * just return this error. Otherwise, we need to
1819 * make sure that this wasn't a duplicate of an
1820 * exclusive create request.
1821 *
1822 * The assumption is made that a non-exclusive create
1823 * request will never return EEXIST.
1824 */
1825 if (error != EEXIST || args->how.mode == GUARDED)
1826 goto out;
1827 /*
1828 * Lookup the file so that we can get a vnode for it.
1829 */
1830 error = VOP_LOOKUP(dvp, name, &vp, NULL, 0,
1831 NULL, cr, NULL, NULL, NULL);
1895 * still recover by checking the size of the file
1896 * after it has created it and then issue a setattr
1897 * request of its own to set the size of the file.
1898 */
1899 if (vap != NULL &&
1900 (args->how.mode == UNCHECKED ||
1901 args->how.mode == GUARDED) &&
1902 args->how.createhow3_u.obj_attributes.size.set_it &&
1903 vap->va_size != reqsize) {
1904 va.va_mask = AT_SIZE;
1905 va.va_size = reqsize;
1906 (void) VOP_SETATTR(vp, &va, 0, cr, NULL);
1907 va.va_mask = AT_ALL;
1908 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
1909 }
1910 }
1911
1912 if (name != args->where.name)
1913 kmem_free(name, MAXPATHLEN + 1);
1914
1915 #ifdef DEBUG
1916 if (!rfs3_do_post_op_attr)
1917 vap = NULL;
1918 #endif
1919
1920 #ifdef DEBUG
1921 if (!rfs3_do_post_op_fh3)
1922 resp->resok.obj.handle_follows = FALSE;
1923 else {
1924 #endif
1925 error = makefh3(&resp->resok.obj.handle, vp, exi);
1926 if (error)
1927 resp->resok.obj.handle_follows = FALSE;
1928 else
1929 resp->resok.obj.handle_follows = TRUE;
1930 #ifdef DEBUG
1931 }
1932 #endif
1933
1934 /*
1935 * Force modified data and metadata out to stable storage.
1936 */
1937 (void) VOP_FSYNC(vp, FNODSYNC, cr, NULL);
1938 (void) VOP_FSYNC(dvp, 0, cr, NULL);
1939
1940 VN_RELE(vp);
1941 if (tvp != NULL) {
1942 if (in_crit)
1943 nbl_end_crit(tvp);
1944 VN_RELE(tvp);
1945 }
1946
1947 resp->status = NFS3_OK;
1948 vattr_to_post_op_attr(vap, &resp->resok.obj_attributes);
1949 vattr_to_wcc_data(dbvap, davap, &resp->resok.dir_wcc);
1950
1951 DTRACE_NFSV3_4(op__create__done, struct svc_req *, req,
1952 cred_t *, cr, vnode_t *, dvp, CREATE3res *, resp);
1996 struct vattr *dbvap;
1997 struct vattr dbva;
1998 struct vattr *davap;
1999 struct vattr dava;
2000 struct sockaddr *ca;
2001 char *name = NULL;
2002
2003 dbvap = NULL;
2004 davap = NULL;
2005
2006 dvp = nfs3_fhtovp(&args->where.dir, exi);
2007
2008 DTRACE_NFSV3_4(op__mkdir__start, struct svc_req *, req,
2009 cred_t *, cr, vnode_t *, dvp, MKDIR3args *, args);
2010
2011 if (dvp == NULL) {
2012 error = ESTALE;
2013 goto out;
2014 }
2015
2016 #ifdef DEBUG
2017 if (rfs3_do_pre_op_attr) {
2018 dbva.va_mask = AT_ALL;
2019 dbvap = VOP_GETATTR(dvp, &dbva, 0, cr, NULL) ? NULL : &dbva;
2020 } else
2021 dbvap = NULL;
2022 #else
2023 dbva.va_mask = AT_ALL;
2024 dbvap = VOP_GETATTR(dvp, &dbva, 0, cr, NULL) ? NULL : &dbva;
2025 #endif
2026 davap = dbvap;
2027
2028 if (args->where.name == nfs3nametoolong) {
2029 resp->status = NFS3ERR_NAMETOOLONG;
2030 goto out1;
2031 }
2032
2033 if (args->where.name == NULL || *(args->where.name) == '\0') {
2034 resp->status = NFS3ERR_ACCES;
2035 goto out1;
2036 }
2037
2038 if (rdonly(exi, req)) {
2039 resp->status = NFS3ERR_ROFS;
2040 goto out1;
2041 }
2042
2043 if (is_system_labeled()) {
2044 bslabel_t *clabel = req->rq_label;
2045
2065 goto out1;
2066 }
2067
2068 ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
2069 name = nfscmd_convname(ca, exi, args->where.name,
2070 NFSCMD_CONV_INBOUND, MAXPATHLEN + 1);
2071
2072 if (name == NULL) {
2073 resp->status = NFS3ERR_INVAL;
2074 goto out1;
2075 }
2076
2077 va.va_mask |= AT_TYPE;
2078 va.va_type = VDIR;
2079
2080 error = VOP_MKDIR(dvp, name, &va, &vp, cr, NULL, 0, NULL);
2081
2082 if (name != args->where.name)
2083 kmem_free(name, MAXPATHLEN + 1);
2084
2085 #ifdef DEBUG
2086 if (rfs3_do_post_op_attr) {
2087 dava.va_mask = AT_ALL;
2088 davap = VOP_GETATTR(dvp, &dava, 0, cr, NULL) ? NULL : &dava;
2089 } else
2090 davap = NULL;
2091 #else
2092 dava.va_mask = AT_ALL;
2093 davap = VOP_GETATTR(dvp, &dava, 0, cr, NULL) ? NULL : &dava;
2094 #endif
2095
2096 /*
2097 * Force modified data and metadata out to stable storage.
2098 */
2099 (void) VOP_FSYNC(dvp, 0, cr, NULL);
2100
2101 if (error)
2102 goto out;
2103
2104 #ifdef DEBUG
2105 if (!rfs3_do_post_op_fh3)
2106 resp->resok.obj.handle_follows = FALSE;
2107 else {
2108 #endif
2109 error = makefh3(&resp->resok.obj.handle, vp, exi);
2110 if (error)
2111 resp->resok.obj.handle_follows = FALSE;
2112 else
2113 resp->resok.obj.handle_follows = TRUE;
2114 #ifdef DEBUG
2115 }
2116 #endif
2117
2118 #ifdef DEBUG
2119 if (rfs3_do_post_op_attr) {
2120 va.va_mask = AT_ALL;
2121 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
2122 } else
2123 vap = NULL;
2124 #else
2125 va.va_mask = AT_ALL;
2126 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
2127 #endif
2128
2129 /*
2130 * Force modified data and metadata out to stable storage.
2131 */
2132 (void) VOP_FSYNC(vp, 0, cr, NULL);
2133
2134 VN_RELE(vp);
2135
2136 resp->status = NFS3_OK;
2137 vattr_to_post_op_attr(vap, &resp->resok.obj_attributes);
2138 vattr_to_wcc_data(dbvap, davap, &resp->resok.dir_wcc);
2139
2140 DTRACE_NFSV3_4(op__mkdir__done, struct svc_req *, req,
2141 cred_t *, cr, vnode_t *, dvp, MKDIR3res *, resp);
2142 VN_RELE(dvp);
2143
2144 return;
2145
2146 out:
2147 if (curthread->t_flag & T_WOULDBLOCK) {
2177 struct vattr dbva;
2178 struct vattr *davap;
2179 struct vattr dava;
2180 struct sockaddr *ca;
2181 char *name = NULL;
2182 char *symdata = NULL;
2183
2184 dbvap = NULL;
2185 davap = NULL;
2186
2187 dvp = nfs3_fhtovp(&args->where.dir, exi);
2188
2189 DTRACE_NFSV3_4(op__symlink__start, struct svc_req *, req,
2190 cred_t *, cr, vnode_t *, dvp, SYMLINK3args *, args);
2191
2192 if (dvp == NULL) {
2193 error = ESTALE;
2194 goto err;
2195 }
2196
2197 #ifdef DEBUG
2198 if (rfs3_do_pre_op_attr) {
2199 dbva.va_mask = AT_ALL;
2200 dbvap = VOP_GETATTR(dvp, &dbva, 0, cr, NULL) ? NULL : &dbva;
2201 } else
2202 dbvap = NULL;
2203 #else
2204 dbva.va_mask = AT_ALL;
2205 dbvap = VOP_GETATTR(dvp, &dbva, 0, cr, NULL) ? NULL : &dbva;
2206 #endif
2207 davap = dbvap;
2208
2209 if (args->where.name == nfs3nametoolong) {
2210 resp->status = NFS3ERR_NAMETOOLONG;
2211 goto err1;
2212 }
2213
2214 if (args->where.name == NULL || *(args->where.name) == '\0') {
2215 resp->status = NFS3ERR_ACCES;
2216 goto err1;
2217 }
2218
2219 if (rdonly(exi, req)) {
2220 resp->status = NFS3ERR_ROFS;
2221 goto err1;
2222 }
2223
2224 if (is_system_labeled()) {
2225 bslabel_t *clabel = req->rq_label;
2226
2258 if (name == NULL) {
2259 /* This is really a Solaris EILSEQ */
2260 resp->status = NFS3ERR_INVAL;
2261 goto err1;
2262 }
2263
2264 symdata = nfscmd_convname(ca, exi, args->symlink.symlink_data,
2265 NFSCMD_CONV_INBOUND, MAXPATHLEN + 1);
2266 if (symdata == NULL) {
2267 /* This is really a Solaris EILSEQ */
2268 resp->status = NFS3ERR_INVAL;
2269 goto err1;
2270 }
2271
2272
2273 va.va_mask |= AT_TYPE;
2274 va.va_type = VLNK;
2275
2276 error = VOP_SYMLINK(dvp, name, &va, symdata, cr, NULL, 0);
2277
2278 #ifdef DEBUG
2279 if (rfs3_do_post_op_attr) {
2280 dava.va_mask = AT_ALL;
2281 davap = VOP_GETATTR(dvp, &dava, 0, cr, NULL) ? NULL : &dava;
2282 } else
2283 davap = NULL;
2284 #else
2285 dava.va_mask = AT_ALL;
2286 davap = VOP_GETATTR(dvp, &dava, 0, cr, NULL) ? NULL : &dava;
2287 #endif
2288
2289 if (error)
2290 goto err;
2291
2292 error = VOP_LOOKUP(dvp, name, &vp, NULL, 0, NULL, cr,
2293 NULL, NULL, NULL);
2294
2295 /*
2296 * Force modified data and metadata out to stable storage.
2297 */
2298 (void) VOP_FSYNC(dvp, 0, cr, NULL);
2299
2300
2301 resp->status = NFS3_OK;
2302 if (error) {
2303 resp->resok.obj.handle_follows = FALSE;
2304 vattr_to_post_op_attr(NULL, &resp->resok.obj_attributes);
2305 vattr_to_wcc_data(dbvap, davap, &resp->resok.dir_wcc);
2306 goto out;
2307 }
2308
2309 #ifdef DEBUG
2310 if (!rfs3_do_post_op_fh3)
2311 resp->resok.obj.handle_follows = FALSE;
2312 else {
2313 #endif
2314 error = makefh3(&resp->resok.obj.handle, vp, exi);
2315 if (error)
2316 resp->resok.obj.handle_follows = FALSE;
2317 else
2318 resp->resok.obj.handle_follows = TRUE;
2319 #ifdef DEBUG
2320 }
2321 #endif
2322
2323 #ifdef DEBUG
2324 if (rfs3_do_post_op_attr) {
2325 va.va_mask = AT_ALL;
2326 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
2327 } else
2328 vap = NULL;
2329 #else
2330 va.va_mask = AT_ALL;
2331 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
2332 #endif
2333
2334 /*
2335 * Force modified data and metadata out to stable storage.
2336 */
2337 (void) VOP_FSYNC(vp, 0, cr, NULL);
2338
2339 VN_RELE(vp);
2340
2341 vattr_to_post_op_attr(vap, &resp->resok.obj_attributes);
2342 vattr_to_wcc_data(dbvap, davap, &resp->resok.dir_wcc);
2343 goto out;
2344
2345 err:
2346 if (curthread->t_flag & T_WOULDBLOCK) {
2347 curthread->t_flag &= ~T_WOULDBLOCK;
2348 resp->status = NFS3ERR_JUKEBOX;
2349 } else
2350 resp->status = puterrno3(error);
2351 err1:
2352 vattr_to_wcc_data(dbvap, davap, &resp->resfail.dir_wcc);
2385 struct vattr *davap;
2386 struct vattr dava;
2387 int mode;
2388 enum vcexcl excl;
2389 struct sockaddr *ca;
2390 char *name = NULL;
2391
2392 dbvap = NULL;
2393 davap = NULL;
2394
2395 dvp = nfs3_fhtovp(&args->where.dir, exi);
2396
2397 DTRACE_NFSV3_4(op__mknod__start, struct svc_req *, req,
2398 cred_t *, cr, vnode_t *, dvp, MKNOD3args *, args);
2399
2400 if (dvp == NULL) {
2401 error = ESTALE;
2402 goto out;
2403 }
2404
2405 #ifdef DEBUG
2406 if (rfs3_do_pre_op_attr) {
2407 dbva.va_mask = AT_ALL;
2408 dbvap = VOP_GETATTR(dvp, &dbva, 0, cr, NULL) ? NULL : &dbva;
2409 } else
2410 dbvap = NULL;
2411 #else
2412 dbva.va_mask = AT_ALL;
2413 dbvap = VOP_GETATTR(dvp, &dbva, 0, cr, NULL) ? NULL : &dbva;
2414 #endif
2415 davap = dbvap;
2416
2417 if (args->where.name == nfs3nametoolong) {
2418 resp->status = NFS3ERR_NAMETOOLONG;
2419 goto out1;
2420 }
2421
2422 if (args->where.name == NULL || *(args->where.name) == '\0') {
2423 resp->status = NFS3ERR_ACCES;
2424 goto out1;
2425 }
2426
2427 if (rdonly(exi, req)) {
2428 resp->status = NFS3ERR_ROFS;
2429 goto out1;
2430 }
2431
2432 if (is_system_labeled()) {
2433 bslabel_t *clabel = req->rq_label;
2434
2496
2497 ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
2498 name = nfscmd_convname(ca, exi, args->where.name,
2499 NFSCMD_CONV_INBOUND, MAXPATHLEN + 1);
2500
2501 if (name == NULL) {
2502 resp->status = NFS3ERR_INVAL;
2503 goto out1;
2504 }
2505
2506 excl = EXCL;
2507
2508 mode = 0;
2509
2510 error = VOP_CREATE(dvp, name, &va, excl, mode,
2511 &vp, cr, 0, NULL, NULL);
2512
2513 if (name != args->where.name)
2514 kmem_free(name, MAXPATHLEN + 1);
2515
2516 #ifdef DEBUG
2517 if (rfs3_do_post_op_attr) {
2518 dava.va_mask = AT_ALL;
2519 davap = VOP_GETATTR(dvp, &dava, 0, cr, NULL) ? NULL : &dava;
2520 } else
2521 davap = NULL;
2522 #else
2523 dava.va_mask = AT_ALL;
2524 davap = VOP_GETATTR(dvp, &dava, 0, cr, NULL) ? NULL : &dava;
2525 #endif
2526
2527 /*
2528 * Force modified data and metadata out to stable storage.
2529 */
2530 (void) VOP_FSYNC(dvp, 0, cr, NULL);
2531
2532 if (error)
2533 goto out;
2534
2535 resp->status = NFS3_OK;
2536
2537 #ifdef DEBUG
2538 if (!rfs3_do_post_op_fh3)
2539 resp->resok.obj.handle_follows = FALSE;
2540 else {
2541 #endif
2542 error = makefh3(&resp->resok.obj.handle, vp, exi);
2543 if (error)
2544 resp->resok.obj.handle_follows = FALSE;
2545 else
2546 resp->resok.obj.handle_follows = TRUE;
2547 #ifdef DEBUG
2548 }
2549 #endif
2550
2551 #ifdef DEBUG
2552 if (rfs3_do_post_op_attr) {
2553 va.va_mask = AT_ALL;
2554 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
2555 } else
2556 vap = NULL;
2557 #else
2558 va.va_mask = AT_ALL;
2559 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
2560 #endif
2561
2562 /*
2563 * Force modified metadata out to stable storage.
2564 *
2565 * if a underlying vp exists, pass it to VOP_FSYNC
2566 */
2567 if (VOP_REALVP(vp, &realvp, NULL) == 0)
2568 (void) VOP_FSYNC(realvp, FNODSYNC, cr, NULL);
2569 else
2570 (void) VOP_FSYNC(vp, FNODSYNC, cr, NULL);
2571
2572 VN_RELE(vp);
2573
2574 vattr_to_post_op_attr(vap, &resp->resok.obj_attributes);
2575 vattr_to_wcc_data(dbvap, davap, &resp->resok.dir_wcc);
2576 DTRACE_NFSV3_4(op__mknod__done, struct svc_req *, req,
2577 cred_t *, cr, vnode_t *, dvp, MKNOD3res *, resp);
2578 VN_RELE(dvp);
2579 return;
2580
2609 struct vattr bva;
2610 struct vattr *avap;
2611 struct vattr ava;
2612 vnode_t *targvp = NULL;
2613 struct sockaddr *ca;
2614 char *name = NULL;
2615
2616 bvap = NULL;
2617 avap = NULL;
2618
2619 vp = nfs3_fhtovp(&args->object.dir, exi);
2620
2621 DTRACE_NFSV3_4(op__remove__start, struct svc_req *, req,
2622 cred_t *, cr, vnode_t *, vp, REMOVE3args *, args);
2623
2624 if (vp == NULL) {
2625 error = ESTALE;
2626 goto err;
2627 }
2628
2629 #ifdef DEBUG
2630 if (rfs3_do_pre_op_attr) {
2631 bva.va_mask = AT_ALL;
2632 bvap = VOP_GETATTR(vp, &bva, 0, cr, NULL) ? NULL : &bva;
2633 } else
2634 bvap = NULL;
2635 #else
2636 bva.va_mask = AT_ALL;
2637 bvap = VOP_GETATTR(vp, &bva, 0, cr, NULL) ? NULL : &bva;
2638 #endif
2639 avap = bvap;
2640
2641 if (vp->v_type != VDIR) {
2642 resp->status = NFS3ERR_NOTDIR;
2643 goto err1;
2644 }
2645
2646 if (args->object.name == nfs3nametoolong) {
2647 resp->status = NFS3ERR_NAMETOOLONG;
2648 goto err1;
2649 }
2650
2651 if (args->object.name == NULL || *(args->object.name) == '\0') {
2652 resp->status = NFS3ERR_ACCES;
2653 goto err1;
2654 }
2655
2656 if (rdonly(exi, req)) {
2657 resp->status = NFS3ERR_ROFS;
2658 goto err1;
2694
2695 if (rfs4_check_delegated(FWRITE, targvp, TRUE)) {
2696 resp->status = NFS3ERR_JUKEBOX;
2697 goto err1;
2698 }
2699
2700 if (!nbl_need_check(targvp)) {
2701 error = VOP_REMOVE(vp, name, cr, NULL, 0);
2702 } else {
2703 nbl_start_crit(targvp, RW_READER);
2704 if (nbl_conflict(targvp, NBL_REMOVE, 0, 0, 0, NULL)) {
2705 error = EACCES;
2706 } else {
2707 error = VOP_REMOVE(vp, name, cr, NULL, 0);
2708 }
2709 nbl_end_crit(targvp);
2710 }
2711 VN_RELE(targvp);
2712 targvp = NULL;
2713
2714 #ifdef DEBUG
2715 if (rfs3_do_post_op_attr) {
2716 ava.va_mask = AT_ALL;
2717 avap = VOP_GETATTR(vp, &ava, 0, cr, NULL) ? NULL : &ava;
2718 } else
2719 avap = NULL;
2720 #else
2721 ava.va_mask = AT_ALL;
2722 avap = VOP_GETATTR(vp, &ava, 0, cr, NULL) ? NULL : &ava;
2723 #endif
2724
2725 /*
2726 * Force modified data and metadata out to stable storage.
2727 */
2728 (void) VOP_FSYNC(vp, 0, cr, NULL);
2729
2730 if (error)
2731 goto err;
2732
2733 resp->status = NFS3_OK;
2734 vattr_to_wcc_data(bvap, avap, &resp->resok.dir_wcc);
2735 goto out;
2736
2737 err:
2738 if (curthread->t_flag & T_WOULDBLOCK) {
2739 curthread->t_flag &= ~T_WOULDBLOCK;
2740 resp->status = NFS3ERR_JUKEBOX;
2741 } else
2742 resp->status = puterrno3(error);
2743 err1:
2769 struct vattr *bvap;
2770 struct vattr bva;
2771 struct vattr *avap;
2772 struct vattr ava;
2773 struct sockaddr *ca;
2774 char *name = NULL;
2775
2776 bvap = NULL;
2777 avap = NULL;
2778
2779 vp = nfs3_fhtovp(&args->object.dir, exi);
2780
2781 DTRACE_NFSV3_4(op__rmdir__start, struct svc_req *, req,
2782 cred_t *, cr, vnode_t *, vp, RMDIR3args *, args);
2783
2784 if (vp == NULL) {
2785 error = ESTALE;
2786 goto err;
2787 }
2788
2789 #ifdef DEBUG
2790 if (rfs3_do_pre_op_attr) {
2791 bva.va_mask = AT_ALL;
2792 bvap = VOP_GETATTR(vp, &bva, 0, cr, NULL) ? NULL : &bva;
2793 } else
2794 bvap = NULL;
2795 #else
2796 bva.va_mask = AT_ALL;
2797 bvap = VOP_GETATTR(vp, &bva, 0, cr, NULL) ? NULL : &bva;
2798 #endif
2799 avap = bvap;
2800
2801 if (vp->v_type != VDIR) {
2802 resp->status = NFS3ERR_NOTDIR;
2803 goto err1;
2804 }
2805
2806 if (args->object.name == nfs3nametoolong) {
2807 resp->status = NFS3ERR_NAMETOOLONG;
2808 goto err1;
2809 }
2810
2811 if (args->object.name == NULL || *(args->object.name) == '\0') {
2812 resp->status = NFS3ERR_ACCES;
2813 goto err1;
2814 }
2815
2816 if (rdonly(exi, req)) {
2817 resp->status = NFS3ERR_ROFS;
2818 goto err1;
2831 resp->status = NFS3ERR_ACCES;
2832 goto err1;
2833 }
2834 }
2835 }
2836
2837 ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
2838 name = nfscmd_convname(ca, exi, args->object.name,
2839 NFSCMD_CONV_INBOUND, MAXPATHLEN + 1);
2840
2841 if (name == NULL) {
2842 resp->status = NFS3ERR_INVAL;
2843 goto err1;
2844 }
2845
2846 error = VOP_RMDIR(vp, name, rootdir, cr, NULL, 0);
2847
2848 if (name != args->object.name)
2849 kmem_free(name, MAXPATHLEN + 1);
2850
2851 #ifdef DEBUG
2852 if (rfs3_do_post_op_attr) {
2853 ava.va_mask = AT_ALL;
2854 avap = VOP_GETATTR(vp, &ava, 0, cr, NULL) ? NULL : &ava;
2855 } else
2856 avap = NULL;
2857 #else
2858 ava.va_mask = AT_ALL;
2859 avap = VOP_GETATTR(vp, &ava, 0, cr, NULL) ? NULL : &ava;
2860 #endif
2861
2862 /*
2863 * Force modified data and metadata out to stable storage.
2864 */
2865 (void) VOP_FSYNC(vp, 0, cr, NULL);
2866
2867 if (error) {
2868 /*
2869 * System V defines rmdir to return EEXIST, not ENOTEMPTY,
2870 * if the directory is not empty. A System V NFS server
2871 * needs to map NFS3ERR_EXIST to NFS3ERR_NOTEMPTY to transmit
2872 * over the wire.
2873 */
2874 if (error == EEXIST)
2875 error = ENOTEMPTY;
2876 goto err;
2877 }
2878
2879 resp->status = NFS3_OK;
2880 vattr_to_wcc_data(bvap, avap, &resp->resok.dir_wcc);
2941 if (fvp == NULL) {
2942 error = ESTALE;
2943 goto err;
2944 }
2945
2946 if (is_system_labeled()) {
2947 clabel = req->rq_label;
2948 ASSERT(clabel != NULL);
2949 DTRACE_PROBE2(tx__rfs3__log__info__oprename__clabel, char *,
2950 "got client label from request(1)", struct svc_req *, req);
2951
2952 if (!blequal(&l_admin_low->tsl_label, clabel)) {
2953 if (!do_rfs_label_check(clabel, fvp, EQUALITY_CHECK,
2954 exi)) {
2955 resp->status = NFS3ERR_ACCES;
2956 goto err1;
2957 }
2958 }
2959 }
2960
2961 #ifdef DEBUG
2962 if (rfs3_do_pre_op_attr) {
2963 fbva.va_mask = AT_ALL;
2964 fbvap = VOP_GETATTR(fvp, &fbva, 0, cr, NULL) ? NULL : &fbva;
2965 } else
2966 fbvap = NULL;
2967 #else
2968 fbva.va_mask = AT_ALL;
2969 fbvap = VOP_GETATTR(fvp, &fbva, 0, cr, NULL) ? NULL : &fbva;
2970 #endif
2971 favap = fbvap;
2972
2973 fh3 = &args->to.dir;
2974 to_exi = checkexport(&fh3->fh3_fsid, FH3TOXFIDP(fh3));
2975 if (to_exi == NULL) {
2976 resp->status = NFS3ERR_ACCES;
2977 goto err1;
2978 }
2979 exi_rele(to_exi);
2980
2981 if (to_exi != exi) {
2982 resp->status = NFS3ERR_XDEV;
2983 goto err1;
2984 }
2985
2986 tvp = nfs3_fhtovp(&args->to.dir, exi);
2987 if (tvp == NULL) {
2988 error = ESTALE;
2989 goto err;
2990 }
2991
2992 #ifdef DEBUG
2993 if (rfs3_do_pre_op_attr) {
2994 tbva.va_mask = AT_ALL;
2995 tbvap = VOP_GETATTR(tvp, &tbva, 0, cr, NULL) ? NULL : &tbva;
2996 } else
2997 tbvap = NULL;
2998 #else
2999 tbva.va_mask = AT_ALL;
3000 tbvap = VOP_GETATTR(tvp, &tbva, 0, cr, NULL) ? NULL : &tbva;
3001 #endif
3002 tavap = tbvap;
3003
3004 if (fvp->v_type != VDIR || tvp->v_type != VDIR) {
3005 resp->status = NFS3ERR_NOTDIR;
3006 goto err1;
3007 }
3008
3009 if (args->from.name == nfs3nametoolong ||
3010 args->to.name == nfs3nametoolong) {
3011 resp->status = NFS3ERR_NAMETOOLONG;
3012 goto err1;
3013 }
3014 if (args->from.name == NULL || *(args->from.name) == '\0' ||
3015 args->to.name == NULL || *(args->to.name) == '\0') {
3016 resp->status = NFS3ERR_ACCES;
3017 goto err1;
3018 }
3019
3020 if (rdonly(exi, req)) {
3021 resp->status = NFS3ERR_ROFS;
3083 }
3084 VN_RELE(targvp);
3085 }
3086
3087 if (!nbl_need_check(srcvp)) {
3088 error = VOP_RENAME(fvp, name, tvp, toname, cr, NULL, 0);
3089 } else {
3090 nbl_start_crit(srcvp, RW_READER);
3091 if (nbl_conflict(srcvp, NBL_RENAME, 0, 0, 0, NULL))
3092 error = EACCES;
3093 else
3094 error = VOP_RENAME(fvp, name, tvp, toname, cr, NULL, 0);
3095 nbl_end_crit(srcvp);
3096 }
3097 if (error == 0)
3098 vn_renamepath(tvp, srcvp, args->to.name,
3099 strlen(args->to.name));
3100 VN_RELE(srcvp);
3101 srcvp = NULL;
3102
3103 #ifdef DEBUG
3104 if (rfs3_do_post_op_attr) {
3105 fava.va_mask = AT_ALL;
3106 favap = VOP_GETATTR(fvp, &fava, 0, cr, NULL) ? NULL : &fava;
3107 tava.va_mask = AT_ALL;
3108 tavap = VOP_GETATTR(tvp, &tava, 0, cr, NULL) ? NULL : &tava;
3109 } else {
3110 favap = NULL;
3111 tavap = NULL;
3112 }
3113 #else
3114 fava.va_mask = AT_ALL;
3115 favap = VOP_GETATTR(fvp, &fava, 0, cr, NULL) ? NULL : &fava;
3116 tava.va_mask = AT_ALL;
3117 tavap = VOP_GETATTR(tvp, &tava, 0, cr, NULL) ? NULL : &tava;
3118 #endif
3119
3120 /*
3121 * Force modified data and metadata out to stable storage.
3122 */
3123 (void) VOP_FSYNC(fvp, 0, cr, NULL);
3124 (void) VOP_FSYNC(tvp, 0, cr, NULL);
3125
3126 if (error)
3127 goto err;
3128
3129 resp->status = NFS3_OK;
3130 vattr_to_wcc_data(fbvap, favap, &resp->resok.fromdir_wcc);
3131 vattr_to_wcc_data(tbvap, tavap, &resp->resok.todir_wcc);
3132 goto out;
3133
3134 err:
3135 if (curthread->t_flag & T_WOULDBLOCK) {
3136 curthread->t_flag &= ~T_WOULDBLOCK;
3137 resp->status = NFS3ERR_JUKEBOX;
3138 } else {
3180 struct exportinfo *to_exi;
3181 bslabel_t *clabel;
3182 struct sockaddr *ca;
3183 char *name = NULL;
3184
3185 vap = NULL;
3186 bvap = NULL;
3187 avap = NULL;
3188 dvp = NULL;
3189
3190 vp = nfs3_fhtovp(&args->file, exi);
3191
3192 DTRACE_NFSV3_4(op__link__start, struct svc_req *, req,
3193 cred_t *, cr, vnode_t *, vp, LINK3args *, args);
3194
3195 if (vp == NULL) {
3196 error = ESTALE;
3197 goto out;
3198 }
3199
3200 #ifdef DEBUG
3201 if (rfs3_do_pre_op_attr) {
3202 va.va_mask = AT_ALL;
3203 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
3204 } else
3205 vap = NULL;
3206 #else
3207 va.va_mask = AT_ALL;
3208 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
3209 #endif
3210
3211 fh3 = &args->link.dir;
3212 to_exi = checkexport(&fh3->fh3_fsid, FH3TOXFIDP(fh3));
3213 if (to_exi == NULL) {
3214 resp->status = NFS3ERR_ACCES;
3215 goto out1;
3216 }
3217 exi_rele(to_exi);
3218
3219 if (to_exi != exi) {
3220 resp->status = NFS3ERR_XDEV;
3221 goto out1;
3222 }
3223
3224 if (is_system_labeled()) {
3225 clabel = req->rq_label;
3226
3227 ASSERT(clabel != NULL);
3228 DTRACE_PROBE2(tx__rfs3__log__info__oplink__clabel, char *,
3229 "got client label from request(1)", struct svc_req *, req);
3230
3231 if (!blequal(&l_admin_low->tsl_label, clabel)) {
3232 if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK,
3233 exi)) {
3234 resp->status = NFS3ERR_ACCES;
3235 goto out1;
3236 }
3237 }
3238 }
3239
3240 dvp = nfs3_fhtovp(&args->link.dir, exi);
3241 if (dvp == NULL) {
3242 error = ESTALE;
3243 goto out;
3244 }
3245
3246 #ifdef DEBUG
3247 if (rfs3_do_pre_op_attr) {
3248 bva.va_mask = AT_ALL;
3249 bvap = VOP_GETATTR(dvp, &bva, 0, cr, NULL) ? NULL : &bva;
3250 } else
3251 bvap = NULL;
3252 #else
3253 bva.va_mask = AT_ALL;
3254 bvap = VOP_GETATTR(dvp, &bva, 0, cr, NULL) ? NULL : &bva;
3255 #endif
3256
3257 if (dvp->v_type != VDIR) {
3258 resp->status = NFS3ERR_NOTDIR;
3259 goto out1;
3260 }
3261
3262 if (args->link.name == nfs3nametoolong) {
3263 resp->status = NFS3ERR_NAMETOOLONG;
3264 goto out1;
3265 }
3266
3267 if (args->link.name == NULL || *(args->link.name) == '\0') {
3268 resp->status = NFS3ERR_ACCES;
3269 goto out1;
3270 }
3271
3272 if (rdonly(exi, req)) {
3273 resp->status = NFS3ERR_ROFS;
3274 goto out1;
3275 }
3281 if (!blequal(&l_admin_low->tsl_label, clabel)) {
3282 if (!do_rfs_label_check(clabel, dvp, EQUALITY_CHECK,
3283 exi)) {
3284 resp->status = NFS3ERR_ACCES;
3285 goto out1;
3286 }
3287 }
3288 }
3289
3290 ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
3291 name = nfscmd_convname(ca, exi, args->link.name,
3292 NFSCMD_CONV_INBOUND, MAXPATHLEN + 1);
3293
3294 if (name == NULL) {
3295 resp->status = NFS3ERR_SERVERFAULT;
3296 goto out1;
3297 }
3298
3299 error = VOP_LINK(dvp, vp, name, cr, NULL, 0);
3300
3301 #ifdef DEBUG
3302 if (rfs3_do_post_op_attr) {
3303 va.va_mask = AT_ALL;
3304 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
3305 ava.va_mask = AT_ALL;
3306 avap = VOP_GETATTR(dvp, &ava, 0, cr, NULL) ? NULL : &ava;
3307 } else {
3308 vap = NULL;
3309 avap = NULL;
3310 }
3311 #else
3312 va.va_mask = AT_ALL;
3313 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
3314 ava.va_mask = AT_ALL;
3315 avap = VOP_GETATTR(dvp, &ava, 0, cr, NULL) ? NULL : &ava;
3316 #endif
3317
3318 /*
3319 * Force modified data and metadata out to stable storage.
3320 */
3321 (void) VOP_FSYNC(vp, FNODSYNC, cr, NULL);
3322 (void) VOP_FSYNC(dvp, 0, cr, NULL);
3323
3324 if (error)
3325 goto out;
3326
3327 VN_RELE(dvp);
3328
3329 resp->status = NFS3_OK;
3330 vattr_to_post_op_attr(vap, &resp->resok.file_attributes);
3331 vattr_to_wcc_data(bvap, avap, &resp->resok.linkdir_wcc);
3332
3333 DTRACE_NFSV3_4(op__link__done, struct svc_req *, req,
3334 cred_t *, cr, vnode_t *, vp, LINK3res *, resp);
3335
3336 VN_RELE(vp);
3425 }
3426
3427 if (is_system_labeled()) {
3428 bslabel_t *clabel = req->rq_label;
3429
3430 ASSERT(clabel != NULL);
3431 DTRACE_PROBE2(tx__rfs3__log__info__opreaddir__clabel, char *,
3432 "got client label from request(1)", struct svc_req *, req);
3433
3434 if (!blequal(&l_admin_low->tsl_label, clabel)) {
3435 if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK,
3436 exi)) {
3437 resp->status = NFS3ERR_ACCES;
3438 goto out1;
3439 }
3440 }
3441 }
3442
3443 (void) VOP_RWLOCK(vp, V_WRITELOCK_FALSE, NULL);
3444
3445 #ifdef DEBUG
3446 if (rfs3_do_pre_op_attr) {
3447 va.va_mask = AT_ALL;
3448 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
3449 } else
3450 vap = NULL;
3451 #else
3452 va.va_mask = AT_ALL;
3453 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
3454 #endif
3455
3456 if (vp->v_type != VDIR) {
3457 resp->status = NFS3ERR_NOTDIR;
3458 goto out1;
3459 }
3460
3461 error = VOP_ACCESS(vp, VREAD, 0, cr, NULL);
3462 if (error)
3463 goto out;
3464
3465 /*
3466 * Now don't allow arbitrary count to alloc;
3467 * allow the maximum not to exceed rfs3_tsize()
3468 */
3469 if (args->count > rfs3_tsize(req))
3470 args->count = rfs3_tsize(req);
3471
3472 /*
3473 * Make sure that there is room to read at least one entry
3474 * if any are available.
3475 */
3476 if (args->count < DIRENT64_RECLEN(MAXNAMELEN))
3477 count = DIRENT64_RECLEN(MAXNAMELEN);
3478 else
3479 count = args->count;
3480
3481 data = kmem_alloc(count, KM_SLEEP);
3482
3483 iov.iov_base = data;
3484 iov.iov_len = count;
3485 uio.uio_iov = &iov;
3486 uio.uio_iovcnt = 1;
3487 uio.uio_segflg = UIO_SYSSPACE;
3488 uio.uio_extflg = UIO_COPY_CACHED;
3489 uio.uio_loffset = (offset_t)args->cookie;
3490 uio.uio_resid = count;
3491
3492 error = VOP_READDIR(vp, &uio, cr, &iseof, NULL, 0);
3493
3494 #ifdef DEBUG
3495 if (rfs3_do_post_op_attr) {
3496 va.va_mask = AT_ALL;
3497 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
3498 } else
3499 vap = NULL;
3500 #else
3501 va.va_mask = AT_ALL;
3502 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
3503 #endif
3504
3505 if (error) {
3506 kmem_free(data, count);
3507 goto out;
3508 }
3509
3510 /*
3511 * If the count was not large enough to be able to guarantee
3512 * to be able to return at least one entry, then need to
3513 * check to see if NFS3ERR_TOOSMALL should be returned.
3514 */
3515 if (args->count < NFS3_READDIR_MIN_COUNT(MAXNAMELEN)) {
3516 /*
3517 * bufsize is used to keep track of the size of the response.
3518 * It is primed with:
3519 * 1 for the status +
3520 * 1 for the dir_attributes.attributes boolean +
3521 * 2 for the cookie verifier
3522 * all times BYTES_PER_XDR_UNIT to convert from XDR units
3523 * to bytes. If there are directory attributes to be
3713
3714 if (is_system_labeled()) {
3715 bslabel_t *clabel = req->rq_label;
3716
3717 ASSERT(clabel != NULL);
3718 DTRACE_PROBE2(tx__rfs3__log__info__opreaddirplus__clabel,
3719 char *, "got client label from request(1)",
3720 struct svc_req *, req);
3721
3722 if (!blequal(&l_admin_low->tsl_label, clabel)) {
3723 if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK,
3724 exi)) {
3725 resp->status = NFS3ERR_ACCES;
3726 goto out1;
3727 }
3728 }
3729 }
3730
3731 (void) VOP_RWLOCK(vp, V_WRITELOCK_FALSE, NULL);
3732
3733 #ifdef DEBUG
3734 if (rfs3_do_pre_op_attr) {
3735 va.va_mask = AT_ALL;
3736 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
3737 } else
3738 vap = NULL;
3739 #else
3740 va.va_mask = AT_ALL;
3741 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
3742 #endif
3743
3744 if (vp->v_type != VDIR) {
3745 error = ENOTDIR;
3746 goto out;
3747 }
3748
3749 error = VOP_ACCESS(vp, VREAD, 0, cr, NULL);
3750 if (error)
3751 goto out;
3752
3753 /*
3754 * Don't allow arbitrary counts for allocation
3755 */
3756 if (args->maxcount > rfs3_tsize(req))
3757 args->maxcount = rfs3_tsize(req);
3758
3759 /*
3760 * Make sure that there is room to read at least one entry
3761 * if any are available
3762 */
3881 iseof = FALSE;
3882 goto good;
3883 }
3884 bufsize += entrysize;
3885 nents++;
3886 }
3887
3888 /*
3889 * If there is enough room to fit at least 1 more entry including
3890 * post op attributes and filehandle in the buffer AND that we haven't
3891 * exceeded dircount then go back and get some more.
3892 */
3893 if (!iseof &&
3894 (args->maxcount - bufsize) >= NFS3_READDIRPLUS_ENTRY(MAXNAMELEN)) {
3895 space_left -= (prev_len - uio.uio_resid);
3896 if (space_left >= DIRENT64_RECLEN(MAXNAMELEN))
3897 goto getmoredents;
3898
3899 /* else, fall through */
3900 }
3901
3902 good:
3903
3904 #ifdef DEBUG
3905 if (rfs3_do_post_op_attr) {
3906 va.va_mask = AT_ALL;
3907 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
3908 } else
3909 vap = NULL;
3910 #else
3911 va.va_mask = AT_ALL;
3912 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
3913 #endif
3914
3915 VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, NULL);
3916
3917 infop = kmem_alloc(nents * sizeof (struct entryplus3_info), KM_SLEEP);
3918 resp->resok.infop = infop;
3919
3920 dp = (struct dirent64 *)data;
3921 for (i = 0; i < nents; i++) {
3922
3923 if (dp->d_ino == 0) {
3924 infop[i].attr.attributes = FALSE;
3925 infop[i].fh.handle_follows = FALSE;
3926 dp = nextdp(dp);
3927 continue;
3928 }
3929
3930 infop[i].namelen = namlen[i];
3931
3932 error = VOP_LOOKUP(vp, dp->d_name, &nvp, NULL, 0, NULL, cr,
3933 NULL, NULL, NULL);
3934 if (error) {
3935 infop[i].attr.attributes = FALSE;
3936 infop[i].fh.handle_follows = FALSE;
3937 dp = nextdp(dp);
3938 continue;
3939 }
3940
3941 #ifdef DEBUG
3942 if (rfs3_do_post_op_attr) {
3943 nva.va_mask = AT_ALL;
3944 nvap = rfs4_delegated_getattr(nvp, &nva, 0, cr) ?
3945 NULL : &nva;
3946 } else
3947 nvap = NULL;
3948 #else
3949 nva.va_mask = AT_ALL;
3950 nvap = rfs4_delegated_getattr(nvp, &nva, 0, cr) ? NULL : &nva;
3951 #endif
3952 /* Lie about the object type for a referral */
3953 if (vn_is_nfs_reparse(nvp, cr))
3954 nvap->va_type = VLNK;
3955
3956 vattr_to_post_op_attr(nvap, &infop[i].attr);
3957
3958 #ifdef DEBUG
3959 if (!rfs3_do_post_op_fh3)
3960 infop[i].fh.handle_follows = FALSE;
3961 else {
3962 #endif
3963 error = makefh3(&infop[i].fh.handle, nvp, exi);
3964 if (!error)
3965 infop[i].fh.handle_follows = TRUE;
3966 else
3967 infop[i].fh.handle_follows = FALSE;
3968 #ifdef DEBUG
3969 }
3970 #endif
3971
3972 VN_RELE(nvp);
3973 dp = nextdp(dp);
3974 }
3975
3976 ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
3977 ret = nfscmd_convdirplus(ca, exi, data, nents, args->dircount, &ndata);
3978 if (ndata == NULL)
3979 ndata = data;
3980
3981 if (ret > 0) {
3982 /*
3983 * We had to drop one or more entries in order to fit
3984 * during the character conversion. We need to patch
3985 * up the size and eof info.
3986 */
3987 if (iseof)
3988 iseof = FALSE;
3989
3990 ret = nfscmd_dropped_entrysize((struct dirent64 *)data,
4089 }
4090
4091 if (is_system_labeled()) {
4092 bslabel_t *clabel = req->rq_label;
4093
4094 ASSERT(clabel != NULL);
4095 DTRACE_PROBE2(tx__rfs3__log__info__opfsstat__clabel, char *,
4096 "got client label from request(1)", struct svc_req *, req);
4097
4098 if (!blequal(&l_admin_low->tsl_label, clabel)) {
4099 if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK,
4100 exi)) {
4101 resp->status = NFS3ERR_ACCES;
4102 goto out1;
4103 }
4104 }
4105 }
4106
4107 error = VFS_STATVFS(vp->v_vfsp, &sb);
4108
4109 #ifdef DEBUG
4110 if (rfs3_do_post_op_attr) {
4111 va.va_mask = AT_ALL;
4112 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
4113 } else
4114 vap = NULL;
4115 #else
4116 va.va_mask = AT_ALL;
4117 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
4118 #endif
4119
4120 if (error)
4121 goto out;
4122
4123 resp->status = NFS3_OK;
4124 vattr_to_post_op_attr(vap, &resp->resok.obj_attributes);
4125 if (sb.f_blocks != (fsblkcnt64_t)-1)
4126 resp->resok.tbytes = (size3)sb.f_frsize * (size3)sb.f_blocks;
4127 else
4128 resp->resok.tbytes = (size3)sb.f_blocks;
4129 if (sb.f_bfree != (fsblkcnt64_t)-1)
4130 resp->resok.fbytes = (size3)sb.f_frsize * (size3)sb.f_bfree;
4131 else
4132 resp->resok.fbytes = (size3)sb.f_bfree;
4133 if (sb.f_bavail != (fsblkcnt64_t)-1)
4134 resp->resok.abytes = (size3)sb.f_frsize * (size3)sb.f_bavail;
4135 else
4136 resp->resok.abytes = (size3)sb.f_bavail;
4137 resp->resok.tfiles = (size3)sb.f_files;
4138 resp->resok.ffiles = (size3)sb.f_ffree;
4194 }
4195
4196 if (is_system_labeled()) {
4197 bslabel_t *clabel = req->rq_label;
4198
4199 ASSERT(clabel != NULL);
4200 DTRACE_PROBE2(tx__rfs3__log__info__opfsinfo__clabel, char *,
4201 "got client label from request(1)", struct svc_req *, req);
4202
4203 if (!blequal(&l_admin_low->tsl_label, clabel)) {
4204 if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK,
4205 exi)) {
4206 resp->status = NFS3ERR_STALE;
4207 vattr_to_post_op_attr(NULL,
4208 &resp->resfail.obj_attributes);
4209 goto out;
4210 }
4211 }
4212 }
4213
4214 #ifdef DEBUG
4215 if (rfs3_do_post_op_attr) {
4216 va.va_mask = AT_ALL;
4217 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
4218 } else
4219 vap = NULL;
4220 #else
4221 va.va_mask = AT_ALL;
4222 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
4223 #endif
4224
4225 resp->status = NFS3_OK;
4226 vattr_to_post_op_attr(vap, &resp->resok.obj_attributes);
4227 xfer_size = rfs3_tsize(req);
4228 resp->resok.rtmax = xfer_size;
4229 resp->resok.rtpref = xfer_size;
4230 resp->resok.rtmult = DEV_BSIZE;
4231 resp->resok.wtmax = xfer_size;
4232 resp->resok.wtpref = xfer_size;
4233 resp->resok.wtmult = DEV_BSIZE;
4234 resp->resok.dtpref = MAXBSIZE;
4235
4236 /*
4237 * Large file spec: want maxfilesize based on limit of
4238 * underlying filesystem. We can guess 2^31-1 if need be.
4239 */
4240 error = VOP_PATHCONF(vp, _PC_FILESIZEBITS, &l, cr, NULL);
4241 if (error) {
4242 resp->status = puterrno3(error);
4243 goto out;
4306 error = ESTALE;
4307 goto out;
4308 }
4309
4310 if (is_system_labeled()) {
4311 bslabel_t *clabel = req->rq_label;
4312
4313 ASSERT(clabel != NULL);
4314 DTRACE_PROBE2(tx__rfs3__log__info__oppathconf__clabel, char *,
4315 "got client label from request(1)", struct svc_req *, req);
4316
4317 if (!blequal(&l_admin_low->tsl_label, clabel)) {
4318 if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK,
4319 exi)) {
4320 resp->status = NFS3ERR_ACCES;
4321 goto out1;
4322 }
4323 }
4324 }
4325
4326 #ifdef DEBUG
4327 if (rfs3_do_post_op_attr) {
4328 va.va_mask = AT_ALL;
4329 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
4330 } else
4331 vap = NULL;
4332 #else
4333 va.va_mask = AT_ALL;
4334 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
4335 #endif
4336
4337 error = VOP_PATHCONF(vp, _PC_LINK_MAX, &val, cr, NULL);
4338 if (error)
4339 goto out;
4340 resp->resok.info.link_max = (uint32)val;
4341
4342 error = VOP_PATHCONF(vp, _PC_NAME_MAX, &val, cr, NULL);
4343 if (error)
4344 goto out;
4345 resp->resok.info.name_max = (uint32)val;
4346
4347 error = VOP_PATHCONF(vp, _PC_NO_TRUNC, &val, cr, NULL);
4348 if (error)
4349 goto out;
4350 if (val == 1)
4351 resp->resok.info.no_trunc = TRUE;
4352 else
4353 resp->resok.info.no_trunc = FALSE;
4354
4355 error = VOP_PATHCONF(vp, _PC_CHOWN_RESTRICTED, &val, cr, NULL);
4407 vp = nfs3_fhtovp(&args->file, exi);
4408
4409 DTRACE_NFSV3_4(op__commit__start, struct svc_req *, req,
4410 cred_t *, cr, vnode_t *, vp, COMMIT3args *, args);
4411
4412 if (vp == NULL) {
4413 error = ESTALE;
4414 goto out;
4415 }
4416
4417 bva.va_mask = AT_ALL;
4418 error = VOP_GETATTR(vp, &bva, 0, cr, NULL);
4419
4420 /*
4421 * If we can't get the attributes, then we can't do the
4422 * right access checking. So, we'll fail the request.
4423 */
4424 if (error)
4425 goto out;
4426
4427 #ifdef DEBUG
4428 if (rfs3_do_pre_op_attr)
4429 bvap = &bva;
4430 else
4431 bvap = NULL;
4432 #else
4433 bvap = &bva;
4434 #endif
4435
4436 if (rdonly(exi, req)) {
4437 resp->status = NFS3ERR_ROFS;
4438 goto out1;
4439 }
4440
4441 if (vp->v_type != VREG) {
4442 resp->status = NFS3ERR_INVAL;
4443 goto out1;
4444 }
4445
4446 if (is_system_labeled()) {
4447 bslabel_t *clabel = req->rq_label;
4448
4449 ASSERT(clabel != NULL);
4450 DTRACE_PROBE2(tx__rfs3__log__info__opcommit__clabel, char *,
4451 "got client label from request(1)", struct svc_req *, req);
4452
4453 if (!blequal(&l_admin_low->tsl_label, clabel)) {
4454 if (!do_rfs_label_check(clabel, vp, EQUALITY_CHECK,
4455 exi)) {
4456 resp->status = NFS3ERR_ACCES;
4457 goto out1;
4458 }
4459 }
4460 }
4461
4462 if (crgetuid(cr) != bva.va_uid &&
4463 (error = VOP_ACCESS(vp, VWRITE, 0, cr, NULL)))
4464 goto out;
4465
4466 error = VOP_FSYNC(vp, FSYNC, cr, NULL);
4467
4468 #ifdef DEBUG
4469 if (rfs3_do_post_op_attr) {
4470 ava.va_mask = AT_ALL;
4471 avap = VOP_GETATTR(vp, &ava, 0, cr, NULL) ? NULL : &ava;
4472 } else
4473 avap = NULL;
4474 #else
4475 ava.va_mask = AT_ALL;
4476 avap = VOP_GETATTR(vp, &ava, 0, cr, NULL) ? NULL : &ava;
4477 #endif
4478
4479 if (error)
4480 goto out;
4481
4482 resp->status = NFS3_OK;
4483 vattr_to_wcc_data(bvap, avap, &resp->resok.file_wcc);
4484 resp->resok.verf = write3verf;
4485
4486 DTRACE_NFSV3_4(op__commit__done, struct svc_req *, req,
4487 cred_t *, cr, vnode_t *, vp, COMMIT3res *, resp);
4488
4489 VN_RELE(vp);
4490
4491 return;
4492
4493 out:
4494 if (curthread->t_flag & T_WOULDBLOCK) {
4495 curthread->t_flag &= ~T_WOULDBLOCK;
4496 resp->status = NFS3ERR_JUKEBOX;
4497 } else
|
54 #include <nfs/nfs.h>
55 #include <nfs/export.h>
56 #include <nfs/nfs_cmd.h>
57
58 #include <sys/strsubr.h>
59
60 #include <sys/tsol/label.h>
61 #include <sys/tsol/tndb.h>
62
63 #include <sys/zone.h>
64
65 #include <inet/ip.h>
66 #include <inet/ip6.h>
67
68 /*
69 * These are the interface routines for the server side of the
70 * Network File System. See the NFS version 3 protocol specification
71 * for a description of this interface.
72 */
73
74 static writeverf3 write3verf;
75
76 static int sattr3_to_vattr(sattr3 *, struct vattr *);
77 static int vattr_to_fattr3(struct vattr *, fattr3 *);
78 static int vattr_to_wcc_attr(struct vattr *, wcc_attr *);
79 static void vattr_to_pre_op_attr(struct vattr *, pre_op_attr *);
80 static void vattr_to_wcc_data(struct vattr *, struct vattr *, wcc_data *);
81 static int rdma_setup_read_data3(READ3args *, READ3resok *);
82
83 extern int nfs_loaned_buffers;
84
85 u_longlong_t nfs3_srv_caller_id;
86
87 /* ARGSUSED */
88 void
89 rfs3_getattr(GETATTR3args *args, GETATTR3res *resp, struct exportinfo *exi,
90 struct svc_req *req, cred_t *cr)
91 {
92 int error;
93 vnode_t *vp;
204 * delegated this file. If so, then we return JUKEBOX to
205 * allow the client to retrasmit its request.
206 */
207 if (vp->v_type == VREG && (ava.va_mask & AT_SIZE)) {
208 if (nbl_need_check(vp)) {
209 nbl_start_crit(vp, RW_READER);
210 in_crit = 1;
211 }
212 }
213
214 bva.va_mask = AT_ALL;
215 error = rfs4_delegated_getattr(vp, &bva, 0, cr);
216
217 /*
218 * If we can't get the attributes, then we can't do the
219 * right access checking. So, we'll fail the request.
220 */
221 if (error)
222 goto out;
223
224 bvap = &bva;
225
226 if (rdonly(exi, req) || vn_is_readonly(vp)) {
227 resp->status = NFS3ERR_ROFS;
228 goto out1;
229 }
230
231 if (args->guard.check &&
232 (args->guard.obj_ctime.seconds != bva.va_ctime.tv_sec ||
233 args->guard.obj_ctime.nseconds != bva.va_ctime.tv_nsec)) {
234 resp->status = NFS3ERR_NOT_SYNC;
235 goto out1;
236 }
237
238 if (args->new_attributes.mtime.set_it == SET_TO_CLIENT_TIME)
239 flag = ATTR_UTIME;
240 else
241 flag = 0;
242
243 /*
244 * If the filesystem is exported with nosuid, then mask off
294 bf.l_type = F_WRLCK;
295 bf.l_whence = 0;
296 bf.l_start = (off64_t)ava.va_size;
297 bf.l_len = 0;
298 bf.l_sysid = 0;
299 bf.l_pid = 0;
300 error = VOP_SPACE(vp, F_FREESP, &bf, FWRITE,
301 (offset_t)ava.va_size, cr, &ct);
302 }
303 }
304
305 if (!error && ava.va_mask)
306 error = VOP_SETATTR(vp, &ava, flag, cr, &ct);
307
308 /* check if a monitor detected a delegation conflict */
309 if (error == EAGAIN && (ct.cc_flags & CC_WOULDBLOCK)) {
310 resp->status = NFS3ERR_JUKEBOX;
311 goto out1;
312 }
313
314 ava.va_mask = AT_ALL;
315 avap = rfs4_delegated_getattr(vp, &ava, 0, cr) ? NULL : &ava;
316
317 /*
318 * Force modified metadata out to stable storage.
319 */
320 (void) VOP_FSYNC(vp, FNODSYNC, cr, &ct);
321
322 if (error)
323 goto out;
324
325 if (in_crit)
326 nbl_end_crit(vp);
327
328 resp->status = NFS3_OK;
329 vattr_to_wcc_data(bvap, avap, &resp->resok.obj_wcc);
330
331 DTRACE_NFSV3_4(op__setattr__done, struct svc_req *, req,
332 cred_t *, cr, vnode_t *, vp, SETATTR3res *, resp);
333
334 VN_RELE(vp);
335
385 * location of the public filehandle.
386 */
387 if (exi != NULL && (exi->exi_export.ex_flags & EX_PUBLIC)) {
388 dvp = rootdir;
389 VN_HOLD(dvp);
390
391 DTRACE_NFSV3_4(op__lookup__start, struct svc_req *, req,
392 cred_t *, cr, vnode_t *, dvp, LOOKUP3args *, args);
393 } else {
394 dvp = nfs3_fhtovp(&args->what.dir, exi);
395
396 DTRACE_NFSV3_4(op__lookup__start, struct svc_req *, req,
397 cred_t *, cr, vnode_t *, dvp, LOOKUP3args *, args);
398
399 if (dvp == NULL) {
400 error = ESTALE;
401 goto out;
402 }
403 }
404
405 dva.va_mask = AT_ALL;
406 dvap = VOP_GETATTR(dvp, &dva, 0, cr, NULL) ? NULL : &dva;
407
408 if (args->what.name == nfs3nametoolong) {
409 resp->status = NFS3ERR_NAMETOOLONG;
410 goto out1;
411 }
412
413 if (args->what.name == NULL || *(args->what.name) == '\0') {
414 resp->status = NFS3ERR_ACCES;
415 goto out1;
416 }
417
418 fhp = &args->what.dir;
419 if (strcmp(args->what.name, "..") == 0 &&
420 EQFID(&exi->exi_fid, FH3TOFIDP(fhp))) {
421 resp->status = NFS3ERR_NOENT;
422 goto out1;
423 }
424
425 ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
426 name = nfscmd_convname(ca, exi, args->what.name,
481
482 if (is_system_labeled() && error == 0) {
483 bslabel_t *clabel = req->rq_label;
484
485 ASSERT(clabel != NULL);
486 DTRACE_PROBE2(tx__rfs3__log__info__oplookup__clabel, char *,
487 "got client label from request(1)", struct svc_req *, req);
488
489 if (!blequal(&l_admin_low->tsl_label, clabel)) {
490 if (!do_rfs_label_check(clabel, dvp,
491 DOMINANCE_CHECK, exi)) {
492 if (publicfh_flag && exi != NULL)
493 exi_rele(exi);
494 VN_RELE(vp);
495 resp->status = NFS3ERR_ACCES;
496 error = 1;
497 }
498 }
499 }
500
501 dva.va_mask = AT_ALL;
502 dvap = VOP_GETATTR(dvp, &dva, 0, cr, NULL) ? NULL : &dva;
503
504 if (error)
505 goto out;
506
507 if (sec.sec_flags & SEC_QUERY) {
508 error = makefh3_ol(&resp->resok.object, exi, sec.sec_index);
509 } else {
510 error = makefh3(&resp->resok.object, vp, exi);
511 if (!error && publicfh_flag && !chk_clnt_sec(exi, req))
512 auth_weak = TRUE;
513 }
514
515 if (error) {
516 VN_RELE(vp);
517 goto out;
518 }
519
520 /*
521 * If publicfh_flag is true then we have called rfs_publicfh_mclookup
522 * and have obtained a new exportinfo in exi which needs to be
523 * released. Note the the original exportinfo pointed to by exi
524 * will be released by the caller, common_dispatch.
525 */
526 if (publicfh_flag)
527 exi_rele(exi);
528
529 va.va_mask = AT_ALL;
530 vap = rfs4_delegated_getattr(vp, &va, 0, cr) ? NULL : &va;
531
532 VN_RELE(vp);
533
534 resp->status = NFS3_OK;
535 vattr_to_post_op_attr(vap, &resp->resok.obj_attributes);
536 vattr_to_post_op_attr(dvap, &resp->resok.dir_attributes);
537
538 /*
539 * If it's public fh, no 0x81, and client's flavor is
540 * invalid, set WebNFS status to WNFSERR_CLNT_FLAVOR now.
541 * Then set RPC status to AUTH_TOOWEAK in common_dispatch.
542 */
543 if (auth_weak)
544 resp->status = (enum nfsstat3)WNFSERR_CLNT_FLAVOR;
545
546 DTRACE_NFSV3_4(op__lookup__done, struct svc_req *, req,
547 cred_t *, cr, vnode_t *, dvp, LOOKUP3res *, resp);
548 VN_RELE(dvp);
549
550 return;
603 * to check write permissions for regular files and directories.
604 * Special files are interpreted by the client, so the underlying
605 * permissions are sent back to the client for interpretation.
606 */
607 if (rdonly(exi, req) && (vp->v_type == VREG || vp->v_type == VDIR))
608 checkwriteperm = 0;
609 else
610 checkwriteperm = 1;
611
612 /*
613 * We need the mode so that we can correctly determine access
614 * permissions relative to a mandatory lock file. Access to
615 * mandatory lock files is denied on the server, so it might
616 * as well be reflected to the server during the open.
617 */
618 va.va_mask = AT_MODE;
619 error = VOP_GETATTR(vp, &va, 0, cr, NULL);
620 if (error)
621 goto out;
622
623 vap = &va;
624
625 resp->resok.access = 0;
626
627 if (is_system_labeled()) {
628 bslabel_t *clabel = req->rq_label;
629
630 ASSERT(clabel != NULL);
631 DTRACE_PROBE2(tx__rfs3__log__info__opaccess__clabel, char *,
632 "got client label from request(1)", struct svc_req *, req);
633
634 if (!blequal(&l_admin_low->tsl_label, clabel)) {
635 if ((equal_label = do_rfs_label_check(clabel, vp,
636 EQUALITY_CHECK, exi)) == B_FALSE) {
637 dominant_label = do_rfs_label_check(clabel,
638 vp, DOMINANCE_CHECK, exi);
639 } else
640 dominant_label = B_TRUE;
641 admin_low_client = B_FALSE;
642 } else
643 admin_low_client = B_TRUE;
678 (args->access & ACCESS3_DELETE) && vp->v_type == VDIR) {
679 error = VOP_ACCESS(vp, VWRITE, 0, cr, NULL);
680 if (error) {
681 if (curthread->t_flag & T_WOULDBLOCK)
682 goto out;
683 } else if (!is_system_labeled() || admin_low_client ||
684 equal_label)
685 resp->resok.access |= ACCESS3_DELETE;
686 }
687 if (args->access & ACCESS3_EXECUTE) {
688 error = VOP_ACCESS(vp, VEXEC, 0, cr, NULL);
689 if (error) {
690 if (curthread->t_flag & T_WOULDBLOCK)
691 goto out;
692 } else if (!MANDLOCK(vp, va.va_mode) &&
693 (!is_system_labeled() || admin_low_client ||
694 dominant_label))
695 resp->resok.access |= ACCESS3_EXECUTE;
696 }
697
698 va.va_mask = AT_ALL;
699 vap = rfs4_delegated_getattr(vp, &va, 0, cr) ? NULL : &va;
700
701 resp->status = NFS3_OK;
702 vattr_to_post_op_attr(vap, &resp->resok.obj_attributes);
703
704 DTRACE_NFSV3_4(op__access__done, struct svc_req *, req,
705 cred_t *, cr, vnode_t *, vp, ACCESS3res *, resp);
706
707 VN_RELE(vp);
708
709 return;
710
711 out:
712 if (curthread->t_flag & T_WOULDBLOCK) {
713 curthread->t_flag &= ~T_WOULDBLOCK;
714 resp->status = NFS3ERR_JUKEBOX;
715 } else
716 resp->status = puterrno3(error);
717 DTRACE_NFSV3_4(op__access__done, struct svc_req *, req,
718 cred_t *, cr, vnode_t *, vp, ACCESS3res *, resp);
719 if (vp != NULL)
744 char *name = NULL;
745 int is_referral = 0;
746
747 vap = NULL;
748
749 vp = nfs3_fhtovp(&args->symlink, exi);
750
751 DTRACE_NFSV3_4(op__readlink__start, struct svc_req *, req,
752 cred_t *, cr, vnode_t *, vp, READLINK3args *, args);
753
754 if (vp == NULL) {
755 error = ESTALE;
756 goto out;
757 }
758
759 va.va_mask = AT_ALL;
760 error = VOP_GETATTR(vp, &va, 0, cr, NULL);
761 if (error)
762 goto out;
763
764 vap = &va;
765
766 /* We lied about the object type for a referral */
767 if (vn_is_nfs_reparse(vp, cr))
768 is_referral = 1;
769
770 if (vp->v_type != VLNK && !is_referral) {
771 resp->status = NFS3ERR_INVAL;
772 goto out1;
773 }
774
775 if (MANDLOCK(vp, va.va_mode)) {
776 resp->status = NFS3ERR_ACCES;
777 goto out1;
778 }
779
780 if (is_system_labeled()) {
781 bslabel_t *clabel = req->rq_label;
782
783 ASSERT(clabel != NULL);
784 DTRACE_PROBE2(tx__rfs3__log__info__opreadlink__clabel, char *,
812 kmem_free(s, strsz);
813 }
814
815 } else {
816
817 iov.iov_base = data;
818 iov.iov_len = MAXPATHLEN;
819 uio.uio_iov = &iov;
820 uio.uio_iovcnt = 1;
821 uio.uio_segflg = UIO_SYSSPACE;
822 uio.uio_extflg = UIO_COPY_CACHED;
823 uio.uio_loffset = 0;
824 uio.uio_resid = MAXPATHLEN;
825
826 error = VOP_READLINK(vp, &uio, cr, NULL);
827
828 if (!error)
829 *(data + MAXPATHLEN - uio.uio_resid) = '\0';
830 }
831
832 va.va_mask = AT_ALL;
833 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
834
835 /* Lie about object type again just to be consistent */
836 if (is_referral && vap != NULL)
837 vap->va_type = VLNK;
838
839 #if 0 /* notyet */
840 /*
841 * Don't do this. It causes local disk writes when just
842 * reading the file and the overhead is deemed larger
843 * than the benefit.
844 */
845 /*
846 * Force modified metadata out to stable storage.
847 */
848 (void) VOP_FSYNC(vp, FNODSYNC, cr, NULL);
849 #endif
850
851 if (error) {
852 kmem_free(data, MAXPATHLEN + 1);
853 goto out;
854 }
993 error = VOP_RWLOCK(vp, V_WRITELOCK_FALSE, &ct);
994
995 /* check if a monitor detected a delegation conflict */
996 if (error == EAGAIN && (ct.cc_flags & CC_WOULDBLOCK)) {
997 resp->status = NFS3ERR_JUKEBOX;
998 goto out1;
999 }
1000
1001 need_rwunlock = 1;
1002
1003 va.va_mask = AT_ALL;
1004 error = VOP_GETATTR(vp, &va, 0, cr, &ct);
1005
1006 /*
1007 * If we can't get the attributes, then we can't do the
1008 * right access checking. So, we'll fail the request.
1009 */
1010 if (error)
1011 goto out;
1012
1013 vap = &va;
1014
1015 if (vp->v_type != VREG) {
1016 resp->status = NFS3ERR_INVAL;
1017 goto out1;
1018 }
1019
1020 if (crgetuid(cr) != va.va_uid) {
1021 error = VOP_ACCESS(vp, VREAD, 0, cr, &ct);
1022 if (error) {
1023 if (curthread->t_flag & T_WOULDBLOCK)
1024 goto out;
1025 error = VOP_ACCESS(vp, VEXEC, 0, cr, &ct);
1026 if (error)
1027 goto out;
1028 }
1029 }
1030
1031 if (MANDLOCK(vp, va.va_mode)) {
1032 resp->status = NFS3ERR_ACCES;
1033 goto out1;
1143 if (error) {
1144 if (mp)
1145 freemsg(mp);
1146 /* check if a monitor detected a delegation conflict */
1147 if (error == EAGAIN && (ct.cc_flags & CC_WOULDBLOCK)) {
1148 resp->status = NFS3ERR_JUKEBOX;
1149 goto out1;
1150 }
1151 goto out;
1152 }
1153
1154 /* make mblk using zc buffers */
1155 if (loaned_buffers) {
1156 mp = uio_to_mblk(uiop);
1157 ASSERT(mp != NULL);
1158 }
1159
1160 va.va_mask = AT_ALL;
1161 error = VOP_GETATTR(vp, &va, 0, cr, &ct);
1162
1163 if (error)
1164 vap = NULL;
1165 else
1166 vap = &va;
1167
1168 VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, &ct);
1169
1170 if (in_crit)
1171 nbl_end_crit(vp);
1172
1173 resp->status = NFS3_OK;
1174 vattr_to_post_op_attr(vap, &resp->resok.file_attributes);
1175 resp->resok.count = args->count - uiop->uio_resid;
1176 if (!error && offset + resp->resok.count == va.va_size)
1177 resp->resok.eof = TRUE;
1178 else
1179 resp->resok.eof = FALSE;
1180 resp->resok.data.data_len = resp->resok.count;
1181
1182 if (mp)
1183 rfs_rndup_mblks(mp, resp->resok.count, loaned_buffers);
1184
1185 resp->resok.data.mp = mp;
1186 resp->resok.size = (uint_t)args->count;
1320
1321 /* check if a monitor detected a delegation conflict */
1322 if (rwlock_ret == EAGAIN && (ct.cc_flags & CC_WOULDBLOCK)) {
1323 resp->status = NFS3ERR_JUKEBOX;
1324 rwlock_ret = -1;
1325 goto err1;
1326 }
1327
1328
1329 bva.va_mask = AT_ALL;
1330 error = VOP_GETATTR(vp, &bva, 0, cr, &ct);
1331
1332 /*
1333 * If we can't get the attributes, then we can't do the
1334 * right access checking. So, we'll fail the request.
1335 */
1336 if (error)
1337 goto err;
1338
1339 bvap = &bva;
1340 avap = bvap;
1341
1342 if (args->count != args->data.data_len) {
1343 resp->status = NFS3ERR_INVAL;
1344 goto err1;
1345 }
1346
1347 if (rdonly(exi, req)) {
1348 resp->status = NFS3ERR_ROFS;
1349 goto err1;
1350 }
1351
1352 if (vp->v_type != VREG) {
1353 resp->status = NFS3ERR_INVAL;
1354 goto err1;
1355 }
1356
1357 if (crgetuid(cr) != bva.va_uid &&
1358 (error = VOP_ACCESS(vp, VWRITE, 0, cr, &ct)))
1359 goto err;
1431 * the cred of the current thread to be used if quota
1432 * checking is enabled.
1433 */
1434 savecred = curthread->t_cred;
1435 curthread->t_cred = cr;
1436 error = VOP_WRITE(vp, &uio, ioflag, cr, &ct);
1437 curthread->t_cred = savecred;
1438
1439 if (iovp != iov)
1440 kmem_free(iovp, sizeof (*iovp) * iovcnt);
1441
1442 /* check if a monitor detected a delegation conflict */
1443 if (error == EAGAIN && (ct.cc_flags & CC_WOULDBLOCK)) {
1444 resp->status = NFS3ERR_JUKEBOX;
1445 goto err1;
1446 }
1447
1448 ava.va_mask = AT_ALL;
1449 avap = VOP_GETATTR(vp, &ava, 0, cr, &ct) ? NULL : &ava;
1450
1451 if (error)
1452 goto err;
1453
1454 /*
1455 * If we were unable to get the V_WRITELOCK_TRUE, then we
1456 * may not have accurate after attrs, so check if
1457 * we have both attributes, they have a non-zero va_seq, and
1458 * va_seq has changed by exactly one,
1459 * if not, turn off the before attr.
1460 */
1461 if (rwlock_ret != V_WRITELOCK_TRUE) {
1462 if (bvap == NULL || avap == NULL ||
1463 bvap->va_seq == 0 || avap->va_seq == 0 ||
1464 avap->va_seq != (bvap->va_seq + 1)) {
1465 bvap = NULL;
1466 }
1467 }
1468
1469 resp->status = NFS3_OK;
1470 vattr_to_wcc_data(bvap, avap, &resp->resok.file_wcc);
1519 enum vcexcl excl;
1520 nfstime3 *mtime;
1521 len_t reqsize;
1522 bool_t trunc;
1523 struct sockaddr *ca;
1524 char *name = NULL;
1525
1526 dbvap = NULL;
1527 davap = NULL;
1528
1529 dvp = nfs3_fhtovp(&args->where.dir, exi);
1530
1531 DTRACE_NFSV3_4(op__create__start, struct svc_req *, req,
1532 cred_t *, cr, vnode_t *, dvp, CREATE3args *, args);
1533
1534 if (dvp == NULL) {
1535 error = ESTALE;
1536 goto out;
1537 }
1538
1539 dbva.va_mask = AT_ALL;
1540 dbvap = VOP_GETATTR(dvp, &dbva, 0, cr, NULL) ? NULL : &dbva;
1541 davap = dbvap;
1542
1543 if (args->where.name == nfs3nametoolong) {
1544 resp->status = NFS3ERR_NAMETOOLONG;
1545 goto out1;
1546 }
1547
1548 if (args->where.name == NULL || *(args->where.name) == '\0') {
1549 resp->status = NFS3ERR_ACCES;
1550 goto out1;
1551 }
1552
1553 if (rdonly(exi, req)) {
1554 resp->status = NFS3ERR_ROFS;
1555 goto out1;
1556 }
1557
1558 if (is_system_labeled()) {
1559 bslabel_t *clabel = req->rq_label;
1560
1683 goto out1;
1684 }
1685
1686 /*
1687 * If the filesystem is exported with nosuid, then mask off
1688 * the setuid and setgid bits.
1689 */
1690 if (va.va_type == VREG && (exi->exi_export.ex_flags & EX_NOSUID))
1691 va.va_mode &= ~(VSUID | VSGID);
1692
1693 tryagain:
1694 /*
1695 * The file open mode used is VWRITE. If the client needs
1696 * some other semantic, then it should do the access checking
1697 * itself. It would have been nice to have the file open mode
1698 * passed as part of the arguments.
1699 */
1700 error = VOP_CREATE(dvp, name, &va, excl, VWRITE,
1701 &vp, cr, 0, NULL, NULL);
1702
1703 dava.va_mask = AT_ALL;
1704 davap = VOP_GETATTR(dvp, &dava, 0, cr, NULL) ? NULL : &dava;
1705
1706 if (error) {
1707 /*
1708 * If we got something other than file already exists
1709 * then just return this error. Otherwise, we got
1710 * EEXIST. If we were doing a GUARDED create, then
1711 * just return this error. Otherwise, we need to
1712 * make sure that this wasn't a duplicate of an
1713 * exclusive create request.
1714 *
1715 * The assumption is made that a non-exclusive create
1716 * request will never return EEXIST.
1717 */
1718 if (error != EEXIST || args->how.mode == GUARDED)
1719 goto out;
1720 /*
1721 * Lookup the file so that we can get a vnode for it.
1722 */
1723 error = VOP_LOOKUP(dvp, name, &vp, NULL, 0,
1724 NULL, cr, NULL, NULL, NULL);
1788 * still recover by checking the size of the file
1789 * after it has created it and then issue a setattr
1790 * request of its own to set the size of the file.
1791 */
1792 if (vap != NULL &&
1793 (args->how.mode == UNCHECKED ||
1794 args->how.mode == GUARDED) &&
1795 args->how.createhow3_u.obj_attributes.size.set_it &&
1796 vap->va_size != reqsize) {
1797 va.va_mask = AT_SIZE;
1798 va.va_size = reqsize;
1799 (void) VOP_SETATTR(vp, &va, 0, cr, NULL);
1800 va.va_mask = AT_ALL;
1801 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
1802 }
1803 }
1804
1805 if (name != args->where.name)
1806 kmem_free(name, MAXPATHLEN + 1);
1807
1808 error = makefh3(&resp->resok.obj.handle, vp, exi);
1809 if (error)
1810 resp->resok.obj.handle_follows = FALSE;
1811 else
1812 resp->resok.obj.handle_follows = TRUE;
1813
1814 /*
1815 * Force modified data and metadata out to stable storage.
1816 */
1817 (void) VOP_FSYNC(vp, FNODSYNC, cr, NULL);
1818 (void) VOP_FSYNC(dvp, 0, cr, NULL);
1819
1820 VN_RELE(vp);
1821 if (tvp != NULL) {
1822 if (in_crit)
1823 nbl_end_crit(tvp);
1824 VN_RELE(tvp);
1825 }
1826
1827 resp->status = NFS3_OK;
1828 vattr_to_post_op_attr(vap, &resp->resok.obj_attributes);
1829 vattr_to_wcc_data(dbvap, davap, &resp->resok.dir_wcc);
1830
1831 DTRACE_NFSV3_4(op__create__done, struct svc_req *, req,
1832 cred_t *, cr, vnode_t *, dvp, CREATE3res *, resp);
1876 struct vattr *dbvap;
1877 struct vattr dbva;
1878 struct vattr *davap;
1879 struct vattr dava;
1880 struct sockaddr *ca;
1881 char *name = NULL;
1882
1883 dbvap = NULL;
1884 davap = NULL;
1885
1886 dvp = nfs3_fhtovp(&args->where.dir, exi);
1887
1888 DTRACE_NFSV3_4(op__mkdir__start, struct svc_req *, req,
1889 cred_t *, cr, vnode_t *, dvp, MKDIR3args *, args);
1890
1891 if (dvp == NULL) {
1892 error = ESTALE;
1893 goto out;
1894 }
1895
1896 dbva.va_mask = AT_ALL;
1897 dbvap = VOP_GETATTR(dvp, &dbva, 0, cr, NULL) ? NULL : &dbva;
1898 davap = dbvap;
1899
1900 if (args->where.name == nfs3nametoolong) {
1901 resp->status = NFS3ERR_NAMETOOLONG;
1902 goto out1;
1903 }
1904
1905 if (args->where.name == NULL || *(args->where.name) == '\0') {
1906 resp->status = NFS3ERR_ACCES;
1907 goto out1;
1908 }
1909
1910 if (rdonly(exi, req)) {
1911 resp->status = NFS3ERR_ROFS;
1912 goto out1;
1913 }
1914
1915 if (is_system_labeled()) {
1916 bslabel_t *clabel = req->rq_label;
1917
1937 goto out1;
1938 }
1939
1940 ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
1941 name = nfscmd_convname(ca, exi, args->where.name,
1942 NFSCMD_CONV_INBOUND, MAXPATHLEN + 1);
1943
1944 if (name == NULL) {
1945 resp->status = NFS3ERR_INVAL;
1946 goto out1;
1947 }
1948
1949 va.va_mask |= AT_TYPE;
1950 va.va_type = VDIR;
1951
1952 error = VOP_MKDIR(dvp, name, &va, &vp, cr, NULL, 0, NULL);
1953
1954 if (name != args->where.name)
1955 kmem_free(name, MAXPATHLEN + 1);
1956
1957 dava.va_mask = AT_ALL;
1958 davap = VOP_GETATTR(dvp, &dava, 0, cr, NULL) ? NULL : &dava;
1959
1960 /*
1961 * Force modified data and metadata out to stable storage.
1962 */
1963 (void) VOP_FSYNC(dvp, 0, cr, NULL);
1964
1965 if (error)
1966 goto out;
1967
1968 error = makefh3(&resp->resok.obj.handle, vp, exi);
1969 if (error)
1970 resp->resok.obj.handle_follows = FALSE;
1971 else
1972 resp->resok.obj.handle_follows = TRUE;
1973
1974 va.va_mask = AT_ALL;
1975 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
1976
1977 /*
1978 * Force modified data and metadata out to stable storage.
1979 */
1980 (void) VOP_FSYNC(vp, 0, cr, NULL);
1981
1982 VN_RELE(vp);
1983
1984 resp->status = NFS3_OK;
1985 vattr_to_post_op_attr(vap, &resp->resok.obj_attributes);
1986 vattr_to_wcc_data(dbvap, davap, &resp->resok.dir_wcc);
1987
1988 DTRACE_NFSV3_4(op__mkdir__done, struct svc_req *, req,
1989 cred_t *, cr, vnode_t *, dvp, MKDIR3res *, resp);
1990 VN_RELE(dvp);
1991
1992 return;
1993
1994 out:
1995 if (curthread->t_flag & T_WOULDBLOCK) {
2025 struct vattr dbva;
2026 struct vattr *davap;
2027 struct vattr dava;
2028 struct sockaddr *ca;
2029 char *name = NULL;
2030 char *symdata = NULL;
2031
2032 dbvap = NULL;
2033 davap = NULL;
2034
2035 dvp = nfs3_fhtovp(&args->where.dir, exi);
2036
2037 DTRACE_NFSV3_4(op__symlink__start, struct svc_req *, req,
2038 cred_t *, cr, vnode_t *, dvp, SYMLINK3args *, args);
2039
2040 if (dvp == NULL) {
2041 error = ESTALE;
2042 goto err;
2043 }
2044
2045 dbva.va_mask = AT_ALL;
2046 dbvap = VOP_GETATTR(dvp, &dbva, 0, cr, NULL) ? NULL : &dbva;
2047 davap = dbvap;
2048
2049 if (args->where.name == nfs3nametoolong) {
2050 resp->status = NFS3ERR_NAMETOOLONG;
2051 goto err1;
2052 }
2053
2054 if (args->where.name == NULL || *(args->where.name) == '\0') {
2055 resp->status = NFS3ERR_ACCES;
2056 goto err1;
2057 }
2058
2059 if (rdonly(exi, req)) {
2060 resp->status = NFS3ERR_ROFS;
2061 goto err1;
2062 }
2063
2064 if (is_system_labeled()) {
2065 bslabel_t *clabel = req->rq_label;
2066
2098 if (name == NULL) {
2099 /* This is really a Solaris EILSEQ */
2100 resp->status = NFS3ERR_INVAL;
2101 goto err1;
2102 }
2103
2104 symdata = nfscmd_convname(ca, exi, args->symlink.symlink_data,
2105 NFSCMD_CONV_INBOUND, MAXPATHLEN + 1);
2106 if (symdata == NULL) {
2107 /* This is really a Solaris EILSEQ */
2108 resp->status = NFS3ERR_INVAL;
2109 goto err1;
2110 }
2111
2112
2113 va.va_mask |= AT_TYPE;
2114 va.va_type = VLNK;
2115
2116 error = VOP_SYMLINK(dvp, name, &va, symdata, cr, NULL, 0);
2117
2118 dava.va_mask = AT_ALL;
2119 davap = VOP_GETATTR(dvp, &dava, 0, cr, NULL) ? NULL : &dava;
2120
2121 if (error)
2122 goto err;
2123
2124 error = VOP_LOOKUP(dvp, name, &vp, NULL, 0, NULL, cr,
2125 NULL, NULL, NULL);
2126
2127 /*
2128 * Force modified data and metadata out to stable storage.
2129 */
2130 (void) VOP_FSYNC(dvp, 0, cr, NULL);
2131
2132
2133 resp->status = NFS3_OK;
2134 if (error) {
2135 resp->resok.obj.handle_follows = FALSE;
2136 vattr_to_post_op_attr(NULL, &resp->resok.obj_attributes);
2137 vattr_to_wcc_data(dbvap, davap, &resp->resok.dir_wcc);
2138 goto out;
2139 }
2140
2141 error = makefh3(&resp->resok.obj.handle, vp, exi);
2142 if (error)
2143 resp->resok.obj.handle_follows = FALSE;
2144 else
2145 resp->resok.obj.handle_follows = TRUE;
2146
2147 va.va_mask = AT_ALL;
2148 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
2149
2150 /*
2151 * Force modified data and metadata out to stable storage.
2152 */
2153 (void) VOP_FSYNC(vp, 0, cr, NULL);
2154
2155 VN_RELE(vp);
2156
2157 vattr_to_post_op_attr(vap, &resp->resok.obj_attributes);
2158 vattr_to_wcc_data(dbvap, davap, &resp->resok.dir_wcc);
2159 goto out;
2160
2161 err:
2162 if (curthread->t_flag & T_WOULDBLOCK) {
2163 curthread->t_flag &= ~T_WOULDBLOCK;
2164 resp->status = NFS3ERR_JUKEBOX;
2165 } else
2166 resp->status = puterrno3(error);
2167 err1:
2168 vattr_to_wcc_data(dbvap, davap, &resp->resfail.dir_wcc);
2201 struct vattr *davap;
2202 struct vattr dava;
2203 int mode;
2204 enum vcexcl excl;
2205 struct sockaddr *ca;
2206 char *name = NULL;
2207
2208 dbvap = NULL;
2209 davap = NULL;
2210
2211 dvp = nfs3_fhtovp(&args->where.dir, exi);
2212
2213 DTRACE_NFSV3_4(op__mknod__start, struct svc_req *, req,
2214 cred_t *, cr, vnode_t *, dvp, MKNOD3args *, args);
2215
2216 if (dvp == NULL) {
2217 error = ESTALE;
2218 goto out;
2219 }
2220
2221 dbva.va_mask = AT_ALL;
2222 dbvap = VOP_GETATTR(dvp, &dbva, 0, cr, NULL) ? NULL : &dbva;
2223 davap = dbvap;
2224
2225 if (args->where.name == nfs3nametoolong) {
2226 resp->status = NFS3ERR_NAMETOOLONG;
2227 goto out1;
2228 }
2229
2230 if (args->where.name == NULL || *(args->where.name) == '\0') {
2231 resp->status = NFS3ERR_ACCES;
2232 goto out1;
2233 }
2234
2235 if (rdonly(exi, req)) {
2236 resp->status = NFS3ERR_ROFS;
2237 goto out1;
2238 }
2239
2240 if (is_system_labeled()) {
2241 bslabel_t *clabel = req->rq_label;
2242
2304
2305 ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
2306 name = nfscmd_convname(ca, exi, args->where.name,
2307 NFSCMD_CONV_INBOUND, MAXPATHLEN + 1);
2308
2309 if (name == NULL) {
2310 resp->status = NFS3ERR_INVAL;
2311 goto out1;
2312 }
2313
2314 excl = EXCL;
2315
2316 mode = 0;
2317
2318 error = VOP_CREATE(dvp, name, &va, excl, mode,
2319 &vp, cr, 0, NULL, NULL);
2320
2321 if (name != args->where.name)
2322 kmem_free(name, MAXPATHLEN + 1);
2323
2324 dava.va_mask = AT_ALL;
2325 davap = VOP_GETATTR(dvp, &dava, 0, cr, NULL) ? NULL : &dava;
2326
2327 /*
2328 * Force modified data and metadata out to stable storage.
2329 */
2330 (void) VOP_FSYNC(dvp, 0, cr, NULL);
2331
2332 if (error)
2333 goto out;
2334
2335 resp->status = NFS3_OK;
2336
2337 error = makefh3(&resp->resok.obj.handle, vp, exi);
2338 if (error)
2339 resp->resok.obj.handle_follows = FALSE;
2340 else
2341 resp->resok.obj.handle_follows = TRUE;
2342
2343 va.va_mask = AT_ALL;
2344 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
2345
2346 /*
2347 * Force modified metadata out to stable storage.
2348 *
2349 * if a underlying vp exists, pass it to VOP_FSYNC
2350 */
2351 if (VOP_REALVP(vp, &realvp, NULL) == 0)
2352 (void) VOP_FSYNC(realvp, FNODSYNC, cr, NULL);
2353 else
2354 (void) VOP_FSYNC(vp, FNODSYNC, cr, NULL);
2355
2356 VN_RELE(vp);
2357
2358 vattr_to_post_op_attr(vap, &resp->resok.obj_attributes);
2359 vattr_to_wcc_data(dbvap, davap, &resp->resok.dir_wcc);
2360 DTRACE_NFSV3_4(op__mknod__done, struct svc_req *, req,
2361 cred_t *, cr, vnode_t *, dvp, MKNOD3res *, resp);
2362 VN_RELE(dvp);
2363 return;
2364
2393 struct vattr bva;
2394 struct vattr *avap;
2395 struct vattr ava;
2396 vnode_t *targvp = NULL;
2397 struct sockaddr *ca;
2398 char *name = NULL;
2399
2400 bvap = NULL;
2401 avap = NULL;
2402
2403 vp = nfs3_fhtovp(&args->object.dir, exi);
2404
2405 DTRACE_NFSV3_4(op__remove__start, struct svc_req *, req,
2406 cred_t *, cr, vnode_t *, vp, REMOVE3args *, args);
2407
2408 if (vp == NULL) {
2409 error = ESTALE;
2410 goto err;
2411 }
2412
2413 bva.va_mask = AT_ALL;
2414 bvap = VOP_GETATTR(vp, &bva, 0, cr, NULL) ? NULL : &bva;
2415 avap = bvap;
2416
2417 if (vp->v_type != VDIR) {
2418 resp->status = NFS3ERR_NOTDIR;
2419 goto err1;
2420 }
2421
2422 if (args->object.name == nfs3nametoolong) {
2423 resp->status = NFS3ERR_NAMETOOLONG;
2424 goto err1;
2425 }
2426
2427 if (args->object.name == NULL || *(args->object.name) == '\0') {
2428 resp->status = NFS3ERR_ACCES;
2429 goto err1;
2430 }
2431
2432 if (rdonly(exi, req)) {
2433 resp->status = NFS3ERR_ROFS;
2434 goto err1;
2470
2471 if (rfs4_check_delegated(FWRITE, targvp, TRUE)) {
2472 resp->status = NFS3ERR_JUKEBOX;
2473 goto err1;
2474 }
2475
2476 if (!nbl_need_check(targvp)) {
2477 error = VOP_REMOVE(vp, name, cr, NULL, 0);
2478 } else {
2479 nbl_start_crit(targvp, RW_READER);
2480 if (nbl_conflict(targvp, NBL_REMOVE, 0, 0, 0, NULL)) {
2481 error = EACCES;
2482 } else {
2483 error = VOP_REMOVE(vp, name, cr, NULL, 0);
2484 }
2485 nbl_end_crit(targvp);
2486 }
2487 VN_RELE(targvp);
2488 targvp = NULL;
2489
2490 ava.va_mask = AT_ALL;
2491 avap = VOP_GETATTR(vp, &ava, 0, cr, NULL) ? NULL : &ava;
2492
2493 /*
2494 * Force modified data and metadata out to stable storage.
2495 */
2496 (void) VOP_FSYNC(vp, 0, cr, NULL);
2497
2498 if (error)
2499 goto err;
2500
2501 resp->status = NFS3_OK;
2502 vattr_to_wcc_data(bvap, avap, &resp->resok.dir_wcc);
2503 goto out;
2504
2505 err:
2506 if (curthread->t_flag & T_WOULDBLOCK) {
2507 curthread->t_flag &= ~T_WOULDBLOCK;
2508 resp->status = NFS3ERR_JUKEBOX;
2509 } else
2510 resp->status = puterrno3(error);
2511 err1:
2537 struct vattr *bvap;
2538 struct vattr bva;
2539 struct vattr *avap;
2540 struct vattr ava;
2541 struct sockaddr *ca;
2542 char *name = NULL;
2543
2544 bvap = NULL;
2545 avap = NULL;
2546
2547 vp = nfs3_fhtovp(&args->object.dir, exi);
2548
2549 DTRACE_NFSV3_4(op__rmdir__start, struct svc_req *, req,
2550 cred_t *, cr, vnode_t *, vp, RMDIR3args *, args);
2551
2552 if (vp == NULL) {
2553 error = ESTALE;
2554 goto err;
2555 }
2556
2557 bva.va_mask = AT_ALL;
2558 bvap = VOP_GETATTR(vp, &bva, 0, cr, NULL) ? NULL : &bva;
2559 avap = bvap;
2560
2561 if (vp->v_type != VDIR) {
2562 resp->status = NFS3ERR_NOTDIR;
2563 goto err1;
2564 }
2565
2566 if (args->object.name == nfs3nametoolong) {
2567 resp->status = NFS3ERR_NAMETOOLONG;
2568 goto err1;
2569 }
2570
2571 if (args->object.name == NULL || *(args->object.name) == '\0') {
2572 resp->status = NFS3ERR_ACCES;
2573 goto err1;
2574 }
2575
2576 if (rdonly(exi, req)) {
2577 resp->status = NFS3ERR_ROFS;
2578 goto err1;
2591 resp->status = NFS3ERR_ACCES;
2592 goto err1;
2593 }
2594 }
2595 }
2596
2597 ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
2598 name = nfscmd_convname(ca, exi, args->object.name,
2599 NFSCMD_CONV_INBOUND, MAXPATHLEN + 1);
2600
2601 if (name == NULL) {
2602 resp->status = NFS3ERR_INVAL;
2603 goto err1;
2604 }
2605
2606 error = VOP_RMDIR(vp, name, rootdir, cr, NULL, 0);
2607
2608 if (name != args->object.name)
2609 kmem_free(name, MAXPATHLEN + 1);
2610
2611 ava.va_mask = AT_ALL;
2612 avap = VOP_GETATTR(vp, &ava, 0, cr, NULL) ? NULL : &ava;
2613
2614 /*
2615 * Force modified data and metadata out to stable storage.
2616 */
2617 (void) VOP_FSYNC(vp, 0, cr, NULL);
2618
2619 if (error) {
2620 /*
2621 * System V defines rmdir to return EEXIST, not ENOTEMPTY,
2622 * if the directory is not empty. A System V NFS server
2623 * needs to map NFS3ERR_EXIST to NFS3ERR_NOTEMPTY to transmit
2624 * over the wire.
2625 */
2626 if (error == EEXIST)
2627 error = ENOTEMPTY;
2628 goto err;
2629 }
2630
2631 resp->status = NFS3_OK;
2632 vattr_to_wcc_data(bvap, avap, &resp->resok.dir_wcc);
2693 if (fvp == NULL) {
2694 error = ESTALE;
2695 goto err;
2696 }
2697
2698 if (is_system_labeled()) {
2699 clabel = req->rq_label;
2700 ASSERT(clabel != NULL);
2701 DTRACE_PROBE2(tx__rfs3__log__info__oprename__clabel, char *,
2702 "got client label from request(1)", struct svc_req *, req);
2703
2704 if (!blequal(&l_admin_low->tsl_label, clabel)) {
2705 if (!do_rfs_label_check(clabel, fvp, EQUALITY_CHECK,
2706 exi)) {
2707 resp->status = NFS3ERR_ACCES;
2708 goto err1;
2709 }
2710 }
2711 }
2712
2713 fbva.va_mask = AT_ALL;
2714 fbvap = VOP_GETATTR(fvp, &fbva, 0, cr, NULL) ? NULL : &fbva;
2715 favap = fbvap;
2716
2717 fh3 = &args->to.dir;
2718 to_exi = checkexport(&fh3->fh3_fsid, FH3TOXFIDP(fh3));
2719 if (to_exi == NULL) {
2720 resp->status = NFS3ERR_ACCES;
2721 goto err1;
2722 }
2723 exi_rele(to_exi);
2724
2725 if (to_exi != exi) {
2726 resp->status = NFS3ERR_XDEV;
2727 goto err1;
2728 }
2729
2730 tvp = nfs3_fhtovp(&args->to.dir, exi);
2731 if (tvp == NULL) {
2732 error = ESTALE;
2733 goto err;
2734 }
2735
2736 tbva.va_mask = AT_ALL;
2737 tbvap = VOP_GETATTR(tvp, &tbva, 0, cr, NULL) ? NULL : &tbva;
2738 tavap = tbvap;
2739
2740 if (fvp->v_type != VDIR || tvp->v_type != VDIR) {
2741 resp->status = NFS3ERR_NOTDIR;
2742 goto err1;
2743 }
2744
2745 if (args->from.name == nfs3nametoolong ||
2746 args->to.name == nfs3nametoolong) {
2747 resp->status = NFS3ERR_NAMETOOLONG;
2748 goto err1;
2749 }
2750 if (args->from.name == NULL || *(args->from.name) == '\0' ||
2751 args->to.name == NULL || *(args->to.name) == '\0') {
2752 resp->status = NFS3ERR_ACCES;
2753 goto err1;
2754 }
2755
2756 if (rdonly(exi, req)) {
2757 resp->status = NFS3ERR_ROFS;
2819 }
2820 VN_RELE(targvp);
2821 }
2822
2823 if (!nbl_need_check(srcvp)) {
2824 error = VOP_RENAME(fvp, name, tvp, toname, cr, NULL, 0);
2825 } else {
2826 nbl_start_crit(srcvp, RW_READER);
2827 if (nbl_conflict(srcvp, NBL_RENAME, 0, 0, 0, NULL))
2828 error = EACCES;
2829 else
2830 error = VOP_RENAME(fvp, name, tvp, toname, cr, NULL, 0);
2831 nbl_end_crit(srcvp);
2832 }
2833 if (error == 0)
2834 vn_renamepath(tvp, srcvp, args->to.name,
2835 strlen(args->to.name));
2836 VN_RELE(srcvp);
2837 srcvp = NULL;
2838
2839 fava.va_mask = AT_ALL;
2840 favap = VOP_GETATTR(fvp, &fava, 0, cr, NULL) ? NULL : &fava;
2841 tava.va_mask = AT_ALL;
2842 tavap = VOP_GETATTR(tvp, &tava, 0, cr, NULL) ? NULL : &tava;
2843
2844 /*
2845 * Force modified data and metadata out to stable storage.
2846 */
2847 (void) VOP_FSYNC(fvp, 0, cr, NULL);
2848 (void) VOP_FSYNC(tvp, 0, cr, NULL);
2849
2850 if (error)
2851 goto err;
2852
2853 resp->status = NFS3_OK;
2854 vattr_to_wcc_data(fbvap, favap, &resp->resok.fromdir_wcc);
2855 vattr_to_wcc_data(tbvap, tavap, &resp->resok.todir_wcc);
2856 goto out;
2857
2858 err:
2859 if (curthread->t_flag & T_WOULDBLOCK) {
2860 curthread->t_flag &= ~T_WOULDBLOCK;
2861 resp->status = NFS3ERR_JUKEBOX;
2862 } else {
2904 struct exportinfo *to_exi;
2905 bslabel_t *clabel;
2906 struct sockaddr *ca;
2907 char *name = NULL;
2908
2909 vap = NULL;
2910 bvap = NULL;
2911 avap = NULL;
2912 dvp = NULL;
2913
2914 vp = nfs3_fhtovp(&args->file, exi);
2915
2916 DTRACE_NFSV3_4(op__link__start, struct svc_req *, req,
2917 cred_t *, cr, vnode_t *, vp, LINK3args *, args);
2918
2919 if (vp == NULL) {
2920 error = ESTALE;
2921 goto out;
2922 }
2923
2924 va.va_mask = AT_ALL;
2925 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
2926
2927 fh3 = &args->link.dir;
2928 to_exi = checkexport(&fh3->fh3_fsid, FH3TOXFIDP(fh3));
2929 if (to_exi == NULL) {
2930 resp->status = NFS3ERR_ACCES;
2931 goto out1;
2932 }
2933 exi_rele(to_exi);
2934
2935 if (to_exi != exi) {
2936 resp->status = NFS3ERR_XDEV;
2937 goto out1;
2938 }
2939
2940 if (is_system_labeled()) {
2941 clabel = req->rq_label;
2942
2943 ASSERT(clabel != NULL);
2944 DTRACE_PROBE2(tx__rfs3__log__info__oplink__clabel, char *,
2945 "got client label from request(1)", struct svc_req *, req);
2946
2947 if (!blequal(&l_admin_low->tsl_label, clabel)) {
2948 if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK,
2949 exi)) {
2950 resp->status = NFS3ERR_ACCES;
2951 goto out1;
2952 }
2953 }
2954 }
2955
2956 dvp = nfs3_fhtovp(&args->link.dir, exi);
2957 if (dvp == NULL) {
2958 error = ESTALE;
2959 goto out;
2960 }
2961
2962 bva.va_mask = AT_ALL;
2963 bvap = VOP_GETATTR(dvp, &bva, 0, cr, NULL) ? NULL : &bva;
2964
2965 if (dvp->v_type != VDIR) {
2966 resp->status = NFS3ERR_NOTDIR;
2967 goto out1;
2968 }
2969
2970 if (args->link.name == nfs3nametoolong) {
2971 resp->status = NFS3ERR_NAMETOOLONG;
2972 goto out1;
2973 }
2974
2975 if (args->link.name == NULL || *(args->link.name) == '\0') {
2976 resp->status = NFS3ERR_ACCES;
2977 goto out1;
2978 }
2979
2980 if (rdonly(exi, req)) {
2981 resp->status = NFS3ERR_ROFS;
2982 goto out1;
2983 }
2989 if (!blequal(&l_admin_low->tsl_label, clabel)) {
2990 if (!do_rfs_label_check(clabel, dvp, EQUALITY_CHECK,
2991 exi)) {
2992 resp->status = NFS3ERR_ACCES;
2993 goto out1;
2994 }
2995 }
2996 }
2997
2998 ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
2999 name = nfscmd_convname(ca, exi, args->link.name,
3000 NFSCMD_CONV_INBOUND, MAXPATHLEN + 1);
3001
3002 if (name == NULL) {
3003 resp->status = NFS3ERR_SERVERFAULT;
3004 goto out1;
3005 }
3006
3007 error = VOP_LINK(dvp, vp, name, cr, NULL, 0);
3008
3009 va.va_mask = AT_ALL;
3010 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
3011 ava.va_mask = AT_ALL;
3012 avap = VOP_GETATTR(dvp, &ava, 0, cr, NULL) ? NULL : &ava;
3013
3014 /*
3015 * Force modified data and metadata out to stable storage.
3016 */
3017 (void) VOP_FSYNC(vp, FNODSYNC, cr, NULL);
3018 (void) VOP_FSYNC(dvp, 0, cr, NULL);
3019
3020 if (error)
3021 goto out;
3022
3023 VN_RELE(dvp);
3024
3025 resp->status = NFS3_OK;
3026 vattr_to_post_op_attr(vap, &resp->resok.file_attributes);
3027 vattr_to_wcc_data(bvap, avap, &resp->resok.linkdir_wcc);
3028
3029 DTRACE_NFSV3_4(op__link__done, struct svc_req *, req,
3030 cred_t *, cr, vnode_t *, vp, LINK3res *, resp);
3031
3032 VN_RELE(vp);
3121 }
3122
3123 if (is_system_labeled()) {
3124 bslabel_t *clabel = req->rq_label;
3125
3126 ASSERT(clabel != NULL);
3127 DTRACE_PROBE2(tx__rfs3__log__info__opreaddir__clabel, char *,
3128 "got client label from request(1)", struct svc_req *, req);
3129
3130 if (!blequal(&l_admin_low->tsl_label, clabel)) {
3131 if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK,
3132 exi)) {
3133 resp->status = NFS3ERR_ACCES;
3134 goto out1;
3135 }
3136 }
3137 }
3138
3139 (void) VOP_RWLOCK(vp, V_WRITELOCK_FALSE, NULL);
3140
3141 va.va_mask = AT_ALL;
3142 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
3143
3144 if (vp->v_type != VDIR) {
3145 resp->status = NFS3ERR_NOTDIR;
3146 goto out1;
3147 }
3148
3149 error = VOP_ACCESS(vp, VREAD, 0, cr, NULL);
3150 if (error)
3151 goto out;
3152
3153 /*
3154 * Now don't allow arbitrary count to alloc;
3155 * allow the maximum not to exceed rfs3_tsize()
3156 */
3157 if (args->count > rfs3_tsize(req))
3158 args->count = rfs3_tsize(req);
3159
3160 /*
3161 * Make sure that there is room to read at least one entry
3162 * if any are available.
3163 */
3164 if (args->count < DIRENT64_RECLEN(MAXNAMELEN))
3165 count = DIRENT64_RECLEN(MAXNAMELEN);
3166 else
3167 count = args->count;
3168
3169 data = kmem_alloc(count, KM_SLEEP);
3170
3171 iov.iov_base = data;
3172 iov.iov_len = count;
3173 uio.uio_iov = &iov;
3174 uio.uio_iovcnt = 1;
3175 uio.uio_segflg = UIO_SYSSPACE;
3176 uio.uio_extflg = UIO_COPY_CACHED;
3177 uio.uio_loffset = (offset_t)args->cookie;
3178 uio.uio_resid = count;
3179
3180 error = VOP_READDIR(vp, &uio, cr, &iseof, NULL, 0);
3181
3182 va.va_mask = AT_ALL;
3183 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
3184
3185 if (error) {
3186 kmem_free(data, count);
3187 goto out;
3188 }
3189
3190 /*
3191 * If the count was not large enough to be able to guarantee
3192 * to be able to return at least one entry, then need to
3193 * check to see if NFS3ERR_TOOSMALL should be returned.
3194 */
3195 if (args->count < NFS3_READDIR_MIN_COUNT(MAXNAMELEN)) {
3196 /*
3197 * bufsize is used to keep track of the size of the response.
3198 * It is primed with:
3199 * 1 for the status +
3200 * 1 for the dir_attributes.attributes boolean +
3201 * 2 for the cookie verifier
3202 * all times BYTES_PER_XDR_UNIT to convert from XDR units
3203 * to bytes. If there are directory attributes to be
3393
3394 if (is_system_labeled()) {
3395 bslabel_t *clabel = req->rq_label;
3396
3397 ASSERT(clabel != NULL);
3398 DTRACE_PROBE2(tx__rfs3__log__info__opreaddirplus__clabel,
3399 char *, "got client label from request(1)",
3400 struct svc_req *, req);
3401
3402 if (!blequal(&l_admin_low->tsl_label, clabel)) {
3403 if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK,
3404 exi)) {
3405 resp->status = NFS3ERR_ACCES;
3406 goto out1;
3407 }
3408 }
3409 }
3410
3411 (void) VOP_RWLOCK(vp, V_WRITELOCK_FALSE, NULL);
3412
3413 va.va_mask = AT_ALL;
3414 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
3415
3416 if (vp->v_type != VDIR) {
3417 error = ENOTDIR;
3418 goto out;
3419 }
3420
3421 error = VOP_ACCESS(vp, VREAD, 0, cr, NULL);
3422 if (error)
3423 goto out;
3424
3425 /*
3426 * Don't allow arbitrary counts for allocation
3427 */
3428 if (args->maxcount > rfs3_tsize(req))
3429 args->maxcount = rfs3_tsize(req);
3430
3431 /*
3432 * Make sure that there is room to read at least one entry
3433 * if any are available
3434 */
3553 iseof = FALSE;
3554 goto good;
3555 }
3556 bufsize += entrysize;
3557 nents++;
3558 }
3559
3560 /*
3561 * If there is enough room to fit at least 1 more entry including
3562 * post op attributes and filehandle in the buffer AND that we haven't
3563 * exceeded dircount then go back and get some more.
3564 */
3565 if (!iseof &&
3566 (args->maxcount - bufsize) >= NFS3_READDIRPLUS_ENTRY(MAXNAMELEN)) {
3567 space_left -= (prev_len - uio.uio_resid);
3568 if (space_left >= DIRENT64_RECLEN(MAXNAMELEN))
3569 goto getmoredents;
3570
3571 /* else, fall through */
3572 }
3573 good:
3574 va.va_mask = AT_ALL;
3575 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
3576
3577 VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, NULL);
3578
3579 infop = kmem_alloc(nents * sizeof (struct entryplus3_info), KM_SLEEP);
3580 resp->resok.infop = infop;
3581
3582 dp = (struct dirent64 *)data;
3583 for (i = 0; i < nents; i++) {
3584
3585 if (dp->d_ino == 0) {
3586 infop[i].attr.attributes = FALSE;
3587 infop[i].fh.handle_follows = FALSE;
3588 dp = nextdp(dp);
3589 continue;
3590 }
3591
3592 infop[i].namelen = namlen[i];
3593
3594 error = VOP_LOOKUP(vp, dp->d_name, &nvp, NULL, 0, NULL, cr,
3595 NULL, NULL, NULL);
3596 if (error) {
3597 infop[i].attr.attributes = FALSE;
3598 infop[i].fh.handle_follows = FALSE;
3599 dp = nextdp(dp);
3600 continue;
3601 }
3602
3603 nva.va_mask = AT_ALL;
3604 nvap = rfs4_delegated_getattr(nvp, &nva, 0, cr) ? NULL : &nva;
3605
3606 /* Lie about the object type for a referral */
3607 if (vn_is_nfs_reparse(nvp, cr))
3608 nvap->va_type = VLNK;
3609
3610 vattr_to_post_op_attr(nvap, &infop[i].attr);
3611
3612 error = makefh3(&infop[i].fh.handle, nvp, exi);
3613 if (!error)
3614 infop[i].fh.handle_follows = TRUE;
3615 else
3616 infop[i].fh.handle_follows = FALSE;
3617
3618 VN_RELE(nvp);
3619 dp = nextdp(dp);
3620 }
3621
3622 ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
3623 ret = nfscmd_convdirplus(ca, exi, data, nents, args->dircount, &ndata);
3624 if (ndata == NULL)
3625 ndata = data;
3626
3627 if (ret > 0) {
3628 /*
3629 * We had to drop one or more entries in order to fit
3630 * during the character conversion. We need to patch
3631 * up the size and eof info.
3632 */
3633 if (iseof)
3634 iseof = FALSE;
3635
3636 ret = nfscmd_dropped_entrysize((struct dirent64 *)data,
3735 }
3736
3737 if (is_system_labeled()) {
3738 bslabel_t *clabel = req->rq_label;
3739
3740 ASSERT(clabel != NULL);
3741 DTRACE_PROBE2(tx__rfs3__log__info__opfsstat__clabel, char *,
3742 "got client label from request(1)", struct svc_req *, req);
3743
3744 if (!blequal(&l_admin_low->tsl_label, clabel)) {
3745 if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK,
3746 exi)) {
3747 resp->status = NFS3ERR_ACCES;
3748 goto out1;
3749 }
3750 }
3751 }
3752
3753 error = VFS_STATVFS(vp->v_vfsp, &sb);
3754
3755 va.va_mask = AT_ALL;
3756 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
3757
3758 if (error)
3759 goto out;
3760
3761 resp->status = NFS3_OK;
3762 vattr_to_post_op_attr(vap, &resp->resok.obj_attributes);
3763 if (sb.f_blocks != (fsblkcnt64_t)-1)
3764 resp->resok.tbytes = (size3)sb.f_frsize * (size3)sb.f_blocks;
3765 else
3766 resp->resok.tbytes = (size3)sb.f_blocks;
3767 if (sb.f_bfree != (fsblkcnt64_t)-1)
3768 resp->resok.fbytes = (size3)sb.f_frsize * (size3)sb.f_bfree;
3769 else
3770 resp->resok.fbytes = (size3)sb.f_bfree;
3771 if (sb.f_bavail != (fsblkcnt64_t)-1)
3772 resp->resok.abytes = (size3)sb.f_frsize * (size3)sb.f_bavail;
3773 else
3774 resp->resok.abytes = (size3)sb.f_bavail;
3775 resp->resok.tfiles = (size3)sb.f_files;
3776 resp->resok.ffiles = (size3)sb.f_ffree;
3832 }
3833
3834 if (is_system_labeled()) {
3835 bslabel_t *clabel = req->rq_label;
3836
3837 ASSERT(clabel != NULL);
3838 DTRACE_PROBE2(tx__rfs3__log__info__opfsinfo__clabel, char *,
3839 "got client label from request(1)", struct svc_req *, req);
3840
3841 if (!blequal(&l_admin_low->tsl_label, clabel)) {
3842 if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK,
3843 exi)) {
3844 resp->status = NFS3ERR_STALE;
3845 vattr_to_post_op_attr(NULL,
3846 &resp->resfail.obj_attributes);
3847 goto out;
3848 }
3849 }
3850 }
3851
3852 va.va_mask = AT_ALL;
3853 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
3854
3855 resp->status = NFS3_OK;
3856 vattr_to_post_op_attr(vap, &resp->resok.obj_attributes);
3857 xfer_size = rfs3_tsize(req);
3858 resp->resok.rtmax = xfer_size;
3859 resp->resok.rtpref = xfer_size;
3860 resp->resok.rtmult = DEV_BSIZE;
3861 resp->resok.wtmax = xfer_size;
3862 resp->resok.wtpref = xfer_size;
3863 resp->resok.wtmult = DEV_BSIZE;
3864 resp->resok.dtpref = MAXBSIZE;
3865
3866 /*
3867 * Large file spec: want maxfilesize based on limit of
3868 * underlying filesystem. We can guess 2^31-1 if need be.
3869 */
3870 error = VOP_PATHCONF(vp, _PC_FILESIZEBITS, &l, cr, NULL);
3871 if (error) {
3872 resp->status = puterrno3(error);
3873 goto out;
3936 error = ESTALE;
3937 goto out;
3938 }
3939
3940 if (is_system_labeled()) {
3941 bslabel_t *clabel = req->rq_label;
3942
3943 ASSERT(clabel != NULL);
3944 DTRACE_PROBE2(tx__rfs3__log__info__oppathconf__clabel, char *,
3945 "got client label from request(1)", struct svc_req *, req);
3946
3947 if (!blequal(&l_admin_low->tsl_label, clabel)) {
3948 if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK,
3949 exi)) {
3950 resp->status = NFS3ERR_ACCES;
3951 goto out1;
3952 }
3953 }
3954 }
3955
3956 va.va_mask = AT_ALL;
3957 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
3958
3959 error = VOP_PATHCONF(vp, _PC_LINK_MAX, &val, cr, NULL);
3960 if (error)
3961 goto out;
3962 resp->resok.info.link_max = (uint32)val;
3963
3964 error = VOP_PATHCONF(vp, _PC_NAME_MAX, &val, cr, NULL);
3965 if (error)
3966 goto out;
3967 resp->resok.info.name_max = (uint32)val;
3968
3969 error = VOP_PATHCONF(vp, _PC_NO_TRUNC, &val, cr, NULL);
3970 if (error)
3971 goto out;
3972 if (val == 1)
3973 resp->resok.info.no_trunc = TRUE;
3974 else
3975 resp->resok.info.no_trunc = FALSE;
3976
3977 error = VOP_PATHCONF(vp, _PC_CHOWN_RESTRICTED, &val, cr, NULL);
4029 vp = nfs3_fhtovp(&args->file, exi);
4030
4031 DTRACE_NFSV3_4(op__commit__start, struct svc_req *, req,
4032 cred_t *, cr, vnode_t *, vp, COMMIT3args *, args);
4033
4034 if (vp == NULL) {
4035 error = ESTALE;
4036 goto out;
4037 }
4038
4039 bva.va_mask = AT_ALL;
4040 error = VOP_GETATTR(vp, &bva, 0, cr, NULL);
4041
4042 /*
4043 * If we can't get the attributes, then we can't do the
4044 * right access checking. So, we'll fail the request.
4045 */
4046 if (error)
4047 goto out;
4048
4049 bvap = &bva;
4050
4051 if (rdonly(exi, req)) {
4052 resp->status = NFS3ERR_ROFS;
4053 goto out1;
4054 }
4055
4056 if (vp->v_type != VREG) {
4057 resp->status = NFS3ERR_INVAL;
4058 goto out1;
4059 }
4060
4061 if (is_system_labeled()) {
4062 bslabel_t *clabel = req->rq_label;
4063
4064 ASSERT(clabel != NULL);
4065 DTRACE_PROBE2(tx__rfs3__log__info__opcommit__clabel, char *,
4066 "got client label from request(1)", struct svc_req *, req);
4067
4068 if (!blequal(&l_admin_low->tsl_label, clabel)) {
4069 if (!do_rfs_label_check(clabel, vp, EQUALITY_CHECK,
4070 exi)) {
4071 resp->status = NFS3ERR_ACCES;
4072 goto out1;
4073 }
4074 }
4075 }
4076
4077 if (crgetuid(cr) != bva.va_uid &&
4078 (error = VOP_ACCESS(vp, VWRITE, 0, cr, NULL)))
4079 goto out;
4080
4081 error = VOP_FSYNC(vp, FSYNC, cr, NULL);
4082
4083 ava.va_mask = AT_ALL;
4084 avap = VOP_GETATTR(vp, &ava, 0, cr, NULL) ? NULL : &ava;
4085
4086 if (error)
4087 goto out;
4088
4089 resp->status = NFS3_OK;
4090 vattr_to_wcc_data(bvap, avap, &resp->resok.file_wcc);
4091 resp->resok.verf = write3verf;
4092
4093 DTRACE_NFSV3_4(op__commit__done, struct svc_req *, req,
4094 cred_t *, cr, vnode_t *, vp, COMMIT3res *, resp);
4095
4096 VN_RELE(vp);
4097
4098 return;
4099
4100 out:
4101 if (curthread->t_flag & T_WOULDBLOCK) {
4102 curthread->t_flag &= ~T_WOULDBLOCK;
4103 resp->status = NFS3ERR_JUKEBOX;
4104 } else
|