Print this page
12505 Answer KEBE question about cred in unexport()


  68 #include <nfs/lm.h>
  69 #include <sys/sunddi.h>
  70 
  71 /*
  72  * exi_id support
  73  *
  74  * exi_id_next          The next exi_id available.
  75  * exi_id_overflow      The exi_id_next already overflowed, so we should
  76  *                      thoroughly check for duplicates.
  77  * exi_id_tree          AVL tree indexed by exi_id.
  78  * nfs_exi_id_lock      Lock to protect the export ID list
  79  *
  80  * All exi_id_next, exi_id_overflow, and exi_id_tree are protected by
  81  * nfs_exi_id_lock.
  82  */
  83 static int exi_id_next;
  84 static bool_t exi_id_overflow;
  85 avl_tree_t exi_id_tree;
  86 kmutex_t nfs_exi_id_lock;
  87 
  88 static int      unexport(nfs_export_t *, exportinfo_t *);
  89 static void     exportfree(exportinfo_t *);
  90 static int      loadindex(exportdata_t *);
  91 
  92 extern void     nfsauth_cache_free(exportinfo_t *);
  93 extern int      sec_svc_loadrootnames(int, int, caddr_t **, model_t);
  94 extern void     sec_svc_freerootnames(int, int, caddr_t *);
  95 
  96 static int      build_seclist_nodups(exportdata_t *, secinfo_t *, int);
  97 static void     srv_secinfo_add(secinfo_t **, int *, secinfo_t *, int, int);
  98 static void     srv_secinfo_remove(secinfo_t **, int *, secinfo_t *, int);
  99 static void     srv_secinfo_treeclimb(nfs_export_t *, exportinfo_t *,
 100                     secinfo_t *, int, bool_t);
 101 
 102 #ifdef VOLATILE_FH_TEST
 103 static struct ex_vol_rename *find_volrnm_fh(exportinfo_t *, nfs_fh4 *);
 104 static uint32_t find_volrnm_fh_id(exportinfo_t *, nfs_fh4 *);
 105 static void     free_volrnm_list(exportinfo_t *);
 106 #endif /* VOLATILE_FH_TEST */
 107 
 108 fhandle_t nullfh2;      /* for comparing V2 filehandles */


 958         mutex_enter(&nfs_exi_id_lock);
 959         ne->exi_root->exi_id = exi_id_get_next();
 960         avl_add(&exi_id_tree, ne->exi_root);
 961         mutex_exit(&nfs_exi_id_lock);
 962 
 963         rw_exit(&ne->exported_lock);
 964         ne->ns_root = NULL;
 965 
 966         ng->nfs_export = ne;
 967 }
 968 
 969 /*
 970  * During zone shutdown, remove exports
 971  */
 972 void
 973 nfs_export_zone_shutdown(nfs_globals_t *ng)
 974 {
 975         nfs_export_t *ne = ng->nfs_export;
 976         struct exportinfo *exi, *nexi;
 977         int i, errors;


 978 






 979         rw_enter(&ne->exported_lock, RW_READER);
 980 
 981         errors = 0;
 982         for (i = 0; i < EXPTABLESIZE; i++) {
 983 
 984                 exi = ne->exptable[i];
 985                 if (exi != NULL)
 986                         exi_hold(exi);
 987 
 988                 while (exi != NULL) {
 989 
 990                         /*
 991                          * Get and hold next export before
 992                          * dropping the rwlock and unexport
 993                          */
 994                         nexi = exi->fid_hash.next;
 995                         if (nexi != NULL)
 996                                 exi_hold(nexi);
 997 
 998                         rw_exit(&ne->exported_lock);
 999 
1000                         /*
1001                          * Skip ne->exi_root which gets special
1002                          * create/destroy handling.
1003                          */
1004                         if (exi != ne->exi_root &&
1005                             unexport(ne, exi) != 0)
1006                                 errors++;
1007                         exi_rele(exi);
1008 
1009                         rw_enter(&ne->exported_lock, RW_READER);
1010                         exi = nexi;
1011                 }
1012         }
1013         if (errors > 0) {
1014                 cmn_err(CE_NOTE, "NFS: failed un-exports in zone %d",
1015                     (int)ng->nfs_zoneid);
1016         }
1017 
1018         rw_exit(&ne->exported_lock);

1019 }
1020 
1021 void
1022 nfs_export_zone_fini(nfs_globals_t *ng)
1023 {
1024         int i;
1025         nfs_export_t *ne = ng->nfs_export;
1026         struct exportinfo *exi;
1027 
1028         ng->nfs_export = NULL;
1029 
1030         rw_enter(&ne->exported_lock, RW_WRITER);
1031 
1032         mutex_enter(&nfs_exi_id_lock);
1033         avl_remove(&exi_id_tree, ne->exi_root);
1034         mutex_exit(&nfs_exi_id_lock);
1035 
1036         export_unlink(ne, ne->exi_root);
1037 
1038         rw_exit(&ne->exported_lock);


1269 
1270         /* Walk the export list looking for that pathname */
1271         rw_enter(&ne->exported_lock, RW_READER);
1272         DTRACE_PROBE(nfss__i__exported_lock1_start);
1273         for (ex1 = ne->exptable_path_hash[pkp_tab_hash(lookpn.pn_path,
1274             strlen(lookpn.pn_path))]; ex1; ex1 = ex1->path_hash.next) {
1275                 if (ex1 != ne->exi_root && 0 ==
1276                     strcmp(ex1->exi_export.ex_path, lookpn.pn_path)) {
1277                         exi_hold(ex1);
1278                         break;
1279                 }
1280         }
1281         DTRACE_PROBE(nfss__i__exported_lock1_stop);
1282         rw_exit(&ne->exported_lock);
1283 
1284         /* Is this an unshare? */
1285         if (STRUCT_FGETP(uap, uex) == NULL) {
1286                 pn_free(&lookpn);
1287                 if (ex1 == NULL)
1288                         return (EINVAL);
1289                 error = unexport(ne, ex1);
1290                 exi_rele(ex1);
1291                 return (error);
1292         }
1293 
1294         /* It is a share or a re-share */
1295         error = lookupname(STRUCT_FGETP(uap, dname), UIO_USERSPACE,
1296             FOLLOW, &dvp, &vp);
1297         if (error == EINVAL) {
1298                 /*
1299                  * if fname resolves to / we get EINVAL error
1300                  * since we wanted the parent vnode. Try again
1301                  * with NULL dvp.
1302                  */
1303                 error = lookupname(STRUCT_FGETP(uap, dname), UIO_USERSPACE,
1304                     FOLLOW, NULL, &vp);
1305                 dvp = NULL;
1306         }
1307         if (!error && vp == NULL) {
1308                 /* Last component of fname not found */
1309                 if (dvp != NULL)


1869 }
1870 
1871 /*
1872  * Remove the exportinfo from the export list
1873  */
1874 void
1875 export_unlink(nfs_export_t *ne, struct exportinfo *exi)
1876 {
1877         ASSERT(RW_WRITE_HELD(&ne->exported_lock));
1878 
1879         exp_hash_unlink(exi, fid_hash);
1880         exp_hash_unlink(exi, path_hash);
1881         ASSERT3P(exi->exi_ne, ==, ne);
1882         exi->exi_ne = NULL;
1883 }
1884 
1885 /*
1886  * Unexport an exported filesystem
1887  */
1888 static int
1889 unexport(nfs_export_t *ne, struct exportinfo *exi)
1890 {
1891         struct secinfo cursec[MAX_FLAVORS];
1892         int curcnt;
1893 
1894         rw_enter(&ne->exported_lock, RW_WRITER);
1895 
1896         /* Check if exi is still linked in the export table */
1897         if (!EXP_LINKED(exi) || PSEUDO(exi)) {
1898                 rw_exit(&ne->exported_lock);
1899                 return (EINVAL);
1900         }
1901 
1902         mutex_enter(&nfs_exi_id_lock);
1903         avl_remove(&exi_id_tree, exi);
1904         mutex_exit(&nfs_exi_id_lock);
1905         export_unlink(ne, exi);
1906 
1907         /*
1908          * Remove security flavors before treeclimb_unexport() is called
1909          * because srv_secinfo_treeclimb needs the namespace tree


1937 
1938         /*
1939          * Need to call into the NFSv4 server and release all data
1940          * held on this particular export.  This is important since
1941          * the v4 server may be holding file locks or vnodes under
1942          * this export.
1943          */
1944         rfs4_clean_state_exi(ne, exi);
1945 
1946         /*
1947          * Notify the lock manager that the filesystem is being
1948          * unexported.
1949          */
1950         lm_unexport(exi);
1951 
1952         /*
1953          * If this was a public export, restore
1954          * the public filehandle to the root.
1955          */
1956 
1957         /*
1958          * XXX KEBE ASKS --> Should CRED() instead be
1959          * exi->exi_zone->zone_kcred?
1960          */
1961         if (exi == ne->exi_public) {
1962                 ne->exi_public = ne->exi_root;
1963 
1964                 nfslog_share_record(ne->exi_public, CRED());
1965         }
1966 
1967         if (exi->exi_export.ex_flags & EX_LOG)
1968                 nfslog_unshare_record(exi, CRED());
1969 
1970         exi_rele(exi);
1971         return (0);
1972 }
1973 
1974 /*
1975  * Get file handle system call.
1976  * Takes file name and returns a file handle for it.
1977  * Credentials must be verified before calling.
1978  */
1979 int
1980 nfs_getfh(struct nfs_getfh_args *args, model_t model, cred_t *cr)
1981 {
1982         nfs_fh3 fh;
1983         char buf[NFS3_MAXFHSIZE];
1984         char *logptr, logbuf[NFS3_MAXFHSIZE];
1985         int l = NFS3_MAXFHSIZE;
1986         vnode_t *vp;
1987         vnode_t *dvp;
1988         struct exportinfo *exi;




  68 #include <nfs/lm.h>
  69 #include <sys/sunddi.h>
  70 
  71 /*
  72  * exi_id support
  73  *
  74  * exi_id_next          The next exi_id available.
  75  * exi_id_overflow      The exi_id_next already overflowed, so we should
  76  *                      thoroughly check for duplicates.
  77  * exi_id_tree          AVL tree indexed by exi_id.
  78  * nfs_exi_id_lock      Lock to protect the export ID list
  79  *
  80  * All exi_id_next, exi_id_overflow, and exi_id_tree are protected by
  81  * nfs_exi_id_lock.
  82  */
  83 static int exi_id_next;
  84 static bool_t exi_id_overflow;
  85 avl_tree_t exi_id_tree;
  86 kmutex_t nfs_exi_id_lock;
  87 
  88 static int      unexport(nfs_export_t *, exportinfo_t *, cred_t *);
  89 static void     exportfree(exportinfo_t *);
  90 static int      loadindex(exportdata_t *);
  91 
  92 extern void     nfsauth_cache_free(exportinfo_t *);
  93 extern int      sec_svc_loadrootnames(int, int, caddr_t **, model_t);
  94 extern void     sec_svc_freerootnames(int, int, caddr_t *);
  95 
  96 static int      build_seclist_nodups(exportdata_t *, secinfo_t *, int);
  97 static void     srv_secinfo_add(secinfo_t **, int *, secinfo_t *, int, int);
  98 static void     srv_secinfo_remove(secinfo_t **, int *, secinfo_t *, int);
  99 static void     srv_secinfo_treeclimb(nfs_export_t *, exportinfo_t *,
 100                     secinfo_t *, int, bool_t);
 101 
 102 #ifdef VOLATILE_FH_TEST
 103 static struct ex_vol_rename *find_volrnm_fh(exportinfo_t *, nfs_fh4 *);
 104 static uint32_t find_volrnm_fh_id(exportinfo_t *, nfs_fh4 *);
 105 static void     free_volrnm_list(exportinfo_t *);
 106 #endif /* VOLATILE_FH_TEST */
 107 
 108 fhandle_t nullfh2;      /* for comparing V2 filehandles */


 958         mutex_enter(&nfs_exi_id_lock);
 959         ne->exi_root->exi_id = exi_id_get_next();
 960         avl_add(&exi_id_tree, ne->exi_root);
 961         mutex_exit(&nfs_exi_id_lock);
 962 
 963         rw_exit(&ne->exported_lock);
 964         ne->ns_root = NULL;
 965 
 966         ng->nfs_export = ne;
 967 }
 968 
 969 /*
 970  * During zone shutdown, remove exports
 971  */
 972 void
 973 nfs_export_zone_shutdown(nfs_globals_t *ng)
 974 {
 975         nfs_export_t *ne = ng->nfs_export;
 976         struct exportinfo *exi, *nexi;
 977         int i, errors;
 978         zoneid_t zoneid = ng->nfs_zoneid;
 979         cred_t *cr;
 980 
 981         /*
 982          * Use the zone's credential.  Since this is a zone shutdown method,
 983          * the zone_t should still be around for a zone_get_kcred() call.
 984          */
 985         cr = zone_get_kcred(zoneid);
 986         VERIFY(cr != NULL);
 987         rw_enter(&ne->exported_lock, RW_READER);
 988 
 989         errors = 0;
 990         for (i = 0; i < EXPTABLESIZE; i++) {
 991 
 992                 exi = ne->exptable[i];
 993                 if (exi != NULL)
 994                         exi_hold(exi);
 995 
 996                 while (exi != NULL) {
 997                         ASSERT3U(zoneid, ==, exi->exi_zoneid);
 998                         /*
 999                          * Get and hold next export before
1000                          * dropping the rwlock and unexport
1001                          */
1002                         nexi = exi->fid_hash.next;
1003                         if (nexi != NULL)
1004                                 exi_hold(nexi);
1005 
1006                         rw_exit(&ne->exported_lock);
1007 
1008                         /*
1009                          * Skip ne->exi_root which gets special
1010                          * create/destroy handling.
1011                          */
1012                         if (exi != ne->exi_root &&
1013                             unexport(ne, exi, cr) != 0)
1014                                 errors++;
1015                         exi_rele(exi);
1016 
1017                         rw_enter(&ne->exported_lock, RW_READER);
1018                         exi = nexi;
1019                 }
1020         }
1021         if (errors > 0) {
1022                 cmn_err(CE_NOTE, "NFS: failed un-exports in zone %d",
1023                     (int)ng->nfs_zoneid);
1024         }
1025 
1026         rw_exit(&ne->exported_lock);
1027         crfree(cr);
1028 }
1029 
1030 void
1031 nfs_export_zone_fini(nfs_globals_t *ng)
1032 {
1033         int i;
1034         nfs_export_t *ne = ng->nfs_export;
1035         struct exportinfo *exi;
1036 
1037         ng->nfs_export = NULL;
1038 
1039         rw_enter(&ne->exported_lock, RW_WRITER);
1040 
1041         mutex_enter(&nfs_exi_id_lock);
1042         avl_remove(&exi_id_tree, ne->exi_root);
1043         mutex_exit(&nfs_exi_id_lock);
1044 
1045         export_unlink(ne, ne->exi_root);
1046 
1047         rw_exit(&ne->exported_lock);


1278 
1279         /* Walk the export list looking for that pathname */
1280         rw_enter(&ne->exported_lock, RW_READER);
1281         DTRACE_PROBE(nfss__i__exported_lock1_start);
1282         for (ex1 = ne->exptable_path_hash[pkp_tab_hash(lookpn.pn_path,
1283             strlen(lookpn.pn_path))]; ex1; ex1 = ex1->path_hash.next) {
1284                 if (ex1 != ne->exi_root && 0 ==
1285                     strcmp(ex1->exi_export.ex_path, lookpn.pn_path)) {
1286                         exi_hold(ex1);
1287                         break;
1288                 }
1289         }
1290         DTRACE_PROBE(nfss__i__exported_lock1_stop);
1291         rw_exit(&ne->exported_lock);
1292 
1293         /* Is this an unshare? */
1294         if (STRUCT_FGETP(uap, uex) == NULL) {
1295                 pn_free(&lookpn);
1296                 if (ex1 == NULL)
1297                         return (EINVAL);
1298                 error = unexport(ne, ex1, cr);
1299                 exi_rele(ex1);
1300                 return (error);
1301         }
1302 
1303         /* It is a share or a re-share */
1304         error = lookupname(STRUCT_FGETP(uap, dname), UIO_USERSPACE,
1305             FOLLOW, &dvp, &vp);
1306         if (error == EINVAL) {
1307                 /*
1308                  * if fname resolves to / we get EINVAL error
1309                  * since we wanted the parent vnode. Try again
1310                  * with NULL dvp.
1311                  */
1312                 error = lookupname(STRUCT_FGETP(uap, dname), UIO_USERSPACE,
1313                     FOLLOW, NULL, &vp);
1314                 dvp = NULL;
1315         }
1316         if (!error && vp == NULL) {
1317                 /* Last component of fname not found */
1318                 if (dvp != NULL)


1878 }
1879 
1880 /*
1881  * Remove the exportinfo from the export list
1882  */
1883 void
1884 export_unlink(nfs_export_t *ne, struct exportinfo *exi)
1885 {
1886         ASSERT(RW_WRITE_HELD(&ne->exported_lock));
1887 
1888         exp_hash_unlink(exi, fid_hash);
1889         exp_hash_unlink(exi, path_hash);
1890         ASSERT3P(exi->exi_ne, ==, ne);
1891         exi->exi_ne = NULL;
1892 }
1893 
1894 /*
1895  * Unexport an exported filesystem
1896  */
1897 static int
1898 unexport(nfs_export_t *ne, struct exportinfo *exi, cred_t *cr)
1899 {
1900         struct secinfo cursec[MAX_FLAVORS];
1901         int curcnt;
1902 
1903         rw_enter(&ne->exported_lock, RW_WRITER);
1904 
1905         /* Check if exi is still linked in the export table */
1906         if (!EXP_LINKED(exi) || PSEUDO(exi)) {
1907                 rw_exit(&ne->exported_lock);
1908                 return (EINVAL);
1909         }
1910 
1911         mutex_enter(&nfs_exi_id_lock);
1912         avl_remove(&exi_id_tree, exi);
1913         mutex_exit(&nfs_exi_id_lock);
1914         export_unlink(ne, exi);
1915 
1916         /*
1917          * Remove security flavors before treeclimb_unexport() is called
1918          * because srv_secinfo_treeclimb needs the namespace tree


1946 
1947         /*
1948          * Need to call into the NFSv4 server and release all data
1949          * held on this particular export.  This is important since
1950          * the v4 server may be holding file locks or vnodes under
1951          * this export.
1952          */
1953         rfs4_clean_state_exi(ne, exi);
1954 
1955         /*
1956          * Notify the lock manager that the filesystem is being
1957          * unexported.
1958          */
1959         lm_unexport(exi);
1960 
1961         /*
1962          * If this was a public export, restore
1963          * the public filehandle to the root.
1964          */
1965 




1966         if (exi == ne->exi_public) {
1967                 ne->exi_public = ne->exi_root;
1968 
1969                 nfslog_share_record(ne->exi_public, cr);
1970         }
1971 
1972         if (exi->exi_export.ex_flags & EX_LOG)
1973                 nfslog_unshare_record(exi, cr);
1974 
1975         exi_rele(exi);
1976         return (0);
1977 }
1978 
1979 /*
1980  * Get file handle system call.
1981  * Takes file name and returns a file handle for it.
1982  * Credentials must be verified before calling.
1983  */
1984 int
1985 nfs_getfh(struct nfs_getfh_args *args, model_t model, cred_t *cr)
1986 {
1987         nfs_fh3 fh;
1988         char buf[NFS3_MAXFHSIZE];
1989         char *logptr, logbuf[NFS3_MAXFHSIZE];
1990         int l = NFS3_MAXFHSIZE;
1991         vnode_t *vp;
1992         vnode_t *dvp;
1993         struct exportinfo *exi;