blob: f205804b9d1a2acbcbbf741023699c9d2a77d436 [file] [log] [blame]
Stephen Smalleyf0740362012-01-04 12:30:47 -05001/*
2 * Class and permission mappings.
3 */
4
5#include <errno.h>
6#include <stdio.h>
7#include <stdlib.h>
8#include <stdarg.h>
Stephen Smalleyf0740362012-01-04 12:30:47 -05009#include <selinux/selinux.h>
10#include <selinux/avc.h>
11#include "mapping.h"
12
13/*
14 * Class and permission mappings
15 */
16
17struct 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
23static struct selinux_mapping *current_mapping = NULL;
24static security_class_t current_mapping_size = 0;
25
26/*
27 * Mapping setting function
28 */
29
30int
31selinux_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;
Eric Parisc01e95f2012-11-29 09:41:38 -050069 while (p_in->perms[k]) {
Stephen Smalleyf0740362012-01-04 12:30:47 -050070 /* 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;
87err2:
88 free(current_mapping);
89 current_mapping = NULL;
90 current_mapping_size = 0;
91err:
92 return -1;
93}
94
95/*
96 * Get real, kernel values from mapped values
97 */
98
99security_class_t
100unmap_class(security_class_t tclass)
101{
102 if (tclass < current_mapping_size)
103 return current_mapping[tclass].value;
104
Richard Haines574290e2011-03-30 17:10:05 +0100105 /* 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;
Stephen Smalleyf0740362012-01-04 12:30:47 -0500112}
113
114access_vector_t
115unmap_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)) {
Stephen Smalleyf0740362012-01-04 12:30:47 -0500123 kperm |= current_mapping[tclass].perms[i];
124 tperm &= ~(1<<i);
125 }
Stephen Smalleyf0740362012-01-04 12:30:47 -0500126 return kperm;
127 }
128
Richard Haines574290e2011-03-30 17:10:05 +0100129 /* 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;
Stephen Smalleyf0740362012-01-04 12:30:47 -0500136}
137
138/*
139 * Get mapped values from real, kernel values
140 */
141
142security_class_t
143map_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
Richard Haines574290e2011-03-30 17:10:05 +0100151/* 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;
Stephen Smalleyf0740362012-01-04 12:30:47 -0500158}
159
160access_vector_t
161map_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 }
Stephen Smalleyf0740362012-01-04 12:30:47 -0500172
Richard Haines574290e2011-03-30 17:10:05 +0100173 if (tperm == 0) {
174 errno = EINVAL;
175 return 0;
176 }
177 else
178 return tperm;
179 }
Stephen Smalleyf0740362012-01-04 12:30:47 -0500180 return kperm;
181}
182
183void
184map_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}