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