tlabel.c revision 45916cd2fec6e79bca5dee0421bd39e3c2910d1e
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * CDDL HEADER START
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * The contents of this file are subject to the terms of the
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Common Development and Distribution License (the "License").
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * You may not use this file except in compliance with the License.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * See the License for the specific language governing permissions
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * and limitations under the License.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * When distributing Covered Code, include this CDDL HEADER in each
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * If applicable, add the following below this CDDL HEADER, with the
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * fields enclosed by brackets "[]" replaced with your own identifying
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * information: Portions Copyright [yyyy] [name of copyright owner]
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * CDDL HEADER END
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Use is subject to license terms.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#pragma ident "%Z%%M% %I% %E% SMI"
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Initialize labels infrastructure.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * This is called during startup() time (before vfs_mntroot) by thread_init().
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * It has to be called early so that the is_system_labeled() function returns
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * the right value when called by the networking code on a diskless boot.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Use the value of "label_services" within the edition module.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * If for some reason label_services is not found, this will
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * result in the appropriate default -- "off."
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tslabel_cache = kmem_cache_create("tslabel_cache", sizeof (ts_label_t),
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk l_admin_low = labelalloc(&label, default_doi, KM_SLEEP);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk l_admin_high = labelalloc(&label, default_doi, KM_SLEEP);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Allocate new ts_label_t.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ts_label_t *lab = kmem_cache_alloc(tslabel_cache, flag);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Put a hold on a label structure.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Release previous hold on a label structure. Free it if refcnt == 0.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Compare labels. Return 1 if equal, 0 otherwise.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * There's no protocol today to obtain the label from the server.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * So we rely on conventions: zones, zone names, and zone paths
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * must match across TX servers and their TX clients. Now use
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * the exported name to find the equivalent local zone and its
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * label. Caller is responsible for doing a label_rele of the
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * returned ts_label.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* treat path as absolute but it doesn't have leading '/' */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Skip over zonepath (not including "root"), e.g. /zone/internal
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* Check if we now have something like "/zone/public/" */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* LINTED: following cast to ipaddr is OK */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk } else if (strcmp(knconf->knc_protofmly, NC_INET6) == 0) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* LINTED: following cast to ipaddr is OK */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ipaddr = &((struct sockaddr_in6 *)addr->buf)->sin6_addr;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk srv_label = labelalloc(server_sl, default_doi, KM_SLEEP);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * getflabel -
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Return pointer to the ts_label associated with the specified file,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * or returns NULL if error occurs. Caller is responsible for doing
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * a label_rele of the ts_label.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Get rid of all but the last loopback vfs, since the last such mount
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * has the correct resource to use (except for nfs case, handled later).
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk while (strcmp(vfssw[nvfs->vfs_fstype].vsw_name, "lofs") == 0) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * rvp/rvfsp now represent the preliminary vnode/vfs we may use. Now
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * check if the next vfs is nfs; if so, then it has the correct info
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * to use. And finally, for some cases on loop-back mounts there will
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * be no resource; for these, use the underlying vfs also.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (strcmp(vfssw[rvfsp->vfs_fstype].vsw_name, "lofs") == 0) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ((strcmp(vfssw[nvfs->vfs_fstype].vsw_name, "nfs") == 0)) ||
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* rvp/rvfsp now represent the real vnode/vfs we will be using */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* Go elsewhere to handle all nfs files. */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (strncmp(vfssw[rvfsp->vfs_fstype].vsw_name, "nfs", 3) == 0)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Fast path, for objects in a labeled zone: everything except
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * for lofs/nfs will be just the label of that zone.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if ((rvfsp->vfs_zone != NULL) && (rvfsp->vfs_zone != global_zone)) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk "lofs") != 0)) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Sanity check - resource may be weird for some cases, like devices.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * In this case, the label must be "local", so just use the mount point.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * If the vfs source zone is properly set to a non-global zone, or
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * any zone if the mount is R/W, then use the label of that zone.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if ((zone != global_zone) || ((vfsp->vfs_flag & VFS_RDONLY) != 0))
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Otherwise, if we're not in the global zone, use the label of
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * our zone.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * We're in the global zone and the mount is R/W ... so the file
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * may actually be in the global zone -- or in the root of any zone.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Always build our own path for the file, to be sure it's simplified
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * (i.e., no ".", "..", "//", and so on).
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (vnodetopath(NULL, vp, vpath, sizeof (vpath), CRED()) != 0) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if ((curproc->p_zone == global_zone) && (zone == global_zone)) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * File is in the global zone - check whether it's admin_high.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * If it's in a filesys that was exported from the global zone,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * it's admin_low by definition. Otherwise, if it's in a
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * filesys that's NOT exported to any zone, it's admin_high.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * And for these files if there wasn't a valid mount resource,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * the file must be admin_high (not exported, probably a global
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * zone device).
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* force admin_low */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk const char *rstr;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Check for a match: does this vfs correspond
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * to our global zone file path? I.e., check
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * if the resource string of this vfs is a
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * prefix of our path.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* force admin_low */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Now that we have the "home" zone for the file, return the slabel
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * of that zone.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (copyout((caddr_t)label2bslabel(tsl), (caddr_t)label_p,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk sizeof (*(label_p))) != 0)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * fgetlabel(2TSOL) - get file label
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * getlabel(2TSOL) - get file label
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* Sanity check arguments */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if ((error = copyinstr(path, spath, MAXPATHLEN, NULL)) != 0) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (error = lookupname(spath, UIO_SYSSPACE, FOLLOW, NULLVPP, &vp)) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (0);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (0);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Used by NFSv4 to query label of a pathname
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * component during lookup/access ops.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * mount traverse has been done by caller
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * before calling this routine.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * v_path not cached. Since we rely on path
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * of an obj to get its label, we need to get
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * path corresponding to the parent vnode.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Caller has verified that the file is either
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * exported or visible. So if the path falls in
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * global zone, admin_low is returned; otherwise
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * the zone's label is returned.