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