/* * Get the label if any of a zfs filesystem. Get the dataset, then * get its mlslabel property, convert as needed, and return it. If * there's no mlslabel or it is the default one, return NULL. */ static ts_label_t * getflabel_zfs(vfs_t *vfsp) { int error; ts_label_t *tsl = NULL; refstr_t *resource_ref; bslabel_t ds_sl; char ds_hexsl[MAXNAMELEN]; const char *osname; resource_ref = vfs_getresource(vfsp); osname = refstr_value(resource_ref); error = dsl_prop_get(osname, zfs_prop_to_name(ZFS_PROP_MLSLABEL), 1, sizeof (ds_hexsl), &ds_hexsl, NULL); refstr_rele(resource_ref); if ((error) || (strcasecmp(ds_hexsl, ZFS_MLSLABEL_DEFAULT) == 0)) return (NULL); if (hexstr_to_label(ds_hexsl, &ds_sl) != 0) return (NULL); tsl = labelalloc(&ds_sl, default_doi, KM_SLEEP); return (tsl); }
/* * There's no protocol today to obtain the label from the server. * So we rely on conventions: zones, zone names, and zone paths * must match across TX servers and their TX clients. Now use * the exported name to find the equivalent local zone and its * label. Caller is responsible for doing a label_rele of the * returned ts_label. */ ts_label_t * getflabel_cipso(vfs_t *vfsp) { zone_t *reszone; zone_t *new_reszone; char *nfspath, *respath; refstr_t *resource_ref; boolean_t treat_abs = B_FALSE; if (vfsp->vfs_resource == NULL) return (NULL); /* error */ resource_ref = vfs_getresource(vfsp); nfspath = (char *)refstr_value(resource_ref); respath = strchr(nfspath, ':'); /* skip server name */ if (respath) respath++; /* skip over ":" */ if (*respath != '/') { /* treat path as absolute but it doesn't have leading '/' */ treat_abs = B_TRUE; } reszone = zone_find_by_any_path(respath, treat_abs); if (reszone == global_zone) { refstr_rele(resource_ref); label_hold(l_admin_low); zone_rele(reszone); return (l_admin_low); } /* * Skip over zonepath (not including "root"), e.g. /zone/internal */ respath += reszone->zone_rootpathlen - 7; if (treat_abs) respath--; /* no leading '/' to skip */ if (strncmp(respath, "/root/", 6) == 0) { /* Check if we now have something like "/zone/public/" */ respath += 5; /* skip "/root" first */ new_reszone = zone_find_by_any_path(respath, B_FALSE); if (new_reszone != global_zone) { zone_rele(reszone); reszone = new_reszone; } else { zone_rele(new_reszone); } } refstr_rele(resource_ref); label_hold(reszone->zone_slabel); zone_rele(reszone); return (reszone->zone_slabel); }
static void zfsctl_rename_snap(zfsctl_snapdir_t *sdp, zfs_snapentry_t *sep, const char *nm) { avl_index_t where; vfs_t *vfsp; refstr_t *pathref; char newpath[MAXNAMELEN]; char *tail; ASSERT(MUTEX_HELD(&sdp->sd_lock)); ASSERT(sep != NULL); vfsp = vn_mountedvfs(sep->se_root); ASSERT(vfsp != NULL); vfs_lock_wait(vfsp); /* * Change the name in the AVL tree. */ avl_remove(&sdp->sd_snaps, sep); kmem_free(sep->se_name, strlen(sep->se_name) + 1); sep->se_name = kmem_alloc(strlen(nm) + 1, KM_SLEEP); (void) strcpy(sep->se_name, nm); VERIFY(avl_find(&sdp->sd_snaps, sep, &where) == NULL); avl_insert(&sdp->sd_snaps, sep, where); /* * Change the current mountpoint info: * - update the tail of the mntpoint path * - update the tail of the resource path */ pathref = vfs_getmntpoint(vfsp); (void) strncpy(newpath, refstr_value(pathref), sizeof (newpath)); VERIFY((tail = strrchr(newpath, '/')) != NULL); *(tail+1) = '\0'; ASSERT3U(strlen(newpath) + strlen(nm), <, sizeof (newpath)); (void) strcat(newpath, nm); refstr_rele(pathref); vfs_setmntpoint(vfsp, newpath); pathref = vfs_getresource(vfsp); (void) strncpy(newpath, refstr_value(pathref), sizeof (newpath)); VERIFY((tail = strrchr(newpath, '@')) != NULL); *(tail+1) = '\0'; ASSERT3U(strlen(newpath) + strlen(nm), <, sizeof (newpath)); (void) strcat(newpath, nm); refstr_rele(pathref); vfs_setresource(vfsp, newpath); vfs_unlock(vfsp); }