policydb.c revision 4ebc669d5dc59771284b2d61eb4cce53e6a7069e
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Author : Stephen Smalley, <sds@epoch.ncsc.mil> */
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com>
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *	Support for enhanced MLS infrastructure.
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Updated: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 	Added conditional policy language extensions
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Updated: Red Hat, Inc.  James Morris <jmorris@redhat.com>
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *      Fine-grained netlink support
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *      IPv6 support
1690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) *      Code cleanup
1790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) *
1890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
1990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * Copyright (C) 2003 - 2005 Tresys Technology, LLC
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright (C) 2003 - 2007 Red Hat, Inc.
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  This library is free software; you can redistribute it and/or
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  modify it under the terms of the GNU Lesser General Public
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  License as published by the Free Software Foundation; either
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  version 2.1 of the License, or (at your option) any later version.
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  This library is distributed in the hope that it will be useful,
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  but WITHOUT ANY WARRANTY; without even the implied warranty of
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  Lesser General Public License for more details.
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  You should have received a copy of the GNU Lesser General Public
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  License along with this library; if not, write to the Free Software
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* FLASK */
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Implementation of the policy database.
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <assert.h>
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdlib.h>
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sepol/policydb/policydb.h>
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sepol/policydb/expand.h>
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sepol/policydb/conditional.h>
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sepol/policydb/avrule_block.h>
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sepol/policydb/util.h>
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sepol/policydb/flask.h>
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "private.h"
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "debug.h"
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "mls.h"
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define POLICYDB_TARGET_SZ   ARRAY_SIZE(policydb_target_strings)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)char *policydb_target_strings[] = { POLICYDB_STRING, POLICYDB_XEN_STRING };
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* These need to be updated if SYM_NUM or OCON_NUM changes */
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static struct policydb_compat_info policydb_compat[] = {
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .type = POLICY_KERN,
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .version = POLICYDB_VERSION_BOUNDARY,
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .sym_num = SYM_NUM,
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .ocon_num = OCON_XEN_PCIDEVICE + 1,
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .target_platform = SEPOL_TARGET_XEN,
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 },
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .type = POLICY_KERN,
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .version = POLICYDB_VERSION_BASE,
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .sym_num = SYM_NUM - 3,
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .ocon_num = OCON_FSUSE + 1,
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .target_platform = SEPOL_TARGET_SELINUX,
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 },
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .type = POLICY_KERN,
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .version = POLICYDB_VERSION_BOOL,
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .sym_num = SYM_NUM - 2,
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .ocon_num = OCON_FSUSE + 1,
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .target_platform = SEPOL_TARGET_SELINUX,
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 },
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .type = POLICY_KERN,
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .version = POLICYDB_VERSION_IPV6,
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .sym_num = SYM_NUM - 2,
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .ocon_num = OCON_NODE6 + 1,
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .target_platform = SEPOL_TARGET_SELINUX,
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 },
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .type = POLICY_KERN,
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .version = POLICYDB_VERSION_NLCLASS,
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .sym_num = SYM_NUM - 2,
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .ocon_num = OCON_NODE6 + 1,
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .target_platform = SEPOL_TARGET_SELINUX,
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 },
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .type = POLICY_KERN,
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .version = POLICYDB_VERSION_MLS,
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .sym_num = SYM_NUM,
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .ocon_num = OCON_NODE6 + 1,
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .target_platform = SEPOL_TARGET_SELINUX,
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 },
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .type = POLICY_KERN,
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .version = POLICYDB_VERSION_AVTAB,
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .sym_num = SYM_NUM,
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .ocon_num = OCON_NODE6 + 1,
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .target_platform = SEPOL_TARGET_SELINUX,
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 },
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .type = POLICY_KERN,
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .version = POLICYDB_VERSION_RANGETRANS,
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .sym_num = SYM_NUM,
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .ocon_num = OCON_NODE6 + 1,
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .target_platform = SEPOL_TARGET_SELINUX,
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 },
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .type = POLICY_KERN,
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .version = POLICYDB_VERSION_POLCAP,
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .sym_num = SYM_NUM,
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .ocon_num = OCON_NODE6 + 1,
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .target_platform = SEPOL_TARGET_SELINUX,
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 },
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .type = POLICY_KERN,
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .version = POLICYDB_VERSION_PERMISSIVE,
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .sym_num = SYM_NUM,
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .ocon_num = OCON_NODE6 + 1,
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .target_platform = SEPOL_TARGET_SELINUX,
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 },
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .type = POLICY_KERN,
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .version = POLICYDB_VERSION_BOUNDARY,
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .sym_num = SYM_NUM,
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .ocon_num = OCON_NODE6 + 1,
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .target_platform = SEPOL_TARGET_SELINUX,
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	},
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .type = POLICY_KERN,
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .version = POLICYDB_VERSION_FILENAME_TRANS,
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .sym_num = SYM_NUM,
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .ocon_num = OCON_NODE6 + 1,
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .target_platform = SEPOL_TARGET_SELINUX,
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	},
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .type = POLICY_KERN,
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .version = POLICYDB_VERSION_ROLETRANS,
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .sym_num = SYM_NUM,
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .ocon_num = OCON_NODE6 + 1,
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .target_platform = SEPOL_TARGET_SELINUX,
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	},
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .type = POLICY_KERN,
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .version = POLICYDB_VERSION_NEW_OBJECT_DEFAULTS,
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .sym_num = SYM_NUM,
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .ocon_num = OCON_NODE6 + 1,
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .target_platform = SEPOL_TARGET_SELINUX,
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	},
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .type = POLICY_BASE,
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .version = MOD_POLICYDB_VERSION_BASE,
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .sym_num = SYM_NUM,
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .ocon_num = OCON_NODE6 + 1,
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .target_platform = SEPOL_TARGET_SELINUX,
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 },
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .type = POLICY_BASE,
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .version = MOD_POLICYDB_VERSION_MLS,
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .sym_num = SYM_NUM,
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .ocon_num = OCON_NODE6 + 1,
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .target_platform = SEPOL_TARGET_SELINUX,
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 },
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	{
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	 .type = POLICY_BASE,
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .version = MOD_POLICYDB_VERSION_MLS_USERS,
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .sym_num = SYM_NUM,
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .ocon_num = OCON_NODE6 + 1,
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .target_platform = SEPOL_TARGET_SELINUX,
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 },
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .type = POLICY_BASE,
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .version = MOD_POLICYDB_VERSION_POLCAP,
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .sym_num = SYM_NUM,
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .ocon_num = OCON_NODE6 + 1,
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .target_platform = SEPOL_TARGET_SELINUX,
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 },
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .type = POLICY_BASE,
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .version = MOD_POLICYDB_VERSION_PERMISSIVE,
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .sym_num = SYM_NUM,
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .ocon_num = OCON_NODE6 + 1,
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .target_platform = SEPOL_TARGET_SELINUX,
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 },
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .type = POLICY_BASE,
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .version = MOD_POLICYDB_VERSION_BOUNDARY,
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .sym_num = SYM_NUM,
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .ocon_num = OCON_NODE6 + 1,
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .target_platform = SEPOL_TARGET_SELINUX,
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	},
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .type = POLICY_BASE,
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .version = MOD_POLICYDB_VERSION_BOUNDARY_ALIAS,
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .sym_num = SYM_NUM,
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .ocon_num = OCON_NODE6 + 1,
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .target_platform = SEPOL_TARGET_SELINUX,
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	},
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .type = POLICY_BASE,
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .version = MOD_POLICYDB_VERSION_FILENAME_TRANS,
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .sym_num = SYM_NUM,
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .ocon_num = OCON_NODE6 + 1,
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .target_platform = SEPOL_TARGET_SELINUX,
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	},
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .type = POLICY_BASE,
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .version = MOD_POLICYDB_VERSION_ROLETRANS,
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .sym_num = SYM_NUM,
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .ocon_num = OCON_NODE6 + 1,
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .target_platform = SEPOL_TARGET_SELINUX,
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	},
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .type = POLICY_BASE,
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .version = MOD_POLICYDB_VERSION_ROLEATTRIB,
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .sym_num = SYM_NUM,
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .ocon_num = OCON_NODE6 + 1,
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .target_platform = SEPOL_TARGET_SELINUX,
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	},
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .type = POLICY_BASE,
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .version = MOD_POLICYDB_VERSION_TUNABLE_SEP,
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .sym_num = SYM_NUM,
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .ocon_num = OCON_NODE6 + 1,
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .target_platform = SEPOL_TARGET_SELINUX,
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	},
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .type = POLICY_BASE,
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .version = MOD_POLICYDB_VERSION_NEW_OBJECT_DEFAULTS,
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .sym_num = SYM_NUM,
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .ocon_num = OCON_NODE6 + 1,
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .target_platform = SEPOL_TARGET_SELINUX,
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	},
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .type = POLICY_MOD,
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .version = MOD_POLICYDB_VERSION_BASE,
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .sym_num = SYM_NUM,
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .ocon_num = 0,
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .target_platform = SEPOL_TARGET_SELINUX,
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 },
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .type = POLICY_MOD,
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .version = MOD_POLICYDB_VERSION_MLS,
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	 .sym_num = SYM_NUM,
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .ocon_num = 0,
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .target_platform = SEPOL_TARGET_SELINUX,
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 },
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	{
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	 .type = POLICY_MOD,
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .version = MOD_POLICYDB_VERSION_MLS_USERS,
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .sym_num = SYM_NUM,
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .ocon_num = 0,
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .target_platform = SEPOL_TARGET_SELINUX,
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 },
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .type = POLICY_MOD,
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .version = MOD_POLICYDB_VERSION_POLCAP,
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .sym_num = SYM_NUM,
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .ocon_num = 0,
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .target_platform = SEPOL_TARGET_SELINUX,
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 },
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .type = POLICY_MOD,
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .version = MOD_POLICYDB_VERSION_PERMISSIVE,
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .sym_num = SYM_NUM,
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .ocon_num = 0,
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .target_platform = SEPOL_TARGET_SELINUX,
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 },
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .type = POLICY_MOD,
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .version = MOD_POLICYDB_VERSION_BOUNDARY,
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .sym_num = SYM_NUM,
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .ocon_num = 0,
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .target_platform = SEPOL_TARGET_SELINUX,
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	},
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .type = POLICY_MOD,
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .version = MOD_POLICYDB_VERSION_BOUNDARY_ALIAS,
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .sym_num = SYM_NUM,
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .ocon_num = 0,
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .target_platform = SEPOL_TARGET_SELINUX,
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	},
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .type = POLICY_MOD,
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .version = MOD_POLICYDB_VERSION_FILENAME_TRANS,
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .sym_num = SYM_NUM,
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .ocon_num = 0,
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .target_platform = SEPOL_TARGET_SELINUX,
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	},
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .type = POLICY_MOD,
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .version = MOD_POLICYDB_VERSION_ROLETRANS,
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .sym_num = SYM_NUM,
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .ocon_num = 0,
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .target_platform = SEPOL_TARGET_SELINUX,
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	},
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .type = POLICY_MOD,
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .version = MOD_POLICYDB_VERSION_ROLEATTRIB,
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .sym_num = SYM_NUM,
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .ocon_num = 0,
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .target_platform = SEPOL_TARGET_SELINUX,
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	},
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .type = POLICY_MOD,
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .version = MOD_POLICYDB_VERSION_TUNABLE_SEP,
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .sym_num = SYM_NUM,
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .ocon_num = 0,
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .target_platform = SEPOL_TARGET_SELINUX,
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	},
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .type = POLICY_MOD,
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .version = MOD_POLICYDB_VERSION_NEW_OBJECT_DEFAULTS,
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .sym_num = SYM_NUM,
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .ocon_num = 0,
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 .target_platform = SEPOL_TARGET_SELINUX,
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	},
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if 0
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static char *symtab_name[SYM_NUM] = {
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	"common prefixes",
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	"classes",
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	"roles",
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	"types",
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	"users",
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	"bools" mls_symtab_names cond_symtab_names
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static unsigned int symtab_sizes[SYM_NUM] = {
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	2,
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	32,
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	16,
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	512,
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	128,
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	16,
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	16,
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	16,
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct policydb_compat_info *policydb_lookup_compat(unsigned int version,
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)						    unsigned int type,
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)						unsigned int target_platform)
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	unsigned int i;
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	struct policydb_compat_info *info = NULL;
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	for (i = 0; i < sizeof(policydb_compat) / sizeof(*info); i++) {
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (policydb_compat[i].version == version &&
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    policydb_compat[i].type == type &&
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    policydb_compat[i].target_platform == target_platform) {
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			info = &policydb_compat[i];
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			break;
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		}
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return info;
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void type_set_init(type_set_t * x)
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	memset(x, 0, sizeof(type_set_t));
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	ebitmap_init(&x->types);
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	ebitmap_init(&x->negset);
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void type_set_destroy(type_set_t * x)
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (x != NULL) {
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		ebitmap_destroy(&x->types);
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		ebitmap_destroy(&x->negset);
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void role_set_init(role_set_t * x)
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	memset(x, 0, sizeof(role_set_t));
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	ebitmap_init(&x->roles);
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void role_set_destroy(role_set_t * x)
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	ebitmap_destroy(&x->roles);
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void role_datum_init(role_datum_t * x)
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	memset(x, 0, sizeof(role_datum_t));
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	ebitmap_init(&x->dominates);
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	type_set_init(&x->types);
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	ebitmap_init(&x->cache);
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	ebitmap_init(&x->roles);
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void role_datum_destroy(role_datum_t * x)
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (x != NULL) {
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		ebitmap_destroy(&x->dominates);
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		type_set_destroy(&x->types);
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		ebitmap_destroy(&x->cache);
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		ebitmap_destroy(&x->roles);
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void type_datum_init(type_datum_t * x)
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	memset(x, 0, sizeof(*x));
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	ebitmap_init(&x->types);
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void type_datum_destroy(type_datum_t * x)
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (x != NULL) {
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		ebitmap_destroy(&x->types);
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void user_datum_init(user_datum_t * x)
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	memset(x, 0, sizeof(user_datum_t));
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	role_set_init(&x->roles);
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	mls_semantic_range_init(&x->range);
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	mls_semantic_level_init(&x->dfltlevel);
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	ebitmap_init(&x->cache);
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	mls_range_init(&x->exp_range);
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	mls_level_init(&x->exp_dfltlevel);
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void user_datum_destroy(user_datum_t * x)
4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (x != NULL) {
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		role_set_destroy(&x->roles);
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		mls_semantic_range_destroy(&x->range);
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		mls_semantic_level_destroy(&x->dfltlevel);
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		ebitmap_destroy(&x->cache);
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		mls_range_destroy(&x->exp_range);
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		mls_level_destroy(&x->exp_dfltlevel);
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void level_datum_init(level_datum_t * x)
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	memset(x, 0, sizeof(level_datum_t));
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void level_datum_destroy(level_datum_t * x __attribute__ ((unused)))
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* the mls_level_t referenced by the level_datum is managed
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 * separately for now, so there is nothing to destroy */
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return;
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void cat_datum_init(cat_datum_t * x)
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	memset(x, 0, sizeof(cat_datum_t));
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void cat_datum_destroy(cat_datum_t * x __attribute__ ((unused)))
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* it's currently a simple struct - really nothing to destroy */
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return;
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void class_perm_node_init(class_perm_node_t * x)
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	memset(x, 0, sizeof(class_perm_node_t));
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void avrule_init(avrule_t * x)
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	memset(x, 0, sizeof(avrule_t));
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	type_set_init(&x->stypes);
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	type_set_init(&x->ttypes);
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void avrule_destroy(avrule_t * x)
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	class_perm_node_t *cur, *next;
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (x == NULL) {
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return;
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	type_set_destroy(&x->stypes);
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	type_set_destroy(&x->ttypes);
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	next = x->perms;
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	while (next) {
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		cur = next;
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		next = cur->next;
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		free(cur);
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void role_trans_rule_init(role_trans_rule_t * x)
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	memset(x, 0, sizeof(*x));
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	role_set_init(&x->roles);
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	type_set_init(&x->types);
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	ebitmap_init(&x->classes);
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void role_trans_rule_destroy(role_trans_rule_t * x)
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (x != NULL) {
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		role_set_destroy(&x->roles);
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		type_set_destroy(&x->types);
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		ebitmap_destroy(&x->classes);
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void role_trans_rule_list_destroy(role_trans_rule_t * x)
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	while (x != NULL) {
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		role_trans_rule_t *next = x->next;
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		role_trans_rule_destroy(x);
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		free(x);
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		x = next;
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void filename_trans_rule_init(filename_trans_rule_t * x)
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	memset(x, 0, sizeof(*x));
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	type_set_init(&x->stypes);
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	type_set_init(&x->ttypes);
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void filename_trans_rule_destroy(filename_trans_rule_t * x)
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (!x)
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return;
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	type_set_destroy(&x->stypes);
5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	type_set_destroy(&x->ttypes);
5442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	free(x->name);
5452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void filename_trans_rule_list_destroy(filename_trans_rule_t * x)
5482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
5492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	filename_trans_rule_t *next;
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	while (x) {
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		next = x->next;
5522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		filename_trans_rule_destroy(x);
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		free(x);
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		x = next;
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
557
558void role_allow_rule_init(role_allow_rule_t * x)
559{
560	memset(x, 0, sizeof(role_allow_rule_t));
561	role_set_init(&x->roles);
562	role_set_init(&x->new_roles);
563}
564
565void role_allow_rule_destroy(role_allow_rule_t * x)
566{
567	role_set_destroy(&x->roles);
568	role_set_destroy(&x->new_roles);
569}
570
571void role_allow_rule_list_destroy(role_allow_rule_t * x)
572{
573	while (x != NULL) {
574		role_allow_rule_t *next = x->next;
575		role_allow_rule_destroy(x);
576		free(x);
577		x = next;
578	}
579}
580
581void range_trans_rule_init(range_trans_rule_t * x)
582{
583	type_set_init(&x->stypes);
584	type_set_init(&x->ttypes);
585	ebitmap_init(&x->tclasses);
586	mls_semantic_range_init(&x->trange);
587	x->next = NULL;
588}
589
590void range_trans_rule_destroy(range_trans_rule_t * x)
591{
592	type_set_destroy(&x->stypes);
593	type_set_destroy(&x->ttypes);
594	ebitmap_destroy(&x->tclasses);
595	mls_semantic_range_destroy(&x->trange);
596}
597
598void range_trans_rule_list_destroy(range_trans_rule_t * x)
599{
600	while (x != NULL) {
601		range_trans_rule_t *next = x->next;
602		range_trans_rule_destroy(x);
603		free(x);
604		x = next;
605	}
606}
607
608void avrule_list_destroy(avrule_t * x)
609{
610	avrule_t *next, *cur;
611
612	if (!x)
613		return;
614
615	next = x;
616	while (next) {
617		cur = next;
618		next = next->next;
619		avrule_destroy(cur);
620		free(cur);
621	}
622}
623
624/*
625 * Initialize the role table by implicitly adding role 'object_r'.  If
626 * the policy is a module, set object_r's scope to be SCOPE_REQ,
627 * otherwise set it to SCOPE_DECL.
628 */
629static int roles_init(policydb_t * p)
630{
631	char *key = 0;
632	int rc;
633	role_datum_t *role;
634
635	role = calloc(1, sizeof(role_datum_t));
636	if (!role) {
637		rc = -ENOMEM;
638		goto out;
639	}
640	key = malloc(strlen(OBJECT_R) + 1);
641	if (!key) {
642		rc = -ENOMEM;
643		goto out_free_role;
644	}
645	strcpy(key, OBJECT_R);
646	rc = symtab_insert(p, SYM_ROLES, key, role,
647			   (p->policy_type ==
648			    POLICY_MOD ? SCOPE_REQ : SCOPE_DECL), 1,
649			   &role->s.value);
650	if (rc)
651		goto out_free_key;
652	if (role->s.value != OBJECT_R_VAL) {
653		rc = -EINVAL;
654		goto out_free_role;
655	}
656      out:
657	return rc;
658
659      out_free_key:
660	free(key);
661      out_free_role:
662	free(role);
663	goto out;
664}
665
666/*
667 * Initialize a policy database structure.
668 */
669int policydb_init(policydb_t * p)
670{
671	int i, rc;
672
673	memset(p, 0, sizeof(policydb_t));
674
675	ebitmap_init(&p->policycaps);
676
677	ebitmap_init(&p->permissive_map);
678
679	for (i = 0; i < SYM_NUM; i++) {
680		p->sym_val_to_name[i] = NULL;
681		rc = symtab_init(&p->symtab[i], symtab_sizes[i]);
682		if (rc)
683			goto out_free_symtab;
684	}
685
686	/* initialize the module stuff */
687	for (i = 0; i < SYM_NUM; i++) {
688		if (symtab_init(&p->scope[i], symtab_sizes[i])) {
689			goto out_free_symtab;
690		}
691	}
692	if ((p->global = avrule_block_create()) == NULL ||
693	    (p->global->branch_list = avrule_decl_create(1)) == NULL) {
694		goto out_free_symtab;
695	}
696	p->decl_val_to_struct = NULL;
697
698	rc = avtab_init(&p->te_avtab);
699	if (rc)
700		goto out_free_symtab;
701
702	rc = roles_init(p);
703	if (rc)
704		goto out_free_symtab;
705
706	rc = cond_policydb_init(p);
707	if (rc)
708		goto out_free_symtab;
709      out:
710	return rc;
711
712      out_free_symtab:
713	for (i = 0; i < SYM_NUM; i++) {
714		hashtab_destroy(p->symtab[i].table);
715		hashtab_destroy(p->scope[i].table);
716	}
717	avrule_block_list_destroy(p->global);
718	goto out;
719}
720
721int policydb_role_cache(hashtab_key_t key
722			__attribute__ ((unused)), hashtab_datum_t datum,
723			void *arg)
724{
725	policydb_t *p;
726	role_datum_t *role;
727
728	role = (role_datum_t *) datum;
729	p = (policydb_t *) arg;
730
731	ebitmap_destroy(&role->cache);
732	if (type_set_expand(&role->types, &role->cache, p, 1)) {
733		return -1;
734	}
735
736	return 0;
737}
738
739int policydb_user_cache(hashtab_key_t key
740			__attribute__ ((unused)), hashtab_datum_t datum,
741			void *arg)
742{
743	policydb_t *p;
744	user_datum_t *user;
745
746	user = (user_datum_t *) datum;
747	p = (policydb_t *) arg;
748
749	ebitmap_destroy(&user->cache);
750	if (role_set_expand(&user->roles, &user->cache, p, NULL, NULL)) {
751		return -1;
752	}
753
754	/* we do not expand user's MLS info in kernel policies because the
755	 * semantic representation is not present and we do not expand user's
756	 * MLS info in module policies because all of the necessary mls
757	 * information is not present */
758	if (p->policy_type != POLICY_KERN && p->policy_type != POLICY_MOD) {
759		mls_range_destroy(&user->exp_range);
760		if (mls_semantic_range_expand(&user->range,
761					      &user->exp_range, p, NULL)) {
762			return -1;
763		}
764
765		mls_level_destroy(&user->exp_dfltlevel);
766		if (mls_semantic_level_expand(&user->dfltlevel,
767					      &user->exp_dfltlevel, p, NULL)) {
768			return -1;
769		}
770	}
771
772	return 0;
773}
774
775/*
776 * The following *_index functions are used to
777 * define the val_to_name and val_to_struct arrays
778 * in a policy database structure.  The val_to_name
779 * arrays are used when converting security context
780 * structures into string representations.  The
781 * val_to_struct arrays are used when the attributes
782 * of a class, role, or user are needed.
783 */
784
785static int common_index(hashtab_key_t key, hashtab_datum_t datum, void *datap)
786{
787	policydb_t *p;
788	common_datum_t *comdatum;
789
790	comdatum = (common_datum_t *) datum;
791	p = (policydb_t *) datap;
792	if (!comdatum->s.value || comdatum->s.value > p->p_commons.nprim)
793		return -EINVAL;
794	p->p_common_val_to_name[comdatum->s.value - 1] = (char *)key;
795
796	return 0;
797}
798
799static int class_index(hashtab_key_t key, hashtab_datum_t datum, void *datap)
800{
801	policydb_t *p;
802	class_datum_t *cladatum;
803
804	cladatum = (class_datum_t *) datum;
805	p = (policydb_t *) datap;
806	if (!cladatum->s.value || cladatum->s.value > p->p_classes.nprim)
807		return -EINVAL;
808	p->p_class_val_to_name[cladatum->s.value - 1] = (char *)key;
809	p->class_val_to_struct[cladatum->s.value - 1] = cladatum;
810
811	return 0;
812}
813
814static int role_index(hashtab_key_t key, hashtab_datum_t datum, void *datap)
815{
816	policydb_t *p;
817	role_datum_t *role;
818
819	role = (role_datum_t *) datum;
820	p = (policydb_t *) datap;
821	if (!role->s.value || role->s.value > p->p_roles.nprim)
822		return -EINVAL;
823	p->p_role_val_to_name[role->s.value - 1] = (char *)key;
824	p->role_val_to_struct[role->s.value - 1] = role;
825
826	return 0;
827}
828
829static int type_index(hashtab_key_t key, hashtab_datum_t datum, void *datap)
830{
831	policydb_t *p;
832	type_datum_t *typdatum;
833
834	typdatum = (type_datum_t *) datum;
835	p = (policydb_t *) datap;
836
837	if (typdatum->primary) {
838		if (!typdatum->s.value || typdatum->s.value > p->p_types.nprim)
839			return -EINVAL;
840		p->p_type_val_to_name[typdatum->s.value - 1] = (char *)key;
841		p->type_val_to_struct[typdatum->s.value - 1] = typdatum;
842	}
843
844	return 0;
845}
846
847static int user_index(hashtab_key_t key, hashtab_datum_t datum, void *datap)
848{
849	policydb_t *p;
850	user_datum_t *usrdatum;
851
852	usrdatum = (user_datum_t *) datum;
853	p = (policydb_t *) datap;
854
855	if (!usrdatum->s.value || usrdatum->s.value > p->p_users.nprim)
856		return -EINVAL;
857
858	p->p_user_val_to_name[usrdatum->s.value - 1] = (char *)key;
859	p->user_val_to_struct[usrdatum->s.value - 1] = usrdatum;
860
861	return 0;
862}
863
864static int sens_index(hashtab_key_t key, hashtab_datum_t datum, void *datap)
865{
866	policydb_t *p;
867	level_datum_t *levdatum;
868
869	levdatum = (level_datum_t *) datum;
870	p = (policydb_t *) datap;
871
872	if (!levdatum->isalias) {
873		if (!levdatum->level->sens ||
874		    levdatum->level->sens > p->p_levels.nprim)
875			return -EINVAL;
876		p->p_sens_val_to_name[levdatum->level->sens - 1] = (char *)key;
877	}
878
879	return 0;
880}
881
882static int cat_index(hashtab_key_t key, hashtab_datum_t datum, void *datap)
883{
884	policydb_t *p;
885	cat_datum_t *catdatum;
886
887	catdatum = (cat_datum_t *) datum;
888	p = (policydb_t *) datap;
889
890	if (!catdatum->isalias) {
891		if (!catdatum->s.value || catdatum->s.value > p->p_cats.nprim)
892			return -EINVAL;
893		p->p_cat_val_to_name[catdatum->s.value - 1] = (char *)key;
894	}
895
896	return 0;
897}
898
899static int (*index_f[SYM_NUM]) (hashtab_key_t key, hashtab_datum_t datum,
900				void *datap) = {
901common_index, class_index, role_index, type_index, user_index,
902	    cond_index_bool, sens_index, cat_index,};
903
904/*
905 * Define the common val_to_name array and the class
906 * val_to_name and val_to_struct arrays in a policy
907 * database structure.
908 */
909int policydb_index_classes(policydb_t * p)
910{
911	free(p->p_common_val_to_name);
912	p->p_common_val_to_name = (char **)
913	    malloc(p->p_commons.nprim * sizeof(char *));
914	if (!p->p_common_val_to_name)
915		return -1;
916
917	if (hashtab_map(p->p_commons.table, common_index, p))
918		return -1;
919
920	free(p->class_val_to_struct);
921	p->class_val_to_struct = (class_datum_t **)
922	    malloc(p->p_classes.nprim * sizeof(class_datum_t *));
923	if (!p->class_val_to_struct)
924		return -1;
925
926	free(p->p_class_val_to_name);
927	p->p_class_val_to_name = (char **)
928	    malloc(p->p_classes.nprim * sizeof(char *));
929	if (!p->p_class_val_to_name)
930		return -1;
931
932	if (hashtab_map(p->p_classes.table, class_index, p))
933		return -1;
934
935	return 0;
936}
937
938int policydb_index_bools(policydb_t * p)
939{
940
941	if (cond_init_bool_indexes(p) == -1)
942		return -1;
943	p->p_bool_val_to_name = (char **)
944	    malloc(p->p_bools.nprim * sizeof(char *));
945	if (!p->p_bool_val_to_name)
946		return -1;
947	if (hashtab_map(p->p_bools.table, cond_index_bool, p))
948		return -1;
949	return 0;
950}
951
952int policydb_index_decls(policydb_t * p)
953{
954	avrule_block_t *curblock;
955	avrule_decl_t *decl;
956	int num_decls = 0;
957
958	free(p->decl_val_to_struct);
959
960	for (curblock = p->global; curblock != NULL; curblock = curblock->next) {
961		for (decl = curblock->branch_list; decl != NULL;
962		     decl = decl->next) {
963			num_decls++;
964		}
965	}
966
967	p->decl_val_to_struct =
968	    calloc(num_decls, sizeof(*(p->decl_val_to_struct)));
969	if (!p->decl_val_to_struct) {
970		return -1;
971	}
972
973	for (curblock = p->global; curblock != NULL; curblock = curblock->next) {
974		for (decl = curblock->branch_list; decl != NULL;
975		     decl = decl->next) {
976			p->decl_val_to_struct[decl->decl_id - 1] = decl;
977		}
978	}
979
980	return 0;
981}
982
983/*
984 * Define the other val_to_name and val_to_struct arrays
985 * in a policy database structure.
986 */
987int policydb_index_others(sepol_handle_t * handle,
988			  policydb_t * p, unsigned verbose)
989{
990	int i;
991
992	if (verbose) {
993		INFO(handle,
994		     "security:  %d users, %d roles, %d types, %d bools",
995		     p->p_users.nprim, p->p_roles.nprim, p->p_types.nprim,
996		     p->p_bools.nprim);
997
998		if (p->mls)
999			INFO(handle, "security: %d sens, %d cats",
1000			     p->p_levels.nprim, p->p_cats.nprim);
1001
1002		INFO(handle, "security:  %d classes, %d rules, %d cond rules",
1003		     p->p_classes.nprim, p->te_avtab.nel, p->te_cond_avtab.nel);
1004	}
1005#if 0
1006	avtab_hash_eval(&p->te_avtab, "rules");
1007	for (i = 0; i < SYM_NUM; i++)
1008		hashtab_hash_eval(p->symtab[i].table, symtab_name[i]);
1009#endif
1010
1011	free(p->role_val_to_struct);
1012	p->role_val_to_struct = (role_datum_t **)
1013	    malloc(p->p_roles.nprim * sizeof(role_datum_t *));
1014	if (!p->role_val_to_struct)
1015		return -1;
1016
1017	free(p->user_val_to_struct);
1018	p->user_val_to_struct = (user_datum_t **)
1019	    malloc(p->p_users.nprim * sizeof(user_datum_t *));
1020	if (!p->user_val_to_struct)
1021		return -1;
1022
1023	free(p->type_val_to_struct);
1024	p->type_val_to_struct = (type_datum_t **)
1025	    calloc(p->p_types.nprim, sizeof(type_datum_t *));
1026	if (!p->type_val_to_struct)
1027		return -1;
1028
1029	cond_init_bool_indexes(p);
1030
1031	for (i = SYM_ROLES; i < SYM_NUM; i++) {
1032		free(p->sym_val_to_name[i]);
1033		p->sym_val_to_name[i] = NULL;
1034		if (p->symtab[i].nprim) {
1035			p->sym_val_to_name[i] = (char **)
1036			    calloc(p->symtab[i].nprim, sizeof(char *));
1037			if (!p->sym_val_to_name[i])
1038				return -1;
1039			if (hashtab_map(p->symtab[i].table, index_f[i], p))
1040				return -1;
1041		}
1042	}
1043
1044	/* This pre-expands the roles and users for context validity checking */
1045	if (hashtab_map(p->p_roles.table, policydb_role_cache, p))
1046		return -1;
1047
1048	if (hashtab_map(p->p_users.table, policydb_user_cache, p))
1049		return -1;
1050
1051	return 0;
1052}
1053
1054/*
1055 * The following *_destroy functions are used to
1056 * free any memory allocated for each kind of
1057 * symbol data in the policy database.
1058 */
1059
1060static int perm_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p
1061			__attribute__ ((unused)))
1062{
1063	if (key)
1064		free(key);
1065	free(datum);
1066	return 0;
1067}
1068
1069static int common_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p
1070			  __attribute__ ((unused)))
1071{
1072	common_datum_t *comdatum;
1073
1074	if (key)
1075		free(key);
1076	comdatum = (common_datum_t *) datum;
1077	hashtab_map(comdatum->permissions.table, perm_destroy, 0);
1078	hashtab_destroy(comdatum->permissions.table);
1079	free(datum);
1080	return 0;
1081}
1082
1083static int class_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p
1084			 __attribute__ ((unused)))
1085{
1086	class_datum_t *cladatum;
1087	constraint_node_t *constraint, *ctemp;
1088	constraint_expr_t *e, *etmp;
1089
1090	if (key)
1091		free(key);
1092	cladatum = (class_datum_t *) datum;
1093	if (cladatum == NULL) {
1094		return 0;
1095	}
1096	hashtab_map(cladatum->permissions.table, perm_destroy, 0);
1097	hashtab_destroy(cladatum->permissions.table);
1098	constraint = cladatum->constraints;
1099	while (constraint) {
1100		e = constraint->expr;
1101		while (e) {
1102			etmp = e;
1103			e = e->next;
1104			constraint_expr_destroy(etmp);
1105		}
1106		ctemp = constraint;
1107		constraint = constraint->next;
1108		free(ctemp);
1109	}
1110
1111	constraint = cladatum->validatetrans;
1112	while (constraint) {
1113		e = constraint->expr;
1114		while (e) {
1115			etmp = e;
1116			e = e->next;
1117			constraint_expr_destroy(etmp);
1118		}
1119		ctemp = constraint;
1120		constraint = constraint->next;
1121		free(ctemp);
1122	}
1123
1124	if (cladatum->comkey)
1125		free(cladatum->comkey);
1126	free(datum);
1127	return 0;
1128}
1129
1130static int role_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p
1131			__attribute__ ((unused)))
1132{
1133	free(key);
1134	role_datum_destroy((role_datum_t *) datum);
1135	free(datum);
1136	return 0;
1137}
1138
1139static int type_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p
1140			__attribute__ ((unused)))
1141{
1142	free(key);
1143	type_datum_destroy((type_datum_t *) datum);
1144	free(datum);
1145	return 0;
1146}
1147
1148static int user_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p
1149			__attribute__ ((unused)))
1150{
1151	free(key);
1152	user_datum_destroy((user_datum_t *) datum);
1153	free(datum);
1154	return 0;
1155}
1156
1157static int sens_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p
1158			__attribute__ ((unused)))
1159{
1160	level_datum_t *levdatum;
1161
1162	if (key)
1163		free(key);
1164	levdatum = (level_datum_t *) datum;
1165	mls_level_destroy(levdatum->level);
1166	free(levdatum->level);
1167	level_datum_destroy(levdatum);
1168	free(levdatum);
1169	return 0;
1170}
1171
1172static int cat_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p
1173		       __attribute__ ((unused)))
1174{
1175	if (key)
1176		free(key);
1177	cat_datum_destroy((cat_datum_t *) datum);
1178	free(datum);
1179	return 0;
1180}
1181
1182static int (*destroy_f[SYM_NUM]) (hashtab_key_t key, hashtab_datum_t datum,
1183				  void *datap) = {
1184common_destroy, class_destroy, role_destroy, type_destroy, user_destroy,
1185	    cond_destroy_bool, sens_destroy, cat_destroy,};
1186
1187void ocontext_selinux_free(ocontext_t **ocontexts)
1188{
1189	ocontext_t *c, *ctmp;
1190	int i;
1191
1192	for (i = 0; i < OCON_NUM; i++) {
1193		c = ocontexts[i];
1194		while (c) {
1195			ctmp = c;
1196			c = c->next;
1197			context_destroy(&ctmp->context[0]);
1198			context_destroy(&ctmp->context[1]);
1199			if (i == OCON_ISID || i == OCON_FS || i == OCON_NETIF
1200				|| i == OCON_FSUSE)
1201				free(ctmp->u.name);
1202			free(ctmp);
1203		}
1204	}
1205}
1206
1207void ocontext_xen_free(ocontext_t **ocontexts)
1208{
1209	ocontext_t *c, *ctmp;
1210	int i;
1211
1212	for (i = 0; i < OCON_NUM; i++) {
1213		c = ocontexts[i];
1214		while (c) {
1215			ctmp = c;
1216			c = c->next;
1217			context_destroy(&ctmp->context[0]);
1218			context_destroy(&ctmp->context[1]);
1219			if (i == OCON_ISID)
1220				free(ctmp->u.name);
1221			free(ctmp);
1222		}
1223	}
1224}
1225
1226/*
1227 * Free any memory allocated by a policy database structure.
1228 */
1229void policydb_destroy(policydb_t * p)
1230{
1231	ocontext_t *c, *ctmp;
1232	genfs_t *g, *gtmp;
1233	unsigned int i;
1234	role_allow_t *ra, *lra = NULL;
1235	role_trans_t *tr, *ltr = NULL;
1236	range_trans_t *rt, *lrt = NULL;
1237	filename_trans_t *ft, *nft;
1238
1239	if (!p)
1240		return;
1241
1242	ebitmap_destroy(&p->policycaps);
1243
1244	ebitmap_destroy(&p->permissive_map);
1245
1246	symtabs_destroy(p->symtab);
1247
1248	for (i = 0; i < SYM_NUM; i++) {
1249		if (p->sym_val_to_name[i])
1250			free(p->sym_val_to_name[i]);
1251	}
1252
1253	if (p->class_val_to_struct)
1254		free(p->class_val_to_struct);
1255	if (p->role_val_to_struct)
1256		free(p->role_val_to_struct);
1257	if (p->user_val_to_struct)
1258		free(p->user_val_to_struct);
1259	if (p->type_val_to_struct)
1260		free(p->type_val_to_struct);
1261	free(p->decl_val_to_struct);
1262
1263	for (i = 0; i < SYM_NUM; i++) {
1264		hashtab_map(p->scope[i].table, scope_destroy, 0);
1265		hashtab_destroy(p->scope[i].table);
1266	}
1267	avrule_block_list_destroy(p->global);
1268	free(p->name);
1269	free(p->version);
1270
1271	avtab_destroy(&p->te_avtab);
1272
1273	if (p->target_platform == SEPOL_TARGET_SELINUX)
1274		ocontext_selinux_free(p->ocontexts);
1275	else if (p->target_platform == SEPOL_TARGET_XEN)
1276		ocontext_xen_free(p->ocontexts);
1277
1278	g = p->genfs;
1279	while (g) {
1280		free(g->fstype);
1281		c = g->head;
1282		while (c) {
1283			ctmp = c;
1284			c = c->next;
1285			context_destroy(&ctmp->context[0]);
1286			free(ctmp->u.name);
1287			free(ctmp);
1288		}
1289		gtmp = g;
1290		g = g->next;
1291		free(gtmp);
1292	}
1293	cond_policydb_destroy(p);
1294
1295	for (tr = p->role_tr; tr; tr = tr->next) {
1296		if (ltr)
1297			free(ltr);
1298		ltr = tr;
1299	}
1300	if (ltr)
1301		free(ltr);
1302
1303	ft = p->filename_trans;
1304	while (ft) {
1305		nft = ft->next;
1306		free(ft->name);
1307		free(ft);
1308		ft = nft;
1309	}
1310
1311	for (ra = p->role_allow; ra; ra = ra->next) {
1312		if (lra)
1313			free(lra);
1314		lra = ra;
1315	}
1316	if (lra)
1317		free(lra);
1318
1319	for (rt = p->range_tr; rt; rt = rt->next) {
1320		if (lrt) {
1321			ebitmap_destroy(&lrt->target_range.level[0].cat);
1322			ebitmap_destroy(&lrt->target_range.level[1].cat);
1323			free(lrt);
1324		}
1325		lrt = rt;
1326	}
1327	if (lrt) {
1328		ebitmap_destroy(&lrt->target_range.level[0].cat);
1329		ebitmap_destroy(&lrt->target_range.level[1].cat);
1330		free(lrt);
1331	}
1332
1333	if (p->type_attr_map) {
1334		for (i = 0; i < p->p_types.nprim; i++) {
1335			ebitmap_destroy(&p->type_attr_map[i]);
1336		}
1337		free(p->type_attr_map);
1338	}
1339
1340	if (p->attr_type_map) {
1341		for (i = 0; i < p->p_types.nprim; i++) {
1342			ebitmap_destroy(&p->attr_type_map[i]);
1343		}
1344		free(p->attr_type_map);
1345	}
1346
1347	return;
1348}
1349
1350void symtabs_destroy(symtab_t * symtab)
1351{
1352	int i;
1353	for (i = 0; i < SYM_NUM; i++) {
1354		hashtab_map(symtab[i].table, destroy_f[i], 0);
1355		hashtab_destroy(symtab[i].table);
1356	}
1357}
1358
1359int scope_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p
1360		  __attribute__ ((unused)))
1361{
1362	scope_datum_t *cur = (scope_datum_t *) datum;
1363	free(key);
1364	if (cur != NULL) {
1365		free(cur->decl_ids);
1366	}
1367	free(cur);
1368	return 0;
1369}
1370
1371hashtab_destroy_func_t get_symtab_destroy_func(int sym_num)
1372{
1373	if (sym_num < 0 || sym_num >= SYM_NUM) {
1374		return NULL;
1375	}
1376	return (hashtab_destroy_func_t) destroy_f[sym_num];
1377}
1378
1379/*
1380 * Load the initial SIDs specified in a policy database
1381 * structure into a SID table.
1382 */
1383int policydb_load_isids(policydb_t * p, sidtab_t * s)
1384{
1385	ocontext_t *head, *c;
1386
1387	if (sepol_sidtab_init(s)) {
1388		ERR(NULL, "out of memory on SID table init");
1389		return -1;
1390	}
1391
1392	head = p->ocontexts[OCON_ISID];
1393	for (c = head; c; c = c->next) {
1394		if (!c->context[0].user) {
1395			ERR(NULL, "SID %s was never defined", c->u.name);
1396			return -1;
1397		}
1398		if (sepol_sidtab_insert(s, c->sid[0], &c->context[0])) {
1399			ERR(NULL, "unable to load initial SID %s", c->u.name);
1400			return -1;
1401		}
1402	}
1403
1404	return 0;
1405}
1406
1407/* Declare a symbol for a certain avrule_block context.  Insert it
1408 * into a symbol table for a policy.  This function will handle
1409 * inserting the appropriate scope information in addition to
1410 * inserting the symbol into the hash table.
1411 *
1412 * arguments:
1413 *   policydb_t *pol       module policy to modify
1414 *   uint32_t sym          the symbole table for insertion (SYM_*)
1415 *   hashtab_key_t key     the key for the symbol - not cloned
1416 *   hashtab_datum_t data  the data for the symbol - not cloned
1417 *   scope                 scope of this symbol, either SCOPE_REQ or SCOPE_DECL
1418 *   avrule_decl_id        identifier for this symbol's encapsulating declaration
1419 *   value (out)           assigned value to the symbol (if value is not NULL)
1420 *
1421 * returns:
1422 *   0                     success
1423 *   1                     success, but symbol already existed as a requirement
1424 *                         (datum was not inserted and needs to be free()d)
1425 *   -1                    general error
1426 *   -2                    scope conflicted
1427 *   -ENOMEM               memory error
1428 *   error codes from hashtab_insert
1429 */
1430int symtab_insert(policydb_t * pol, uint32_t sym,
1431		  hashtab_key_t key, hashtab_datum_t datum,
1432		  uint32_t scope, uint32_t avrule_decl_id, uint32_t * value)
1433{
1434	int rc, retval = 0;
1435	unsigned int i;
1436	scope_datum_t *scope_datum;
1437
1438	/* check if the symbol is already there.  multiple
1439	 * declarations of non-roles/non-users are illegal, but
1440	 * multiple requires are allowed. */
1441
1442	/* FIX ME - the failures after the hashtab_insert will leave
1443	 * the policy in a inconsistent state. */
1444	rc = hashtab_insert(pol->symtab[sym].table, key, datum);
1445	if (rc == SEPOL_OK) {
1446		/* if no value is passed in the symbol is not primary
1447		 * (i.e. aliases) */
1448		if (value)
1449			*value = ++pol->symtab[sym].nprim;
1450	} else if (rc == SEPOL_EEXIST) {
1451		retval = 1;	/* symbol not added -- need to free() later */
1452	} else {
1453		return rc;
1454	}
1455
1456	/* get existing scope information; if there is not one then
1457	 * create it */
1458	scope_datum =
1459	    (scope_datum_t *) hashtab_search(pol->scope[sym].table, key);
1460	if (scope_datum == NULL) {
1461		hashtab_key_t key2 = strdup((char *)key);
1462		if (!key2)
1463			return -ENOMEM;
1464		if ((scope_datum = malloc(sizeof(*scope_datum))) == NULL) {
1465			free(key2);
1466			return -ENOMEM;
1467		}
1468		scope_datum->scope = scope;
1469		scope_datum->decl_ids = NULL;
1470		scope_datum->decl_ids_len = 0;
1471		if ((rc =
1472		     hashtab_insert(pol->scope[sym].table, key2,
1473				    scope_datum)) != 0) {
1474			free(key2);
1475			free(scope_datum);
1476			return rc;
1477		}
1478	} else if (scope_datum->scope == SCOPE_DECL && scope == SCOPE_DECL) {
1479		/* disallow multiple declarations for non-roles/users */
1480		if (sym != SYM_ROLES && sym != SYM_USERS) {
1481			return -2;
1482		}
1483		/* Further confine that a role attribute can't have the same
1484		 * name as another regular role, and a role attribute can't
1485		 * be declared more than once. */
1486		if (sym == SYM_ROLES) {
1487			role_datum_t *base_role;
1488			role_datum_t *cur_role = (role_datum_t *)datum;
1489
1490			base_role = (role_datum_t *)
1491					hashtab_search(pol->symtab[sym].table,
1492						       key);
1493			assert(base_role != NULL);
1494
1495			if (!((base_role->flavor == ROLE_ROLE) &&
1496			    (cur_role->flavor == ROLE_ROLE))) {
1497				/* Only regular roles are allowed to have
1498				 * multiple declarations. */
1499				return -2;
1500			}
1501		}
1502	} else if (scope_datum->scope == SCOPE_REQ && scope == SCOPE_DECL) {
1503		scope_datum->scope = SCOPE_DECL;
1504	} else if (scope_datum->scope != scope) {
1505		/* This only happens in DECL then REQUIRE case, which is handled by caller */
1506		return -2;
1507	}
1508
1509	/* search through the pre-existing list to avoid adding duplicates */
1510	for (i = 0; i < scope_datum->decl_ids_len; i++) {
1511		if (scope_datum->decl_ids[i] == avrule_decl_id) {
1512			/* already there, so don't modify its scope */
1513			return retval;
1514		}
1515	}
1516
1517	if (add_i_to_a(avrule_decl_id,
1518		       &scope_datum->decl_ids_len,
1519		       &scope_datum->decl_ids) == -1) {
1520		return -ENOMEM;
1521	}
1522
1523	return retval;
1524}
1525
1526int type_set_or(type_set_t * dst, type_set_t * a, type_set_t * b)
1527{
1528	type_set_init(dst);
1529
1530	if (ebitmap_or(&dst->types, &a->types, &b->types)) {
1531		return -1;
1532	}
1533	if (ebitmap_or(&dst->negset, &a->negset, &b->negset)) {
1534		return -1;
1535	}
1536
1537	dst->flags |= a->flags;
1538	dst->flags |= b->flags;
1539
1540	return 0;
1541}
1542
1543int type_set_cpy(type_set_t * dst, type_set_t * src)
1544{
1545	type_set_init(dst);
1546
1547	dst->flags = src->flags;
1548	if (ebitmap_cpy(&dst->types, &src->types))
1549		return -1;
1550	if (ebitmap_cpy(&dst->negset, &src->negset))
1551		return -1;
1552
1553	return 0;
1554}
1555
1556int type_set_or_eq(type_set_t * dst, type_set_t * other)
1557{
1558	int ret;
1559	type_set_t tmp;
1560
1561	if (type_set_or(&tmp, dst, other))
1562		return -1;
1563	type_set_destroy(dst);
1564	ret = type_set_cpy(dst, &tmp);
1565	type_set_destroy(&tmp);
1566
1567	return ret;
1568}
1569
1570int role_set_get_role(role_set_t * x, uint32_t role)
1571{
1572	if (x->flags & ROLE_STAR)
1573		return 1;
1574
1575	if (ebitmap_get_bit(&x->roles, role - 1)) {
1576		if (x->flags & ROLE_COMP)
1577			return 0;
1578		else
1579			return 1;
1580	} else {
1581		if (x->flags & ROLE_COMP)
1582			return 1;
1583		else
1584			return 0;
1585	}
1586}
1587
1588/***********************************************************************/
1589/* everything below is for policy reads */
1590
1591/* The following are read functions for module structures */
1592
1593static int role_set_read(role_set_t * r, struct policy_file *fp)
1594{
1595	uint32_t buf[1];
1596	int rc;
1597
1598	if (ebitmap_read(&r->roles, fp))
1599		return -1;
1600	rc = next_entry(buf, fp, sizeof(uint32_t));
1601	if (rc < 0)
1602		return -1;
1603	r->flags = le32_to_cpu(buf[0]);
1604
1605	return 0;
1606}
1607
1608static int type_set_read(type_set_t * t, struct policy_file *fp)
1609{
1610	uint32_t buf[1];
1611	int rc;
1612
1613	if (ebitmap_read(&t->types, fp))
1614		return -1;
1615	if (ebitmap_read(&t->negset, fp))
1616		return -1;
1617
1618	rc = next_entry(buf, fp, sizeof(uint32_t));
1619	if (rc < 0)
1620		return -1;
1621	t->flags = le32_to_cpu(buf[0]);
1622
1623	return 0;
1624}
1625
1626/*
1627 * Read a MLS range structure from a policydb binary
1628 * representation file.
1629 */
1630static int mls_read_range_helper(mls_range_t * r, struct policy_file *fp)
1631{
1632	uint32_t buf[2], items;
1633	int rc;
1634
1635	rc = next_entry(buf, fp, sizeof(uint32_t));
1636	if (rc < 0)
1637		goto out;
1638
1639	items = le32_to_cpu(buf[0]);
1640	if (items > ARRAY_SIZE(buf)) {
1641		ERR(fp->handle, "range overflow");
1642		rc = -EINVAL;
1643		goto out;
1644	}
1645	rc = next_entry(buf, fp, sizeof(uint32_t) * items);
1646	if (rc < 0) {
1647		ERR(fp->handle, "truncated range");
1648		goto out;
1649	}
1650	r->level[0].sens = le32_to_cpu(buf[0]);
1651	if (items > 1)
1652		r->level[1].sens = le32_to_cpu(buf[1]);
1653	else
1654		r->level[1].sens = r->level[0].sens;
1655
1656	rc = ebitmap_read(&r->level[0].cat, fp);
1657	if (rc) {
1658		ERR(fp->handle, "error reading low categories");
1659		goto out;
1660	}
1661	if (items > 1) {
1662		rc = ebitmap_read(&r->level[1].cat, fp);
1663		if (rc) {
1664			ERR(fp->handle, "error reading high categories");
1665			goto bad_high;
1666		}
1667	} else {
1668		rc = ebitmap_cpy(&r->level[1].cat, &r->level[0].cat);
1669		if (rc) {
1670			ERR(fp->handle, "out of memory");
1671			goto bad_high;
1672		}
1673	}
1674
1675	rc = 0;
1676      out:
1677	return rc;
1678      bad_high:
1679	ebitmap_destroy(&r->level[0].cat);
1680	goto out;
1681}
1682
1683/*
1684 * Read a semantic MLS level structure from a policydb binary
1685 * representation file.
1686 */
1687static int mls_read_semantic_level_helper(mls_semantic_level_t * l,
1688					  struct policy_file *fp)
1689{
1690	uint32_t buf[2], ncat;
1691	unsigned int i;
1692	mls_semantic_cat_t *cat;
1693	int rc;
1694
1695	mls_semantic_level_init(l);
1696
1697	rc = next_entry(buf, fp, sizeof(uint32_t) * 2);
1698	if (rc < 0) {
1699		ERR(fp->handle, "truncated level");
1700		goto bad;
1701	}
1702	l->sens = le32_to_cpu(buf[0]);
1703
1704	ncat = le32_to_cpu(buf[1]);
1705	for (i = 0; i < ncat; i++) {
1706		cat = (mls_semantic_cat_t *) malloc(sizeof(mls_semantic_cat_t));
1707		if (!cat) {
1708			ERR(fp->handle, "out of memory");
1709			goto bad;
1710		}
1711
1712		mls_semantic_cat_init(cat);
1713		cat->next = l->cat;
1714		l->cat = cat;
1715
1716		rc = next_entry(buf, fp, sizeof(uint32_t) * 2);
1717		if (rc < 0) {
1718			ERR(fp->handle, "error reading level categories");
1719			goto bad;
1720		}
1721		cat->low = le32_to_cpu(buf[0]);
1722		cat->high = le32_to_cpu(buf[1]);
1723	}
1724
1725	return 0;
1726
1727      bad:
1728	return -EINVAL;
1729}
1730
1731/*
1732 * Read a semantic MLS range structure from a policydb binary
1733 * representation file.
1734 */
1735static int mls_read_semantic_range_helper(mls_semantic_range_t * r,
1736					  struct policy_file *fp)
1737{
1738	int rc;
1739
1740	rc = mls_read_semantic_level_helper(&r->level[0], fp);
1741	if (rc)
1742		return rc;
1743
1744	rc = mls_read_semantic_level_helper(&r->level[1], fp);
1745
1746	return rc;
1747}
1748
1749static int mls_level_to_semantic(mls_level_t * l, mls_semantic_level_t * sl)
1750{
1751	unsigned int i;
1752	ebitmap_node_t *cnode;
1753	mls_semantic_cat_t *open_cat = NULL;
1754
1755	mls_semantic_level_init(sl);
1756	sl->sens = l->sens;
1757	ebitmap_for_each_bit(&l->cat, cnode, i) {
1758		if (ebitmap_node_get_bit(cnode, i)) {
1759			if (open_cat)
1760				continue;
1761			open_cat = (mls_semantic_cat_t *)
1762			    malloc(sizeof(mls_semantic_cat_t));
1763			if (!open_cat)
1764				return -1;
1765
1766			mls_semantic_cat_init(open_cat);
1767			open_cat->low = i + 1;
1768			open_cat->next = sl->cat;
1769			sl->cat = open_cat;
1770		} else {
1771			if (!open_cat)
1772				continue;
1773			open_cat->high = i;
1774			open_cat = NULL;
1775		}
1776	}
1777	if (open_cat)
1778		open_cat->high = i;
1779
1780	return 0;
1781}
1782
1783static int mls_range_to_semantic(mls_range_t * r, mls_semantic_range_t * sr)
1784{
1785	if (mls_level_to_semantic(&r->level[0], &sr->level[0]))
1786		return -1;
1787
1788	if (mls_level_to_semantic(&r->level[1], &sr->level[1]))
1789		return -1;
1790
1791	return 0;
1792}
1793
1794/*
1795 * Read and validate a security context structure
1796 * from a policydb binary representation file.
1797 */
1798static int context_read_and_validate(context_struct_t * c,
1799				     policydb_t * p, struct policy_file *fp)
1800{
1801	uint32_t buf[3];
1802	int rc;
1803
1804	rc = next_entry(buf, fp, sizeof(uint32_t) * 3);
1805	if (rc < 0) {
1806		ERR(fp->handle, "context truncated");
1807		return -1;
1808	}
1809	c->user = le32_to_cpu(buf[0]);
1810	c->role = le32_to_cpu(buf[1]);
1811	c->type = le32_to_cpu(buf[2]);
1812	if ((p->policy_type == POLICY_KERN
1813	     && p->policyvers >= POLICYDB_VERSION_MLS)
1814	    || (p->policy_type == POLICY_BASE
1815		&& p->policyvers >= MOD_POLICYDB_VERSION_MLS)) {
1816		if (mls_read_range_helper(&c->range, fp)) {
1817			ERR(fp->handle, "error reading MLS range "
1818			    "of context");
1819			return -1;
1820		}
1821	}
1822
1823	if (!policydb_context_isvalid(p, c)) {
1824		ERR(fp->handle, "invalid security context");
1825		context_destroy(c);
1826		return -1;
1827	}
1828	return 0;
1829}
1830
1831/*
1832 * The following *_read functions are used to
1833 * read the symbol data from a policy database
1834 * binary representation file.
1835 */
1836
1837static int perm_read(policydb_t * p
1838		     __attribute__ ((unused)), hashtab_t h,
1839		     struct policy_file *fp)
1840{
1841	char *key = 0;
1842	perm_datum_t *perdatum;
1843	uint32_t buf[2];
1844	size_t len;
1845	int rc;
1846
1847	perdatum = calloc(1, sizeof(perm_datum_t));
1848	if (!perdatum)
1849		return -1;
1850
1851	rc = next_entry(buf, fp, sizeof(uint32_t) * 2);
1852	if (rc < 0)
1853		goto bad;
1854
1855	len = le32_to_cpu(buf[0]);
1856	perdatum->s.value = le32_to_cpu(buf[1]);
1857
1858	key = malloc(len + 1);
1859	if (!key)
1860		goto bad;
1861	rc = next_entry(key, fp, len);
1862	if (rc < 0)
1863		goto bad;
1864	key[len] = 0;
1865
1866	if (hashtab_insert(h, key, perdatum))
1867		goto bad;
1868
1869	return 0;
1870
1871      bad:
1872	perm_destroy(key, perdatum, NULL);
1873	return -1;
1874}
1875
1876static int common_read(policydb_t * p, hashtab_t h, struct policy_file *fp)
1877{
1878	char *key = 0;
1879	common_datum_t *comdatum;
1880	uint32_t buf[4];
1881	size_t len, nel;
1882	unsigned int i;
1883	int rc;
1884
1885	comdatum = calloc(1, sizeof(common_datum_t));
1886	if (!comdatum)
1887		return -1;
1888
1889	rc = next_entry(buf, fp, sizeof(uint32_t) * 4);
1890	if (rc < 0)
1891		goto bad;
1892
1893	len = le32_to_cpu(buf[0]);
1894	comdatum->s.value = le32_to_cpu(buf[1]);
1895
1896	if (symtab_init(&comdatum->permissions, PERM_SYMTAB_SIZE))
1897		goto bad;
1898	comdatum->permissions.nprim = le32_to_cpu(buf[2]);
1899	nel = le32_to_cpu(buf[3]);
1900
1901	key = malloc(len + 1);
1902	if (!key)
1903		goto bad;
1904	rc = next_entry(key, fp, len);
1905	if (rc < 0)
1906		goto bad;
1907	key[len] = 0;
1908
1909	for (i = 0; i < nel; i++) {
1910		if (perm_read(p, comdatum->permissions.table, fp))
1911			goto bad;
1912	}
1913
1914	if (hashtab_insert(h, key, comdatum))
1915		goto bad;
1916
1917	return 0;
1918
1919      bad:
1920	common_destroy(key, comdatum, NULL);
1921	return -1;
1922}
1923
1924static int read_cons_helper(policydb_t * p, constraint_node_t ** nodep,
1925			    unsigned int ncons,
1926			    int allowxtarget, struct policy_file *fp)
1927{
1928	constraint_node_t *c, *lc;
1929	constraint_expr_t *e, *le;
1930	uint32_t buf[3];
1931	size_t nexpr;
1932	unsigned int i, j;
1933	int rc, depth;
1934
1935	lc = NULL;
1936	for (i = 0; i < ncons; i++) {
1937		c = calloc(1, sizeof(constraint_node_t));
1938		if (!c)
1939			return -1;
1940
1941		if (lc)
1942			lc->next = c;
1943		else
1944			*nodep = c;
1945
1946		rc = next_entry(buf, fp, (sizeof(uint32_t) * 2));
1947		if (rc < 0)
1948			return -1;
1949		c->permissions = le32_to_cpu(buf[0]);
1950		nexpr = le32_to_cpu(buf[1]);
1951		le = NULL;
1952		depth = -1;
1953		for (j = 0; j < nexpr; j++) {
1954			e = malloc(sizeof(constraint_expr_t));
1955			if (!e)
1956				return -1;
1957			if (constraint_expr_init(e) == -1) {
1958				free(e);
1959				return -1;
1960			}
1961			if (le) {
1962				le->next = e;
1963			} else {
1964				c->expr = e;
1965			}
1966
1967			rc = next_entry(buf, fp, (sizeof(uint32_t) * 3));
1968			if (rc < 0)
1969				return -1;
1970			e->expr_type = le32_to_cpu(buf[0]);
1971			e->attr = le32_to_cpu(buf[1]);
1972			e->op = le32_to_cpu(buf[2]);
1973
1974			switch (e->expr_type) {
1975			case CEXPR_NOT:
1976				if (depth < 0)
1977					return -1;
1978				break;
1979			case CEXPR_AND:
1980			case CEXPR_OR:
1981				if (depth < 1)
1982					return -1;
1983				depth--;
1984				break;
1985			case CEXPR_ATTR:
1986				if (depth == (CEXPR_MAXDEPTH - 1))
1987					return -1;
1988				depth++;
1989				break;
1990			case CEXPR_NAMES:
1991				if (!allowxtarget && (e->attr & CEXPR_XTARGET))
1992					return -1;
1993				if (depth == (CEXPR_MAXDEPTH - 1))
1994					return -1;
1995				depth++;
1996				if (ebitmap_read(&e->names, fp))
1997					return -1;
1998				if (p->policy_type != POLICY_KERN &&
1999				    type_set_read(e->type_names, fp))
2000					return -1;
2001				break;
2002			default:
2003				return -1;
2004			}
2005			le = e;
2006		}
2007		if (depth != 0)
2008			return -1;
2009		lc = c;
2010	}
2011
2012	return 0;
2013}
2014
2015static int class_read(policydb_t * p, hashtab_t h, struct policy_file *fp)
2016{
2017	char *key = 0;
2018	class_datum_t *cladatum;
2019	uint32_t buf[6];
2020	size_t len, len2, ncons, nel;
2021	unsigned int i;
2022	int rc;
2023
2024	cladatum = (class_datum_t *) calloc(1, sizeof(class_datum_t));
2025	if (!cladatum)
2026		return -1;
2027
2028	rc = next_entry(buf, fp, sizeof(uint32_t) * 6);
2029	if (rc < 0)
2030		goto bad;
2031
2032	len = le32_to_cpu(buf[0]);
2033	len2 = le32_to_cpu(buf[1]);
2034	cladatum->s.value = le32_to_cpu(buf[2]);
2035
2036	if (symtab_init(&cladatum->permissions, PERM_SYMTAB_SIZE))
2037		goto bad;
2038	cladatum->permissions.nprim = le32_to_cpu(buf[3]);
2039	nel = le32_to_cpu(buf[4]);
2040
2041	ncons = le32_to_cpu(buf[5]);
2042
2043	key = malloc(len + 1);
2044	if (!key)
2045		goto bad;
2046	rc = next_entry(key, fp, len);
2047	if (rc < 0)
2048		goto bad;
2049	key[len] = 0;
2050
2051	if (len2) {
2052		cladatum->comkey = malloc(len2 + 1);
2053		if (!cladatum->comkey)
2054			goto bad;
2055		rc = next_entry(cladatum->comkey, fp, len2);
2056		if (rc < 0)
2057			goto bad;
2058		cladatum->comkey[len2] = 0;
2059
2060		cladatum->comdatum = hashtab_search(p->p_commons.table,
2061						    cladatum->comkey);
2062		if (!cladatum->comdatum) {
2063			ERR(fp->handle, "unknown common %s", cladatum->comkey);
2064			goto bad;
2065		}
2066	}
2067	for (i = 0; i < nel; i++) {
2068		if (perm_read(p, cladatum->permissions.table, fp))
2069			goto bad;
2070	}
2071
2072	if (read_cons_helper(p, &cladatum->constraints, ncons, 0, fp))
2073		goto bad;
2074
2075	if ((p->policy_type == POLICY_KERN
2076	     && p->policyvers >= POLICYDB_VERSION_VALIDATETRANS)
2077	    || (p->policy_type == POLICY_BASE
2078		&& p->policyvers >= MOD_POLICYDB_VERSION_VALIDATETRANS)) {
2079		/* grab the validatetrans rules */
2080		rc = next_entry(buf, fp, sizeof(uint32_t));
2081		if (rc < 0)
2082			goto bad;
2083		ncons = le32_to_cpu(buf[0]);
2084		if (read_cons_helper(p, &cladatum->validatetrans, ncons, 1, fp))
2085			goto bad;
2086	}
2087
2088	if ((p->policy_type == POLICY_KERN &&
2089	     p->policyvers >= POLICYDB_VERSION_NEW_OBJECT_DEFAULTS) ||
2090	    (p->policy_type == POLICY_BASE &&
2091	     p->policyvers >= MOD_POLICYDB_VERSION_NEW_OBJECT_DEFAULTS)) {
2092		rc = next_entry(buf, fp, sizeof(uint32_t) * 3);
2093		if (rc < 0)
2094			goto bad;
2095		cladatum->default_user = le32_to_cpu(buf[0]);
2096		cladatum->default_role = le32_to_cpu(buf[1]);
2097		cladatum->default_range = le32_to_cpu(buf[2]);
2098	}
2099
2100	if (hashtab_insert(h, key, cladatum))
2101		goto bad;
2102
2103	return 0;
2104
2105      bad:
2106	class_destroy(key, cladatum, NULL);
2107	return -1;
2108}
2109
2110static int role_read(policydb_t * p
2111		     __attribute__ ((unused)), hashtab_t h,
2112		     struct policy_file *fp)
2113{
2114	char *key = 0;
2115	role_datum_t *role;
2116	uint32_t buf[3];
2117	size_t len;
2118	int rc, to_read = 2;
2119
2120	role = calloc(1, sizeof(role_datum_t));
2121	if (!role)
2122		return -1;
2123
2124	if (policydb_has_boundary_feature(p))
2125		to_read = 3;
2126
2127	rc = next_entry(buf, fp, sizeof(uint32_t) * to_read);
2128	if (rc < 0)
2129		goto bad;
2130
2131	len = le32_to_cpu(buf[0]);
2132	role->s.value = le32_to_cpu(buf[1]);
2133	if (policydb_has_boundary_feature(p))
2134		role->bounds = le32_to_cpu(buf[2]);
2135
2136	key = malloc(len + 1);
2137	if (!key)
2138		goto bad;
2139	rc = next_entry(key, fp, len);
2140	if (rc < 0)
2141		goto bad;
2142	key[len] = 0;
2143
2144	if (ebitmap_read(&role->dominates, fp))
2145		goto bad;
2146
2147	if (p->policy_type == POLICY_KERN) {
2148		if (ebitmap_read(&role->types.types, fp))
2149			goto bad;
2150	} else {
2151		if (type_set_read(&role->types, fp))
2152			goto bad;
2153	}
2154
2155	if (p->policy_type != POLICY_KERN &&
2156	    p->policyvers >= MOD_POLICYDB_VERSION_ROLEATTRIB) {
2157		rc = next_entry(buf, fp, sizeof(uint32_t));
2158		if (rc < 0)
2159			goto bad;
2160
2161		role->flavor = le32_to_cpu(buf[0]);
2162
2163		if (ebitmap_read(&role->roles, fp))
2164			goto bad;
2165	}
2166
2167	if (strcmp(key, OBJECT_R) == 0) {
2168		if (role->s.value != OBJECT_R_VAL) {
2169			ERR(fp->handle, "role %s has wrong value %d",
2170			    OBJECT_R, role->s.value);
2171			role_destroy(key, role, NULL);
2172			return -1;
2173		}
2174		role_destroy(key, role, NULL);
2175		return 0;
2176	}
2177
2178	if (hashtab_insert(h, key, role))
2179		goto bad;
2180
2181	return 0;
2182
2183      bad:
2184	role_destroy(key, role, NULL);
2185	return -1;
2186}
2187
2188static int type_read(policydb_t * p
2189		     __attribute__ ((unused)), hashtab_t h,
2190		     struct policy_file *fp)
2191{
2192	char *key = 0;
2193	type_datum_t *typdatum;
2194	uint32_t buf[5];
2195	size_t len;
2196	int rc, to_read;
2197	int pos = 0;
2198
2199	typdatum = calloc(1, sizeof(type_datum_t));
2200	if (!typdatum)
2201		return -1;
2202
2203	if (policydb_has_boundary_feature(p)) {
2204		if (p->policy_type != POLICY_KERN
2205		    && p->policyvers >= MOD_POLICYDB_VERSION_BOUNDARY_ALIAS)
2206			to_read = 5;
2207		else
2208			to_read = 4;
2209	}
2210	else if (p->policy_type == POLICY_KERN)
2211		to_read = 3;
2212	else if (p->policyvers >= MOD_POLICYDB_VERSION_PERMISSIVE)
2213		to_read = 5;
2214	else
2215		to_read = 4;
2216
2217	rc = next_entry(buf, fp, sizeof(uint32_t) * to_read);
2218	if (rc < 0)
2219		goto bad;
2220
2221	len = le32_to_cpu(buf[pos]);
2222	typdatum->s.value = le32_to_cpu(buf[++pos]);
2223	if (policydb_has_boundary_feature(p)) {
2224		uint32_t properties;
2225
2226		if (p->policy_type != POLICY_KERN
2227		    && p->policyvers >= MOD_POLICYDB_VERSION_BOUNDARY_ALIAS) {
2228			typdatum->primary = le32_to_cpu(buf[++pos]);
2229			properties = le32_to_cpu(buf[++pos]);
2230		}
2231		else {
2232			properties = le32_to_cpu(buf[++pos]);
2233
2234			if (properties & TYPEDATUM_PROPERTY_PRIMARY)
2235				typdatum->primary = 1;
2236		}
2237
2238		if (properties & TYPEDATUM_PROPERTY_ATTRIBUTE)
2239			typdatum->flavor = TYPE_ATTRIB;
2240		if (properties & TYPEDATUM_PROPERTY_ALIAS
2241		    && p->policy_type != POLICY_KERN)
2242			typdatum->flavor = TYPE_ALIAS;
2243		if (properties & TYPEDATUM_PROPERTY_PERMISSIVE
2244		    && p->policy_type != POLICY_KERN)
2245			typdatum->flags |= TYPE_FLAGS_PERMISSIVE;
2246
2247		typdatum->bounds = le32_to_cpu(buf[++pos]);
2248	} else {
2249		typdatum->primary = le32_to_cpu(buf[++pos]);
2250		if (p->policy_type != POLICY_KERN) {
2251			typdatum->flavor = le32_to_cpu(buf[++pos]);
2252			if (p->policyvers >= MOD_POLICYDB_VERSION_PERMISSIVE)
2253				typdatum->flags = le32_to_cpu(buf[++pos]);
2254		}
2255	}
2256
2257	if (p->policy_type != POLICY_KERN) {
2258		if (ebitmap_read(&typdatum->types, fp))
2259			goto bad;
2260	}
2261
2262	key = malloc(len + 1);
2263	if (!key)
2264		goto bad;
2265	rc = next_entry(key, fp, len);
2266	if (rc < 0)
2267		goto bad;
2268	key[len] = 0;
2269
2270	if (hashtab_insert(h, key, typdatum))
2271		goto bad;
2272
2273	return 0;
2274
2275      bad:
2276	type_destroy(key, typdatum, NULL);
2277	return -1;
2278}
2279
2280int role_trans_read(policydb_t *p, struct policy_file *fp)
2281{
2282	role_trans_t **t = &p->role_tr;
2283	unsigned int i;
2284	uint32_t buf[3], nel;
2285	role_trans_t *tr, *ltr;
2286	int rc;
2287	int new_roletr = (p->policy_type == POLICY_KERN &&
2288			  p->policyvers >= POLICYDB_VERSION_ROLETRANS);
2289
2290	rc = next_entry(buf, fp, sizeof(uint32_t));
2291	if (rc < 0)
2292		return -1;
2293	nel = le32_to_cpu(buf[0]);
2294	ltr = NULL;
2295	for (i = 0; i < nel; i++) {
2296		tr = calloc(1, sizeof(struct role_trans));
2297		if (!tr) {
2298			return -1;
2299		}
2300		if (ltr) {
2301			ltr->next = tr;
2302		} else {
2303			*t = tr;
2304		}
2305		rc = next_entry(buf, fp, sizeof(uint32_t) * 3);
2306		if (rc < 0)
2307			return -1;
2308		tr->role = le32_to_cpu(buf[0]);
2309		tr->type = le32_to_cpu(buf[1]);
2310		tr->new_role = le32_to_cpu(buf[2]);
2311		if (new_roletr) {
2312			rc = next_entry(buf, fp, sizeof(uint32_t));
2313			if (rc < 0)
2314				return -1;
2315			tr->tclass = le32_to_cpu(buf[0]);
2316		} else
2317			tr->tclass = SECCLASS_PROCESS;
2318		ltr = tr;
2319	}
2320	return 0;
2321}
2322
2323int role_allow_read(role_allow_t ** r, struct policy_file *fp)
2324{
2325	unsigned int i;
2326	uint32_t buf[2], nel;
2327	role_allow_t *ra, *lra;
2328	int rc;
2329
2330	rc = next_entry(buf, fp, sizeof(uint32_t));
2331	if (rc < 0)
2332		return -1;
2333	nel = le32_to_cpu(buf[0]);
2334	lra = NULL;
2335	for (i = 0; i < nel; i++) {
2336		ra = calloc(1, sizeof(struct role_allow));
2337		if (!ra) {
2338			return -1;
2339		}
2340		if (lra) {
2341			lra->next = ra;
2342		} else {
2343			*r = ra;
2344		}
2345		rc = next_entry(buf, fp, sizeof(uint32_t) * 2);
2346		if (rc < 0)
2347			return -1;
2348		ra->role = le32_to_cpu(buf[0]);
2349		ra->new_role = le32_to_cpu(buf[1]);
2350		lra = ra;
2351	}
2352	return 0;
2353}
2354
2355int filename_trans_read(filename_trans_t **t, struct policy_file *fp)
2356{
2357	unsigned int i;
2358	uint32_t buf[4], nel, len;
2359	filename_trans_t *ft, *lft;
2360	int rc;
2361	char *name;
2362
2363	rc = next_entry(buf, fp, sizeof(uint32_t));
2364	if (rc < 0)
2365		return -1;
2366	nel = le32_to_cpu(buf[0]);
2367
2368	lft = NULL;
2369	for (i = 0; i < nel; i++) {
2370		ft = calloc(1, sizeof(struct filename_trans));
2371		if (!ft)
2372			return -1;
2373		if (lft)
2374			lft->next = ft;
2375		else
2376			*t = ft;
2377		lft = ft;
2378		rc = next_entry(buf, fp, sizeof(uint32_t));
2379		if (rc < 0)
2380			return -1;
2381		len = le32_to_cpu(buf[0]);
2382
2383		name = calloc(len + 1, sizeof(*name));
2384		if (!name)
2385			return -1;
2386
2387		ft->name = name;
2388
2389		rc = next_entry(name, fp, len);
2390		if (rc < 0)
2391			return -1;
2392
2393		rc = next_entry(buf, fp, sizeof(uint32_t) * 4);
2394		if (rc < 0)
2395			return -1;
2396
2397		ft->stype = le32_to_cpu(buf[0]);
2398		ft->ttype = le32_to_cpu(buf[1]);
2399		ft->tclass = le32_to_cpu(buf[2]);
2400		ft->otype = le32_to_cpu(buf[3]);
2401	}
2402	return 0;
2403}
2404
2405static int ocontext_read_xen(struct policydb_compat_info *info,
2406	policydb_t *p, struct policy_file *fp)
2407{
2408	unsigned int i, j;
2409	size_t nel;
2410	ocontext_t *l, *c;
2411	uint32_t buf[8];
2412	int rc;
2413
2414	for (i = 0; i < info->ocon_num; i++) {
2415		rc = next_entry(buf, fp, sizeof(uint32_t));
2416		if (rc < 0)
2417			return -1;
2418		nel = le32_to_cpu(buf[0]);
2419		l = NULL;
2420		for (j = 0; j < nel; j++) {
2421			c = calloc(1, sizeof(ocontext_t));
2422			if (!c)
2423				return -1;
2424			if (l)
2425				l->next = c;
2426			else
2427				p->ocontexts[i] = c;
2428			l = c;
2429			switch (i) {
2430			case OCON_XEN_ISID:
2431				rc = next_entry(buf, fp, sizeof(uint32_t));
2432				if (rc < 0)
2433					return -1;
2434				c->sid[0] = le32_to_cpu(buf[0]);
2435				if (context_read_and_validate
2436				    (&c->context[0], p, fp))
2437					return -1;
2438				break;
2439			case OCON_XEN_PIRQ:
2440				rc = next_entry(buf, fp, sizeof(uint32_t));
2441				if (rc < 0)
2442					return -1;
2443				c->u.pirq = le32_to_cpu(buf[0]);
2444				if (context_read_and_validate
2445				    (&c->context[0], p, fp))
2446					return -1;
2447				break;
2448			case OCON_XEN_IOPORT:
2449				rc = next_entry(buf, fp, sizeof(uint32_t) * 2);
2450				if (rc < 0)
2451					return -1;
2452				c->u.ioport.low_ioport = le32_to_cpu(buf[0]);
2453				c->u.ioport.high_ioport = le32_to_cpu(buf[1]);
2454				if (context_read_and_validate
2455				    (&c->context[0], p, fp))
2456					return -1;
2457				break;
2458			case OCON_XEN_IOMEM:
2459				rc = next_entry(buf, fp, sizeof(uint32_t) * 2);
2460				if (rc < 0)
2461					return -1;
2462				c->u.iomem.low_iomem = le32_to_cpu(buf[0]);
2463				c->u.iomem.high_iomem = le32_to_cpu(buf[1]);
2464				if (context_read_and_validate
2465				    (&c->context[0], p, fp))
2466					return -1;
2467				break;
2468			case OCON_XEN_PCIDEVICE:
2469				rc = next_entry(buf, fp, sizeof(uint32_t));
2470				if (rc < 0)
2471					return -1;
2472				c->u.device = le32_to_cpu(buf[0]);
2473				if (context_read_and_validate
2474				    (&c->context[0], p, fp))
2475					return -1;
2476				break;
2477			default:
2478				/* should never get here */
2479				ERR(fp->handle, "Unknown Xen ocontext");
2480				return -1;
2481			}
2482		}
2483	}
2484	return 0;
2485}
2486static int ocontext_read_selinux(struct policydb_compat_info *info,
2487			 policydb_t * p, struct policy_file *fp)
2488{
2489	unsigned int i, j;
2490	size_t nel, len;
2491	ocontext_t *l, *c;
2492	uint32_t buf[8];
2493	int rc;
2494
2495	for (i = 0; i < info->ocon_num; i++) {
2496		rc = next_entry(buf, fp, sizeof(uint32_t));
2497		if (rc < 0)
2498			return -1;
2499		nel = le32_to_cpu(buf[0]);
2500		l = NULL;
2501		for (j = 0; j < nel; j++) {
2502			c = calloc(1, sizeof(ocontext_t));
2503			if (!c) {
2504				return -1;
2505			}
2506			if (l) {
2507				l->next = c;
2508			} else {
2509				p->ocontexts[i] = c;
2510			}
2511			l = c;
2512			switch (i) {
2513			case OCON_ISID:
2514				rc = next_entry(buf, fp, sizeof(uint32_t));
2515				if (rc < 0)
2516					return -1;
2517				c->sid[0] = le32_to_cpu(buf[0]);
2518				if (context_read_and_validate
2519				    (&c->context[0], p, fp))
2520					return -1;
2521				break;
2522			case OCON_FS:
2523			case OCON_NETIF:
2524				rc = next_entry(buf, fp, sizeof(uint32_t));
2525				if (rc < 0)
2526					return -1;
2527				len = le32_to_cpu(buf[0]);
2528				c->u.name = malloc(len + 1);
2529				if (!c->u.name)
2530					return -1;
2531				rc = next_entry(c->u.name, fp, len);
2532				if (rc < 0)
2533					return -1;
2534				c->u.name[len] = 0;
2535				if (context_read_and_validate
2536				    (&c->context[0], p, fp))
2537					return -1;
2538				if (context_read_and_validate
2539				    (&c->context[1], p, fp))
2540					return -1;
2541				break;
2542			case OCON_PORT:
2543				rc = next_entry(buf, fp, sizeof(uint32_t) * 3);
2544				if (rc < 0)
2545					return -1;
2546				c->u.port.protocol = le32_to_cpu(buf[0]);
2547				c->u.port.low_port = le32_to_cpu(buf[1]);
2548				c->u.port.high_port = le32_to_cpu(buf[2]);
2549				if (context_read_and_validate
2550				    (&c->context[0], p, fp))
2551					return -1;
2552				break;
2553			case OCON_NODE:
2554				rc = next_entry(buf, fp, sizeof(uint32_t) * 2);
2555				if (rc < 0)
2556					return -1;
2557				c->u.node.addr = buf[0]; /* network order */
2558				c->u.node.mask = buf[1]; /* network order */
2559				if (context_read_and_validate
2560				    (&c->context[0], p, fp))
2561					return -1;
2562				break;
2563			case OCON_FSUSE:
2564				rc = next_entry(buf, fp, sizeof(uint32_t) * 2);
2565				if (rc < 0)
2566					return -1;
2567				c->v.behavior = le32_to_cpu(buf[0]);
2568				len = le32_to_cpu(buf[1]);
2569				c->u.name = malloc(len + 1);
2570				if (!c->u.name)
2571					return -1;
2572				rc = next_entry(c->u.name, fp, len);
2573				if (rc < 0)
2574					return -1;
2575				c->u.name[len] = 0;
2576				if (context_read_and_validate
2577				    (&c->context[0], p, fp))
2578					return -1;
2579				break;
2580			case OCON_NODE6:{
2581				int k;
2582
2583				rc = next_entry(buf, fp, sizeof(uint32_t) * 8);
2584				if (rc < 0)
2585					return -1;
2586				for (k = 0; k < 4; k++)
2587					 /* network order */
2588					c->u.node6.addr[k] = buf[k];
2589				for (k = 0; k < 4; k++)
2590					/* network order */
2591					c->u.node6.mask[k] = buf[k + 4];
2592				if (context_read_and_validate
2593				    (&c->context[0], p, fp))
2594					return -1;
2595				break;
2596				}
2597			default:{
2598				ERR(fp->handle, "Unknown SELinux ocontext");
2599				return -1;
2600				}
2601			}
2602		}
2603	}
2604	return 0;
2605}
2606
2607static int ocontext_read(struct policydb_compat_info *info,
2608	policydb_t *p, struct policy_file *fp)
2609{
2610	int rc = -1;
2611	switch (p->target_platform) {
2612	case SEPOL_TARGET_SELINUX:
2613		rc = ocontext_read_selinux(info, p, fp);
2614		break;
2615	case SEPOL_TARGET_XEN:
2616		rc = ocontext_read_xen(info, p, fp);
2617		break;
2618	default:
2619		ERR(fp->handle, "Unknown target");
2620	}
2621	return rc;
2622}
2623
2624static int genfs_read(policydb_t * p, struct policy_file *fp)
2625{
2626	uint32_t buf[1];
2627	size_t nel, nel2, len, len2;
2628	genfs_t *genfs_p, *newgenfs, *genfs;
2629	unsigned int i, j;
2630	ocontext_t *l, *c, *newc = NULL;
2631	int rc;
2632
2633	rc = next_entry(buf, fp, sizeof(uint32_t));
2634	if (rc < 0)
2635		goto bad;
2636	nel = le32_to_cpu(buf[0]);
2637	genfs_p = NULL;
2638	for (i = 0; i < nel; i++) {
2639		rc = next_entry(buf, fp, sizeof(uint32_t));
2640		if (rc < 0)
2641			goto bad;
2642		len = le32_to_cpu(buf[0]);
2643		newgenfs = calloc(1, sizeof(genfs_t));
2644		if (!newgenfs)
2645			goto bad;
2646		newgenfs->fstype = malloc(len + 1);
2647		if (!newgenfs->fstype) {
2648			free(newgenfs);
2649			goto bad;
2650		}
2651		rc = next_entry(newgenfs->fstype, fp, len);
2652		if (rc < 0) {
2653			free(newgenfs->fstype);
2654			free(newgenfs);
2655			goto bad;
2656		}
2657		newgenfs->fstype[len] = 0;
2658		for (genfs_p = NULL, genfs = p->genfs; genfs;
2659		     genfs_p = genfs, genfs = genfs->next) {
2660			if (strcmp(newgenfs->fstype, genfs->fstype) == 0) {
2661				ERR(fp->handle, "dup genfs fstype %s",
2662				    newgenfs->fstype);
2663				free(newgenfs->fstype);
2664				free(newgenfs);
2665				goto bad;
2666			}
2667			if (strcmp(newgenfs->fstype, genfs->fstype) < 0)
2668				break;
2669		}
2670		newgenfs->next = genfs;
2671		if (genfs_p)
2672			genfs_p->next = newgenfs;
2673		else
2674			p->genfs = newgenfs;
2675		rc = next_entry(buf, fp, sizeof(uint32_t));
2676		if (rc < 0)
2677			goto bad;
2678		nel2 = le32_to_cpu(buf[0]);
2679		for (j = 0; j < nel2; j++) {
2680			newc = calloc(1, sizeof(ocontext_t));
2681			if (!newc) {
2682				goto bad;
2683			}
2684			rc = next_entry(buf, fp, sizeof(uint32_t));
2685			if (rc < 0)
2686				goto bad;
2687			len = le32_to_cpu(buf[0]);
2688			newc->u.name = malloc(len + 1);
2689			if (!newc->u.name) {
2690				goto bad;
2691			}
2692			rc = next_entry(newc->u.name, fp, len);
2693			if (rc < 0)
2694				goto bad;
2695			newc->u.name[len] = 0;
2696			rc = next_entry(buf, fp, sizeof(uint32_t));
2697			if (rc < 0)
2698				goto bad;
2699			newc->v.sclass = le32_to_cpu(buf[0]);
2700			if (context_read_and_validate(&newc->context[0], p, fp))
2701				goto bad;
2702			for (l = NULL, c = newgenfs->head; c;
2703			     l = c, c = c->next) {
2704				if (!strcmp(newc->u.name, c->u.name) &&
2705				    (!c->v.sclass || !newc->v.sclass ||
2706				     newc->v.sclass == c->v.sclass)) {
2707					ERR(fp->handle, "dup genfs entry "
2708					    "(%s,%s)", newgenfs->fstype,
2709					    c->u.name);
2710					goto bad;
2711				}
2712				len = strlen(newc->u.name);
2713				len2 = strlen(c->u.name);
2714				if (len > len2)
2715					break;
2716			}
2717			newc->next = c;
2718			if (l)
2719				l->next = newc;
2720			else
2721				newgenfs->head = newc;
2722		}
2723	}
2724
2725	return 0;
2726
2727      bad:
2728	if (newc) {
2729		context_destroy(&newc->context[0]);
2730		context_destroy(&newc->context[1]);
2731		free(newc->u.name);
2732		free(newc);
2733	}
2734	return -1;
2735}
2736
2737/*
2738 * Read a MLS level structure from a policydb binary
2739 * representation file.
2740 */
2741static int mls_read_level(mls_level_t * lp, struct policy_file *fp)
2742{
2743	uint32_t buf[1];
2744	int rc;
2745
2746	mls_level_init(lp);
2747
2748	rc = next_entry(buf, fp, sizeof(uint32_t));
2749	if (rc < 0) {
2750		ERR(fp->handle, "truncated level");
2751		goto bad;
2752	}
2753	lp->sens = le32_to_cpu(buf[0]);
2754
2755	if (ebitmap_read(&lp->cat, fp)) {
2756		ERR(fp->handle, "error reading level categories");
2757		goto bad;
2758	}
2759	return 0;
2760
2761      bad:
2762	return -EINVAL;
2763}
2764
2765static int user_read(policydb_t * p, hashtab_t h, struct policy_file *fp)
2766{
2767	char *key = 0;
2768	user_datum_t *usrdatum;
2769	uint32_t buf[3];
2770	size_t len;
2771	int rc, to_read = 2;
2772
2773	usrdatum = calloc(1, sizeof(user_datum_t));
2774	if (!usrdatum)
2775		return -1;
2776
2777	if (policydb_has_boundary_feature(p))
2778		to_read = 3;
2779
2780	rc = next_entry(buf, fp, sizeof(uint32_t) * to_read);
2781	if (rc < 0)
2782		goto bad;
2783
2784	len = le32_to_cpu(buf[0]);
2785	usrdatum->s.value = le32_to_cpu(buf[1]);
2786	if (policydb_has_boundary_feature(p))
2787		usrdatum->bounds = le32_to_cpu(buf[2]);
2788
2789	key = malloc(len + 1);
2790	if (!key)
2791		goto bad;
2792	rc = next_entry(key, fp, len);
2793	if (rc < 0)
2794		goto bad;
2795	key[len] = 0;
2796
2797	if (p->policy_type == POLICY_KERN) {
2798		if (ebitmap_read(&usrdatum->roles.roles, fp))
2799			goto bad;
2800	} else {
2801		if (role_set_read(&usrdatum->roles, fp))
2802			goto bad;
2803	}
2804
2805	/* users were not allowed in mls modules before version
2806	 * MOD_POLICYDB_VERSION_MLS_USERS, but they could have been
2807	 * required - the mls fields will be empty.  user declarations in
2808	 * non-mls modules will also have empty mls fields */
2809	if ((p->policy_type == POLICY_KERN
2810	     && p->policyvers >= POLICYDB_VERSION_MLS)
2811	    || (p->policy_type == POLICY_MOD
2812		&& p->policyvers >= MOD_POLICYDB_VERSION_MLS
2813		&& p->policyvers < MOD_POLICYDB_VERSION_MLS_USERS)
2814	    || (p->policy_type == POLICY_BASE
2815		&& p->policyvers >= MOD_POLICYDB_VERSION_MLS
2816		&& p->policyvers < MOD_POLICYDB_VERSION_MLS_USERS)) {
2817		if (mls_read_range_helper(&usrdatum->exp_range, fp))
2818			goto bad;
2819		if (mls_read_level(&usrdatum->exp_dfltlevel, fp))
2820			goto bad;
2821		if (p->policy_type != POLICY_KERN) {
2822			if (mls_range_to_semantic(&usrdatum->exp_range,
2823						  &usrdatum->range))
2824				goto bad;
2825			if (mls_level_to_semantic(&usrdatum->exp_dfltlevel,
2826						  &usrdatum->dfltlevel))
2827				goto bad;
2828		}
2829	} else if ((p->policy_type == POLICY_MOD
2830		    && p->policyvers >= MOD_POLICYDB_VERSION_MLS_USERS)
2831		   || (p->policy_type == POLICY_BASE
2832		       && p->policyvers >= MOD_POLICYDB_VERSION_MLS_USERS)) {
2833		if (mls_read_semantic_range_helper(&usrdatum->range, fp))
2834			goto bad;
2835		if (mls_read_semantic_level_helper(&usrdatum->dfltlevel, fp))
2836			goto bad;
2837	}
2838
2839	if (hashtab_insert(h, key, usrdatum))
2840		goto bad;
2841
2842	return 0;
2843
2844      bad:
2845	user_destroy(key, usrdatum, NULL);
2846	return -1;
2847}
2848
2849static int sens_read(policydb_t * p
2850		     __attribute__ ((unused)), hashtab_t h,
2851		     struct policy_file *fp)
2852{
2853	char *key = 0;
2854	level_datum_t *levdatum;
2855	uint32_t buf[2], len;
2856	int rc;
2857
2858	levdatum = malloc(sizeof(level_datum_t));
2859	if (!levdatum)
2860		return -1;
2861	level_datum_init(levdatum);
2862
2863	rc = next_entry(buf, fp, (sizeof(uint32_t) * 2));
2864	if (rc < 0)
2865		goto bad;
2866
2867	len = le32_to_cpu(buf[0]);
2868	levdatum->isalias = le32_to_cpu(buf[1]);
2869
2870	key = malloc(len + 1);
2871	if (!key)
2872		goto bad;
2873	rc = next_entry(key, fp, len);
2874	if (rc < 0)
2875		goto bad;
2876	key[len] = 0;
2877
2878	levdatum->level = malloc(sizeof(mls_level_t));
2879	if (!levdatum->level || mls_read_level(levdatum->level, fp))
2880		goto bad;
2881
2882	if (hashtab_insert(h, key, levdatum))
2883		goto bad;
2884
2885	return 0;
2886
2887      bad:
2888	sens_destroy(key, levdatum, NULL);
2889	return -1;
2890}
2891
2892static int cat_read(policydb_t * p
2893		    __attribute__ ((unused)), hashtab_t h,
2894		    struct policy_file *fp)
2895{
2896	char *key = 0;
2897	cat_datum_t *catdatum;
2898	uint32_t buf[3], len;
2899	int rc;
2900
2901	catdatum = malloc(sizeof(cat_datum_t));
2902	if (!catdatum)
2903		return -1;
2904	cat_datum_init(catdatum);
2905
2906	rc = next_entry(buf, fp, (sizeof(uint32_t) * 3));
2907	if (rc < 0)
2908		goto bad;
2909
2910	len = le32_to_cpu(buf[0]);
2911	catdatum->s.value = le32_to_cpu(buf[1]);
2912	catdatum->isalias = le32_to_cpu(buf[2]);
2913
2914	key = malloc(len + 1);
2915	if (!key)
2916		goto bad;
2917	rc = next_entry(key, fp, len);
2918	if (rc < 0)
2919		goto bad;
2920	key[len] = 0;
2921
2922	if (hashtab_insert(h, key, catdatum))
2923		goto bad;
2924
2925	return 0;
2926
2927      bad:
2928	cat_destroy(key, catdatum, NULL);
2929	return -1;
2930}
2931
2932static int (*read_f[SYM_NUM]) (policydb_t * p, hashtab_t h,
2933			       struct policy_file * fp) = {
2934common_read, class_read, role_read, type_read, user_read,
2935	    cond_read_bool, sens_read, cat_read,};
2936
2937/************** module reading functions below **************/
2938
2939static avrule_t *avrule_read(policydb_t * p
2940			     __attribute__ ((unused)), struct policy_file *fp)
2941{
2942	unsigned int i;
2943	uint32_t buf[2], len;
2944	class_perm_node_t *cur, *tail = NULL;
2945	avrule_t *avrule;
2946	int rc;
2947
2948	avrule = (avrule_t *) malloc(sizeof(avrule_t));
2949	if (!avrule)
2950		return NULL;
2951
2952	avrule_init(avrule);
2953
2954	rc = next_entry(buf, fp, sizeof(uint32_t) * 2);
2955	if (rc < 0)
2956		goto bad;
2957
2958	(avrule)->specified = le32_to_cpu(buf[0]);
2959	(avrule)->flags = le32_to_cpu(buf[1]);
2960
2961	if (type_set_read(&avrule->stypes, fp))
2962		goto bad;
2963
2964	if (type_set_read(&avrule->ttypes, fp))
2965		goto bad;
2966
2967	rc = next_entry(buf, fp, sizeof(uint32_t));
2968	if (rc < 0)
2969		goto bad;
2970	len = le32_to_cpu(buf[0]);
2971
2972	for (i = 0; i < len; i++) {
2973		cur = (class_perm_node_t *) malloc(sizeof(class_perm_node_t));
2974		if (!cur)
2975			goto bad;
2976		class_perm_node_init(cur);
2977
2978		rc = next_entry(buf, fp, sizeof(uint32_t) * 2);
2979		if (rc < 0) {
2980			free(cur);
2981			goto bad;
2982		}
2983
2984		cur->class = le32_to_cpu(buf[0]);
2985		cur->data = le32_to_cpu(buf[1]);
2986
2987		if (!tail) {
2988			avrule->perms = cur;
2989		} else {
2990			tail->next = cur;
2991		}
2992		tail = cur;
2993	}
2994
2995	return avrule;
2996      bad:
2997	if (avrule) {
2998		avrule_destroy(avrule);
2999		free(avrule);
3000	}
3001	return NULL;
3002}
3003
3004static int range_read(policydb_t * p, struct policy_file *fp)
3005{
3006	uint32_t buf[2], nel;
3007	range_trans_t *rt, *lrt;
3008	range_trans_rule_t *rtr, *lrtr = NULL;
3009	unsigned int i;
3010	int new_rangetr = (p->policy_type == POLICY_KERN &&
3011			   p->policyvers >= POLICYDB_VERSION_RANGETRANS);
3012	int rc;
3013
3014	rc = next_entry(buf, fp, sizeof(uint32_t));
3015	if (rc < 0)
3016		return -1;
3017	nel = le32_to_cpu(buf[0]);
3018	lrt = NULL;
3019	for (i = 0; i < nel; i++) {
3020		rt = calloc(1, sizeof(range_trans_t));
3021		if (!rt)
3022			return -1;
3023		if (lrt)
3024			lrt->next = rt;
3025		else
3026			p->range_tr = rt;
3027		rc = next_entry(buf, fp, (sizeof(uint32_t) * 2));
3028		if (rc < 0)
3029			return -1;
3030		rt->source_type = le32_to_cpu(buf[0]);
3031		rt->target_type = le32_to_cpu(buf[1]);
3032		if (new_rangetr) {
3033			rc = next_entry(buf, fp, (sizeof(uint32_t)));
3034			if (rc < 0)
3035				return -1;
3036			rt->target_class = le32_to_cpu(buf[0]);
3037		} else
3038			rt->target_class = SECCLASS_PROCESS;
3039		if (mls_read_range_helper(&rt->target_range, fp))
3040			return -1;
3041		lrt = rt;
3042	}
3043
3044	/* if this is a kernel policy, we are done - otherwise we need to
3045	 * convert these structs to range_trans_rule_ts */
3046	if (p->policy_type == POLICY_KERN)
3047		return 0;
3048
3049	/* create range_trans_rules_ts that correspond to the range_trans_ts
3050	 * that were just read in from an older policy */
3051	for (rt = p->range_tr; rt; rt = rt->next) {
3052		rtr = malloc(sizeof(range_trans_rule_t));
3053		if (!rtr) {
3054			return -1;
3055		}
3056		range_trans_rule_init(rtr);
3057
3058		if (lrtr)
3059			lrtr->next = rtr;
3060		else
3061			p->global->enabled->range_tr_rules = rtr;
3062
3063		if (ebitmap_set_bit(&rtr->stypes.types, rt->source_type - 1, 1))
3064			return -1;
3065
3066		if (ebitmap_set_bit(&rtr->ttypes.types, rt->target_type - 1, 1))
3067			return -1;
3068
3069		if (ebitmap_set_bit(&rtr->tclasses, rt->target_class - 1, 1))
3070			return -1;
3071
3072		if (mls_range_to_semantic(&rt->target_range, &rtr->trange))
3073			return -1;
3074
3075		lrtr = rtr;
3076	}
3077
3078	/* now destroy the range_trans_ts */
3079	lrt = NULL;
3080	for (rt = p->range_tr; rt; rt = rt->next) {
3081		if (lrt) {
3082			ebitmap_destroy(&lrt->target_range.level[0].cat);
3083			ebitmap_destroy(&lrt->target_range.level[1].cat);
3084			free(lrt);
3085		}
3086		lrt = rt;
3087	}
3088	if (lrt) {
3089		ebitmap_destroy(&lrt->target_range.level[0].cat);
3090		ebitmap_destroy(&lrt->target_range.level[1].cat);
3091		free(lrt);
3092	}
3093	p->range_tr = NULL;
3094
3095	return 0;
3096}
3097
3098int avrule_read_list(policydb_t * p, avrule_t ** avrules,
3099		     struct policy_file *fp)
3100{
3101	unsigned int i;
3102	avrule_t *cur, *tail;
3103	uint32_t buf[1], len;
3104	int rc;
3105
3106	*avrules = tail = NULL;
3107
3108	rc = next_entry(buf, fp, sizeof(uint32_t));
3109	if (rc < 0) {
3110		return -1;
3111	}
3112	len = le32_to_cpu(buf[0]);
3113
3114	for (i = 0; i < len; i++) {
3115		cur = avrule_read(p, fp);
3116		if (!cur) {
3117			return -1;
3118		}
3119
3120		if (!tail) {
3121			*avrules = cur;
3122		} else {
3123			tail->next = cur;
3124		}
3125		tail = cur;
3126	}
3127
3128	return 0;
3129}
3130
3131static int role_trans_rule_read(policydb_t *p, role_trans_rule_t ** r,
3132				struct policy_file *fp)
3133{
3134	uint32_t buf[1], nel;
3135	unsigned int i;
3136	role_trans_rule_t *tr, *ltr;
3137	int rc;
3138
3139	rc = next_entry(buf, fp, sizeof(uint32_t));
3140	if (rc < 0)
3141		return -1;
3142	nel = le32_to_cpu(buf[0]);
3143	ltr = NULL;
3144	for (i = 0; i < nel; i++) {
3145		tr = malloc(sizeof(role_trans_rule_t));
3146		if (!tr) {
3147			return -1;
3148		}
3149		role_trans_rule_init(tr);
3150
3151		if (ltr) {
3152			ltr->next = tr;
3153		} else {
3154			*r = tr;
3155		}
3156
3157		if (role_set_read(&tr->roles, fp))
3158			return -1;
3159
3160		if (type_set_read(&tr->types, fp))
3161			return -1;
3162
3163		if (p->policyvers >= MOD_POLICYDB_VERSION_ROLETRANS) {
3164			if (ebitmap_read(&tr->classes, fp))
3165				return -1;
3166		} else {
3167			if (ebitmap_set_bit(&tr->classes, SECCLASS_PROCESS - 1, 1))
3168				return -1;
3169		}
3170
3171		rc = next_entry(buf, fp, sizeof(uint32_t));
3172		if (rc < 0)
3173			return -1;
3174		tr->new_role = le32_to_cpu(buf[0]);
3175		ltr = tr;
3176	}
3177
3178	return 0;
3179}
3180
3181static int role_allow_rule_read(role_allow_rule_t ** r, struct policy_file *fp)
3182{
3183	unsigned int i;
3184	uint32_t buf[1], nel;
3185	role_allow_rule_t *ra, *lra;
3186	int rc;
3187
3188	rc = next_entry(buf, fp, sizeof(uint32_t));
3189	if (rc < 0)
3190		return -1;
3191	nel = le32_to_cpu(buf[0]);
3192	lra = NULL;
3193	for (i = 0; i < nel; i++) {
3194		ra = malloc(sizeof(role_allow_rule_t));
3195		if (!ra) {
3196			return -1;
3197		}
3198		role_allow_rule_init(ra);
3199
3200		if (lra) {
3201			lra->next = ra;
3202		} else {
3203			*r = ra;
3204		}
3205
3206		if (role_set_read(&ra->roles, fp))
3207			return -1;
3208
3209		if (role_set_read(&ra->new_roles, fp))
3210			return -1;
3211
3212		lra = ra;
3213	}
3214	return 0;
3215}
3216
3217static int filename_trans_rule_read(filename_trans_rule_t ** r, struct policy_file *fp)
3218{
3219	uint32_t buf[2], nel;
3220	unsigned int i, len;
3221	filename_trans_rule_t *ftr, *lftr;
3222	int rc;
3223
3224	rc = next_entry(buf, fp, sizeof(uint32_t));
3225	if (rc < 0)
3226		return -1;
3227	nel = le32_to_cpu(buf[0]);
3228	lftr = NULL;
3229	for (i = 0; i < nel; i++) {
3230		ftr = malloc(sizeof(*ftr));
3231		if (!ftr)
3232			return -1;
3233
3234		filename_trans_rule_init(ftr);
3235
3236		if (lftr)
3237			lftr->next = ftr;
3238		else
3239			*r = ftr;
3240		lftr = ftr;
3241
3242		rc = next_entry(buf, fp, sizeof(uint32_t));
3243		if (rc < 0)
3244			return -1;
3245
3246		len = le32_to_cpu(buf[0]);
3247
3248		ftr->name = malloc(len + 1);
3249		if (!ftr->name)
3250			return -1;
3251
3252		rc = next_entry(ftr->name, fp, len);
3253		if (rc)
3254			return -1;
3255		ftr->name[len] = 0;
3256
3257		if (type_set_read(&ftr->stypes, fp))
3258			return -1;
3259
3260		if (type_set_read(&ftr->ttypes, fp))
3261			return -1;
3262
3263		rc = next_entry(buf, fp, sizeof(uint32_t) * 2);
3264		if (rc < 0)
3265			return -1;
3266		ftr->tclass = le32_to_cpu(buf[0]);
3267		ftr->otype = le32_to_cpu(buf[1]);
3268	}
3269
3270	return 0;
3271}
3272
3273static int range_trans_rule_read(range_trans_rule_t ** r,
3274				 struct policy_file *fp)
3275{
3276	uint32_t buf[1], nel;
3277	unsigned int i;
3278	range_trans_rule_t *rt, *lrt = NULL;
3279	int rc;
3280
3281	rc = next_entry(buf, fp, sizeof(uint32_t));
3282	if (rc < 0)
3283		return -1;
3284	nel = le32_to_cpu(buf[0]);
3285	for (i = 0; i < nel; i++) {
3286		rt = malloc(sizeof(range_trans_rule_t));
3287		if (!rt) {
3288			return -1;
3289		}
3290		range_trans_rule_init(rt);
3291
3292		if (lrt)
3293			lrt->next = rt;
3294		else
3295			*r = rt;
3296
3297		if (type_set_read(&rt->stypes, fp))
3298			return -1;
3299
3300		if (type_set_read(&rt->ttypes, fp))
3301			return -1;
3302
3303		if (ebitmap_read(&rt->tclasses, fp))
3304			return -1;
3305
3306		if (mls_read_semantic_range_helper(&rt->trange, fp))
3307			return -1;
3308
3309		lrt = rt;
3310	}
3311
3312	return 0;
3313}
3314
3315static int scope_index_read(scope_index_t * scope_index,
3316			    unsigned int num_scope_syms, struct policy_file *fp)
3317{
3318	unsigned int i;
3319	uint32_t buf[1];
3320	int rc;
3321
3322	for (i = 0; i < num_scope_syms; i++) {
3323		if (ebitmap_read(scope_index->scope + i, fp) == -1) {
3324			return -1;
3325		}
3326	}
3327	rc = next_entry(buf, fp, sizeof(uint32_t));
3328	if (rc < 0)
3329		return -1;
3330	scope_index->class_perms_len = le32_to_cpu(buf[0]);
3331	if (scope_index->class_perms_len == 0) {
3332		scope_index->class_perms_map = NULL;
3333		return 0;
3334	}
3335	if ((scope_index->class_perms_map =
3336	     calloc(scope_index->class_perms_len,
3337		    sizeof(*scope_index->class_perms_map))) == NULL) {
3338		return -1;
3339	}
3340	for (i = 0; i < scope_index->class_perms_len; i++) {
3341		if (ebitmap_read(scope_index->class_perms_map + i, fp) == -1) {
3342			return -1;
3343		}
3344	}
3345	return 0;
3346}
3347
3348static int avrule_decl_read(policydb_t * p, avrule_decl_t * decl,
3349			    unsigned int num_scope_syms, struct policy_file *fp)
3350{
3351	uint32_t buf[2], nprim, nel;
3352	unsigned int i, j;
3353	int rc;
3354
3355	rc = next_entry(buf, fp, sizeof(uint32_t) * 2);
3356	if (rc < 0)
3357		return -1;
3358	decl->decl_id = le32_to_cpu(buf[0]);
3359	decl->enabled = le32_to_cpu(buf[1]);
3360	if (cond_read_list(p, &decl->cond_list, fp) == -1 ||
3361	    avrule_read_list(p, &decl->avrules, fp) == -1 ||
3362	    role_trans_rule_read(p, &decl->role_tr_rules, fp) == -1 ||
3363	    role_allow_rule_read(&decl->role_allow_rules, fp) == -1) {
3364		return -1;
3365	}
3366
3367	if (p->policyvers >= MOD_POLICYDB_VERSION_FILENAME_TRANS &&
3368	    filename_trans_rule_read(&decl->filename_trans_rules, fp))
3369		return -1;
3370
3371	if (p->policyvers >= MOD_POLICYDB_VERSION_RANGETRANS &&
3372	    range_trans_rule_read(&decl->range_tr_rules, fp) == -1) {
3373		return -1;
3374	}
3375	if (scope_index_read(&decl->required, num_scope_syms, fp) == -1 ||
3376	    scope_index_read(&decl->declared, num_scope_syms, fp) == -1) {
3377		return -1;
3378	}
3379
3380	for (i = 0; i < num_scope_syms; i++) {
3381		rc = next_entry(buf, fp, sizeof(uint32_t) * 2);
3382		if (rc < 0)
3383			return -1;
3384		nprim = le32_to_cpu(buf[0]);
3385		nel = le32_to_cpu(buf[1]);
3386		for (j = 0; j < nel; j++) {
3387			if (read_f[i] (p, decl->symtab[i].table, fp)) {
3388				return -1;
3389			}
3390		}
3391		decl->symtab[i].nprim = nprim;
3392	}
3393	return 0;
3394}
3395
3396static int avrule_block_read(policydb_t * p,
3397			     avrule_block_t ** block,
3398			     unsigned int num_scope_syms,
3399			     struct policy_file *fp)
3400{
3401	avrule_block_t *last_block = NULL, *curblock;
3402	uint32_t buf[1], num_blocks, nel;
3403	int rc;
3404
3405	rc = next_entry(buf, fp, sizeof(uint32_t));
3406	if (rc < 0)
3407		return -1;
3408	num_blocks = le32_to_cpu(buf[0]);
3409	nel = num_blocks;
3410	while (num_blocks > 0) {
3411		avrule_decl_t *last_decl = NULL, *curdecl;
3412		uint32_t num_decls;
3413		if ((curblock = calloc(1, sizeof(*curblock))) == NULL) {
3414			return -1;
3415		}
3416		rc = next_entry(buf, fp, sizeof(uint32_t));
3417		if (rc < 0) {
3418			free(curblock);
3419			return -1;
3420		}
3421		/* if this is the first block its non-optional, else its optional */
3422		if (num_blocks != nel)
3423			curblock->flags |= AVRULE_OPTIONAL;
3424
3425		num_decls = le32_to_cpu(buf[0]);
3426		while (num_decls > 0) {
3427			if ((curdecl = avrule_decl_create(0)) == NULL) {
3428				avrule_block_destroy(curblock);
3429				return -1;
3430			}
3431			if (avrule_decl_read(p, curdecl, num_scope_syms, fp) ==
3432			    -1) {
3433				avrule_decl_destroy(curdecl);
3434				avrule_block_destroy(curblock);
3435				return -1;
3436			}
3437			if (curdecl->enabled) {
3438				if (curblock->enabled != NULL) {
3439					/* probably a corrupt file */
3440					avrule_decl_destroy(curdecl);
3441					avrule_block_destroy(curblock);
3442					return -1;
3443				}
3444				curblock->enabled = curdecl;
3445			}
3446			/* one must be careful to reconstruct the
3447			 * decl chain in its correct order */
3448			if (curblock->branch_list == NULL) {
3449				curblock->branch_list = curdecl;
3450			} else {
3451				last_decl->next = curdecl;
3452			}
3453			last_decl = curdecl;
3454			num_decls--;
3455		}
3456
3457		if (*block == NULL) {
3458			*block = curblock;
3459		} else {
3460			last_block->next = curblock;
3461		}
3462		last_block = curblock;
3463
3464		num_blocks--;
3465	}
3466
3467	return 0;
3468}
3469
3470static int scope_read(policydb_t * p, int symnum, struct policy_file *fp)
3471{
3472	scope_datum_t *scope = NULL;
3473	uint32_t buf[2];
3474	char *key = NULL;
3475	size_t key_len;
3476	unsigned int i;
3477	hashtab_t h = p->scope[symnum].table;
3478	int rc;
3479
3480	rc = next_entry(buf, fp, sizeof(uint32_t));
3481	if (rc < 0)
3482		goto cleanup;
3483	key_len = le32_to_cpu(buf[0]);
3484	key = malloc(key_len + 1);
3485	if (!key)
3486		goto cleanup;
3487	rc = next_entry(key, fp, key_len);
3488	if (rc < 0)
3489		goto cleanup;
3490	key[key_len] = '\0';
3491
3492	/* ensure that there already exists a symbol with this key */
3493	if (hashtab_search(p->symtab[symnum].table, key) == NULL) {
3494		goto cleanup;
3495	}
3496
3497	if ((scope = calloc(1, sizeof(*scope))) == NULL) {
3498		goto cleanup;
3499	}
3500	rc = next_entry(buf, fp, sizeof(uint32_t) * 2);
3501	if (rc < 0)
3502		goto cleanup;
3503	scope->scope = le32_to_cpu(buf[0]);
3504	scope->decl_ids_len = le32_to_cpu(buf[1]);
3505	assert(scope->decl_ids_len > 0);
3506	if ((scope->decl_ids =
3507	     malloc(scope->decl_ids_len * sizeof(uint32_t))) == NULL) {
3508		goto cleanup;
3509	}
3510	rc = next_entry(scope->decl_ids, fp, sizeof(uint32_t) * scope->decl_ids_len);
3511	if (rc < 0)
3512		goto cleanup;
3513	for (i = 0; i < scope->decl_ids_len; i++) {
3514		scope->decl_ids[i] = le32_to_cpu(scope->decl_ids[i]);
3515	}
3516
3517	if (strcmp(key, "object_r") == 0 && h == p->p_roles_scope.table) {
3518		/* object_r was already added to this table in roles_init() */
3519		scope_destroy(key, scope, NULL);
3520	} else {
3521		if (hashtab_insert(h, key, scope)) {
3522			goto cleanup;
3523		}
3524	}
3525
3526	return 0;
3527
3528      cleanup:
3529	scope_destroy(key, scope, NULL);
3530	return -1;
3531}
3532
3533/*
3534 * Read the configuration data from a policy database binary
3535 * representation file into a policy database structure.
3536 */
3537int policydb_read(policydb_t * p, struct policy_file *fp, unsigned verbose)
3538{
3539
3540	unsigned int i, j, r_policyvers;
3541	uint32_t buf[5];
3542	size_t len, nprim, nel;
3543	char *policydb_str;
3544	struct policydb_compat_info *info;
3545	unsigned int policy_type, bufindex;
3546	ebitmap_node_t *tnode;
3547	int rc;
3548
3549	/* Read the magic number and string length. */
3550	rc = next_entry(buf, fp, sizeof(uint32_t) * 2);
3551	if (rc < 0)
3552		return POLICYDB_ERROR;
3553	for (i = 0; i < 2; i++)
3554		buf[i] = le32_to_cpu(buf[i]);
3555
3556	if (buf[0] == POLICYDB_MAGIC) {
3557		policy_type = POLICY_KERN;
3558	} else if (buf[0] == POLICYDB_MOD_MAGIC) {
3559		policy_type = POLICY_MOD;
3560	} else {
3561		ERR(fp->handle, "policydb magic number %#08x does not "
3562		    "match expected magic number %#08x or %#08x",
3563		    buf[0], POLICYDB_MAGIC, POLICYDB_MOD_MAGIC);
3564		return POLICYDB_ERROR;
3565	}
3566
3567	len = buf[1];
3568	if (len > POLICYDB_STRING_MAX_LENGTH) {
3569		ERR(fp->handle, "policydb string length too long ");
3570		return POLICYDB_ERROR;
3571	}
3572
3573	policydb_str = malloc(len + 1);
3574	if (!policydb_str) {
3575		ERR(fp->handle, "unable to allocate memory for policydb "
3576		    "string of length %zu", len);
3577		return POLICYDB_ERROR;
3578	}
3579	rc = next_entry(policydb_str, fp, len);
3580	if (rc < 0) {
3581		ERR(fp->handle, "truncated policydb string identifier");
3582		free(policydb_str);
3583		return POLICYDB_ERROR;
3584	}
3585	policydb_str[len] = 0;
3586
3587	if (policy_type == POLICY_KERN) {
3588		for (i = 0; i < POLICYDB_TARGET_SZ; i++) {
3589			if ((strcmp(policydb_str, policydb_target_strings[i])
3590				== 0)) {
3591				policydb_set_target_platform(p, i);
3592				break;
3593			}
3594		}
3595
3596		if (i == POLICYDB_TARGET_SZ) {
3597			ERR(fp->handle, "cannot find a valid target for policy "
3598				"string %s", policydb_str);
3599			free(policydb_str);
3600			return POLICYDB_ERROR;
3601		}
3602	} else {
3603		if (strcmp(policydb_str, POLICYDB_MOD_STRING)) {
3604			ERR(fp->handle, "invalid string identifier %s",
3605				policydb_str);
3606			free(policydb_str);
3607			return POLICYDB_ERROR;
3608		}
3609	}
3610
3611	/* Done with policydb_str. */
3612	free(policydb_str);
3613	policydb_str = NULL;
3614
3615	/* Read the version, config, and table sizes (and policy type if it's a module). */
3616	if (policy_type == POLICY_KERN)
3617		nel = 4;
3618	else
3619		nel = 5;
3620
3621	rc = next_entry(buf, fp, sizeof(uint32_t) * nel);
3622	if (rc < 0)
3623		return POLICYDB_ERROR;
3624	for (i = 0; i < nel; i++)
3625		buf[i] = le32_to_cpu(buf[i]);
3626
3627	bufindex = 0;
3628
3629	if (policy_type == POLICY_MOD) {
3630		/* We know it's a module but not whether it's a base
3631		   module or regular binary policy module.  buf[0]
3632		   tells us which. */
3633		policy_type = buf[bufindex];
3634		if (policy_type != POLICY_MOD && policy_type != POLICY_BASE) {
3635			ERR(fp->handle, "unknown module type: %#08x",
3636			    policy_type);
3637			return POLICYDB_ERROR;
3638		}
3639		bufindex++;
3640	}
3641
3642	r_policyvers = buf[bufindex];
3643	if (policy_type == POLICY_KERN) {
3644		if (r_policyvers < POLICYDB_VERSION_MIN ||
3645		    r_policyvers > POLICYDB_VERSION_MAX) {
3646			ERR(fp->handle, "policydb version %d does not match "
3647			    "my version range %d-%d", buf[bufindex],
3648			    POLICYDB_VERSION_MIN, POLICYDB_VERSION_MAX);
3649			return POLICYDB_ERROR;
3650		}
3651	} else if (policy_type == POLICY_BASE || policy_type == POLICY_MOD) {
3652		if (r_policyvers < MOD_POLICYDB_VERSION_MIN ||
3653		    r_policyvers > MOD_POLICYDB_VERSION_MAX) {
3654			ERR(fp->handle, "policydb module version %d does "
3655			    "not match my version range %d-%d",
3656			    buf[bufindex], MOD_POLICYDB_VERSION_MIN,
3657			    MOD_POLICYDB_VERSION_MAX);
3658			return POLICYDB_ERROR;
3659		}
3660	} else {
3661		assert(0);
3662	}
3663	bufindex++;
3664
3665	/* Set the policy type and version from the read values. */
3666	p->policy_type = policy_type;
3667	p->policyvers = r_policyvers;
3668
3669	if (buf[bufindex] & POLICYDB_CONFIG_MLS) {
3670		p->mls = 1;
3671	} else {
3672		p->mls = 0;
3673	}
3674
3675	p->handle_unknown = buf[bufindex] & POLICYDB_CONFIG_UNKNOWN_MASK;
3676
3677	bufindex++;
3678
3679	info = policydb_lookup_compat(r_policyvers, policy_type,
3680					p->target_platform);
3681	if (!info) {
3682		ERR(fp->handle, "unable to find policy compat info "
3683		    "for version %d", r_policyvers);
3684		goto bad;
3685	}
3686
3687	if (buf[bufindex] != info->sym_num
3688	    || buf[bufindex + 1] != info->ocon_num) {
3689		ERR(fp->handle,
3690		    "policydb table sizes (%d,%d) do not " "match mine (%d,%d)",
3691		    buf[bufindex], buf[bufindex + 1], info->sym_num,
3692		    info->ocon_num);
3693		goto bad;
3694	}
3695
3696	if (p->policy_type == POLICY_MOD) {
3697		/* Get the module name and version */
3698		if ((rc = next_entry(buf, fp, sizeof(uint32_t))) < 0) {
3699			goto bad;
3700		}
3701		len = le32_to_cpu(buf[0]);
3702		if ((p->name = malloc(len + 1)) == NULL) {
3703			goto bad;
3704		}
3705		if ((rc = next_entry(p->name, fp, len)) < 0) {
3706			goto bad;
3707		}
3708		p->name[len] = '\0';
3709		if ((rc = next_entry(buf, fp, sizeof(uint32_t))) < 0) {
3710			goto bad;
3711		}
3712		len = le32_to_cpu(buf[0]);
3713		if ((p->version = malloc(len + 1)) == NULL) {
3714			goto bad;
3715		}
3716		if ((rc = next_entry(p->version, fp, len)) < 0) {
3717			goto bad;
3718		}
3719		p->version[len] = '\0';
3720	}
3721
3722	if ((p->policyvers >= POLICYDB_VERSION_POLCAP &&
3723	     p->policy_type == POLICY_KERN) ||
3724	    (p->policyvers >= MOD_POLICYDB_VERSION_POLCAP &&
3725	     p->policy_type == POLICY_BASE) ||
3726	    (p->policyvers >= MOD_POLICYDB_VERSION_POLCAP &&
3727	     p->policy_type == POLICY_MOD)) {
3728		if (ebitmap_read(&p->policycaps, fp))
3729			goto bad;
3730	}
3731
3732	if (p->policyvers >= POLICYDB_VERSION_PERMISSIVE &&
3733	    p->policy_type == POLICY_KERN) {
3734		if (ebitmap_read(&p->permissive_map, fp))
3735			goto bad;
3736	}
3737
3738	for (i = 0; i < info->sym_num; i++) {
3739		rc = next_entry(buf, fp, sizeof(uint32_t) * 2);
3740		if (rc < 0)
3741			goto bad;
3742		nprim = le32_to_cpu(buf[0]);
3743		nel = le32_to_cpu(buf[1]);
3744		for (j = 0; j < nel; j++) {
3745			if (read_f[i] (p, p->symtab[i].table, fp))
3746				goto bad;
3747		}
3748
3749		p->symtab[i].nprim = nprim;
3750	}
3751
3752	if (policy_type == POLICY_KERN) {
3753		if (avtab_read(&p->te_avtab, fp, r_policyvers))
3754			goto bad;
3755		if (r_policyvers >= POLICYDB_VERSION_BOOL)
3756			if (cond_read_list(p, &p->cond_list, fp))
3757				goto bad;
3758		if (role_trans_read(p, fp))
3759			goto bad;
3760		if (role_allow_read(&p->role_allow, fp))
3761			goto bad;
3762		if (r_policyvers >= POLICYDB_VERSION_FILENAME_TRANS &&
3763		    filename_trans_read(&p->filename_trans, fp))
3764			goto bad;
3765	} else {
3766		/* first read the AV rule blocks, then the scope tables */
3767		avrule_block_destroy(p->global);
3768		p->global = NULL;
3769		if (avrule_block_read(p, &p->global, info->sym_num, fp) == -1) {
3770			goto bad;
3771		}
3772		for (i = 0; i < info->sym_num; i++) {
3773			if ((rc = next_entry(buf, fp, sizeof(uint32_t))) < 0) {
3774				goto bad;
3775			}
3776			nel = le32_to_cpu(buf[0]);
3777			for (j = 0; j < nel; j++) {
3778				if (scope_read(p, i, fp))
3779					goto bad;
3780			}
3781		}
3782
3783	}
3784
3785	if (policydb_index_decls(p))
3786		goto bad;
3787
3788	if (policydb_index_classes(p))
3789		goto bad;
3790
3791	if (policydb_index_others(fp->handle, p, verbose))
3792		goto bad;
3793
3794	if (ocontext_read(info, p, fp) == -1) {
3795		goto bad;
3796	}
3797
3798	if (genfs_read(p, fp) == -1) {
3799		goto bad;
3800	}
3801
3802	if ((p->policy_type == POLICY_KERN
3803	     && p->policyvers >= POLICYDB_VERSION_MLS)
3804	    || (p->policy_type == POLICY_BASE
3805		&& p->policyvers >= MOD_POLICYDB_VERSION_MLS
3806		&& p->policyvers < MOD_POLICYDB_VERSION_RANGETRANS)) {
3807		if (range_read(p, fp)) {
3808			goto bad;
3809		}
3810	}
3811
3812	if (policy_type == POLICY_KERN) {
3813		p->type_attr_map = malloc(p->p_types.nprim * sizeof(ebitmap_t));
3814		p->attr_type_map = malloc(p->p_types.nprim * sizeof(ebitmap_t));
3815		if (!p->type_attr_map || !p->attr_type_map)
3816			goto bad;
3817		for (i = 0; i < p->p_types.nprim; i++) {
3818			ebitmap_init(&p->type_attr_map[i]);
3819			ebitmap_init(&p->attr_type_map[i]);
3820		}
3821		for (i = 0; i < p->p_types.nprim; i++) {
3822			if (r_policyvers >= POLICYDB_VERSION_AVTAB) {
3823				if (ebitmap_read(&p->type_attr_map[i], fp))
3824					goto bad;
3825				ebitmap_for_each_bit(&p->type_attr_map[i],
3826						     tnode, j) {
3827					if (!ebitmap_node_get_bit(tnode, j)
3828					    || i == j)
3829						continue;
3830					if (ebitmap_set_bit
3831					    (&p->attr_type_map[j], i, 1))
3832						goto bad;
3833				}
3834			}
3835			/* add the type itself as the degenerate case */
3836			if (ebitmap_set_bit(&p->type_attr_map[i], i, 1))
3837				goto bad;
3838		}
3839	}
3840
3841	return POLICYDB_SUCCESS;
3842      bad:
3843	return POLICYDB_ERROR;
3844}
3845
3846int policydb_reindex_users(policydb_t * p)
3847{
3848	unsigned int i = SYM_USERS;
3849
3850	if (p->user_val_to_struct)
3851		free(p->user_val_to_struct);
3852	if (p->sym_val_to_name[i])
3853		free(p->sym_val_to_name[i]);
3854
3855	p->user_val_to_struct = (user_datum_t **)
3856	    malloc(p->p_users.nprim * sizeof(user_datum_t *));
3857	if (!p->user_val_to_struct)
3858		return -1;
3859
3860	p->sym_val_to_name[i] = (char **)
3861	    malloc(p->symtab[i].nprim * sizeof(char *));
3862	if (!p->sym_val_to_name[i])
3863		return -1;
3864
3865	if (hashtab_map(p->symtab[i].table, index_f[i], p))
3866		return -1;
3867
3868	/* Expand user roles for context validity checking */
3869	if (hashtab_map(p->p_users.table, policydb_user_cache, p))
3870		return -1;
3871
3872	return 0;
3873}
3874
3875void policy_file_init(policy_file_t *pf)
3876{
3877	memset(pf, 0, sizeof(policy_file_t));
3878}
3879
3880int policydb_set_target_platform(policydb_t *p, int platform)
3881{
3882	if (platform == SEPOL_TARGET_SELINUX)
3883		p->target_platform = SEPOL_TARGET_SELINUX;
3884	else if (platform == SEPOL_TARGET_XEN)
3885		p->target_platform = SEPOL_TARGET_XEN;
3886	else
3887		return -1;
3888
3889	return 0;
3890}
3891
3892