16cd6a6acSopenharmony_ci#define _GNU_SOURCE  /* vasprintf(3) */
26cd6a6acSopenharmony_ci
36cd6a6acSopenharmony_ci#include "test-neverallow.h"
46cd6a6acSopenharmony_ci
56cd6a6acSopenharmony_ci#include "helpers.h"
66cd6a6acSopenharmony_ci#include "test-common.h"
76cd6a6acSopenharmony_ci
86cd6a6acSopenharmony_ci#include <sepol/debug.h>
96cd6a6acSopenharmony_ci#include <sepol/policydb/link.h>
106cd6a6acSopenharmony_ci#include <sepol/policydb/expand.h>
116cd6a6acSopenharmony_ci
126cd6a6acSopenharmony_ci#include <stdio.h>
136cd6a6acSopenharmony_ci#include <stdarg.h>
146cd6a6acSopenharmony_ci
156cd6a6acSopenharmony_ciextern int mls;
166cd6a6acSopenharmony_ci
176cd6a6acSopenharmony_ciint neverallow_test_init(void)
186cd6a6acSopenharmony_ci{
196cd6a6acSopenharmony_ci	return 0;
206cd6a6acSopenharmony_ci}
216cd6a6acSopenharmony_ci
226cd6a6acSopenharmony_ciint neverallow_test_cleanup(void)
236cd6a6acSopenharmony_ci{
246cd6a6acSopenharmony_ci	return 0;
256cd6a6acSopenharmony_ci}
266cd6a6acSopenharmony_ci
276cd6a6acSopenharmony_cistatic struct msg_list {
286cd6a6acSopenharmony_ci	char *msg;
296cd6a6acSopenharmony_ci	struct msg_list *next;
306cd6a6acSopenharmony_ci} *messages;
316cd6a6acSopenharmony_ci
326cd6a6acSopenharmony_cistatic void messages_clean(void)
336cd6a6acSopenharmony_ci{
346cd6a6acSopenharmony_ci	while (messages) {
356cd6a6acSopenharmony_ci		struct msg_list *n = messages->next;
366cd6a6acSopenharmony_ci		free(messages->msg);
376cd6a6acSopenharmony_ci		free(messages);
386cd6a6acSopenharmony_ci		messages = n;
396cd6a6acSopenharmony_ci	}
406cd6a6acSopenharmony_ci}
416cd6a6acSopenharmony_ci
426cd6a6acSopenharmony_cistatic void messages_check(unsigned count, const char *const expected[count])
436cd6a6acSopenharmony_ci{
446cd6a6acSopenharmony_ci	unsigned i;
456cd6a6acSopenharmony_ci	const struct msg_list *m = messages;
466cd6a6acSopenharmony_ci
476cd6a6acSopenharmony_ci	for (i = 0; i < count; i++, m = m->next) {
486cd6a6acSopenharmony_ci		if (!m) {
496cd6a6acSopenharmony_ci			CU_FAIL("less messages than expected");
506cd6a6acSopenharmony_ci			fprintf(stderr, "\n<expected %u, got %u>\n", count, i);
516cd6a6acSopenharmony_ci			return;
526cd6a6acSopenharmony_ci		}
536cd6a6acSopenharmony_ci
546cd6a6acSopenharmony_ci		if (strcmp(expected[i], m->msg) != 0) {
556cd6a6acSopenharmony_ci			CU_FAIL("messages differ from expected");
566cd6a6acSopenharmony_ci			fprintf(stderr, "\n<expected: '''%s''', got: '''%s'''>\n", expected[i], m->msg);
576cd6a6acSopenharmony_ci		}
586cd6a6acSopenharmony_ci	}
596cd6a6acSopenharmony_ci
606cd6a6acSopenharmony_ci	if (m) {
616cd6a6acSopenharmony_ci		CU_FAIL("more messages than expected");
626cd6a6acSopenharmony_ci		fprintf(stderr, "\n<expected %u; next message: '''%s'''>\n", count, m->msg);
636cd6a6acSopenharmony_ci	}
646cd6a6acSopenharmony_ci}
656cd6a6acSopenharmony_ci
666cd6a6acSopenharmony_ci__attribute__ ((format(printf, 3, 4)))
676cd6a6acSopenharmony_cistatic void msg_handler(void *varg __attribute__ ((unused)),
686cd6a6acSopenharmony_ci			sepol_handle_t * handle __attribute__ ((unused)),
696cd6a6acSopenharmony_ci			const char *fmt, ...)
706cd6a6acSopenharmony_ci{
716cd6a6acSopenharmony_ci	char *msg;
726cd6a6acSopenharmony_ci	va_list ap;
736cd6a6acSopenharmony_ci	int r;
746cd6a6acSopenharmony_ci
756cd6a6acSopenharmony_ci	va_start(ap, fmt);
766cd6a6acSopenharmony_ci	r = vasprintf(&msg, fmt, ap);
776cd6a6acSopenharmony_ci	if (r < 0)
786cd6a6acSopenharmony_ci		CU_FAIL_FATAL("oom");
796cd6a6acSopenharmony_ci	va_end(ap);
806cd6a6acSopenharmony_ci
816cd6a6acSopenharmony_ci	struct msg_list *new = malloc(sizeof(*new));
826cd6a6acSopenharmony_ci	if (!new)
836cd6a6acSopenharmony_ci		CU_FAIL_FATAL("oom");
846cd6a6acSopenharmony_ci	new->msg = msg;
856cd6a6acSopenharmony_ci	new->next = messages;
866cd6a6acSopenharmony_ci	messages = new;
876cd6a6acSopenharmony_ci}
886cd6a6acSopenharmony_ci
896cd6a6acSopenharmony_ci#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*a))
906cd6a6acSopenharmony_ci
916cd6a6acSopenharmony_cistatic void test_neverallow_basic(void)
926cd6a6acSopenharmony_ci{
936cd6a6acSopenharmony_ci	policydb_t basemod, base_expanded;
946cd6a6acSopenharmony_ci	sepol_handle_t *handle;
956cd6a6acSopenharmony_ci	static const char *const expected_messages[] = {
966cd6a6acSopenharmony_ci		"30 neverallow failures occurred",
976cd6a6acSopenharmony_ci		"neverallow on line 53 of policies/test-neverallow/policy.conf.std (or line 53 of policies/test-neverallow/policy.conf.std) violated by allow test1_t test1_t:file { read };",
986cd6a6acSopenharmony_ci		"neverallow on line 60 of policies/test-neverallow/policy.conf.std (or line 60 of policies/test-neverallow/policy.conf.std) violated by allow test2_t test2_t:file { read write };",
996cd6a6acSopenharmony_ci		"neverallow on line 67 of policies/test-neverallow/policy.conf.std (or line 67 of policies/test-neverallow/policy.conf.std) violated by allow test3_t test3_t:file { read };",
1006cd6a6acSopenharmony_ci		"neverallow on line 74 of policies/test-neverallow/policy.conf.std (or line 74 of policies/test-neverallow/policy.conf.std) violated by allow test4_t test4_t:file { read };",
1016cd6a6acSopenharmony_ci		"neverallow on line 81 of policies/test-neverallow/policy.conf.std (or line 81 of policies/test-neverallow/policy.conf.std) violated by allow test5_t test5_t:file { read };",
1026cd6a6acSopenharmony_ci		"neverallow on line 89 of policies/test-neverallow/policy.conf.std (or line 89 of policies/test-neverallow/policy.conf.std) violated by allow test6_1_t test6_1_t:file { read };",
1036cd6a6acSopenharmony_ci		"neverallow on line 97 of policies/test-neverallow/policy.conf.std (or line 97 of policies/test-neverallow/policy.conf.std) violated by allow test7_1_t test7_1_t:file { read };",
1046cd6a6acSopenharmony_ci		"neverallow on line 106 of policies/test-neverallow/policy.conf.std (or line 106 of policies/test-neverallow/policy.conf.std) violated by allow test8_t test8_t:file { write };",
1056cd6a6acSopenharmony_ci		"neverallow on line 106 of policies/test-neverallow/policy.conf.std (or line 106 of policies/test-neverallow/policy.conf.std) violated by allow test8_t test8_t:file { read };",
1066cd6a6acSopenharmony_ci		"neverallow on line 115 of policies/test-neverallow/policy.conf.std (or line 115 of policies/test-neverallow/policy.conf.std) violated by allow test9_t test9_t:file { read };",
1076cd6a6acSopenharmony_ci		"neverallow on line 115 of policies/test-neverallow/policy.conf.std (or line 115 of policies/test-neverallow/policy.conf.std) violated by allow test9_t test9_t:file { write };",
1086cd6a6acSopenharmony_ci		"neverallow on line 124 of policies/test-neverallow/policy.conf.std (or line 124 of policies/test-neverallow/policy.conf.std) violated by allow test10_1_t test10_1_t:file { read };",
1096cd6a6acSopenharmony_ci		"neverallow on line 131 of policies/test-neverallow/policy.conf.std (or line 131 of policies/test-neverallow/policy.conf.std) violated by allow test11_t test11_t:process { dyntransition transition };",
1106cd6a6acSopenharmony_ci		"neverallow on line 143 of policies/test-neverallow/policy.conf.std (or line 143 of policies/test-neverallow/policy.conf.std) violated by allow test12_3_t test12_1_t:file { getattr };",
1116cd6a6acSopenharmony_ci		"neverallow on line 143 of policies/test-neverallow/policy.conf.std (or line 143 of policies/test-neverallow/policy.conf.std) violated by allow test12_3_t test12_2_t:file { getattr };",
1126cd6a6acSopenharmony_ci		"neverallow on line 144 of policies/test-neverallow/policy.conf.std (or line 144 of policies/test-neverallow/policy.conf.std) violated by allow test12_3_t test12_1_t:file { open };",
1136cd6a6acSopenharmony_ci		"neverallow on line 144 of policies/test-neverallow/policy.conf.std (or line 144 of policies/test-neverallow/policy.conf.std) violated by allow test12_2_t test12_1_t:file { open };",
1146cd6a6acSopenharmony_ci		"neverallow on line 156 of policies/test-neverallow/policy.conf.std (or line 156 of policies/test-neverallow/policy.conf.std) violated by allow test13_1_t test13_1_t:file { read };",
1156cd6a6acSopenharmony_ci		"neverallowxperm on line 174 of policies/test-neverallow/policy.conf.std (or line 174 of policies/test-neverallow/policy.conf.std) violated by\nallow test15_t test15_t:file { ioctl };",
1166cd6a6acSopenharmony_ci		"neverallowxperm on line 182 of policies/test-neverallow/policy.conf.std (or line 182 of policies/test-neverallow/policy.conf.std) violated by\nallowxperm test16_t test16_t:file ioctl { 0x1111 };",
1176cd6a6acSopenharmony_ci		"neverallowxperm on line 198 of policies/test-neverallow/policy.conf.std (or line 198 of policies/test-neverallow/policy.conf.std) violated by\nallowxperm test18_t test18_t:file ioctl { 0x1111 };",
1186cd6a6acSopenharmony_ci		"neverallowxperm on line 206 of policies/test-neverallow/policy.conf.std (or line 206 of policies/test-neverallow/policy.conf.std) violated by\nallowxperm test19_t test19_t:file ioctl { 0x1111 };",
1196cd6a6acSopenharmony_ci		"neverallowxperm on line 216 of policies/test-neverallow/policy.conf.std (or line 216 of policies/test-neverallow/policy.conf.std) violated by\nallowxperm test20_a test20_a:file ioctl { 0x1111 };",
1206cd6a6acSopenharmony_ci		"neverallowxperm on line 227 of policies/test-neverallow/policy.conf.std (or line 227 of policies/test-neverallow/policy.conf.std) violated by\nallowxperm test21_1_a test21_2_a:file ioctl { 0x1111 };",
1216cd6a6acSopenharmony_ci		"neverallowxperm on line 237 of policies/test-neverallow/policy.conf.std (or line 237 of policies/test-neverallow/policy.conf.std) violated by\nallowxperm test22_t test22_t:file ioctl { 0x1111 };",
1226cd6a6acSopenharmony_ci		"neverallowxperm on line 247 of policies/test-neverallow/policy.conf.std (or line 247 of policies/test-neverallow/policy.conf.std) violated by\nallowxperm test23_t test23_t:file ioctl { 0x1111 };",
1236cd6a6acSopenharmony_ci		"neverallowxperm on line 257 of policies/test-neverallow/policy.conf.std (or line 257 of policies/test-neverallow/policy.conf.std) violated by\nallowxperm test24_t test24_a:file ioctl { 0x1111 };",
1246cd6a6acSopenharmony_ci		"neverallowxperm on line 267 of policies/test-neverallow/policy.conf.std (or line 267 of policies/test-neverallow/policy.conf.std) violated by\nallowxperm test25_t test25_t:file ioctl { 0x1111 };",
1256cd6a6acSopenharmony_ci		"neverallowxperm on line 277 of policies/test-neverallow/policy.conf.std (or line 277 of policies/test-neverallow/policy.conf.std) violated by\nallowxperm test26_a test26_a:file ioctl { 0x1111 };",
1266cd6a6acSopenharmony_ci		"neverallowxperm on line 277 of policies/test-neverallow/policy.conf.std (or line 277 of policies/test-neverallow/policy.conf.std) violated by\nallowxperm test26_a test26_a:file ioctl { 0x1111 };",
1276cd6a6acSopenharmony_ci	};
1286cd6a6acSopenharmony_ci
1296cd6a6acSopenharmony_ci	if (policydb_init(&base_expanded))
1306cd6a6acSopenharmony_ci		CU_FAIL_FATAL("Failed to initialize policy");
1316cd6a6acSopenharmony_ci
1326cd6a6acSopenharmony_ci	if (test_load_policy(&basemod, POLICY_BASE, mls, "test-neverallow", "policy.conf"))
1336cd6a6acSopenharmony_ci		CU_FAIL_FATAL("Failed to load policy");
1346cd6a6acSopenharmony_ci
1356cd6a6acSopenharmony_ci	if (link_modules(NULL, &basemod, NULL, 0, 0))
1366cd6a6acSopenharmony_ci		CU_FAIL_FATAL("Failed to link base module");
1376cd6a6acSopenharmony_ci
1386cd6a6acSopenharmony_ci	if (expand_module(NULL, &basemod, &base_expanded, 0, 0))
1396cd6a6acSopenharmony_ci		CU_FAIL_FATAL("Failed to expand policy");
1406cd6a6acSopenharmony_ci
1416cd6a6acSopenharmony_ci	if ((handle = sepol_handle_create()) == NULL)
1426cd6a6acSopenharmony_ci		CU_FAIL_FATAL("Failed to initialize handle");
1436cd6a6acSopenharmony_ci
1446cd6a6acSopenharmony_ci	sepol_msg_set_callback(handle, msg_handler, NULL);
1456cd6a6acSopenharmony_ci
1466cd6a6acSopenharmony_ci	if (check_assertions(handle, &base_expanded, base_expanded.global->branch_list->avrules) != -1)
1476cd6a6acSopenharmony_ci		CU_FAIL("Assertions did not trigger");
1486cd6a6acSopenharmony_ci
1496cd6a6acSopenharmony_ci	messages_check(ARRAY_SIZE(expected_messages), expected_messages);
1506cd6a6acSopenharmony_ci
1516cd6a6acSopenharmony_ci	sepol_handle_destroy(handle);
1526cd6a6acSopenharmony_ci	messages_clean();
1536cd6a6acSopenharmony_ci	policydb_destroy(&basemod);
1546cd6a6acSopenharmony_ci	policydb_destroy(&base_expanded);
1556cd6a6acSopenharmony_ci}
1566cd6a6acSopenharmony_ci
1576cd6a6acSopenharmony_ciint neverallow_add_tests(CU_pSuite suite)
1586cd6a6acSopenharmony_ci{
1596cd6a6acSopenharmony_ci	/*
1606cd6a6acSopenharmony_ci	 * neverallow rules operate only on types and are unaffected by MLS
1616cd6a6acSopenharmony_ci	 * (avoid adjusting the messages for std and mls)
1626cd6a6acSopenharmony_ci	 */
1636cd6a6acSopenharmony_ci	if (mls)
1646cd6a6acSopenharmony_ci		return 0;
1656cd6a6acSopenharmony_ci
1666cd6a6acSopenharmony_ci	if (NULL == CU_add_test(suite, "neverallow_basic", test_neverallow_basic)) {
1676cd6a6acSopenharmony_ci		CU_cleanup_registry();
1686cd6a6acSopenharmony_ci		return CU_get_error();
1696cd6a6acSopenharmony_ci	}
1706cd6a6acSopenharmony_ci
1716cd6a6acSopenharmony_ci	return 0;
1726cd6a6acSopenharmony_ci}
173