blob: f9858ce1a053a2ac568fe3aef884f65d67a2fae0 [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>
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
18struct 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
24static struct selinux_mapping *current_mapping = NULL;
25static security_class_t current_mapping_size = 0;
26
27/*
28 * Mapping setting function
29 */
30
31int
32selinux_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;
88err2:
89 free(current_mapping);
90 current_mapping = NULL;
91 current_mapping_size = 0;
92err:
93 return -1;
94}
95
96/*
97 * Get real, kernel values from mapped values
98 */
99
100security_class_t
101unmap_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
110access_vector_t
111unmap_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
135security_class_t
136map_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
148access_vector_t
149map_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
168void
169map_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}