18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Implementation of the policy database.
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Author : Stephen Smalley, <sds@tycho.nsa.gov>
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci/*
98c2ecf20Sopenharmony_ci * Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com>
108c2ecf20Sopenharmony_ci *
118c2ecf20Sopenharmony_ci *	Support for enhanced MLS infrastructure.
128c2ecf20Sopenharmony_ci *
138c2ecf20Sopenharmony_ci * Updated: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com>
148c2ecf20Sopenharmony_ci *
158c2ecf20Sopenharmony_ci *	Added conditional policy language extensions
168c2ecf20Sopenharmony_ci *
178c2ecf20Sopenharmony_ci * Updated: Hewlett-Packard <paul@paul-moore.com>
188c2ecf20Sopenharmony_ci *
198c2ecf20Sopenharmony_ci *      Added support for the policy capability bitmap
208c2ecf20Sopenharmony_ci *
218c2ecf20Sopenharmony_ci * Update: Mellanox Techonologies
228c2ecf20Sopenharmony_ci *
238c2ecf20Sopenharmony_ci *	Added Infiniband support
248c2ecf20Sopenharmony_ci *
258c2ecf20Sopenharmony_ci * Copyright (C) 2016 Mellanox Techonologies
268c2ecf20Sopenharmony_ci * Copyright (C) 2007 Hewlett-Packard Development Company, L.P.
278c2ecf20Sopenharmony_ci * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
288c2ecf20Sopenharmony_ci * Copyright (C) 2003 - 2004 Tresys Technology, LLC
298c2ecf20Sopenharmony_ci */
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci#include <linux/kernel.h>
328c2ecf20Sopenharmony_ci#include <linux/sched.h>
338c2ecf20Sopenharmony_ci#include <linux/slab.h>
348c2ecf20Sopenharmony_ci#include <linux/string.h>
358c2ecf20Sopenharmony_ci#include <linux/errno.h>
368c2ecf20Sopenharmony_ci#include <linux/audit.h>
378c2ecf20Sopenharmony_ci#include "security.h"
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_ci#include "policydb.h"
408c2ecf20Sopenharmony_ci#include "conditional.h"
418c2ecf20Sopenharmony_ci#include "mls.h"
428c2ecf20Sopenharmony_ci#include "services.h"
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci#define _DEBUG_HASHES
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ci#ifdef DEBUG_HASHES
478c2ecf20Sopenharmony_cistatic const char *symtab_name[SYM_NUM] = {
488c2ecf20Sopenharmony_ci	"common prefixes",
498c2ecf20Sopenharmony_ci	"classes",
508c2ecf20Sopenharmony_ci	"roles",
518c2ecf20Sopenharmony_ci	"types",
528c2ecf20Sopenharmony_ci	"users",
538c2ecf20Sopenharmony_ci	"bools",
548c2ecf20Sopenharmony_ci	"levels",
558c2ecf20Sopenharmony_ci	"categories",
568c2ecf20Sopenharmony_ci};
578c2ecf20Sopenharmony_ci#endif
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_cistruct policydb_compat_info {
608c2ecf20Sopenharmony_ci	int version;
618c2ecf20Sopenharmony_ci	int sym_num;
628c2ecf20Sopenharmony_ci	int ocon_num;
638c2ecf20Sopenharmony_ci};
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_ci/* These need to be updated if SYM_NUM or OCON_NUM changes */
668c2ecf20Sopenharmony_cistatic struct policydb_compat_info policydb_compat[] = {
678c2ecf20Sopenharmony_ci	{
688c2ecf20Sopenharmony_ci		.version	= POLICYDB_VERSION_BASE,
698c2ecf20Sopenharmony_ci		.sym_num	= SYM_NUM - 3,
708c2ecf20Sopenharmony_ci		.ocon_num	= OCON_NUM - 3,
718c2ecf20Sopenharmony_ci	},
728c2ecf20Sopenharmony_ci	{
738c2ecf20Sopenharmony_ci		.version	= POLICYDB_VERSION_BOOL,
748c2ecf20Sopenharmony_ci		.sym_num	= SYM_NUM - 2,
758c2ecf20Sopenharmony_ci		.ocon_num	= OCON_NUM - 3,
768c2ecf20Sopenharmony_ci	},
778c2ecf20Sopenharmony_ci	{
788c2ecf20Sopenharmony_ci		.version	= POLICYDB_VERSION_IPV6,
798c2ecf20Sopenharmony_ci		.sym_num	= SYM_NUM - 2,
808c2ecf20Sopenharmony_ci		.ocon_num	= OCON_NUM - 2,
818c2ecf20Sopenharmony_ci	},
828c2ecf20Sopenharmony_ci	{
838c2ecf20Sopenharmony_ci		.version	= POLICYDB_VERSION_NLCLASS,
848c2ecf20Sopenharmony_ci		.sym_num	= SYM_NUM - 2,
858c2ecf20Sopenharmony_ci		.ocon_num	= OCON_NUM - 2,
868c2ecf20Sopenharmony_ci	},
878c2ecf20Sopenharmony_ci	{
888c2ecf20Sopenharmony_ci		.version	= POLICYDB_VERSION_MLS,
898c2ecf20Sopenharmony_ci		.sym_num	= SYM_NUM,
908c2ecf20Sopenharmony_ci		.ocon_num	= OCON_NUM - 2,
918c2ecf20Sopenharmony_ci	},
928c2ecf20Sopenharmony_ci	{
938c2ecf20Sopenharmony_ci		.version	= POLICYDB_VERSION_AVTAB,
948c2ecf20Sopenharmony_ci		.sym_num	= SYM_NUM,
958c2ecf20Sopenharmony_ci		.ocon_num	= OCON_NUM - 2,
968c2ecf20Sopenharmony_ci	},
978c2ecf20Sopenharmony_ci	{
988c2ecf20Sopenharmony_ci		.version	= POLICYDB_VERSION_RANGETRANS,
998c2ecf20Sopenharmony_ci		.sym_num	= SYM_NUM,
1008c2ecf20Sopenharmony_ci		.ocon_num	= OCON_NUM - 2,
1018c2ecf20Sopenharmony_ci	},
1028c2ecf20Sopenharmony_ci	{
1038c2ecf20Sopenharmony_ci		.version	= POLICYDB_VERSION_POLCAP,
1048c2ecf20Sopenharmony_ci		.sym_num	= SYM_NUM,
1058c2ecf20Sopenharmony_ci		.ocon_num	= OCON_NUM - 2,
1068c2ecf20Sopenharmony_ci	},
1078c2ecf20Sopenharmony_ci	{
1088c2ecf20Sopenharmony_ci		.version	= POLICYDB_VERSION_PERMISSIVE,
1098c2ecf20Sopenharmony_ci		.sym_num	= SYM_NUM,
1108c2ecf20Sopenharmony_ci		.ocon_num	= OCON_NUM - 2,
1118c2ecf20Sopenharmony_ci	},
1128c2ecf20Sopenharmony_ci	{
1138c2ecf20Sopenharmony_ci		.version	= POLICYDB_VERSION_BOUNDARY,
1148c2ecf20Sopenharmony_ci		.sym_num	= SYM_NUM,
1158c2ecf20Sopenharmony_ci		.ocon_num	= OCON_NUM - 2,
1168c2ecf20Sopenharmony_ci	},
1178c2ecf20Sopenharmony_ci	{
1188c2ecf20Sopenharmony_ci		.version	= POLICYDB_VERSION_FILENAME_TRANS,
1198c2ecf20Sopenharmony_ci		.sym_num	= SYM_NUM,
1208c2ecf20Sopenharmony_ci		.ocon_num	= OCON_NUM - 2,
1218c2ecf20Sopenharmony_ci	},
1228c2ecf20Sopenharmony_ci	{
1238c2ecf20Sopenharmony_ci		.version	= POLICYDB_VERSION_ROLETRANS,
1248c2ecf20Sopenharmony_ci		.sym_num	= SYM_NUM,
1258c2ecf20Sopenharmony_ci		.ocon_num	= OCON_NUM - 2,
1268c2ecf20Sopenharmony_ci	},
1278c2ecf20Sopenharmony_ci	{
1288c2ecf20Sopenharmony_ci		.version	= POLICYDB_VERSION_NEW_OBJECT_DEFAULTS,
1298c2ecf20Sopenharmony_ci		.sym_num	= SYM_NUM,
1308c2ecf20Sopenharmony_ci		.ocon_num	= OCON_NUM - 2,
1318c2ecf20Sopenharmony_ci	},
1328c2ecf20Sopenharmony_ci	{
1338c2ecf20Sopenharmony_ci		.version	= POLICYDB_VERSION_DEFAULT_TYPE,
1348c2ecf20Sopenharmony_ci		.sym_num	= SYM_NUM,
1358c2ecf20Sopenharmony_ci		.ocon_num	= OCON_NUM - 2,
1368c2ecf20Sopenharmony_ci	},
1378c2ecf20Sopenharmony_ci	{
1388c2ecf20Sopenharmony_ci		.version	= POLICYDB_VERSION_CONSTRAINT_NAMES,
1398c2ecf20Sopenharmony_ci		.sym_num	= SYM_NUM,
1408c2ecf20Sopenharmony_ci		.ocon_num	= OCON_NUM - 2,
1418c2ecf20Sopenharmony_ci	},
1428c2ecf20Sopenharmony_ci	{
1438c2ecf20Sopenharmony_ci		.version	= POLICYDB_VERSION_XPERMS_IOCTL,
1448c2ecf20Sopenharmony_ci		.sym_num	= SYM_NUM,
1458c2ecf20Sopenharmony_ci		.ocon_num	= OCON_NUM - 2,
1468c2ecf20Sopenharmony_ci	},
1478c2ecf20Sopenharmony_ci	{
1488c2ecf20Sopenharmony_ci		.version	= POLICYDB_VERSION_INFINIBAND,
1498c2ecf20Sopenharmony_ci		.sym_num	= SYM_NUM,
1508c2ecf20Sopenharmony_ci		.ocon_num	= OCON_NUM,
1518c2ecf20Sopenharmony_ci	},
1528c2ecf20Sopenharmony_ci	{
1538c2ecf20Sopenharmony_ci		.version	= POLICYDB_VERSION_GLBLUB,
1548c2ecf20Sopenharmony_ci		.sym_num	= SYM_NUM,
1558c2ecf20Sopenharmony_ci		.ocon_num	= OCON_NUM,
1568c2ecf20Sopenharmony_ci	},
1578c2ecf20Sopenharmony_ci	{
1588c2ecf20Sopenharmony_ci		.version	= POLICYDB_VERSION_COMP_FTRANS,
1598c2ecf20Sopenharmony_ci		.sym_num	= SYM_NUM,
1608c2ecf20Sopenharmony_ci		.ocon_num	= OCON_NUM,
1618c2ecf20Sopenharmony_ci	},
1628c2ecf20Sopenharmony_ci};
1638c2ecf20Sopenharmony_ci
1648c2ecf20Sopenharmony_cistatic struct policydb_compat_info *policydb_lookup_compat(int version)
1658c2ecf20Sopenharmony_ci{
1668c2ecf20Sopenharmony_ci	int i;
1678c2ecf20Sopenharmony_ci	struct policydb_compat_info *info = NULL;
1688c2ecf20Sopenharmony_ci
1698c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(policydb_compat); i++) {
1708c2ecf20Sopenharmony_ci		if (policydb_compat[i].version == version) {
1718c2ecf20Sopenharmony_ci			info = &policydb_compat[i];
1728c2ecf20Sopenharmony_ci			break;
1738c2ecf20Sopenharmony_ci		}
1748c2ecf20Sopenharmony_ci	}
1758c2ecf20Sopenharmony_ci	return info;
1768c2ecf20Sopenharmony_ci}
1778c2ecf20Sopenharmony_ci
1788c2ecf20Sopenharmony_ci/*
1798c2ecf20Sopenharmony_ci * The following *_destroy functions are used to
1808c2ecf20Sopenharmony_ci * free any memory allocated for each kind of
1818c2ecf20Sopenharmony_ci * symbol data in the policy database.
1828c2ecf20Sopenharmony_ci */
1838c2ecf20Sopenharmony_ci
1848c2ecf20Sopenharmony_cistatic int perm_destroy(void *key, void *datum, void *p)
1858c2ecf20Sopenharmony_ci{
1868c2ecf20Sopenharmony_ci	kfree(key);
1878c2ecf20Sopenharmony_ci	kfree(datum);
1888c2ecf20Sopenharmony_ci	return 0;
1898c2ecf20Sopenharmony_ci}
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_cistatic int common_destroy(void *key, void *datum, void *p)
1928c2ecf20Sopenharmony_ci{
1938c2ecf20Sopenharmony_ci	struct common_datum *comdatum;
1948c2ecf20Sopenharmony_ci
1958c2ecf20Sopenharmony_ci	kfree(key);
1968c2ecf20Sopenharmony_ci	if (datum) {
1978c2ecf20Sopenharmony_ci		comdatum = datum;
1988c2ecf20Sopenharmony_ci		hashtab_map(&comdatum->permissions.table, perm_destroy, NULL);
1998c2ecf20Sopenharmony_ci		hashtab_destroy(&comdatum->permissions.table);
2008c2ecf20Sopenharmony_ci	}
2018c2ecf20Sopenharmony_ci	kfree(datum);
2028c2ecf20Sopenharmony_ci	return 0;
2038c2ecf20Sopenharmony_ci}
2048c2ecf20Sopenharmony_ci
2058c2ecf20Sopenharmony_cistatic void constraint_expr_destroy(struct constraint_expr *expr)
2068c2ecf20Sopenharmony_ci{
2078c2ecf20Sopenharmony_ci	if (expr) {
2088c2ecf20Sopenharmony_ci		ebitmap_destroy(&expr->names);
2098c2ecf20Sopenharmony_ci		if (expr->type_names) {
2108c2ecf20Sopenharmony_ci			ebitmap_destroy(&expr->type_names->types);
2118c2ecf20Sopenharmony_ci			ebitmap_destroy(&expr->type_names->negset);
2128c2ecf20Sopenharmony_ci			kfree(expr->type_names);
2138c2ecf20Sopenharmony_ci		}
2148c2ecf20Sopenharmony_ci		kfree(expr);
2158c2ecf20Sopenharmony_ci	}
2168c2ecf20Sopenharmony_ci}
2178c2ecf20Sopenharmony_ci
2188c2ecf20Sopenharmony_cistatic int cls_destroy(void *key, void *datum, void *p)
2198c2ecf20Sopenharmony_ci{
2208c2ecf20Sopenharmony_ci	struct class_datum *cladatum;
2218c2ecf20Sopenharmony_ci	struct constraint_node *constraint, *ctemp;
2228c2ecf20Sopenharmony_ci	struct constraint_expr *e, *etmp;
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_ci	kfree(key);
2258c2ecf20Sopenharmony_ci	if (datum) {
2268c2ecf20Sopenharmony_ci		cladatum = datum;
2278c2ecf20Sopenharmony_ci		hashtab_map(&cladatum->permissions.table, perm_destroy, NULL);
2288c2ecf20Sopenharmony_ci		hashtab_destroy(&cladatum->permissions.table);
2298c2ecf20Sopenharmony_ci		constraint = cladatum->constraints;
2308c2ecf20Sopenharmony_ci		while (constraint) {
2318c2ecf20Sopenharmony_ci			e = constraint->expr;
2328c2ecf20Sopenharmony_ci			while (e) {
2338c2ecf20Sopenharmony_ci				etmp = e;
2348c2ecf20Sopenharmony_ci				e = e->next;
2358c2ecf20Sopenharmony_ci				constraint_expr_destroy(etmp);
2368c2ecf20Sopenharmony_ci			}
2378c2ecf20Sopenharmony_ci			ctemp = constraint;
2388c2ecf20Sopenharmony_ci			constraint = constraint->next;
2398c2ecf20Sopenharmony_ci			kfree(ctemp);
2408c2ecf20Sopenharmony_ci		}
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_ci		constraint = cladatum->validatetrans;
2438c2ecf20Sopenharmony_ci		while (constraint) {
2448c2ecf20Sopenharmony_ci			e = constraint->expr;
2458c2ecf20Sopenharmony_ci			while (e) {
2468c2ecf20Sopenharmony_ci				etmp = e;
2478c2ecf20Sopenharmony_ci				e = e->next;
2488c2ecf20Sopenharmony_ci				constraint_expr_destroy(etmp);
2498c2ecf20Sopenharmony_ci			}
2508c2ecf20Sopenharmony_ci			ctemp = constraint;
2518c2ecf20Sopenharmony_ci			constraint = constraint->next;
2528c2ecf20Sopenharmony_ci			kfree(ctemp);
2538c2ecf20Sopenharmony_ci		}
2548c2ecf20Sopenharmony_ci		kfree(cladatum->comkey);
2558c2ecf20Sopenharmony_ci	}
2568c2ecf20Sopenharmony_ci	kfree(datum);
2578c2ecf20Sopenharmony_ci	return 0;
2588c2ecf20Sopenharmony_ci}
2598c2ecf20Sopenharmony_ci
2608c2ecf20Sopenharmony_cistatic int role_destroy(void *key, void *datum, void *p)
2618c2ecf20Sopenharmony_ci{
2628c2ecf20Sopenharmony_ci	struct role_datum *role;
2638c2ecf20Sopenharmony_ci
2648c2ecf20Sopenharmony_ci	kfree(key);
2658c2ecf20Sopenharmony_ci	if (datum) {
2668c2ecf20Sopenharmony_ci		role = datum;
2678c2ecf20Sopenharmony_ci		ebitmap_destroy(&role->dominates);
2688c2ecf20Sopenharmony_ci		ebitmap_destroy(&role->types);
2698c2ecf20Sopenharmony_ci	}
2708c2ecf20Sopenharmony_ci	kfree(datum);
2718c2ecf20Sopenharmony_ci	return 0;
2728c2ecf20Sopenharmony_ci}
2738c2ecf20Sopenharmony_ci
2748c2ecf20Sopenharmony_cistatic int type_destroy(void *key, void *datum, void *p)
2758c2ecf20Sopenharmony_ci{
2768c2ecf20Sopenharmony_ci	kfree(key);
2778c2ecf20Sopenharmony_ci	kfree(datum);
2788c2ecf20Sopenharmony_ci	return 0;
2798c2ecf20Sopenharmony_ci}
2808c2ecf20Sopenharmony_ci
2818c2ecf20Sopenharmony_cistatic int user_destroy(void *key, void *datum, void *p)
2828c2ecf20Sopenharmony_ci{
2838c2ecf20Sopenharmony_ci	struct user_datum *usrdatum;
2848c2ecf20Sopenharmony_ci
2858c2ecf20Sopenharmony_ci	kfree(key);
2868c2ecf20Sopenharmony_ci	if (datum) {
2878c2ecf20Sopenharmony_ci		usrdatum = datum;
2888c2ecf20Sopenharmony_ci		ebitmap_destroy(&usrdatum->roles);
2898c2ecf20Sopenharmony_ci		ebitmap_destroy(&usrdatum->range.level[0].cat);
2908c2ecf20Sopenharmony_ci		ebitmap_destroy(&usrdatum->range.level[1].cat);
2918c2ecf20Sopenharmony_ci		ebitmap_destroy(&usrdatum->dfltlevel.cat);
2928c2ecf20Sopenharmony_ci	}
2938c2ecf20Sopenharmony_ci	kfree(datum);
2948c2ecf20Sopenharmony_ci	return 0;
2958c2ecf20Sopenharmony_ci}
2968c2ecf20Sopenharmony_ci
2978c2ecf20Sopenharmony_cistatic int sens_destroy(void *key, void *datum, void *p)
2988c2ecf20Sopenharmony_ci{
2998c2ecf20Sopenharmony_ci	struct level_datum *levdatum;
3008c2ecf20Sopenharmony_ci
3018c2ecf20Sopenharmony_ci	kfree(key);
3028c2ecf20Sopenharmony_ci	if (datum) {
3038c2ecf20Sopenharmony_ci		levdatum = datum;
3048c2ecf20Sopenharmony_ci		if (levdatum->level)
3058c2ecf20Sopenharmony_ci			ebitmap_destroy(&levdatum->level->cat);
3068c2ecf20Sopenharmony_ci		kfree(levdatum->level);
3078c2ecf20Sopenharmony_ci	}
3088c2ecf20Sopenharmony_ci	kfree(datum);
3098c2ecf20Sopenharmony_ci	return 0;
3108c2ecf20Sopenharmony_ci}
3118c2ecf20Sopenharmony_ci
3128c2ecf20Sopenharmony_cistatic int cat_destroy(void *key, void *datum, void *p)
3138c2ecf20Sopenharmony_ci{
3148c2ecf20Sopenharmony_ci	kfree(key);
3158c2ecf20Sopenharmony_ci	kfree(datum);
3168c2ecf20Sopenharmony_ci	return 0;
3178c2ecf20Sopenharmony_ci}
3188c2ecf20Sopenharmony_ci
3198c2ecf20Sopenharmony_cistatic int (*destroy_f[SYM_NUM]) (void *key, void *datum, void *datap) =
3208c2ecf20Sopenharmony_ci{
3218c2ecf20Sopenharmony_ci	common_destroy,
3228c2ecf20Sopenharmony_ci	cls_destroy,
3238c2ecf20Sopenharmony_ci	role_destroy,
3248c2ecf20Sopenharmony_ci	type_destroy,
3258c2ecf20Sopenharmony_ci	user_destroy,
3268c2ecf20Sopenharmony_ci	cond_destroy_bool,
3278c2ecf20Sopenharmony_ci	sens_destroy,
3288c2ecf20Sopenharmony_ci	cat_destroy,
3298c2ecf20Sopenharmony_ci};
3308c2ecf20Sopenharmony_ci
3318c2ecf20Sopenharmony_cistatic int filenametr_destroy(void *key, void *datum, void *p)
3328c2ecf20Sopenharmony_ci{
3338c2ecf20Sopenharmony_ci	struct filename_trans_key *ft = key;
3348c2ecf20Sopenharmony_ci	struct filename_trans_datum *next, *d = datum;
3358c2ecf20Sopenharmony_ci
3368c2ecf20Sopenharmony_ci	kfree(ft->name);
3378c2ecf20Sopenharmony_ci	kfree(key);
3388c2ecf20Sopenharmony_ci	do {
3398c2ecf20Sopenharmony_ci		ebitmap_destroy(&d->stypes);
3408c2ecf20Sopenharmony_ci		next = d->next;
3418c2ecf20Sopenharmony_ci		kfree(d);
3428c2ecf20Sopenharmony_ci		d = next;
3438c2ecf20Sopenharmony_ci	} while (unlikely(d));
3448c2ecf20Sopenharmony_ci	cond_resched();
3458c2ecf20Sopenharmony_ci	return 0;
3468c2ecf20Sopenharmony_ci}
3478c2ecf20Sopenharmony_ci
3488c2ecf20Sopenharmony_cistatic int range_tr_destroy(void *key, void *datum, void *p)
3498c2ecf20Sopenharmony_ci{
3508c2ecf20Sopenharmony_ci	struct mls_range *rt = datum;
3518c2ecf20Sopenharmony_ci
3528c2ecf20Sopenharmony_ci	kfree(key);
3538c2ecf20Sopenharmony_ci	ebitmap_destroy(&rt->level[0].cat);
3548c2ecf20Sopenharmony_ci	ebitmap_destroy(&rt->level[1].cat);
3558c2ecf20Sopenharmony_ci	kfree(datum);
3568c2ecf20Sopenharmony_ci	cond_resched();
3578c2ecf20Sopenharmony_ci	return 0;
3588c2ecf20Sopenharmony_ci}
3598c2ecf20Sopenharmony_ci
3608c2ecf20Sopenharmony_cistatic int role_tr_destroy(void *key, void *datum, void *p)
3618c2ecf20Sopenharmony_ci{
3628c2ecf20Sopenharmony_ci	kfree(key);
3638c2ecf20Sopenharmony_ci	kfree(datum);
3648c2ecf20Sopenharmony_ci	return 0;
3658c2ecf20Sopenharmony_ci}
3668c2ecf20Sopenharmony_ci
3678c2ecf20Sopenharmony_cistatic void ocontext_destroy(struct ocontext *c, int i)
3688c2ecf20Sopenharmony_ci{
3698c2ecf20Sopenharmony_ci	if (!c)
3708c2ecf20Sopenharmony_ci		return;
3718c2ecf20Sopenharmony_ci
3728c2ecf20Sopenharmony_ci	context_destroy(&c->context[0]);
3738c2ecf20Sopenharmony_ci	context_destroy(&c->context[1]);
3748c2ecf20Sopenharmony_ci	if (i == OCON_ISID || i == OCON_FS ||
3758c2ecf20Sopenharmony_ci	    i == OCON_NETIF || i == OCON_FSUSE)
3768c2ecf20Sopenharmony_ci		kfree(c->u.name);
3778c2ecf20Sopenharmony_ci	kfree(c);
3788c2ecf20Sopenharmony_ci}
3798c2ecf20Sopenharmony_ci
3808c2ecf20Sopenharmony_ci/*
3818c2ecf20Sopenharmony_ci * Initialize the role table.
3828c2ecf20Sopenharmony_ci */
3838c2ecf20Sopenharmony_cistatic int roles_init(struct policydb *p)
3848c2ecf20Sopenharmony_ci{
3858c2ecf20Sopenharmony_ci	char *key = NULL;
3868c2ecf20Sopenharmony_ci	int rc;
3878c2ecf20Sopenharmony_ci	struct role_datum *role;
3888c2ecf20Sopenharmony_ci
3898c2ecf20Sopenharmony_ci	role = kzalloc(sizeof(*role), GFP_KERNEL);
3908c2ecf20Sopenharmony_ci	if (!role)
3918c2ecf20Sopenharmony_ci		return -ENOMEM;
3928c2ecf20Sopenharmony_ci
3938c2ecf20Sopenharmony_ci	rc = -EINVAL;
3948c2ecf20Sopenharmony_ci	role->value = ++p->p_roles.nprim;
3958c2ecf20Sopenharmony_ci	if (role->value != OBJECT_R_VAL)
3968c2ecf20Sopenharmony_ci		goto out;
3978c2ecf20Sopenharmony_ci
3988c2ecf20Sopenharmony_ci	rc = -ENOMEM;
3998c2ecf20Sopenharmony_ci	key = kstrdup(OBJECT_R, GFP_KERNEL);
4008c2ecf20Sopenharmony_ci	if (!key)
4018c2ecf20Sopenharmony_ci		goto out;
4028c2ecf20Sopenharmony_ci
4038c2ecf20Sopenharmony_ci	rc = symtab_insert(&p->p_roles, key, role);
4048c2ecf20Sopenharmony_ci	if (rc)
4058c2ecf20Sopenharmony_ci		goto out;
4068c2ecf20Sopenharmony_ci
4078c2ecf20Sopenharmony_ci	return 0;
4088c2ecf20Sopenharmony_ciout:
4098c2ecf20Sopenharmony_ci	kfree(key);
4108c2ecf20Sopenharmony_ci	kfree(role);
4118c2ecf20Sopenharmony_ci	return rc;
4128c2ecf20Sopenharmony_ci}
4138c2ecf20Sopenharmony_ci
4148c2ecf20Sopenharmony_cistatic u32 filenametr_hash(const void *k)
4158c2ecf20Sopenharmony_ci{
4168c2ecf20Sopenharmony_ci	const struct filename_trans_key *ft = k;
4178c2ecf20Sopenharmony_ci	unsigned long hash;
4188c2ecf20Sopenharmony_ci	unsigned int byte_num;
4198c2ecf20Sopenharmony_ci	unsigned char focus;
4208c2ecf20Sopenharmony_ci
4218c2ecf20Sopenharmony_ci	hash = ft->ttype ^ ft->tclass;
4228c2ecf20Sopenharmony_ci
4238c2ecf20Sopenharmony_ci	byte_num = 0;
4248c2ecf20Sopenharmony_ci	while ((focus = ft->name[byte_num++]))
4258c2ecf20Sopenharmony_ci		hash = partial_name_hash(focus, hash);
4268c2ecf20Sopenharmony_ci	return hash;
4278c2ecf20Sopenharmony_ci}
4288c2ecf20Sopenharmony_ci
4298c2ecf20Sopenharmony_cistatic int filenametr_cmp(const void *k1, const void *k2)
4308c2ecf20Sopenharmony_ci{
4318c2ecf20Sopenharmony_ci	const struct filename_trans_key *ft1 = k1;
4328c2ecf20Sopenharmony_ci	const struct filename_trans_key *ft2 = k2;
4338c2ecf20Sopenharmony_ci	int v;
4348c2ecf20Sopenharmony_ci
4358c2ecf20Sopenharmony_ci	v = ft1->ttype - ft2->ttype;
4368c2ecf20Sopenharmony_ci	if (v)
4378c2ecf20Sopenharmony_ci		return v;
4388c2ecf20Sopenharmony_ci
4398c2ecf20Sopenharmony_ci	v = ft1->tclass - ft2->tclass;
4408c2ecf20Sopenharmony_ci	if (v)
4418c2ecf20Sopenharmony_ci		return v;
4428c2ecf20Sopenharmony_ci
4438c2ecf20Sopenharmony_ci	return strcmp(ft1->name, ft2->name);
4448c2ecf20Sopenharmony_ci
4458c2ecf20Sopenharmony_ci}
4468c2ecf20Sopenharmony_ci
4478c2ecf20Sopenharmony_cistatic const struct hashtab_key_params filenametr_key_params = {
4488c2ecf20Sopenharmony_ci	.hash = filenametr_hash,
4498c2ecf20Sopenharmony_ci	.cmp = filenametr_cmp,
4508c2ecf20Sopenharmony_ci};
4518c2ecf20Sopenharmony_ci
4528c2ecf20Sopenharmony_cistruct filename_trans_datum *policydb_filenametr_search(
4538c2ecf20Sopenharmony_ci	struct policydb *p, struct filename_trans_key *key)
4548c2ecf20Sopenharmony_ci{
4558c2ecf20Sopenharmony_ci	return hashtab_search(&p->filename_trans, key, filenametr_key_params);
4568c2ecf20Sopenharmony_ci}
4578c2ecf20Sopenharmony_ci
4588c2ecf20Sopenharmony_cistatic u32 rangetr_hash(const void *k)
4598c2ecf20Sopenharmony_ci{
4608c2ecf20Sopenharmony_ci	const struct range_trans *key = k;
4618c2ecf20Sopenharmony_ci
4628c2ecf20Sopenharmony_ci	return key->source_type + (key->target_type << 3) +
4638c2ecf20Sopenharmony_ci		(key->target_class << 5);
4648c2ecf20Sopenharmony_ci}
4658c2ecf20Sopenharmony_ci
4668c2ecf20Sopenharmony_cistatic int rangetr_cmp(const void *k1, const void *k2)
4678c2ecf20Sopenharmony_ci{
4688c2ecf20Sopenharmony_ci	const struct range_trans *key1 = k1, *key2 = k2;
4698c2ecf20Sopenharmony_ci	int v;
4708c2ecf20Sopenharmony_ci
4718c2ecf20Sopenharmony_ci	v = key1->source_type - key2->source_type;
4728c2ecf20Sopenharmony_ci	if (v)
4738c2ecf20Sopenharmony_ci		return v;
4748c2ecf20Sopenharmony_ci
4758c2ecf20Sopenharmony_ci	v = key1->target_type - key2->target_type;
4768c2ecf20Sopenharmony_ci	if (v)
4778c2ecf20Sopenharmony_ci		return v;
4788c2ecf20Sopenharmony_ci
4798c2ecf20Sopenharmony_ci	v = key1->target_class - key2->target_class;
4808c2ecf20Sopenharmony_ci
4818c2ecf20Sopenharmony_ci	return v;
4828c2ecf20Sopenharmony_ci}
4838c2ecf20Sopenharmony_ci
4848c2ecf20Sopenharmony_cistatic const struct hashtab_key_params rangetr_key_params = {
4858c2ecf20Sopenharmony_ci	.hash = rangetr_hash,
4868c2ecf20Sopenharmony_ci	.cmp = rangetr_cmp,
4878c2ecf20Sopenharmony_ci};
4888c2ecf20Sopenharmony_ci
4898c2ecf20Sopenharmony_cistruct mls_range *policydb_rangetr_search(struct policydb *p,
4908c2ecf20Sopenharmony_ci					  struct range_trans *key)
4918c2ecf20Sopenharmony_ci{
4928c2ecf20Sopenharmony_ci	return hashtab_search(&p->range_tr, key, rangetr_key_params);
4938c2ecf20Sopenharmony_ci}
4948c2ecf20Sopenharmony_ci
4958c2ecf20Sopenharmony_cistatic u32 role_trans_hash(const void *k)
4968c2ecf20Sopenharmony_ci{
4978c2ecf20Sopenharmony_ci	const struct role_trans_key *key = k;
4988c2ecf20Sopenharmony_ci
4998c2ecf20Sopenharmony_ci	return key->role + (key->type << 3) + (key->tclass << 5);
5008c2ecf20Sopenharmony_ci}
5018c2ecf20Sopenharmony_ci
5028c2ecf20Sopenharmony_cistatic int role_trans_cmp(const void *k1, const void *k2)
5038c2ecf20Sopenharmony_ci{
5048c2ecf20Sopenharmony_ci	const struct role_trans_key *key1 = k1, *key2 = k2;
5058c2ecf20Sopenharmony_ci	int v;
5068c2ecf20Sopenharmony_ci
5078c2ecf20Sopenharmony_ci	v = key1->role - key2->role;
5088c2ecf20Sopenharmony_ci	if (v)
5098c2ecf20Sopenharmony_ci		return v;
5108c2ecf20Sopenharmony_ci
5118c2ecf20Sopenharmony_ci	v = key1->type - key2->type;
5128c2ecf20Sopenharmony_ci	if (v)
5138c2ecf20Sopenharmony_ci		return v;
5148c2ecf20Sopenharmony_ci
5158c2ecf20Sopenharmony_ci	return key1->tclass - key2->tclass;
5168c2ecf20Sopenharmony_ci}
5178c2ecf20Sopenharmony_ci
5188c2ecf20Sopenharmony_cistatic const struct hashtab_key_params roletr_key_params = {
5198c2ecf20Sopenharmony_ci	.hash = role_trans_hash,
5208c2ecf20Sopenharmony_ci	.cmp = role_trans_cmp,
5218c2ecf20Sopenharmony_ci};
5228c2ecf20Sopenharmony_ci
5238c2ecf20Sopenharmony_cistruct role_trans_datum *policydb_roletr_search(struct policydb *p,
5248c2ecf20Sopenharmony_ci						struct role_trans_key *key)
5258c2ecf20Sopenharmony_ci{
5268c2ecf20Sopenharmony_ci	return hashtab_search(&p->role_tr, key, roletr_key_params);
5278c2ecf20Sopenharmony_ci}
5288c2ecf20Sopenharmony_ci
5298c2ecf20Sopenharmony_ci/*
5308c2ecf20Sopenharmony_ci * Initialize a policy database structure.
5318c2ecf20Sopenharmony_ci */
5328c2ecf20Sopenharmony_cistatic void policydb_init(struct policydb *p)
5338c2ecf20Sopenharmony_ci{
5348c2ecf20Sopenharmony_ci	memset(p, 0, sizeof(*p));
5358c2ecf20Sopenharmony_ci
5368c2ecf20Sopenharmony_ci	avtab_init(&p->te_avtab);
5378c2ecf20Sopenharmony_ci	cond_policydb_init(p);
5388c2ecf20Sopenharmony_ci
5398c2ecf20Sopenharmony_ci	ebitmap_init(&p->filename_trans_ttypes);
5408c2ecf20Sopenharmony_ci	ebitmap_init(&p->policycaps);
5418c2ecf20Sopenharmony_ci	ebitmap_init(&p->permissive_map);
5428c2ecf20Sopenharmony_ci}
5438c2ecf20Sopenharmony_ci
5448c2ecf20Sopenharmony_ci/*
5458c2ecf20Sopenharmony_ci * The following *_index functions are used to
5468c2ecf20Sopenharmony_ci * define the val_to_name and val_to_struct arrays
5478c2ecf20Sopenharmony_ci * in a policy database structure.  The val_to_name
5488c2ecf20Sopenharmony_ci * arrays are used when converting security context
5498c2ecf20Sopenharmony_ci * structures into string representations.  The
5508c2ecf20Sopenharmony_ci * val_to_struct arrays are used when the attributes
5518c2ecf20Sopenharmony_ci * of a class, role, or user are needed.
5528c2ecf20Sopenharmony_ci */
5538c2ecf20Sopenharmony_ci
5548c2ecf20Sopenharmony_cistatic int common_index(void *key, void *datum, void *datap)
5558c2ecf20Sopenharmony_ci{
5568c2ecf20Sopenharmony_ci	struct policydb *p;
5578c2ecf20Sopenharmony_ci	struct common_datum *comdatum;
5588c2ecf20Sopenharmony_ci
5598c2ecf20Sopenharmony_ci	comdatum = datum;
5608c2ecf20Sopenharmony_ci	p = datap;
5618c2ecf20Sopenharmony_ci	if (!comdatum->value || comdatum->value > p->p_commons.nprim)
5628c2ecf20Sopenharmony_ci		return -EINVAL;
5638c2ecf20Sopenharmony_ci
5648c2ecf20Sopenharmony_ci	p->sym_val_to_name[SYM_COMMONS][comdatum->value - 1] = key;
5658c2ecf20Sopenharmony_ci
5668c2ecf20Sopenharmony_ci	return 0;
5678c2ecf20Sopenharmony_ci}
5688c2ecf20Sopenharmony_ci
5698c2ecf20Sopenharmony_cistatic int class_index(void *key, void *datum, void *datap)
5708c2ecf20Sopenharmony_ci{
5718c2ecf20Sopenharmony_ci	struct policydb *p;
5728c2ecf20Sopenharmony_ci	struct class_datum *cladatum;
5738c2ecf20Sopenharmony_ci
5748c2ecf20Sopenharmony_ci	cladatum = datum;
5758c2ecf20Sopenharmony_ci	p = datap;
5768c2ecf20Sopenharmony_ci	if (!cladatum->value || cladatum->value > p->p_classes.nprim)
5778c2ecf20Sopenharmony_ci		return -EINVAL;
5788c2ecf20Sopenharmony_ci
5798c2ecf20Sopenharmony_ci	p->sym_val_to_name[SYM_CLASSES][cladatum->value - 1] = key;
5808c2ecf20Sopenharmony_ci	p->class_val_to_struct[cladatum->value - 1] = cladatum;
5818c2ecf20Sopenharmony_ci	return 0;
5828c2ecf20Sopenharmony_ci}
5838c2ecf20Sopenharmony_ci
5848c2ecf20Sopenharmony_cistatic int role_index(void *key, void *datum, void *datap)
5858c2ecf20Sopenharmony_ci{
5868c2ecf20Sopenharmony_ci	struct policydb *p;
5878c2ecf20Sopenharmony_ci	struct role_datum *role;
5888c2ecf20Sopenharmony_ci
5898c2ecf20Sopenharmony_ci	role = datum;
5908c2ecf20Sopenharmony_ci	p = datap;
5918c2ecf20Sopenharmony_ci	if (!role->value
5928c2ecf20Sopenharmony_ci	    || role->value > p->p_roles.nprim
5938c2ecf20Sopenharmony_ci	    || role->bounds > p->p_roles.nprim)
5948c2ecf20Sopenharmony_ci		return -EINVAL;
5958c2ecf20Sopenharmony_ci
5968c2ecf20Sopenharmony_ci	p->sym_val_to_name[SYM_ROLES][role->value - 1] = key;
5978c2ecf20Sopenharmony_ci	p->role_val_to_struct[role->value - 1] = role;
5988c2ecf20Sopenharmony_ci	return 0;
5998c2ecf20Sopenharmony_ci}
6008c2ecf20Sopenharmony_ci
6018c2ecf20Sopenharmony_cistatic int type_index(void *key, void *datum, void *datap)
6028c2ecf20Sopenharmony_ci{
6038c2ecf20Sopenharmony_ci	struct policydb *p;
6048c2ecf20Sopenharmony_ci	struct type_datum *typdatum;
6058c2ecf20Sopenharmony_ci
6068c2ecf20Sopenharmony_ci	typdatum = datum;
6078c2ecf20Sopenharmony_ci	p = datap;
6088c2ecf20Sopenharmony_ci
6098c2ecf20Sopenharmony_ci	if (typdatum->primary) {
6108c2ecf20Sopenharmony_ci		if (!typdatum->value
6118c2ecf20Sopenharmony_ci		    || typdatum->value > p->p_types.nprim
6128c2ecf20Sopenharmony_ci		    || typdatum->bounds > p->p_types.nprim)
6138c2ecf20Sopenharmony_ci			return -EINVAL;
6148c2ecf20Sopenharmony_ci		p->sym_val_to_name[SYM_TYPES][typdatum->value - 1] = key;
6158c2ecf20Sopenharmony_ci		p->type_val_to_struct[typdatum->value - 1] = typdatum;
6168c2ecf20Sopenharmony_ci	}
6178c2ecf20Sopenharmony_ci
6188c2ecf20Sopenharmony_ci	return 0;
6198c2ecf20Sopenharmony_ci}
6208c2ecf20Sopenharmony_ci
6218c2ecf20Sopenharmony_cistatic int user_index(void *key, void *datum, void *datap)
6228c2ecf20Sopenharmony_ci{
6238c2ecf20Sopenharmony_ci	struct policydb *p;
6248c2ecf20Sopenharmony_ci	struct user_datum *usrdatum;
6258c2ecf20Sopenharmony_ci
6268c2ecf20Sopenharmony_ci	usrdatum = datum;
6278c2ecf20Sopenharmony_ci	p = datap;
6288c2ecf20Sopenharmony_ci	if (!usrdatum->value
6298c2ecf20Sopenharmony_ci	    || usrdatum->value > p->p_users.nprim
6308c2ecf20Sopenharmony_ci	    || usrdatum->bounds > p->p_users.nprim)
6318c2ecf20Sopenharmony_ci		return -EINVAL;
6328c2ecf20Sopenharmony_ci
6338c2ecf20Sopenharmony_ci	p->sym_val_to_name[SYM_USERS][usrdatum->value - 1] = key;
6348c2ecf20Sopenharmony_ci	p->user_val_to_struct[usrdatum->value - 1] = usrdatum;
6358c2ecf20Sopenharmony_ci	return 0;
6368c2ecf20Sopenharmony_ci}
6378c2ecf20Sopenharmony_ci
6388c2ecf20Sopenharmony_cistatic int sens_index(void *key, void *datum, void *datap)
6398c2ecf20Sopenharmony_ci{
6408c2ecf20Sopenharmony_ci	struct policydb *p;
6418c2ecf20Sopenharmony_ci	struct level_datum *levdatum;
6428c2ecf20Sopenharmony_ci
6438c2ecf20Sopenharmony_ci	levdatum = datum;
6448c2ecf20Sopenharmony_ci	p = datap;
6458c2ecf20Sopenharmony_ci
6468c2ecf20Sopenharmony_ci	if (!levdatum->isalias) {
6478c2ecf20Sopenharmony_ci		if (!levdatum->level->sens ||
6488c2ecf20Sopenharmony_ci		    levdatum->level->sens > p->p_levels.nprim)
6498c2ecf20Sopenharmony_ci			return -EINVAL;
6508c2ecf20Sopenharmony_ci
6518c2ecf20Sopenharmony_ci		p->sym_val_to_name[SYM_LEVELS][levdatum->level->sens - 1] = key;
6528c2ecf20Sopenharmony_ci	}
6538c2ecf20Sopenharmony_ci
6548c2ecf20Sopenharmony_ci	return 0;
6558c2ecf20Sopenharmony_ci}
6568c2ecf20Sopenharmony_ci
6578c2ecf20Sopenharmony_cistatic int cat_index(void *key, void *datum, void *datap)
6588c2ecf20Sopenharmony_ci{
6598c2ecf20Sopenharmony_ci	struct policydb *p;
6608c2ecf20Sopenharmony_ci	struct cat_datum *catdatum;
6618c2ecf20Sopenharmony_ci
6628c2ecf20Sopenharmony_ci	catdatum = datum;
6638c2ecf20Sopenharmony_ci	p = datap;
6648c2ecf20Sopenharmony_ci
6658c2ecf20Sopenharmony_ci	if (!catdatum->isalias) {
6668c2ecf20Sopenharmony_ci		if (!catdatum->value || catdatum->value > p->p_cats.nprim)
6678c2ecf20Sopenharmony_ci			return -EINVAL;
6688c2ecf20Sopenharmony_ci
6698c2ecf20Sopenharmony_ci		p->sym_val_to_name[SYM_CATS][catdatum->value - 1] = key;
6708c2ecf20Sopenharmony_ci	}
6718c2ecf20Sopenharmony_ci
6728c2ecf20Sopenharmony_ci	return 0;
6738c2ecf20Sopenharmony_ci}
6748c2ecf20Sopenharmony_ci
6758c2ecf20Sopenharmony_cistatic int (*index_f[SYM_NUM]) (void *key, void *datum, void *datap) =
6768c2ecf20Sopenharmony_ci{
6778c2ecf20Sopenharmony_ci	common_index,
6788c2ecf20Sopenharmony_ci	class_index,
6798c2ecf20Sopenharmony_ci	role_index,
6808c2ecf20Sopenharmony_ci	type_index,
6818c2ecf20Sopenharmony_ci	user_index,
6828c2ecf20Sopenharmony_ci	cond_index_bool,
6838c2ecf20Sopenharmony_ci	sens_index,
6848c2ecf20Sopenharmony_ci	cat_index,
6858c2ecf20Sopenharmony_ci};
6868c2ecf20Sopenharmony_ci
6878c2ecf20Sopenharmony_ci#ifdef DEBUG_HASHES
6888c2ecf20Sopenharmony_cistatic void hash_eval(struct hashtab *h, const char *hash_name)
6898c2ecf20Sopenharmony_ci{
6908c2ecf20Sopenharmony_ci	struct hashtab_info info;
6918c2ecf20Sopenharmony_ci
6928c2ecf20Sopenharmony_ci	hashtab_stat(h, &info);
6938c2ecf20Sopenharmony_ci	pr_debug("SELinux: %s:  %d entries and %d/%d buckets used, longest chain length %d\n",
6948c2ecf20Sopenharmony_ci		 hash_name, h->nel, info.slots_used, h->size,
6958c2ecf20Sopenharmony_ci		 info.max_chain_len);
6968c2ecf20Sopenharmony_ci}
6978c2ecf20Sopenharmony_ci
6988c2ecf20Sopenharmony_cistatic void symtab_hash_eval(struct symtab *s)
6998c2ecf20Sopenharmony_ci{
7008c2ecf20Sopenharmony_ci	int i;
7018c2ecf20Sopenharmony_ci
7028c2ecf20Sopenharmony_ci	for (i = 0; i < SYM_NUM; i++)
7038c2ecf20Sopenharmony_ci		hash_eval(&s[i].table, symtab_name[i]);
7048c2ecf20Sopenharmony_ci}
7058c2ecf20Sopenharmony_ci
7068c2ecf20Sopenharmony_ci#else
7078c2ecf20Sopenharmony_cistatic inline void hash_eval(struct hashtab *h, char *hash_name)
7088c2ecf20Sopenharmony_ci{
7098c2ecf20Sopenharmony_ci}
7108c2ecf20Sopenharmony_ci#endif
7118c2ecf20Sopenharmony_ci
7128c2ecf20Sopenharmony_ci/*
7138c2ecf20Sopenharmony_ci * Define the other val_to_name and val_to_struct arrays
7148c2ecf20Sopenharmony_ci * in a policy database structure.
7158c2ecf20Sopenharmony_ci *
7168c2ecf20Sopenharmony_ci * Caller must clean up on failure.
7178c2ecf20Sopenharmony_ci */
7188c2ecf20Sopenharmony_cistatic int policydb_index(struct policydb *p)
7198c2ecf20Sopenharmony_ci{
7208c2ecf20Sopenharmony_ci	int i, rc;
7218c2ecf20Sopenharmony_ci
7228c2ecf20Sopenharmony_ci	if (p->mls_enabled)
7238c2ecf20Sopenharmony_ci		pr_debug("SELinux:  %d users, %d roles, %d types, %d bools, %d sens, %d cats\n",
7248c2ecf20Sopenharmony_ci			 p->p_users.nprim, p->p_roles.nprim, p->p_types.nprim,
7258c2ecf20Sopenharmony_ci			 p->p_bools.nprim, p->p_levels.nprim, p->p_cats.nprim);
7268c2ecf20Sopenharmony_ci	else
7278c2ecf20Sopenharmony_ci		pr_debug("SELinux:  %d users, %d roles, %d types, %d bools\n",
7288c2ecf20Sopenharmony_ci			 p->p_users.nprim, p->p_roles.nprim, p->p_types.nprim,
7298c2ecf20Sopenharmony_ci			 p->p_bools.nprim);
7308c2ecf20Sopenharmony_ci
7318c2ecf20Sopenharmony_ci	pr_debug("SELinux:  %d classes, %d rules\n",
7328c2ecf20Sopenharmony_ci		 p->p_classes.nprim, p->te_avtab.nel);
7338c2ecf20Sopenharmony_ci
7348c2ecf20Sopenharmony_ci#ifdef DEBUG_HASHES
7358c2ecf20Sopenharmony_ci	avtab_hash_eval(&p->te_avtab, "rules");
7368c2ecf20Sopenharmony_ci	symtab_hash_eval(p->symtab);
7378c2ecf20Sopenharmony_ci#endif
7388c2ecf20Sopenharmony_ci
7398c2ecf20Sopenharmony_ci	p->class_val_to_struct = kcalloc(p->p_classes.nprim,
7408c2ecf20Sopenharmony_ci					 sizeof(*p->class_val_to_struct),
7418c2ecf20Sopenharmony_ci					 GFP_KERNEL);
7428c2ecf20Sopenharmony_ci	if (!p->class_val_to_struct)
7438c2ecf20Sopenharmony_ci		return -ENOMEM;
7448c2ecf20Sopenharmony_ci
7458c2ecf20Sopenharmony_ci	p->role_val_to_struct = kcalloc(p->p_roles.nprim,
7468c2ecf20Sopenharmony_ci					sizeof(*p->role_val_to_struct),
7478c2ecf20Sopenharmony_ci					GFP_KERNEL);
7488c2ecf20Sopenharmony_ci	if (!p->role_val_to_struct)
7498c2ecf20Sopenharmony_ci		return -ENOMEM;
7508c2ecf20Sopenharmony_ci
7518c2ecf20Sopenharmony_ci	p->user_val_to_struct = kcalloc(p->p_users.nprim,
7528c2ecf20Sopenharmony_ci					sizeof(*p->user_val_to_struct),
7538c2ecf20Sopenharmony_ci					GFP_KERNEL);
7548c2ecf20Sopenharmony_ci	if (!p->user_val_to_struct)
7558c2ecf20Sopenharmony_ci		return -ENOMEM;
7568c2ecf20Sopenharmony_ci
7578c2ecf20Sopenharmony_ci	p->type_val_to_struct = kvcalloc(p->p_types.nprim,
7588c2ecf20Sopenharmony_ci					 sizeof(*p->type_val_to_struct),
7598c2ecf20Sopenharmony_ci					 GFP_KERNEL);
7608c2ecf20Sopenharmony_ci	if (!p->type_val_to_struct)
7618c2ecf20Sopenharmony_ci		return -ENOMEM;
7628c2ecf20Sopenharmony_ci
7638c2ecf20Sopenharmony_ci	rc = cond_init_bool_indexes(p);
7648c2ecf20Sopenharmony_ci	if (rc)
7658c2ecf20Sopenharmony_ci		goto out;
7668c2ecf20Sopenharmony_ci
7678c2ecf20Sopenharmony_ci	for (i = 0; i < SYM_NUM; i++) {
7688c2ecf20Sopenharmony_ci		p->sym_val_to_name[i] = kvcalloc(p->symtab[i].nprim,
7698c2ecf20Sopenharmony_ci						 sizeof(char *),
7708c2ecf20Sopenharmony_ci						 GFP_KERNEL);
7718c2ecf20Sopenharmony_ci		if (!p->sym_val_to_name[i])
7728c2ecf20Sopenharmony_ci			return -ENOMEM;
7738c2ecf20Sopenharmony_ci
7748c2ecf20Sopenharmony_ci		rc = hashtab_map(&p->symtab[i].table, index_f[i], p);
7758c2ecf20Sopenharmony_ci		if (rc)
7768c2ecf20Sopenharmony_ci			goto out;
7778c2ecf20Sopenharmony_ci	}
7788c2ecf20Sopenharmony_ci	rc = 0;
7798c2ecf20Sopenharmony_ciout:
7808c2ecf20Sopenharmony_ci	return rc;
7818c2ecf20Sopenharmony_ci}
7828c2ecf20Sopenharmony_ci
7838c2ecf20Sopenharmony_ci/*
7848c2ecf20Sopenharmony_ci * Free any memory allocated by a policy database structure.
7858c2ecf20Sopenharmony_ci */
7868c2ecf20Sopenharmony_civoid policydb_destroy(struct policydb *p)
7878c2ecf20Sopenharmony_ci{
7888c2ecf20Sopenharmony_ci	struct ocontext *c, *ctmp;
7898c2ecf20Sopenharmony_ci	struct genfs *g, *gtmp;
7908c2ecf20Sopenharmony_ci	int i;
7918c2ecf20Sopenharmony_ci	struct role_allow *ra, *lra = NULL;
7928c2ecf20Sopenharmony_ci
7938c2ecf20Sopenharmony_ci	for (i = 0; i < SYM_NUM; i++) {
7948c2ecf20Sopenharmony_ci		cond_resched();
7958c2ecf20Sopenharmony_ci		hashtab_map(&p->symtab[i].table, destroy_f[i], NULL);
7968c2ecf20Sopenharmony_ci		hashtab_destroy(&p->symtab[i].table);
7978c2ecf20Sopenharmony_ci	}
7988c2ecf20Sopenharmony_ci
7998c2ecf20Sopenharmony_ci	for (i = 0; i < SYM_NUM; i++)
8008c2ecf20Sopenharmony_ci		kvfree(p->sym_val_to_name[i]);
8018c2ecf20Sopenharmony_ci
8028c2ecf20Sopenharmony_ci	kfree(p->class_val_to_struct);
8038c2ecf20Sopenharmony_ci	kfree(p->role_val_to_struct);
8048c2ecf20Sopenharmony_ci	kfree(p->user_val_to_struct);
8058c2ecf20Sopenharmony_ci	kvfree(p->type_val_to_struct);
8068c2ecf20Sopenharmony_ci
8078c2ecf20Sopenharmony_ci	avtab_destroy(&p->te_avtab);
8088c2ecf20Sopenharmony_ci
8098c2ecf20Sopenharmony_ci	for (i = 0; i < OCON_NUM; i++) {
8108c2ecf20Sopenharmony_ci		cond_resched();
8118c2ecf20Sopenharmony_ci		c = p->ocontexts[i];
8128c2ecf20Sopenharmony_ci		while (c) {
8138c2ecf20Sopenharmony_ci			ctmp = c;
8148c2ecf20Sopenharmony_ci			c = c->next;
8158c2ecf20Sopenharmony_ci			ocontext_destroy(ctmp, i);
8168c2ecf20Sopenharmony_ci		}
8178c2ecf20Sopenharmony_ci		p->ocontexts[i] = NULL;
8188c2ecf20Sopenharmony_ci	}
8198c2ecf20Sopenharmony_ci
8208c2ecf20Sopenharmony_ci	g = p->genfs;
8218c2ecf20Sopenharmony_ci	while (g) {
8228c2ecf20Sopenharmony_ci		cond_resched();
8238c2ecf20Sopenharmony_ci		kfree(g->fstype);
8248c2ecf20Sopenharmony_ci		c = g->head;
8258c2ecf20Sopenharmony_ci		while (c) {
8268c2ecf20Sopenharmony_ci			ctmp = c;
8278c2ecf20Sopenharmony_ci			c = c->next;
8288c2ecf20Sopenharmony_ci			ocontext_destroy(ctmp, OCON_FSUSE);
8298c2ecf20Sopenharmony_ci		}
8308c2ecf20Sopenharmony_ci		gtmp = g;
8318c2ecf20Sopenharmony_ci		g = g->next;
8328c2ecf20Sopenharmony_ci		kfree(gtmp);
8338c2ecf20Sopenharmony_ci	}
8348c2ecf20Sopenharmony_ci	p->genfs = NULL;
8358c2ecf20Sopenharmony_ci
8368c2ecf20Sopenharmony_ci	cond_policydb_destroy(p);
8378c2ecf20Sopenharmony_ci
8388c2ecf20Sopenharmony_ci	hashtab_map(&p->role_tr, role_tr_destroy, NULL);
8398c2ecf20Sopenharmony_ci	hashtab_destroy(&p->role_tr);
8408c2ecf20Sopenharmony_ci
8418c2ecf20Sopenharmony_ci	for (ra = p->role_allow; ra; ra = ra->next) {
8428c2ecf20Sopenharmony_ci		cond_resched();
8438c2ecf20Sopenharmony_ci		kfree(lra);
8448c2ecf20Sopenharmony_ci		lra = ra;
8458c2ecf20Sopenharmony_ci	}
8468c2ecf20Sopenharmony_ci	kfree(lra);
8478c2ecf20Sopenharmony_ci
8488c2ecf20Sopenharmony_ci	hashtab_map(&p->filename_trans, filenametr_destroy, NULL);
8498c2ecf20Sopenharmony_ci	hashtab_destroy(&p->filename_trans);
8508c2ecf20Sopenharmony_ci
8518c2ecf20Sopenharmony_ci	hashtab_map(&p->range_tr, range_tr_destroy, NULL);
8528c2ecf20Sopenharmony_ci	hashtab_destroy(&p->range_tr);
8538c2ecf20Sopenharmony_ci
8548c2ecf20Sopenharmony_ci	if (p->type_attr_map_array) {
8558c2ecf20Sopenharmony_ci		for (i = 0; i < p->p_types.nprim; i++)
8568c2ecf20Sopenharmony_ci			ebitmap_destroy(&p->type_attr_map_array[i]);
8578c2ecf20Sopenharmony_ci		kvfree(p->type_attr_map_array);
8588c2ecf20Sopenharmony_ci	}
8598c2ecf20Sopenharmony_ci
8608c2ecf20Sopenharmony_ci	ebitmap_destroy(&p->filename_trans_ttypes);
8618c2ecf20Sopenharmony_ci	ebitmap_destroy(&p->policycaps);
8628c2ecf20Sopenharmony_ci	ebitmap_destroy(&p->permissive_map);
8638c2ecf20Sopenharmony_ci}
8648c2ecf20Sopenharmony_ci
8658c2ecf20Sopenharmony_ci/*
8668c2ecf20Sopenharmony_ci * Load the initial SIDs specified in a policy database
8678c2ecf20Sopenharmony_ci * structure into a SID table.
8688c2ecf20Sopenharmony_ci */
8698c2ecf20Sopenharmony_ciint policydb_load_isids(struct policydb *p, struct sidtab *s)
8708c2ecf20Sopenharmony_ci{
8718c2ecf20Sopenharmony_ci	struct ocontext *head, *c;
8728c2ecf20Sopenharmony_ci	int rc;
8738c2ecf20Sopenharmony_ci
8748c2ecf20Sopenharmony_ci	rc = sidtab_init(s);
8758c2ecf20Sopenharmony_ci	if (rc) {
8768c2ecf20Sopenharmony_ci		pr_err("SELinux:  out of memory on SID table init\n");
8778c2ecf20Sopenharmony_ci		return rc;
8788c2ecf20Sopenharmony_ci	}
8798c2ecf20Sopenharmony_ci
8808c2ecf20Sopenharmony_ci	head = p->ocontexts[OCON_ISID];
8818c2ecf20Sopenharmony_ci	for (c = head; c; c = c->next) {
8828c2ecf20Sopenharmony_ci		u32 sid = c->sid[0];
8838c2ecf20Sopenharmony_ci		const char *name = security_get_initial_sid_context(sid);
8848c2ecf20Sopenharmony_ci
8858c2ecf20Sopenharmony_ci		if (sid == SECSID_NULL) {
8868c2ecf20Sopenharmony_ci			pr_err("SELinux:  SID 0 was assigned a context.\n");
8878c2ecf20Sopenharmony_ci			sidtab_destroy(s);
8888c2ecf20Sopenharmony_ci			return -EINVAL;
8898c2ecf20Sopenharmony_ci		}
8908c2ecf20Sopenharmony_ci
8918c2ecf20Sopenharmony_ci		/* Ignore initial SIDs unused by this kernel. */
8928c2ecf20Sopenharmony_ci		if (!name)
8938c2ecf20Sopenharmony_ci			continue;
8948c2ecf20Sopenharmony_ci
8958c2ecf20Sopenharmony_ci		rc = sidtab_set_initial(s, sid, &c->context[0]);
8968c2ecf20Sopenharmony_ci		if (rc) {
8978c2ecf20Sopenharmony_ci			pr_err("SELinux:  unable to load initial SID %s.\n",
8988c2ecf20Sopenharmony_ci			       name);
8998c2ecf20Sopenharmony_ci			sidtab_destroy(s);
9008c2ecf20Sopenharmony_ci			return rc;
9018c2ecf20Sopenharmony_ci		}
9028c2ecf20Sopenharmony_ci	}
9038c2ecf20Sopenharmony_ci	return 0;
9048c2ecf20Sopenharmony_ci}
9058c2ecf20Sopenharmony_ci
9068c2ecf20Sopenharmony_ciint policydb_class_isvalid(struct policydb *p, unsigned int class)
9078c2ecf20Sopenharmony_ci{
9088c2ecf20Sopenharmony_ci	if (!class || class > p->p_classes.nprim)
9098c2ecf20Sopenharmony_ci		return 0;
9108c2ecf20Sopenharmony_ci	return 1;
9118c2ecf20Sopenharmony_ci}
9128c2ecf20Sopenharmony_ci
9138c2ecf20Sopenharmony_ciint policydb_role_isvalid(struct policydb *p, unsigned int role)
9148c2ecf20Sopenharmony_ci{
9158c2ecf20Sopenharmony_ci	if (!role || role > p->p_roles.nprim)
9168c2ecf20Sopenharmony_ci		return 0;
9178c2ecf20Sopenharmony_ci	return 1;
9188c2ecf20Sopenharmony_ci}
9198c2ecf20Sopenharmony_ci
9208c2ecf20Sopenharmony_ciint policydb_type_isvalid(struct policydb *p, unsigned int type)
9218c2ecf20Sopenharmony_ci{
9228c2ecf20Sopenharmony_ci	if (!type || type > p->p_types.nprim)
9238c2ecf20Sopenharmony_ci		return 0;
9248c2ecf20Sopenharmony_ci	return 1;
9258c2ecf20Sopenharmony_ci}
9268c2ecf20Sopenharmony_ci
9278c2ecf20Sopenharmony_ci/*
9288c2ecf20Sopenharmony_ci * Return 1 if the fields in the security context
9298c2ecf20Sopenharmony_ci * structure `c' are valid.  Return 0 otherwise.
9308c2ecf20Sopenharmony_ci */
9318c2ecf20Sopenharmony_ciint policydb_context_isvalid(struct policydb *p, struct context *c)
9328c2ecf20Sopenharmony_ci{
9338c2ecf20Sopenharmony_ci	struct role_datum *role;
9348c2ecf20Sopenharmony_ci	struct user_datum *usrdatum;
9358c2ecf20Sopenharmony_ci
9368c2ecf20Sopenharmony_ci	if (!c->role || c->role > p->p_roles.nprim)
9378c2ecf20Sopenharmony_ci		return 0;
9388c2ecf20Sopenharmony_ci
9398c2ecf20Sopenharmony_ci	if (!c->user || c->user > p->p_users.nprim)
9408c2ecf20Sopenharmony_ci		return 0;
9418c2ecf20Sopenharmony_ci
9428c2ecf20Sopenharmony_ci	if (!c->type || c->type > p->p_types.nprim)
9438c2ecf20Sopenharmony_ci		return 0;
9448c2ecf20Sopenharmony_ci
9458c2ecf20Sopenharmony_ci	if (c->role != OBJECT_R_VAL) {
9468c2ecf20Sopenharmony_ci		/*
9478c2ecf20Sopenharmony_ci		 * Role must be authorized for the type.
9488c2ecf20Sopenharmony_ci		 */
9498c2ecf20Sopenharmony_ci		role = p->role_val_to_struct[c->role - 1];
9508c2ecf20Sopenharmony_ci		if (!role || !ebitmap_get_bit(&role->types, c->type - 1))
9518c2ecf20Sopenharmony_ci			/* role may not be associated with type */
9528c2ecf20Sopenharmony_ci			return 0;
9538c2ecf20Sopenharmony_ci
9548c2ecf20Sopenharmony_ci		/*
9558c2ecf20Sopenharmony_ci		 * User must be authorized for the role.
9568c2ecf20Sopenharmony_ci		 */
9578c2ecf20Sopenharmony_ci		usrdatum = p->user_val_to_struct[c->user - 1];
9588c2ecf20Sopenharmony_ci		if (!usrdatum)
9598c2ecf20Sopenharmony_ci			return 0;
9608c2ecf20Sopenharmony_ci
9618c2ecf20Sopenharmony_ci		if (!ebitmap_get_bit(&usrdatum->roles, c->role - 1))
9628c2ecf20Sopenharmony_ci			/* user may not be associated with role */
9638c2ecf20Sopenharmony_ci			return 0;
9648c2ecf20Sopenharmony_ci	}
9658c2ecf20Sopenharmony_ci
9668c2ecf20Sopenharmony_ci	if (!mls_context_isvalid(p, c))
9678c2ecf20Sopenharmony_ci		return 0;
9688c2ecf20Sopenharmony_ci
9698c2ecf20Sopenharmony_ci	return 1;
9708c2ecf20Sopenharmony_ci}
9718c2ecf20Sopenharmony_ci
9728c2ecf20Sopenharmony_ci/*
9738c2ecf20Sopenharmony_ci * Read a MLS range structure from a policydb binary
9748c2ecf20Sopenharmony_ci * representation file.
9758c2ecf20Sopenharmony_ci */
9768c2ecf20Sopenharmony_cistatic int mls_read_range_helper(struct mls_range *r, void *fp)
9778c2ecf20Sopenharmony_ci{
9788c2ecf20Sopenharmony_ci	__le32 buf[2];
9798c2ecf20Sopenharmony_ci	u32 items;
9808c2ecf20Sopenharmony_ci	int rc;
9818c2ecf20Sopenharmony_ci
9828c2ecf20Sopenharmony_ci	rc = next_entry(buf, fp, sizeof(u32));
9838c2ecf20Sopenharmony_ci	if (rc)
9848c2ecf20Sopenharmony_ci		goto out;
9858c2ecf20Sopenharmony_ci
9868c2ecf20Sopenharmony_ci	rc = -EINVAL;
9878c2ecf20Sopenharmony_ci	items = le32_to_cpu(buf[0]);
9888c2ecf20Sopenharmony_ci	if (items > ARRAY_SIZE(buf)) {
9898c2ecf20Sopenharmony_ci		pr_err("SELinux: mls:  range overflow\n");
9908c2ecf20Sopenharmony_ci		goto out;
9918c2ecf20Sopenharmony_ci	}
9928c2ecf20Sopenharmony_ci
9938c2ecf20Sopenharmony_ci	rc = next_entry(buf, fp, sizeof(u32) * items);
9948c2ecf20Sopenharmony_ci	if (rc) {
9958c2ecf20Sopenharmony_ci		pr_err("SELinux: mls:  truncated range\n");
9968c2ecf20Sopenharmony_ci		goto out;
9978c2ecf20Sopenharmony_ci	}
9988c2ecf20Sopenharmony_ci
9998c2ecf20Sopenharmony_ci	r->level[0].sens = le32_to_cpu(buf[0]);
10008c2ecf20Sopenharmony_ci	if (items > 1)
10018c2ecf20Sopenharmony_ci		r->level[1].sens = le32_to_cpu(buf[1]);
10028c2ecf20Sopenharmony_ci	else
10038c2ecf20Sopenharmony_ci		r->level[1].sens = r->level[0].sens;
10048c2ecf20Sopenharmony_ci
10058c2ecf20Sopenharmony_ci	rc = ebitmap_read(&r->level[0].cat, fp);
10068c2ecf20Sopenharmony_ci	if (rc) {
10078c2ecf20Sopenharmony_ci		pr_err("SELinux: mls:  error reading low categories\n");
10088c2ecf20Sopenharmony_ci		goto out;
10098c2ecf20Sopenharmony_ci	}
10108c2ecf20Sopenharmony_ci	if (items > 1) {
10118c2ecf20Sopenharmony_ci		rc = ebitmap_read(&r->level[1].cat, fp);
10128c2ecf20Sopenharmony_ci		if (rc) {
10138c2ecf20Sopenharmony_ci			pr_err("SELinux: mls:  error reading high categories\n");
10148c2ecf20Sopenharmony_ci			goto bad_high;
10158c2ecf20Sopenharmony_ci		}
10168c2ecf20Sopenharmony_ci	} else {
10178c2ecf20Sopenharmony_ci		rc = ebitmap_cpy(&r->level[1].cat, &r->level[0].cat);
10188c2ecf20Sopenharmony_ci		if (rc) {
10198c2ecf20Sopenharmony_ci			pr_err("SELinux: mls:  out of memory\n");
10208c2ecf20Sopenharmony_ci			goto bad_high;
10218c2ecf20Sopenharmony_ci		}
10228c2ecf20Sopenharmony_ci	}
10238c2ecf20Sopenharmony_ci
10248c2ecf20Sopenharmony_ci	return 0;
10258c2ecf20Sopenharmony_cibad_high:
10268c2ecf20Sopenharmony_ci	ebitmap_destroy(&r->level[0].cat);
10278c2ecf20Sopenharmony_ciout:
10288c2ecf20Sopenharmony_ci	return rc;
10298c2ecf20Sopenharmony_ci}
10308c2ecf20Sopenharmony_ci
10318c2ecf20Sopenharmony_ci/*
10328c2ecf20Sopenharmony_ci * Read and validate a security context structure
10338c2ecf20Sopenharmony_ci * from a policydb binary representation file.
10348c2ecf20Sopenharmony_ci */
10358c2ecf20Sopenharmony_cistatic int context_read_and_validate(struct context *c,
10368c2ecf20Sopenharmony_ci				     struct policydb *p,
10378c2ecf20Sopenharmony_ci				     void *fp)
10388c2ecf20Sopenharmony_ci{
10398c2ecf20Sopenharmony_ci	__le32 buf[3];
10408c2ecf20Sopenharmony_ci	int rc;
10418c2ecf20Sopenharmony_ci
10428c2ecf20Sopenharmony_ci	rc = next_entry(buf, fp, sizeof buf);
10438c2ecf20Sopenharmony_ci	if (rc) {
10448c2ecf20Sopenharmony_ci		pr_err("SELinux: context truncated\n");
10458c2ecf20Sopenharmony_ci		goto out;
10468c2ecf20Sopenharmony_ci	}
10478c2ecf20Sopenharmony_ci	c->user = le32_to_cpu(buf[0]);
10488c2ecf20Sopenharmony_ci	c->role = le32_to_cpu(buf[1]);
10498c2ecf20Sopenharmony_ci	c->type = le32_to_cpu(buf[2]);
10508c2ecf20Sopenharmony_ci	if (p->policyvers >= POLICYDB_VERSION_MLS) {
10518c2ecf20Sopenharmony_ci		rc = mls_read_range_helper(&c->range, fp);
10528c2ecf20Sopenharmony_ci		if (rc) {
10538c2ecf20Sopenharmony_ci			pr_err("SELinux: error reading MLS range of context\n");
10548c2ecf20Sopenharmony_ci			goto out;
10558c2ecf20Sopenharmony_ci		}
10568c2ecf20Sopenharmony_ci	}
10578c2ecf20Sopenharmony_ci
10588c2ecf20Sopenharmony_ci	rc = -EINVAL;
10598c2ecf20Sopenharmony_ci	if (!policydb_context_isvalid(p, c)) {
10608c2ecf20Sopenharmony_ci		pr_err("SELinux:  invalid security context\n");
10618c2ecf20Sopenharmony_ci		context_destroy(c);
10628c2ecf20Sopenharmony_ci		goto out;
10638c2ecf20Sopenharmony_ci	}
10648c2ecf20Sopenharmony_ci	rc = 0;
10658c2ecf20Sopenharmony_ciout:
10668c2ecf20Sopenharmony_ci	return rc;
10678c2ecf20Sopenharmony_ci}
10688c2ecf20Sopenharmony_ci
10698c2ecf20Sopenharmony_ci/*
10708c2ecf20Sopenharmony_ci * The following *_read functions are used to
10718c2ecf20Sopenharmony_ci * read the symbol data from a policy database
10728c2ecf20Sopenharmony_ci * binary representation file.
10738c2ecf20Sopenharmony_ci */
10748c2ecf20Sopenharmony_ci
10758c2ecf20Sopenharmony_cistatic int str_read(char **strp, gfp_t flags, void *fp, u32 len)
10768c2ecf20Sopenharmony_ci{
10778c2ecf20Sopenharmony_ci	int rc;
10788c2ecf20Sopenharmony_ci	char *str;
10798c2ecf20Sopenharmony_ci
10808c2ecf20Sopenharmony_ci	if ((len == 0) || (len == (u32)-1))
10818c2ecf20Sopenharmony_ci		return -EINVAL;
10828c2ecf20Sopenharmony_ci
10838c2ecf20Sopenharmony_ci	str = kmalloc(len + 1, flags | __GFP_NOWARN);
10848c2ecf20Sopenharmony_ci	if (!str)
10858c2ecf20Sopenharmony_ci		return -ENOMEM;
10868c2ecf20Sopenharmony_ci
10878c2ecf20Sopenharmony_ci	rc = next_entry(str, fp, len);
10888c2ecf20Sopenharmony_ci	if (rc) {
10898c2ecf20Sopenharmony_ci		kfree(str);
10908c2ecf20Sopenharmony_ci		return rc;
10918c2ecf20Sopenharmony_ci	}
10928c2ecf20Sopenharmony_ci
10938c2ecf20Sopenharmony_ci	str[len] = '\0';
10948c2ecf20Sopenharmony_ci	*strp = str;
10958c2ecf20Sopenharmony_ci	return 0;
10968c2ecf20Sopenharmony_ci}
10978c2ecf20Sopenharmony_ci
10988c2ecf20Sopenharmony_cistatic int perm_read(struct policydb *p, struct symtab *s, void *fp)
10998c2ecf20Sopenharmony_ci{
11008c2ecf20Sopenharmony_ci	char *key = NULL;
11018c2ecf20Sopenharmony_ci	struct perm_datum *perdatum;
11028c2ecf20Sopenharmony_ci	int rc;
11038c2ecf20Sopenharmony_ci	__le32 buf[2];
11048c2ecf20Sopenharmony_ci	u32 len;
11058c2ecf20Sopenharmony_ci
11068c2ecf20Sopenharmony_ci	perdatum = kzalloc(sizeof(*perdatum), GFP_KERNEL);
11078c2ecf20Sopenharmony_ci	if (!perdatum)
11088c2ecf20Sopenharmony_ci		return -ENOMEM;
11098c2ecf20Sopenharmony_ci
11108c2ecf20Sopenharmony_ci	rc = next_entry(buf, fp, sizeof buf);
11118c2ecf20Sopenharmony_ci	if (rc)
11128c2ecf20Sopenharmony_ci		goto bad;
11138c2ecf20Sopenharmony_ci
11148c2ecf20Sopenharmony_ci	len = le32_to_cpu(buf[0]);
11158c2ecf20Sopenharmony_ci	perdatum->value = le32_to_cpu(buf[1]);
11168c2ecf20Sopenharmony_ci
11178c2ecf20Sopenharmony_ci	rc = str_read(&key, GFP_KERNEL, fp, len);
11188c2ecf20Sopenharmony_ci	if (rc)
11198c2ecf20Sopenharmony_ci		goto bad;
11208c2ecf20Sopenharmony_ci
11218c2ecf20Sopenharmony_ci	rc = symtab_insert(s, key, perdatum);
11228c2ecf20Sopenharmony_ci	if (rc)
11238c2ecf20Sopenharmony_ci		goto bad;
11248c2ecf20Sopenharmony_ci
11258c2ecf20Sopenharmony_ci	return 0;
11268c2ecf20Sopenharmony_cibad:
11278c2ecf20Sopenharmony_ci	perm_destroy(key, perdatum, NULL);
11288c2ecf20Sopenharmony_ci	return rc;
11298c2ecf20Sopenharmony_ci}
11308c2ecf20Sopenharmony_ci
11318c2ecf20Sopenharmony_cistatic int common_read(struct policydb *p, struct symtab *s, void *fp)
11328c2ecf20Sopenharmony_ci{
11338c2ecf20Sopenharmony_ci	char *key = NULL;
11348c2ecf20Sopenharmony_ci	struct common_datum *comdatum;
11358c2ecf20Sopenharmony_ci	__le32 buf[4];
11368c2ecf20Sopenharmony_ci	u32 len, nel;
11378c2ecf20Sopenharmony_ci	int i, rc;
11388c2ecf20Sopenharmony_ci
11398c2ecf20Sopenharmony_ci	comdatum = kzalloc(sizeof(*comdatum), GFP_KERNEL);
11408c2ecf20Sopenharmony_ci	if (!comdatum)
11418c2ecf20Sopenharmony_ci		return -ENOMEM;
11428c2ecf20Sopenharmony_ci
11438c2ecf20Sopenharmony_ci	rc = next_entry(buf, fp, sizeof buf);
11448c2ecf20Sopenharmony_ci	if (rc)
11458c2ecf20Sopenharmony_ci		goto bad;
11468c2ecf20Sopenharmony_ci
11478c2ecf20Sopenharmony_ci	len = le32_to_cpu(buf[0]);
11488c2ecf20Sopenharmony_ci	comdatum->value = le32_to_cpu(buf[1]);
11498c2ecf20Sopenharmony_ci	nel = le32_to_cpu(buf[3]);
11508c2ecf20Sopenharmony_ci
11518c2ecf20Sopenharmony_ci	rc = symtab_init(&comdatum->permissions, nel);
11528c2ecf20Sopenharmony_ci	if (rc)
11538c2ecf20Sopenharmony_ci		goto bad;
11548c2ecf20Sopenharmony_ci	comdatum->permissions.nprim = le32_to_cpu(buf[2]);
11558c2ecf20Sopenharmony_ci
11568c2ecf20Sopenharmony_ci	rc = str_read(&key, GFP_KERNEL, fp, len);
11578c2ecf20Sopenharmony_ci	if (rc)
11588c2ecf20Sopenharmony_ci		goto bad;
11598c2ecf20Sopenharmony_ci
11608c2ecf20Sopenharmony_ci	for (i = 0; i < nel; i++) {
11618c2ecf20Sopenharmony_ci		rc = perm_read(p, &comdatum->permissions, fp);
11628c2ecf20Sopenharmony_ci		if (rc)
11638c2ecf20Sopenharmony_ci			goto bad;
11648c2ecf20Sopenharmony_ci	}
11658c2ecf20Sopenharmony_ci
11668c2ecf20Sopenharmony_ci	rc = symtab_insert(s, key, comdatum);
11678c2ecf20Sopenharmony_ci	if (rc)
11688c2ecf20Sopenharmony_ci		goto bad;
11698c2ecf20Sopenharmony_ci	return 0;
11708c2ecf20Sopenharmony_cibad:
11718c2ecf20Sopenharmony_ci	common_destroy(key, comdatum, NULL);
11728c2ecf20Sopenharmony_ci	return rc;
11738c2ecf20Sopenharmony_ci}
11748c2ecf20Sopenharmony_ci
11758c2ecf20Sopenharmony_cistatic void type_set_init(struct type_set *t)
11768c2ecf20Sopenharmony_ci{
11778c2ecf20Sopenharmony_ci	ebitmap_init(&t->types);
11788c2ecf20Sopenharmony_ci	ebitmap_init(&t->negset);
11798c2ecf20Sopenharmony_ci}
11808c2ecf20Sopenharmony_ci
11818c2ecf20Sopenharmony_cistatic int type_set_read(struct type_set *t, void *fp)
11828c2ecf20Sopenharmony_ci{
11838c2ecf20Sopenharmony_ci	__le32 buf[1];
11848c2ecf20Sopenharmony_ci	int rc;
11858c2ecf20Sopenharmony_ci
11868c2ecf20Sopenharmony_ci	if (ebitmap_read(&t->types, fp))
11878c2ecf20Sopenharmony_ci		return -EINVAL;
11888c2ecf20Sopenharmony_ci	if (ebitmap_read(&t->negset, fp))
11898c2ecf20Sopenharmony_ci		return -EINVAL;
11908c2ecf20Sopenharmony_ci
11918c2ecf20Sopenharmony_ci	rc = next_entry(buf, fp, sizeof(u32));
11928c2ecf20Sopenharmony_ci	if (rc < 0)
11938c2ecf20Sopenharmony_ci		return -EINVAL;
11948c2ecf20Sopenharmony_ci	t->flags = le32_to_cpu(buf[0]);
11958c2ecf20Sopenharmony_ci
11968c2ecf20Sopenharmony_ci	return 0;
11978c2ecf20Sopenharmony_ci}
11988c2ecf20Sopenharmony_ci
11998c2ecf20Sopenharmony_ci
12008c2ecf20Sopenharmony_cistatic int read_cons_helper(struct policydb *p,
12018c2ecf20Sopenharmony_ci				struct constraint_node **nodep,
12028c2ecf20Sopenharmony_ci				int ncons, int allowxtarget, void *fp)
12038c2ecf20Sopenharmony_ci{
12048c2ecf20Sopenharmony_ci	struct constraint_node *c, *lc;
12058c2ecf20Sopenharmony_ci	struct constraint_expr *e, *le;
12068c2ecf20Sopenharmony_ci	__le32 buf[3];
12078c2ecf20Sopenharmony_ci	u32 nexpr;
12088c2ecf20Sopenharmony_ci	int rc, i, j, depth;
12098c2ecf20Sopenharmony_ci
12108c2ecf20Sopenharmony_ci	lc = NULL;
12118c2ecf20Sopenharmony_ci	for (i = 0; i < ncons; i++) {
12128c2ecf20Sopenharmony_ci		c = kzalloc(sizeof(*c), GFP_KERNEL);
12138c2ecf20Sopenharmony_ci		if (!c)
12148c2ecf20Sopenharmony_ci			return -ENOMEM;
12158c2ecf20Sopenharmony_ci
12168c2ecf20Sopenharmony_ci		if (lc)
12178c2ecf20Sopenharmony_ci			lc->next = c;
12188c2ecf20Sopenharmony_ci		else
12198c2ecf20Sopenharmony_ci			*nodep = c;
12208c2ecf20Sopenharmony_ci
12218c2ecf20Sopenharmony_ci		rc = next_entry(buf, fp, (sizeof(u32) * 2));
12228c2ecf20Sopenharmony_ci		if (rc)
12238c2ecf20Sopenharmony_ci			return rc;
12248c2ecf20Sopenharmony_ci		c->permissions = le32_to_cpu(buf[0]);
12258c2ecf20Sopenharmony_ci		nexpr = le32_to_cpu(buf[1]);
12268c2ecf20Sopenharmony_ci		le = NULL;
12278c2ecf20Sopenharmony_ci		depth = -1;
12288c2ecf20Sopenharmony_ci		for (j = 0; j < nexpr; j++) {
12298c2ecf20Sopenharmony_ci			e = kzalloc(sizeof(*e), GFP_KERNEL);
12308c2ecf20Sopenharmony_ci			if (!e)
12318c2ecf20Sopenharmony_ci				return -ENOMEM;
12328c2ecf20Sopenharmony_ci
12338c2ecf20Sopenharmony_ci			if (le)
12348c2ecf20Sopenharmony_ci				le->next = e;
12358c2ecf20Sopenharmony_ci			else
12368c2ecf20Sopenharmony_ci				c->expr = e;
12378c2ecf20Sopenharmony_ci
12388c2ecf20Sopenharmony_ci			rc = next_entry(buf, fp, (sizeof(u32) * 3));
12398c2ecf20Sopenharmony_ci			if (rc)
12408c2ecf20Sopenharmony_ci				return rc;
12418c2ecf20Sopenharmony_ci			e->expr_type = le32_to_cpu(buf[0]);
12428c2ecf20Sopenharmony_ci			e->attr = le32_to_cpu(buf[1]);
12438c2ecf20Sopenharmony_ci			e->op = le32_to_cpu(buf[2]);
12448c2ecf20Sopenharmony_ci
12458c2ecf20Sopenharmony_ci			switch (e->expr_type) {
12468c2ecf20Sopenharmony_ci			case CEXPR_NOT:
12478c2ecf20Sopenharmony_ci				if (depth < 0)
12488c2ecf20Sopenharmony_ci					return -EINVAL;
12498c2ecf20Sopenharmony_ci				break;
12508c2ecf20Sopenharmony_ci			case CEXPR_AND:
12518c2ecf20Sopenharmony_ci			case CEXPR_OR:
12528c2ecf20Sopenharmony_ci				if (depth < 1)
12538c2ecf20Sopenharmony_ci					return -EINVAL;
12548c2ecf20Sopenharmony_ci				depth--;
12558c2ecf20Sopenharmony_ci				break;
12568c2ecf20Sopenharmony_ci			case CEXPR_ATTR:
12578c2ecf20Sopenharmony_ci				if (depth == (CEXPR_MAXDEPTH - 1))
12588c2ecf20Sopenharmony_ci					return -EINVAL;
12598c2ecf20Sopenharmony_ci				depth++;
12608c2ecf20Sopenharmony_ci				break;
12618c2ecf20Sopenharmony_ci			case CEXPR_NAMES:
12628c2ecf20Sopenharmony_ci				if (!allowxtarget && (e->attr & CEXPR_XTARGET))
12638c2ecf20Sopenharmony_ci					return -EINVAL;
12648c2ecf20Sopenharmony_ci				if (depth == (CEXPR_MAXDEPTH - 1))
12658c2ecf20Sopenharmony_ci					return -EINVAL;
12668c2ecf20Sopenharmony_ci				depth++;
12678c2ecf20Sopenharmony_ci				rc = ebitmap_read(&e->names, fp);
12688c2ecf20Sopenharmony_ci				if (rc)
12698c2ecf20Sopenharmony_ci					return rc;
12708c2ecf20Sopenharmony_ci				if (p->policyvers >=
12718c2ecf20Sopenharmony_ci				    POLICYDB_VERSION_CONSTRAINT_NAMES) {
12728c2ecf20Sopenharmony_ci					e->type_names = kzalloc(sizeof
12738c2ecf20Sopenharmony_ci						(*e->type_names), GFP_KERNEL);
12748c2ecf20Sopenharmony_ci					if (!e->type_names)
12758c2ecf20Sopenharmony_ci						return -ENOMEM;
12768c2ecf20Sopenharmony_ci					type_set_init(e->type_names);
12778c2ecf20Sopenharmony_ci					rc = type_set_read(e->type_names, fp);
12788c2ecf20Sopenharmony_ci					if (rc)
12798c2ecf20Sopenharmony_ci						return rc;
12808c2ecf20Sopenharmony_ci				}
12818c2ecf20Sopenharmony_ci				break;
12828c2ecf20Sopenharmony_ci			default:
12838c2ecf20Sopenharmony_ci				return -EINVAL;
12848c2ecf20Sopenharmony_ci			}
12858c2ecf20Sopenharmony_ci			le = e;
12868c2ecf20Sopenharmony_ci		}
12878c2ecf20Sopenharmony_ci		if (depth != 0)
12888c2ecf20Sopenharmony_ci			return -EINVAL;
12898c2ecf20Sopenharmony_ci		lc = c;
12908c2ecf20Sopenharmony_ci	}
12918c2ecf20Sopenharmony_ci
12928c2ecf20Sopenharmony_ci	return 0;
12938c2ecf20Sopenharmony_ci}
12948c2ecf20Sopenharmony_ci
12958c2ecf20Sopenharmony_cistatic int class_read(struct policydb *p, struct symtab *s, void *fp)
12968c2ecf20Sopenharmony_ci{
12978c2ecf20Sopenharmony_ci	char *key = NULL;
12988c2ecf20Sopenharmony_ci	struct class_datum *cladatum;
12998c2ecf20Sopenharmony_ci	__le32 buf[6];
13008c2ecf20Sopenharmony_ci	u32 len, len2, ncons, nel;
13018c2ecf20Sopenharmony_ci	int i, rc;
13028c2ecf20Sopenharmony_ci
13038c2ecf20Sopenharmony_ci	cladatum = kzalloc(sizeof(*cladatum), GFP_KERNEL);
13048c2ecf20Sopenharmony_ci	if (!cladatum)
13058c2ecf20Sopenharmony_ci		return -ENOMEM;
13068c2ecf20Sopenharmony_ci
13078c2ecf20Sopenharmony_ci	rc = next_entry(buf, fp, sizeof(u32)*6);
13088c2ecf20Sopenharmony_ci	if (rc)
13098c2ecf20Sopenharmony_ci		goto bad;
13108c2ecf20Sopenharmony_ci
13118c2ecf20Sopenharmony_ci	len = le32_to_cpu(buf[0]);
13128c2ecf20Sopenharmony_ci	len2 = le32_to_cpu(buf[1]);
13138c2ecf20Sopenharmony_ci	cladatum->value = le32_to_cpu(buf[2]);
13148c2ecf20Sopenharmony_ci	nel = le32_to_cpu(buf[4]);
13158c2ecf20Sopenharmony_ci
13168c2ecf20Sopenharmony_ci	rc = symtab_init(&cladatum->permissions, nel);
13178c2ecf20Sopenharmony_ci	if (rc)
13188c2ecf20Sopenharmony_ci		goto bad;
13198c2ecf20Sopenharmony_ci	cladatum->permissions.nprim = le32_to_cpu(buf[3]);
13208c2ecf20Sopenharmony_ci
13218c2ecf20Sopenharmony_ci	ncons = le32_to_cpu(buf[5]);
13228c2ecf20Sopenharmony_ci
13238c2ecf20Sopenharmony_ci	rc = str_read(&key, GFP_KERNEL, fp, len);
13248c2ecf20Sopenharmony_ci	if (rc)
13258c2ecf20Sopenharmony_ci		goto bad;
13268c2ecf20Sopenharmony_ci
13278c2ecf20Sopenharmony_ci	if (len2) {
13288c2ecf20Sopenharmony_ci		rc = str_read(&cladatum->comkey, GFP_KERNEL, fp, len2);
13298c2ecf20Sopenharmony_ci		if (rc)
13308c2ecf20Sopenharmony_ci			goto bad;
13318c2ecf20Sopenharmony_ci
13328c2ecf20Sopenharmony_ci		rc = -EINVAL;
13338c2ecf20Sopenharmony_ci		cladatum->comdatum = symtab_search(&p->p_commons,
13348c2ecf20Sopenharmony_ci						   cladatum->comkey);
13358c2ecf20Sopenharmony_ci		if (!cladatum->comdatum) {
13368c2ecf20Sopenharmony_ci			pr_err("SELinux:  unknown common %s\n",
13378c2ecf20Sopenharmony_ci			       cladatum->comkey);
13388c2ecf20Sopenharmony_ci			goto bad;
13398c2ecf20Sopenharmony_ci		}
13408c2ecf20Sopenharmony_ci	}
13418c2ecf20Sopenharmony_ci	for (i = 0; i < nel; i++) {
13428c2ecf20Sopenharmony_ci		rc = perm_read(p, &cladatum->permissions, fp);
13438c2ecf20Sopenharmony_ci		if (rc)
13448c2ecf20Sopenharmony_ci			goto bad;
13458c2ecf20Sopenharmony_ci	}
13468c2ecf20Sopenharmony_ci
13478c2ecf20Sopenharmony_ci	rc = read_cons_helper(p, &cladatum->constraints, ncons, 0, fp);
13488c2ecf20Sopenharmony_ci	if (rc)
13498c2ecf20Sopenharmony_ci		goto bad;
13508c2ecf20Sopenharmony_ci
13518c2ecf20Sopenharmony_ci	if (p->policyvers >= POLICYDB_VERSION_VALIDATETRANS) {
13528c2ecf20Sopenharmony_ci		/* grab the validatetrans rules */
13538c2ecf20Sopenharmony_ci		rc = next_entry(buf, fp, sizeof(u32));
13548c2ecf20Sopenharmony_ci		if (rc)
13558c2ecf20Sopenharmony_ci			goto bad;
13568c2ecf20Sopenharmony_ci		ncons = le32_to_cpu(buf[0]);
13578c2ecf20Sopenharmony_ci		rc = read_cons_helper(p, &cladatum->validatetrans,
13588c2ecf20Sopenharmony_ci				ncons, 1, fp);
13598c2ecf20Sopenharmony_ci		if (rc)
13608c2ecf20Sopenharmony_ci			goto bad;
13618c2ecf20Sopenharmony_ci	}
13628c2ecf20Sopenharmony_ci
13638c2ecf20Sopenharmony_ci	if (p->policyvers >= POLICYDB_VERSION_NEW_OBJECT_DEFAULTS) {
13648c2ecf20Sopenharmony_ci		rc = next_entry(buf, fp, sizeof(u32) * 3);
13658c2ecf20Sopenharmony_ci		if (rc)
13668c2ecf20Sopenharmony_ci			goto bad;
13678c2ecf20Sopenharmony_ci
13688c2ecf20Sopenharmony_ci		cladatum->default_user = le32_to_cpu(buf[0]);
13698c2ecf20Sopenharmony_ci		cladatum->default_role = le32_to_cpu(buf[1]);
13708c2ecf20Sopenharmony_ci		cladatum->default_range = le32_to_cpu(buf[2]);
13718c2ecf20Sopenharmony_ci	}
13728c2ecf20Sopenharmony_ci
13738c2ecf20Sopenharmony_ci	if (p->policyvers >= POLICYDB_VERSION_DEFAULT_TYPE) {
13748c2ecf20Sopenharmony_ci		rc = next_entry(buf, fp, sizeof(u32) * 1);
13758c2ecf20Sopenharmony_ci		if (rc)
13768c2ecf20Sopenharmony_ci			goto bad;
13778c2ecf20Sopenharmony_ci		cladatum->default_type = le32_to_cpu(buf[0]);
13788c2ecf20Sopenharmony_ci	}
13798c2ecf20Sopenharmony_ci
13808c2ecf20Sopenharmony_ci	rc = symtab_insert(s, key, cladatum);
13818c2ecf20Sopenharmony_ci	if (rc)
13828c2ecf20Sopenharmony_ci		goto bad;
13838c2ecf20Sopenharmony_ci
13848c2ecf20Sopenharmony_ci	return 0;
13858c2ecf20Sopenharmony_cibad:
13868c2ecf20Sopenharmony_ci	cls_destroy(key, cladatum, NULL);
13878c2ecf20Sopenharmony_ci	return rc;
13888c2ecf20Sopenharmony_ci}
13898c2ecf20Sopenharmony_ci
13908c2ecf20Sopenharmony_cistatic int role_read(struct policydb *p, struct symtab *s, void *fp)
13918c2ecf20Sopenharmony_ci{
13928c2ecf20Sopenharmony_ci	char *key = NULL;
13938c2ecf20Sopenharmony_ci	struct role_datum *role;
13948c2ecf20Sopenharmony_ci	int rc, to_read = 2;
13958c2ecf20Sopenharmony_ci	__le32 buf[3];
13968c2ecf20Sopenharmony_ci	u32 len;
13978c2ecf20Sopenharmony_ci
13988c2ecf20Sopenharmony_ci	role = kzalloc(sizeof(*role), GFP_KERNEL);
13998c2ecf20Sopenharmony_ci	if (!role)
14008c2ecf20Sopenharmony_ci		return -ENOMEM;
14018c2ecf20Sopenharmony_ci
14028c2ecf20Sopenharmony_ci	if (p->policyvers >= POLICYDB_VERSION_BOUNDARY)
14038c2ecf20Sopenharmony_ci		to_read = 3;
14048c2ecf20Sopenharmony_ci
14058c2ecf20Sopenharmony_ci	rc = next_entry(buf, fp, sizeof(buf[0]) * to_read);
14068c2ecf20Sopenharmony_ci	if (rc)
14078c2ecf20Sopenharmony_ci		goto bad;
14088c2ecf20Sopenharmony_ci
14098c2ecf20Sopenharmony_ci	len = le32_to_cpu(buf[0]);
14108c2ecf20Sopenharmony_ci	role->value = le32_to_cpu(buf[1]);
14118c2ecf20Sopenharmony_ci	if (p->policyvers >= POLICYDB_VERSION_BOUNDARY)
14128c2ecf20Sopenharmony_ci		role->bounds = le32_to_cpu(buf[2]);
14138c2ecf20Sopenharmony_ci
14148c2ecf20Sopenharmony_ci	rc = str_read(&key, GFP_KERNEL, fp, len);
14158c2ecf20Sopenharmony_ci	if (rc)
14168c2ecf20Sopenharmony_ci		goto bad;
14178c2ecf20Sopenharmony_ci
14188c2ecf20Sopenharmony_ci	rc = ebitmap_read(&role->dominates, fp);
14198c2ecf20Sopenharmony_ci	if (rc)
14208c2ecf20Sopenharmony_ci		goto bad;
14218c2ecf20Sopenharmony_ci
14228c2ecf20Sopenharmony_ci	rc = ebitmap_read(&role->types, fp);
14238c2ecf20Sopenharmony_ci	if (rc)
14248c2ecf20Sopenharmony_ci		goto bad;
14258c2ecf20Sopenharmony_ci
14268c2ecf20Sopenharmony_ci	if (strcmp(key, OBJECT_R) == 0) {
14278c2ecf20Sopenharmony_ci		rc = -EINVAL;
14288c2ecf20Sopenharmony_ci		if (role->value != OBJECT_R_VAL) {
14298c2ecf20Sopenharmony_ci			pr_err("SELinux: Role %s has wrong value %d\n",
14308c2ecf20Sopenharmony_ci			       OBJECT_R, role->value);
14318c2ecf20Sopenharmony_ci			goto bad;
14328c2ecf20Sopenharmony_ci		}
14338c2ecf20Sopenharmony_ci		rc = 0;
14348c2ecf20Sopenharmony_ci		goto bad;
14358c2ecf20Sopenharmony_ci	}
14368c2ecf20Sopenharmony_ci
14378c2ecf20Sopenharmony_ci	rc = symtab_insert(s, key, role);
14388c2ecf20Sopenharmony_ci	if (rc)
14398c2ecf20Sopenharmony_ci		goto bad;
14408c2ecf20Sopenharmony_ci	return 0;
14418c2ecf20Sopenharmony_cibad:
14428c2ecf20Sopenharmony_ci	role_destroy(key, role, NULL);
14438c2ecf20Sopenharmony_ci	return rc;
14448c2ecf20Sopenharmony_ci}
14458c2ecf20Sopenharmony_ci
14468c2ecf20Sopenharmony_cistatic int type_read(struct policydb *p, struct symtab *s, void *fp)
14478c2ecf20Sopenharmony_ci{
14488c2ecf20Sopenharmony_ci	char *key = NULL;
14498c2ecf20Sopenharmony_ci	struct type_datum *typdatum;
14508c2ecf20Sopenharmony_ci	int rc, to_read = 3;
14518c2ecf20Sopenharmony_ci	__le32 buf[4];
14528c2ecf20Sopenharmony_ci	u32 len;
14538c2ecf20Sopenharmony_ci
14548c2ecf20Sopenharmony_ci	typdatum = kzalloc(sizeof(*typdatum), GFP_KERNEL);
14558c2ecf20Sopenharmony_ci	if (!typdatum)
14568c2ecf20Sopenharmony_ci		return -ENOMEM;
14578c2ecf20Sopenharmony_ci
14588c2ecf20Sopenharmony_ci	if (p->policyvers >= POLICYDB_VERSION_BOUNDARY)
14598c2ecf20Sopenharmony_ci		to_read = 4;
14608c2ecf20Sopenharmony_ci
14618c2ecf20Sopenharmony_ci	rc = next_entry(buf, fp, sizeof(buf[0]) * to_read);
14628c2ecf20Sopenharmony_ci	if (rc)
14638c2ecf20Sopenharmony_ci		goto bad;
14648c2ecf20Sopenharmony_ci
14658c2ecf20Sopenharmony_ci	len = le32_to_cpu(buf[0]);
14668c2ecf20Sopenharmony_ci	typdatum->value = le32_to_cpu(buf[1]);
14678c2ecf20Sopenharmony_ci	if (p->policyvers >= POLICYDB_VERSION_BOUNDARY) {
14688c2ecf20Sopenharmony_ci		u32 prop = le32_to_cpu(buf[2]);
14698c2ecf20Sopenharmony_ci
14708c2ecf20Sopenharmony_ci		if (prop & TYPEDATUM_PROPERTY_PRIMARY)
14718c2ecf20Sopenharmony_ci			typdatum->primary = 1;
14728c2ecf20Sopenharmony_ci		if (prop & TYPEDATUM_PROPERTY_ATTRIBUTE)
14738c2ecf20Sopenharmony_ci			typdatum->attribute = 1;
14748c2ecf20Sopenharmony_ci
14758c2ecf20Sopenharmony_ci		typdatum->bounds = le32_to_cpu(buf[3]);
14768c2ecf20Sopenharmony_ci	} else {
14778c2ecf20Sopenharmony_ci		typdatum->primary = le32_to_cpu(buf[2]);
14788c2ecf20Sopenharmony_ci	}
14798c2ecf20Sopenharmony_ci
14808c2ecf20Sopenharmony_ci	rc = str_read(&key, GFP_KERNEL, fp, len);
14818c2ecf20Sopenharmony_ci	if (rc)
14828c2ecf20Sopenharmony_ci		goto bad;
14838c2ecf20Sopenharmony_ci
14848c2ecf20Sopenharmony_ci	rc = symtab_insert(s, key, typdatum);
14858c2ecf20Sopenharmony_ci	if (rc)
14868c2ecf20Sopenharmony_ci		goto bad;
14878c2ecf20Sopenharmony_ci	return 0;
14888c2ecf20Sopenharmony_cibad:
14898c2ecf20Sopenharmony_ci	type_destroy(key, typdatum, NULL);
14908c2ecf20Sopenharmony_ci	return rc;
14918c2ecf20Sopenharmony_ci}
14928c2ecf20Sopenharmony_ci
14938c2ecf20Sopenharmony_ci
14948c2ecf20Sopenharmony_ci/*
14958c2ecf20Sopenharmony_ci * Read a MLS level structure from a policydb binary
14968c2ecf20Sopenharmony_ci * representation file.
14978c2ecf20Sopenharmony_ci */
14988c2ecf20Sopenharmony_cistatic int mls_read_level(struct mls_level *lp, void *fp)
14998c2ecf20Sopenharmony_ci{
15008c2ecf20Sopenharmony_ci	__le32 buf[1];
15018c2ecf20Sopenharmony_ci	int rc;
15028c2ecf20Sopenharmony_ci
15038c2ecf20Sopenharmony_ci	memset(lp, 0, sizeof(*lp));
15048c2ecf20Sopenharmony_ci
15058c2ecf20Sopenharmony_ci	rc = next_entry(buf, fp, sizeof buf);
15068c2ecf20Sopenharmony_ci	if (rc) {
15078c2ecf20Sopenharmony_ci		pr_err("SELinux: mls: truncated level\n");
15088c2ecf20Sopenharmony_ci		return rc;
15098c2ecf20Sopenharmony_ci	}
15108c2ecf20Sopenharmony_ci	lp->sens = le32_to_cpu(buf[0]);
15118c2ecf20Sopenharmony_ci
15128c2ecf20Sopenharmony_ci	rc = ebitmap_read(&lp->cat, fp);
15138c2ecf20Sopenharmony_ci	if (rc) {
15148c2ecf20Sopenharmony_ci		pr_err("SELinux: mls:  error reading level categories\n");
15158c2ecf20Sopenharmony_ci		return rc;
15168c2ecf20Sopenharmony_ci	}
15178c2ecf20Sopenharmony_ci	return 0;
15188c2ecf20Sopenharmony_ci}
15198c2ecf20Sopenharmony_ci
15208c2ecf20Sopenharmony_cistatic int user_read(struct policydb *p, struct symtab *s, void *fp)
15218c2ecf20Sopenharmony_ci{
15228c2ecf20Sopenharmony_ci	char *key = NULL;
15238c2ecf20Sopenharmony_ci	struct user_datum *usrdatum;
15248c2ecf20Sopenharmony_ci	int rc, to_read = 2;
15258c2ecf20Sopenharmony_ci	__le32 buf[3];
15268c2ecf20Sopenharmony_ci	u32 len;
15278c2ecf20Sopenharmony_ci
15288c2ecf20Sopenharmony_ci	usrdatum = kzalloc(sizeof(*usrdatum), GFP_KERNEL);
15298c2ecf20Sopenharmony_ci	if (!usrdatum)
15308c2ecf20Sopenharmony_ci		return -ENOMEM;
15318c2ecf20Sopenharmony_ci
15328c2ecf20Sopenharmony_ci	if (p->policyvers >= POLICYDB_VERSION_BOUNDARY)
15338c2ecf20Sopenharmony_ci		to_read = 3;
15348c2ecf20Sopenharmony_ci
15358c2ecf20Sopenharmony_ci	rc = next_entry(buf, fp, sizeof(buf[0]) * to_read);
15368c2ecf20Sopenharmony_ci	if (rc)
15378c2ecf20Sopenharmony_ci		goto bad;
15388c2ecf20Sopenharmony_ci
15398c2ecf20Sopenharmony_ci	len = le32_to_cpu(buf[0]);
15408c2ecf20Sopenharmony_ci	usrdatum->value = le32_to_cpu(buf[1]);
15418c2ecf20Sopenharmony_ci	if (p->policyvers >= POLICYDB_VERSION_BOUNDARY)
15428c2ecf20Sopenharmony_ci		usrdatum->bounds = le32_to_cpu(buf[2]);
15438c2ecf20Sopenharmony_ci
15448c2ecf20Sopenharmony_ci	rc = str_read(&key, GFP_KERNEL, fp, len);
15458c2ecf20Sopenharmony_ci	if (rc)
15468c2ecf20Sopenharmony_ci		goto bad;
15478c2ecf20Sopenharmony_ci
15488c2ecf20Sopenharmony_ci	rc = ebitmap_read(&usrdatum->roles, fp);
15498c2ecf20Sopenharmony_ci	if (rc)
15508c2ecf20Sopenharmony_ci		goto bad;
15518c2ecf20Sopenharmony_ci
15528c2ecf20Sopenharmony_ci	if (p->policyvers >= POLICYDB_VERSION_MLS) {
15538c2ecf20Sopenharmony_ci		rc = mls_read_range_helper(&usrdatum->range, fp);
15548c2ecf20Sopenharmony_ci		if (rc)
15558c2ecf20Sopenharmony_ci			goto bad;
15568c2ecf20Sopenharmony_ci		rc = mls_read_level(&usrdatum->dfltlevel, fp);
15578c2ecf20Sopenharmony_ci		if (rc)
15588c2ecf20Sopenharmony_ci			goto bad;
15598c2ecf20Sopenharmony_ci	}
15608c2ecf20Sopenharmony_ci
15618c2ecf20Sopenharmony_ci	rc = symtab_insert(s, key, usrdatum);
15628c2ecf20Sopenharmony_ci	if (rc)
15638c2ecf20Sopenharmony_ci		goto bad;
15648c2ecf20Sopenharmony_ci	return 0;
15658c2ecf20Sopenharmony_cibad:
15668c2ecf20Sopenharmony_ci	user_destroy(key, usrdatum, NULL);
15678c2ecf20Sopenharmony_ci	return rc;
15688c2ecf20Sopenharmony_ci}
15698c2ecf20Sopenharmony_ci
15708c2ecf20Sopenharmony_cistatic int sens_read(struct policydb *p, struct symtab *s, void *fp)
15718c2ecf20Sopenharmony_ci{
15728c2ecf20Sopenharmony_ci	char *key = NULL;
15738c2ecf20Sopenharmony_ci	struct level_datum *levdatum;
15748c2ecf20Sopenharmony_ci	int rc;
15758c2ecf20Sopenharmony_ci	__le32 buf[2];
15768c2ecf20Sopenharmony_ci	u32 len;
15778c2ecf20Sopenharmony_ci
15788c2ecf20Sopenharmony_ci	levdatum = kzalloc(sizeof(*levdatum), GFP_ATOMIC);
15798c2ecf20Sopenharmony_ci	if (!levdatum)
15808c2ecf20Sopenharmony_ci		return -ENOMEM;
15818c2ecf20Sopenharmony_ci
15828c2ecf20Sopenharmony_ci	rc = next_entry(buf, fp, sizeof buf);
15838c2ecf20Sopenharmony_ci	if (rc)
15848c2ecf20Sopenharmony_ci		goto bad;
15858c2ecf20Sopenharmony_ci
15868c2ecf20Sopenharmony_ci	len = le32_to_cpu(buf[0]);
15878c2ecf20Sopenharmony_ci	levdatum->isalias = le32_to_cpu(buf[1]);
15888c2ecf20Sopenharmony_ci
15898c2ecf20Sopenharmony_ci	rc = str_read(&key, GFP_ATOMIC, fp, len);
15908c2ecf20Sopenharmony_ci	if (rc)
15918c2ecf20Sopenharmony_ci		goto bad;
15928c2ecf20Sopenharmony_ci
15938c2ecf20Sopenharmony_ci	rc = -ENOMEM;
15948c2ecf20Sopenharmony_ci	levdatum->level = kmalloc(sizeof(*levdatum->level), GFP_ATOMIC);
15958c2ecf20Sopenharmony_ci	if (!levdatum->level)
15968c2ecf20Sopenharmony_ci		goto bad;
15978c2ecf20Sopenharmony_ci
15988c2ecf20Sopenharmony_ci	rc = mls_read_level(levdatum->level, fp);
15998c2ecf20Sopenharmony_ci	if (rc)
16008c2ecf20Sopenharmony_ci		goto bad;
16018c2ecf20Sopenharmony_ci
16028c2ecf20Sopenharmony_ci	rc = symtab_insert(s, key, levdatum);
16038c2ecf20Sopenharmony_ci	if (rc)
16048c2ecf20Sopenharmony_ci		goto bad;
16058c2ecf20Sopenharmony_ci	return 0;
16068c2ecf20Sopenharmony_cibad:
16078c2ecf20Sopenharmony_ci	sens_destroy(key, levdatum, NULL);
16088c2ecf20Sopenharmony_ci	return rc;
16098c2ecf20Sopenharmony_ci}
16108c2ecf20Sopenharmony_ci
16118c2ecf20Sopenharmony_cistatic int cat_read(struct policydb *p, struct symtab *s, void *fp)
16128c2ecf20Sopenharmony_ci{
16138c2ecf20Sopenharmony_ci	char *key = NULL;
16148c2ecf20Sopenharmony_ci	struct cat_datum *catdatum;
16158c2ecf20Sopenharmony_ci	int rc;
16168c2ecf20Sopenharmony_ci	__le32 buf[3];
16178c2ecf20Sopenharmony_ci	u32 len;
16188c2ecf20Sopenharmony_ci
16198c2ecf20Sopenharmony_ci	catdatum = kzalloc(sizeof(*catdatum), GFP_ATOMIC);
16208c2ecf20Sopenharmony_ci	if (!catdatum)
16218c2ecf20Sopenharmony_ci		return -ENOMEM;
16228c2ecf20Sopenharmony_ci
16238c2ecf20Sopenharmony_ci	rc = next_entry(buf, fp, sizeof buf);
16248c2ecf20Sopenharmony_ci	if (rc)
16258c2ecf20Sopenharmony_ci		goto bad;
16268c2ecf20Sopenharmony_ci
16278c2ecf20Sopenharmony_ci	len = le32_to_cpu(buf[0]);
16288c2ecf20Sopenharmony_ci	catdatum->value = le32_to_cpu(buf[1]);
16298c2ecf20Sopenharmony_ci	catdatum->isalias = le32_to_cpu(buf[2]);
16308c2ecf20Sopenharmony_ci
16318c2ecf20Sopenharmony_ci	rc = str_read(&key, GFP_ATOMIC, fp, len);
16328c2ecf20Sopenharmony_ci	if (rc)
16338c2ecf20Sopenharmony_ci		goto bad;
16348c2ecf20Sopenharmony_ci
16358c2ecf20Sopenharmony_ci	rc = symtab_insert(s, key, catdatum);
16368c2ecf20Sopenharmony_ci	if (rc)
16378c2ecf20Sopenharmony_ci		goto bad;
16388c2ecf20Sopenharmony_ci	return 0;
16398c2ecf20Sopenharmony_cibad:
16408c2ecf20Sopenharmony_ci	cat_destroy(key, catdatum, NULL);
16418c2ecf20Sopenharmony_ci	return rc;
16428c2ecf20Sopenharmony_ci}
16438c2ecf20Sopenharmony_ci
16448c2ecf20Sopenharmony_cistatic int (*read_f[SYM_NUM]) (struct policydb *p, struct symtab *s, void *fp) =
16458c2ecf20Sopenharmony_ci{
16468c2ecf20Sopenharmony_ci	common_read,
16478c2ecf20Sopenharmony_ci	class_read,
16488c2ecf20Sopenharmony_ci	role_read,
16498c2ecf20Sopenharmony_ci	type_read,
16508c2ecf20Sopenharmony_ci	user_read,
16518c2ecf20Sopenharmony_ci	cond_read_bool,
16528c2ecf20Sopenharmony_ci	sens_read,
16538c2ecf20Sopenharmony_ci	cat_read,
16548c2ecf20Sopenharmony_ci};
16558c2ecf20Sopenharmony_ci
16568c2ecf20Sopenharmony_cistatic int user_bounds_sanity_check(void *key, void *datum, void *datap)
16578c2ecf20Sopenharmony_ci{
16588c2ecf20Sopenharmony_ci	struct user_datum *upper, *user;
16598c2ecf20Sopenharmony_ci	struct policydb *p = datap;
16608c2ecf20Sopenharmony_ci	int depth = 0;
16618c2ecf20Sopenharmony_ci
16628c2ecf20Sopenharmony_ci	upper = user = datum;
16638c2ecf20Sopenharmony_ci	while (upper->bounds) {
16648c2ecf20Sopenharmony_ci		struct ebitmap_node *node;
16658c2ecf20Sopenharmony_ci		unsigned long bit;
16668c2ecf20Sopenharmony_ci
16678c2ecf20Sopenharmony_ci		if (++depth == POLICYDB_BOUNDS_MAXDEPTH) {
16688c2ecf20Sopenharmony_ci			pr_err("SELinux: user %s: "
16698c2ecf20Sopenharmony_ci			       "too deep or looped boundary",
16708c2ecf20Sopenharmony_ci			       (char *) key);
16718c2ecf20Sopenharmony_ci			return -EINVAL;
16728c2ecf20Sopenharmony_ci		}
16738c2ecf20Sopenharmony_ci
16748c2ecf20Sopenharmony_ci		upper = p->user_val_to_struct[upper->bounds - 1];
16758c2ecf20Sopenharmony_ci		ebitmap_for_each_positive_bit(&user->roles, node, bit) {
16768c2ecf20Sopenharmony_ci			if (ebitmap_get_bit(&upper->roles, bit))
16778c2ecf20Sopenharmony_ci				continue;
16788c2ecf20Sopenharmony_ci
16798c2ecf20Sopenharmony_ci			pr_err("SELinux: boundary violated policy: "
16808c2ecf20Sopenharmony_ci			       "user=%s role=%s bounds=%s\n",
16818c2ecf20Sopenharmony_ci			       sym_name(p, SYM_USERS, user->value - 1),
16828c2ecf20Sopenharmony_ci			       sym_name(p, SYM_ROLES, bit),
16838c2ecf20Sopenharmony_ci			       sym_name(p, SYM_USERS, upper->value - 1));
16848c2ecf20Sopenharmony_ci
16858c2ecf20Sopenharmony_ci			return -EINVAL;
16868c2ecf20Sopenharmony_ci		}
16878c2ecf20Sopenharmony_ci	}
16888c2ecf20Sopenharmony_ci
16898c2ecf20Sopenharmony_ci	return 0;
16908c2ecf20Sopenharmony_ci}
16918c2ecf20Sopenharmony_ci
16928c2ecf20Sopenharmony_cistatic int role_bounds_sanity_check(void *key, void *datum, void *datap)
16938c2ecf20Sopenharmony_ci{
16948c2ecf20Sopenharmony_ci	struct role_datum *upper, *role;
16958c2ecf20Sopenharmony_ci	struct policydb *p = datap;
16968c2ecf20Sopenharmony_ci	int depth = 0;
16978c2ecf20Sopenharmony_ci
16988c2ecf20Sopenharmony_ci	upper = role = datum;
16998c2ecf20Sopenharmony_ci	while (upper->bounds) {
17008c2ecf20Sopenharmony_ci		struct ebitmap_node *node;
17018c2ecf20Sopenharmony_ci		unsigned long bit;
17028c2ecf20Sopenharmony_ci
17038c2ecf20Sopenharmony_ci		if (++depth == POLICYDB_BOUNDS_MAXDEPTH) {
17048c2ecf20Sopenharmony_ci			pr_err("SELinux: role %s: "
17058c2ecf20Sopenharmony_ci			       "too deep or looped bounds\n",
17068c2ecf20Sopenharmony_ci			       (char *) key);
17078c2ecf20Sopenharmony_ci			return -EINVAL;
17088c2ecf20Sopenharmony_ci		}
17098c2ecf20Sopenharmony_ci
17108c2ecf20Sopenharmony_ci		upper = p->role_val_to_struct[upper->bounds - 1];
17118c2ecf20Sopenharmony_ci		ebitmap_for_each_positive_bit(&role->types, node, bit) {
17128c2ecf20Sopenharmony_ci			if (ebitmap_get_bit(&upper->types, bit))
17138c2ecf20Sopenharmony_ci				continue;
17148c2ecf20Sopenharmony_ci
17158c2ecf20Sopenharmony_ci			pr_err("SELinux: boundary violated policy: "
17168c2ecf20Sopenharmony_ci			       "role=%s type=%s bounds=%s\n",
17178c2ecf20Sopenharmony_ci			       sym_name(p, SYM_ROLES, role->value - 1),
17188c2ecf20Sopenharmony_ci			       sym_name(p, SYM_TYPES, bit),
17198c2ecf20Sopenharmony_ci			       sym_name(p, SYM_ROLES, upper->value - 1));
17208c2ecf20Sopenharmony_ci
17218c2ecf20Sopenharmony_ci			return -EINVAL;
17228c2ecf20Sopenharmony_ci		}
17238c2ecf20Sopenharmony_ci	}
17248c2ecf20Sopenharmony_ci
17258c2ecf20Sopenharmony_ci	return 0;
17268c2ecf20Sopenharmony_ci}
17278c2ecf20Sopenharmony_ci
17288c2ecf20Sopenharmony_cistatic int type_bounds_sanity_check(void *key, void *datum, void *datap)
17298c2ecf20Sopenharmony_ci{
17308c2ecf20Sopenharmony_ci	struct type_datum *upper;
17318c2ecf20Sopenharmony_ci	struct policydb *p = datap;
17328c2ecf20Sopenharmony_ci	int depth = 0;
17338c2ecf20Sopenharmony_ci
17348c2ecf20Sopenharmony_ci	upper = datum;
17358c2ecf20Sopenharmony_ci	while (upper->bounds) {
17368c2ecf20Sopenharmony_ci		if (++depth == POLICYDB_BOUNDS_MAXDEPTH) {
17378c2ecf20Sopenharmony_ci			pr_err("SELinux: type %s: "
17388c2ecf20Sopenharmony_ci			       "too deep or looped boundary\n",
17398c2ecf20Sopenharmony_ci			       (char *) key);
17408c2ecf20Sopenharmony_ci			return -EINVAL;
17418c2ecf20Sopenharmony_ci		}
17428c2ecf20Sopenharmony_ci
17438c2ecf20Sopenharmony_ci		upper = p->type_val_to_struct[upper->bounds - 1];
17448c2ecf20Sopenharmony_ci		BUG_ON(!upper);
17458c2ecf20Sopenharmony_ci
17468c2ecf20Sopenharmony_ci		if (upper->attribute) {
17478c2ecf20Sopenharmony_ci			pr_err("SELinux: type %s: "
17488c2ecf20Sopenharmony_ci			       "bounded by attribute %s",
17498c2ecf20Sopenharmony_ci			       (char *) key,
17508c2ecf20Sopenharmony_ci			       sym_name(p, SYM_TYPES, upper->value - 1));
17518c2ecf20Sopenharmony_ci			return -EINVAL;
17528c2ecf20Sopenharmony_ci		}
17538c2ecf20Sopenharmony_ci	}
17548c2ecf20Sopenharmony_ci
17558c2ecf20Sopenharmony_ci	return 0;
17568c2ecf20Sopenharmony_ci}
17578c2ecf20Sopenharmony_ci
17588c2ecf20Sopenharmony_cistatic int policydb_bounds_sanity_check(struct policydb *p)
17598c2ecf20Sopenharmony_ci{
17608c2ecf20Sopenharmony_ci	int rc;
17618c2ecf20Sopenharmony_ci
17628c2ecf20Sopenharmony_ci	if (p->policyvers < POLICYDB_VERSION_BOUNDARY)
17638c2ecf20Sopenharmony_ci		return 0;
17648c2ecf20Sopenharmony_ci
17658c2ecf20Sopenharmony_ci	rc = hashtab_map(&p->p_users.table, user_bounds_sanity_check, p);
17668c2ecf20Sopenharmony_ci	if (rc)
17678c2ecf20Sopenharmony_ci		return rc;
17688c2ecf20Sopenharmony_ci
17698c2ecf20Sopenharmony_ci	rc = hashtab_map(&p->p_roles.table, role_bounds_sanity_check, p);
17708c2ecf20Sopenharmony_ci	if (rc)
17718c2ecf20Sopenharmony_ci		return rc;
17728c2ecf20Sopenharmony_ci
17738c2ecf20Sopenharmony_ci	rc = hashtab_map(&p->p_types.table, type_bounds_sanity_check, p);
17748c2ecf20Sopenharmony_ci	if (rc)
17758c2ecf20Sopenharmony_ci		return rc;
17768c2ecf20Sopenharmony_ci
17778c2ecf20Sopenharmony_ci	return 0;
17788c2ecf20Sopenharmony_ci}
17798c2ecf20Sopenharmony_ci
17808c2ecf20Sopenharmony_ciu16 string_to_security_class(struct policydb *p, const char *name)
17818c2ecf20Sopenharmony_ci{
17828c2ecf20Sopenharmony_ci	struct class_datum *cladatum;
17838c2ecf20Sopenharmony_ci
17848c2ecf20Sopenharmony_ci	cladatum = symtab_search(&p->p_classes, name);
17858c2ecf20Sopenharmony_ci	if (!cladatum)
17868c2ecf20Sopenharmony_ci		return 0;
17878c2ecf20Sopenharmony_ci
17888c2ecf20Sopenharmony_ci	return cladatum->value;
17898c2ecf20Sopenharmony_ci}
17908c2ecf20Sopenharmony_ci
17918c2ecf20Sopenharmony_ciu32 string_to_av_perm(struct policydb *p, u16 tclass, const char *name)
17928c2ecf20Sopenharmony_ci{
17938c2ecf20Sopenharmony_ci	struct class_datum *cladatum;
17948c2ecf20Sopenharmony_ci	struct perm_datum *perdatum = NULL;
17958c2ecf20Sopenharmony_ci	struct common_datum *comdatum;
17968c2ecf20Sopenharmony_ci
17978c2ecf20Sopenharmony_ci	if (!tclass || tclass > p->p_classes.nprim)
17988c2ecf20Sopenharmony_ci		return 0;
17998c2ecf20Sopenharmony_ci
18008c2ecf20Sopenharmony_ci	cladatum = p->class_val_to_struct[tclass-1];
18018c2ecf20Sopenharmony_ci	comdatum = cladatum->comdatum;
18028c2ecf20Sopenharmony_ci	if (comdatum)
18038c2ecf20Sopenharmony_ci		perdatum = symtab_search(&comdatum->permissions, name);
18048c2ecf20Sopenharmony_ci	if (!perdatum)
18058c2ecf20Sopenharmony_ci		perdatum = symtab_search(&cladatum->permissions, name);
18068c2ecf20Sopenharmony_ci	if (!perdatum)
18078c2ecf20Sopenharmony_ci		return 0;
18088c2ecf20Sopenharmony_ci
18098c2ecf20Sopenharmony_ci	return 1U << (perdatum->value-1);
18108c2ecf20Sopenharmony_ci}
18118c2ecf20Sopenharmony_ci
18128c2ecf20Sopenharmony_cistatic int range_read(struct policydb *p, void *fp)
18138c2ecf20Sopenharmony_ci{
18148c2ecf20Sopenharmony_ci	struct range_trans *rt = NULL;
18158c2ecf20Sopenharmony_ci	struct mls_range *r = NULL;
18168c2ecf20Sopenharmony_ci	int i, rc;
18178c2ecf20Sopenharmony_ci	__le32 buf[2];
18188c2ecf20Sopenharmony_ci	u32 nel;
18198c2ecf20Sopenharmony_ci
18208c2ecf20Sopenharmony_ci	if (p->policyvers < POLICYDB_VERSION_MLS)
18218c2ecf20Sopenharmony_ci		return 0;
18228c2ecf20Sopenharmony_ci
18238c2ecf20Sopenharmony_ci	rc = next_entry(buf, fp, sizeof(u32));
18248c2ecf20Sopenharmony_ci	if (rc)
18258c2ecf20Sopenharmony_ci		return rc;
18268c2ecf20Sopenharmony_ci
18278c2ecf20Sopenharmony_ci	nel = le32_to_cpu(buf[0]);
18288c2ecf20Sopenharmony_ci
18298c2ecf20Sopenharmony_ci	rc = hashtab_init(&p->range_tr, nel);
18308c2ecf20Sopenharmony_ci	if (rc)
18318c2ecf20Sopenharmony_ci		return rc;
18328c2ecf20Sopenharmony_ci
18338c2ecf20Sopenharmony_ci	for (i = 0; i < nel; i++) {
18348c2ecf20Sopenharmony_ci		rc = -ENOMEM;
18358c2ecf20Sopenharmony_ci		rt = kzalloc(sizeof(*rt), GFP_KERNEL);
18368c2ecf20Sopenharmony_ci		if (!rt)
18378c2ecf20Sopenharmony_ci			goto out;
18388c2ecf20Sopenharmony_ci
18398c2ecf20Sopenharmony_ci		rc = next_entry(buf, fp, (sizeof(u32) * 2));
18408c2ecf20Sopenharmony_ci		if (rc)
18418c2ecf20Sopenharmony_ci			goto out;
18428c2ecf20Sopenharmony_ci
18438c2ecf20Sopenharmony_ci		rt->source_type = le32_to_cpu(buf[0]);
18448c2ecf20Sopenharmony_ci		rt->target_type = le32_to_cpu(buf[1]);
18458c2ecf20Sopenharmony_ci		if (p->policyvers >= POLICYDB_VERSION_RANGETRANS) {
18468c2ecf20Sopenharmony_ci			rc = next_entry(buf, fp, sizeof(u32));
18478c2ecf20Sopenharmony_ci			if (rc)
18488c2ecf20Sopenharmony_ci				goto out;
18498c2ecf20Sopenharmony_ci			rt->target_class = le32_to_cpu(buf[0]);
18508c2ecf20Sopenharmony_ci		} else
18518c2ecf20Sopenharmony_ci			rt->target_class = p->process_class;
18528c2ecf20Sopenharmony_ci
18538c2ecf20Sopenharmony_ci		rc = -EINVAL;
18548c2ecf20Sopenharmony_ci		if (!policydb_type_isvalid(p, rt->source_type) ||
18558c2ecf20Sopenharmony_ci		    !policydb_type_isvalid(p, rt->target_type) ||
18568c2ecf20Sopenharmony_ci		    !policydb_class_isvalid(p, rt->target_class))
18578c2ecf20Sopenharmony_ci			goto out;
18588c2ecf20Sopenharmony_ci
18598c2ecf20Sopenharmony_ci		rc = -ENOMEM;
18608c2ecf20Sopenharmony_ci		r = kzalloc(sizeof(*r), GFP_KERNEL);
18618c2ecf20Sopenharmony_ci		if (!r)
18628c2ecf20Sopenharmony_ci			goto out;
18638c2ecf20Sopenharmony_ci
18648c2ecf20Sopenharmony_ci		rc = mls_read_range_helper(r, fp);
18658c2ecf20Sopenharmony_ci		if (rc)
18668c2ecf20Sopenharmony_ci			goto out;
18678c2ecf20Sopenharmony_ci
18688c2ecf20Sopenharmony_ci		rc = -EINVAL;
18698c2ecf20Sopenharmony_ci		if (!mls_range_isvalid(p, r)) {
18708c2ecf20Sopenharmony_ci			pr_warn("SELinux:  rangetrans:  invalid range\n");
18718c2ecf20Sopenharmony_ci			goto out;
18728c2ecf20Sopenharmony_ci		}
18738c2ecf20Sopenharmony_ci
18748c2ecf20Sopenharmony_ci		rc = hashtab_insert(&p->range_tr, rt, r, rangetr_key_params);
18758c2ecf20Sopenharmony_ci		if (rc)
18768c2ecf20Sopenharmony_ci			goto out;
18778c2ecf20Sopenharmony_ci
18788c2ecf20Sopenharmony_ci		rt = NULL;
18798c2ecf20Sopenharmony_ci		r = NULL;
18808c2ecf20Sopenharmony_ci	}
18818c2ecf20Sopenharmony_ci	hash_eval(&p->range_tr, "rangetr");
18828c2ecf20Sopenharmony_ci	rc = 0;
18838c2ecf20Sopenharmony_ciout:
18848c2ecf20Sopenharmony_ci	kfree(rt);
18858c2ecf20Sopenharmony_ci	kfree(r);
18868c2ecf20Sopenharmony_ci	return rc;
18878c2ecf20Sopenharmony_ci}
18888c2ecf20Sopenharmony_ci
18898c2ecf20Sopenharmony_cistatic int filename_trans_read_helper_compat(struct policydb *p, void *fp)
18908c2ecf20Sopenharmony_ci{
18918c2ecf20Sopenharmony_ci	struct filename_trans_key key, *ft = NULL;
18928c2ecf20Sopenharmony_ci	struct filename_trans_datum *last, *datum = NULL;
18938c2ecf20Sopenharmony_ci	char *name = NULL;
18948c2ecf20Sopenharmony_ci	u32 len, stype, otype;
18958c2ecf20Sopenharmony_ci	__le32 buf[4];
18968c2ecf20Sopenharmony_ci	int rc;
18978c2ecf20Sopenharmony_ci
18988c2ecf20Sopenharmony_ci	/* length of the path component string */
18998c2ecf20Sopenharmony_ci	rc = next_entry(buf, fp, sizeof(u32));
19008c2ecf20Sopenharmony_ci	if (rc)
19018c2ecf20Sopenharmony_ci		return rc;
19028c2ecf20Sopenharmony_ci	len = le32_to_cpu(buf[0]);
19038c2ecf20Sopenharmony_ci
19048c2ecf20Sopenharmony_ci	/* path component string */
19058c2ecf20Sopenharmony_ci	rc = str_read(&name, GFP_KERNEL, fp, len);
19068c2ecf20Sopenharmony_ci	if (rc)
19078c2ecf20Sopenharmony_ci		return rc;
19088c2ecf20Sopenharmony_ci
19098c2ecf20Sopenharmony_ci	rc = next_entry(buf, fp, sizeof(u32) * 4);
19108c2ecf20Sopenharmony_ci	if (rc)
19118c2ecf20Sopenharmony_ci		goto out;
19128c2ecf20Sopenharmony_ci
19138c2ecf20Sopenharmony_ci	stype = le32_to_cpu(buf[0]);
19148c2ecf20Sopenharmony_ci	key.ttype = le32_to_cpu(buf[1]);
19158c2ecf20Sopenharmony_ci	key.tclass = le32_to_cpu(buf[2]);
19168c2ecf20Sopenharmony_ci	key.name = name;
19178c2ecf20Sopenharmony_ci
19188c2ecf20Sopenharmony_ci	otype = le32_to_cpu(buf[3]);
19198c2ecf20Sopenharmony_ci
19208c2ecf20Sopenharmony_ci	last = NULL;
19218c2ecf20Sopenharmony_ci	datum = policydb_filenametr_search(p, &key);
19228c2ecf20Sopenharmony_ci	while (datum) {
19238c2ecf20Sopenharmony_ci		if (unlikely(ebitmap_get_bit(&datum->stypes, stype - 1))) {
19248c2ecf20Sopenharmony_ci			/* conflicting/duplicate rules are ignored */
19258c2ecf20Sopenharmony_ci			datum = NULL;
19268c2ecf20Sopenharmony_ci			goto out;
19278c2ecf20Sopenharmony_ci		}
19288c2ecf20Sopenharmony_ci		if (likely(datum->otype == otype))
19298c2ecf20Sopenharmony_ci			break;
19308c2ecf20Sopenharmony_ci		last = datum;
19318c2ecf20Sopenharmony_ci		datum = datum->next;
19328c2ecf20Sopenharmony_ci	}
19338c2ecf20Sopenharmony_ci	if (!datum) {
19348c2ecf20Sopenharmony_ci		rc = -ENOMEM;
19358c2ecf20Sopenharmony_ci		datum = kmalloc(sizeof(*datum), GFP_KERNEL);
19368c2ecf20Sopenharmony_ci		if (!datum)
19378c2ecf20Sopenharmony_ci			goto out;
19388c2ecf20Sopenharmony_ci
19398c2ecf20Sopenharmony_ci		ebitmap_init(&datum->stypes);
19408c2ecf20Sopenharmony_ci		datum->otype = otype;
19418c2ecf20Sopenharmony_ci		datum->next = NULL;
19428c2ecf20Sopenharmony_ci
19438c2ecf20Sopenharmony_ci		if (unlikely(last)) {
19448c2ecf20Sopenharmony_ci			last->next = datum;
19458c2ecf20Sopenharmony_ci		} else {
19468c2ecf20Sopenharmony_ci			rc = -ENOMEM;
19478c2ecf20Sopenharmony_ci			ft = kmemdup(&key, sizeof(key), GFP_KERNEL);
19488c2ecf20Sopenharmony_ci			if (!ft)
19498c2ecf20Sopenharmony_ci				goto out;
19508c2ecf20Sopenharmony_ci
19518c2ecf20Sopenharmony_ci			rc = hashtab_insert(&p->filename_trans, ft, datum,
19528c2ecf20Sopenharmony_ci					    filenametr_key_params);
19538c2ecf20Sopenharmony_ci			if (rc)
19548c2ecf20Sopenharmony_ci				goto out;
19558c2ecf20Sopenharmony_ci			name = NULL;
19568c2ecf20Sopenharmony_ci
19578c2ecf20Sopenharmony_ci			rc = ebitmap_set_bit(&p->filename_trans_ttypes,
19588c2ecf20Sopenharmony_ci					     key.ttype, 1);
19598c2ecf20Sopenharmony_ci			if (rc)
19608c2ecf20Sopenharmony_ci				return rc;
19618c2ecf20Sopenharmony_ci		}
19628c2ecf20Sopenharmony_ci	}
19638c2ecf20Sopenharmony_ci	kfree(name);
19648c2ecf20Sopenharmony_ci	return ebitmap_set_bit(&datum->stypes, stype - 1, 1);
19658c2ecf20Sopenharmony_ci
19668c2ecf20Sopenharmony_ciout:
19678c2ecf20Sopenharmony_ci	kfree(ft);
19688c2ecf20Sopenharmony_ci	kfree(name);
19698c2ecf20Sopenharmony_ci	kfree(datum);
19708c2ecf20Sopenharmony_ci	return rc;
19718c2ecf20Sopenharmony_ci}
19728c2ecf20Sopenharmony_ci
19738c2ecf20Sopenharmony_cistatic int filename_trans_read_helper(struct policydb *p, void *fp)
19748c2ecf20Sopenharmony_ci{
19758c2ecf20Sopenharmony_ci	struct filename_trans_key *ft = NULL;
19768c2ecf20Sopenharmony_ci	struct filename_trans_datum **dst, *datum, *first = NULL;
19778c2ecf20Sopenharmony_ci	char *name = NULL;
19788c2ecf20Sopenharmony_ci	u32 len, ttype, tclass, ndatum, i;
19798c2ecf20Sopenharmony_ci	__le32 buf[3];
19808c2ecf20Sopenharmony_ci	int rc;
19818c2ecf20Sopenharmony_ci
19828c2ecf20Sopenharmony_ci	/* length of the path component string */
19838c2ecf20Sopenharmony_ci	rc = next_entry(buf, fp, sizeof(u32));
19848c2ecf20Sopenharmony_ci	if (rc)
19858c2ecf20Sopenharmony_ci		return rc;
19868c2ecf20Sopenharmony_ci	len = le32_to_cpu(buf[0]);
19878c2ecf20Sopenharmony_ci
19888c2ecf20Sopenharmony_ci	/* path component string */
19898c2ecf20Sopenharmony_ci	rc = str_read(&name, GFP_KERNEL, fp, len);
19908c2ecf20Sopenharmony_ci	if (rc)
19918c2ecf20Sopenharmony_ci		return rc;
19928c2ecf20Sopenharmony_ci
19938c2ecf20Sopenharmony_ci	rc = next_entry(buf, fp, sizeof(u32) * 3);
19948c2ecf20Sopenharmony_ci	if (rc)
19958c2ecf20Sopenharmony_ci		goto out;
19968c2ecf20Sopenharmony_ci
19978c2ecf20Sopenharmony_ci	ttype = le32_to_cpu(buf[0]);
19988c2ecf20Sopenharmony_ci	tclass = le32_to_cpu(buf[1]);
19998c2ecf20Sopenharmony_ci
20008c2ecf20Sopenharmony_ci	ndatum = le32_to_cpu(buf[2]);
20018c2ecf20Sopenharmony_ci	if (ndatum == 0) {
20028c2ecf20Sopenharmony_ci		pr_err("SELinux:  Filename transition key with no datum\n");
20038c2ecf20Sopenharmony_ci		rc = -ENOENT;
20048c2ecf20Sopenharmony_ci		goto out;
20058c2ecf20Sopenharmony_ci	}
20068c2ecf20Sopenharmony_ci
20078c2ecf20Sopenharmony_ci	dst = &first;
20088c2ecf20Sopenharmony_ci	for (i = 0; i < ndatum; i++) {
20098c2ecf20Sopenharmony_ci		rc = -ENOMEM;
20108c2ecf20Sopenharmony_ci		datum = kmalloc(sizeof(*datum), GFP_KERNEL);
20118c2ecf20Sopenharmony_ci		if (!datum)
20128c2ecf20Sopenharmony_ci			goto out;
20138c2ecf20Sopenharmony_ci
20148c2ecf20Sopenharmony_ci		datum->next = NULL;
20158c2ecf20Sopenharmony_ci		*dst = datum;
20168c2ecf20Sopenharmony_ci
20178c2ecf20Sopenharmony_ci		/* ebitmap_read() will at least init the bitmap */
20188c2ecf20Sopenharmony_ci		rc = ebitmap_read(&datum->stypes, fp);
20198c2ecf20Sopenharmony_ci		if (rc)
20208c2ecf20Sopenharmony_ci			goto out;
20218c2ecf20Sopenharmony_ci
20228c2ecf20Sopenharmony_ci		rc = next_entry(buf, fp, sizeof(u32));
20238c2ecf20Sopenharmony_ci		if (rc)
20248c2ecf20Sopenharmony_ci			goto out;
20258c2ecf20Sopenharmony_ci
20268c2ecf20Sopenharmony_ci		datum->otype = le32_to_cpu(buf[0]);
20278c2ecf20Sopenharmony_ci
20288c2ecf20Sopenharmony_ci		dst = &datum->next;
20298c2ecf20Sopenharmony_ci	}
20308c2ecf20Sopenharmony_ci
20318c2ecf20Sopenharmony_ci	rc = -ENOMEM;
20328c2ecf20Sopenharmony_ci	ft = kmalloc(sizeof(*ft), GFP_KERNEL);
20338c2ecf20Sopenharmony_ci	if (!ft)
20348c2ecf20Sopenharmony_ci		goto out;
20358c2ecf20Sopenharmony_ci
20368c2ecf20Sopenharmony_ci	ft->ttype = ttype;
20378c2ecf20Sopenharmony_ci	ft->tclass = tclass;
20388c2ecf20Sopenharmony_ci	ft->name = name;
20398c2ecf20Sopenharmony_ci
20408c2ecf20Sopenharmony_ci	rc = hashtab_insert(&p->filename_trans, ft, first,
20418c2ecf20Sopenharmony_ci			    filenametr_key_params);
20428c2ecf20Sopenharmony_ci	if (rc == -EEXIST)
20438c2ecf20Sopenharmony_ci		pr_err("SELinux:  Duplicate filename transition key\n");
20448c2ecf20Sopenharmony_ci	if (rc)
20458c2ecf20Sopenharmony_ci		goto out;
20468c2ecf20Sopenharmony_ci
20478c2ecf20Sopenharmony_ci	return ebitmap_set_bit(&p->filename_trans_ttypes, ttype, 1);
20488c2ecf20Sopenharmony_ci
20498c2ecf20Sopenharmony_ciout:
20508c2ecf20Sopenharmony_ci	kfree(ft);
20518c2ecf20Sopenharmony_ci	kfree(name);
20528c2ecf20Sopenharmony_ci	while (first) {
20538c2ecf20Sopenharmony_ci		datum = first;
20548c2ecf20Sopenharmony_ci		first = first->next;
20558c2ecf20Sopenharmony_ci
20568c2ecf20Sopenharmony_ci		ebitmap_destroy(&datum->stypes);
20578c2ecf20Sopenharmony_ci		kfree(datum);
20588c2ecf20Sopenharmony_ci	}
20598c2ecf20Sopenharmony_ci	return rc;
20608c2ecf20Sopenharmony_ci}
20618c2ecf20Sopenharmony_ci
20628c2ecf20Sopenharmony_cistatic int filename_trans_read(struct policydb *p, void *fp)
20638c2ecf20Sopenharmony_ci{
20648c2ecf20Sopenharmony_ci	u32 nel;
20658c2ecf20Sopenharmony_ci	__le32 buf[1];
20668c2ecf20Sopenharmony_ci	int rc, i;
20678c2ecf20Sopenharmony_ci
20688c2ecf20Sopenharmony_ci	if (p->policyvers < POLICYDB_VERSION_FILENAME_TRANS)
20698c2ecf20Sopenharmony_ci		return 0;
20708c2ecf20Sopenharmony_ci
20718c2ecf20Sopenharmony_ci	rc = next_entry(buf, fp, sizeof(u32));
20728c2ecf20Sopenharmony_ci	if (rc)
20738c2ecf20Sopenharmony_ci		return rc;
20748c2ecf20Sopenharmony_ci	nel = le32_to_cpu(buf[0]);
20758c2ecf20Sopenharmony_ci
20768c2ecf20Sopenharmony_ci	if (p->policyvers < POLICYDB_VERSION_COMP_FTRANS) {
20778c2ecf20Sopenharmony_ci		p->compat_filename_trans_count = nel;
20788c2ecf20Sopenharmony_ci
20798c2ecf20Sopenharmony_ci		rc = hashtab_init(&p->filename_trans, (1 << 11));
20808c2ecf20Sopenharmony_ci		if (rc)
20818c2ecf20Sopenharmony_ci			return rc;
20828c2ecf20Sopenharmony_ci
20838c2ecf20Sopenharmony_ci		for (i = 0; i < nel; i++) {
20848c2ecf20Sopenharmony_ci			rc = filename_trans_read_helper_compat(p, fp);
20858c2ecf20Sopenharmony_ci			if (rc)
20868c2ecf20Sopenharmony_ci				return rc;
20878c2ecf20Sopenharmony_ci		}
20888c2ecf20Sopenharmony_ci	} else {
20898c2ecf20Sopenharmony_ci		rc = hashtab_init(&p->filename_trans, nel);
20908c2ecf20Sopenharmony_ci		if (rc)
20918c2ecf20Sopenharmony_ci			return rc;
20928c2ecf20Sopenharmony_ci
20938c2ecf20Sopenharmony_ci		for (i = 0; i < nel; i++) {
20948c2ecf20Sopenharmony_ci			rc = filename_trans_read_helper(p, fp);
20958c2ecf20Sopenharmony_ci			if (rc)
20968c2ecf20Sopenharmony_ci				return rc;
20978c2ecf20Sopenharmony_ci		}
20988c2ecf20Sopenharmony_ci	}
20998c2ecf20Sopenharmony_ci	hash_eval(&p->filename_trans, "filenametr");
21008c2ecf20Sopenharmony_ci	return 0;
21018c2ecf20Sopenharmony_ci}
21028c2ecf20Sopenharmony_ci
21038c2ecf20Sopenharmony_cistatic int genfs_read(struct policydb *p, void *fp)
21048c2ecf20Sopenharmony_ci{
21058c2ecf20Sopenharmony_ci	int i, j, rc;
21068c2ecf20Sopenharmony_ci	u32 nel, nel2, len, len2;
21078c2ecf20Sopenharmony_ci	__le32 buf[1];
21088c2ecf20Sopenharmony_ci	struct ocontext *l, *c;
21098c2ecf20Sopenharmony_ci	struct ocontext *newc = NULL;
21108c2ecf20Sopenharmony_ci	struct genfs *genfs_p, *genfs;
21118c2ecf20Sopenharmony_ci	struct genfs *newgenfs = NULL;
21128c2ecf20Sopenharmony_ci
21138c2ecf20Sopenharmony_ci	rc = next_entry(buf, fp, sizeof(u32));
21148c2ecf20Sopenharmony_ci	if (rc)
21158c2ecf20Sopenharmony_ci		return rc;
21168c2ecf20Sopenharmony_ci	nel = le32_to_cpu(buf[0]);
21178c2ecf20Sopenharmony_ci
21188c2ecf20Sopenharmony_ci	for (i = 0; i < nel; i++) {
21198c2ecf20Sopenharmony_ci		rc = next_entry(buf, fp, sizeof(u32));
21208c2ecf20Sopenharmony_ci		if (rc)
21218c2ecf20Sopenharmony_ci			goto out;
21228c2ecf20Sopenharmony_ci		len = le32_to_cpu(buf[0]);
21238c2ecf20Sopenharmony_ci
21248c2ecf20Sopenharmony_ci		rc = -ENOMEM;
21258c2ecf20Sopenharmony_ci		newgenfs = kzalloc(sizeof(*newgenfs), GFP_KERNEL);
21268c2ecf20Sopenharmony_ci		if (!newgenfs)
21278c2ecf20Sopenharmony_ci			goto out;
21288c2ecf20Sopenharmony_ci
21298c2ecf20Sopenharmony_ci		rc = str_read(&newgenfs->fstype, GFP_KERNEL, fp, len);
21308c2ecf20Sopenharmony_ci		if (rc)
21318c2ecf20Sopenharmony_ci			goto out;
21328c2ecf20Sopenharmony_ci
21338c2ecf20Sopenharmony_ci		for (genfs_p = NULL, genfs = p->genfs; genfs;
21348c2ecf20Sopenharmony_ci		     genfs_p = genfs, genfs = genfs->next) {
21358c2ecf20Sopenharmony_ci			rc = -EINVAL;
21368c2ecf20Sopenharmony_ci			if (strcmp(newgenfs->fstype, genfs->fstype) == 0) {
21378c2ecf20Sopenharmony_ci				pr_err("SELinux:  dup genfs fstype %s\n",
21388c2ecf20Sopenharmony_ci				       newgenfs->fstype);
21398c2ecf20Sopenharmony_ci				goto out;
21408c2ecf20Sopenharmony_ci			}
21418c2ecf20Sopenharmony_ci			if (strcmp(newgenfs->fstype, genfs->fstype) < 0)
21428c2ecf20Sopenharmony_ci				break;
21438c2ecf20Sopenharmony_ci		}
21448c2ecf20Sopenharmony_ci		newgenfs->next = genfs;
21458c2ecf20Sopenharmony_ci		if (genfs_p)
21468c2ecf20Sopenharmony_ci			genfs_p->next = newgenfs;
21478c2ecf20Sopenharmony_ci		else
21488c2ecf20Sopenharmony_ci			p->genfs = newgenfs;
21498c2ecf20Sopenharmony_ci		genfs = newgenfs;
21508c2ecf20Sopenharmony_ci		newgenfs = NULL;
21518c2ecf20Sopenharmony_ci
21528c2ecf20Sopenharmony_ci		rc = next_entry(buf, fp, sizeof(u32));
21538c2ecf20Sopenharmony_ci		if (rc)
21548c2ecf20Sopenharmony_ci			goto out;
21558c2ecf20Sopenharmony_ci
21568c2ecf20Sopenharmony_ci		nel2 = le32_to_cpu(buf[0]);
21578c2ecf20Sopenharmony_ci		for (j = 0; j < nel2; j++) {
21588c2ecf20Sopenharmony_ci			rc = next_entry(buf, fp, sizeof(u32));
21598c2ecf20Sopenharmony_ci			if (rc)
21608c2ecf20Sopenharmony_ci				goto out;
21618c2ecf20Sopenharmony_ci			len = le32_to_cpu(buf[0]);
21628c2ecf20Sopenharmony_ci
21638c2ecf20Sopenharmony_ci			rc = -ENOMEM;
21648c2ecf20Sopenharmony_ci			newc = kzalloc(sizeof(*newc), GFP_KERNEL);
21658c2ecf20Sopenharmony_ci			if (!newc)
21668c2ecf20Sopenharmony_ci				goto out;
21678c2ecf20Sopenharmony_ci
21688c2ecf20Sopenharmony_ci			rc = str_read(&newc->u.name, GFP_KERNEL, fp, len);
21698c2ecf20Sopenharmony_ci			if (rc)
21708c2ecf20Sopenharmony_ci				goto out;
21718c2ecf20Sopenharmony_ci
21728c2ecf20Sopenharmony_ci			rc = next_entry(buf, fp, sizeof(u32));
21738c2ecf20Sopenharmony_ci			if (rc)
21748c2ecf20Sopenharmony_ci				goto out;
21758c2ecf20Sopenharmony_ci
21768c2ecf20Sopenharmony_ci			newc->v.sclass = le32_to_cpu(buf[0]);
21778c2ecf20Sopenharmony_ci			rc = context_read_and_validate(&newc->context[0], p, fp);
21788c2ecf20Sopenharmony_ci			if (rc)
21798c2ecf20Sopenharmony_ci				goto out;
21808c2ecf20Sopenharmony_ci
21818c2ecf20Sopenharmony_ci			for (l = NULL, c = genfs->head; c;
21828c2ecf20Sopenharmony_ci			     l = c, c = c->next) {
21838c2ecf20Sopenharmony_ci				rc = -EINVAL;
21848c2ecf20Sopenharmony_ci				if (!strcmp(newc->u.name, c->u.name) &&
21858c2ecf20Sopenharmony_ci				    (!c->v.sclass || !newc->v.sclass ||
21868c2ecf20Sopenharmony_ci				     newc->v.sclass == c->v.sclass)) {
21878c2ecf20Sopenharmony_ci					pr_err("SELinux:  dup genfs entry (%s,%s)\n",
21888c2ecf20Sopenharmony_ci					       genfs->fstype, c->u.name);
21898c2ecf20Sopenharmony_ci					goto out;
21908c2ecf20Sopenharmony_ci				}
21918c2ecf20Sopenharmony_ci				len = strlen(newc->u.name);
21928c2ecf20Sopenharmony_ci				len2 = strlen(c->u.name);
21938c2ecf20Sopenharmony_ci				if (len > len2)
21948c2ecf20Sopenharmony_ci					break;
21958c2ecf20Sopenharmony_ci			}
21968c2ecf20Sopenharmony_ci
21978c2ecf20Sopenharmony_ci			newc->next = c;
21988c2ecf20Sopenharmony_ci			if (l)
21998c2ecf20Sopenharmony_ci				l->next = newc;
22008c2ecf20Sopenharmony_ci			else
22018c2ecf20Sopenharmony_ci				genfs->head = newc;
22028c2ecf20Sopenharmony_ci			newc = NULL;
22038c2ecf20Sopenharmony_ci		}
22048c2ecf20Sopenharmony_ci	}
22058c2ecf20Sopenharmony_ci	rc = 0;
22068c2ecf20Sopenharmony_ciout:
22078c2ecf20Sopenharmony_ci	if (newgenfs) {
22088c2ecf20Sopenharmony_ci		kfree(newgenfs->fstype);
22098c2ecf20Sopenharmony_ci		kfree(newgenfs);
22108c2ecf20Sopenharmony_ci	}
22118c2ecf20Sopenharmony_ci	ocontext_destroy(newc, OCON_FSUSE);
22128c2ecf20Sopenharmony_ci
22138c2ecf20Sopenharmony_ci	return rc;
22148c2ecf20Sopenharmony_ci}
22158c2ecf20Sopenharmony_ci
22168c2ecf20Sopenharmony_cistatic int ocontext_read(struct policydb *p, struct policydb_compat_info *info,
22178c2ecf20Sopenharmony_ci			 void *fp)
22188c2ecf20Sopenharmony_ci{
22198c2ecf20Sopenharmony_ci	int i, j, rc;
22208c2ecf20Sopenharmony_ci	u32 nel, len;
22218c2ecf20Sopenharmony_ci	__be64 prefixbuf[1];
22228c2ecf20Sopenharmony_ci	__le32 buf[3];
22238c2ecf20Sopenharmony_ci	struct ocontext *l, *c;
22248c2ecf20Sopenharmony_ci	u32 nodebuf[8];
22258c2ecf20Sopenharmony_ci
22268c2ecf20Sopenharmony_ci	for (i = 0; i < info->ocon_num; i++) {
22278c2ecf20Sopenharmony_ci		rc = next_entry(buf, fp, sizeof(u32));
22288c2ecf20Sopenharmony_ci		if (rc)
22298c2ecf20Sopenharmony_ci			goto out;
22308c2ecf20Sopenharmony_ci		nel = le32_to_cpu(buf[0]);
22318c2ecf20Sopenharmony_ci
22328c2ecf20Sopenharmony_ci		l = NULL;
22338c2ecf20Sopenharmony_ci		for (j = 0; j < nel; j++) {
22348c2ecf20Sopenharmony_ci			rc = -ENOMEM;
22358c2ecf20Sopenharmony_ci			c = kzalloc(sizeof(*c), GFP_KERNEL);
22368c2ecf20Sopenharmony_ci			if (!c)
22378c2ecf20Sopenharmony_ci				goto out;
22388c2ecf20Sopenharmony_ci			if (l)
22398c2ecf20Sopenharmony_ci				l->next = c;
22408c2ecf20Sopenharmony_ci			else
22418c2ecf20Sopenharmony_ci				p->ocontexts[i] = c;
22428c2ecf20Sopenharmony_ci			l = c;
22438c2ecf20Sopenharmony_ci
22448c2ecf20Sopenharmony_ci			switch (i) {
22458c2ecf20Sopenharmony_ci			case OCON_ISID:
22468c2ecf20Sopenharmony_ci				rc = next_entry(buf, fp, sizeof(u32));
22478c2ecf20Sopenharmony_ci				if (rc)
22488c2ecf20Sopenharmony_ci					goto out;
22498c2ecf20Sopenharmony_ci
22508c2ecf20Sopenharmony_ci				c->sid[0] = le32_to_cpu(buf[0]);
22518c2ecf20Sopenharmony_ci				rc = context_read_and_validate(&c->context[0], p, fp);
22528c2ecf20Sopenharmony_ci				if (rc)
22538c2ecf20Sopenharmony_ci					goto out;
22548c2ecf20Sopenharmony_ci				break;
22558c2ecf20Sopenharmony_ci			case OCON_FS:
22568c2ecf20Sopenharmony_ci			case OCON_NETIF:
22578c2ecf20Sopenharmony_ci				rc = next_entry(buf, fp, sizeof(u32));
22588c2ecf20Sopenharmony_ci				if (rc)
22598c2ecf20Sopenharmony_ci					goto out;
22608c2ecf20Sopenharmony_ci				len = le32_to_cpu(buf[0]);
22618c2ecf20Sopenharmony_ci
22628c2ecf20Sopenharmony_ci				rc = str_read(&c->u.name, GFP_KERNEL, fp, len);
22638c2ecf20Sopenharmony_ci				if (rc)
22648c2ecf20Sopenharmony_ci					goto out;
22658c2ecf20Sopenharmony_ci
22668c2ecf20Sopenharmony_ci				rc = context_read_and_validate(&c->context[0], p, fp);
22678c2ecf20Sopenharmony_ci				if (rc)
22688c2ecf20Sopenharmony_ci					goto out;
22698c2ecf20Sopenharmony_ci				rc = context_read_and_validate(&c->context[1], p, fp);
22708c2ecf20Sopenharmony_ci				if (rc)
22718c2ecf20Sopenharmony_ci					goto out;
22728c2ecf20Sopenharmony_ci				break;
22738c2ecf20Sopenharmony_ci			case OCON_PORT:
22748c2ecf20Sopenharmony_ci				rc = next_entry(buf, fp, sizeof(u32)*3);
22758c2ecf20Sopenharmony_ci				if (rc)
22768c2ecf20Sopenharmony_ci					goto out;
22778c2ecf20Sopenharmony_ci				c->u.port.protocol = le32_to_cpu(buf[0]);
22788c2ecf20Sopenharmony_ci				c->u.port.low_port = le32_to_cpu(buf[1]);
22798c2ecf20Sopenharmony_ci				c->u.port.high_port = le32_to_cpu(buf[2]);
22808c2ecf20Sopenharmony_ci				rc = context_read_and_validate(&c->context[0], p, fp);
22818c2ecf20Sopenharmony_ci				if (rc)
22828c2ecf20Sopenharmony_ci					goto out;
22838c2ecf20Sopenharmony_ci				break;
22848c2ecf20Sopenharmony_ci			case OCON_NODE:
22858c2ecf20Sopenharmony_ci				rc = next_entry(nodebuf, fp, sizeof(u32) * 2);
22868c2ecf20Sopenharmony_ci				if (rc)
22878c2ecf20Sopenharmony_ci					goto out;
22888c2ecf20Sopenharmony_ci				c->u.node.addr = nodebuf[0]; /* network order */
22898c2ecf20Sopenharmony_ci				c->u.node.mask = nodebuf[1]; /* network order */
22908c2ecf20Sopenharmony_ci				rc = context_read_and_validate(&c->context[0], p, fp);
22918c2ecf20Sopenharmony_ci				if (rc)
22928c2ecf20Sopenharmony_ci					goto out;
22938c2ecf20Sopenharmony_ci				break;
22948c2ecf20Sopenharmony_ci			case OCON_FSUSE:
22958c2ecf20Sopenharmony_ci				rc = next_entry(buf, fp, sizeof(u32)*2);
22968c2ecf20Sopenharmony_ci				if (rc)
22978c2ecf20Sopenharmony_ci					goto out;
22988c2ecf20Sopenharmony_ci
22998c2ecf20Sopenharmony_ci				rc = -EINVAL;
23008c2ecf20Sopenharmony_ci				c->v.behavior = le32_to_cpu(buf[0]);
23018c2ecf20Sopenharmony_ci				/* Determined at runtime, not in policy DB. */
23028c2ecf20Sopenharmony_ci				if (c->v.behavior == SECURITY_FS_USE_MNTPOINT)
23038c2ecf20Sopenharmony_ci					goto out;
23048c2ecf20Sopenharmony_ci				if (c->v.behavior > SECURITY_FS_USE_MAX)
23058c2ecf20Sopenharmony_ci					goto out;
23068c2ecf20Sopenharmony_ci
23078c2ecf20Sopenharmony_ci				len = le32_to_cpu(buf[1]);
23088c2ecf20Sopenharmony_ci				rc = str_read(&c->u.name, GFP_KERNEL, fp, len);
23098c2ecf20Sopenharmony_ci				if (rc)
23108c2ecf20Sopenharmony_ci					goto out;
23118c2ecf20Sopenharmony_ci
23128c2ecf20Sopenharmony_ci				rc = context_read_and_validate(&c->context[0], p, fp);
23138c2ecf20Sopenharmony_ci				if (rc)
23148c2ecf20Sopenharmony_ci					goto out;
23158c2ecf20Sopenharmony_ci				break;
23168c2ecf20Sopenharmony_ci			case OCON_NODE6: {
23178c2ecf20Sopenharmony_ci				int k;
23188c2ecf20Sopenharmony_ci
23198c2ecf20Sopenharmony_ci				rc = next_entry(nodebuf, fp, sizeof(u32) * 8);
23208c2ecf20Sopenharmony_ci				if (rc)
23218c2ecf20Sopenharmony_ci					goto out;
23228c2ecf20Sopenharmony_ci				for (k = 0; k < 4; k++)
23238c2ecf20Sopenharmony_ci					c->u.node6.addr[k] = nodebuf[k];
23248c2ecf20Sopenharmony_ci				for (k = 0; k < 4; k++)
23258c2ecf20Sopenharmony_ci					c->u.node6.mask[k] = nodebuf[k+4];
23268c2ecf20Sopenharmony_ci				rc = context_read_and_validate(&c->context[0], p, fp);
23278c2ecf20Sopenharmony_ci				if (rc)
23288c2ecf20Sopenharmony_ci					goto out;
23298c2ecf20Sopenharmony_ci				break;
23308c2ecf20Sopenharmony_ci			}
23318c2ecf20Sopenharmony_ci			case OCON_IBPKEY: {
23328c2ecf20Sopenharmony_ci				u32 pkey_lo, pkey_hi;
23338c2ecf20Sopenharmony_ci
23348c2ecf20Sopenharmony_ci				rc = next_entry(prefixbuf, fp, sizeof(u64));
23358c2ecf20Sopenharmony_ci				if (rc)
23368c2ecf20Sopenharmony_ci					goto out;
23378c2ecf20Sopenharmony_ci
23388c2ecf20Sopenharmony_ci				/* we need to have subnet_prefix in CPU order */
23398c2ecf20Sopenharmony_ci				c->u.ibpkey.subnet_prefix = be64_to_cpu(prefixbuf[0]);
23408c2ecf20Sopenharmony_ci
23418c2ecf20Sopenharmony_ci				rc = next_entry(buf, fp, sizeof(u32) * 2);
23428c2ecf20Sopenharmony_ci				if (rc)
23438c2ecf20Sopenharmony_ci					goto out;
23448c2ecf20Sopenharmony_ci
23458c2ecf20Sopenharmony_ci				pkey_lo = le32_to_cpu(buf[0]);
23468c2ecf20Sopenharmony_ci				pkey_hi = le32_to_cpu(buf[1]);
23478c2ecf20Sopenharmony_ci
23488c2ecf20Sopenharmony_ci				if (pkey_lo > U16_MAX || pkey_hi > U16_MAX) {
23498c2ecf20Sopenharmony_ci					rc = -EINVAL;
23508c2ecf20Sopenharmony_ci					goto out;
23518c2ecf20Sopenharmony_ci				}
23528c2ecf20Sopenharmony_ci
23538c2ecf20Sopenharmony_ci				c->u.ibpkey.low_pkey  = pkey_lo;
23548c2ecf20Sopenharmony_ci				c->u.ibpkey.high_pkey = pkey_hi;
23558c2ecf20Sopenharmony_ci
23568c2ecf20Sopenharmony_ci				rc = context_read_and_validate(&c->context[0],
23578c2ecf20Sopenharmony_ci							       p,
23588c2ecf20Sopenharmony_ci							       fp);
23598c2ecf20Sopenharmony_ci				if (rc)
23608c2ecf20Sopenharmony_ci					goto out;
23618c2ecf20Sopenharmony_ci				break;
23628c2ecf20Sopenharmony_ci			}
23638c2ecf20Sopenharmony_ci			case OCON_IBENDPORT: {
23648c2ecf20Sopenharmony_ci				u32 port;
23658c2ecf20Sopenharmony_ci
23668c2ecf20Sopenharmony_ci				rc = next_entry(buf, fp, sizeof(u32) * 2);
23678c2ecf20Sopenharmony_ci				if (rc)
23688c2ecf20Sopenharmony_ci					goto out;
23698c2ecf20Sopenharmony_ci				len = le32_to_cpu(buf[0]);
23708c2ecf20Sopenharmony_ci
23718c2ecf20Sopenharmony_ci				rc = str_read(&c->u.ibendport.dev_name, GFP_KERNEL, fp, len);
23728c2ecf20Sopenharmony_ci				if (rc)
23738c2ecf20Sopenharmony_ci					goto out;
23748c2ecf20Sopenharmony_ci
23758c2ecf20Sopenharmony_ci				port = le32_to_cpu(buf[1]);
23768c2ecf20Sopenharmony_ci				if (port > U8_MAX || port == 0) {
23778c2ecf20Sopenharmony_ci					rc = -EINVAL;
23788c2ecf20Sopenharmony_ci					goto out;
23798c2ecf20Sopenharmony_ci				}
23808c2ecf20Sopenharmony_ci
23818c2ecf20Sopenharmony_ci				c->u.ibendport.port = port;
23828c2ecf20Sopenharmony_ci
23838c2ecf20Sopenharmony_ci				rc = context_read_and_validate(&c->context[0],
23848c2ecf20Sopenharmony_ci							       p,
23858c2ecf20Sopenharmony_ci							       fp);
23868c2ecf20Sopenharmony_ci				if (rc)
23878c2ecf20Sopenharmony_ci					goto out;
23888c2ecf20Sopenharmony_ci				break;
23898c2ecf20Sopenharmony_ci			} /* end case */
23908c2ecf20Sopenharmony_ci			} /* end switch */
23918c2ecf20Sopenharmony_ci		}
23928c2ecf20Sopenharmony_ci	}
23938c2ecf20Sopenharmony_ci	rc = 0;
23948c2ecf20Sopenharmony_ciout:
23958c2ecf20Sopenharmony_ci	return rc;
23968c2ecf20Sopenharmony_ci}
23978c2ecf20Sopenharmony_ci
23988c2ecf20Sopenharmony_ci/*
23998c2ecf20Sopenharmony_ci * Read the configuration data from a policy database binary
24008c2ecf20Sopenharmony_ci * representation file into a policy database structure.
24018c2ecf20Sopenharmony_ci */
24028c2ecf20Sopenharmony_ciint policydb_read(struct policydb *p, void *fp)
24038c2ecf20Sopenharmony_ci{
24048c2ecf20Sopenharmony_ci	struct role_allow *ra, *lra;
24058c2ecf20Sopenharmony_ci	struct role_trans_key *rtk = NULL;
24068c2ecf20Sopenharmony_ci	struct role_trans_datum *rtd = NULL;
24078c2ecf20Sopenharmony_ci	int i, j, rc;
24088c2ecf20Sopenharmony_ci	__le32 buf[4];
24098c2ecf20Sopenharmony_ci	u32 len, nprim, nel, perm;
24108c2ecf20Sopenharmony_ci
24118c2ecf20Sopenharmony_ci	char *policydb_str;
24128c2ecf20Sopenharmony_ci	struct policydb_compat_info *info;
24138c2ecf20Sopenharmony_ci
24148c2ecf20Sopenharmony_ci	policydb_init(p);
24158c2ecf20Sopenharmony_ci
24168c2ecf20Sopenharmony_ci	/* Read the magic number and string length. */
24178c2ecf20Sopenharmony_ci	rc = next_entry(buf, fp, sizeof(u32) * 2);
24188c2ecf20Sopenharmony_ci	if (rc)
24198c2ecf20Sopenharmony_ci		goto bad;
24208c2ecf20Sopenharmony_ci
24218c2ecf20Sopenharmony_ci	rc = -EINVAL;
24228c2ecf20Sopenharmony_ci	if (le32_to_cpu(buf[0]) != POLICYDB_MAGIC) {
24238c2ecf20Sopenharmony_ci		pr_err("SELinux:  policydb magic number 0x%x does "
24248c2ecf20Sopenharmony_ci		       "not match expected magic number 0x%x\n",
24258c2ecf20Sopenharmony_ci		       le32_to_cpu(buf[0]), POLICYDB_MAGIC);
24268c2ecf20Sopenharmony_ci		goto bad;
24278c2ecf20Sopenharmony_ci	}
24288c2ecf20Sopenharmony_ci
24298c2ecf20Sopenharmony_ci	rc = -EINVAL;
24308c2ecf20Sopenharmony_ci	len = le32_to_cpu(buf[1]);
24318c2ecf20Sopenharmony_ci	if (len != strlen(POLICYDB_STRING)) {
24328c2ecf20Sopenharmony_ci		pr_err("SELinux:  policydb string length %d does not "
24338c2ecf20Sopenharmony_ci		       "match expected length %zu\n",
24348c2ecf20Sopenharmony_ci		       len, strlen(POLICYDB_STRING));
24358c2ecf20Sopenharmony_ci		goto bad;
24368c2ecf20Sopenharmony_ci	}
24378c2ecf20Sopenharmony_ci
24388c2ecf20Sopenharmony_ci	rc = -ENOMEM;
24398c2ecf20Sopenharmony_ci	policydb_str = kmalloc(len + 1, GFP_KERNEL);
24408c2ecf20Sopenharmony_ci	if (!policydb_str) {
24418c2ecf20Sopenharmony_ci		pr_err("SELinux:  unable to allocate memory for policydb "
24428c2ecf20Sopenharmony_ci		       "string of length %d\n", len);
24438c2ecf20Sopenharmony_ci		goto bad;
24448c2ecf20Sopenharmony_ci	}
24458c2ecf20Sopenharmony_ci
24468c2ecf20Sopenharmony_ci	rc = next_entry(policydb_str, fp, len);
24478c2ecf20Sopenharmony_ci	if (rc) {
24488c2ecf20Sopenharmony_ci		pr_err("SELinux:  truncated policydb string identifier\n");
24498c2ecf20Sopenharmony_ci		kfree(policydb_str);
24508c2ecf20Sopenharmony_ci		goto bad;
24518c2ecf20Sopenharmony_ci	}
24528c2ecf20Sopenharmony_ci
24538c2ecf20Sopenharmony_ci	rc = -EINVAL;
24548c2ecf20Sopenharmony_ci	policydb_str[len] = '\0';
24558c2ecf20Sopenharmony_ci	if (strcmp(policydb_str, POLICYDB_STRING)) {
24568c2ecf20Sopenharmony_ci		pr_err("SELinux:  policydb string %s does not match "
24578c2ecf20Sopenharmony_ci		       "my string %s\n", policydb_str, POLICYDB_STRING);
24588c2ecf20Sopenharmony_ci		kfree(policydb_str);
24598c2ecf20Sopenharmony_ci		goto bad;
24608c2ecf20Sopenharmony_ci	}
24618c2ecf20Sopenharmony_ci	/* Done with policydb_str. */
24628c2ecf20Sopenharmony_ci	kfree(policydb_str);
24638c2ecf20Sopenharmony_ci	policydb_str = NULL;
24648c2ecf20Sopenharmony_ci
24658c2ecf20Sopenharmony_ci	/* Read the version and table sizes. */
24668c2ecf20Sopenharmony_ci	rc = next_entry(buf, fp, sizeof(u32)*4);
24678c2ecf20Sopenharmony_ci	if (rc)
24688c2ecf20Sopenharmony_ci		goto bad;
24698c2ecf20Sopenharmony_ci
24708c2ecf20Sopenharmony_ci	rc = -EINVAL;
24718c2ecf20Sopenharmony_ci	p->policyvers = le32_to_cpu(buf[0]);
24728c2ecf20Sopenharmony_ci	if (p->policyvers < POLICYDB_VERSION_MIN ||
24738c2ecf20Sopenharmony_ci	    p->policyvers > POLICYDB_VERSION_MAX) {
24748c2ecf20Sopenharmony_ci		pr_err("SELinux:  policydb version %d does not match "
24758c2ecf20Sopenharmony_ci		       "my version range %d-%d\n",
24768c2ecf20Sopenharmony_ci		       le32_to_cpu(buf[0]), POLICYDB_VERSION_MIN, POLICYDB_VERSION_MAX);
24778c2ecf20Sopenharmony_ci		goto bad;
24788c2ecf20Sopenharmony_ci	}
24798c2ecf20Sopenharmony_ci
24808c2ecf20Sopenharmony_ci	if ((le32_to_cpu(buf[1]) & POLICYDB_CONFIG_MLS)) {
24818c2ecf20Sopenharmony_ci		p->mls_enabled = 1;
24828c2ecf20Sopenharmony_ci
24838c2ecf20Sopenharmony_ci		rc = -EINVAL;
24848c2ecf20Sopenharmony_ci		if (p->policyvers < POLICYDB_VERSION_MLS) {
24858c2ecf20Sopenharmony_ci			pr_err("SELinux: security policydb version %d "
24868c2ecf20Sopenharmony_ci				"(MLS) not backwards compatible\n",
24878c2ecf20Sopenharmony_ci				p->policyvers);
24888c2ecf20Sopenharmony_ci			goto bad;
24898c2ecf20Sopenharmony_ci		}
24908c2ecf20Sopenharmony_ci	}
24918c2ecf20Sopenharmony_ci	p->reject_unknown = !!(le32_to_cpu(buf[1]) & REJECT_UNKNOWN);
24928c2ecf20Sopenharmony_ci	p->allow_unknown = !!(le32_to_cpu(buf[1]) & ALLOW_UNKNOWN);
24938c2ecf20Sopenharmony_ci
24948c2ecf20Sopenharmony_ci	if (p->policyvers >= POLICYDB_VERSION_POLCAP) {
24958c2ecf20Sopenharmony_ci		rc = ebitmap_read(&p->policycaps, fp);
24968c2ecf20Sopenharmony_ci		if (rc)
24978c2ecf20Sopenharmony_ci			goto bad;
24988c2ecf20Sopenharmony_ci	}
24998c2ecf20Sopenharmony_ci
25008c2ecf20Sopenharmony_ci	if (p->policyvers >= POLICYDB_VERSION_PERMISSIVE) {
25018c2ecf20Sopenharmony_ci		rc = ebitmap_read(&p->permissive_map, fp);
25028c2ecf20Sopenharmony_ci		if (rc)
25038c2ecf20Sopenharmony_ci			goto bad;
25048c2ecf20Sopenharmony_ci	}
25058c2ecf20Sopenharmony_ci
25068c2ecf20Sopenharmony_ci	rc = -EINVAL;
25078c2ecf20Sopenharmony_ci	info = policydb_lookup_compat(p->policyvers);
25088c2ecf20Sopenharmony_ci	if (!info) {
25098c2ecf20Sopenharmony_ci		pr_err("SELinux:  unable to find policy compat info "
25108c2ecf20Sopenharmony_ci		       "for version %d\n", p->policyvers);
25118c2ecf20Sopenharmony_ci		goto bad;
25128c2ecf20Sopenharmony_ci	}
25138c2ecf20Sopenharmony_ci
25148c2ecf20Sopenharmony_ci	rc = -EINVAL;
25158c2ecf20Sopenharmony_ci	if (le32_to_cpu(buf[2]) != info->sym_num ||
25168c2ecf20Sopenharmony_ci		le32_to_cpu(buf[3]) != info->ocon_num) {
25178c2ecf20Sopenharmony_ci		pr_err("SELinux:  policydb table sizes (%d,%d) do "
25188c2ecf20Sopenharmony_ci		       "not match mine (%d,%d)\n", le32_to_cpu(buf[2]),
25198c2ecf20Sopenharmony_ci			le32_to_cpu(buf[3]),
25208c2ecf20Sopenharmony_ci		       info->sym_num, info->ocon_num);
25218c2ecf20Sopenharmony_ci		goto bad;
25228c2ecf20Sopenharmony_ci	}
25238c2ecf20Sopenharmony_ci
25248c2ecf20Sopenharmony_ci	for (i = 0; i < info->sym_num; i++) {
25258c2ecf20Sopenharmony_ci		rc = next_entry(buf, fp, sizeof(u32)*2);
25268c2ecf20Sopenharmony_ci		if (rc)
25278c2ecf20Sopenharmony_ci			goto bad;
25288c2ecf20Sopenharmony_ci		nprim = le32_to_cpu(buf[0]);
25298c2ecf20Sopenharmony_ci		nel = le32_to_cpu(buf[1]);
25308c2ecf20Sopenharmony_ci
25318c2ecf20Sopenharmony_ci		rc = symtab_init(&p->symtab[i], nel);
25328c2ecf20Sopenharmony_ci		if (rc)
25338c2ecf20Sopenharmony_ci			goto out;
25348c2ecf20Sopenharmony_ci
25358c2ecf20Sopenharmony_ci		if (i == SYM_ROLES) {
25368c2ecf20Sopenharmony_ci			rc = roles_init(p);
25378c2ecf20Sopenharmony_ci			if (rc)
25388c2ecf20Sopenharmony_ci				goto out;
25398c2ecf20Sopenharmony_ci		}
25408c2ecf20Sopenharmony_ci
25418c2ecf20Sopenharmony_ci		for (j = 0; j < nel; j++) {
25428c2ecf20Sopenharmony_ci			rc = read_f[i](p, &p->symtab[i], fp);
25438c2ecf20Sopenharmony_ci			if (rc)
25448c2ecf20Sopenharmony_ci				goto bad;
25458c2ecf20Sopenharmony_ci		}
25468c2ecf20Sopenharmony_ci
25478c2ecf20Sopenharmony_ci		p->symtab[i].nprim = nprim;
25488c2ecf20Sopenharmony_ci	}
25498c2ecf20Sopenharmony_ci
25508c2ecf20Sopenharmony_ci	rc = -EINVAL;
25518c2ecf20Sopenharmony_ci	p->process_class = string_to_security_class(p, "process");
25528c2ecf20Sopenharmony_ci	if (!p->process_class) {
25538c2ecf20Sopenharmony_ci		pr_err("SELinux: process class is required, not defined in policy\n");
25548c2ecf20Sopenharmony_ci		goto bad;
25558c2ecf20Sopenharmony_ci	}
25568c2ecf20Sopenharmony_ci
25578c2ecf20Sopenharmony_ci	rc = avtab_read(&p->te_avtab, fp, p);
25588c2ecf20Sopenharmony_ci	if (rc)
25598c2ecf20Sopenharmony_ci		goto bad;
25608c2ecf20Sopenharmony_ci
25618c2ecf20Sopenharmony_ci	if (p->policyvers >= POLICYDB_VERSION_BOOL) {
25628c2ecf20Sopenharmony_ci		rc = cond_read_list(p, fp);
25638c2ecf20Sopenharmony_ci		if (rc)
25648c2ecf20Sopenharmony_ci			goto bad;
25658c2ecf20Sopenharmony_ci	}
25668c2ecf20Sopenharmony_ci
25678c2ecf20Sopenharmony_ci	rc = next_entry(buf, fp, sizeof(u32));
25688c2ecf20Sopenharmony_ci	if (rc)
25698c2ecf20Sopenharmony_ci		goto bad;
25708c2ecf20Sopenharmony_ci	nel = le32_to_cpu(buf[0]);
25718c2ecf20Sopenharmony_ci
25728c2ecf20Sopenharmony_ci	rc = hashtab_init(&p->role_tr, nel);
25738c2ecf20Sopenharmony_ci	if (rc)
25748c2ecf20Sopenharmony_ci		goto bad;
25758c2ecf20Sopenharmony_ci	for (i = 0; i < nel; i++) {
25768c2ecf20Sopenharmony_ci		rc = -ENOMEM;
25778c2ecf20Sopenharmony_ci		rtk = kmalloc(sizeof(*rtk), GFP_KERNEL);
25788c2ecf20Sopenharmony_ci		if (!rtk)
25798c2ecf20Sopenharmony_ci			goto bad;
25808c2ecf20Sopenharmony_ci
25818c2ecf20Sopenharmony_ci		rc = -ENOMEM;
25828c2ecf20Sopenharmony_ci		rtd = kmalloc(sizeof(*rtd), GFP_KERNEL);
25838c2ecf20Sopenharmony_ci		if (!rtd)
25848c2ecf20Sopenharmony_ci			goto bad;
25858c2ecf20Sopenharmony_ci
25868c2ecf20Sopenharmony_ci		rc = next_entry(buf, fp, sizeof(u32)*3);
25878c2ecf20Sopenharmony_ci		if (rc)
25888c2ecf20Sopenharmony_ci			goto bad;
25898c2ecf20Sopenharmony_ci
25908c2ecf20Sopenharmony_ci		rc = -EINVAL;
25918c2ecf20Sopenharmony_ci		rtk->role = le32_to_cpu(buf[0]);
25928c2ecf20Sopenharmony_ci		rtk->type = le32_to_cpu(buf[1]);
25938c2ecf20Sopenharmony_ci		rtd->new_role = le32_to_cpu(buf[2]);
25948c2ecf20Sopenharmony_ci		if (p->policyvers >= POLICYDB_VERSION_ROLETRANS) {
25958c2ecf20Sopenharmony_ci			rc = next_entry(buf, fp, sizeof(u32));
25968c2ecf20Sopenharmony_ci			if (rc)
25978c2ecf20Sopenharmony_ci				goto bad;
25988c2ecf20Sopenharmony_ci			rtk->tclass = le32_to_cpu(buf[0]);
25998c2ecf20Sopenharmony_ci		} else
26008c2ecf20Sopenharmony_ci			rtk->tclass = p->process_class;
26018c2ecf20Sopenharmony_ci
26028c2ecf20Sopenharmony_ci		rc = -EINVAL;
26038c2ecf20Sopenharmony_ci		if (!policydb_role_isvalid(p, rtk->role) ||
26048c2ecf20Sopenharmony_ci		    !policydb_type_isvalid(p, rtk->type) ||
26058c2ecf20Sopenharmony_ci		    !policydb_class_isvalid(p, rtk->tclass) ||
26068c2ecf20Sopenharmony_ci		    !policydb_role_isvalid(p, rtd->new_role))
26078c2ecf20Sopenharmony_ci			goto bad;
26088c2ecf20Sopenharmony_ci
26098c2ecf20Sopenharmony_ci		rc = hashtab_insert(&p->role_tr, rtk, rtd, roletr_key_params);
26108c2ecf20Sopenharmony_ci		if (rc)
26118c2ecf20Sopenharmony_ci			goto bad;
26128c2ecf20Sopenharmony_ci
26138c2ecf20Sopenharmony_ci		rtk = NULL;
26148c2ecf20Sopenharmony_ci		rtd = NULL;
26158c2ecf20Sopenharmony_ci	}
26168c2ecf20Sopenharmony_ci
26178c2ecf20Sopenharmony_ci	rc = next_entry(buf, fp, sizeof(u32));
26188c2ecf20Sopenharmony_ci	if (rc)
26198c2ecf20Sopenharmony_ci		goto bad;
26208c2ecf20Sopenharmony_ci	nel = le32_to_cpu(buf[0]);
26218c2ecf20Sopenharmony_ci	lra = NULL;
26228c2ecf20Sopenharmony_ci	for (i = 0; i < nel; i++) {
26238c2ecf20Sopenharmony_ci		rc = -ENOMEM;
26248c2ecf20Sopenharmony_ci		ra = kzalloc(sizeof(*ra), GFP_KERNEL);
26258c2ecf20Sopenharmony_ci		if (!ra)
26268c2ecf20Sopenharmony_ci			goto bad;
26278c2ecf20Sopenharmony_ci		if (lra)
26288c2ecf20Sopenharmony_ci			lra->next = ra;
26298c2ecf20Sopenharmony_ci		else
26308c2ecf20Sopenharmony_ci			p->role_allow = ra;
26318c2ecf20Sopenharmony_ci		rc = next_entry(buf, fp, sizeof(u32)*2);
26328c2ecf20Sopenharmony_ci		if (rc)
26338c2ecf20Sopenharmony_ci			goto bad;
26348c2ecf20Sopenharmony_ci
26358c2ecf20Sopenharmony_ci		rc = -EINVAL;
26368c2ecf20Sopenharmony_ci		ra->role = le32_to_cpu(buf[0]);
26378c2ecf20Sopenharmony_ci		ra->new_role = le32_to_cpu(buf[1]);
26388c2ecf20Sopenharmony_ci		if (!policydb_role_isvalid(p, ra->role) ||
26398c2ecf20Sopenharmony_ci		    !policydb_role_isvalid(p, ra->new_role))
26408c2ecf20Sopenharmony_ci			goto bad;
26418c2ecf20Sopenharmony_ci		lra = ra;
26428c2ecf20Sopenharmony_ci	}
26438c2ecf20Sopenharmony_ci
26448c2ecf20Sopenharmony_ci	rc = filename_trans_read(p, fp);
26458c2ecf20Sopenharmony_ci	if (rc)
26468c2ecf20Sopenharmony_ci		goto bad;
26478c2ecf20Sopenharmony_ci
26488c2ecf20Sopenharmony_ci	rc = policydb_index(p);
26498c2ecf20Sopenharmony_ci	if (rc)
26508c2ecf20Sopenharmony_ci		goto bad;
26518c2ecf20Sopenharmony_ci
26528c2ecf20Sopenharmony_ci	rc = -EINVAL;
26538c2ecf20Sopenharmony_ci	perm = string_to_av_perm(p, p->process_class, "transition");
26548c2ecf20Sopenharmony_ci	if (!perm) {
26558c2ecf20Sopenharmony_ci		pr_err("SELinux: process transition permission is required, not defined in policy\n");
26568c2ecf20Sopenharmony_ci		goto bad;
26578c2ecf20Sopenharmony_ci	}
26588c2ecf20Sopenharmony_ci	p->process_trans_perms = perm;
26598c2ecf20Sopenharmony_ci	perm = string_to_av_perm(p, p->process_class, "dyntransition");
26608c2ecf20Sopenharmony_ci	if (!perm) {
26618c2ecf20Sopenharmony_ci		pr_err("SELinux: process dyntransition permission is required, not defined in policy\n");
26628c2ecf20Sopenharmony_ci		goto bad;
26638c2ecf20Sopenharmony_ci	}
26648c2ecf20Sopenharmony_ci	p->process_trans_perms |= perm;
26658c2ecf20Sopenharmony_ci
26668c2ecf20Sopenharmony_ci	rc = ocontext_read(p, info, fp);
26678c2ecf20Sopenharmony_ci	if (rc)
26688c2ecf20Sopenharmony_ci		goto bad;
26698c2ecf20Sopenharmony_ci
26708c2ecf20Sopenharmony_ci	rc = genfs_read(p, fp);
26718c2ecf20Sopenharmony_ci	if (rc)
26728c2ecf20Sopenharmony_ci		goto bad;
26738c2ecf20Sopenharmony_ci
26748c2ecf20Sopenharmony_ci	rc = range_read(p, fp);
26758c2ecf20Sopenharmony_ci	if (rc)
26768c2ecf20Sopenharmony_ci		goto bad;
26778c2ecf20Sopenharmony_ci
26788c2ecf20Sopenharmony_ci	rc = -ENOMEM;
26798c2ecf20Sopenharmony_ci	p->type_attr_map_array = kvcalloc(p->p_types.nprim,
26808c2ecf20Sopenharmony_ci					  sizeof(*p->type_attr_map_array),
26818c2ecf20Sopenharmony_ci					  GFP_KERNEL);
26828c2ecf20Sopenharmony_ci	if (!p->type_attr_map_array)
26838c2ecf20Sopenharmony_ci		goto bad;
26848c2ecf20Sopenharmony_ci
26858c2ecf20Sopenharmony_ci	/* just in case ebitmap_init() becomes more than just a memset(0): */
26868c2ecf20Sopenharmony_ci	for (i = 0; i < p->p_types.nprim; i++)
26878c2ecf20Sopenharmony_ci		ebitmap_init(&p->type_attr_map_array[i]);
26888c2ecf20Sopenharmony_ci
26898c2ecf20Sopenharmony_ci	for (i = 0; i < p->p_types.nprim; i++) {
26908c2ecf20Sopenharmony_ci		struct ebitmap *e = &p->type_attr_map_array[i];
26918c2ecf20Sopenharmony_ci
26928c2ecf20Sopenharmony_ci		if (p->policyvers >= POLICYDB_VERSION_AVTAB) {
26938c2ecf20Sopenharmony_ci			rc = ebitmap_read(e, fp);
26948c2ecf20Sopenharmony_ci			if (rc)
26958c2ecf20Sopenharmony_ci				goto bad;
26968c2ecf20Sopenharmony_ci		}
26978c2ecf20Sopenharmony_ci		/* add the type itself as the degenerate case */
26988c2ecf20Sopenharmony_ci		rc = ebitmap_set_bit(e, i, 1);
26998c2ecf20Sopenharmony_ci		if (rc)
27008c2ecf20Sopenharmony_ci			goto bad;
27018c2ecf20Sopenharmony_ci	}
27028c2ecf20Sopenharmony_ci
27038c2ecf20Sopenharmony_ci	rc = policydb_bounds_sanity_check(p);
27048c2ecf20Sopenharmony_ci	if (rc)
27058c2ecf20Sopenharmony_ci		goto bad;
27068c2ecf20Sopenharmony_ci
27078c2ecf20Sopenharmony_ci	rc = 0;
27088c2ecf20Sopenharmony_ciout:
27098c2ecf20Sopenharmony_ci	return rc;
27108c2ecf20Sopenharmony_cibad:
27118c2ecf20Sopenharmony_ci	kfree(rtk);
27128c2ecf20Sopenharmony_ci	kfree(rtd);
27138c2ecf20Sopenharmony_ci	policydb_destroy(p);
27148c2ecf20Sopenharmony_ci	goto out;
27158c2ecf20Sopenharmony_ci}
27168c2ecf20Sopenharmony_ci
27178c2ecf20Sopenharmony_ci/*
27188c2ecf20Sopenharmony_ci * Write a MLS level structure to a policydb binary
27198c2ecf20Sopenharmony_ci * representation file.
27208c2ecf20Sopenharmony_ci */
27218c2ecf20Sopenharmony_cistatic int mls_write_level(struct mls_level *l, void *fp)
27228c2ecf20Sopenharmony_ci{
27238c2ecf20Sopenharmony_ci	__le32 buf[1];
27248c2ecf20Sopenharmony_ci	int rc;
27258c2ecf20Sopenharmony_ci
27268c2ecf20Sopenharmony_ci	buf[0] = cpu_to_le32(l->sens);
27278c2ecf20Sopenharmony_ci	rc = put_entry(buf, sizeof(u32), 1, fp);
27288c2ecf20Sopenharmony_ci	if (rc)
27298c2ecf20Sopenharmony_ci		return rc;
27308c2ecf20Sopenharmony_ci
27318c2ecf20Sopenharmony_ci	rc = ebitmap_write(&l->cat, fp);
27328c2ecf20Sopenharmony_ci	if (rc)
27338c2ecf20Sopenharmony_ci		return rc;
27348c2ecf20Sopenharmony_ci
27358c2ecf20Sopenharmony_ci	return 0;
27368c2ecf20Sopenharmony_ci}
27378c2ecf20Sopenharmony_ci
27388c2ecf20Sopenharmony_ci/*
27398c2ecf20Sopenharmony_ci * Write a MLS range structure to a policydb binary
27408c2ecf20Sopenharmony_ci * representation file.
27418c2ecf20Sopenharmony_ci */
27428c2ecf20Sopenharmony_cistatic int mls_write_range_helper(struct mls_range *r, void *fp)
27438c2ecf20Sopenharmony_ci{
27448c2ecf20Sopenharmony_ci	__le32 buf[3];
27458c2ecf20Sopenharmony_ci	size_t items;
27468c2ecf20Sopenharmony_ci	int rc, eq;
27478c2ecf20Sopenharmony_ci
27488c2ecf20Sopenharmony_ci	eq = mls_level_eq(&r->level[1], &r->level[0]);
27498c2ecf20Sopenharmony_ci
27508c2ecf20Sopenharmony_ci	if (eq)
27518c2ecf20Sopenharmony_ci		items = 2;
27528c2ecf20Sopenharmony_ci	else
27538c2ecf20Sopenharmony_ci		items = 3;
27548c2ecf20Sopenharmony_ci	buf[0] = cpu_to_le32(items-1);
27558c2ecf20Sopenharmony_ci	buf[1] = cpu_to_le32(r->level[0].sens);
27568c2ecf20Sopenharmony_ci	if (!eq)
27578c2ecf20Sopenharmony_ci		buf[2] = cpu_to_le32(r->level[1].sens);
27588c2ecf20Sopenharmony_ci
27598c2ecf20Sopenharmony_ci	BUG_ON(items > ARRAY_SIZE(buf));
27608c2ecf20Sopenharmony_ci
27618c2ecf20Sopenharmony_ci	rc = put_entry(buf, sizeof(u32), items, fp);
27628c2ecf20Sopenharmony_ci	if (rc)
27638c2ecf20Sopenharmony_ci		return rc;
27648c2ecf20Sopenharmony_ci
27658c2ecf20Sopenharmony_ci	rc = ebitmap_write(&r->level[0].cat, fp);
27668c2ecf20Sopenharmony_ci	if (rc)
27678c2ecf20Sopenharmony_ci		return rc;
27688c2ecf20Sopenharmony_ci	if (!eq) {
27698c2ecf20Sopenharmony_ci		rc = ebitmap_write(&r->level[1].cat, fp);
27708c2ecf20Sopenharmony_ci		if (rc)
27718c2ecf20Sopenharmony_ci			return rc;
27728c2ecf20Sopenharmony_ci	}
27738c2ecf20Sopenharmony_ci
27748c2ecf20Sopenharmony_ci	return 0;
27758c2ecf20Sopenharmony_ci}
27768c2ecf20Sopenharmony_ci
27778c2ecf20Sopenharmony_cistatic int sens_write(void *vkey, void *datum, void *ptr)
27788c2ecf20Sopenharmony_ci{
27798c2ecf20Sopenharmony_ci	char *key = vkey;
27808c2ecf20Sopenharmony_ci	struct level_datum *levdatum = datum;
27818c2ecf20Sopenharmony_ci	struct policy_data *pd = ptr;
27828c2ecf20Sopenharmony_ci	void *fp = pd->fp;
27838c2ecf20Sopenharmony_ci	__le32 buf[2];
27848c2ecf20Sopenharmony_ci	size_t len;
27858c2ecf20Sopenharmony_ci	int rc;
27868c2ecf20Sopenharmony_ci
27878c2ecf20Sopenharmony_ci	len = strlen(key);
27888c2ecf20Sopenharmony_ci	buf[0] = cpu_to_le32(len);
27898c2ecf20Sopenharmony_ci	buf[1] = cpu_to_le32(levdatum->isalias);
27908c2ecf20Sopenharmony_ci	rc = put_entry(buf, sizeof(u32), 2, fp);
27918c2ecf20Sopenharmony_ci	if (rc)
27928c2ecf20Sopenharmony_ci		return rc;
27938c2ecf20Sopenharmony_ci
27948c2ecf20Sopenharmony_ci	rc = put_entry(key, 1, len, fp);
27958c2ecf20Sopenharmony_ci	if (rc)
27968c2ecf20Sopenharmony_ci		return rc;
27978c2ecf20Sopenharmony_ci
27988c2ecf20Sopenharmony_ci	rc = mls_write_level(levdatum->level, fp);
27998c2ecf20Sopenharmony_ci	if (rc)
28008c2ecf20Sopenharmony_ci		return rc;
28018c2ecf20Sopenharmony_ci
28028c2ecf20Sopenharmony_ci	return 0;
28038c2ecf20Sopenharmony_ci}
28048c2ecf20Sopenharmony_ci
28058c2ecf20Sopenharmony_cistatic int cat_write(void *vkey, void *datum, void *ptr)
28068c2ecf20Sopenharmony_ci{
28078c2ecf20Sopenharmony_ci	char *key = vkey;
28088c2ecf20Sopenharmony_ci	struct cat_datum *catdatum = datum;
28098c2ecf20Sopenharmony_ci	struct policy_data *pd = ptr;
28108c2ecf20Sopenharmony_ci	void *fp = pd->fp;
28118c2ecf20Sopenharmony_ci	__le32 buf[3];
28128c2ecf20Sopenharmony_ci	size_t len;
28138c2ecf20Sopenharmony_ci	int rc;
28148c2ecf20Sopenharmony_ci
28158c2ecf20Sopenharmony_ci	len = strlen(key);
28168c2ecf20Sopenharmony_ci	buf[0] = cpu_to_le32(len);
28178c2ecf20Sopenharmony_ci	buf[1] = cpu_to_le32(catdatum->value);
28188c2ecf20Sopenharmony_ci	buf[2] = cpu_to_le32(catdatum->isalias);
28198c2ecf20Sopenharmony_ci	rc = put_entry(buf, sizeof(u32), 3, fp);
28208c2ecf20Sopenharmony_ci	if (rc)
28218c2ecf20Sopenharmony_ci		return rc;
28228c2ecf20Sopenharmony_ci
28238c2ecf20Sopenharmony_ci	rc = put_entry(key, 1, len, fp);
28248c2ecf20Sopenharmony_ci	if (rc)
28258c2ecf20Sopenharmony_ci		return rc;
28268c2ecf20Sopenharmony_ci
28278c2ecf20Sopenharmony_ci	return 0;
28288c2ecf20Sopenharmony_ci}
28298c2ecf20Sopenharmony_ci
28308c2ecf20Sopenharmony_cistatic int role_trans_write_one(void *key, void *datum, void *ptr)
28318c2ecf20Sopenharmony_ci{
28328c2ecf20Sopenharmony_ci	struct role_trans_key *rtk = key;
28338c2ecf20Sopenharmony_ci	struct role_trans_datum *rtd = datum;
28348c2ecf20Sopenharmony_ci	struct policy_data *pd = ptr;
28358c2ecf20Sopenharmony_ci	void *fp = pd->fp;
28368c2ecf20Sopenharmony_ci	struct policydb *p = pd->p;
28378c2ecf20Sopenharmony_ci	__le32 buf[3];
28388c2ecf20Sopenharmony_ci	int rc;
28398c2ecf20Sopenharmony_ci
28408c2ecf20Sopenharmony_ci	buf[0] = cpu_to_le32(rtk->role);
28418c2ecf20Sopenharmony_ci	buf[1] = cpu_to_le32(rtk->type);
28428c2ecf20Sopenharmony_ci	buf[2] = cpu_to_le32(rtd->new_role);
28438c2ecf20Sopenharmony_ci	rc = put_entry(buf, sizeof(u32), 3, fp);
28448c2ecf20Sopenharmony_ci	if (rc)
28458c2ecf20Sopenharmony_ci		return rc;
28468c2ecf20Sopenharmony_ci	if (p->policyvers >= POLICYDB_VERSION_ROLETRANS) {
28478c2ecf20Sopenharmony_ci		buf[0] = cpu_to_le32(rtk->tclass);
28488c2ecf20Sopenharmony_ci		rc = put_entry(buf, sizeof(u32), 1, fp);
28498c2ecf20Sopenharmony_ci		if (rc)
28508c2ecf20Sopenharmony_ci			return rc;
28518c2ecf20Sopenharmony_ci	}
28528c2ecf20Sopenharmony_ci	return 0;
28538c2ecf20Sopenharmony_ci}
28548c2ecf20Sopenharmony_ci
28558c2ecf20Sopenharmony_cistatic int role_trans_write(struct policydb *p, void *fp)
28568c2ecf20Sopenharmony_ci{
28578c2ecf20Sopenharmony_ci	struct policy_data pd = { .p = p, .fp = fp };
28588c2ecf20Sopenharmony_ci	__le32 buf[1];
28598c2ecf20Sopenharmony_ci	int rc;
28608c2ecf20Sopenharmony_ci
28618c2ecf20Sopenharmony_ci	buf[0] = cpu_to_le32(p->role_tr.nel);
28628c2ecf20Sopenharmony_ci	rc = put_entry(buf, sizeof(u32), 1, fp);
28638c2ecf20Sopenharmony_ci	if (rc)
28648c2ecf20Sopenharmony_ci		return rc;
28658c2ecf20Sopenharmony_ci
28668c2ecf20Sopenharmony_ci	return hashtab_map(&p->role_tr, role_trans_write_one, &pd);
28678c2ecf20Sopenharmony_ci}
28688c2ecf20Sopenharmony_ci
28698c2ecf20Sopenharmony_cistatic int role_allow_write(struct role_allow *r, void *fp)
28708c2ecf20Sopenharmony_ci{
28718c2ecf20Sopenharmony_ci	struct role_allow *ra;
28728c2ecf20Sopenharmony_ci	__le32 buf[2];
28738c2ecf20Sopenharmony_ci	size_t nel;
28748c2ecf20Sopenharmony_ci	int rc;
28758c2ecf20Sopenharmony_ci
28768c2ecf20Sopenharmony_ci	nel = 0;
28778c2ecf20Sopenharmony_ci	for (ra = r; ra; ra = ra->next)
28788c2ecf20Sopenharmony_ci		nel++;
28798c2ecf20Sopenharmony_ci	buf[0] = cpu_to_le32(nel);
28808c2ecf20Sopenharmony_ci	rc = put_entry(buf, sizeof(u32), 1, fp);
28818c2ecf20Sopenharmony_ci	if (rc)
28828c2ecf20Sopenharmony_ci		return rc;
28838c2ecf20Sopenharmony_ci	for (ra = r; ra; ra = ra->next) {
28848c2ecf20Sopenharmony_ci		buf[0] = cpu_to_le32(ra->role);
28858c2ecf20Sopenharmony_ci		buf[1] = cpu_to_le32(ra->new_role);
28868c2ecf20Sopenharmony_ci		rc = put_entry(buf, sizeof(u32), 2, fp);
28878c2ecf20Sopenharmony_ci		if (rc)
28888c2ecf20Sopenharmony_ci			return rc;
28898c2ecf20Sopenharmony_ci	}
28908c2ecf20Sopenharmony_ci	return 0;
28918c2ecf20Sopenharmony_ci}
28928c2ecf20Sopenharmony_ci
28938c2ecf20Sopenharmony_ci/*
28948c2ecf20Sopenharmony_ci * Write a security context structure
28958c2ecf20Sopenharmony_ci * to a policydb binary representation file.
28968c2ecf20Sopenharmony_ci */
28978c2ecf20Sopenharmony_cistatic int context_write(struct policydb *p, struct context *c,
28988c2ecf20Sopenharmony_ci			 void *fp)
28998c2ecf20Sopenharmony_ci{
29008c2ecf20Sopenharmony_ci	int rc;
29018c2ecf20Sopenharmony_ci	__le32 buf[3];
29028c2ecf20Sopenharmony_ci
29038c2ecf20Sopenharmony_ci	buf[0] = cpu_to_le32(c->user);
29048c2ecf20Sopenharmony_ci	buf[1] = cpu_to_le32(c->role);
29058c2ecf20Sopenharmony_ci	buf[2] = cpu_to_le32(c->type);
29068c2ecf20Sopenharmony_ci
29078c2ecf20Sopenharmony_ci	rc = put_entry(buf, sizeof(u32), 3, fp);
29088c2ecf20Sopenharmony_ci	if (rc)
29098c2ecf20Sopenharmony_ci		return rc;
29108c2ecf20Sopenharmony_ci
29118c2ecf20Sopenharmony_ci	rc = mls_write_range_helper(&c->range, fp);
29128c2ecf20Sopenharmony_ci	if (rc)
29138c2ecf20Sopenharmony_ci		return rc;
29148c2ecf20Sopenharmony_ci
29158c2ecf20Sopenharmony_ci	return 0;
29168c2ecf20Sopenharmony_ci}
29178c2ecf20Sopenharmony_ci
29188c2ecf20Sopenharmony_ci/*
29198c2ecf20Sopenharmony_ci * The following *_write functions are used to
29208c2ecf20Sopenharmony_ci * write the symbol data to a policy database
29218c2ecf20Sopenharmony_ci * binary representation file.
29228c2ecf20Sopenharmony_ci */
29238c2ecf20Sopenharmony_ci
29248c2ecf20Sopenharmony_cistatic int perm_write(void *vkey, void *datum, void *fp)
29258c2ecf20Sopenharmony_ci{
29268c2ecf20Sopenharmony_ci	char *key = vkey;
29278c2ecf20Sopenharmony_ci	struct perm_datum *perdatum = datum;
29288c2ecf20Sopenharmony_ci	__le32 buf[2];
29298c2ecf20Sopenharmony_ci	size_t len;
29308c2ecf20Sopenharmony_ci	int rc;
29318c2ecf20Sopenharmony_ci
29328c2ecf20Sopenharmony_ci	len = strlen(key);
29338c2ecf20Sopenharmony_ci	buf[0] = cpu_to_le32(len);
29348c2ecf20Sopenharmony_ci	buf[1] = cpu_to_le32(perdatum->value);
29358c2ecf20Sopenharmony_ci	rc = put_entry(buf, sizeof(u32), 2, fp);
29368c2ecf20Sopenharmony_ci	if (rc)
29378c2ecf20Sopenharmony_ci		return rc;
29388c2ecf20Sopenharmony_ci
29398c2ecf20Sopenharmony_ci	rc = put_entry(key, 1, len, fp);
29408c2ecf20Sopenharmony_ci	if (rc)
29418c2ecf20Sopenharmony_ci		return rc;
29428c2ecf20Sopenharmony_ci
29438c2ecf20Sopenharmony_ci	return 0;
29448c2ecf20Sopenharmony_ci}
29458c2ecf20Sopenharmony_ci
29468c2ecf20Sopenharmony_cistatic int common_write(void *vkey, void *datum, void *ptr)
29478c2ecf20Sopenharmony_ci{
29488c2ecf20Sopenharmony_ci	char *key = vkey;
29498c2ecf20Sopenharmony_ci	struct common_datum *comdatum = datum;
29508c2ecf20Sopenharmony_ci	struct policy_data *pd = ptr;
29518c2ecf20Sopenharmony_ci	void *fp = pd->fp;
29528c2ecf20Sopenharmony_ci	__le32 buf[4];
29538c2ecf20Sopenharmony_ci	size_t len;
29548c2ecf20Sopenharmony_ci	int rc;
29558c2ecf20Sopenharmony_ci
29568c2ecf20Sopenharmony_ci	len = strlen(key);
29578c2ecf20Sopenharmony_ci	buf[0] = cpu_to_le32(len);
29588c2ecf20Sopenharmony_ci	buf[1] = cpu_to_le32(comdatum->value);
29598c2ecf20Sopenharmony_ci	buf[2] = cpu_to_le32(comdatum->permissions.nprim);
29608c2ecf20Sopenharmony_ci	buf[3] = cpu_to_le32(comdatum->permissions.table.nel);
29618c2ecf20Sopenharmony_ci	rc = put_entry(buf, sizeof(u32), 4, fp);
29628c2ecf20Sopenharmony_ci	if (rc)
29638c2ecf20Sopenharmony_ci		return rc;
29648c2ecf20Sopenharmony_ci
29658c2ecf20Sopenharmony_ci	rc = put_entry(key, 1, len, fp);
29668c2ecf20Sopenharmony_ci	if (rc)
29678c2ecf20Sopenharmony_ci		return rc;
29688c2ecf20Sopenharmony_ci
29698c2ecf20Sopenharmony_ci	rc = hashtab_map(&comdatum->permissions.table, perm_write, fp);
29708c2ecf20Sopenharmony_ci	if (rc)
29718c2ecf20Sopenharmony_ci		return rc;
29728c2ecf20Sopenharmony_ci
29738c2ecf20Sopenharmony_ci	return 0;
29748c2ecf20Sopenharmony_ci}
29758c2ecf20Sopenharmony_ci
29768c2ecf20Sopenharmony_cistatic int type_set_write(struct type_set *t, void *fp)
29778c2ecf20Sopenharmony_ci{
29788c2ecf20Sopenharmony_ci	int rc;
29798c2ecf20Sopenharmony_ci	__le32 buf[1];
29808c2ecf20Sopenharmony_ci
29818c2ecf20Sopenharmony_ci	if (ebitmap_write(&t->types, fp))
29828c2ecf20Sopenharmony_ci		return -EINVAL;
29838c2ecf20Sopenharmony_ci	if (ebitmap_write(&t->negset, fp))
29848c2ecf20Sopenharmony_ci		return -EINVAL;
29858c2ecf20Sopenharmony_ci
29868c2ecf20Sopenharmony_ci	buf[0] = cpu_to_le32(t->flags);
29878c2ecf20Sopenharmony_ci	rc = put_entry(buf, sizeof(u32), 1, fp);
29888c2ecf20Sopenharmony_ci	if (rc)
29898c2ecf20Sopenharmony_ci		return -EINVAL;
29908c2ecf20Sopenharmony_ci
29918c2ecf20Sopenharmony_ci	return 0;
29928c2ecf20Sopenharmony_ci}
29938c2ecf20Sopenharmony_ci
29948c2ecf20Sopenharmony_cistatic int write_cons_helper(struct policydb *p, struct constraint_node *node,
29958c2ecf20Sopenharmony_ci			     void *fp)
29968c2ecf20Sopenharmony_ci{
29978c2ecf20Sopenharmony_ci	struct constraint_node *c;
29988c2ecf20Sopenharmony_ci	struct constraint_expr *e;
29998c2ecf20Sopenharmony_ci	__le32 buf[3];
30008c2ecf20Sopenharmony_ci	u32 nel;
30018c2ecf20Sopenharmony_ci	int rc;
30028c2ecf20Sopenharmony_ci
30038c2ecf20Sopenharmony_ci	for (c = node; c; c = c->next) {
30048c2ecf20Sopenharmony_ci		nel = 0;
30058c2ecf20Sopenharmony_ci		for (e = c->expr; e; e = e->next)
30068c2ecf20Sopenharmony_ci			nel++;
30078c2ecf20Sopenharmony_ci		buf[0] = cpu_to_le32(c->permissions);
30088c2ecf20Sopenharmony_ci		buf[1] = cpu_to_le32(nel);
30098c2ecf20Sopenharmony_ci		rc = put_entry(buf, sizeof(u32), 2, fp);
30108c2ecf20Sopenharmony_ci		if (rc)
30118c2ecf20Sopenharmony_ci			return rc;
30128c2ecf20Sopenharmony_ci		for (e = c->expr; e; e = e->next) {
30138c2ecf20Sopenharmony_ci			buf[0] = cpu_to_le32(e->expr_type);
30148c2ecf20Sopenharmony_ci			buf[1] = cpu_to_le32(e->attr);
30158c2ecf20Sopenharmony_ci			buf[2] = cpu_to_le32(e->op);
30168c2ecf20Sopenharmony_ci			rc = put_entry(buf, sizeof(u32), 3, fp);
30178c2ecf20Sopenharmony_ci			if (rc)
30188c2ecf20Sopenharmony_ci				return rc;
30198c2ecf20Sopenharmony_ci
30208c2ecf20Sopenharmony_ci			switch (e->expr_type) {
30218c2ecf20Sopenharmony_ci			case CEXPR_NAMES:
30228c2ecf20Sopenharmony_ci				rc = ebitmap_write(&e->names, fp);
30238c2ecf20Sopenharmony_ci				if (rc)
30248c2ecf20Sopenharmony_ci					return rc;
30258c2ecf20Sopenharmony_ci				if (p->policyvers >=
30268c2ecf20Sopenharmony_ci					POLICYDB_VERSION_CONSTRAINT_NAMES) {
30278c2ecf20Sopenharmony_ci					rc = type_set_write(e->type_names, fp);
30288c2ecf20Sopenharmony_ci					if (rc)
30298c2ecf20Sopenharmony_ci						return rc;
30308c2ecf20Sopenharmony_ci				}
30318c2ecf20Sopenharmony_ci				break;
30328c2ecf20Sopenharmony_ci			default:
30338c2ecf20Sopenharmony_ci				break;
30348c2ecf20Sopenharmony_ci			}
30358c2ecf20Sopenharmony_ci		}
30368c2ecf20Sopenharmony_ci	}
30378c2ecf20Sopenharmony_ci
30388c2ecf20Sopenharmony_ci	return 0;
30398c2ecf20Sopenharmony_ci}
30408c2ecf20Sopenharmony_ci
30418c2ecf20Sopenharmony_cistatic int class_write(void *vkey, void *datum, void *ptr)
30428c2ecf20Sopenharmony_ci{
30438c2ecf20Sopenharmony_ci	char *key = vkey;
30448c2ecf20Sopenharmony_ci	struct class_datum *cladatum = datum;
30458c2ecf20Sopenharmony_ci	struct policy_data *pd = ptr;
30468c2ecf20Sopenharmony_ci	void *fp = pd->fp;
30478c2ecf20Sopenharmony_ci	struct policydb *p = pd->p;
30488c2ecf20Sopenharmony_ci	struct constraint_node *c;
30498c2ecf20Sopenharmony_ci	__le32 buf[6];
30508c2ecf20Sopenharmony_ci	u32 ncons;
30518c2ecf20Sopenharmony_ci	size_t len, len2;
30528c2ecf20Sopenharmony_ci	int rc;
30538c2ecf20Sopenharmony_ci
30548c2ecf20Sopenharmony_ci	len = strlen(key);
30558c2ecf20Sopenharmony_ci	if (cladatum->comkey)
30568c2ecf20Sopenharmony_ci		len2 = strlen(cladatum->comkey);
30578c2ecf20Sopenharmony_ci	else
30588c2ecf20Sopenharmony_ci		len2 = 0;
30598c2ecf20Sopenharmony_ci
30608c2ecf20Sopenharmony_ci	ncons = 0;
30618c2ecf20Sopenharmony_ci	for (c = cladatum->constraints; c; c = c->next)
30628c2ecf20Sopenharmony_ci		ncons++;
30638c2ecf20Sopenharmony_ci
30648c2ecf20Sopenharmony_ci	buf[0] = cpu_to_le32(len);
30658c2ecf20Sopenharmony_ci	buf[1] = cpu_to_le32(len2);
30668c2ecf20Sopenharmony_ci	buf[2] = cpu_to_le32(cladatum->value);
30678c2ecf20Sopenharmony_ci	buf[3] = cpu_to_le32(cladatum->permissions.nprim);
30688c2ecf20Sopenharmony_ci	buf[4] = cpu_to_le32(cladatum->permissions.table.nel);
30698c2ecf20Sopenharmony_ci	buf[5] = cpu_to_le32(ncons);
30708c2ecf20Sopenharmony_ci	rc = put_entry(buf, sizeof(u32), 6, fp);
30718c2ecf20Sopenharmony_ci	if (rc)
30728c2ecf20Sopenharmony_ci		return rc;
30738c2ecf20Sopenharmony_ci
30748c2ecf20Sopenharmony_ci	rc = put_entry(key, 1, len, fp);
30758c2ecf20Sopenharmony_ci	if (rc)
30768c2ecf20Sopenharmony_ci		return rc;
30778c2ecf20Sopenharmony_ci
30788c2ecf20Sopenharmony_ci	if (cladatum->comkey) {
30798c2ecf20Sopenharmony_ci		rc = put_entry(cladatum->comkey, 1, len2, fp);
30808c2ecf20Sopenharmony_ci		if (rc)
30818c2ecf20Sopenharmony_ci			return rc;
30828c2ecf20Sopenharmony_ci	}
30838c2ecf20Sopenharmony_ci
30848c2ecf20Sopenharmony_ci	rc = hashtab_map(&cladatum->permissions.table, perm_write, fp);
30858c2ecf20Sopenharmony_ci	if (rc)
30868c2ecf20Sopenharmony_ci		return rc;
30878c2ecf20Sopenharmony_ci
30888c2ecf20Sopenharmony_ci	rc = write_cons_helper(p, cladatum->constraints, fp);
30898c2ecf20Sopenharmony_ci	if (rc)
30908c2ecf20Sopenharmony_ci		return rc;
30918c2ecf20Sopenharmony_ci
30928c2ecf20Sopenharmony_ci	/* write out the validatetrans rule */
30938c2ecf20Sopenharmony_ci	ncons = 0;
30948c2ecf20Sopenharmony_ci	for (c = cladatum->validatetrans; c; c = c->next)
30958c2ecf20Sopenharmony_ci		ncons++;
30968c2ecf20Sopenharmony_ci
30978c2ecf20Sopenharmony_ci	buf[0] = cpu_to_le32(ncons);
30988c2ecf20Sopenharmony_ci	rc = put_entry(buf, sizeof(u32), 1, fp);
30998c2ecf20Sopenharmony_ci	if (rc)
31008c2ecf20Sopenharmony_ci		return rc;
31018c2ecf20Sopenharmony_ci
31028c2ecf20Sopenharmony_ci	rc = write_cons_helper(p, cladatum->validatetrans, fp);
31038c2ecf20Sopenharmony_ci	if (rc)
31048c2ecf20Sopenharmony_ci		return rc;
31058c2ecf20Sopenharmony_ci
31068c2ecf20Sopenharmony_ci	if (p->policyvers >= POLICYDB_VERSION_NEW_OBJECT_DEFAULTS) {
31078c2ecf20Sopenharmony_ci		buf[0] = cpu_to_le32(cladatum->default_user);
31088c2ecf20Sopenharmony_ci		buf[1] = cpu_to_le32(cladatum->default_role);
31098c2ecf20Sopenharmony_ci		buf[2] = cpu_to_le32(cladatum->default_range);
31108c2ecf20Sopenharmony_ci
31118c2ecf20Sopenharmony_ci		rc = put_entry(buf, sizeof(uint32_t), 3, fp);
31128c2ecf20Sopenharmony_ci		if (rc)
31138c2ecf20Sopenharmony_ci			return rc;
31148c2ecf20Sopenharmony_ci	}
31158c2ecf20Sopenharmony_ci
31168c2ecf20Sopenharmony_ci	if (p->policyvers >= POLICYDB_VERSION_DEFAULT_TYPE) {
31178c2ecf20Sopenharmony_ci		buf[0] = cpu_to_le32(cladatum->default_type);
31188c2ecf20Sopenharmony_ci		rc = put_entry(buf, sizeof(uint32_t), 1, fp);
31198c2ecf20Sopenharmony_ci		if (rc)
31208c2ecf20Sopenharmony_ci			return rc;
31218c2ecf20Sopenharmony_ci	}
31228c2ecf20Sopenharmony_ci
31238c2ecf20Sopenharmony_ci	return 0;
31248c2ecf20Sopenharmony_ci}
31258c2ecf20Sopenharmony_ci
31268c2ecf20Sopenharmony_cistatic int role_write(void *vkey, void *datum, void *ptr)
31278c2ecf20Sopenharmony_ci{
31288c2ecf20Sopenharmony_ci	char *key = vkey;
31298c2ecf20Sopenharmony_ci	struct role_datum *role = datum;
31308c2ecf20Sopenharmony_ci	struct policy_data *pd = ptr;
31318c2ecf20Sopenharmony_ci	void *fp = pd->fp;
31328c2ecf20Sopenharmony_ci	struct policydb *p = pd->p;
31338c2ecf20Sopenharmony_ci	__le32 buf[3];
31348c2ecf20Sopenharmony_ci	size_t items, len;
31358c2ecf20Sopenharmony_ci	int rc;
31368c2ecf20Sopenharmony_ci
31378c2ecf20Sopenharmony_ci	len = strlen(key);
31388c2ecf20Sopenharmony_ci	items = 0;
31398c2ecf20Sopenharmony_ci	buf[items++] = cpu_to_le32(len);
31408c2ecf20Sopenharmony_ci	buf[items++] = cpu_to_le32(role->value);
31418c2ecf20Sopenharmony_ci	if (p->policyvers >= POLICYDB_VERSION_BOUNDARY)
31428c2ecf20Sopenharmony_ci		buf[items++] = cpu_to_le32(role->bounds);
31438c2ecf20Sopenharmony_ci
31448c2ecf20Sopenharmony_ci	BUG_ON(items > ARRAY_SIZE(buf));
31458c2ecf20Sopenharmony_ci
31468c2ecf20Sopenharmony_ci	rc = put_entry(buf, sizeof(u32), items, fp);
31478c2ecf20Sopenharmony_ci	if (rc)
31488c2ecf20Sopenharmony_ci		return rc;
31498c2ecf20Sopenharmony_ci
31508c2ecf20Sopenharmony_ci	rc = put_entry(key, 1, len, fp);
31518c2ecf20Sopenharmony_ci	if (rc)
31528c2ecf20Sopenharmony_ci		return rc;
31538c2ecf20Sopenharmony_ci
31548c2ecf20Sopenharmony_ci	rc = ebitmap_write(&role->dominates, fp);
31558c2ecf20Sopenharmony_ci	if (rc)
31568c2ecf20Sopenharmony_ci		return rc;
31578c2ecf20Sopenharmony_ci
31588c2ecf20Sopenharmony_ci	rc = ebitmap_write(&role->types, fp);
31598c2ecf20Sopenharmony_ci	if (rc)
31608c2ecf20Sopenharmony_ci		return rc;
31618c2ecf20Sopenharmony_ci
31628c2ecf20Sopenharmony_ci	return 0;
31638c2ecf20Sopenharmony_ci}
31648c2ecf20Sopenharmony_ci
31658c2ecf20Sopenharmony_cistatic int type_write(void *vkey, void *datum, void *ptr)
31668c2ecf20Sopenharmony_ci{
31678c2ecf20Sopenharmony_ci	char *key = vkey;
31688c2ecf20Sopenharmony_ci	struct type_datum *typdatum = datum;
31698c2ecf20Sopenharmony_ci	struct policy_data *pd = ptr;
31708c2ecf20Sopenharmony_ci	struct policydb *p = pd->p;
31718c2ecf20Sopenharmony_ci	void *fp = pd->fp;
31728c2ecf20Sopenharmony_ci	__le32 buf[4];
31738c2ecf20Sopenharmony_ci	int rc;
31748c2ecf20Sopenharmony_ci	size_t items, len;
31758c2ecf20Sopenharmony_ci
31768c2ecf20Sopenharmony_ci	len = strlen(key);
31778c2ecf20Sopenharmony_ci	items = 0;
31788c2ecf20Sopenharmony_ci	buf[items++] = cpu_to_le32(len);
31798c2ecf20Sopenharmony_ci	buf[items++] = cpu_to_le32(typdatum->value);
31808c2ecf20Sopenharmony_ci	if (p->policyvers >= POLICYDB_VERSION_BOUNDARY) {
31818c2ecf20Sopenharmony_ci		u32 properties = 0;
31828c2ecf20Sopenharmony_ci
31838c2ecf20Sopenharmony_ci		if (typdatum->primary)
31848c2ecf20Sopenharmony_ci			properties |= TYPEDATUM_PROPERTY_PRIMARY;
31858c2ecf20Sopenharmony_ci
31868c2ecf20Sopenharmony_ci		if (typdatum->attribute)
31878c2ecf20Sopenharmony_ci			properties |= TYPEDATUM_PROPERTY_ATTRIBUTE;
31888c2ecf20Sopenharmony_ci
31898c2ecf20Sopenharmony_ci		buf[items++] = cpu_to_le32(properties);
31908c2ecf20Sopenharmony_ci		buf[items++] = cpu_to_le32(typdatum->bounds);
31918c2ecf20Sopenharmony_ci	} else {
31928c2ecf20Sopenharmony_ci		buf[items++] = cpu_to_le32(typdatum->primary);
31938c2ecf20Sopenharmony_ci	}
31948c2ecf20Sopenharmony_ci	BUG_ON(items > ARRAY_SIZE(buf));
31958c2ecf20Sopenharmony_ci	rc = put_entry(buf, sizeof(u32), items, fp);
31968c2ecf20Sopenharmony_ci	if (rc)
31978c2ecf20Sopenharmony_ci		return rc;
31988c2ecf20Sopenharmony_ci
31998c2ecf20Sopenharmony_ci	rc = put_entry(key, 1, len, fp);
32008c2ecf20Sopenharmony_ci	if (rc)
32018c2ecf20Sopenharmony_ci		return rc;
32028c2ecf20Sopenharmony_ci
32038c2ecf20Sopenharmony_ci	return 0;
32048c2ecf20Sopenharmony_ci}
32058c2ecf20Sopenharmony_ci
32068c2ecf20Sopenharmony_cistatic int user_write(void *vkey, void *datum, void *ptr)
32078c2ecf20Sopenharmony_ci{
32088c2ecf20Sopenharmony_ci	char *key = vkey;
32098c2ecf20Sopenharmony_ci	struct user_datum *usrdatum = datum;
32108c2ecf20Sopenharmony_ci	struct policy_data *pd = ptr;
32118c2ecf20Sopenharmony_ci	struct policydb *p = pd->p;
32128c2ecf20Sopenharmony_ci	void *fp = pd->fp;
32138c2ecf20Sopenharmony_ci	__le32 buf[3];
32148c2ecf20Sopenharmony_ci	size_t items, len;
32158c2ecf20Sopenharmony_ci	int rc;
32168c2ecf20Sopenharmony_ci
32178c2ecf20Sopenharmony_ci	len = strlen(key);
32188c2ecf20Sopenharmony_ci	items = 0;
32198c2ecf20Sopenharmony_ci	buf[items++] = cpu_to_le32(len);
32208c2ecf20Sopenharmony_ci	buf[items++] = cpu_to_le32(usrdatum->value);
32218c2ecf20Sopenharmony_ci	if (p->policyvers >= POLICYDB_VERSION_BOUNDARY)
32228c2ecf20Sopenharmony_ci		buf[items++] = cpu_to_le32(usrdatum->bounds);
32238c2ecf20Sopenharmony_ci	BUG_ON(items > ARRAY_SIZE(buf));
32248c2ecf20Sopenharmony_ci	rc = put_entry(buf, sizeof(u32), items, fp);
32258c2ecf20Sopenharmony_ci	if (rc)
32268c2ecf20Sopenharmony_ci		return rc;
32278c2ecf20Sopenharmony_ci
32288c2ecf20Sopenharmony_ci	rc = put_entry(key, 1, len, fp);
32298c2ecf20Sopenharmony_ci	if (rc)
32308c2ecf20Sopenharmony_ci		return rc;
32318c2ecf20Sopenharmony_ci
32328c2ecf20Sopenharmony_ci	rc = ebitmap_write(&usrdatum->roles, fp);
32338c2ecf20Sopenharmony_ci	if (rc)
32348c2ecf20Sopenharmony_ci		return rc;
32358c2ecf20Sopenharmony_ci
32368c2ecf20Sopenharmony_ci	rc = mls_write_range_helper(&usrdatum->range, fp);
32378c2ecf20Sopenharmony_ci	if (rc)
32388c2ecf20Sopenharmony_ci		return rc;
32398c2ecf20Sopenharmony_ci
32408c2ecf20Sopenharmony_ci	rc = mls_write_level(&usrdatum->dfltlevel, fp);
32418c2ecf20Sopenharmony_ci	if (rc)
32428c2ecf20Sopenharmony_ci		return rc;
32438c2ecf20Sopenharmony_ci
32448c2ecf20Sopenharmony_ci	return 0;
32458c2ecf20Sopenharmony_ci}
32468c2ecf20Sopenharmony_ci
32478c2ecf20Sopenharmony_cistatic int (*write_f[SYM_NUM]) (void *key, void *datum,
32488c2ecf20Sopenharmony_ci				void *datap) =
32498c2ecf20Sopenharmony_ci{
32508c2ecf20Sopenharmony_ci	common_write,
32518c2ecf20Sopenharmony_ci	class_write,
32528c2ecf20Sopenharmony_ci	role_write,
32538c2ecf20Sopenharmony_ci	type_write,
32548c2ecf20Sopenharmony_ci	user_write,
32558c2ecf20Sopenharmony_ci	cond_write_bool,
32568c2ecf20Sopenharmony_ci	sens_write,
32578c2ecf20Sopenharmony_ci	cat_write,
32588c2ecf20Sopenharmony_ci};
32598c2ecf20Sopenharmony_ci
32608c2ecf20Sopenharmony_cistatic int ocontext_write(struct policydb *p, struct policydb_compat_info *info,
32618c2ecf20Sopenharmony_ci			  void *fp)
32628c2ecf20Sopenharmony_ci{
32638c2ecf20Sopenharmony_ci	unsigned int i, j, rc;
32648c2ecf20Sopenharmony_ci	size_t nel, len;
32658c2ecf20Sopenharmony_ci	__be64 prefixbuf[1];
32668c2ecf20Sopenharmony_ci	__le32 buf[3];
32678c2ecf20Sopenharmony_ci	u32 nodebuf[8];
32688c2ecf20Sopenharmony_ci	struct ocontext *c;
32698c2ecf20Sopenharmony_ci	for (i = 0; i < info->ocon_num; i++) {
32708c2ecf20Sopenharmony_ci		nel = 0;
32718c2ecf20Sopenharmony_ci		for (c = p->ocontexts[i]; c; c = c->next)
32728c2ecf20Sopenharmony_ci			nel++;
32738c2ecf20Sopenharmony_ci		buf[0] = cpu_to_le32(nel);
32748c2ecf20Sopenharmony_ci		rc = put_entry(buf, sizeof(u32), 1, fp);
32758c2ecf20Sopenharmony_ci		if (rc)
32768c2ecf20Sopenharmony_ci			return rc;
32778c2ecf20Sopenharmony_ci		for (c = p->ocontexts[i]; c; c = c->next) {
32788c2ecf20Sopenharmony_ci			switch (i) {
32798c2ecf20Sopenharmony_ci			case OCON_ISID:
32808c2ecf20Sopenharmony_ci				buf[0] = cpu_to_le32(c->sid[0]);
32818c2ecf20Sopenharmony_ci				rc = put_entry(buf, sizeof(u32), 1, fp);
32828c2ecf20Sopenharmony_ci				if (rc)
32838c2ecf20Sopenharmony_ci					return rc;
32848c2ecf20Sopenharmony_ci				rc = context_write(p, &c->context[0], fp);
32858c2ecf20Sopenharmony_ci				if (rc)
32868c2ecf20Sopenharmony_ci					return rc;
32878c2ecf20Sopenharmony_ci				break;
32888c2ecf20Sopenharmony_ci			case OCON_FS:
32898c2ecf20Sopenharmony_ci			case OCON_NETIF:
32908c2ecf20Sopenharmony_ci				len = strlen(c->u.name);
32918c2ecf20Sopenharmony_ci				buf[0] = cpu_to_le32(len);
32928c2ecf20Sopenharmony_ci				rc = put_entry(buf, sizeof(u32), 1, fp);
32938c2ecf20Sopenharmony_ci				if (rc)
32948c2ecf20Sopenharmony_ci					return rc;
32958c2ecf20Sopenharmony_ci				rc = put_entry(c->u.name, 1, len, fp);
32968c2ecf20Sopenharmony_ci				if (rc)
32978c2ecf20Sopenharmony_ci					return rc;
32988c2ecf20Sopenharmony_ci				rc = context_write(p, &c->context[0], fp);
32998c2ecf20Sopenharmony_ci				if (rc)
33008c2ecf20Sopenharmony_ci					return rc;
33018c2ecf20Sopenharmony_ci				rc = context_write(p, &c->context[1], fp);
33028c2ecf20Sopenharmony_ci				if (rc)
33038c2ecf20Sopenharmony_ci					return rc;
33048c2ecf20Sopenharmony_ci				break;
33058c2ecf20Sopenharmony_ci			case OCON_PORT:
33068c2ecf20Sopenharmony_ci				buf[0] = cpu_to_le32(c->u.port.protocol);
33078c2ecf20Sopenharmony_ci				buf[1] = cpu_to_le32(c->u.port.low_port);
33088c2ecf20Sopenharmony_ci				buf[2] = cpu_to_le32(c->u.port.high_port);
33098c2ecf20Sopenharmony_ci				rc = put_entry(buf, sizeof(u32), 3, fp);
33108c2ecf20Sopenharmony_ci				if (rc)
33118c2ecf20Sopenharmony_ci					return rc;
33128c2ecf20Sopenharmony_ci				rc = context_write(p, &c->context[0], fp);
33138c2ecf20Sopenharmony_ci				if (rc)
33148c2ecf20Sopenharmony_ci					return rc;
33158c2ecf20Sopenharmony_ci				break;
33168c2ecf20Sopenharmony_ci			case OCON_NODE:
33178c2ecf20Sopenharmony_ci				nodebuf[0] = c->u.node.addr; /* network order */
33188c2ecf20Sopenharmony_ci				nodebuf[1] = c->u.node.mask; /* network order */
33198c2ecf20Sopenharmony_ci				rc = put_entry(nodebuf, sizeof(u32), 2, fp);
33208c2ecf20Sopenharmony_ci				if (rc)
33218c2ecf20Sopenharmony_ci					return rc;
33228c2ecf20Sopenharmony_ci				rc = context_write(p, &c->context[0], fp);
33238c2ecf20Sopenharmony_ci				if (rc)
33248c2ecf20Sopenharmony_ci					return rc;
33258c2ecf20Sopenharmony_ci				break;
33268c2ecf20Sopenharmony_ci			case OCON_FSUSE:
33278c2ecf20Sopenharmony_ci				buf[0] = cpu_to_le32(c->v.behavior);
33288c2ecf20Sopenharmony_ci				len = strlen(c->u.name);
33298c2ecf20Sopenharmony_ci				buf[1] = cpu_to_le32(len);
33308c2ecf20Sopenharmony_ci				rc = put_entry(buf, sizeof(u32), 2, fp);
33318c2ecf20Sopenharmony_ci				if (rc)
33328c2ecf20Sopenharmony_ci					return rc;
33338c2ecf20Sopenharmony_ci				rc = put_entry(c->u.name, 1, len, fp);
33348c2ecf20Sopenharmony_ci				if (rc)
33358c2ecf20Sopenharmony_ci					return rc;
33368c2ecf20Sopenharmony_ci				rc = context_write(p, &c->context[0], fp);
33378c2ecf20Sopenharmony_ci				if (rc)
33388c2ecf20Sopenharmony_ci					return rc;
33398c2ecf20Sopenharmony_ci				break;
33408c2ecf20Sopenharmony_ci			case OCON_NODE6:
33418c2ecf20Sopenharmony_ci				for (j = 0; j < 4; j++)
33428c2ecf20Sopenharmony_ci					nodebuf[j] = c->u.node6.addr[j]; /* network order */
33438c2ecf20Sopenharmony_ci				for (j = 0; j < 4; j++)
33448c2ecf20Sopenharmony_ci					nodebuf[j + 4] = c->u.node6.mask[j]; /* network order */
33458c2ecf20Sopenharmony_ci				rc = put_entry(nodebuf, sizeof(u32), 8, fp);
33468c2ecf20Sopenharmony_ci				if (rc)
33478c2ecf20Sopenharmony_ci					return rc;
33488c2ecf20Sopenharmony_ci				rc = context_write(p, &c->context[0], fp);
33498c2ecf20Sopenharmony_ci				if (rc)
33508c2ecf20Sopenharmony_ci					return rc;
33518c2ecf20Sopenharmony_ci				break;
33528c2ecf20Sopenharmony_ci			case OCON_IBPKEY:
33538c2ecf20Sopenharmony_ci				/* subnet_prefix is in CPU order */
33548c2ecf20Sopenharmony_ci				prefixbuf[0] = cpu_to_be64(c->u.ibpkey.subnet_prefix);
33558c2ecf20Sopenharmony_ci
33568c2ecf20Sopenharmony_ci				rc = put_entry(prefixbuf, sizeof(u64), 1, fp);
33578c2ecf20Sopenharmony_ci				if (rc)
33588c2ecf20Sopenharmony_ci					return rc;
33598c2ecf20Sopenharmony_ci
33608c2ecf20Sopenharmony_ci				buf[0] = cpu_to_le32(c->u.ibpkey.low_pkey);
33618c2ecf20Sopenharmony_ci				buf[1] = cpu_to_le32(c->u.ibpkey.high_pkey);
33628c2ecf20Sopenharmony_ci
33638c2ecf20Sopenharmony_ci				rc = put_entry(buf, sizeof(u32), 2, fp);
33648c2ecf20Sopenharmony_ci				if (rc)
33658c2ecf20Sopenharmony_ci					return rc;
33668c2ecf20Sopenharmony_ci				rc = context_write(p, &c->context[0], fp);
33678c2ecf20Sopenharmony_ci				if (rc)
33688c2ecf20Sopenharmony_ci					return rc;
33698c2ecf20Sopenharmony_ci				break;
33708c2ecf20Sopenharmony_ci			case OCON_IBENDPORT:
33718c2ecf20Sopenharmony_ci				len = strlen(c->u.ibendport.dev_name);
33728c2ecf20Sopenharmony_ci				buf[0] = cpu_to_le32(len);
33738c2ecf20Sopenharmony_ci				buf[1] = cpu_to_le32(c->u.ibendport.port);
33748c2ecf20Sopenharmony_ci				rc = put_entry(buf, sizeof(u32), 2, fp);
33758c2ecf20Sopenharmony_ci				if (rc)
33768c2ecf20Sopenharmony_ci					return rc;
33778c2ecf20Sopenharmony_ci				rc = put_entry(c->u.ibendport.dev_name, 1, len, fp);
33788c2ecf20Sopenharmony_ci				if (rc)
33798c2ecf20Sopenharmony_ci					return rc;
33808c2ecf20Sopenharmony_ci				rc = context_write(p, &c->context[0], fp);
33818c2ecf20Sopenharmony_ci				if (rc)
33828c2ecf20Sopenharmony_ci					return rc;
33838c2ecf20Sopenharmony_ci				break;
33848c2ecf20Sopenharmony_ci			}
33858c2ecf20Sopenharmony_ci		}
33868c2ecf20Sopenharmony_ci	}
33878c2ecf20Sopenharmony_ci	return 0;
33888c2ecf20Sopenharmony_ci}
33898c2ecf20Sopenharmony_ci
33908c2ecf20Sopenharmony_cistatic int genfs_write(struct policydb *p, void *fp)
33918c2ecf20Sopenharmony_ci{
33928c2ecf20Sopenharmony_ci	struct genfs *genfs;
33938c2ecf20Sopenharmony_ci	struct ocontext *c;
33948c2ecf20Sopenharmony_ci	size_t len;
33958c2ecf20Sopenharmony_ci	__le32 buf[1];
33968c2ecf20Sopenharmony_ci	int rc;
33978c2ecf20Sopenharmony_ci
33988c2ecf20Sopenharmony_ci	len = 0;
33998c2ecf20Sopenharmony_ci	for (genfs = p->genfs; genfs; genfs = genfs->next)
34008c2ecf20Sopenharmony_ci		len++;
34018c2ecf20Sopenharmony_ci	buf[0] = cpu_to_le32(len);
34028c2ecf20Sopenharmony_ci	rc = put_entry(buf, sizeof(u32), 1, fp);
34038c2ecf20Sopenharmony_ci	if (rc)
34048c2ecf20Sopenharmony_ci		return rc;
34058c2ecf20Sopenharmony_ci	for (genfs = p->genfs; genfs; genfs = genfs->next) {
34068c2ecf20Sopenharmony_ci		len = strlen(genfs->fstype);
34078c2ecf20Sopenharmony_ci		buf[0] = cpu_to_le32(len);
34088c2ecf20Sopenharmony_ci		rc = put_entry(buf, sizeof(u32), 1, fp);
34098c2ecf20Sopenharmony_ci		if (rc)
34108c2ecf20Sopenharmony_ci			return rc;
34118c2ecf20Sopenharmony_ci		rc = put_entry(genfs->fstype, 1, len, fp);
34128c2ecf20Sopenharmony_ci		if (rc)
34138c2ecf20Sopenharmony_ci			return rc;
34148c2ecf20Sopenharmony_ci		len = 0;
34158c2ecf20Sopenharmony_ci		for (c = genfs->head; c; c = c->next)
34168c2ecf20Sopenharmony_ci			len++;
34178c2ecf20Sopenharmony_ci		buf[0] = cpu_to_le32(len);
34188c2ecf20Sopenharmony_ci		rc = put_entry(buf, sizeof(u32), 1, fp);
34198c2ecf20Sopenharmony_ci		if (rc)
34208c2ecf20Sopenharmony_ci			return rc;
34218c2ecf20Sopenharmony_ci		for (c = genfs->head; c; c = c->next) {
34228c2ecf20Sopenharmony_ci			len = strlen(c->u.name);
34238c2ecf20Sopenharmony_ci			buf[0] = cpu_to_le32(len);
34248c2ecf20Sopenharmony_ci			rc = put_entry(buf, sizeof(u32), 1, fp);
34258c2ecf20Sopenharmony_ci			if (rc)
34268c2ecf20Sopenharmony_ci				return rc;
34278c2ecf20Sopenharmony_ci			rc = put_entry(c->u.name, 1, len, fp);
34288c2ecf20Sopenharmony_ci			if (rc)
34298c2ecf20Sopenharmony_ci				return rc;
34308c2ecf20Sopenharmony_ci			buf[0] = cpu_to_le32(c->v.sclass);
34318c2ecf20Sopenharmony_ci			rc = put_entry(buf, sizeof(u32), 1, fp);
34328c2ecf20Sopenharmony_ci			if (rc)
34338c2ecf20Sopenharmony_ci				return rc;
34348c2ecf20Sopenharmony_ci			rc = context_write(p, &c->context[0], fp);
34358c2ecf20Sopenharmony_ci			if (rc)
34368c2ecf20Sopenharmony_ci				return rc;
34378c2ecf20Sopenharmony_ci		}
34388c2ecf20Sopenharmony_ci	}
34398c2ecf20Sopenharmony_ci	return 0;
34408c2ecf20Sopenharmony_ci}
34418c2ecf20Sopenharmony_ci
34428c2ecf20Sopenharmony_cistatic int range_write_helper(void *key, void *data, void *ptr)
34438c2ecf20Sopenharmony_ci{
34448c2ecf20Sopenharmony_ci	__le32 buf[2];
34458c2ecf20Sopenharmony_ci	struct range_trans *rt = key;
34468c2ecf20Sopenharmony_ci	struct mls_range *r = data;
34478c2ecf20Sopenharmony_ci	struct policy_data *pd = ptr;
34488c2ecf20Sopenharmony_ci	void *fp = pd->fp;
34498c2ecf20Sopenharmony_ci	struct policydb *p = pd->p;
34508c2ecf20Sopenharmony_ci	int rc;
34518c2ecf20Sopenharmony_ci
34528c2ecf20Sopenharmony_ci	buf[0] = cpu_to_le32(rt->source_type);
34538c2ecf20Sopenharmony_ci	buf[1] = cpu_to_le32(rt->target_type);
34548c2ecf20Sopenharmony_ci	rc = put_entry(buf, sizeof(u32), 2, fp);
34558c2ecf20Sopenharmony_ci	if (rc)
34568c2ecf20Sopenharmony_ci		return rc;
34578c2ecf20Sopenharmony_ci	if (p->policyvers >= POLICYDB_VERSION_RANGETRANS) {
34588c2ecf20Sopenharmony_ci		buf[0] = cpu_to_le32(rt->target_class);
34598c2ecf20Sopenharmony_ci		rc = put_entry(buf, sizeof(u32), 1, fp);
34608c2ecf20Sopenharmony_ci		if (rc)
34618c2ecf20Sopenharmony_ci			return rc;
34628c2ecf20Sopenharmony_ci	}
34638c2ecf20Sopenharmony_ci	rc = mls_write_range_helper(r, fp);
34648c2ecf20Sopenharmony_ci	if (rc)
34658c2ecf20Sopenharmony_ci		return rc;
34668c2ecf20Sopenharmony_ci
34678c2ecf20Sopenharmony_ci	return 0;
34688c2ecf20Sopenharmony_ci}
34698c2ecf20Sopenharmony_ci
34708c2ecf20Sopenharmony_cistatic int range_write(struct policydb *p, void *fp)
34718c2ecf20Sopenharmony_ci{
34728c2ecf20Sopenharmony_ci	__le32 buf[1];
34738c2ecf20Sopenharmony_ci	int rc;
34748c2ecf20Sopenharmony_ci	struct policy_data pd;
34758c2ecf20Sopenharmony_ci
34768c2ecf20Sopenharmony_ci	pd.p = p;
34778c2ecf20Sopenharmony_ci	pd.fp = fp;
34788c2ecf20Sopenharmony_ci
34798c2ecf20Sopenharmony_ci	buf[0] = cpu_to_le32(p->range_tr.nel);
34808c2ecf20Sopenharmony_ci	rc = put_entry(buf, sizeof(u32), 1, fp);
34818c2ecf20Sopenharmony_ci	if (rc)
34828c2ecf20Sopenharmony_ci		return rc;
34838c2ecf20Sopenharmony_ci
34848c2ecf20Sopenharmony_ci	/* actually write all of the entries */
34858c2ecf20Sopenharmony_ci	rc = hashtab_map(&p->range_tr, range_write_helper, &pd);
34868c2ecf20Sopenharmony_ci	if (rc)
34878c2ecf20Sopenharmony_ci		return rc;
34888c2ecf20Sopenharmony_ci
34898c2ecf20Sopenharmony_ci	return 0;
34908c2ecf20Sopenharmony_ci}
34918c2ecf20Sopenharmony_ci
34928c2ecf20Sopenharmony_cistatic int filename_write_helper_compat(void *key, void *data, void *ptr)
34938c2ecf20Sopenharmony_ci{
34948c2ecf20Sopenharmony_ci	struct filename_trans_key *ft = key;
34958c2ecf20Sopenharmony_ci	struct filename_trans_datum *datum = data;
34968c2ecf20Sopenharmony_ci	struct ebitmap_node *node;
34978c2ecf20Sopenharmony_ci	void *fp = ptr;
34988c2ecf20Sopenharmony_ci	__le32 buf[4];
34998c2ecf20Sopenharmony_ci	int rc;
35008c2ecf20Sopenharmony_ci	u32 bit, len = strlen(ft->name);
35018c2ecf20Sopenharmony_ci
35028c2ecf20Sopenharmony_ci	do {
35038c2ecf20Sopenharmony_ci		ebitmap_for_each_positive_bit(&datum->stypes, node, bit) {
35048c2ecf20Sopenharmony_ci			buf[0] = cpu_to_le32(len);
35058c2ecf20Sopenharmony_ci			rc = put_entry(buf, sizeof(u32), 1, fp);
35068c2ecf20Sopenharmony_ci			if (rc)
35078c2ecf20Sopenharmony_ci				return rc;
35088c2ecf20Sopenharmony_ci
35098c2ecf20Sopenharmony_ci			rc = put_entry(ft->name, sizeof(char), len, fp);
35108c2ecf20Sopenharmony_ci			if (rc)
35118c2ecf20Sopenharmony_ci				return rc;
35128c2ecf20Sopenharmony_ci
35138c2ecf20Sopenharmony_ci			buf[0] = cpu_to_le32(bit + 1);
35148c2ecf20Sopenharmony_ci			buf[1] = cpu_to_le32(ft->ttype);
35158c2ecf20Sopenharmony_ci			buf[2] = cpu_to_le32(ft->tclass);
35168c2ecf20Sopenharmony_ci			buf[3] = cpu_to_le32(datum->otype);
35178c2ecf20Sopenharmony_ci
35188c2ecf20Sopenharmony_ci			rc = put_entry(buf, sizeof(u32), 4, fp);
35198c2ecf20Sopenharmony_ci			if (rc)
35208c2ecf20Sopenharmony_ci				return rc;
35218c2ecf20Sopenharmony_ci		}
35228c2ecf20Sopenharmony_ci
35238c2ecf20Sopenharmony_ci		datum = datum->next;
35248c2ecf20Sopenharmony_ci	} while (unlikely(datum));
35258c2ecf20Sopenharmony_ci
35268c2ecf20Sopenharmony_ci	return 0;
35278c2ecf20Sopenharmony_ci}
35288c2ecf20Sopenharmony_ci
35298c2ecf20Sopenharmony_cistatic int filename_write_helper(void *key, void *data, void *ptr)
35308c2ecf20Sopenharmony_ci{
35318c2ecf20Sopenharmony_ci	struct filename_trans_key *ft = key;
35328c2ecf20Sopenharmony_ci	struct filename_trans_datum *datum;
35338c2ecf20Sopenharmony_ci	void *fp = ptr;
35348c2ecf20Sopenharmony_ci	__le32 buf[3];
35358c2ecf20Sopenharmony_ci	int rc;
35368c2ecf20Sopenharmony_ci	u32 ndatum, len = strlen(ft->name);
35378c2ecf20Sopenharmony_ci
35388c2ecf20Sopenharmony_ci	buf[0] = cpu_to_le32(len);
35398c2ecf20Sopenharmony_ci	rc = put_entry(buf, sizeof(u32), 1, fp);
35408c2ecf20Sopenharmony_ci	if (rc)
35418c2ecf20Sopenharmony_ci		return rc;
35428c2ecf20Sopenharmony_ci
35438c2ecf20Sopenharmony_ci	rc = put_entry(ft->name, sizeof(char), len, fp);
35448c2ecf20Sopenharmony_ci	if (rc)
35458c2ecf20Sopenharmony_ci		return rc;
35468c2ecf20Sopenharmony_ci
35478c2ecf20Sopenharmony_ci	ndatum = 0;
35488c2ecf20Sopenharmony_ci	datum = data;
35498c2ecf20Sopenharmony_ci	do {
35508c2ecf20Sopenharmony_ci		ndatum++;
35518c2ecf20Sopenharmony_ci		datum = datum->next;
35528c2ecf20Sopenharmony_ci	} while (unlikely(datum));
35538c2ecf20Sopenharmony_ci
35548c2ecf20Sopenharmony_ci	buf[0] = cpu_to_le32(ft->ttype);
35558c2ecf20Sopenharmony_ci	buf[1] = cpu_to_le32(ft->tclass);
35568c2ecf20Sopenharmony_ci	buf[2] = cpu_to_le32(ndatum);
35578c2ecf20Sopenharmony_ci	rc = put_entry(buf, sizeof(u32), 3, fp);
35588c2ecf20Sopenharmony_ci	if (rc)
35598c2ecf20Sopenharmony_ci		return rc;
35608c2ecf20Sopenharmony_ci
35618c2ecf20Sopenharmony_ci	datum = data;
35628c2ecf20Sopenharmony_ci	do {
35638c2ecf20Sopenharmony_ci		rc = ebitmap_write(&datum->stypes, fp);
35648c2ecf20Sopenharmony_ci		if (rc)
35658c2ecf20Sopenharmony_ci			return rc;
35668c2ecf20Sopenharmony_ci
35678c2ecf20Sopenharmony_ci		buf[0] = cpu_to_le32(datum->otype);
35688c2ecf20Sopenharmony_ci		rc = put_entry(buf, sizeof(u32), 1, fp);
35698c2ecf20Sopenharmony_ci		if (rc)
35708c2ecf20Sopenharmony_ci			return rc;
35718c2ecf20Sopenharmony_ci
35728c2ecf20Sopenharmony_ci		datum = datum->next;
35738c2ecf20Sopenharmony_ci	} while (unlikely(datum));
35748c2ecf20Sopenharmony_ci
35758c2ecf20Sopenharmony_ci	return 0;
35768c2ecf20Sopenharmony_ci}
35778c2ecf20Sopenharmony_ci
35788c2ecf20Sopenharmony_cistatic int filename_trans_write(struct policydb *p, void *fp)
35798c2ecf20Sopenharmony_ci{
35808c2ecf20Sopenharmony_ci	__le32 buf[1];
35818c2ecf20Sopenharmony_ci	int rc;
35828c2ecf20Sopenharmony_ci
35838c2ecf20Sopenharmony_ci	if (p->policyvers < POLICYDB_VERSION_FILENAME_TRANS)
35848c2ecf20Sopenharmony_ci		return 0;
35858c2ecf20Sopenharmony_ci
35868c2ecf20Sopenharmony_ci	if (p->policyvers < POLICYDB_VERSION_COMP_FTRANS) {
35878c2ecf20Sopenharmony_ci		buf[0] = cpu_to_le32(p->compat_filename_trans_count);
35888c2ecf20Sopenharmony_ci		rc = put_entry(buf, sizeof(u32), 1, fp);
35898c2ecf20Sopenharmony_ci		if (rc)
35908c2ecf20Sopenharmony_ci			return rc;
35918c2ecf20Sopenharmony_ci
35928c2ecf20Sopenharmony_ci		rc = hashtab_map(&p->filename_trans,
35938c2ecf20Sopenharmony_ci				 filename_write_helper_compat, fp);
35948c2ecf20Sopenharmony_ci	} else {
35958c2ecf20Sopenharmony_ci		buf[0] = cpu_to_le32(p->filename_trans.nel);
35968c2ecf20Sopenharmony_ci		rc = put_entry(buf, sizeof(u32), 1, fp);
35978c2ecf20Sopenharmony_ci		if (rc)
35988c2ecf20Sopenharmony_ci			return rc;
35998c2ecf20Sopenharmony_ci
36008c2ecf20Sopenharmony_ci		rc = hashtab_map(&p->filename_trans, filename_write_helper, fp);
36018c2ecf20Sopenharmony_ci	}
36028c2ecf20Sopenharmony_ci	return rc;
36038c2ecf20Sopenharmony_ci}
36048c2ecf20Sopenharmony_ci
36058c2ecf20Sopenharmony_ci/*
36068c2ecf20Sopenharmony_ci * Write the configuration data in a policy database
36078c2ecf20Sopenharmony_ci * structure to a policy database binary representation
36088c2ecf20Sopenharmony_ci * file.
36098c2ecf20Sopenharmony_ci */
36108c2ecf20Sopenharmony_ciint policydb_write(struct policydb *p, void *fp)
36118c2ecf20Sopenharmony_ci{
36128c2ecf20Sopenharmony_ci	unsigned int i, num_syms;
36138c2ecf20Sopenharmony_ci	int rc;
36148c2ecf20Sopenharmony_ci	__le32 buf[4];
36158c2ecf20Sopenharmony_ci	u32 config;
36168c2ecf20Sopenharmony_ci	size_t len;
36178c2ecf20Sopenharmony_ci	struct policydb_compat_info *info;
36188c2ecf20Sopenharmony_ci
36198c2ecf20Sopenharmony_ci	/*
36208c2ecf20Sopenharmony_ci	 * refuse to write policy older than compressed avtab
36218c2ecf20Sopenharmony_ci	 * to simplify the writer.  There are other tests dropped
36228c2ecf20Sopenharmony_ci	 * since we assume this throughout the writer code.  Be
36238c2ecf20Sopenharmony_ci	 * careful if you ever try to remove this restriction
36248c2ecf20Sopenharmony_ci	 */
36258c2ecf20Sopenharmony_ci	if (p->policyvers < POLICYDB_VERSION_AVTAB) {
36268c2ecf20Sopenharmony_ci		pr_err("SELinux: refusing to write policy version %d."
36278c2ecf20Sopenharmony_ci		       "  Because it is less than version %d\n", p->policyvers,
36288c2ecf20Sopenharmony_ci		       POLICYDB_VERSION_AVTAB);
36298c2ecf20Sopenharmony_ci		return -EINVAL;
36308c2ecf20Sopenharmony_ci	}
36318c2ecf20Sopenharmony_ci
36328c2ecf20Sopenharmony_ci	config = 0;
36338c2ecf20Sopenharmony_ci	if (p->mls_enabled)
36348c2ecf20Sopenharmony_ci		config |= POLICYDB_CONFIG_MLS;
36358c2ecf20Sopenharmony_ci
36368c2ecf20Sopenharmony_ci	if (p->reject_unknown)
36378c2ecf20Sopenharmony_ci		config |= REJECT_UNKNOWN;
36388c2ecf20Sopenharmony_ci	if (p->allow_unknown)
36398c2ecf20Sopenharmony_ci		config |= ALLOW_UNKNOWN;
36408c2ecf20Sopenharmony_ci
36418c2ecf20Sopenharmony_ci	/* Write the magic number and string identifiers. */
36428c2ecf20Sopenharmony_ci	buf[0] = cpu_to_le32(POLICYDB_MAGIC);
36438c2ecf20Sopenharmony_ci	len = strlen(POLICYDB_STRING);
36448c2ecf20Sopenharmony_ci	buf[1] = cpu_to_le32(len);
36458c2ecf20Sopenharmony_ci	rc = put_entry(buf, sizeof(u32), 2, fp);
36468c2ecf20Sopenharmony_ci	if (rc)
36478c2ecf20Sopenharmony_ci		return rc;
36488c2ecf20Sopenharmony_ci	rc = put_entry(POLICYDB_STRING, 1, len, fp);
36498c2ecf20Sopenharmony_ci	if (rc)
36508c2ecf20Sopenharmony_ci		return rc;
36518c2ecf20Sopenharmony_ci
36528c2ecf20Sopenharmony_ci	/* Write the version, config, and table sizes. */
36538c2ecf20Sopenharmony_ci	info = policydb_lookup_compat(p->policyvers);
36548c2ecf20Sopenharmony_ci	if (!info) {
36558c2ecf20Sopenharmony_ci		pr_err("SELinux: compatibility lookup failed for policy "
36568c2ecf20Sopenharmony_ci		    "version %d", p->policyvers);
36578c2ecf20Sopenharmony_ci		return -EINVAL;
36588c2ecf20Sopenharmony_ci	}
36598c2ecf20Sopenharmony_ci
36608c2ecf20Sopenharmony_ci	buf[0] = cpu_to_le32(p->policyvers);
36618c2ecf20Sopenharmony_ci	buf[1] = cpu_to_le32(config);
36628c2ecf20Sopenharmony_ci	buf[2] = cpu_to_le32(info->sym_num);
36638c2ecf20Sopenharmony_ci	buf[3] = cpu_to_le32(info->ocon_num);
36648c2ecf20Sopenharmony_ci
36658c2ecf20Sopenharmony_ci	rc = put_entry(buf, sizeof(u32), 4, fp);
36668c2ecf20Sopenharmony_ci	if (rc)
36678c2ecf20Sopenharmony_ci		return rc;
36688c2ecf20Sopenharmony_ci
36698c2ecf20Sopenharmony_ci	if (p->policyvers >= POLICYDB_VERSION_POLCAP) {
36708c2ecf20Sopenharmony_ci		rc = ebitmap_write(&p->policycaps, fp);
36718c2ecf20Sopenharmony_ci		if (rc)
36728c2ecf20Sopenharmony_ci			return rc;
36738c2ecf20Sopenharmony_ci	}
36748c2ecf20Sopenharmony_ci
36758c2ecf20Sopenharmony_ci	if (p->policyvers >= POLICYDB_VERSION_PERMISSIVE) {
36768c2ecf20Sopenharmony_ci		rc = ebitmap_write(&p->permissive_map, fp);
36778c2ecf20Sopenharmony_ci		if (rc)
36788c2ecf20Sopenharmony_ci			return rc;
36798c2ecf20Sopenharmony_ci	}
36808c2ecf20Sopenharmony_ci
36818c2ecf20Sopenharmony_ci	num_syms = info->sym_num;
36828c2ecf20Sopenharmony_ci	for (i = 0; i < num_syms; i++) {
36838c2ecf20Sopenharmony_ci		struct policy_data pd;
36848c2ecf20Sopenharmony_ci
36858c2ecf20Sopenharmony_ci		pd.fp = fp;
36868c2ecf20Sopenharmony_ci		pd.p = p;
36878c2ecf20Sopenharmony_ci
36888c2ecf20Sopenharmony_ci		buf[0] = cpu_to_le32(p->symtab[i].nprim);
36898c2ecf20Sopenharmony_ci		buf[1] = cpu_to_le32(p->symtab[i].table.nel);
36908c2ecf20Sopenharmony_ci
36918c2ecf20Sopenharmony_ci		rc = put_entry(buf, sizeof(u32), 2, fp);
36928c2ecf20Sopenharmony_ci		if (rc)
36938c2ecf20Sopenharmony_ci			return rc;
36948c2ecf20Sopenharmony_ci		rc = hashtab_map(&p->symtab[i].table, write_f[i], &pd);
36958c2ecf20Sopenharmony_ci		if (rc)
36968c2ecf20Sopenharmony_ci			return rc;
36978c2ecf20Sopenharmony_ci	}
36988c2ecf20Sopenharmony_ci
36998c2ecf20Sopenharmony_ci	rc = avtab_write(p, &p->te_avtab, fp);
37008c2ecf20Sopenharmony_ci	if (rc)
37018c2ecf20Sopenharmony_ci		return rc;
37028c2ecf20Sopenharmony_ci
37038c2ecf20Sopenharmony_ci	rc = cond_write_list(p, fp);
37048c2ecf20Sopenharmony_ci	if (rc)
37058c2ecf20Sopenharmony_ci		return rc;
37068c2ecf20Sopenharmony_ci
37078c2ecf20Sopenharmony_ci	rc = role_trans_write(p, fp);
37088c2ecf20Sopenharmony_ci	if (rc)
37098c2ecf20Sopenharmony_ci		return rc;
37108c2ecf20Sopenharmony_ci
37118c2ecf20Sopenharmony_ci	rc = role_allow_write(p->role_allow, fp);
37128c2ecf20Sopenharmony_ci	if (rc)
37138c2ecf20Sopenharmony_ci		return rc;
37148c2ecf20Sopenharmony_ci
37158c2ecf20Sopenharmony_ci	rc = filename_trans_write(p, fp);
37168c2ecf20Sopenharmony_ci	if (rc)
37178c2ecf20Sopenharmony_ci		return rc;
37188c2ecf20Sopenharmony_ci
37198c2ecf20Sopenharmony_ci	rc = ocontext_write(p, info, fp);
37208c2ecf20Sopenharmony_ci	if (rc)
37218c2ecf20Sopenharmony_ci		return rc;
37228c2ecf20Sopenharmony_ci
37238c2ecf20Sopenharmony_ci	rc = genfs_write(p, fp);
37248c2ecf20Sopenharmony_ci	if (rc)
37258c2ecf20Sopenharmony_ci		return rc;
37268c2ecf20Sopenharmony_ci
37278c2ecf20Sopenharmony_ci	rc = range_write(p, fp);
37288c2ecf20Sopenharmony_ci	if (rc)
37298c2ecf20Sopenharmony_ci		return rc;
37308c2ecf20Sopenharmony_ci
37318c2ecf20Sopenharmony_ci	for (i = 0; i < p->p_types.nprim; i++) {
37328c2ecf20Sopenharmony_ci		struct ebitmap *e = &p->type_attr_map_array[i];
37338c2ecf20Sopenharmony_ci
37348c2ecf20Sopenharmony_ci		rc = ebitmap_write(e, fp);
37358c2ecf20Sopenharmony_ci		if (rc)
37368c2ecf20Sopenharmony_ci			return rc;
37378c2ecf20Sopenharmony_ci	}
37388c2ecf20Sopenharmony_ci
37398c2ecf20Sopenharmony_ci	return 0;
37408c2ecf20Sopenharmony_ci}
3741