• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
18 struct 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 
24 static struct selinux_mapping *current_mapping = NULL;
25 static security_class_t current_mapping_size = 0;
26 
27 /*
28  * Mapping setting function
29  */
30 
31 int
selinux_set_mapping(struct security_class_mapping * map)32 selinux_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;
88 err2:
89 	free(current_mapping);
90 	current_mapping = NULL;
91 	current_mapping_size = 0;
92 err:
93 	return -1;
94 }
95 
96 /*
97  * Get real, kernel values from mapped values
98  */
99 
100 security_class_t
unmap_class(security_class_t tclass)101 unmap_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 
110 access_vector_t
unmap_perm(security_class_t tclass,access_vector_t tperm)111 unmap_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 
135 security_class_t
map_class(security_class_t kclass)136 map_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 
148 access_vector_t
map_perm(security_class_t tclass,access_vector_t kperm)149 map_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 
168 void
map_decision(security_class_t tclass,struct av_decision * avd)169 map_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