1/*
2 * Class and permission mappings.
3 */
4
5#include <errno.h>
6#include <stdio.h>
7#include <stdlib.h>
8#include <stdarg.h>
9#include <selinux/selinux.h>
10#include <selinux/avc.h>
11#include "mapping.h"
12
13/*
14 * Class and permission mappings
15 */
16
17struct selinux_mapping {
18	security_class_t value; /* real, kernel value */
19	unsigned num_perms;
20	access_vector_t perms[sizeof(access_vector_t) * 8];
21};
22
23static struct selinux_mapping *current_mapping = NULL;
24static security_class_t current_mapping_size = 0;
25
26/*
27 * Mapping setting function
28 */
29
30int
31selinux_set_mapping(struct security_class_mapping *map)
32{
33	size_t size = sizeof(struct selinux_mapping);
34	security_class_t i, j;
35	unsigned k;
36
37	free(current_mapping);
38	current_mapping = NULL;
39	current_mapping_size = 0;
40
41	if (avc_reset() < 0)
42		goto err;
43
44	/* Find number of classes in the input mapping */
45	if (!map) {
46		errno = EINVAL;
47		goto err;
48	}
49	i = 0;
50	while (map[i].name)
51		i++;
52
53	/* Allocate space for the class records, plus one for class zero */
54	current_mapping = (struct selinux_mapping *)calloc(++i, size);
55	if (!current_mapping)
56		goto err;
57
58	/* Store the raw class and permission values */
59	j = 0;
60	while (map[j].name) {
61		struct security_class_mapping *p_in = map + (j++);
62		struct selinux_mapping *p_out = current_mapping + j;
63
64		p_out->value = string_to_security_class(p_in->name);
65		if (!p_out->value)
66			goto err2;
67
68		k = 0;
69		while (p_in->perms[k]) {
70			/* An empty permission string skips ahead */
71			if (!*p_in->perms[k]) {
72				k++;
73				continue;
74			}
75			p_out->perms[k] = string_to_av_perm(p_out->value,
76							    p_in->perms[k]);
77			if (!p_out->perms[k])
78				goto err2;
79			k++;
80		}
81		p_out->num_perms = k;
82	}
83
84	/* Set the mapping size here so the above lookups are "raw" */
85	current_mapping_size = i;
86	return 0;
87err2:
88	free(current_mapping);
89	current_mapping = NULL;
90	current_mapping_size = 0;
91err:
92	return -1;
93}
94
95/*
96 * Get real, kernel values from mapped values
97 */
98
99security_class_t
100unmap_class(security_class_t tclass)
101{
102	if (tclass < current_mapping_size)
103		return current_mapping[tclass].value;
104
105	/* If here no mapping set or the class requested is not valid. */
106	if (current_mapping_size != 0) {
107		errno = EINVAL;
108		return 0;
109	}
110	else
111		return tclass;
112}
113
114access_vector_t
115unmap_perm(security_class_t tclass, access_vector_t tperm)
116{
117	if (tclass < current_mapping_size) {
118		unsigned i;
119		access_vector_t kperm = 0;
120
121		for (i=0; i<current_mapping[tclass].num_perms; i++)
122			if (tperm & (1<<i)) {
123				kperm |= current_mapping[tclass].perms[i];
124				tperm &= ~(1<<i);
125			}
126		return kperm;
127	}
128
129	/* If here no mapping set or the perm requested is not valid. */
130	if (current_mapping_size != 0) {
131		errno = EINVAL;
132		return 0;
133	}
134	else
135		return tperm;
136}
137
138/*
139 * Get mapped values from real, kernel values
140 */
141
142security_class_t
143map_class(security_class_t kclass)
144{
145	security_class_t i;
146
147	for (i=0; i<current_mapping_size; i++)
148		if (current_mapping[i].value == kclass)
149			return i;
150
151/* If here no mapping set or the class requested is not valid. */
152	if (current_mapping_size != 0) {
153		errno = EINVAL;
154		return 0;
155	}
156	else
157		return kclass;
158}
159
160access_vector_t
161map_perm(security_class_t tclass, access_vector_t kperm)
162{
163	if (tclass < current_mapping_size) {
164		unsigned i;
165		access_vector_t tperm = 0;
166
167		for (i=0; i<current_mapping[tclass].num_perms; i++)
168			if (kperm & current_mapping[tclass].perms[i]) {
169				tperm |= 1<<i;
170				kperm &= ~current_mapping[tclass].perms[i];
171			}
172
173		if (tperm == 0) {
174			errno = EINVAL;
175			return 0;
176		}
177		else
178			return tperm;
179	}
180	return kperm;
181}
182
183void
184map_decision(security_class_t tclass, struct av_decision *avd)
185{
186	if (tclass < current_mapping_size) {
187		unsigned i;
188		access_vector_t result;
189
190		for (i=0, result=0; i<current_mapping[tclass].num_perms; i++)
191			if (avd->allowed & current_mapping[tclass].perms[i])
192				result |= 1<<i;
193		avd->allowed = result;
194
195		for (i=0, result=0; i<current_mapping[tclass].num_perms; i++)
196			if (avd->decided & current_mapping[tclass].perms[i])
197				result |= 1<<i;
198		avd->decided = result;
199
200		for (i=0, result=0; i<current_mapping[tclass].num_perms; i++)
201			if (avd->auditallow & current_mapping[tclass].perms[i])
202				result |= 1<<i;
203		avd->auditallow = result;
204
205		for (i=0, result=0; i<current_mapping[tclass].num_perms; i++)
206			if (avd->auditdeny & current_mapping[tclass].perms[i])
207				result |= 1<<i;
208		avd->auditdeny = result;
209	}
210}
211