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