xref: /third_party/selinux/libsepol/src/ibpkeys.c (revision 6cd6a6ac)
16cd6a6acSopenharmony_ci#include <netinet/in.h>
26cd6a6acSopenharmony_ci#include <stdlib.h>
36cd6a6acSopenharmony_ci#include <inttypes.h>
46cd6a6acSopenharmony_ci
56cd6a6acSopenharmony_ci#include "debug.h"
66cd6a6acSopenharmony_ci#include "context.h"
76cd6a6acSopenharmony_ci#include "handle.h"
86cd6a6acSopenharmony_ci
96cd6a6acSopenharmony_ci#include <sepol/ibpkey_record.h>
106cd6a6acSopenharmony_ci#include <sepol/policydb/policydb.h>
116cd6a6acSopenharmony_ci#include "ibpkey_internal.h"
126cd6a6acSopenharmony_ci
136cd6a6acSopenharmony_ci/* Create a low level ibpkey structure from
146cd6a6acSopenharmony_ci * a high level representation
156cd6a6acSopenharmony_ci */
166cd6a6acSopenharmony_cistatic int ibpkey_from_record(sepol_handle_t *handle,
176cd6a6acSopenharmony_ci			      const policydb_t *policydb,
186cd6a6acSopenharmony_ci			      ocontext_t **ibpkey, const sepol_ibpkey_t *data)
196cd6a6acSopenharmony_ci{
206cd6a6acSopenharmony_ci	ocontext_t *tmp_ibpkey = NULL;
216cd6a6acSopenharmony_ci	context_struct_t *tmp_con = NULL;
226cd6a6acSopenharmony_ci	char *subnet_prefix_buf = NULL;
236cd6a6acSopenharmony_ci	int low = sepol_ibpkey_get_low(data);
246cd6a6acSopenharmony_ci	int high = sepol_ibpkey_get_high(data);
256cd6a6acSopenharmony_ci
266cd6a6acSopenharmony_ci	tmp_ibpkey = (ocontext_t *)calloc(1, sizeof(*tmp_ibpkey));
276cd6a6acSopenharmony_ci	if (!tmp_ibpkey)
286cd6a6acSopenharmony_ci		goto omem;
296cd6a6acSopenharmony_ci
306cd6a6acSopenharmony_ci	tmp_ibpkey->u.ibpkey.subnet_prefix = sepol_ibpkey_get_subnet_prefix_bytes(data);
316cd6a6acSopenharmony_ci
326cd6a6acSopenharmony_ci	/* Pkey range */
336cd6a6acSopenharmony_ci	tmp_ibpkey->u.ibpkey.low_pkey = low;
346cd6a6acSopenharmony_ci	tmp_ibpkey->u.ibpkey.high_pkey = high;
356cd6a6acSopenharmony_ci	if (tmp_ibpkey->u.ibpkey.low_pkey > tmp_ibpkey->u.ibpkey.high_pkey) {
366cd6a6acSopenharmony_ci		ERR(handle, "low ibpkey %d exceeds high ibpkey %d",
376cd6a6acSopenharmony_ci		    tmp_ibpkey->u.ibpkey.low_pkey, tmp_ibpkey->u.ibpkey.high_pkey);
386cd6a6acSopenharmony_ci		goto err;
396cd6a6acSopenharmony_ci	}
406cd6a6acSopenharmony_ci
416cd6a6acSopenharmony_ci	/* Context */
426cd6a6acSopenharmony_ci	if (context_from_record(handle, policydb, &tmp_con,
436cd6a6acSopenharmony_ci				sepol_ibpkey_get_con(data)) < 0)
446cd6a6acSopenharmony_ci		goto err;
456cd6a6acSopenharmony_ci	context_cpy(&tmp_ibpkey->context[0], tmp_con);
466cd6a6acSopenharmony_ci	context_destroy(tmp_con);
476cd6a6acSopenharmony_ci	free(tmp_con);
486cd6a6acSopenharmony_ci	tmp_con = NULL;
496cd6a6acSopenharmony_ci
506cd6a6acSopenharmony_ci	*ibpkey = tmp_ibpkey;
516cd6a6acSopenharmony_ci	return STATUS_SUCCESS;
526cd6a6acSopenharmony_ci
536cd6a6acSopenharmony_ciomem:
546cd6a6acSopenharmony_ci	ERR(handle, "out of memory");
556cd6a6acSopenharmony_ci
566cd6a6acSopenharmony_cierr:
576cd6a6acSopenharmony_ci	if (tmp_ibpkey) {
586cd6a6acSopenharmony_ci		context_destroy(&tmp_ibpkey->context[0]);
596cd6a6acSopenharmony_ci		free(tmp_ibpkey);
606cd6a6acSopenharmony_ci	}
616cd6a6acSopenharmony_ci	context_destroy(tmp_con);
626cd6a6acSopenharmony_ci	free(tmp_con);
636cd6a6acSopenharmony_ci	free(subnet_prefix_buf);
646cd6a6acSopenharmony_ci	ERR(handle, "could not create ibpkey structure");
656cd6a6acSopenharmony_ci	return STATUS_ERR;
666cd6a6acSopenharmony_ci}
676cd6a6acSopenharmony_ci
686cd6a6acSopenharmony_cistatic int ibpkey_to_record(sepol_handle_t *handle,
696cd6a6acSopenharmony_ci			    const policydb_t *policydb,
706cd6a6acSopenharmony_ci			    ocontext_t *ibpkey, sepol_ibpkey_t **record)
716cd6a6acSopenharmony_ci{
726cd6a6acSopenharmony_ci	context_struct_t *con = &ibpkey->context[0];
736cd6a6acSopenharmony_ci	sepol_context_t *tmp_con = NULL;
746cd6a6acSopenharmony_ci	sepol_ibpkey_t *tmp_record = NULL;
756cd6a6acSopenharmony_ci
766cd6a6acSopenharmony_ci	if (sepol_ibpkey_create(handle, &tmp_record) < 0)
776cd6a6acSopenharmony_ci		goto err;
786cd6a6acSopenharmony_ci
796cd6a6acSopenharmony_ci	sepol_ibpkey_set_subnet_prefix_bytes(tmp_record,
806cd6a6acSopenharmony_ci					     ibpkey->u.ibpkey.subnet_prefix);
816cd6a6acSopenharmony_ci
826cd6a6acSopenharmony_ci	sepol_ibpkey_set_range(tmp_record, ibpkey->u.ibpkey.low_pkey,
836cd6a6acSopenharmony_ci			       ibpkey->u.ibpkey.high_pkey);
846cd6a6acSopenharmony_ci
856cd6a6acSopenharmony_ci	if (context_to_record(handle, policydb, con, &tmp_con) < 0)
866cd6a6acSopenharmony_ci		goto err;
876cd6a6acSopenharmony_ci
886cd6a6acSopenharmony_ci	if (sepol_ibpkey_set_con(handle, tmp_record, tmp_con) < 0)
896cd6a6acSopenharmony_ci		goto err;
906cd6a6acSopenharmony_ci
916cd6a6acSopenharmony_ci	sepol_context_free(tmp_con);
926cd6a6acSopenharmony_ci	*record = tmp_record;
936cd6a6acSopenharmony_ci	return STATUS_SUCCESS;
946cd6a6acSopenharmony_ci
956cd6a6acSopenharmony_cierr:
966cd6a6acSopenharmony_ci	ERR(handle, "could not convert ibpkey to record");
976cd6a6acSopenharmony_ci	sepol_context_free(tmp_con);
986cd6a6acSopenharmony_ci	sepol_ibpkey_free(tmp_record);
996cd6a6acSopenharmony_ci	return STATUS_ERR;
1006cd6a6acSopenharmony_ci}
1016cd6a6acSopenharmony_ci
1026cd6a6acSopenharmony_ci/* Return the number of ibpkeys */
1036cd6a6acSopenharmony_ciextern int sepol_ibpkey_count(sepol_handle_t *handle __attribute__ ((unused)),
1046cd6a6acSopenharmony_ci			      const sepol_policydb_t *p, unsigned int *response)
1056cd6a6acSopenharmony_ci{
1066cd6a6acSopenharmony_ci	unsigned int count = 0;
1076cd6a6acSopenharmony_ci	ocontext_t *c, *head;
1086cd6a6acSopenharmony_ci	const policydb_t *policydb = &p->p;
1096cd6a6acSopenharmony_ci
1106cd6a6acSopenharmony_ci	head = policydb->ocontexts[OCON_IBPKEY];
1116cd6a6acSopenharmony_ci	for (c = head; c; c = c->next)
1126cd6a6acSopenharmony_ci		count++;
1136cd6a6acSopenharmony_ci
1146cd6a6acSopenharmony_ci	*response = count;
1156cd6a6acSopenharmony_ci
1166cd6a6acSopenharmony_ci	return STATUS_SUCCESS;
1176cd6a6acSopenharmony_ci}
1186cd6a6acSopenharmony_ci
1196cd6a6acSopenharmony_ci/* Check if a ibpkey exists */
1206cd6a6acSopenharmony_ciint sepol_ibpkey_exists(sepol_handle_t *handle __attribute__ ((unused)),
1216cd6a6acSopenharmony_ci			const sepol_policydb_t *p,
1226cd6a6acSopenharmony_ci			const sepol_ibpkey_key_t *key, int *response)
1236cd6a6acSopenharmony_ci{
1246cd6a6acSopenharmony_ci	const policydb_t *policydb = &p->p;
1256cd6a6acSopenharmony_ci	ocontext_t *c, *head;
1266cd6a6acSopenharmony_ci	int low, high;
1276cd6a6acSopenharmony_ci	uint64_t subnet_prefix;
1286cd6a6acSopenharmony_ci
1296cd6a6acSopenharmony_ci	sepol_ibpkey_key_unpack(key, &subnet_prefix, &low, &high);
1306cd6a6acSopenharmony_ci
1316cd6a6acSopenharmony_ci	head = policydb->ocontexts[OCON_IBPKEY];
1326cd6a6acSopenharmony_ci	for (c = head; c; c = c->next) {
1336cd6a6acSopenharmony_ci		uint64_t subnet_prefix2 = c->u.ibpkey.subnet_prefix;
1346cd6a6acSopenharmony_ci		uint16_t low2 = c->u.ibpkey.low_pkey;
1356cd6a6acSopenharmony_ci		uint16_t high2 = c->u.ibpkey.high_pkey;
1366cd6a6acSopenharmony_ci
1376cd6a6acSopenharmony_ci		if (low2 == low &&
1386cd6a6acSopenharmony_ci		    high2 == high &&
1396cd6a6acSopenharmony_ci		    subnet_prefix == subnet_prefix2) {
1406cd6a6acSopenharmony_ci			*response = 1;
1416cd6a6acSopenharmony_ci			return STATUS_SUCCESS;
1426cd6a6acSopenharmony_ci		}
1436cd6a6acSopenharmony_ci	}
1446cd6a6acSopenharmony_ci
1456cd6a6acSopenharmony_ci	*response = 0;
1466cd6a6acSopenharmony_ci	return STATUS_SUCCESS;
1476cd6a6acSopenharmony_ci}
1486cd6a6acSopenharmony_ci
1496cd6a6acSopenharmony_ci/* Query a ibpkey */
1506cd6a6acSopenharmony_ciint sepol_ibpkey_query(sepol_handle_t *handle,
1516cd6a6acSopenharmony_ci		       const sepol_policydb_t *p,
1526cd6a6acSopenharmony_ci		       const sepol_ibpkey_key_t *key, sepol_ibpkey_t **response)
1536cd6a6acSopenharmony_ci{
1546cd6a6acSopenharmony_ci	const policydb_t *policydb = &p->p;
1556cd6a6acSopenharmony_ci	ocontext_t *c, *head;
1566cd6a6acSopenharmony_ci	int low, high;
1576cd6a6acSopenharmony_ci	uint64_t subnet_prefix;
1586cd6a6acSopenharmony_ci
1596cd6a6acSopenharmony_ci	sepol_ibpkey_key_unpack(key, &subnet_prefix, &low, &high);
1606cd6a6acSopenharmony_ci
1616cd6a6acSopenharmony_ci	head = policydb->ocontexts[OCON_IBPKEY];
1626cd6a6acSopenharmony_ci	for (c = head; c; c = c->next) {
1636cd6a6acSopenharmony_ci		uint64_t subnet_prefix2 = c->u.ibpkey.subnet_prefix;
1646cd6a6acSopenharmony_ci		int low2 = c->u.ibpkey.low_pkey;
1656cd6a6acSopenharmony_ci		int high2 = c->u.ibpkey.high_pkey;
1666cd6a6acSopenharmony_ci
1676cd6a6acSopenharmony_ci		if (low2 == low &&
1686cd6a6acSopenharmony_ci		    high2 == high &&
1696cd6a6acSopenharmony_ci		    subnet_prefix == subnet_prefix2) {
1706cd6a6acSopenharmony_ci			if (ibpkey_to_record(handle, policydb, c, response) < 0)
1716cd6a6acSopenharmony_ci				goto err;
1726cd6a6acSopenharmony_ci			return STATUS_SUCCESS;
1736cd6a6acSopenharmony_ci		}
1746cd6a6acSopenharmony_ci	}
1756cd6a6acSopenharmony_ci
1766cd6a6acSopenharmony_ci	*response = NULL;
1776cd6a6acSopenharmony_ci	return STATUS_SUCCESS;
1786cd6a6acSopenharmony_ci
1796cd6a6acSopenharmony_cierr:
1806cd6a6acSopenharmony_ci	ERR(handle, "could not query ibpkey subnet prefix: %#" PRIx64 " range %u - %u exists",
1816cd6a6acSopenharmony_ci	    subnet_prefix, low, high);
1826cd6a6acSopenharmony_ci	return STATUS_ERR;
1836cd6a6acSopenharmony_ci}
1846cd6a6acSopenharmony_ci
1856cd6a6acSopenharmony_ci/* Load a ibpkey into policy */
1866cd6a6acSopenharmony_ciint sepol_ibpkey_modify(sepol_handle_t *handle,
1876cd6a6acSopenharmony_ci			sepol_policydb_t *p,
1886cd6a6acSopenharmony_ci			const sepol_ibpkey_key_t *key, const sepol_ibpkey_t *data)
1896cd6a6acSopenharmony_ci{
1906cd6a6acSopenharmony_ci	policydb_t *policydb = &p->p;
1916cd6a6acSopenharmony_ci	ocontext_t *ibpkey = NULL;
1926cd6a6acSopenharmony_ci	int low, high;
1936cd6a6acSopenharmony_ci	uint64_t subnet_prefix;
1946cd6a6acSopenharmony_ci
1956cd6a6acSopenharmony_ci	sepol_ibpkey_key_unpack(key, &subnet_prefix, &low, &high);
1966cd6a6acSopenharmony_ci
1976cd6a6acSopenharmony_ci	if (ibpkey_from_record(handle, policydb, &ibpkey, data) < 0)
1986cd6a6acSopenharmony_ci		goto err;
1996cd6a6acSopenharmony_ci
2006cd6a6acSopenharmony_ci	/* Attach to context list */
2016cd6a6acSopenharmony_ci	ibpkey->next = policydb->ocontexts[OCON_IBPKEY];
2026cd6a6acSopenharmony_ci	policydb->ocontexts[OCON_IBPKEY] = ibpkey;
2036cd6a6acSopenharmony_ci
2046cd6a6acSopenharmony_ci	return STATUS_SUCCESS;
2056cd6a6acSopenharmony_ci
2066cd6a6acSopenharmony_cierr:
2076cd6a6acSopenharmony_ci	ERR(handle, "could not load ibpkey subnet prefix: %#" PRIx64 " range %u - %u exists",
2086cd6a6acSopenharmony_ci	    subnet_prefix, low, high);
2096cd6a6acSopenharmony_ci	if (ibpkey) {
2106cd6a6acSopenharmony_ci		context_destroy(&ibpkey->context[0]);
2116cd6a6acSopenharmony_ci		free(ibpkey);
2126cd6a6acSopenharmony_ci	}
2136cd6a6acSopenharmony_ci	return STATUS_ERR;
2146cd6a6acSopenharmony_ci}
2156cd6a6acSopenharmony_ci
2166cd6a6acSopenharmony_ciint sepol_ibpkey_iterate(sepol_handle_t *handle,
2176cd6a6acSopenharmony_ci			 const sepol_policydb_t *p,
2186cd6a6acSopenharmony_ci			 int (*fn)(const sepol_ibpkey_t *ibpkey,
2196cd6a6acSopenharmony_ci				   void *fn_arg), void *arg)
2206cd6a6acSopenharmony_ci{
2216cd6a6acSopenharmony_ci	const policydb_t *policydb = &p->p;
2226cd6a6acSopenharmony_ci	ocontext_t *c, *head;
2236cd6a6acSopenharmony_ci	sepol_ibpkey_t *ibpkey = NULL;
2246cd6a6acSopenharmony_ci
2256cd6a6acSopenharmony_ci	head = policydb->ocontexts[OCON_IBPKEY];
2266cd6a6acSopenharmony_ci	for (c = head; c; c = c->next) {
2276cd6a6acSopenharmony_ci		int status;
2286cd6a6acSopenharmony_ci
2296cd6a6acSopenharmony_ci		if (ibpkey_to_record(handle, policydb, c, &ibpkey) < 0)
2306cd6a6acSopenharmony_ci			goto err;
2316cd6a6acSopenharmony_ci
2326cd6a6acSopenharmony_ci		/* Invoke handler */
2336cd6a6acSopenharmony_ci		status = fn(ibpkey, arg);
2346cd6a6acSopenharmony_ci		if (status < 0)
2356cd6a6acSopenharmony_ci			goto err;
2366cd6a6acSopenharmony_ci
2376cd6a6acSopenharmony_ci		sepol_ibpkey_free(ibpkey);
2386cd6a6acSopenharmony_ci		ibpkey = NULL;
2396cd6a6acSopenharmony_ci
2406cd6a6acSopenharmony_ci		/* Handler requested exit */
2416cd6a6acSopenharmony_ci		if (status > 0)
2426cd6a6acSopenharmony_ci			break;
2436cd6a6acSopenharmony_ci	}
2446cd6a6acSopenharmony_ci
2456cd6a6acSopenharmony_ci	return STATUS_SUCCESS;
2466cd6a6acSopenharmony_ci
2476cd6a6acSopenharmony_cierr:
2486cd6a6acSopenharmony_ci	ERR(handle, "could not iterate over ibpkeys");
2496cd6a6acSopenharmony_ci	sepol_ibpkey_free(ibpkey);
2506cd6a6acSopenharmony_ci	return STATUS_ERR;
2516cd6a6acSopenharmony_ci}
252