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 <selinux/selinux.h>
10f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include <selinux/avc.h>
11f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include "mapping.h"
12f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
13f074036424618c130dacb3464465a8b40bffef5Stephen Smalley/*
14f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * Class and permission mappings
15f074036424618c130dacb3464465a8b40bffef5Stephen Smalley */
16f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
17f074036424618c130dacb3464465a8b40bffef5Stephen Smalleystruct selinux_mapping {
18f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	security_class_t value; /* real, kernel value */
19f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	unsigned num_perms;
20f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	access_vector_t perms[sizeof(access_vector_t) * 8];
21f074036424618c130dacb3464465a8b40bffef5Stephen Smalley};
22f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
23f074036424618c130dacb3464465a8b40bffef5Stephen Smalleystatic struct selinux_mapping *current_mapping = NULL;
24f074036424618c130dacb3464465a8b40bffef5Stephen Smalleystatic security_class_t current_mapping_size = 0;
25f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
26f074036424618c130dacb3464465a8b40bffef5Stephen Smalley/*
27f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * Mapping setting function
28f074036424618c130dacb3464465a8b40bffef5Stephen Smalley */
29f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
30f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyint
31f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyselinux_set_mapping(struct security_class_mapping *map)
32f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{
33f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	size_t size = sizeof(struct selinux_mapping);
34f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	security_class_t i, j;
35f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	unsigned k;
36f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
37f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	free(current_mapping);
38f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	current_mapping = NULL;
39f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	current_mapping_size = 0;
40f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
41f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	if (avc_reset() < 0)
42f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		goto err;
43f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
44f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	/* Find number of classes in the input mapping */
45f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	if (!map) {
46f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		errno = EINVAL;
47f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		goto err;
48f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	}
49f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	i = 0;
50f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	while (map[i].name)
51f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		i++;
52f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
53f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	/* Allocate space for the class records, plus one for class zero */
54f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	current_mapping = (struct selinux_mapping *)calloc(++i, size);
55f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	if (!current_mapping)
56f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		goto err;
57f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
58f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	/* Store the raw class and permission values */
59f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	j = 0;
60f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	while (map[j].name) {
61f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		struct security_class_mapping *p_in = map + (j++);
62f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		struct selinux_mapping *p_out = current_mapping + j;
63f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
64f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		p_out->value = string_to_security_class(p_in->name);
65f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		if (!p_out->value)
66f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			goto err2;
67f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
68f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		k = 0;
69c01e95f737527e068edcacb1179affca9f62a52dEric Paris		while (p_in->perms[k]) {
70f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			/* An empty permission string skips ahead */
71f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			if (!*p_in->perms[k]) {
72f074036424618c130dacb3464465a8b40bffef5Stephen Smalley				k++;
73f074036424618c130dacb3464465a8b40bffef5Stephen Smalley				continue;
74f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			}
75f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			p_out->perms[k] = string_to_av_perm(p_out->value,
76f074036424618c130dacb3464465a8b40bffef5Stephen Smalley							    p_in->perms[k]);
77f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			if (!p_out->perms[k])
78f074036424618c130dacb3464465a8b40bffef5Stephen Smalley				goto err2;
79f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			k++;
80f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		}
81f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		p_out->num_perms = k;
82f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	}
83f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
84f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	/* Set the mapping size here so the above lookups are "raw" */
85f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	current_mapping_size = i;
86f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	return 0;
87f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyerr2:
88f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	free(current_mapping);
89f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	current_mapping = NULL;
90f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	current_mapping_size = 0;
91f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyerr:
92f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	return -1;
93f074036424618c130dacb3464465a8b40bffef5Stephen Smalley}
94f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
95f074036424618c130dacb3464465a8b40bffef5Stephen Smalley/*
96f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * Get real, kernel values from mapped values
97f074036424618c130dacb3464465a8b40bffef5Stephen Smalley */
98f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
99f074036424618c130dacb3464465a8b40bffef5Stephen Smalleysecurity_class_t
100f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyunmap_class(security_class_t tclass)
101f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{
102f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	if (tclass < current_mapping_size)
103f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		return current_mapping[tclass].value;
104f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
105574290e4d18567218176b3b839895b2500f7e128Richard Haines	/* If here no mapping set or the class requested is not valid. */
106574290e4d18567218176b3b839895b2500f7e128Richard Haines	if (current_mapping_size != 0) {
107574290e4d18567218176b3b839895b2500f7e128Richard Haines		errno = EINVAL;
108574290e4d18567218176b3b839895b2500f7e128Richard Haines		return 0;
109574290e4d18567218176b3b839895b2500f7e128Richard Haines	}
110574290e4d18567218176b3b839895b2500f7e128Richard Haines	else
111574290e4d18567218176b3b839895b2500f7e128Richard Haines		return tclass;
112f074036424618c130dacb3464465a8b40bffef5Stephen Smalley}
113f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
114f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyaccess_vector_t
115f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyunmap_perm(security_class_t tclass, access_vector_t tperm)
116f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{
117f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	if (tclass < current_mapping_size) {
118f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		unsigned i;
119f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		access_vector_t kperm = 0;
120f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
121f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		for (i=0; i<current_mapping[tclass].num_perms; i++)
122f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			if (tperm & (1<<i)) {
123f074036424618c130dacb3464465a8b40bffef5Stephen Smalley				kperm |= current_mapping[tclass].perms[i];
124f074036424618c130dacb3464465a8b40bffef5Stephen Smalley				tperm &= ~(1<<i);
125f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			}
126f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		return kperm;
127f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	}
128f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
129574290e4d18567218176b3b839895b2500f7e128Richard Haines	/* If here no mapping set or the perm requested is not valid. */
130574290e4d18567218176b3b839895b2500f7e128Richard Haines	if (current_mapping_size != 0) {
131574290e4d18567218176b3b839895b2500f7e128Richard Haines		errno = EINVAL;
132574290e4d18567218176b3b839895b2500f7e128Richard Haines		return 0;
133574290e4d18567218176b3b839895b2500f7e128Richard Haines	}
134574290e4d18567218176b3b839895b2500f7e128Richard Haines	else
135574290e4d18567218176b3b839895b2500f7e128Richard Haines		return tperm;
136f074036424618c130dacb3464465a8b40bffef5Stephen Smalley}
137f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
138f074036424618c130dacb3464465a8b40bffef5Stephen Smalley/*
139f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * Get mapped values from real, kernel values
140f074036424618c130dacb3464465a8b40bffef5Stephen Smalley */
141f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
142f074036424618c130dacb3464465a8b40bffef5Stephen Smalleysecurity_class_t
143f074036424618c130dacb3464465a8b40bffef5Stephen Smalleymap_class(security_class_t kclass)
144f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{
145f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	security_class_t i;
146f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
147f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	for (i=0; i<current_mapping_size; i++)
148f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		if (current_mapping[i].value == kclass)
149f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			return i;
150f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
151574290e4d18567218176b3b839895b2500f7e128Richard Haines/* If here no mapping set or the class requested is not valid. */
152574290e4d18567218176b3b839895b2500f7e128Richard Haines	if (current_mapping_size != 0) {
153574290e4d18567218176b3b839895b2500f7e128Richard Haines		errno = EINVAL;
154574290e4d18567218176b3b839895b2500f7e128Richard Haines		return 0;
155574290e4d18567218176b3b839895b2500f7e128Richard Haines	}
156574290e4d18567218176b3b839895b2500f7e128Richard Haines	else
157574290e4d18567218176b3b839895b2500f7e128Richard Haines		return kclass;
158f074036424618c130dacb3464465a8b40bffef5Stephen Smalley}
159f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
160f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyaccess_vector_t
161f074036424618c130dacb3464465a8b40bffef5Stephen Smalleymap_perm(security_class_t tclass, access_vector_t kperm)
162f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{
163f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	if (tclass < current_mapping_size) {
164f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		unsigned i;
165f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		access_vector_t tperm = 0;
166f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
167f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		for (i=0; i<current_mapping[tclass].num_perms; i++)
168f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			if (kperm & current_mapping[tclass].perms[i]) {
169f074036424618c130dacb3464465a8b40bffef5Stephen Smalley				tperm |= 1<<i;
170f074036424618c130dacb3464465a8b40bffef5Stephen Smalley				kperm &= ~current_mapping[tclass].perms[i];
171f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			}
172f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
173574290e4d18567218176b3b839895b2500f7e128Richard Haines		if (tperm == 0) {
174574290e4d18567218176b3b839895b2500f7e128Richard Haines			errno = EINVAL;
175574290e4d18567218176b3b839895b2500f7e128Richard Haines			return 0;
176574290e4d18567218176b3b839895b2500f7e128Richard Haines		}
177574290e4d18567218176b3b839895b2500f7e128Richard Haines		else
178574290e4d18567218176b3b839895b2500f7e128Richard Haines			return tperm;
179574290e4d18567218176b3b839895b2500f7e128Richard Haines	}
180f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	return kperm;
181f074036424618c130dacb3464465a8b40bffef5Stephen Smalley}
182f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
183f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyvoid
184f074036424618c130dacb3464465a8b40bffef5Stephen Smalleymap_decision(security_class_t tclass, struct av_decision *avd)
185f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{
186f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	if (tclass < current_mapping_size) {
187f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		unsigned i;
188f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		access_vector_t result;
189f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
190f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		for (i=0, result=0; i<current_mapping[tclass].num_perms; i++)
191f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			if (avd->allowed & current_mapping[tclass].perms[i])
192f074036424618c130dacb3464465a8b40bffef5Stephen Smalley				result |= 1<<i;
193f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		avd->allowed = result;
194f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
195f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		for (i=0, result=0; i<current_mapping[tclass].num_perms; i++)
196f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			if (avd->decided & current_mapping[tclass].perms[i])
197f074036424618c130dacb3464465a8b40bffef5Stephen Smalley				result |= 1<<i;
198f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		avd->decided = result;
199f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
200f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		for (i=0, result=0; i<current_mapping[tclass].num_perms; i++)
201f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			if (avd->auditallow & current_mapping[tclass].perms[i])
202f074036424618c130dacb3464465a8b40bffef5Stephen Smalley				result |= 1<<i;
203f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		avd->auditallow = result;
204f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
205f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		for (i=0, result=0; i<current_mapping[tclass].num_perms; i++)
206f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			if (avd->auditdeny & current_mapping[tclass].perms[i])
207f074036424618c130dacb3464465a8b40bffef5Stephen Smalley				result |= 1<<i;
208f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		avd->auditdeny = result;
209f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	}
210f074036424618c130dacb3464465a8b40bffef5Stephen Smalley}
211