/*
* 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);
}