11676Sjpk /* 21676Sjpk * CDDL HEADER START 31676Sjpk * 41676Sjpk * The contents of this file are subject to the terms of the 51676Sjpk * Common Development and Distribution License (the "License"). 61676Sjpk * You may not use this file except in compliance with the License. 71676Sjpk * 81676Sjpk * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 91676Sjpk * or http://www.opensolaris.org/os/licensing. 101676Sjpk * See the License for the specific language governing permissions 111676Sjpk * and limitations under the License. 121676Sjpk * 131676Sjpk * When distributing Covered Code, include this CDDL HEADER in each 141676Sjpk * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 151676Sjpk * If applicable, add the following below this CDDL HEADER, with the 161676Sjpk * fields enclosed by brackets "[]" replaced with your own identifying 171676Sjpk * information: Portions Copyright [yyyy] [name of copyright owner] 181676Sjpk * 191676Sjpk * CDDL HEADER END 201676Sjpk */ 211676Sjpk /* 22*12236SRic.Aleshire@Sun.COM * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. 231676Sjpk */ 241676Sjpk 251676Sjpk #include <sys/types.h> 261676Sjpk #include <sys/param.h> 271676Sjpk #include <sys/cmn_err.h> 281676Sjpk #include <sys/systm.h> 291676Sjpk #include <sys/cred.h> 301676Sjpk #include <sys/modctl.h> 311676Sjpk #include <sys/vfs.h> 321676Sjpk #include <sys/vnode.h> 331676Sjpk #include <sys/tiuser.h> 341676Sjpk #include <sys/kmem.h> 351676Sjpk #include <sys/pathname.h> 361676Sjpk #include <sys/zone.h> 371676Sjpk #include <sys/tsol/label.h> 381676Sjpk #include <sys/tsol/tnet.h> 391676Sjpk #include <sys/fs/lofs_node.h> 40*12236SRic.Aleshire@Sun.COM #include <sys/fs/zfs.h> 41*12236SRic.Aleshire@Sun.COM #include <sys/dsl_prop.h> 421676Sjpk #include <inet/ip6.h> 431676Sjpk #include <rpc/auth.h> 441676Sjpk #include <rpc/clnt.h> 451676Sjpk #include <nfs/nfs.h> 461676Sjpk #include <nfs/nfs4.h> 471676Sjpk #include <nfs/nfs_clnt.h> 481676Sjpk 491676Sjpk 504746Srica int sys_labeling = 0; /* the default is "off" */ 511676Sjpk 521676Sjpk static kmem_cache_t *tslabel_cache; 531676Sjpk ts_label_t *l_admin_low; 541676Sjpk ts_label_t *l_admin_high; 551676Sjpk 561676Sjpk uint32_t default_doi = DEFAULT_DOI; 571676Sjpk 581676Sjpk /* 591676Sjpk * Initialize labels infrastructure. 601676Sjpk * This is called during startup() time (before vfs_mntroot) by thread_init(). 611676Sjpk * It has to be called early so that the is_system_labeled() function returns 621676Sjpk * the right value when called by the networking code on a diskless boot. 631676Sjpk */ 641676Sjpk void 651676Sjpk label_init(void) 661676Sjpk { 671676Sjpk bslabel_t label; 681676Sjpk 691676Sjpk /* 704746Srica * sys_labeling will default to "off" unless it is overridden 714746Srica * in /etc/system. 721676Sjpk */ 731676Sjpk 741676Sjpk tslabel_cache = kmem_cache_create("tslabel_cache", sizeof (ts_label_t), 751676Sjpk 0, NULL, NULL, NULL, NULL, NULL, 0); 761676Sjpk bsllow(&label); 771676Sjpk l_admin_low = labelalloc(&label, default_doi, KM_SLEEP); 781676Sjpk bslhigh(&label); 791676Sjpk l_admin_high = labelalloc(&label, default_doi, KM_SLEEP); 801676Sjpk } 811676Sjpk 821676Sjpk /* 831676Sjpk * Allocate new ts_label_t. 841676Sjpk */ 851676Sjpk ts_label_t * 861676Sjpk labelalloc(const bslabel_t *val, uint32_t doi, int flag) 871676Sjpk { 881676Sjpk ts_label_t *lab = kmem_cache_alloc(tslabel_cache, flag); 891676Sjpk 901676Sjpk if (lab != NULL) { 911676Sjpk lab->tsl_ref = 1; 921676Sjpk lab->tsl_doi = doi; 934448Skp158701 lab->tsl_flags = 0; 941676Sjpk if (val == NULL) 951676Sjpk bzero(&lab->tsl_label, sizeof (bslabel_t)); 961676Sjpk else 971676Sjpk bcopy(val, &lab->tsl_label, sizeof (bslabel_t)); 981676Sjpk } 991676Sjpk return (lab); 1001676Sjpk } 1011676Sjpk 1021676Sjpk /* 1039710SKen.Powell@Sun.COM * Duplicate an existing ts_label_t to a new one, with only 1049710SKen.Powell@Sun.COM * the current reference. 1059710SKen.Powell@Sun.COM */ 1069710SKen.Powell@Sun.COM ts_label_t * 1079710SKen.Powell@Sun.COM labeldup(const ts_label_t *val, int flag) 1089710SKen.Powell@Sun.COM { 1099710SKen.Powell@Sun.COM ts_label_t *lab = kmem_cache_alloc(tslabel_cache, flag); 1109710SKen.Powell@Sun.COM 1119710SKen.Powell@Sun.COM if (lab != NULL) { 1129710SKen.Powell@Sun.COM bcopy(val, lab, sizeof (ts_label_t)); 1139710SKen.Powell@Sun.COM lab->tsl_ref = 1; 1149710SKen.Powell@Sun.COM } 1159710SKen.Powell@Sun.COM return (lab); 1169710SKen.Powell@Sun.COM } 1179710SKen.Powell@Sun.COM 1189710SKen.Powell@Sun.COM /* 1191676Sjpk * Put a hold on a label structure. 1201676Sjpk */ 1211676Sjpk void 1221676Sjpk label_hold(ts_label_t *lab) 1231676Sjpk { 1241676Sjpk atomic_add_32(&lab->tsl_ref, 1); 1251676Sjpk } 1261676Sjpk 1271676Sjpk /* 1281676Sjpk * Release previous hold on a label structure. Free it if refcnt == 0. 1291676Sjpk */ 1301676Sjpk void 1311676Sjpk label_rele(ts_label_t *lab) 1321676Sjpk { 1331676Sjpk if (atomic_add_32_nv(&lab->tsl_ref, -1) == 0) 1341676Sjpk kmem_cache_free(tslabel_cache, lab); 1351676Sjpk } 1361676Sjpk 1371676Sjpk bslabel_t * 1381676Sjpk label2bslabel(ts_label_t *lab) 1391676Sjpk { 1401676Sjpk return (&lab->tsl_label); 1411676Sjpk } 1421676Sjpk 1431676Sjpk 1441676Sjpk uint32_t 1451676Sjpk label2doi(ts_label_t *lab) 1461676Sjpk { 1471676Sjpk return (lab->tsl_doi); 1481676Sjpk } 1491676Sjpk 1501676Sjpk /* 1511676Sjpk * Compare labels. Return 1 if equal, 0 otherwise. 1521676Sjpk */ 1531676Sjpk boolean_t 1541676Sjpk label_equal(const ts_label_t *l1, const ts_label_t *l2) 1551676Sjpk { 1561676Sjpk return ((l1->tsl_doi == l2->tsl_doi) && 1571676Sjpk blequal(&l1->tsl_label, &l2->tsl_label)); 1581676Sjpk } 1591676Sjpk 1601676Sjpk /* 1611676Sjpk * There's no protocol today to obtain the label from the server. 1621676Sjpk * So we rely on conventions: zones, zone names, and zone paths 1631676Sjpk * must match across TX servers and their TX clients. Now use 1641676Sjpk * the exported name to find the equivalent local zone and its 1651676Sjpk * label. Caller is responsible for doing a label_rele of the 1661676Sjpk * returned ts_label. 1671676Sjpk */ 1681676Sjpk ts_label_t * 1691676Sjpk getflabel_cipso(vfs_t *vfsp) 1701676Sjpk { 1711676Sjpk zone_t *reszone; 1721676Sjpk zone_t *new_reszone; 1731676Sjpk char *nfspath, *respath; 1741676Sjpk refstr_t *resource_ref; 1751676Sjpk boolean_t treat_abs = B_FALSE; 1761676Sjpk 1771676Sjpk if (vfsp->vfs_resource == NULL) 1781676Sjpk return (NULL); /* error */ 1791676Sjpk resource_ref = vfs_getresource(vfsp); 1801676Sjpk 1811676Sjpk nfspath = (char *)refstr_value(resource_ref); 1821676Sjpk respath = strchr(nfspath, ':'); /* skip server name */ 1831676Sjpk if (respath) 1841676Sjpk respath++; /* skip over ":" */ 1851676Sjpk if (*respath != '/') { 1861676Sjpk /* treat path as absolute but it doesn't have leading '/' */ 1871676Sjpk treat_abs = B_TRUE; 1881676Sjpk } 1891676Sjpk 1901676Sjpk reszone = zone_find_by_any_path(respath, treat_abs); 1911676Sjpk if (reszone == global_zone) { 1921676Sjpk refstr_rele(resource_ref); 1931676Sjpk label_hold(l_admin_low); 1941676Sjpk zone_rele(reszone); 1951676Sjpk return (l_admin_low); 1961676Sjpk } 1971676Sjpk 1981676Sjpk /* 1991676Sjpk * Skip over zonepath (not including "root"), e.g. /zone/internal 2001676Sjpk */ 2011676Sjpk respath += reszone->zone_rootpathlen - 7; 2021676Sjpk if (treat_abs) 2031676Sjpk respath--; /* no leading '/' to skip */ 2041676Sjpk if (strncmp(respath, "/root/", 6) == 0) { 2051676Sjpk /* Check if we now have something like "/zone/public/" */ 2061676Sjpk 2071676Sjpk respath += 5; /* skip "/root" first */ 2081676Sjpk new_reszone = zone_find_by_any_path(respath, B_FALSE); 2091676Sjpk if (new_reszone != global_zone) { 2101676Sjpk zone_rele(reszone); 2111676Sjpk reszone = new_reszone; 2121676Sjpk } else { 2131676Sjpk zone_rele(new_reszone); 2141676Sjpk } 2151676Sjpk } 2161676Sjpk 2171676Sjpk refstr_rele(resource_ref); 2181676Sjpk label_hold(reszone->zone_slabel); 2191676Sjpk zone_rele(reszone); 2201676Sjpk 2211676Sjpk return (reszone->zone_slabel); 2221676Sjpk } 2231676Sjpk 224*12236SRic.Aleshire@Sun.COM /* 225*12236SRic.Aleshire@Sun.COM * Get the label if any of a zfs filesystem. Get the dataset, then 226*12236SRic.Aleshire@Sun.COM * get its mlslabel property, convert as needed, and return it. If 227*12236SRic.Aleshire@Sun.COM * there's no mlslabel or it is the default one, return NULL. 228*12236SRic.Aleshire@Sun.COM */ 229*12236SRic.Aleshire@Sun.COM static ts_label_t * 230*12236SRic.Aleshire@Sun.COM getflabel_zfs(vfs_t *vfsp) 231*12236SRic.Aleshire@Sun.COM { 232*12236SRic.Aleshire@Sun.COM int error; 233*12236SRic.Aleshire@Sun.COM ts_label_t *tsl = NULL; 234*12236SRic.Aleshire@Sun.COM refstr_t *resource_ref; 235*12236SRic.Aleshire@Sun.COM bslabel_t ds_sl; 236*12236SRic.Aleshire@Sun.COM char ds_hexsl[MAXNAMELEN]; 237*12236SRic.Aleshire@Sun.COM const char *osname; 238*12236SRic.Aleshire@Sun.COM 239*12236SRic.Aleshire@Sun.COM resource_ref = vfs_getresource(vfsp); 240*12236SRic.Aleshire@Sun.COM osname = refstr_value(resource_ref); 241*12236SRic.Aleshire@Sun.COM 242*12236SRic.Aleshire@Sun.COM error = dsl_prop_get(osname, zfs_prop_to_name(ZFS_PROP_MLSLABEL), 243*12236SRic.Aleshire@Sun.COM 1, sizeof (ds_hexsl), &ds_hexsl, NULL); 244*12236SRic.Aleshire@Sun.COM refstr_rele(resource_ref); 245*12236SRic.Aleshire@Sun.COM 246*12236SRic.Aleshire@Sun.COM if ((error) || (strcasecmp(ds_hexsl, ZFS_MLSLABEL_DEFAULT) == 0)) 247*12236SRic.Aleshire@Sun.COM return (NULL); 248*12236SRic.Aleshire@Sun.COM if (hexstr_to_label(ds_hexsl, &ds_sl) != 0) 249*12236SRic.Aleshire@Sun.COM return (NULL); 250*12236SRic.Aleshire@Sun.COM 251*12236SRic.Aleshire@Sun.COM tsl = labelalloc(&ds_sl, default_doi, KM_SLEEP); 252*12236SRic.Aleshire@Sun.COM return (tsl); 253*12236SRic.Aleshire@Sun.COM } 254*12236SRic.Aleshire@Sun.COM 2551676Sjpk static ts_label_t * 2561676Sjpk getflabel_nfs(vfs_t *vfsp) 2571676Sjpk { 2581676Sjpk bslabel_t *server_sl; 2591676Sjpk ts_label_t *srv_label; 2601676Sjpk tsol_tpc_t *tp; 2611676Sjpk int addr_type; 2621676Sjpk void *ipaddr; 2631676Sjpk struct servinfo *svp; 2641676Sjpk struct netbuf *addr; 2651676Sjpk struct knetconfig *knconf; 2661676Sjpk mntinfo_t *mi; 2671676Sjpk 2681676Sjpk mi = VFTOMI(vfsp); 2691676Sjpk svp = mi->mi_curr_serv; 2701676Sjpk addr = &svp->sv_addr; 2711676Sjpk knconf = svp->sv_knconf; 2721676Sjpk 2731676Sjpk if (strcmp(knconf->knc_protofmly, NC_INET) == 0) { 2741676Sjpk addr_type = IPV4_VERSION; 2751676Sjpk /* LINTED: following cast to ipaddr is OK */ 2761676Sjpk ipaddr = &((struct sockaddr_in *)addr->buf)->sin_addr; 2771676Sjpk } else if (strcmp(knconf->knc_protofmly, NC_INET6) == 0) { 2781676Sjpk addr_type = IPV6_VERSION; 2791676Sjpk /* LINTED: following cast to ipaddr is OK */ 2801676Sjpk ipaddr = &((struct sockaddr_in6 *)addr->buf)->sin6_addr; 2811676Sjpk } else { 2821676Sjpk goto errout; 2831676Sjpk } 2841676Sjpk 2851676Sjpk tp = find_tpc(ipaddr, addr_type, B_FALSE); 2861676Sjpk if (tp == NULL) 2871676Sjpk goto errout; 2881676Sjpk 2891676Sjpk if (tp->tpc_tp.host_type == SUN_CIPSO) { 2901676Sjpk TPC_RELE(tp); 2911676Sjpk return (getflabel_cipso(vfsp)); 2921676Sjpk } 2931676Sjpk 2941676Sjpk if (tp->tpc_tp.host_type != UNLABELED) 2951676Sjpk goto errout; 2961676Sjpk 2971676Sjpk server_sl = &tp->tpc_tp.tp_def_label; 2981676Sjpk srv_label = labelalloc(server_sl, default_doi, KM_SLEEP); 2991676Sjpk 3001676Sjpk TPC_RELE(tp); 3011676Sjpk 3021676Sjpk return (srv_label); 3031676Sjpk 3041676Sjpk errout: 3051676Sjpk return (NULL); 3061676Sjpk } 3071676Sjpk 3081676Sjpk /* 3091676Sjpk * getflabel - 3101676Sjpk * 3111676Sjpk * Return pointer to the ts_label associated with the specified file, 3121676Sjpk * or returns NULL if error occurs. Caller is responsible for doing 3131676Sjpk * a label_rele of the ts_label. 3141676Sjpk */ 3151676Sjpk ts_label_t * 3161676Sjpk getflabel(vnode_t *vp) 3171676Sjpk { 3181799Sgfaden vfs_t *vfsp, *rvfsp; 3191676Sjpk vnode_t *rvp, *rvp2; 3201676Sjpk zone_t *zone; 3211676Sjpk ts_label_t *zl; 3221676Sjpk boolean_t vfs_is_held = B_FALSE; 3231676Sjpk char vpath[MAXPATHLEN]; 3241676Sjpk 3251676Sjpk ASSERT(vp); 3261799Sgfaden vfsp = vp->v_vfsp; 3271676Sjpk if (vfsp == NULL) 3281676Sjpk return (NULL); 3291676Sjpk 3301799Sgfaden rvp = vp; 3311676Sjpk 3321676Sjpk /* 3331799Sgfaden * Traverse lofs mounts and fattach'es to get the real vnode 3341676Sjpk */ 3355331Samw if (VOP_REALVP(rvp, &rvp2, NULL) == 0) 3361676Sjpk rvp = rvp2; 3371676Sjpk 3381799Sgfaden rvfsp = rvp->v_vfsp; 3391676Sjpk 3401676Sjpk /* rvp/rvfsp now represent the real vnode/vfs we will be using */ 3411676Sjpk 3421676Sjpk /* Go elsewhere to handle all nfs files. */ 3431676Sjpk if (strncmp(vfssw[rvfsp->vfs_fstype].vsw_name, "nfs", 3) == 0) 3441676Sjpk return (getflabel_nfs(rvfsp)); 3451676Sjpk 3461676Sjpk /* 3471676Sjpk * Fast path, for objects in a labeled zone: everything except 3481676Sjpk * for lofs/nfs will be just the label of that zone. 3491676Sjpk */ 3501676Sjpk if ((rvfsp->vfs_zone != NULL) && (rvfsp->vfs_zone != global_zone)) { 3511676Sjpk if ((strcmp(vfssw[rvfsp->vfs_fstype].vsw_name, 3521676Sjpk "lofs") != 0)) { 3531676Sjpk zone = rvfsp->vfs_zone; 3541676Sjpk zone_hold(zone); 3551676Sjpk goto zone_out; /* return this label */ 3561676Sjpk } 3571676Sjpk } 3581676Sjpk 3591799Sgfaden if (vnodetopath(rootdir, rvp, vpath, sizeof (vpath), kcred) != 0) { 3601799Sgfaden return (NULL); 3611676Sjpk } 3621676Sjpk 3631676Sjpk /* 3641799Sgfaden * Sanity check - vpath may be weird for some cases, like devices. 3651676Sjpk */ 3661799Sgfaden if (*vpath != '/') { 3671799Sgfaden zone = curproc->p_zone; 3681799Sgfaden zone_hold(zone); 3691799Sgfaden goto zone_out; 3701676Sjpk } 3711676Sjpk 3722194Srica /* 373*12236SRic.Aleshire@Sun.COM * For zfs filesystem, return the explicit label property if a 374*12236SRic.Aleshire@Sun.COM * meaningful one exists. 375*12236SRic.Aleshire@Sun.COM */ 376*12236SRic.Aleshire@Sun.COM if (strncmp(vfssw[rvfsp->vfs_fstype].vsw_name, "zfs", 3) == 0) { 377*12236SRic.Aleshire@Sun.COM ts_label_t *tsl; 378*12236SRic.Aleshire@Sun.COM 379*12236SRic.Aleshire@Sun.COM tsl = getflabel_zfs(rvfsp); 380*12236SRic.Aleshire@Sun.COM 381*12236SRic.Aleshire@Sun.COM /* if label found, return it, otherwise continue... */ 382*12236SRic.Aleshire@Sun.COM if (tsl != NULL) 383*12236SRic.Aleshire@Sun.COM return (tsl); 384*12236SRic.Aleshire@Sun.COM } 385*12236SRic.Aleshire@Sun.COM 386*12236SRic.Aleshire@Sun.COM /* 3872194Srica * If a mountpoint exists, hold the vfs while we reference it. 3882194Srica * Otherwise if mountpoint is NULL it should not be held (e.g., 3892194Srica * a hold/release on spec_vfs would result in an attempted free 3902194Srica * and panic.) 3912194Srica */ 3922194Srica if (vfsp->vfs_mntpt != NULL) { 3932194Srica VFS_HOLD(vfsp); 3942194Srica vfs_is_held = B_TRUE; 3952194Srica } 3961676Sjpk 3971799Sgfaden zone = zone_find_by_any_path(vpath, B_FALSE); 3981676Sjpk 3991676Sjpk /* 4001799Sgfaden * If the vnode source zone is properly set to a non-global zone, or 4011676Sjpk * any zone if the mount is R/W, then use the label of that zone. 4021676Sjpk */ 4031676Sjpk if ((zone != global_zone) || ((vfsp->vfs_flag & VFS_RDONLY) != 0)) 4041676Sjpk goto zone_out; /* return this label */ 4051676Sjpk 4061676Sjpk /* 4071676Sjpk * Otherwise, if we're not in the global zone, use the label of 4081676Sjpk * our zone. 4091676Sjpk */ 4101676Sjpk if ((zone = curproc->p_zone) != global_zone) { 4111676Sjpk zone_hold(zone); 4121676Sjpk goto zone_out; /* return this label */ 4131676Sjpk } 4141676Sjpk 4151676Sjpk /* 4161676Sjpk * We're in the global zone and the mount is R/W ... so the file 4171676Sjpk * may actually be in the global zone -- or in the root of any zone. 4181676Sjpk * Always build our own path for the file, to be sure it's simplified 4191676Sjpk * (i.e., no ".", "..", "//", and so on). 4201676Sjpk */ 4211676Sjpk 4221676Sjpk zone_rele(zone); 4231676Sjpk zone = zone_find_by_any_path(vpath, B_FALSE); 4241676Sjpk 4251676Sjpk zone_out: 4261676Sjpk if ((curproc->p_zone == global_zone) && (zone == global_zone)) { 4271676Sjpk vfs_t *nvfs; 4281676Sjpk boolean_t exported = B_FALSE; 4291676Sjpk refstr_t *mntpt_ref; 4301676Sjpk char *mntpt; 4311676Sjpk 4321676Sjpk /* 4331676Sjpk * File is in the global zone - check whether it's admin_high. 4341676Sjpk * If it's in a filesys that was exported from the global zone, 4351676Sjpk * it's admin_low by definition. Otherwise, if it's in a 4361676Sjpk * filesys that's NOT exported to any zone, it's admin_high. 4371676Sjpk * 4381676Sjpk * And for these files if there wasn't a valid mount resource, 4391676Sjpk * the file must be admin_high (not exported, probably a global 4401676Sjpk * zone device). 4411676Sjpk */ 4421676Sjpk if (!vfs_is_held) 4431676Sjpk goto out_high; 4441676Sjpk 4451676Sjpk mntpt_ref = vfs_getmntpoint(vfsp); 4461676Sjpk mntpt = (char *)refstr_value(mntpt_ref); 4471676Sjpk 4481676Sjpk if ((mntpt != NULL) && (*mntpt == '/')) { 4491676Sjpk zone_t *to_zone; 4501676Sjpk 4511676Sjpk to_zone = zone_find_by_any_path(mntpt, B_FALSE); 4521676Sjpk zone_rele(to_zone); 4531676Sjpk if (to_zone != global_zone) { 4541676Sjpk /* force admin_low */ 4551676Sjpk exported = B_TRUE; 4561676Sjpk } 4571676Sjpk } 4581676Sjpk if (mntpt_ref) 4591676Sjpk refstr_rele(mntpt_ref); 4601676Sjpk 4611676Sjpk if (!exported) { 4621676Sjpk size_t plen = strlen(vpath); 4631676Sjpk 4641676Sjpk vfs_list_read_lock(); 4651676Sjpk nvfs = vfsp->vfs_next; 4661676Sjpk while (nvfs != vfsp) { 4671676Sjpk const char *rstr; 4681676Sjpk size_t rlen = 0; 4691676Sjpk 470*12236SRic.Aleshire@Sun.COM /* 471*12236SRic.Aleshire@Sun.COM * Skip checking this vfs if it's not lofs 472*12236SRic.Aleshire@Sun.COM * (the only way to export from the global 473*12236SRic.Aleshire@Sun.COM * zone to a zone). 474*12236SRic.Aleshire@Sun.COM */ 475*12236SRic.Aleshire@Sun.COM if (strncmp(vfssw[nvfs->vfs_fstype].vsw_name, 476*12236SRic.Aleshire@Sun.COM "lofs", 4) != 0) { 477*12236SRic.Aleshire@Sun.COM nvfs = nvfs->vfs_next; 478*12236SRic.Aleshire@Sun.COM continue; 479*12236SRic.Aleshire@Sun.COM } 480*12236SRic.Aleshire@Sun.COM 4811676Sjpk rstr = refstr_value(nvfs->vfs_resource); 4821676Sjpk if (rstr != NULL) 4831676Sjpk rlen = strlen(rstr); 4841676Sjpk 4851676Sjpk /* 4861676Sjpk * Check for a match: does this vfs correspond 4871676Sjpk * to our global zone file path? I.e., check 4881676Sjpk * if the resource string of this vfs is a 4891676Sjpk * prefix of our path. 4901676Sjpk */ 4911676Sjpk if ((rlen > 0) && (rlen <= plen) && 4921676Sjpk (strncmp(rstr, vpath, rlen) == 0) && 4931676Sjpk (vpath[rlen] == '/' || 4941676Sjpk vpath[rlen] == '\0')) { 4951676Sjpk /* force admin_low */ 4961676Sjpk exported = B_TRUE; 4971676Sjpk break; 4981676Sjpk } 4991676Sjpk nvfs = nvfs->vfs_next; 5001676Sjpk } 5011676Sjpk vfs_list_unlock(); 5021676Sjpk } 5031676Sjpk 5041676Sjpk if (!exported) 5051676Sjpk goto out_high; 5061676Sjpk } 5071676Sjpk 5081676Sjpk if (vfs_is_held) 5091676Sjpk VFS_RELE(vfsp); 5101676Sjpk 5111676Sjpk /* 5121676Sjpk * Now that we have the "home" zone for the file, return the slabel 5131676Sjpk * of that zone. 5141676Sjpk */ 5151676Sjpk zl = zone->zone_slabel; 5161676Sjpk label_hold(zl); 5171676Sjpk zone_rele(zone); 5181676Sjpk return (zl); 5191676Sjpk 5201676Sjpk out_high: 5211676Sjpk if (vfs_is_held) 5221676Sjpk VFS_RELE(vfsp); 5231676Sjpk 5241676Sjpk label_hold(l_admin_high); 5251676Sjpk zone_rele(zone); 5261676Sjpk return (l_admin_high); 5271676Sjpk } 5281676Sjpk 5291676Sjpk static int 5301676Sjpk cgetlabel(bslabel_t *label_p, vnode_t *vp) 5311676Sjpk { 5321676Sjpk ts_label_t *tsl; 5331676Sjpk int error = 0; 5341676Sjpk 5351676Sjpk if ((tsl = getflabel(vp)) == NULL) 5361676Sjpk return (EIO); 5371676Sjpk 5381676Sjpk if (copyout((caddr_t)label2bslabel(tsl), (caddr_t)label_p, 5391676Sjpk sizeof (*(label_p))) != 0) 5401676Sjpk error = EFAULT; 5411676Sjpk 5421676Sjpk label_rele(tsl); 5431676Sjpk return (error); 5441676Sjpk } 5451676Sjpk 5461676Sjpk /* 5471676Sjpk * fgetlabel(2TSOL) - get file label 5481676Sjpk * getlabel(2TSOL) - get file label 5491676Sjpk */ 5501676Sjpk int 5511676Sjpk getlabel(const char *path, bslabel_t *label_p) 5521676Sjpk { 5531676Sjpk struct vnode *vp; 5541676Sjpk char *spath; 5551676Sjpk int error; 5561676Sjpk 5571676Sjpk /* Sanity check arguments */ 5581676Sjpk if (path == NULL) 5591676Sjpk return (set_errno(EINVAL)); 5601676Sjpk 5611676Sjpk spath = kmem_zalloc(MAXPATHLEN, KM_SLEEP); 5621676Sjpk if ((error = copyinstr(path, spath, MAXPATHLEN, NULL)) != 0) { 5631676Sjpk kmem_free(spath, MAXPATHLEN); 5641676Sjpk return (set_errno(error)); 5651676Sjpk } 5661676Sjpk 5671676Sjpk if (error = lookupname(spath, UIO_SYSSPACE, FOLLOW, NULLVPP, &vp)) { 5681676Sjpk kmem_free(spath, MAXPATHLEN); 5691676Sjpk return (set_errno(error)); 5701676Sjpk } 5711676Sjpk kmem_free(spath, MAXPATHLEN); 5721676Sjpk 5731676Sjpk error = cgetlabel(label_p, vp); 5741676Sjpk 5751676Sjpk VN_RELE(vp); 5761676Sjpk if (error != 0) 5771676Sjpk return (set_errno(error)); 5781676Sjpk else 5791676Sjpk return (0); 5801676Sjpk } 5811676Sjpk 5821676Sjpk int 5831676Sjpk fgetlabel(int fd, bslabel_t *label_p) 5841676Sjpk { 5851676Sjpk file_t *fp; 5861676Sjpk int error; 5871676Sjpk 5881676Sjpk if ((fp = getf(fd)) == NULL) 5891676Sjpk return (set_errno(EBADF)); 5901676Sjpk 5911676Sjpk error = cgetlabel(label_p, fp->f_vnode); 5921676Sjpk releasef(fd); 5931676Sjpk 5941676Sjpk if (error != 0) 5951676Sjpk return (set_errno(error)); 5961676Sjpk else 5971676Sjpk return (0); 5981676Sjpk } 599