tlabel.c revision 45916cd2fec6e79bca5dee0421bd39e3c2910d1e
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * CDDL HEADER START
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
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 *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * or http://www.opensolaris.org/os/licensing.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * See the License for the specific language governing permissions
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * and limitations under the License.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
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 *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * CDDL HEADER END
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Use is subject to license terms.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#pragma ident "%Z%%M% %I% %E% SMI"
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <sys/types.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <sys/param.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <sys/cmn_err.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <sys/systm.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <sys/cred.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <sys/modctl.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <sys/vfs.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <sys/vnode.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <sys/tiuser.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <sys/kmem.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <sys/pathname.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <sys/zone.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <sys/tsol/label.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <sys/tsol/tnet.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <sys/fs/lofs_node.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <inet/ip6.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <rpc/auth.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <rpc/clnt.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <nfs/nfs.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <nfs/nfs4.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <nfs/nfs_clnt.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#include <sys/dnlc.h>
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkint sys_labeling = -1; /* initially unset */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkstatic kmem_cache_t *tslabel_cache;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkts_label_t *l_admin_low;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkts_label_t *l_admin_high;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkuint32_t default_doi = DEFAULT_DOI;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/*
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 */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkvoid
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpklabel_init(void)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk bslabel_t label;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
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 */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (modgetsymvalue("label_services", B_FALSE) != 0)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk sys_labeling = 1;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk else
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk sys_labeling = 0;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tslabel_cache = kmem_cache_create("tslabel_cache", sizeof (ts_label_t),
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk 0, NULL, NULL, NULL, NULL, NULL, 0);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk bsllow(&label);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk l_admin_low = labelalloc(&label, default_doi, KM_SLEEP);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk bslhigh(&label);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk l_admin_high = labelalloc(&label, default_doi, KM_SLEEP);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Allocate new ts_label_t.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkts_label_t *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpklabelalloc(const bslabel_t *val, uint32_t doi, int flag)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ts_label_t *lab = kmem_cache_alloc(tslabel_cache, flag);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (lab != NULL) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk lab->tsl_ref = 1;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk lab->tsl_doi = doi;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (val == NULL)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk bzero(&lab->tsl_label, sizeof (bslabel_t));
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk else
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk bcopy(val, &lab->tsl_label, sizeof (bslabel_t));
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (lab);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Put a hold on a label structure.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkvoid
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpklabel_hold(ts_label_t *lab)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk atomic_add_32(&lab->tsl_ref, 1);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Release previous hold on a label structure. Free it if refcnt == 0.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkvoid
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpklabel_rele(ts_label_t *lab)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (atomic_add_32_nv(&lab->tsl_ref, -1) == 0)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk kmem_cache_free(tslabel_cache, lab);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkbslabel_t *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpklabel2bslabel(ts_label_t *lab)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (&lab->tsl_label);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkuint32_t
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpklabel2doi(ts_label_t *lab)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (lab->tsl_doi);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Compare labels. Return 1 if equal, 0 otherwise.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkboolean_t
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpklabel_equal(const ts_label_t *l1, const ts_label_t *l2)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return ((l1->tsl_doi == l2->tsl_doi) &&
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk blequal(&l1->tsl_label, &l2->tsl_label));
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/*
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 */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkts_label_t *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkgetflabel_cipso(vfs_t *vfsp)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk zone_t *reszone;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk zone_t *new_reszone;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk char *nfspath, *respath;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk refstr_t *resource_ref;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk boolean_t treat_abs = B_FALSE;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (vfsp->vfs_resource == NULL)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (NULL); /* error */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk resource_ref = vfs_getresource(vfsp);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk nfspath = (char *)refstr_value(resource_ref);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk respath = strchr(nfspath, ':'); /* skip server name */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (respath)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk respath++; /* skip over ":" */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (*respath != '/') {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* treat path as absolute but it doesn't have leading '/' */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk treat_abs = B_TRUE;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk reszone = zone_find_by_any_path(respath, treat_abs);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (reszone == global_zone) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk refstr_rele(resource_ref);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk label_hold(l_admin_low);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk zone_rele(reszone);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (l_admin_low);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Skip over zonepath (not including "root"), e.g. /zone/internal
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk respath += reszone->zone_rootpathlen - 7;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (treat_abs)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk respath--; /* no leading '/' to skip */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (strncmp(respath, "/root/", 6) == 0) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* Check if we now have something like "/zone/public/" */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk respath += 5; /* skip "/root" first */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk new_reszone = zone_find_by_any_path(respath, B_FALSE);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (new_reszone != global_zone) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk zone_rele(reszone);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk reszone = new_reszone;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk } else {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk zone_rele(new_reszone);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk refstr_rele(resource_ref);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk label_hold(reszone->zone_slabel);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk zone_rele(reszone);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (reszone->zone_slabel);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkstatic ts_label_t *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkgetflabel_nfs(vfs_t *vfsp)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk bslabel_t *server_sl;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ts_label_t *srv_label;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tsol_tpc_t *tp;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk int addr_type;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk void *ipaddr;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk struct servinfo *svp;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk struct netbuf *addr;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk struct knetconfig *knconf;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mntinfo_t *mi;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mi = VFTOMI(vfsp);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk svp = mi->mi_curr_serv;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk addr = &svp->sv_addr;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk knconf = svp->sv_knconf;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (strcmp(knconf->knc_protofmly, NC_INET) == 0) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk addr_type = IPV4_VERSION;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* LINTED: following cast to ipaddr is OK */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ipaddr = &((struct sockaddr_in *)addr->buf)->sin_addr;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk } else if (strcmp(knconf->knc_protofmly, NC_INET6) == 0) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk addr_type = IPV6_VERSION;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* LINTED: following cast to ipaddr is OK */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ipaddr = &((struct sockaddr_in6 *)addr->buf)->sin6_addr;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk } else {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk goto errout;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tp = find_tpc(ipaddr, addr_type, B_FALSE);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (tp == NULL)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk goto errout;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (tp->tpc_tp.host_type == SUN_CIPSO) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk TPC_RELE(tp);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (getflabel_cipso(vfsp));
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (tp->tpc_tp.host_type != UNLABELED)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk goto errout;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk server_sl = &tp->tpc_tp.tp_def_label;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk srv_label = labelalloc(server_sl, default_doi, KM_SLEEP);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk TPC_RELE(tp);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (srv_label);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkerrout:
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (NULL);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * getflabel -
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk *
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 */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkts_label_t *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkgetflabel(vnode_t *vp)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk vfs_t *vfsp, *rvfsp, *nvfs;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk vnode_t *rvp, *rvp2;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk zone_t *zone;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ts_label_t *zl;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk boolean_t vfs_is_held = B_FALSE;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk refstr_t *resource_ref = NULL;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk char *resource = NULL;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk char vpath[MAXPATHLEN];
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT(vp);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk vfsp = rvfsp = nvfs = vp->v_vfsp;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (vfsp == NULL)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (NULL);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk rvp = rvp2 = vp;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
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 */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk while (strcmp(vfssw[nvfs->vfs_fstype].vsw_name, "lofs") == 0) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk rvp = rvp2;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk rvfsp = nvfs;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if ((rvp2 = realvp(rvp)) == NULL)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk break;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (((nvfs = rvp2->v_vfsp) == NULL) || (nvfs == rvfsp))
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk break;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
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 */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (strcmp(vfssw[rvfsp->vfs_fstype].vsw_name, "lofs") == 0) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (((rvp2 = realvp(rvp)) != NULL) &&
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ((nvfs = rvp2->v_vfsp) != NULL) &&
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ((strcmp(vfssw[nvfs->vfs_fstype].vsw_name, "nfs") == 0)) ||
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk (rvfsp->vfs_resource == NULL)) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk rvp = rvp2;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk rvfsp = nvfs;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* rvp/rvfsp now represent the real vnode/vfs we will be using */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* Go elsewhere to handle all nfs files. */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (strncmp(vfssw[rvfsp->vfs_fstype].vsw_name, "nfs", 3) == 0)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (getflabel_nfs(rvfsp));
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Fast path, for objects in a labeled zone: everything except
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * for lofs/nfs will be just the label of that zone.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if ((rvfsp->vfs_zone != NULL) && (rvfsp->vfs_zone != global_zone)) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if ((strcmp(vfssw[rvfsp->vfs_fstype].vsw_name,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk "lofs") != 0)) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk zone = rvfsp->vfs_zone;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk zone_hold(zone);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk goto zone_out; /* return this label */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (rvfsp->vfs_resource) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk resource_ref = vfs_getresource(rvfsp);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk resource = (char *)refstr_value(resource_ref);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
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 */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if ((resource == NULL) || (*resource != '/')) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (resource_ref)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk refstr_rele(resource_ref);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (rvfsp->vfs_mntpt) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk resource_ref = vfs_getmntpoint(rvfsp);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk resource = (char *)refstr_value(resource_ref);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if ((resource == NULL) || (*resource != '/')) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk zone = curproc->p_zone;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk zone_hold(zone);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk goto zone_out;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk VFS_HOLD(vfsp);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk vfs_is_held = B_TRUE;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk zone = zone_find_by_any_path(resource, B_FALSE);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
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 */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if ((zone != global_zone) || ((vfsp->vfs_flag & VFS_RDONLY) != 0))
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk goto zone_out; /* return this label */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Otherwise, if we're not in the global zone, use the label of
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * our zone.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if ((zone = curproc->p_zone) != global_zone) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk zone_hold(zone);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk goto zone_out; /* return this label */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
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 */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (vnodetopath(NULL, vp, vpath, sizeof (vpath), CRED()) != 0) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (vfs_is_held)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk VFS_RELE(vfsp);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (resource_ref)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk refstr_rele(resource_ref);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk zone_rele(zone);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (NULL);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk zone_rele(zone);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk zone = zone_find_by_any_path(vpath, B_FALSE);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkzone_out:
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if ((curproc->p_zone == global_zone) && (zone == global_zone)) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk vfs_t *nvfs;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk boolean_t exported = B_FALSE;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk refstr_t *mntpt_ref;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk char *mntpt;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
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 *
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 */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (!vfs_is_held)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk goto out_high;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mntpt_ref = vfs_getmntpoint(vfsp);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mntpt = (char *)refstr_value(mntpt_ref);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if ((mntpt != NULL) && (*mntpt == '/')) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk zone_t *to_zone;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk to_zone = zone_find_by_any_path(mntpt, B_FALSE);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk zone_rele(to_zone);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (to_zone != global_zone) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* force admin_low */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk exported = B_TRUE;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (mntpt_ref)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk refstr_rele(mntpt_ref);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (!exported) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk size_t plen = strlen(vpath);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk vfs_list_read_lock();
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk nvfs = vfsp->vfs_next;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk while (nvfs != vfsp) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk const char *rstr;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk size_t rlen = 0;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk rstr = refstr_value(nvfs->vfs_resource);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (rstr != NULL)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk rlen = strlen(rstr);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
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 */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if ((rlen > 0) && (rlen <= plen) &&
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk (strncmp(rstr, vpath, rlen) == 0) &&
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk (vpath[rlen] == '/' ||
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk vpath[rlen] == '\0')) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* force admin_low */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk exported = B_TRUE;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk break;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk nvfs = nvfs->vfs_next;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk vfs_list_unlock();
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (!exported)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk goto out_high;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (vfs_is_held)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk VFS_RELE(vfsp);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (resource_ref)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk refstr_rele(resource_ref);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Now that we have the "home" zone for the file, return the slabel
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * of that zone.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk zl = zone->zone_slabel;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk label_hold(zl);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk zone_rele(zone);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (zl);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkout_high:
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (vfs_is_held)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk VFS_RELE(vfsp);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (resource_ref)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk refstr_rele(resource_ref);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk label_hold(l_admin_high);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk zone_rele(zone);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (l_admin_high);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkstatic int
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkcgetlabel(bslabel_t *label_p, vnode_t *vp)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ts_label_t *tsl;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk int error = 0;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if ((tsl = getflabel(vp)) == NULL)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (EIO);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (copyout((caddr_t)label2bslabel(tsl), (caddr_t)label_p,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk sizeof (*(label_p))) != 0)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk error = EFAULT;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk label_rele(tsl);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (error);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * fgetlabel(2TSOL) - get file label
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * getlabel(2TSOL) - get file label
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkint
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkgetlabel(const char *path, bslabel_t *label_p)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk struct vnode *vp;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk char *spath;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk int error;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* Sanity check arguments */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (path == NULL)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (set_errno(EINVAL));
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk spath = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if ((error = copyinstr(path, spath, MAXPATHLEN, NULL)) != 0) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk kmem_free(spath, MAXPATHLEN);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (set_errno(error));
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (error = lookupname(spath, UIO_SYSSPACE, FOLLOW, NULLVPP, &vp)) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk kmem_free(spath, MAXPATHLEN);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (set_errno(error));
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk kmem_free(spath, MAXPATHLEN);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk error = cgetlabel(label_p, vp);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk VN_RELE(vp);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (error != 0)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (set_errno(error));
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk else
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (0);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkint
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkfgetlabel(int fd, bslabel_t *label_p)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk file_t *fp;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk int error;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if ((fp = getf(fd)) == NULL)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (set_errno(EBADF));
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk error = cgetlabel(label_p, fp->f_vnode);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk releasef(fd);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (error != 0)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (set_errno(error));
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk else
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (0);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Used by NFSv4 to query label of a pathname
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * component during lookup/access ops.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkts_label_t *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpknfs4_getflabel(vnode_t *vp)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk{
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk zone_t *zone;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ts_label_t *zone_label;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk char path[MAXNAMELEN];
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk vnode_t *pvp, *tvp;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mutex_enter(&vp->v_lock);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * mount traverse has been done by caller
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * before calling this routine.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk ASSERT(!vn_ismntpt(vp));
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (vp->v_path != NULL) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk zone = zone_find_by_any_path(vp->v_path, B_FALSE);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mutex_exit(&vp->v_lock);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk } else {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
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 */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tvp = vp;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk do {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mutex_exit(&tvp->v_lock);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if ((pvp = dnlc_reverse_lookup(tvp, path,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk sizeof (path))) == NULL)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (NULL);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mutex_enter(&pvp->v_lock);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk tvp = pvp;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk } while (pvp->v_path == NULL);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk zone = zone_find_by_any_path(pvp->v_path, B_FALSE);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk mutex_exit(&pvp->v_lock);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk }
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /*
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.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk zone_label = zone->zone_slabel;
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk label_hold(zone_label);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk zone_rele(zone);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk return (zone_label);
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk}