936 {
937 int i;
938
939 for (i = 0; i < count; i++) {
940 if (nfsnum == flavor_list[i])
941 return (TRUE);
942 }
943 return (FALSE);
944 }
945
946 /*
947 * Used by rfs4_op_secinfo to get the security information from the
948 * export structure associated with the component.
949 */
950 /* ARGSUSED */
951 static nfsstat4
952 do_rfs4_op_secinfo(struct compound_state *cs, char *nm, SECINFO4res *resp)
953 {
954 int error, different_export = 0;
955 vnode_t *dvp, *vp;
956 struct exportinfo *exi = NULL;
957 fid_t fid;
958 uint_t count, i;
959 secinfo4 *resok_val;
960 struct secinfo *secp;
961 seconfig_t *si;
962 bool_t did_traverse = FALSE;
963 int dotdot, walk;
964 nfs_export_t *ne = nfs_get_export();
965
966 dvp = cs->vp;
967 dotdot = (nm[0] == '.' && nm[1] == '.' && nm[2] == '\0');
968
969 /*
970 * If dotdotting, then need to check whether it's above the
971 * root of a filesystem, or above an export point.
972 */
973 if (dotdot) {
974
975 /*
976 * If dotdotting at the root of a filesystem, then
977 * need to traverse back to the mounted-on filesystem
978 * and do the dotdot lookup there.
979 */
980 if ((cs->vp->v_flag & VROOT) || VN_IS_CURZONEROOT(cs->vp)) {
981
982 /*
983 * If at the system root, then can
984 * go up no further.
985 */
986 if (VN_CMP(dvp, ZONE_ROOTVP()))
987 return (puterrno4(ENOENT));
988
989 /*
990 * Traverse back to the mounted-on filesystem
991 */
992 dvp = untraverse(cs->vp);
993
994 /*
995 * Set the different_export flag so we remember
996 * to pick up a new exportinfo entry for
997 * this new filesystem.
998 */
999 different_export = 1;
1000 } else {
1001
1002 /*
1003 * If dotdotting above an export point then set
1004 * the different_export to get new export info.
1005 */
1006 different_export = nfs_exported(cs->exi, cs->vp);
1007 }
1008 }
1009
1010 /*
1011 * Get the vnode for the component "nm".
1012 */
1013 error = VOP_LOOKUP(dvp, nm, &vp, NULL, 0, NULL, cs->cr,
1014 NULL, NULL, NULL);
1015 if (error)
1016 return (puterrno4(error));
1017
1018 /*
1019 * If the vnode is in a pseudo filesystem, or if the security flavor
1020 * used in the request is valid but not an explicitly shared flavor,
1021 * or the access bit indicates that this is a limited access,
1022 * check whether this vnode is visible.
1023 */
1024 if (!different_export &&
1025 (PSEUDO(cs->exi) || ! is_exported_sec(cs->nfsflavor, cs->exi) ||
1026 cs->access & CS_ACCESS_LIMITED)) {
1027 if (! nfs_visible(cs->exi, vp, &different_export)) {
1028 VN_RELE(vp);
1029 return (puterrno4(ENOENT));
1030 }
1031 }
1032
1033 /*
1034 * If it's a mountpoint, then traverse it.
1035 */
1036 if (vn_ismntpt(vp)) {
1037 if ((error = traverse(&vp)) != 0) {
1038 VN_RELE(vp);
1039 return (puterrno4(error));
1040 }
1041 /* remember that we had to traverse mountpoint */
1042 did_traverse = TRUE;
1043 different_export = 1;
1044 } else if (vp->v_vfsp != dvp->v_vfsp) {
1045 /*
1046 * If vp isn't a mountpoint and the vfs ptrs aren't the same,
1047 * then vp is probably an LOFS object. We don't need the
1049 * a server fs boundary and need to call checkexport4.
1050 * (LOFS lookup hides server fs mountpoints, and actually calls
1051 * traverse)
1052 */
1053 different_export = 1;
1054 }
1055
1056 /*
1057 * Get the export information for it.
1058 */
1059 if (different_export) {
1060
1061 bzero(&fid, sizeof (fid));
1062 fid.fid_len = MAXFIDSZ;
1063 error = vop_fid_pseudo(vp, &fid);
1064 if (error) {
1065 VN_RELE(vp);
1066 return (puterrno4(error));
1067 }
1068
1069 if (dotdot)
1070 exi = nfs_vptoexi(NULL, vp, cs->cr, &walk, NULL, TRUE);
1071 else
1072 exi = checkexport4(&vp->v_vfsp->vfs_fsid, &fid, vp);
1073
1074 if (exi == NULL) {
1075 if (did_traverse == TRUE) {
1076 /*
1077 * If this vnode is a mounted-on vnode,
1078 * but the mounted-on file system is not
1079 * exported, send back the secinfo for
1080 * the exported node that the mounted-on
1081 * vnode lives in.
1082 */
1083 exi = cs->exi;
1084 } else {
1085 VN_RELE(vp);
1086 return (puterrno4(EACCES));
1087 }
1088 }
1089 } else {
1090 exi = cs->exi;
1091 }
1092 ASSERT(exi != NULL);
1093
1094
1095 /*
1096 * Create the secinfo result based on the security information
1097 * from the exportinfo structure (exi).
1098 *
1099 * Return all flavors for a pseudo node.
1100 * For a real export node, return the flavor that the client
1101 * has access with.
1102 */
1103 ASSERT(RW_LOCK_HELD(&ne->exported_lock));
1104 if (PSEUDO(exi)) {
1105 count = exi->exi_export.ex_seccnt; /* total sec count */
1106 resok_val = kmem_alloc(count * sizeof (secinfo4), KM_SLEEP);
1107 secp = exi->exi_export.ex_secinfo;
1108
1109 for (i = 0; i < count; i++) {
1110 si = &secp[i].s_secinfo;
2701 fid_t fid;
2702 int attrdir, dotdot, walk;
2703 bool_t is_newvp = FALSE;
2704
2705 if (cs->vp->v_flag & V_XATTRDIR) {
2706 attrdir = 1;
2707 ASSERT(get_fh4_flag(&cs->fh, FH4_ATTRDIR));
2708 } else {
2709 attrdir = 0;
2710 ASSERT(! get_fh4_flag(&cs->fh, FH4_ATTRDIR));
2711 }
2712
2713 dotdot = (nm[0] == '.' && nm[1] == '.' && nm[2] == '\0');
2714
2715 /*
2716 * If dotdotting, then need to check whether it's
2717 * above the root of a filesystem, or above an
2718 * export point.
2719 */
2720 if (dotdot) {
2721
2722 /*
2723 * If dotdotting at the root of a filesystem, then
2724 * need to traverse back to the mounted-on filesystem
2725 * and do the dotdot lookup there.
2726 */
2727 if ((cs->vp->v_flag & VROOT) || VN_IS_CURZONEROOT(cs->vp)) {
2728
2729 /*
2730 * If at the system root, then can
2731 * go up no further.
2732 */
2733 if (VN_CMP(cs->vp, ZONE_ROOTVP()))
2734 return (puterrno4(ENOENT));
2735
2736 /*
2737 * Traverse back to the mounted-on filesystem
2738 */
2739 cs->vp = untraverse(cs->vp);
2740
2741 /*
|
936 {
937 int i;
938
939 for (i = 0; i < count; i++) {
940 if (nfsnum == flavor_list[i])
941 return (TRUE);
942 }
943 return (FALSE);
944 }
945
946 /*
947 * Used by rfs4_op_secinfo to get the security information from the
948 * export structure associated with the component.
949 */
950 /* ARGSUSED */
951 static nfsstat4
952 do_rfs4_op_secinfo(struct compound_state *cs, char *nm, SECINFO4res *resp)
953 {
954 int error, different_export = 0;
955 vnode_t *dvp, *vp;
956 struct exportinfo *exi;
957 fid_t fid;
958 uint_t count, i;
959 secinfo4 *resok_val;
960 struct secinfo *secp;
961 seconfig_t *si;
962 bool_t did_traverse = FALSE;
963 int dotdot, walk;
964 nfs_export_t *ne = nfs_get_export();
965
966 dvp = cs->vp;
967 exi = cs->exi;
968 ASSERT(exi != NULL);
969 dotdot = (nm[0] == '.' && nm[1] == '.' && nm[2] == '\0');
970
971 /*
972 * If dotdotting, then need to check whether it's above the
973 * root of a filesystem, or above an export point.
974 */
975 if (dotdot) {
976 ASSERT3U(exi->exi_zoneid, ==, curzone->zone_id);
977 /*
978 * If dotdotting at the root of a filesystem, then
979 * need to traverse back to the mounted-on filesystem
980 * and do the dotdot lookup there.
981 */
982 if ((dvp->v_flag & VROOT) || VN_IS_CURZONEROOT(dvp)) {
983
984 /*
985 * If at the system root, then can
986 * go up no further.
987 */
988 if (VN_CMP(dvp, ZONE_ROOTVP()))
989 return (puterrno4(ENOENT));
990
991 /*
992 * Traverse back to the mounted-on filesystem
993 */
994 dvp = untraverse(dvp);
995
996 /*
997 * Set the different_export flag so we remember
998 * to pick up a new exportinfo entry for
999 * this new filesystem.
1000 */
1001 different_export = 1;
1002 } else {
1003
1004 /*
1005 * If dotdotting above an export point then set
1006 * the different_export to get new export info.
1007 */
1008 different_export = nfs_exported(exi, dvp);
1009 }
1010 }
1011
1012 /*
1013 * Get the vnode for the component "nm".
1014 */
1015 error = VOP_LOOKUP(dvp, nm, &vp, NULL, 0, NULL, cs->cr,
1016 NULL, NULL, NULL);
1017 if (error)
1018 return (puterrno4(error));
1019
1020 /*
1021 * If the vnode is in a pseudo filesystem, or if the security flavor
1022 * used in the request is valid but not an explicitly shared flavor,
1023 * or the access bit indicates that this is a limited access,
1024 * check whether this vnode is visible.
1025 */
1026 if (!different_export &&
1027 (PSEUDO(exi) || !is_exported_sec(cs->nfsflavor, exi) ||
1028 cs->access & CS_ACCESS_LIMITED)) {
1029 if (! nfs_visible(exi, vp, &different_export)) {
1030 VN_RELE(vp);
1031 return (puterrno4(ENOENT));
1032 }
1033 }
1034
1035 /*
1036 * If it's a mountpoint, then traverse it.
1037 */
1038 if (vn_ismntpt(vp)) {
1039 if ((error = traverse(&vp)) != 0) {
1040 VN_RELE(vp);
1041 return (puterrno4(error));
1042 }
1043 /* remember that we had to traverse mountpoint */
1044 did_traverse = TRUE;
1045 different_export = 1;
1046 } else if (vp->v_vfsp != dvp->v_vfsp) {
1047 /*
1048 * If vp isn't a mountpoint and the vfs ptrs aren't the same,
1049 * then vp is probably an LOFS object. We don't need the
1051 * a server fs boundary and need to call checkexport4.
1052 * (LOFS lookup hides server fs mountpoints, and actually calls
1053 * traverse)
1054 */
1055 different_export = 1;
1056 }
1057
1058 /*
1059 * Get the export information for it.
1060 */
1061 if (different_export) {
1062
1063 bzero(&fid, sizeof (fid));
1064 fid.fid_len = MAXFIDSZ;
1065 error = vop_fid_pseudo(vp, &fid);
1066 if (error) {
1067 VN_RELE(vp);
1068 return (puterrno4(error));
1069 }
1070
1071 /* We'll need to reassign "exi". */
1072 if (dotdot)
1073 exi = nfs_vptoexi(NULL, vp, cs->cr, &walk, NULL, TRUE);
1074 else
1075 exi = checkexport4(&vp->v_vfsp->vfs_fsid, &fid, vp);
1076
1077 if (exi == NULL) {
1078 if (did_traverse == TRUE) {
1079 /*
1080 * If this vnode is a mounted-on vnode,
1081 * but the mounted-on file system is not
1082 * exported, send back the secinfo for
1083 * the exported node that the mounted-on
1084 * vnode lives in.
1085 */
1086 exi = cs->exi;
1087 } else {
1088 VN_RELE(vp);
1089 return (puterrno4(EACCES));
1090 }
1091 }
1092 }
1093 ASSERT(exi != NULL);
1094
1095
1096 /*
1097 * Create the secinfo result based on the security information
1098 * from the exportinfo structure (exi).
1099 *
1100 * Return all flavors for a pseudo node.
1101 * For a real export node, return the flavor that the client
1102 * has access with.
1103 */
1104 ASSERT(RW_LOCK_HELD(&ne->exported_lock));
1105 if (PSEUDO(exi)) {
1106 count = exi->exi_export.ex_seccnt; /* total sec count */
1107 resok_val = kmem_alloc(count * sizeof (secinfo4), KM_SLEEP);
1108 secp = exi->exi_export.ex_secinfo;
1109
1110 for (i = 0; i < count; i++) {
1111 si = &secp[i].s_secinfo;
2702 fid_t fid;
2703 int attrdir, dotdot, walk;
2704 bool_t is_newvp = FALSE;
2705
2706 if (cs->vp->v_flag & V_XATTRDIR) {
2707 attrdir = 1;
2708 ASSERT(get_fh4_flag(&cs->fh, FH4_ATTRDIR));
2709 } else {
2710 attrdir = 0;
2711 ASSERT(! get_fh4_flag(&cs->fh, FH4_ATTRDIR));
2712 }
2713
2714 dotdot = (nm[0] == '.' && nm[1] == '.' && nm[2] == '\0');
2715
2716 /*
2717 * If dotdotting, then need to check whether it's
2718 * above the root of a filesystem, or above an
2719 * export point.
2720 */
2721 if (dotdot) {
2722 ASSERT(cs->exi != NULL);
2723 ASSERT3U(cs->exi->exi_zoneid, ==, curzone->zone_id);
2724 /*
2725 * If dotdotting at the root of a filesystem, then
2726 * need to traverse back to the mounted-on filesystem
2727 * and do the dotdot lookup there.
2728 */
2729 if ((cs->vp->v_flag & VROOT) || VN_IS_CURZONEROOT(cs->vp)) {
2730
2731 /*
2732 * If at the system root, then can
2733 * go up no further.
2734 */
2735 if (VN_CMP(cs->vp, ZONE_ROOTVP()))
2736 return (puterrno4(ENOENT));
2737
2738 /*
2739 * Traverse back to the mounted-on filesystem
2740 */
2741 cs->vp = untraverse(cs->vp);
2742
2743 /*
|