• 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 <stdbool.h>
10 #include <selinux/selinux.h>
11 #include <selinux/avc.h>
12 #include "callbacks.h"
13 #include "mapping.h"
14 #include "selinux_internal.h"
15 
16 /*
17  * Class and permission mappings
18  */
19 
20 struct selinux_mapping {
21 	security_class_t value; /* real, kernel value */
22 	unsigned num_perms;
23 	access_vector_t perms[sizeof(access_vector_t) * 8];
24 };
25 
26 static struct selinux_mapping *current_mapping = NULL;
27 static security_class_t current_mapping_size = 0;
28 
29 /*
30  * Mapping setting function
31  */
32 
33 int
selinux_set_mapping(struct security_class_mapping * map)34 selinux_set_mapping(struct security_class_mapping *map)
35 {
36 	size_t size = sizeof(struct selinux_mapping);
37 	security_class_t i, j;
38 	unsigned k;
39 	bool print_unknown_handle = false;
40 	bool reject = (security_reject_unknown() == 1);
41 	bool deny = (security_deny_unknown() == 1);
42 
43 	free(current_mapping);
44 	current_mapping = NULL;
45 	current_mapping_size = 0;
46 
47 	if (avc_reset() < 0)
48 		goto err;
49 
50 	/* Find number of classes in the input mapping */
51 	if (!map) {
52 		errno = EINVAL;
53 		goto err;
54 	}
55 	i = 0;
56 	while (map[i].name)
57 		i++;
58 
59 	/* Allocate space for the class records, plus one for class zero */
60 	current_mapping = (struct selinux_mapping *)calloc(++i, size);
61 	if (!current_mapping)
62 		goto err;
63 
64 	/* Store the raw class and permission values */
65 	j = 0;
66 	while (map[j].name) {
67 		struct security_class_mapping *p_in = map + (j++);
68 		struct selinux_mapping *p_out = current_mapping + j;
69 
70 		p_out->value = string_to_security_class(p_in->name);
71 		if (!p_out->value) {
72 			selinux_log(SELINUX_INFO,
73 				    "SELinux: Class %s not defined in policy.\n",
74 				    p_in->name);
75 			if (reject)
76 				goto err2;
77 			p_out->num_perms = 0;
78 			print_unknown_handle = true;
79 			continue;
80 		}
81 
82 		k = 0;
83 		while (p_in->perms[k]) {
84 			/* An empty permission string skips ahead */
85 			if (!*p_in->perms[k]) {
86 				k++;
87 				continue;
88 			}
89 			p_out->perms[k] = string_to_av_perm(p_out->value,
90 							    p_in->perms[k]);
91 			if (!p_out->perms[k]) {
92 				selinux_log(SELINUX_INFO,
93 					    "SELinux:  Permission %s in class %s not defined in policy.\n",
94 					    p_in->perms[k], p_in->name);
95 				if (reject)
96 					goto err2;
97 				print_unknown_handle = true;
98 			}
99 			k++;
100 		}
101 		p_out->num_perms = k;
102 	}
103 
104 	if (print_unknown_handle)
105 		selinux_log(SELINUX_INFO,
106 			    "SELinux: the above unknown classes and permissions will be %s\n",
107 			    deny ? "denied" : "allowed");
108 
109 	/* Set the mapping size here so the above lookups are "raw" */
110 	current_mapping_size = i;
111 	return 0;
112 err2:
113 	free(current_mapping);
114 	current_mapping = NULL;
115 	current_mapping_size = 0;
116 err:
117 	return -1;
118 }
119 
120 /*
121  * Get real, kernel values from mapped values
122  */
123 
124 security_class_t
unmap_class(security_class_t tclass)125 unmap_class(security_class_t tclass)
126 {
127 	if (tclass < current_mapping_size)
128 		return current_mapping[tclass].value;
129 
130 	/* If here no mapping set or the class requested is not valid. */
131 	if (current_mapping_size != 0) {
132 		errno = EINVAL;
133 		return 0;
134 	}
135 	else
136 		return tclass;
137 }
138 
139 access_vector_t
unmap_perm(security_class_t tclass,access_vector_t tperm)140 unmap_perm(security_class_t tclass, access_vector_t tperm)
141 {
142 	if (tclass < current_mapping_size) {
143 		unsigned i;
144 		access_vector_t kperm = 0;
145 
146 		for (i = 0; i < current_mapping[tclass].num_perms; i++)
147 			if (tperm & (1<<i)) {
148 				kperm |= current_mapping[tclass].perms[i];
149 				tperm &= ~(1<<i);
150 			}
151 		return kperm;
152 	}
153 
154 	/* If here no mapping set or the perm requested is not valid. */
155 	if (current_mapping_size != 0) {
156 		errno = EINVAL;
157 		return 0;
158 	}
159 	else
160 		return tperm;
161 }
162 
163 /*
164  * Get mapped values from real, kernel values
165  */
166 
167 security_class_t
map_class(security_class_t kclass)168 map_class(security_class_t kclass)
169 {
170 	security_class_t i;
171 
172 	for (i = 0; i < current_mapping_size; i++)
173 		if (current_mapping[i].value == kclass)
174 			return i;
175 
176 /* If here no mapping set or the class requested is not valid. */
177 	if (current_mapping_size != 0) {
178 		errno = EINVAL;
179 		return 0;
180 	}
181 	else
182 		return kclass;
183 }
184 
185 access_vector_t
map_perm(security_class_t tclass,access_vector_t kperm)186 map_perm(security_class_t tclass, access_vector_t kperm)
187 {
188 	if (tclass < current_mapping_size) {
189 		unsigned i;
190 		access_vector_t tperm = 0;
191 
192 		for (i = 0; i < current_mapping[tclass].num_perms; i++)
193 			if (kperm & current_mapping[tclass].perms[i]) {
194 				tperm |= 1<<i;
195 				kperm &= ~current_mapping[tclass].perms[i];
196 			}
197 
198 		if (tperm == 0) {
199 			errno = EINVAL;
200 			return 0;
201 		}
202 		else
203 			return tperm;
204 	}
205 	return kperm;
206 }
207 
208 void
map_decision(security_class_t tclass,struct av_decision * avd)209 map_decision(security_class_t tclass, struct av_decision *avd)
210 {
211 	if (tclass < current_mapping_size) {
212 		bool allow_unknown = (security_deny_unknown() == 0);
213 		struct selinux_mapping *mapping = &current_mapping[tclass];
214 		unsigned int i, n = mapping->num_perms;
215 		access_vector_t result;
216 
217 		for (i = 0, result = 0; i < n; i++) {
218 			if (avd->allowed & mapping->perms[i])
219 				result |= 1<<i;
220 			else if (allow_unknown && !mapping->perms[i])
221 				result |= 1<<i;
222 		}
223 		avd->allowed = result;
224 
225 		for (i = 0, result = 0; i < n; i++) {
226 			if (avd->decided & mapping->perms[i])
227 				result |= 1<<i;
228 			else if (allow_unknown && !mapping->perms[i])
229 				result |= 1<<i;
230 		}
231 		avd->decided = result;
232 
233 		for (i = 0, result = 0; i < n; i++)
234 			if (avd->auditallow & mapping->perms[i])
235 				result |= 1<<i;
236 		avd->auditallow = result;
237 
238 		for (i = 0, result = 0; i < n; i++) {
239 			if (avd->auditdeny & mapping->perms[i])
240 				result |= 1<<i;
241 			else if (!allow_unknown && !mapping->perms[i])
242 				result |= 1<<i;
243 		}
244 
245 		/*
246 		 * Make sure we audit denials for any permission check
247 		 * beyond the mapping->num_perms since this indicates
248 		 * a bug in the object manager.
249 		 */
250 		for (; i < (sizeof(result)*8); i++)
251 			result |= 1<<i;
252 		avd->auditdeny = result;
253 	}
254 }
255