OpenSolaris_b135/lib/libtsol/common/zone.c

Compare this file to the similar file:
Show the results in this format:

/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#pragma ident	"%Z%%M%	%I%	%E% SMI"

#include	<stdlib.h>
#include	<strings.h>
#include	<zone.h>
#include	<errno.h>
#include	<sys/types.h>
#include 	<sys/tsol/label_macro.h>

/*
 * Get label from zone name
 */
m_label_t *
getzonelabelbyname(const char *zone)
{
	zoneid_t	zoneid;

	if ((zoneid = getzoneidbyname(zone)) == -1) {
		errno = EINVAL;
		return (NULL);
	}
	return (getzonelabelbyid(zoneid));
}

/*
 * Get label from zone id
 */
m_label_t *
getzonelabelbyid(zoneid_t zoneid)
{
	m_label_t 	*slabel;

	if ((slabel = m_label_alloc(MAC_LABEL)) == NULL)
		return (NULL);

	if (zone_getattr(zoneid, ZONE_ATTR_SLBL, slabel,
	    sizeof (m_label_t)) < 0) {
		m_label_free(slabel);
		errno = EINVAL;
		return (NULL);
	}

	return (slabel);
}

/*
 * Get zone id from label
 */

zoneid_t
getzoneidbylabel(const m_label_t *label)
{
	m_label_t	admin_low;
	m_label_t	admin_high;
	zoneid_t	zoneid;
	zoneid_t 	*zids;
	uint_t		nzents;
	uint_t		nzents_saved;
	int		i;

	bsllow(&admin_low);
	bslhigh(&admin_high);

	/* Check for admin_low or admin_high; both are global zone */
	if (blequal(label, &admin_low) || blequal(label, &admin_high))
		return (GLOBAL_ZONEID);

	nzents = 0;
	if (zone_list(NULL, &nzents) != 0)
		return (-1);

again:
	if (nzents == 0) {
		errno = EINVAL;
		return (-1);
	}

	/*
	 * Add a small amount of padding here to avoid spinning in a tight loop
	 * if there's a process running somewhere that's creating lots of zones
	 * all at once.
	 */
	nzents += 8;
	if ((zids = malloc(nzents * sizeof (zoneid_t))) == NULL)
		return (-1);
	nzents_saved = nzents;

	if (zone_list(zids, &nzents) != 0) {
		free(zids);
		return (-1);
	}
	if (nzents > nzents_saved) {
		/* list changed, try again */
		free(zids);
		goto again;
	}

	for (i = 0; i < nzents; i++) {
		m_label_t	test_sl;

		if (zids[i] == GLOBAL_ZONEID)
			continue;

		if (zone_getattr(zids[i], ZONE_ATTR_SLBL, &test_sl,
		    sizeof (m_label_t)) < 0)
			continue;	/* Badly configured zone info */

		if (blequal(label, &test_sl) != 0) {
			zoneid = zids[i];
			free(zids);
			return (zoneid);
		}
	}
	free(zids);
	errno = EINVAL;
	return (-1);
}

/*
 * Get zoneroot for a zoneid
 */

char *
getzonerootbyid(zoneid_t zoneid)
{
	char zoneroot[MAXPATHLEN];

	if (zone_getattr(zoneid, ZONE_ATTR_ROOT, zoneroot,
	    sizeof (zoneroot)) == -1) {
		return (NULL);
	}

	return (strdup(zoneroot));
}

/*
 * Get zoneroot for a zonename
 */

char *
getzonerootbyname(const char *zone)
{
	zoneid_t	zoneid;

	if ((zoneid = getzoneidbyname(zone)) == -1)
		return (NULL);
	return (getzonerootbyid(zoneid));
}

/*
 * Get zoneroot for a label
 */

char *
getzonerootbylabel(const m_label_t *label)
{
	zoneid_t	zoneid;

	if ((zoneid = getzoneidbylabel(label)) == -1)
		return (NULL);
	return (getzonerootbyid(zoneid));
}

/*
 * Get label of path relative to global zone
 *
 * This function must be called from the global zone
 */

m_label_t *
getlabelbypath(const char *path)
{
	m_label_t	*slabel;
	zoneid_t 	*zids;
	uint_t		nzents;
	uint_t		nzents_saved;
	int		i;

	if (getzoneid() != GLOBAL_ZONEID) {
		errno = EINVAL;
		return (NULL);
	}

	nzents = 0;
	if (zone_list(NULL, &nzents) != 0)
		return (NULL);

again:
	/* Add a small amount of padding to avoid loops */
	nzents += 8;
	zids = malloc(nzents * sizeof (zoneid_t));
	if (zids == NULL)
		return (NULL);

	nzents_saved = nzents;

	if (zone_list(zids, &nzents) != 0) {
		free(zids);
		return (NULL);
	}
	if (nzents > nzents_saved) {
		/* list changed, try again */
		free(zids);
		goto again;
	}

	slabel = m_label_alloc(MAC_LABEL);
	if (slabel == NULL) {
		free(zids);
		return (NULL);
	}

	for (i = 0; i < nzents; i++) {
		char	zoneroot[MAXPATHLEN];
		int	zonerootlen;

		if (zids[i] == GLOBAL_ZONEID)
			continue;

		if (zone_getattr(zids[i], ZONE_ATTR_ROOT, zoneroot,
		    sizeof (zoneroot)) == -1)
			continue;	/* Badly configured zone info */

		/*
		 * Need to handle the case for the /dev directory which is
		 * parallel to the zone's root directory.  So we back up
		 * 4 bytes - the strlen of "root".
		 */
		if ((zonerootlen = strlen(zoneroot)) <= 4)
			continue;	/* Badly configured zone info */
		if (strncmp(path, zoneroot, zonerootlen - 4) == 0) {
			/*
			 * If we get a match, the file is in a labeled zone.
			 * Return the label of that zone.
			 */
			if (zone_getattr(zids[i], ZONE_ATTR_SLBL, slabel,
			    sizeof (m_label_t)) < 0)
				continue;	/* Badly configured zone info */

			free(zids);
			return (slabel);
		}
	}
	free(zids);
	bsllow(slabel);
	return (slabel);
}