3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
24 * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved.
25 */
26
27 /*
28 * Copyright 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T.
29 * All rights reserved.
30 */
31
32
33 #include <sys/types.h>
34 #include <sys/param.h>
35 #include <sys/time.h>
36 #include <sys/vfs.h>
37 #include <sys/vnode.h>
38 #include <sys/socket.h>
39 #include <sys/errno.h>
40 #include <sys/uio.h>
41 #include <sys/proc.h>
42 #include <sys/user.h>
43 #include <sys/file.h>
44 #include <sys/tiuser.h>
45 #include <sys/kmem.h>
46 #include <sys/pathname.h>
47 #include <sys/debug.h>
48 #include <sys/vtrace.h>
49 #include <sys/cmn_err.h>
50 #include <sys/acl.h>
51 #include <sys/utsname.h>
52 #include <sys/sdt.h>
53 #include <netinet/in.h>
54 #include <sys/avl.h>
55
56 #include <rpc/types.h>
57 #include <rpc/auth.h>
58 #include <rpc/svc.h>
59
60 #include <nfs/nfs.h>
61 #include <nfs/export.h>
62 #include <nfs/nfssys.h>
63 #include <nfs/nfs_clnt.h>
64 #include <nfs/nfs_acl.h>
65 #include <nfs/nfs_log.h>
66 #include <nfs/lm.h>
67 #include <sys/sunddi.h>
68 #include <sys/pkp_hash.h>
69
70 treenode_t *ns_root;
71
72 struct exportinfo *exptable_path_hash[PKP_HASH_SIZE];
73 struct exportinfo *exptable[EXPTABLESIZE];
74
75 static int unexport(exportinfo_t *);
76 static void exportfree(exportinfo_t *);
77 static int loadindex(exportdata_t *);
78
79 extern void nfsauth_cache_free(exportinfo_t *);
80 extern int sec_svc_loadrootnames(int, int, caddr_t **, model_t);
81 extern void sec_svc_freerootnames(int, int, caddr_t *);
82
83 static int build_seclist_nodups(exportdata_t *, secinfo_t *, int);
84 static void srv_secinfo_add(secinfo_t **, int *, secinfo_t *, int, int);
85 static void srv_secinfo_remove(secinfo_t **, int *, secinfo_t *, int);
86 static void srv_secinfo_treeclimb(exportinfo_t *, secinfo_t *, int, bool_t);
87
88 #ifdef VOLATILE_FH_TEST
89 static struct ex_vol_rename *find_volrnm_fh(exportinfo_t *, nfs_fh4 *);
90 static uint32_t find_volrnm_fh_id(exportinfo_t *, nfs_fh4 *);
91 static void free_volrnm_list(exportinfo_t *);
92 #endif /* VOLATILE_FH_TEST */
93
94 /*
95 * exported_lock Read/Write lock that protects the exportinfo list.
96 * This lock must be held when searching or modifiying
97 * the exportinfo list.
98 */
99 krwlock_t exported_lock;
100
101 /*
102 * "public" and default (root) location for public filehandle
103 */
104 struct exportinfo *exi_public, *exi_root;
105
106 fid_t exi_rootfid; /* for checking the default public file handle */
107
108 fhandle_t nullfh2; /* for comparing V2 filehandles */
109
110 /*
111 * macro for static dtrace probes to trace server namespace ref count mods.
112 */
113 #define SECREF_TRACE(seclist, tag, flav, aftcnt) \
114 DTRACE_PROBE4(nfss__i__nmspc__secref, struct secinfo *, (seclist), \
115 char *, (tag), int, (int)(flav), int, (int)(aftcnt))
116
117
118 #define exptablehash(fsid, fid) (nfs_fhhash((fsid), (fid)) & (EXPTABLESIZE - 1))
119
120 static uint8_t
121 xor_hash(uint8_t *data, int len)
122 {
123 uint8_t h = 0;
124
125 while (len--)
126 h ^= *data++;
127
128 return (h);
129 }
130
131 /*
132 * File handle hash function, XOR over all bytes in fsid and fid.
133 */
134 static unsigned
135 nfs_fhhash(fsid_t *fsid, fid_t *fid)
136 {
137 int len;
138 uint8_t h;
139
686 exportinfo_t *exi_ret = NULL;
687
688 for (;;) {
689 tnode = tnode->tree_parent;
690 if (TREE_ROOT(tnode)) {
691 exi_ret = tnode->tree_exi;
692 break;
693 }
694 }
695
696 ASSERT(exi_ret); /* Every visible should have its home exportinfo */
697 return (exi_ret);
698 }
699
700 /*
701 * For NFS V4.
702 * Add or remove the newly exported or unexported security flavors of the
703 * given exportinfo from its ancestors upto the system root.
704 */
705 void
706 srv_secinfo_treeclimb(exportinfo_t *exip, secinfo_t *sec, int seccnt,
707 bool_t isadd)
708 {
709 treenode_t *tnode = exip->exi_tree;
710
711 ASSERT(RW_WRITE_HELD(&exported_lock));
712 ASSERT(tnode != NULL);
713
714 if (seccnt == 0)
715 return;
716
717 /*
718 * If flavors are being added and the new export root isn't
719 * also VROOT, its implicitly allowed flavors are inherited from
720 * its pseudonode.
721 * Note - for VROOT exports the implicitly allowed flavors were
722 * transferred from the PSEUDO export in exportfs()
723 */
724 if (isadd && !(exip->exi_vp->v_flag & VROOT) &&
725 tnode->tree_vis->vis_seccnt > 0) {
726 srv_secinfo_add(&exip->exi_export.ex_secinfo,
727 &exip->exi_export.ex_seccnt, tnode->tree_vis->vis_secinfo,
728 tnode->tree_vis->vis_seccnt, FALSE);
729 }
730
731 /*
765
766 /* hash_name is a text substitution for either fid_hash or path_hash */
767 #define exp_hash_unlink(exi, hash_name) \
768 if (*(exi)->hash_name.bckt == (exi)) \
769 *(exi)->hash_name.bckt = (exi)->hash_name.next; \
770 if ((exi)->hash_name.prev) \
771 (exi)->hash_name.prev->hash_name.next = (exi)->hash_name.next; \
772 if ((exi)->hash_name.next) \
773 (exi)->hash_name.next->hash_name.prev = (exi)->hash_name.prev; \
774 (exi)->hash_name.bckt = NULL;
775
776 #define exp_hash_link(exi, hash_name, bucket) \
777 (exi)->hash_name.bckt = (bucket); \
778 (exi)->hash_name.prev = NULL; \
779 (exi)->hash_name.next = *(bucket); \
780 if ((exi)->hash_name.next) \
781 (exi)->hash_name.next->hash_name.prev = (exi); \
782 *(bucket) = (exi);
783
784 void
785 export_link(exportinfo_t *exi)
786 {
787 exportinfo_t **bckt;
788
789 bckt = &exptable[exptablehash(&exi->exi_fsid, &exi->exi_fid)];
790 exp_hash_link(exi, fid_hash, bckt);
791
792 bckt = &exptable_path_hash[pkp_tab_hash(exi->exi_export.ex_path,
793 strlen(exi->exi_export.ex_path))];
794 exp_hash_link(exi, path_hash, bckt);
795 }
796
797 /*
798 * Initialization routine for export routines. Should only be called once.
799 */
800 int
801 nfs_exportinit(void)
802 {
803 int error;
804 int i;
805
806 rw_init(&exported_lock, NULL, RW_DEFAULT, NULL);
807
808 /*
809 * Allocate the place holder for the public file handle, which
810 * is all zeroes. It is initially set to the root filesystem.
811 */
812 exi_root = kmem_zalloc(sizeof (*exi_root), KM_SLEEP);
813 exi_public = exi_root;
814
815 exi_root->exi_export.ex_flags = EX_PUBLIC;
816 exi_root->exi_export.ex_pathlen = 1; /* length of "/" */
817 exi_root->exi_export.ex_path =
818 kmem_alloc(exi_root->exi_export.ex_pathlen + 1, KM_SLEEP);
819 exi_root->exi_export.ex_path[0] = '/';
820 exi_root->exi_export.ex_path[1] = '\0';
821
822 exi_root->exi_count = 1;
823 mutex_init(&exi_root->exi_lock, NULL, MUTEX_DEFAULT, NULL);
824
825 exi_root->exi_vp = rootdir;
826 exi_rootfid.fid_len = MAXFIDSZ;
827 error = vop_fid_pseudo(exi_root->exi_vp, &exi_rootfid);
828 if (error) {
829 mutex_destroy(&exi_root->exi_lock);
830 kmem_free(exi_root, sizeof (*exi_root));
831 return (error);
832 }
833
834 /*
835 * Initialize auth cache and auth cache lock
836 */
837 for (i = 0; i < AUTH_TABLESIZE; i++) {
838 exi_root->exi_cache[i] = kmem_alloc(sizeof (avl_tree_t),
839 KM_SLEEP);
840 avl_create(exi_root->exi_cache[i], nfsauth_cache_clnt_compar,
841 sizeof (struct auth_cache_clnt),
842 offsetof(struct auth_cache_clnt, authc_link));
843 }
844 rw_init(&exi_root->exi_cache_lock, NULL, RW_DEFAULT, NULL);
845
846 /* setup the fhandle template */
847 exi_root->exi_fh.fh_fsid = rootdir->v_vfsp->vfs_fsid;
848 exi_root->exi_fh.fh_xlen = exi_rootfid.fid_len;
849 bcopy(exi_rootfid.fid_data, exi_root->exi_fh.fh_xdata,
850 exi_rootfid.fid_len);
851 exi_root->exi_fh.fh_len = sizeof (exi_root->exi_fh.fh_data);
852
853 /*
854 * Publish the exportinfo in the hash table
855 */
856 export_link(exi_root);
857
858 nfslog_init();
859 ns_root = NULL;
860
861 return (0);
862 }
863
864 /*
865 * Finalization routine for export routines. Called to cleanup previously
866 * initialization work when the NFS server module could not be loaded correctly.
867 */
868 void
869 nfs_exportfini(void)
870 {
871 int i;
872
873 /*
874 * Deallocate the place holder for the public file handle.
875 */
876 srv_secinfo_list_free(exi_root->exi_export.ex_secinfo,
877 exi_root->exi_export.ex_seccnt);
878 mutex_destroy(&exi_root->exi_lock);
879 rw_destroy(&exi_root->exi_cache_lock);
880 for (i = 0; i < AUTH_TABLESIZE; i++) {
881 avl_destroy(exi_root->exi_cache[i]);
882 kmem_free(exi_root->exi_cache[i], sizeof (avl_tree_t));
883 }
884 kmem_free(exi_root, sizeof (*exi_root));
885
886 rw_destroy(&exported_lock);
887 }
888
889 /*
890 * Check if 2 gss mechanism identifiers are the same.
891 *
892 * return FALSE if not the same.
893 * return TRUE if the same.
894 */
895 static bool_t
896 nfs_mech_equal(rpc_gss_OID mech1, rpc_gss_OID mech2)
897 {
898 if ((mech1->length == 0) && (mech2->length == 0))
899 return (TRUE);
900
901 if (mech1->length != mech2->length)
902 return (FALSE);
903
904 return (bcmp(mech1->elements, mech2->elements, mech1->length) == 0);
905 }
906
907 /*
908 * This routine is used by rpc to map rpc security number
909 * to nfs specific security flavor number.
910 *
911 * The gss callback prototype is
912 * callback(struct svc_req *, gss_cred_id_t *, gss_ctx_id_t *,
913 * rpc_gss_lock_t *, void **),
914 * since nfs does not use the gss_cred_id_t/gss_ctx_id_t arguments
915 * we cast them to void.
916 */
917 /*ARGSUSED*/
918 bool_t
919 rfs_gsscallback(struct svc_req *req, gss_cred_id_t deleg, void *gss_context,
920 rpc_gss_lock_t *lock, void **cookie)
921 {
922 int i, j;
923 rpc_gss_rawcred_t *raw_cred;
924 struct exportinfo *exi;
925
926 /*
927 * We don't deal with delegated credentials.
928 */
929 if (deleg != GSS_C_NO_CREDENTIAL)
930 return (FALSE);
931
932 raw_cred = lock->raw_cred;
933 *cookie = NULL;
934
935 rw_enter(&exported_lock, RW_READER);
936 for (i = 0; i < EXPTABLESIZE; i++) {
937 exi = exptable[i];
938 while (exi) {
939 if (exi->exi_export.ex_seccnt > 0) {
940 struct secinfo *secp;
941 seconfig_t *se;
942 int seccnt;
943
944 secp = exi->exi_export.ex_secinfo;
945 seccnt = exi->exi_export.ex_seccnt;
946 for (j = 0; j < seccnt; j++) {
947 /*
948 * If there is a map of the triplet
949 * (mechanism, service, qop) between
950 * raw_cred and the exported flavor,
951 * get the psudo flavor number.
952 * Also qop should not be NULL, it
953 * should be "default" or something
954 * else.
955 */
956 se = &secp[j].s_secinfo;
957 if ((se->sc_rpcnum == RPCSEC_GSS) &&
958
959 (nfs_mech_equal(
960 se->sc_gss_mech_type,
961 raw_cred->mechanism)) &&
962
963 (se->sc_service ==
964 raw_cred->service) &&
965 (raw_cred->qop == se->sc_qop)) {
966
967 *cookie = (void *)(uintptr_t)
968 se->sc_nfsnum;
969 goto done;
970 }
971 }
972 }
973 exi = exi->fid_hash.next;
974 }
975 }
976 done:
977 rw_exit(&exported_lock);
978
979 /*
980 * If no nfs pseudo number mapping can be found in the export
981 * table, assign the nfsflavor to NFS_FLAVOR_NOMAP. In V4, we may
982 * recover the flavor mismatch from NFS layer (NFS4ERR_WRONGSEC).
983 *
984 * For example:
985 * server first shares with krb5i;
986 * client mounts with krb5i;
987 * server re-shares with krb5p;
988 * client tries with krb5i, but no mapping can be found;
989 * rpcsec_gss module calls this routine to do the mapping,
990 * if this routine fails, request is rejected from
991 * the rpc layer.
992 * What we need is to let the nfs layer rejects the request.
993 * For V4, we can reject with NFS4ERR_WRONGSEC and the client
994 * may recover from it by getting the new flavor via SECINFO.
995 *
996 * nfs pseudo number for RPCSEC_GSS mapping (see nfssec.conf)
997 * is owned by IANA (see RFC 2623).
1024 fid_t fid;
1025 fsid_t fsid;
1026 int error;
1027 size_t allocsize;
1028 struct secinfo *sp;
1029 struct secinfo *exs;
1030 rpc_gss_callback_t cb;
1031 char *pathbuf;
1032 char *log_buffer;
1033 char *tagbuf;
1034 int callback;
1035 int allocd_seccnt;
1036 STRUCT_HANDLE(exportfs_args, uap);
1037 STRUCT_DECL(exportdata, uexi);
1038 struct secinfo newsec[MAX_FLAVORS];
1039 int newcnt;
1040 struct secinfo oldsec[MAX_FLAVORS];
1041 int oldcnt;
1042 int i;
1043 struct pathname lookpn;
1044
1045 STRUCT_SET_HANDLE(uap, model, args);
1046
1047 /* Read in pathname from userspace */
1048 if (error = pn_get(STRUCT_FGETP(uap, dname), UIO_USERSPACE, &lookpn))
1049 return (error);
1050
1051 /* Walk the export list looking for that pathname */
1052 rw_enter(&exported_lock, RW_READER);
1053 DTRACE_PROBE(nfss__i__exported_lock1_start);
1054 for (ex1 = exptable_path_hash[pkp_tab_hash(lookpn.pn_path,
1055 strlen(lookpn.pn_path))]; ex1; ex1 = ex1->path_hash.next) {
1056 if (ex1 != exi_root && 0 ==
1057 strcmp(ex1->exi_export.ex_path, lookpn.pn_path)) {
1058 exi_hold(ex1);
1059 break;
1060 }
1061 }
1062 DTRACE_PROBE(nfss__i__exported_lock1_stop);
1063 rw_exit(&exported_lock);
1064
1065 /* Is this an unshare? */
1066 if (STRUCT_FGETP(uap, uex) == NULL) {
1067 pn_free(&lookpn);
1068 if (ex1 == NULL)
1069 return (EINVAL);
1070 error = unexport(ex1);
1071 exi_rele(ex1);
1072 return (error);
1073 }
1074
1075 /* It is a share or a re-share */
1076 error = lookupname(STRUCT_FGETP(uap, dname), UIO_USERSPACE,
1077 FOLLOW, &dvp, &vp);
1078 if (error == EINVAL) {
1079 /*
1080 * if fname resolves to / we get EINVAL error
1081 * since we wanted the parent vnode. Try again
1082 * with NULL dvp.
1083 */
1084 error = lookupname(STRUCT_FGETP(uap, dname), UIO_USERSPACE,
1085 FOLLOW, NULL, &vp);
1086 dvp = NULL;
1087 }
1088 if (!error && vp == NULL) {
1089 /* Last component of fname not found */
1090 if (dvp != NULL)
1091 VN_RELE(dvp);
1092 error = ENOENT;
1093 }
1094 if (error) {
1095 pn_free(&lookpn);
1096 if (ex1)
1097 exi_rele(ex1);
1098 return (error);
1099 }
1100
1101 /*
1102 * 'vp' may be an AUTOFS node, so we perform a
1103 * VOP_ACCESS() to trigger the mount of the
1104 * intended filesystem, so we can share the intended
1105 * filesystem instead of the AUTOFS filesystem.
1106 */
1107 (void) VOP_ACCESS(vp, 0, 0, cr, NULL);
1108
1109 /*
1110 * We're interested in the top most filesystem.
1111 * This is specially important when uap->dname is a trigger
1112 * AUTOFS node, since we're really interested in sharing the
1113 * filesystem AUTOFS mounted as result of the VOP_ACCESS()
1114 * call not the AUTOFS node itself.
1115 */
1116 if (vn_mountedvfs(vp) != NULL) {
1117 if (error = traverse(&vp)) {
1118 VN_RELE(vp);
1119 if (dvp != NULL)
1120 VN_RELE(dvp);
1121 pn_free(&lookpn);
1122 if (ex1)
1123 exi_rele(ex1);
1124 return (error);
1125 }
1126 }
1127
1128 /* Do not allow sharing another vnode for already shared path */
1129 if (ex1 && !PSEUDO(ex1) && !VN_CMP(ex1->exi_vp, vp)) {
1130 VN_RELE(vp);
1131 if (dvp != NULL)
1132 VN_RELE(dvp);
1133 pn_free(&lookpn);
1134 exi_rele(ex1);
1135 return (EEXIST);
1136 }
1137 if (ex1)
1138 exi_rele(ex1);
1139
1140 /*
1141 * Get the vfs id
1142 */
1143 bzero(&fid, sizeof (fid));
1144 fid.fid_len = MAXFIDSZ;
1145 error = VOP_FID(vp, &fid, NULL);
1146 fsid = vp->v_vfsp->vfs_fsid;
1147
1148 if (error) {
1149 VN_RELE(vp);
1150 if (dvp != NULL)
1151 VN_RELE(dvp);
1152 /*
1153 * If VOP_FID returns ENOSPC then the fid supplied
1154 * is too small. For now we simply return EREMOTE.
1155 */
1156 if (error == ENOSPC)
1157 error = EREMOTE;
1158 pn_free(&lookpn);
1159 return (error);
1160 }
1161
1162 /*
1163 * Do not allow re-sharing a shared vnode under a different path
1164 * PSEUDO export has ex_path fabricated, e.g. "/tmp (pseudo)", skip it.
1165 */
1166 rw_enter(&exported_lock, RW_READER);
1167 DTRACE_PROBE(nfss__i__exported_lock2_start);
1168 for (ex2 = exptable[exptablehash(&fsid, &fid)]; ex2;
1169 ex2 = ex2->fid_hash.next) {
1170 if (ex2 != exi_root && !PSEUDO(ex2) &&
1171 VN_CMP(ex2->exi_vp, vp) &&
1172 strcmp(ex2->exi_export.ex_path, lookpn.pn_path) != 0) {
1173 DTRACE_PROBE(nfss__i__exported_lock2_stop);
1174 rw_exit(&exported_lock);
1175 VN_RELE(vp);
1176 if (dvp != NULL)
1177 VN_RELE(dvp);
1178 pn_free(&lookpn);
1179 return (EEXIST);
1180 }
1181 }
1182 DTRACE_PROBE(nfss__i__exported_lock2_stop);
1183 rw_exit(&exported_lock);
1184 pn_free(&lookpn);
1185
1186 exi = kmem_zalloc(sizeof (*exi), KM_SLEEP);
1187 exi->exi_fsid = fsid;
1188 exi->exi_fid = fid;
1189 exi->exi_vp = vp;
1190 exi->exi_count = 1;
1191 exi->exi_volatile_dev = (vfssw[vp->v_vfsp->vfs_fstype].vsw_flag &
1192 VSW_VOLATILEDEV) ? 1 : 0;
1193 mutex_init(&exi->exi_lock, NULL, MUTEX_DEFAULT, NULL);
1194 exi->exi_dvp = dvp;
1195
1196 /*
1197 * Initialize auth cache and auth cache lock
1198 */
1199 for (i = 0; i < AUTH_TABLESIZE; i++) {
1200 exi->exi_cache[i] = kmem_alloc(sizeof (avl_tree_t), KM_SLEEP);
1201 avl_create(exi->exi_cache[i], nfsauth_cache_clnt_compar,
1202 sizeof (struct auth_cache_clnt),
1203 offsetof(struct auth_cache_clnt, authc_link));
1204 }
1205 rw_init(&exi->exi_cache_lock, NULL, RW_DEFAULT, NULL);
1206
1207 /*
1208 * Build up the template fhandle
1209 */
1210 exi->exi_fh.fh_fsid = fsid;
1444 * lock while dealing with the index option (as we do with
1445 * the public option).
1446 */
1447 if (kex->ex_flags & EX_INDEX) {
1448 if (!kex->ex_index) { /* sanity check */
1449 error = EINVAL;
1450 goto out5;
1451 }
1452 if (error = loadindex(kex))
1453 goto out5;
1454 }
1455
1456 if (kex->ex_flags & EX_LOG) {
1457 if (error = nfslog_setup(exi))
1458 goto out6;
1459 }
1460
1461 /*
1462 * Insert the new entry at the front of the export list
1463 */
1464 rw_enter(&exported_lock, RW_WRITER);
1465 DTRACE_PROBE(nfss__i__exported_lock3_start);
1466
1467 export_link(exi);
1468
1469 /*
1470 * Check the rest of the list for an old entry for the fs.
1471 * If one is found then unlink it, wait until this is the
1472 * only reference and then free it.
1473 */
1474 for (ex = exi->fid_hash.next; ex != NULL; ex = ex->fid_hash.next) {
1475 if (ex != exi_root && VN_CMP(ex->exi_vp, vp)) {
1476 export_unlink(ex);
1477 break;
1478 }
1479 }
1480
1481 /*
1482 * If the public filehandle is pointing at the
1483 * old entry, then point it back at the root.
1484 */
1485 if (ex != NULL && ex == exi_public)
1486 exi_public = exi_root;
1487
1488 /*
1489 * If the public flag is on, make the global exi_public
1490 * point to this entry and turn off the public bit so that
1491 * we can distinguish it from the place holder export.
1492 */
1493 if (kex->ex_flags & EX_PUBLIC) {
1494 exi_public = exi;
1495 kex->ex_flags &= ~EX_PUBLIC;
1496 }
1497
1498 #ifdef VOLATILE_FH_TEST
1499 /*
1500 * Set up the volatile_id value if volatile on share.
1501 * The list of volatile renamed filehandles is always destroyed,
1502 * if the fs was reshared.
1503 */
1504 if (kex->ex_flags & EX_VOLFH)
1505 exi->exi_volatile_id = gethrestime_sec();
1506
1507 mutex_init(&exi->exi_vol_rename_lock, NULL, MUTEX_DEFAULT, NULL);
1508 #endif /* VOLATILE_FH_TEST */
1509
1510 /*
1511 * If this is a new export, then climb up
1512 * the tree and check if any pseudo exports
1513 * need to be created to provide a path for
1514 * NFS v4 clients.
1515 */
1516 if (ex == NULL) {
1517 error = treeclimb_export(exi);
1518 if (error)
1519 goto out7;
1520 } else {
1521 /* If it's a re-export update namespace tree */
1522 exi->exi_tree = ex->exi_tree;
1523 exi->exi_tree->tree_exi = exi;
1524
1525 /* Update the change timestamp */
1526 tree_update_change(exi->exi_tree, NULL);
1527 }
1528
1529 /*
1530 * build a unique flavor list from the flavors specified
1531 * in the share cmd. unique means that each flavor only
1532 * appears once in the secinfo list -- no duplicates allowed.
1533 */
1534 newcnt = build_seclist_nodups(&exi->exi_export, newsec, FALSE);
1535
1536 srv_secinfo_treeclimb(exi, newsec, newcnt, TRUE);
1537
1538 /*
1539 * If re-sharing an old export entry, update the secinfo data
1540 * depending on if the old entry is a pseudo node or not.
1541 */
1542 if (ex != NULL) {
1543 oldcnt = build_seclist_nodups(&ex->exi_export, oldsec, FALSE);
1544 if (PSEUDO(ex)) {
1545 /*
1546 * The dir being shared is a pseudo export root (which
1547 * will be transformed into a real export root). The
1548 * flavor(s) of the new share were propagated to the
1549 * ancestors by srv_secinfo_treeclimb() above. Now
1550 * transfer the implicit flavor refs from the old
1551 * pseudo exprot root to the new (real) export root.
1552 */
1553 srv_secinfo_add(&exi->exi_export.ex_secinfo,
1554 &exi->exi_export.ex_seccnt, oldsec, oldcnt, TRUE);
1555 } else {
1556 /*
1557 * First transfer implicit flavor refs to new export.
1558 * Remove old flavor refs last.
1559 */
1560 srv_secinfo_exp2exp(&exi->exi_export, oldsec, oldcnt);
1561 srv_secinfo_treeclimb(ex, oldsec, oldcnt, FALSE);
1562 }
1563 }
1564
1565 /*
1566 * If it's a re-export and the old entry has a pseudonode list,
1567 * transfer it to the new export.
1568 */
1569 if (ex != NULL && (ex->exi_visible != NULL)) {
1570 exi->exi_visible = ex->exi_visible;
1571 ex->exi_visible = NULL;
1572 }
1573
1574 DTRACE_PROBE(nfss__i__exported_lock3_stop);
1575 rw_exit(&exported_lock);
1576
1577 if (exi_public == exi || kex->ex_flags & EX_LOG) {
1578 /*
1579 * Log share operation to this buffer only.
1580 */
1581 nfslog_share_record(exi, cr);
1582 }
1583
1584 if (ex != NULL)
1585 exi_rele(ex);
1586
1587 return (0);
1588
1589 out7:
1590 /* Unlink the new export in exptable. */
1591 export_unlink(exi);
1592 DTRACE_PROBE(nfss__i__exported_lock3_stop);
1593 rw_exit(&exported_lock);
1594 out6:
1595 if (kex->ex_flags & EX_INDEX)
1596 kmem_free(kex->ex_index, strlen(kex->ex_index) + 1);
1597 out5:
1598 /* free partially completed allocation */
1599 while (--allocd_seccnt >= 0) {
1600 exs = &kex->ex_secinfo[allocd_seccnt];
1601 srv_secinfo_entry_free(exs);
1602 }
1603
1604 if (kex->ex_secinfo) {
1605 kmem_free(kex->ex_secinfo,
1606 kex->ex_seccnt * sizeof (struct secinfo));
1607 }
1608
1609 out4:
1610 if ((kex->ex_flags & EX_LOG) && kex->ex_tag != NULL)
1611 kmem_free(kex->ex_tag, kex->ex_taglen + 1);
1612 out3:
1613 if ((kex->ex_flags & EX_LOG) && kex->ex_log_buffer != NULL)
1617 out1:
1618 VN_RELE(vp);
1619 if (dvp != NULL)
1620 VN_RELE(dvp);
1621 mutex_destroy(&exi->exi_lock);
1622 rw_destroy(&exi->exi_cache_lock);
1623 for (i = 0; i < AUTH_TABLESIZE; i++) {
1624 avl_destroy(exi->exi_cache[i]);
1625 kmem_free(exi->exi_cache[i], sizeof (avl_tree_t));
1626 }
1627
1628 kmem_free(exi, sizeof (*exi));
1629
1630 return (error);
1631 }
1632
1633 /*
1634 * Remove the exportinfo from the export list
1635 */
1636 void
1637 export_unlink(struct exportinfo *exi)
1638 {
1639 ASSERT(RW_WRITE_HELD(&exported_lock));
1640
1641 exp_hash_unlink(exi, fid_hash);
1642 exp_hash_unlink(exi, path_hash);
1643 }
1644
1645 /*
1646 * Unexport an exported filesystem
1647 */
1648 static int
1649 unexport(struct exportinfo *exi)
1650 {
1651 struct secinfo cursec[MAX_FLAVORS];
1652 int curcnt;
1653
1654 rw_enter(&exported_lock, RW_WRITER);
1655
1656 /* Check if exi is still linked in the export table */
1657 if (!EXP_LINKED(exi) || PSEUDO(exi)) {
1658 rw_exit(&exported_lock);
1659 return (EINVAL);
1660 }
1661
1662 export_unlink(exi);
1663
1664 /*
1665 * Remove security flavors before treeclimb_unexport() is called
1666 * because srv_secinfo_treeclimb needs the namespace tree
1667 */
1668 curcnt = build_seclist_nodups(&exi->exi_export, cursec, TRUE);
1669
1670 srv_secinfo_treeclimb(exi, cursec, curcnt, FALSE);
1671
1672 /*
1673 * If there's a visible list, then need to leave
1674 * a pseudo export here to retain the visible list
1675 * for paths to exports below.
1676 */
1677 if (exi->exi_visible != NULL) {
1678 struct exportinfo *newexi;
1679
1680 newexi = pseudo_exportfs(exi->exi_vp, &exi->exi_fid,
1681 exi->exi_visible, &exi->exi_export);
1682 exi->exi_visible = NULL;
1683
1684 /* interconnect the existing treenode with the new exportinfo */
1685 newexi->exi_tree = exi->exi_tree;
1686 newexi->exi_tree->tree_exi = newexi;
1687
1688 /* Update the change timestamp */
1689 tree_update_change(exi->exi_tree, NULL);
1690 } else {
1691 treeclimb_unexport(exi);
1692 }
1693
1694 rw_exit(&exported_lock);
1695
1696 /*
1697 * Need to call into the NFSv4 server and release all data
1698 * held on this particular export. This is important since
1699 * the v4 server may be holding file locks or vnodes under
1700 * this export.
1701 */
1702 rfs4_clean_state_exi(exi);
1703
1704 /*
1705 * Notify the lock manager that the filesystem is being
1706 * unexported.
1707 */
1708 lm_unexport(exi);
1709
1710 /*
1711 * If this was a public export, restore
1712 * the public filehandle to the root.
1713 */
1714 if (exi == exi_public) {
1715 exi_public = exi_root;
1716
1717 nfslog_share_record(exi_public, CRED());
1718 }
1719
1720 if (exi->exi_export.ex_flags & EX_LOG) {
1721 nfslog_unshare_record(exi, CRED());
1722 }
1723
1724 exi_rele(exi);
1725 return (0);
1726 }
1727
1728 /*
1729 * Get file handle system call.
1730 * Takes file name and returns a file handle for it.
1731 * Credentials must be verified before calling.
1732 */
1733 int
1734 nfs_getfh(struct nfs_getfh_args *args, model_t model, cred_t *cr)
1735 {
1736 nfs_fh3 fh;
1737 char buf[NFS3_MAXFHSIZE];
1738 char *logptr, logbuf[NFS3_MAXFHSIZE];
1739 int l = NFS3_MAXFHSIZE;
1740 vnode_t *vp;
1741 vnode_t *dvp;
1742 struct exportinfo *exi;
1743 int error;
1744 int vers;
1860 bcopy(&fh.fh3_fsid, &logbuf[i], sz);
1861 i += sz;
1862 sz = sizeof (ushort_t);
1863 bcopy(&fh.fh3_len, &logbuf[i], sz);
1864 i += sz;
1865 sz = NFS_FHMAXDATA;
1866 bcopy(fh.fh3_data, &logbuf[i], sz);
1867 i += sz;
1868 sz = sizeof (ushort_t);
1869 bcopy(&fh.fh3_xlen, &logbuf[i], sz);
1870 i += sz;
1871 sz = NFS_FHMAXDATA;
1872 bcopy(fh.fh3_xdata, &logbuf[i], sz);
1873 i += sz;
1874 }
1875 }
1876 if (!error && exi->exi_export.ex_flags & EX_LOG) {
1877 nfslog_getfh(exi, (fhandle_t *)logptr,
1878 STRUCT_FGETP(uap, fname), UIO_USERSPACE, cr);
1879 }
1880 exi_rele(exi);
1881 if (!error) {
1882 if (copyout(&l, STRUCT_FGETP(uap, lenp), sizeof (int)))
1883 error = EFAULT;
1884 if (copyout(buf, STRUCT_FGETP(uap, fhp), l))
1885 error = EFAULT;
1886 }
1887 }
1888 VN_RELE(vp);
1889 if (dvp != NULL) {
1890 VN_RELE(dvp);
1891 }
1892 return (error);
1893 }
1894
1895 /*
1896 * Strategy: if vp is in the export list, then
1897 * return the associated file handle. Otherwise, ".."
1898 * once up the vp and try again, until the root of the
1899 * filesystem is reached.
1900 */
2429
2430 if (error || vp == NULL) {
2431 *statp = NFS4ERR_STALE;
2432 return (NULL);
2433 }
2434 /* XXX - disgusting hack */
2435 if (vp->v_type == VNON && vp->v_flag & V_XATTRDIR)
2436 vp->v_type = VDIR;
2437 *statp = NFS4_OK;
2438 return (vp);
2439 }
2440
2441 /*
2442 * Find the export structure associated with the given filesystem.
2443 * If found, then increment the ref count (exi_count).
2444 */
2445 struct exportinfo *
2446 checkexport(fsid_t *fsid, fid_t *fid)
2447 {
2448 struct exportinfo *exi;
2449
2450 rw_enter(&exported_lock, RW_READER);
2451 for (exi = exptable[exptablehash(fsid, fid)];
2452 exi != NULL;
2453 exi = exi->fid_hash.next) {
2454 if (exportmatch(exi, fsid, fid)) {
2455 /*
2456 * If this is the place holder for the
2457 * public file handle, then return the
2458 * real export entry for the public file
2459 * handle.
2460 */
2461 if (exi->exi_export.ex_flags & EX_PUBLIC) {
2462 exi = exi_public;
2463 }
2464
2465 exi_hold(exi);
2466 rw_exit(&exported_lock);
2467 return (exi);
2468 }
2469 }
2470 rw_exit(&exported_lock);
2471 return (NULL);
2472 }
2473
2474
2475 /*
2476 * "old school" version of checkexport() for NFS4. NFS4
2477 * rfs4_compound holds exported_lock for duration of compound
2478 * processing. This version doesn't manipulate exi_count
2479 * since NFS4 breaks fundamental assumptions in the exi_count
2480 * design.
2481 */
2482 struct exportinfo *
2483 checkexport4(fsid_t *fsid, fid_t *fid, vnode_t *vp)
2484 {
2485 struct exportinfo *exi;
2486
2487 ASSERT(RW_LOCK_HELD(&exported_lock));
2488
2489 for (exi = exptable[exptablehash(fsid, fid)];
2490 exi != NULL;
2491 exi = exi->fid_hash.next) {
2492 if (exportmatch(exi, fsid, fid)) {
2493 /*
2494 * If this is the place holder for the
2495 * public file handle, then return the
2496 * real export entry for the public file
2497 * handle.
2498 */
2499 if (exi->exi_export.ex_flags & EX_PUBLIC) {
2500 exi = exi_public;
2501 }
2502
2503 /*
2504 * If vp is given, check if vp is the
2505 * same vnode as the exported node.
2506 *
2507 * Since VOP_FID of a lofs node returns the
2508 * fid of its real node (ufs), the exported
2509 * node for lofs and (pseudo) ufs may have
2510 * the same fsid and fid.
2511 */
2512 if (vp == NULL || vp == exi->exi_vp)
2513 return (exi);
2514 }
2515 }
2516
2517 return (NULL);
2518 }
2519
2520 /*
2521 * Free an entire export list node
2522 */
2523 void
2524 exportfree(struct exportinfo *exi)
2525 {
2526 struct exportdata *ex;
2527 struct charset_cache *cache;
2528 int i;
2529
2530 ex = &exi->exi_export;
2531
2532 ASSERT(exi->exi_vp != NULL && !(exi->exi_export.ex_flags & EX_PUBLIC));
2533 VN_RELE(exi->exi_vp);
2534 if (exi->exi_dvp != NULL)
2535 VN_RELE(exi->exi_dvp);
2536
2537 if (ex->ex_flags & EX_INDEX)
2538 kmem_free(ex->ex_index, strlen(ex->ex_index) + 1);
2539
2540 kmem_free(ex->ex_path, ex->ex_pathlen + 1);
2541 nfsauth_cache_free(exi);
2542
2543 /*
2566
2567 srv_secinfo_list_free(ex->ex_secinfo, ex->ex_seccnt);
2568
2569 #ifdef VOLATILE_FH_TEST
2570 free_volrnm_list(exi);
2571 mutex_destroy(&exi->exi_vol_rename_lock);
2572 #endif /* VOLATILE_FH_TEST */
2573
2574 mutex_destroy(&exi->exi_lock);
2575 rw_destroy(&exi->exi_cache_lock);
2576 /*
2577 * All nodes in the exi_cache AVL trees were removed and freed in the
2578 * nfsauth_cache_free() call above. We will just destroy and free the
2579 * empty AVL trees here.
2580 */
2581 for (i = 0; i < AUTH_TABLESIZE; i++) {
2582 avl_destroy(exi->exi_cache[i]);
2583 kmem_free(exi->exi_cache[i], sizeof (avl_tree_t));
2584 }
2585
2586 kmem_free(exi, sizeof (*exi));
2587 }
2588
2589 /*
2590 * load the index file from user space into kernel space.
2591 */
2592 static int
2593 loadindex(struct exportdata *kex)
2594 {
2595 int error;
2596 char index[MAXNAMELEN+1];
2597 size_t len;
2598
2599 /*
2600 * copyinstr copies the complete string including the NULL and
2601 * returns the len with the NULL byte included in the calculation
2602 * as long as the max length is not exceeded.
2603 */
2604 if (error = copyinstr(kex->ex_index, index, sizeof (index), &len))
2605 return (error);
2607 kex->ex_index = kmem_alloc(len, KM_SLEEP);
2608 bcopy(index, kex->ex_index, len);
2609
2610 return (0);
2611 }
2612
2613 void
2614 exi_hold(struct exportinfo *exi)
2615 {
2616 mutex_enter(&exi->exi_lock);
2617 exi->exi_count++;
2618 mutex_exit(&exi->exi_lock);
2619 }
2620
2621 /*
2622 * When a thread completes using exi, it should call exi_rele().
2623 * exi_rele() decrements exi_count. It releases exi if exi_count == 0, i.e.
2624 * if this is the last user of exi and exi is not on exportinfo list anymore
2625 */
2626 void
2627 exi_rele(struct exportinfo *exi)
2628 {
2629 mutex_enter(&exi->exi_lock);
2630 exi->exi_count--;
2631 if (exi->exi_count == 0) {
2632 mutex_exit(&exi->exi_lock);
2633 exportfree(exi);
2634 } else
2635 mutex_exit(&exi->exi_lock);
2636 }
2637
2638 #ifdef VOLATILE_FH_TEST
2639 /*
2640 * Test for volatile fh's - add file handle to list and set its volatile id
2641 * to time it was renamed. If EX_VOLFH is also on and the fs is reshared,
2642 * the vol_rename queue is purged.
2643 *
2644 * XXX This code is for unit testing purposes only... To correctly use it, it
2645 * needs to tie a rename list to the export struct and (more
2646 * important), protect access to the exi rename list using a write lock.
2647 */
2648
2649 /*
2650 * get the fh vol record if it's in the volatile on rename list. Don't check
2651 * volatile_id in the file handle - compare only the file handles.
2652 */
2653 static struct ex_vol_rename *
2654 find_volrnm_fh(struct exportinfo *exi, nfs_fh4 *fh4p)
2655 {
|
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25
26 /*
27 * Copyright 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T.
28 * All rights reserved.
29 */
30
31 /*
32 * Copyright 2018 Nexenta Systems, Inc.
33 */
34
35 #include <sys/types.h>
36 #include <sys/param.h>
37 #include <sys/time.h>
38 #include <sys/vfs.h>
39 #include <sys/vnode.h>
40 #include <sys/socket.h>
41 #include <sys/errno.h>
42 #include <sys/uio.h>
43 #include <sys/proc.h>
44 #include <sys/user.h>
45 #include <sys/file.h>
46 #include <sys/tiuser.h>
47 #include <sys/kmem.h>
48 #include <sys/pathname.h>
49 #include <sys/debug.h>
50 #include <sys/vtrace.h>
51 #include <sys/cmn_err.h>
52 #include <sys/acl.h>
53 #include <sys/utsname.h>
54 #include <sys/sdt.h>
55 #include <netinet/in.h>
56 #include <sys/avl.h>
57
58 #include <rpc/types.h>
59 #include <rpc/auth.h>
60 #include <rpc/svc.h>
61
62 #include <nfs/nfs.h>
63 #include <nfs/export.h>
64 #include <nfs/nfssys.h>
65 #include <nfs/nfs_clnt.h>
66 #include <nfs/nfs_acl.h>
67 #include <nfs/nfs_log.h>
68 #include <nfs/lm.h>
69 #include <sys/sunddi.h>
70
71 static zone_key_t nfs_export_key;
72
73 /*
74 * exi_id support
75 *
76 * exi_id_next The next exi_id available.
77 * exi_id_overflow The exi_id_next already overflowed, so we should
78 * thoroughly check for duplicates.
79 * exi_id_tree AVL tree indexed by exi_id.
80 * nfs_exi_id_lock Lock to protect the export ID list
81 *
82 * All exi_id_next, exi_id_overflow, and exi_id_tree are protected by
83 * nfs_exi_id_lock.
84 */
85 static int exi_id_next;
86 static bool_t exi_id_overflow;
87 avl_tree_t exi_id_tree;
88 kmutex_t nfs_exi_id_lock;
89
90 static int unexport(nfs_export_t *, exportinfo_t *);
91 static void exportfree(exportinfo_t *);
92 static int loadindex(exportdata_t *);
93
94 extern void nfsauth_cache_free(exportinfo_t *);
95 extern int sec_svc_loadrootnames(int, int, caddr_t **, model_t);
96 extern void sec_svc_freerootnames(int, int, caddr_t *);
97
98 static int build_seclist_nodups(exportdata_t *, secinfo_t *, int);
99 static void srv_secinfo_add(secinfo_t **, int *, secinfo_t *, int, int);
100 static void srv_secinfo_remove(secinfo_t **, int *, secinfo_t *, int);
101 static void srv_secinfo_treeclimb(nfs_export_t *, exportinfo_t *,
102 secinfo_t *, int, bool_t);
103
104 #ifdef VOLATILE_FH_TEST
105 static struct ex_vol_rename *find_volrnm_fh(exportinfo_t *, nfs_fh4 *);
106 static uint32_t find_volrnm_fh_id(exportinfo_t *, nfs_fh4 *);
107 static void free_volrnm_list(exportinfo_t *);
108 #endif /* VOLATILE_FH_TEST */
109
110 fhandle_t nullfh2; /* for comparing V2 filehandles */
111
112 /*
113 * macro for static dtrace probes to trace server namespace ref count mods.
114 */
115 #define SECREF_TRACE(seclist, tag, flav, aftcnt) \
116 DTRACE_PROBE4(nfss__i__nmspc__secref, struct secinfo *, (seclist), \
117 char *, (tag), int, (int)(flav), int, (int)(aftcnt))
118
119
120 #define exptablehash(fsid, fid) (nfs_fhhash((fsid), (fid)) & (EXPTABLESIZE - 1))
121
122 extern nfs_export_t *
123 nfs_get_export(void)
124 {
125 return (zone_getspecific(nfs_export_key, curzone));
126 }
127
128 static uint8_t
129 xor_hash(uint8_t *data, int len)
130 {
131 uint8_t h = 0;
132
133 while (len--)
134 h ^= *data++;
135
136 return (h);
137 }
138
139 /*
140 * File handle hash function, XOR over all bytes in fsid and fid.
141 */
142 static unsigned
143 nfs_fhhash(fsid_t *fsid, fid_t *fid)
144 {
145 int len;
146 uint8_t h;
147
694 exportinfo_t *exi_ret = NULL;
695
696 for (;;) {
697 tnode = tnode->tree_parent;
698 if (TREE_ROOT(tnode)) {
699 exi_ret = tnode->tree_exi;
700 break;
701 }
702 }
703
704 ASSERT(exi_ret); /* Every visible should have its home exportinfo */
705 return (exi_ret);
706 }
707
708 /*
709 * For NFS V4.
710 * Add or remove the newly exported or unexported security flavors of the
711 * given exportinfo from its ancestors upto the system root.
712 */
713 void
714 srv_secinfo_treeclimb(nfs_export_t *ne, exportinfo_t *exip, secinfo_t *sec,
715 int seccnt, bool_t isadd)
716 {
717 treenode_t *tnode = exip->exi_tree;
718
719 ASSERT(RW_WRITE_HELD(&ne->exported_lock));
720 ASSERT(tnode != NULL);
721
722 if (seccnt == 0)
723 return;
724
725 /*
726 * If flavors are being added and the new export root isn't
727 * also VROOT, its implicitly allowed flavors are inherited from
728 * its pseudonode.
729 * Note - for VROOT exports the implicitly allowed flavors were
730 * transferred from the PSEUDO export in exportfs()
731 */
732 if (isadd && !(exip->exi_vp->v_flag & VROOT) &&
733 tnode->tree_vis->vis_seccnt > 0) {
734 srv_secinfo_add(&exip->exi_export.ex_secinfo,
735 &exip->exi_export.ex_seccnt, tnode->tree_vis->vis_secinfo,
736 tnode->tree_vis->vis_seccnt, FALSE);
737 }
738
739 /*
773
774 /* hash_name is a text substitution for either fid_hash or path_hash */
775 #define exp_hash_unlink(exi, hash_name) \
776 if (*(exi)->hash_name.bckt == (exi)) \
777 *(exi)->hash_name.bckt = (exi)->hash_name.next; \
778 if ((exi)->hash_name.prev) \
779 (exi)->hash_name.prev->hash_name.next = (exi)->hash_name.next; \
780 if ((exi)->hash_name.next) \
781 (exi)->hash_name.next->hash_name.prev = (exi)->hash_name.prev; \
782 (exi)->hash_name.bckt = NULL;
783
784 #define exp_hash_link(exi, hash_name, bucket) \
785 (exi)->hash_name.bckt = (bucket); \
786 (exi)->hash_name.prev = NULL; \
787 (exi)->hash_name.next = *(bucket); \
788 if ((exi)->hash_name.next) \
789 (exi)->hash_name.next->hash_name.prev = (exi); \
790 *(bucket) = (exi);
791
792 void
793 export_link(nfs_export_t *ne, exportinfo_t *exi)
794 {
795 exportinfo_t **bckt;
796
797 ASSERT(RW_WRITE_HELD(&ne->exported_lock));
798
799 bckt = &ne->exptable[exptablehash(&exi->exi_fsid, &exi->exi_fid)];
800 exp_hash_link(exi, fid_hash, bckt);
801
802 bckt = &ne->exptable_path_hash[pkp_tab_hash(exi->exi_export.ex_path,
803 strlen(exi->exi_export.ex_path))];
804 exp_hash_link(exi, path_hash, bckt);
805 }
806
807 /*
808 * Helper functions for exi_id handling
809 */
810 static int
811 exi_id_compar(const void *v1, const void *v2)
812 {
813 const struct exportinfo *e1 = v1;
814 const struct exportinfo *e2 = v2;
815
816 if (e1->exi_id < e2->exi_id)
817 return (-1);
818 if (e1->exi_id > e2->exi_id)
819 return (1);
820
821 return (0);
822 }
823
824 int
825 exi_id_get_next()
826 {
827 struct exportinfo e;
828 int ret = exi_id_next;
829
830 ASSERT(MUTEX_HELD(&nfs_exi_id_lock));
831
832 do {
833 exi_id_next++;
834 if (exi_id_next == 0)
835 exi_id_overflow = TRUE;
836
837 if (!exi_id_overflow)
838 break;
839
840 if (exi_id_next == ret)
841 cmn_err(CE_PANIC, "exi_id exhausted");
842
843 e.exi_id = exi_id_next;
844 } while (avl_find(&exi_id_tree, &e, NULL) != NULL);
845
846 return (ret);
847 }
848
849 /*ARGSUSED*/
850 static void *
851 nfs_export_zone_init(zoneid_t zoneid)
852 {
853 int i;
854 nfs_export_t *ne;
855
856 ne = kmem_zalloc(sizeof (*ne), KM_SLEEP);
857
858 rw_init(&ne->exported_lock, NULL, RW_DEFAULT, NULL);
859
860 /*
861 * Allocate the place holder for the public file handle, which
862 * is all zeroes. It is initially set to the root filesystem.
863 */
864 ne->exi_root = kmem_zalloc(sizeof (*ne->exi_root), KM_SLEEP);
865 ne->exi_public = ne->exi_root;
866
867 ne->exi_root->exi_export.ex_flags = EX_PUBLIC;
868 ne->exi_root->exi_export.ex_pathlen = 1; /* length of "/" */
869 ne->exi_root->exi_export.ex_path =
870 kmem_alloc(ne->exi_root->exi_export.ex_pathlen + 1, KM_SLEEP);
871 ne->exi_root->exi_export.ex_path[0] = '/';
872 ne->exi_root->exi_export.ex_path[1] = '\0';
873
874 ne->exi_root->exi_count = 1;
875 mutex_init(&ne->exi_root->exi_lock, NULL, MUTEX_DEFAULT, NULL);
876
877 ne->exi_root->exi_vp = ZONE_ROOTVP();
878 ne->exi_rootfid.fid_len = MAXFIDSZ;
879 if (vop_fid_pseudo(ne->exi_root->exi_vp, &ne->exi_rootfid) != 0) {
880 mutex_destroy(&ne->exi_root->exi_lock);
881 kmem_free(ne->exi_root->exi_export.ex_path,
882 ne->exi_root->exi_export.ex_pathlen + 1);
883 kmem_free(ne->exi_root, sizeof (*ne->exi_root));
884 return (NULL);
885 }
886
887 /* Initialize auth cache and auth cache lock */
888 for (i = 0; i < AUTH_TABLESIZE; i++) {
889 ne->exi_root->exi_cache[i] = kmem_alloc(sizeof (avl_tree_t),
890 KM_SLEEP);
891 avl_create(ne->exi_root->exi_cache[i],
892 nfsauth_cache_clnt_compar, sizeof (struct auth_cache_clnt),
893 offsetof(struct auth_cache_clnt, authc_link));
894 }
895 rw_init(&ne->exi_root->exi_cache_lock, NULL, RW_DEFAULT, NULL);
896
897 /* Setup the fhandle template */
898 ne->exi_root->exi_fh.fh_fsid = rootdir->v_vfsp->vfs_fsid;
899 ne->exi_root->exi_fh.fh_xlen = ne->exi_rootfid.fid_len;
900 bcopy(ne->exi_rootfid.fid_data, ne->exi_root->exi_fh.fh_xdata,
901 ne->exi_rootfid.fid_len);
902 ne->exi_root->exi_fh.fh_len = sizeof (ne->exi_root->exi_fh.fh_data);
903
904 rw_enter(&ne->exported_lock, RW_WRITER);
905
906 /* Publish the exportinfo in the hash table */
907 export_link(ne, ne->exi_root);
908
909 /* Initialize exi_id and exi_kstats */
910 mutex_enter(&nfs_exi_id_lock);
911 ne->exi_root->exi_id = exi_id_get_next();
912 avl_add(&exi_id_tree, ne->exi_root);
913 mutex_exit(&nfs_exi_id_lock);
914 ne->exi_root->exi_kstats = exp_kstats_init(zoneid,
915 ne->exi_root->exi_id, ne->exi_root->exi_export.ex_path,
916 ne->exi_root->exi_export.ex_pathlen, FALSE);
917
918 rw_exit(&ne->exported_lock);
919 ne->ns_root = NULL;
920
921 return (ne);
922 }
923
924 /*ARGSUSED*/
925 static void
926 nfs_export_zone_fini(zoneid_t zoneid, void *data)
927 {
928 int i;
929 nfs_export_t *ne = data;
930 struct exportinfo *exi;
931
932 rw_enter(&ne->exported_lock, RW_WRITER);
933 mutex_enter(&nfs_exi_id_lock);
934
935 exp_kstats_delete(ne->exi_root->exi_kstats);
936 avl_remove(&exi_id_tree, ne->exi_root);
937 export_unlink(ne, ne->exi_root);
938
939 mutex_exit(&nfs_exi_id_lock);
940 rw_exit(&ne->exported_lock);
941
942 /* Deallocate the place holder for the public file handle */
943 srv_secinfo_list_free(ne->exi_root->exi_export.ex_secinfo,
944 ne->exi_root->exi_export.ex_seccnt);
945 mutex_destroy(&ne->exi_root->exi_lock);
946
947 rw_destroy(&ne->exi_root->exi_cache_lock);
948 for (i = 0; i < AUTH_TABLESIZE; i++) {
949 avl_destroy(ne->exi_root->exi_cache[i]);
950 kmem_free(ne->exi_root->exi_cache[i], sizeof (avl_tree_t));
951 }
952
953 exp_kstats_fini(ne->exi_root->exi_kstats);
954 kmem_free(ne->exi_root->exi_export.ex_path,
955 ne->exi_root->exi_export.ex_pathlen + 1);
956 kmem_free(ne->exi_root, sizeof (*ne->exi_root));
957
958 exi = avl_first(&exi_id_tree);
959 while (exi != NULL) {
960 struct exportinfo *nexi = AVL_NEXT(&exi_id_tree, exi);
961 if (zoneid == exi->exi_zoneid)
962 (void) unexport(ne, exi);
963 exi = nexi;
964 }
965
966 rw_destroy(&ne->exported_lock);
967 kmem_free(ne, sizeof (*ne));
968 }
969
970 /*
971 * Initialization routine for export routines.
972 * Should only be called once.
973 */
974 void
975 nfs_exportinit(void)
976 {
977 mutex_init(&nfs_exi_id_lock, NULL, MUTEX_DEFAULT, NULL);
978
979 /* exi_id handling initialization */
980 exi_id_next = 0;
981 exi_id_overflow = FALSE;
982 avl_create(&exi_id_tree, exi_id_compar, sizeof (struct exportinfo),
983 offsetof(struct exportinfo, exi_id_link));
984
985 zone_key_create(&nfs_export_key, nfs_export_zone_init,
986 NULL, nfs_export_zone_fini);
987
988 nfslog_init();
989 }
990
991 /*
992 * Finalization routine for export routines.
993 */
994 void
995 nfs_exportfini(void)
996 {
997 (void) zone_key_delete(nfs_export_key);
998 avl_destroy(&exi_id_tree);
999 mutex_destroy(&nfs_exi_id_lock);
1000 }
1001
1002 /*
1003 * Check if 2 gss mechanism identifiers are the same.
1004 *
1005 * return FALSE if not the same.
1006 * return TRUE if the same.
1007 */
1008 static bool_t
1009 nfs_mech_equal(rpc_gss_OID mech1, rpc_gss_OID mech2)
1010 {
1011 if ((mech1->length == 0) && (mech2->length == 0))
1012 return (TRUE);
1013
1014 if (mech1->length != mech2->length)
1015 return (FALSE);
1016
1017 return (bcmp(mech1->elements, mech2->elements, mech1->length) == 0);
1018 }
1019
1020 /*
1021 * This routine is used by rpc to map rpc security number
1022 * to nfs specific security flavor number.
1023 *
1024 * The gss callback prototype is
1025 * callback(struct svc_req *, gss_cred_id_t *, gss_ctx_id_t *,
1026 * rpc_gss_lock_t *, void **),
1027 * since nfs does not use the gss_cred_id_t/gss_ctx_id_t arguments
1028 * we cast them to void.
1029 */
1030 /*ARGSUSED*/
1031 bool_t
1032 rfs_gsscallback(struct svc_req *req, gss_cred_id_t deleg, void *gss_context,
1033 rpc_gss_lock_t *lock, void **cookie)
1034 {
1035 int i, j;
1036 rpc_gss_rawcred_t *raw_cred;
1037 struct exportinfo *exi;
1038 nfs_export_t *ne = nfs_get_export();
1039
1040 /*
1041 * We don't deal with delegated credentials.
1042 */
1043 if (deleg != GSS_C_NO_CREDENTIAL)
1044 return (FALSE);
1045
1046 raw_cred = lock->raw_cred;
1047 *cookie = NULL;
1048
1049 rw_enter(&ne->exported_lock, RW_READER);
1050
1051 for (i = 0; i < EXPTABLESIZE; i++) {
1052 exi = ne->exptable[i];
1053 while (exi) {
1054 if (exi->exi_export.ex_seccnt > 0) {
1055 struct secinfo *secp;
1056 seconfig_t *se;
1057 int seccnt;
1058
1059 secp = exi->exi_export.ex_secinfo;
1060 seccnt = exi->exi_export.ex_seccnt;
1061 for (j = 0; j < seccnt; j++) {
1062 /*
1063 * If there is a map of the triplet
1064 * (mechanism, service, qop) between
1065 * raw_cred and the exported flavor,
1066 * get the psudo flavor number.
1067 * Also qop should not be NULL, it
1068 * should be "default" or something
1069 * else.
1070 */
1071 se = &secp[j].s_secinfo;
1072 if ((se->sc_rpcnum == RPCSEC_GSS) &&
1073
1074 (nfs_mech_equal(
1075 se->sc_gss_mech_type,
1076 raw_cred->mechanism)) &&
1077
1078 (se->sc_service ==
1079 raw_cred->service) &&
1080 (raw_cred->qop == se->sc_qop)) {
1081
1082 *cookie = (void *)(uintptr_t)
1083 se->sc_nfsnum;
1084 goto done;
1085 }
1086 }
1087 }
1088 exi = exi->fid_hash.next;
1089 }
1090 }
1091 done:
1092 rw_exit(&ne->exported_lock);
1093
1094 /*
1095 * If no nfs pseudo number mapping can be found in the export
1096 * table, assign the nfsflavor to NFS_FLAVOR_NOMAP. In V4, we may
1097 * recover the flavor mismatch from NFS layer (NFS4ERR_WRONGSEC).
1098 *
1099 * For example:
1100 * server first shares with krb5i;
1101 * client mounts with krb5i;
1102 * server re-shares with krb5p;
1103 * client tries with krb5i, but no mapping can be found;
1104 * rpcsec_gss module calls this routine to do the mapping,
1105 * if this routine fails, request is rejected from
1106 * the rpc layer.
1107 * What we need is to let the nfs layer rejects the request.
1108 * For V4, we can reject with NFS4ERR_WRONGSEC and the client
1109 * may recover from it by getting the new flavor via SECINFO.
1110 *
1111 * nfs pseudo number for RPCSEC_GSS mapping (see nfssec.conf)
1112 * is owned by IANA (see RFC 2623).
1139 fid_t fid;
1140 fsid_t fsid;
1141 int error;
1142 size_t allocsize;
1143 struct secinfo *sp;
1144 struct secinfo *exs;
1145 rpc_gss_callback_t cb;
1146 char *pathbuf;
1147 char *log_buffer;
1148 char *tagbuf;
1149 int callback;
1150 int allocd_seccnt;
1151 STRUCT_HANDLE(exportfs_args, uap);
1152 STRUCT_DECL(exportdata, uexi);
1153 struct secinfo newsec[MAX_FLAVORS];
1154 int newcnt;
1155 struct secinfo oldsec[MAX_FLAVORS];
1156 int oldcnt;
1157 int i;
1158 struct pathname lookpn;
1159 nfs_export_t *ne = nfs_get_export();
1160
1161 STRUCT_SET_HANDLE(uap, model, args);
1162
1163 /* Read in pathname from userspace */
1164 if (error = pn_get(STRUCT_FGETP(uap, dname), UIO_USERSPACE, &lookpn))
1165 return (error);
1166
1167 /* Walk the export list looking for that pathname */
1168 rw_enter(&ne->exported_lock, RW_READER);
1169 DTRACE_PROBE(nfss__i__exported_lock1_start);
1170 for (ex1 = ne->exptable_path_hash[pkp_tab_hash(lookpn.pn_path,
1171 strlen(lookpn.pn_path))]; ex1; ex1 = ex1->path_hash.next) {
1172 if (ex1 != ne->exi_root && 0 ==
1173 strcmp(ex1->exi_export.ex_path, lookpn.pn_path)) {
1174 exi_hold(ex1);
1175 break;
1176 }
1177 }
1178 DTRACE_PROBE(nfss__i__exported_lock1_stop);
1179 rw_exit(&ne->exported_lock);
1180
1181 /* Is this an unshare? */
1182 if (STRUCT_FGETP(uap, uex) == NULL) {
1183 pn_free(&lookpn);
1184 if (ex1 == NULL)
1185 return (EINVAL);
1186 error = unexport(ne, ex1);
1187 exi_rele(&ex1);
1188 return (error);
1189 }
1190
1191 /* It is a share or a re-share */
1192 error = lookupname(STRUCT_FGETP(uap, dname), UIO_USERSPACE,
1193 FOLLOW, &dvp, &vp);
1194 if (error == EINVAL) {
1195 /*
1196 * if fname resolves to / we get EINVAL error
1197 * since we wanted the parent vnode. Try again
1198 * with NULL dvp.
1199 */
1200 error = lookupname(STRUCT_FGETP(uap, dname), UIO_USERSPACE,
1201 FOLLOW, NULL, &vp);
1202 dvp = NULL;
1203 }
1204 if (!error && vp == NULL) {
1205 /* Last component of fname not found */
1206 if (dvp != NULL)
1207 VN_RELE(dvp);
1208 error = ENOENT;
1209 }
1210 if (error) {
1211 pn_free(&lookpn);
1212 if (ex1)
1213 exi_rele(&ex1);
1214 return (error);
1215 }
1216
1217 /*
1218 * 'vp' may be an AUTOFS node, so we perform a
1219 * VOP_ACCESS() to trigger the mount of the
1220 * intended filesystem, so we can share the intended
1221 * filesystem instead of the AUTOFS filesystem.
1222 */
1223 (void) VOP_ACCESS(vp, 0, 0, cr, NULL);
1224
1225 /*
1226 * We're interested in the top most filesystem.
1227 * This is specially important when uap->dname is a trigger
1228 * AUTOFS node, since we're really interested in sharing the
1229 * filesystem AUTOFS mounted as result of the VOP_ACCESS()
1230 * call not the AUTOFS node itself.
1231 */
1232 if (vn_mountedvfs(vp) != NULL) {
1233 if (error = traverse(&vp)) {
1234 VN_RELE(vp);
1235 if (dvp != NULL)
1236 VN_RELE(dvp);
1237 pn_free(&lookpn);
1238 if (ex1)
1239 exi_rele(&ex1);
1240 return (error);
1241 }
1242 }
1243
1244 /* Do not allow sharing another vnode for already shared path */
1245 if (ex1 && !PSEUDO(ex1) && !VN_CMP(ex1->exi_vp, vp)) {
1246 VN_RELE(vp);
1247 if (dvp != NULL)
1248 VN_RELE(dvp);
1249 pn_free(&lookpn);
1250 exi_rele(&ex1);
1251 return (EEXIST);
1252 }
1253 if (ex1)
1254 exi_rele(&ex1);
1255
1256 /*
1257 * Get the vfs id
1258 */
1259 bzero(&fid, sizeof (fid));
1260 fid.fid_len = MAXFIDSZ;
1261 error = VOP_FID(vp, &fid, NULL);
1262 fsid = vp->v_vfsp->vfs_fsid;
1263
1264 if (error) {
1265 VN_RELE(vp);
1266 if (dvp != NULL)
1267 VN_RELE(dvp);
1268 /*
1269 * If VOP_FID returns ENOSPC then the fid supplied
1270 * is too small. For now we simply return EREMOTE.
1271 */
1272 if (error == ENOSPC)
1273 error = EREMOTE;
1274 pn_free(&lookpn);
1275 return (error);
1276 }
1277
1278 /*
1279 * Do not allow re-sharing a shared vnode under a different path
1280 * PSEUDO export has ex_path fabricated, e.g. "/tmp (pseudo)", skip it.
1281 */
1282 rw_enter(&ne->exported_lock, RW_READER);
1283 DTRACE_PROBE(nfss__i__exported_lock2_start);
1284 for (ex2 = ne->exptable[exptablehash(&fsid, &fid)]; ex2;
1285 ex2 = ex2->fid_hash.next) {
1286 if (ex2 != ne->exi_root && !PSEUDO(ex2) &&
1287 VN_CMP(ex2->exi_vp, vp) &&
1288 strcmp(ex2->exi_export.ex_path, lookpn.pn_path) != 0) {
1289 DTRACE_PROBE(nfss__i__exported_lock2_stop);
1290 rw_exit(&ne->exported_lock);
1291 VN_RELE(vp);
1292 if (dvp != NULL)
1293 VN_RELE(dvp);
1294 pn_free(&lookpn);
1295 return (EEXIST);
1296 }
1297 }
1298 DTRACE_PROBE(nfss__i__exported_lock2_stop);
1299 rw_exit(&ne->exported_lock);
1300 pn_free(&lookpn);
1301
1302 exi = kmem_zalloc(sizeof (*exi), KM_SLEEP);
1303 exi->exi_fsid = fsid;
1304 exi->exi_fid = fid;
1305 exi->exi_vp = vp;
1306 exi->exi_count = 1;
1307 exi->exi_zoneid = crgetzoneid(cr);
1308 exi->exi_volatile_dev = (vfssw[vp->v_vfsp->vfs_fstype].vsw_flag &
1309 VSW_VOLATILEDEV) ? 1 : 0;
1310 mutex_init(&exi->exi_lock, NULL, MUTEX_DEFAULT, NULL);
1311 exi->exi_dvp = dvp;
1312
1313 /*
1314 * Initialize auth cache and auth cache lock
1315 */
1316 for (i = 0; i < AUTH_TABLESIZE; i++) {
1317 exi->exi_cache[i] = kmem_alloc(sizeof (avl_tree_t), KM_SLEEP);
1318 avl_create(exi->exi_cache[i], nfsauth_cache_clnt_compar,
1319 sizeof (struct auth_cache_clnt),
1320 offsetof(struct auth_cache_clnt, authc_link));
1321 }
1322 rw_init(&exi->exi_cache_lock, NULL, RW_DEFAULT, NULL);
1323
1324 /*
1325 * Build up the template fhandle
1326 */
1327 exi->exi_fh.fh_fsid = fsid;
1561 * lock while dealing with the index option (as we do with
1562 * the public option).
1563 */
1564 if (kex->ex_flags & EX_INDEX) {
1565 if (!kex->ex_index) { /* sanity check */
1566 error = EINVAL;
1567 goto out5;
1568 }
1569 if (error = loadindex(kex))
1570 goto out5;
1571 }
1572
1573 if (kex->ex_flags & EX_LOG) {
1574 if (error = nfslog_setup(exi))
1575 goto out6;
1576 }
1577
1578 /*
1579 * Insert the new entry at the front of the export list
1580 */
1581 rw_enter(&ne->exported_lock, RW_WRITER);
1582 DTRACE_PROBE(nfss__i__exported_lock3_start);
1583
1584 export_link(ne, exi);
1585
1586 /*
1587 * Check the rest of the list for an old entry for the fs.
1588 * If one is found then unlink it, wait until this is the
1589 * only reference and then free it.
1590 */
1591 for (ex = exi->fid_hash.next; ex != NULL; ex = ex->fid_hash.next) {
1592 if (ex != ne->exi_root && VN_CMP(ex->exi_vp, vp)) {
1593 mutex_enter(&nfs_exi_id_lock);
1594 avl_remove(&exi_id_tree, ex);
1595 mutex_exit(&nfs_exi_id_lock);
1596 export_unlink(ne, ex);
1597 break;
1598 }
1599 }
1600
1601 /*
1602 * If the public filehandle is pointing at the
1603 * old entry, then point it back at the root.
1604 */
1605 if (ex != NULL && ex == ne->exi_public)
1606 ne->exi_public = ne->exi_root;
1607
1608 /*
1609 * If the public flag is on, make the global exi_public
1610 * point to this entry and turn off the public bit so that
1611 * we can distinguish it from the place holder export.
1612 */
1613 if (kex->ex_flags & EX_PUBLIC) {
1614 ne->exi_public = exi;
1615 kex->ex_flags &= ~EX_PUBLIC;
1616 }
1617
1618 #ifdef VOLATILE_FH_TEST
1619 /*
1620 * Set up the volatile_id value if volatile on share.
1621 * The list of volatile renamed filehandles is always destroyed,
1622 * if the fs was reshared.
1623 */
1624 if (kex->ex_flags & EX_VOLFH)
1625 exi->exi_volatile_id = gethrestime_sec();
1626
1627 mutex_init(&exi->exi_vol_rename_lock, NULL, MUTEX_DEFAULT, NULL);
1628 #endif /* VOLATILE_FH_TEST */
1629
1630 /*
1631 * If this is a new export, then climb up
1632 * the tree and check if any pseudo exports
1633 * need to be created to provide a path for
1634 * NFS v4 clients.
1635 */
1636 if (ex == NULL) {
1637 error = treeclimb_export(exi);
1638 if (error)
1639 goto out7;
1640 } else {
1641 /* If it's a re-export update namespace tree */
1642 exi->exi_tree = ex->exi_tree;
1643 exi->exi_tree->tree_exi = exi;
1644
1645 /* Update the change timestamp */
1646 tree_update_change(ne, exi->exi_tree, NULL);
1647 }
1648
1649 /*
1650 * build a unique flavor list from the flavors specified
1651 * in the share cmd. unique means that each flavor only
1652 * appears once in the secinfo list -- no duplicates allowed.
1653 */
1654 newcnt = build_seclist_nodups(&exi->exi_export, newsec, FALSE);
1655
1656 srv_secinfo_treeclimb(ne, exi, newsec, newcnt, TRUE);
1657
1658 /*
1659 * If re-sharing an old export entry, update the secinfo data
1660 * depending on if the old entry is a pseudo node or not.
1661 */
1662 if (ex != NULL) {
1663 oldcnt = build_seclist_nodups(&ex->exi_export, oldsec, FALSE);
1664 if (PSEUDO(ex)) {
1665 /*
1666 * The dir being shared is a pseudo export root (which
1667 * will be transformed into a real export root). The
1668 * flavor(s) of the new share were propagated to the
1669 * ancestors by srv_secinfo_treeclimb() above. Now
1670 * transfer the implicit flavor refs from the old
1671 * pseudo exprot root to the new (real) export root.
1672 */
1673 srv_secinfo_add(&exi->exi_export.ex_secinfo,
1674 &exi->exi_export.ex_seccnt, oldsec, oldcnt, TRUE);
1675 } else {
1676 /*
1677 * First transfer implicit flavor refs to new export.
1678 * Remove old flavor refs last.
1679 */
1680 srv_secinfo_exp2exp(&exi->exi_export, oldsec, oldcnt);
1681 srv_secinfo_treeclimb(ne, ex, oldsec, oldcnt, FALSE);
1682 }
1683 }
1684
1685 /*
1686 * If it's a re-export and the old entry has a pseudonode list,
1687 * transfer it to the new export.
1688 */
1689 if (ex != NULL && (ex->exi_visible != NULL)) {
1690 exi->exi_visible = ex->exi_visible;
1691 ex->exi_visible = NULL;
1692 }
1693
1694 /*
1695 * Initialize exi_id and exi_kstats
1696 */
1697 if (ex != NULL) {
1698 exi->exi_id = ex->exi_id;
1699 exi->exi_kstats = ex->exi_kstats;
1700 ex->exi_kstats = NULL;
1701 exp_kstats_reset(exi->exi_kstats, kex->ex_path,
1702 kex->ex_pathlen, FALSE);
1703 } else {
1704 mutex_enter(&nfs_exi_id_lock);
1705 exi->exi_id = exi_id_get_next();
1706 mutex_exit(&nfs_exi_id_lock);
1707 exi->exi_kstats = exp_kstats_init(crgetzoneid(cr), exi->exi_id,
1708 kex->ex_path, kex->ex_pathlen, FALSE);
1709 }
1710 mutex_enter(&nfs_exi_id_lock);
1711 avl_add(&exi_id_tree, exi);
1712 mutex_exit(&nfs_exi_id_lock);
1713
1714 DTRACE_PROBE(nfss__i__exported_lock3_stop);
1715 rw_exit(&ne->exported_lock);
1716
1717 if (ne->exi_public == exi || kex->ex_flags & EX_LOG) {
1718 /*
1719 * Log share operation to this buffer only.
1720 */
1721 nfslog_share_record(exi, cr);
1722 }
1723
1724 if (ex != NULL)
1725 exi_rele(&ex);
1726
1727 return (0);
1728
1729 out7:
1730 /* Unlink the new export in exptable. */
1731 export_unlink(ne, exi);
1732 DTRACE_PROBE(nfss__i__exported_lock3_stop);
1733 rw_exit(&ne->exported_lock);
1734 out6:
1735 if (kex->ex_flags & EX_INDEX)
1736 kmem_free(kex->ex_index, strlen(kex->ex_index) + 1);
1737 out5:
1738 /* free partially completed allocation */
1739 while (--allocd_seccnt >= 0) {
1740 exs = &kex->ex_secinfo[allocd_seccnt];
1741 srv_secinfo_entry_free(exs);
1742 }
1743
1744 if (kex->ex_secinfo) {
1745 kmem_free(kex->ex_secinfo,
1746 kex->ex_seccnt * sizeof (struct secinfo));
1747 }
1748
1749 out4:
1750 if ((kex->ex_flags & EX_LOG) && kex->ex_tag != NULL)
1751 kmem_free(kex->ex_tag, kex->ex_taglen + 1);
1752 out3:
1753 if ((kex->ex_flags & EX_LOG) && kex->ex_log_buffer != NULL)
1757 out1:
1758 VN_RELE(vp);
1759 if (dvp != NULL)
1760 VN_RELE(dvp);
1761 mutex_destroy(&exi->exi_lock);
1762 rw_destroy(&exi->exi_cache_lock);
1763 for (i = 0; i < AUTH_TABLESIZE; i++) {
1764 avl_destroy(exi->exi_cache[i]);
1765 kmem_free(exi->exi_cache[i], sizeof (avl_tree_t));
1766 }
1767
1768 kmem_free(exi, sizeof (*exi));
1769
1770 return (error);
1771 }
1772
1773 /*
1774 * Remove the exportinfo from the export list
1775 */
1776 void
1777 export_unlink(nfs_export_t *ne, struct exportinfo *exi)
1778 {
1779 ASSERT(RW_WRITE_HELD(&ne->exported_lock));
1780
1781 exp_hash_unlink(exi, fid_hash);
1782 exp_hash_unlink(exi, path_hash);
1783 }
1784
1785 /*
1786 * Unexport an exported filesystem
1787 */
1788 static int
1789 unexport(nfs_export_t *ne, struct exportinfo *exi)
1790 {
1791 struct secinfo cursec[MAX_FLAVORS];
1792 int curcnt;
1793
1794 rw_enter(&ne->exported_lock, RW_WRITER);
1795
1796 /* Check if exi is still linked in the export table */
1797 if (!EXP_LINKED(exi) || PSEUDO(exi)) {
1798 rw_exit(&ne->exported_lock);
1799 return (EINVAL);
1800 }
1801
1802 exp_kstats_delete(exi->exi_kstats);
1803 mutex_enter(&nfs_exi_id_lock);
1804 avl_remove(&exi_id_tree, exi);
1805 mutex_exit(&nfs_exi_id_lock);
1806 export_unlink(ne, exi);
1807
1808 /*
1809 * Remove security flavors before treeclimb_unexport() is called
1810 * because srv_secinfo_treeclimb needs the namespace tree
1811 */
1812 curcnt = build_seclist_nodups(&exi->exi_export, cursec, TRUE);
1813 srv_secinfo_treeclimb(ne, exi, cursec, curcnt, FALSE);
1814
1815 /*
1816 * If there's a visible list, then need to leave
1817 * a pseudo export here to retain the visible list
1818 * for paths to exports below.
1819 */
1820 if (exi->exi_visible != NULL) {
1821 struct exportinfo *newexi;
1822
1823 newexi = pseudo_exportfs(ne, exi->exi_vp, &exi->exi_fid,
1824 exi->exi_visible, &exi->exi_export);
1825 exi->exi_visible = NULL;
1826
1827 /* interconnect the existing treenode with the new exportinfo */
1828 newexi->exi_tree = exi->exi_tree;
1829 newexi->exi_tree->tree_exi = newexi;
1830
1831 /* Update the change timestamp */
1832 tree_update_change(ne, exi->exi_tree, NULL);
1833 } else {
1834 treeclimb_unexport(ne, exi);
1835 }
1836
1837 rw_exit(&ne->exported_lock);
1838
1839 /*
1840 * Need to call into the NFSv4 server and release all data
1841 * held on this particular export. This is important since
1842 * the v4 server may be holding file locks or vnodes under
1843 * this export.
1844 */
1845 rfs4_clean_state_exi(exi);
1846
1847 /*
1848 * Notify the lock manager that the filesystem is being
1849 * unexported.
1850 */
1851 lm_unexport(exi);
1852
1853 /*
1854 * If this was a public export, restore
1855 * the public filehandle to the root.
1856 */
1857 if (exi == ne->exi_public) {
1858 ne->exi_public = ne->exi_root;
1859
1860 nfslog_share_record(ne->exi_public, CRED());
1861 }
1862
1863 if (exi->exi_export.ex_flags & EX_LOG)
1864 nfslog_unshare_record(exi, CRED());
1865
1866 exi_rele(&exi);
1867 return (0);
1868 }
1869
1870 /*
1871 * Get file handle system call.
1872 * Takes file name and returns a file handle for it.
1873 * Credentials must be verified before calling.
1874 */
1875 int
1876 nfs_getfh(struct nfs_getfh_args *args, model_t model, cred_t *cr)
1877 {
1878 nfs_fh3 fh;
1879 char buf[NFS3_MAXFHSIZE];
1880 char *logptr, logbuf[NFS3_MAXFHSIZE];
1881 int l = NFS3_MAXFHSIZE;
1882 vnode_t *vp;
1883 vnode_t *dvp;
1884 struct exportinfo *exi;
1885 int error;
1886 int vers;
2002 bcopy(&fh.fh3_fsid, &logbuf[i], sz);
2003 i += sz;
2004 sz = sizeof (ushort_t);
2005 bcopy(&fh.fh3_len, &logbuf[i], sz);
2006 i += sz;
2007 sz = NFS_FHMAXDATA;
2008 bcopy(fh.fh3_data, &logbuf[i], sz);
2009 i += sz;
2010 sz = sizeof (ushort_t);
2011 bcopy(&fh.fh3_xlen, &logbuf[i], sz);
2012 i += sz;
2013 sz = NFS_FHMAXDATA;
2014 bcopy(fh.fh3_xdata, &logbuf[i], sz);
2015 i += sz;
2016 }
2017 }
2018 if (!error && exi->exi_export.ex_flags & EX_LOG) {
2019 nfslog_getfh(exi, (fhandle_t *)logptr,
2020 STRUCT_FGETP(uap, fname), UIO_USERSPACE, cr);
2021 }
2022 exi_rele(&exi);
2023 if (!error) {
2024 if (copyout(&l, STRUCT_FGETP(uap, lenp), sizeof (int)))
2025 error = EFAULT;
2026 if (copyout(buf, STRUCT_FGETP(uap, fhp), l))
2027 error = EFAULT;
2028 }
2029 }
2030 VN_RELE(vp);
2031 if (dvp != NULL) {
2032 VN_RELE(dvp);
2033 }
2034 return (error);
2035 }
2036
2037 /*
2038 * Strategy: if vp is in the export list, then
2039 * return the associated file handle. Otherwise, ".."
2040 * once up the vp and try again, until the root of the
2041 * filesystem is reached.
2042 */
2571
2572 if (error || vp == NULL) {
2573 *statp = NFS4ERR_STALE;
2574 return (NULL);
2575 }
2576 /* XXX - disgusting hack */
2577 if (vp->v_type == VNON && vp->v_flag & V_XATTRDIR)
2578 vp->v_type = VDIR;
2579 *statp = NFS4_OK;
2580 return (vp);
2581 }
2582
2583 /*
2584 * Find the export structure associated with the given filesystem.
2585 * If found, then increment the ref count (exi_count).
2586 */
2587 struct exportinfo *
2588 checkexport(fsid_t *fsid, fid_t *fid)
2589 {
2590 struct exportinfo *exi;
2591 nfs_export_t *ne = nfs_get_export();
2592
2593 rw_enter(&ne->exported_lock, RW_READER);
2594 for (exi = ne->exptable[exptablehash(fsid, fid)];
2595 exi != NULL;
2596 exi = exi->fid_hash.next) {
2597 if (exportmatch(exi, fsid, fid)) {
2598 /*
2599 * If this is the place holder for the
2600 * public file handle, then return the
2601 * real export entry for the public file
2602 * handle.
2603 */
2604 if (exi->exi_export.ex_flags & EX_PUBLIC) {
2605 exi = ne->exi_public;
2606 }
2607
2608 exi_hold(exi);
2609 rw_exit(&ne->exported_lock);
2610 return (exi);
2611 }
2612 }
2613 rw_exit(&ne->exported_lock);
2614 return (NULL);
2615 }
2616
2617
2618 /*
2619 * "old school" version of checkexport() for NFS4. NFS4
2620 * rfs4_compound holds exported_lock for duration of compound
2621 * processing. This version doesn't manipulate exi_count
2622 * since NFS4 breaks fundamental assumptions in the exi_count
2623 * design.
2624 */
2625 struct exportinfo *
2626 checkexport4(fsid_t *fsid, fid_t *fid, vnode_t *vp)
2627 {
2628 struct exportinfo *exi;
2629 nfs_export_t *ne = nfs_get_export();
2630
2631 ASSERT(RW_LOCK_HELD(&ne->exported_lock));
2632
2633 for (exi = ne->exptable[exptablehash(fsid, fid)];
2634 exi != NULL;
2635 exi = exi->fid_hash.next) {
2636 if (exportmatch(exi, fsid, fid)) {
2637 /*
2638 * If this is the place holder for the
2639 * public file handle, then return the
2640 * real export entry for the public file
2641 * handle.
2642 */
2643 if (exi->exi_export.ex_flags & EX_PUBLIC) {
2644 exi = ne->exi_public;
2645 }
2646
2647 /*
2648 * If vp is given, check if vp is the
2649 * same vnode as the exported node.
2650 *
2651 * Since VOP_FID of a lofs node returns the
2652 * fid of its real node (ufs), the exported
2653 * node for lofs and (pseudo) ufs may have
2654 * the same fsid and fid.
2655 */
2656 if (vp == NULL || vp == exi->exi_vp)
2657 return (exi);
2658 }
2659 }
2660
2661 return (NULL);
2662 }
2663
2664 /*
2665 * Free an entire export list node
2666 */
2667 static void
2668 exportfree(struct exportinfo *exi)
2669 {
2670 struct exportdata *ex;
2671 struct charset_cache *cache;
2672 int i;
2673
2674 ex = &exi->exi_export;
2675
2676 ASSERT(exi->exi_vp != NULL && !(exi->exi_export.ex_flags & EX_PUBLIC));
2677 VN_RELE(exi->exi_vp);
2678 if (exi->exi_dvp != NULL)
2679 VN_RELE(exi->exi_dvp);
2680
2681 if (ex->ex_flags & EX_INDEX)
2682 kmem_free(ex->ex_index, strlen(ex->ex_index) + 1);
2683
2684 kmem_free(ex->ex_path, ex->ex_pathlen + 1);
2685 nfsauth_cache_free(exi);
2686
2687 /*
2710
2711 srv_secinfo_list_free(ex->ex_secinfo, ex->ex_seccnt);
2712
2713 #ifdef VOLATILE_FH_TEST
2714 free_volrnm_list(exi);
2715 mutex_destroy(&exi->exi_vol_rename_lock);
2716 #endif /* VOLATILE_FH_TEST */
2717
2718 mutex_destroy(&exi->exi_lock);
2719 rw_destroy(&exi->exi_cache_lock);
2720 /*
2721 * All nodes in the exi_cache AVL trees were removed and freed in the
2722 * nfsauth_cache_free() call above. We will just destroy and free the
2723 * empty AVL trees here.
2724 */
2725 for (i = 0; i < AUTH_TABLESIZE; i++) {
2726 avl_destroy(exi->exi_cache[i]);
2727 kmem_free(exi->exi_cache[i], sizeof (avl_tree_t));
2728 }
2729
2730 exp_kstats_fini(exi->exi_kstats);
2731
2732 kmem_free(exi, sizeof (*exi));
2733 }
2734
2735 /*
2736 * load the index file from user space into kernel space.
2737 */
2738 static int
2739 loadindex(struct exportdata *kex)
2740 {
2741 int error;
2742 char index[MAXNAMELEN+1];
2743 size_t len;
2744
2745 /*
2746 * copyinstr copies the complete string including the NULL and
2747 * returns the len with the NULL byte included in the calculation
2748 * as long as the max length is not exceeded.
2749 */
2750 if (error = copyinstr(kex->ex_index, index, sizeof (index), &len))
2751 return (error);
2753 kex->ex_index = kmem_alloc(len, KM_SLEEP);
2754 bcopy(index, kex->ex_index, len);
2755
2756 return (0);
2757 }
2758
2759 void
2760 exi_hold(struct exportinfo *exi)
2761 {
2762 mutex_enter(&exi->exi_lock);
2763 exi->exi_count++;
2764 mutex_exit(&exi->exi_lock);
2765 }
2766
2767 /*
2768 * When a thread completes using exi, it should call exi_rele().
2769 * exi_rele() decrements exi_count. It releases exi if exi_count == 0, i.e.
2770 * if this is the last user of exi and exi is not on exportinfo list anymore
2771 */
2772 void
2773 exi_rele(struct exportinfo **exi)
2774 {
2775 struct exportinfo *exip = *exi;
2776 mutex_enter(&exip->exi_lock);
2777 exip->exi_count--;
2778 if (exip->exi_count == 0) {
2779 mutex_exit(&exip->exi_lock);
2780 /*
2781 * The exportinfo structure needs to be cleared here
2782 * since the control point, for when we free the structure,
2783 * is in this function and is triggered by the reference
2784 * count. The caller does not necessarily know when that
2785 * will be the case.
2786 */
2787 *exi = NULL;
2788 exportfree(exip);
2789 } else
2790 mutex_exit(&exip->exi_lock);
2791 }
2792
2793 #ifdef VOLATILE_FH_TEST
2794 /*
2795 * Test for volatile fh's - add file handle to list and set its volatile id
2796 * to time it was renamed. If EX_VOLFH is also on and the fs is reshared,
2797 * the vol_rename queue is purged.
2798 *
2799 * XXX This code is for unit testing purposes only... To correctly use it, it
2800 * needs to tie a rename list to the export struct and (more
2801 * important), protect access to the exi rename list using a write lock.
2802 */
2803
2804 /*
2805 * get the fh vol record if it's in the volatile on rename list. Don't check
2806 * volatile_id in the file handle - compare only the file handles.
2807 */
2808 static struct ex_vol_rename *
2809 find_volrnm_fh(struct exportinfo *exi, nfs_fh4 *fh4p)
2810 {
|