xwayland/glamor: Disable GLAMOR after GBM cleanup
[xserver.git] / Xext / xselinux_label.c
blob4110f9074fbc7e89081dfa963e93c39033abb1d8
1 /************************************************************
3 Author: Eamon Walsh <ewalsh@tycho.nsa.gov>
5 Permission to use, copy, modify, distribute, and sell this software and its
6 documentation for any purpose is hereby granted without fee, provided that
7 this permission notice appear in supporting documentation. This permission
8 notice shall be included in all copies or substantial portions of the
9 Software.
11 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
12 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
14 AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
15 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
16 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 ********************************************************/
20 #include <dix-config.h>
22 #include <selinux/label.h>
24 #include "dix/registry_priv.h"
26 #include "xselinuxint.h"
28 /* selection and property atom cache */
29 typedef struct {
30 SELinuxObjectRec prp;
31 SELinuxObjectRec sel;
32 } SELinuxAtomRec;
34 /* dynamic array */
35 typedef struct {
36 unsigned size;
37 void **array;
38 } SELinuxArrayRec;
40 /* labeling handle */
41 static struct selabel_handle *label_hnd;
43 /* Array of object classes indexed by resource type */
44 SELinuxArrayRec arr_types;
46 /* Array of event SIDs indexed by event type */
47 SELinuxArrayRec arr_events;
49 /* Array of property and selection SID structures */
50 SELinuxArrayRec arr_atoms;
53 * Dynamic array helpers
55 static void *
56 SELinuxArrayGet(SELinuxArrayRec * rec, unsigned key)
58 return (rec->size > key) ? rec->array[key] : 0;
61 static int
62 SELinuxArraySet(SELinuxArrayRec * rec, unsigned key, void *val)
64 if (key >= rec->size) {
65 /* Need to increase size of array */
66 rec->array = reallocarray(rec->array, key + 1, sizeof(val));
67 if (!rec->array)
68 return FALSE;
69 memset(rec->array + rec->size, 0, (key - rec->size + 1) * sizeof(val));
70 rec->size = key + 1;
73 rec->array[key] = val;
74 return TRUE;
77 static void
78 SELinuxArrayFree(SELinuxArrayRec * rec, int free_elements)
80 if (free_elements) {
81 unsigned i = rec->size;
83 while (i)
84 free(rec->array[--i]);
87 free(rec->array);
88 rec->size = 0;
89 rec->array = NULL;
93 * Looks up a name in the selection or property mappings
95 static int
96 SELinuxAtomToSIDLookup(Atom atom, SELinuxObjectRec * obj, int map, int polymap)
98 const char *name = NameForAtom(atom);
99 char *ctx;
100 int rc = Success;
102 obj->poly = 1;
104 /* Look in the mappings of names to contexts */
105 if (selabel_lookup_raw(label_hnd, &ctx, name, map) == 0) {
106 obj->poly = 0;
108 else if (errno != ENOENT) {
109 ErrorF("SELinux: a property label lookup failed!\n");
110 return BadValue;
112 else if (selabel_lookup_raw(label_hnd, &ctx, name, polymap) < 0) {
113 ErrorF("SELinux: a property label lookup failed!\n");
114 return BadValue;
117 /* Get a SID for context */
118 if (avc_context_to_sid_raw(ctx, &obj->sid) < 0) {
119 ErrorF("SELinux: a context_to_SID_raw call failed!\n");
120 rc = BadAlloc;
123 freecon(ctx);
124 return rc;
128 * Looks up the SID corresponding to the given property or selection atom
131 SELinuxAtomToSID(Atom atom, int prop, SELinuxObjectRec ** obj_rtn)
133 SELinuxAtomRec *rec;
134 SELinuxObjectRec *obj;
135 int rc, map, polymap;
137 rec = SELinuxArrayGet(&arr_atoms, atom);
138 if (!rec) {
139 rec = calloc(1, sizeof(SELinuxAtomRec));
140 if (!rec || !SELinuxArraySet(&arr_atoms, atom, rec))
141 return BadAlloc;
144 if (prop) {
145 obj = &rec->prp;
146 map = SELABEL_X_PROP;
147 polymap = SELABEL_X_POLYPROP;
149 else {
150 obj = &rec->sel;
151 map = SELABEL_X_SELN;
152 polymap = SELABEL_X_POLYSELN;
155 if (!obj->sid) {
156 rc = SELinuxAtomToSIDLookup(atom, obj, map, polymap);
157 if (rc != Success)
158 goto out;
161 *obj_rtn = obj;
162 rc = Success;
163 out:
164 return rc;
168 * Looks up a SID for a selection/subject pair
171 SELinuxSelectionToSID(Atom selection, SELinuxSubjectRec * subj,
172 security_id_t * sid_rtn, int *poly_rtn)
174 int rc;
175 SELinuxObjectRec *obj;
176 security_id_t tsid;
178 /* Get the default context and polyinstantiation bit */
179 rc = SELinuxAtomToSID(selection, 0, &obj);
180 if (rc != Success)
181 return rc;
183 /* Check for an override context next */
184 if (subj->sel_use_sid) {
185 tsid = subj->sel_use_sid;
186 goto out;
189 tsid = obj->sid;
191 /* Polyinstantiate if necessary to obtain the final SID */
192 if (obj->poly && avc_compute_member(subj->sid, obj->sid,
193 SECCLASS_X_SELECTION, &tsid) < 0) {
194 ErrorF("SELinux: a compute_member call failed!\n");
195 return BadValue;
197 out:
198 *sid_rtn = tsid;
199 if (poly_rtn)
200 *poly_rtn = obj->poly;
201 return Success;
205 * Looks up a SID for a property/subject pair
208 SELinuxPropertyToSID(Atom property, SELinuxSubjectRec * subj,
209 security_id_t * sid_rtn, int *poly_rtn)
211 int rc;
212 SELinuxObjectRec *obj;
213 security_id_t tsid, tsid2;
215 /* Get the default context and polyinstantiation bit */
216 rc = SELinuxAtomToSID(property, 1, &obj);
217 if (rc != Success)
218 return rc;
220 /* Check for an override context next */
221 if (subj->prp_use_sid) {
222 tsid = subj->prp_use_sid;
223 goto out;
226 /* Perform a transition */
227 if (avc_compute_create(subj->sid, obj->sid, SECCLASS_X_PROPERTY, &tsid) < 0) {
228 ErrorF("SELinux: a compute_create call failed!\n");
229 return BadValue;
232 /* Polyinstantiate if necessary to obtain the final SID */
233 if (obj->poly) {
234 tsid2 = tsid;
235 if (avc_compute_member(subj->sid, tsid2,
236 SECCLASS_X_PROPERTY, &tsid) < 0) {
237 ErrorF("SELinux: a compute_member call failed!\n");
238 return BadValue;
241 out:
242 *sid_rtn = tsid;
243 if (poly_rtn)
244 *poly_rtn = obj->poly;
245 return Success;
249 * Looks up the SID corresponding to the given event type
252 SELinuxEventToSID(unsigned type, security_id_t sid_of_window,
253 SELinuxObjectRec * sid_return)
255 const char *name = LookupEventName(type);
256 security_id_t sid;
257 char *ctx;
259 type &= 127;
261 sid = SELinuxArrayGet(&arr_events, type);
262 if (!sid) {
263 /* Look in the mappings of event names to contexts */
264 if (selabel_lookup_raw(label_hnd, &ctx, name, SELABEL_X_EVENT) < 0) {
265 ErrorF("SELinux: an event label lookup failed!\n");
266 return BadValue;
268 /* Get a SID for context */
269 if (avc_context_to_sid_raw(ctx, &sid) < 0) {
270 ErrorF("SELinux: a context_to_SID_raw call failed!\n");
271 freecon(ctx);
272 return BadAlloc;
274 freecon(ctx);
275 /* Cache the SID value */
276 if (!SELinuxArraySet(&arr_events, type, sid))
277 return BadAlloc;
280 /* Perform a transition to obtain the final SID */
281 if (avc_compute_create(sid_of_window, sid, SECCLASS_X_EVENT,
282 &sid_return->sid) < 0) {
283 ErrorF("SELinux: a compute_create call failed!\n");
284 return BadValue;
287 return Success;
291 SELinuxExtensionToSID(const char *name, security_id_t * sid_rtn)
293 char *ctx;
295 /* Look in the mappings of extension names to contexts */
296 if (selabel_lookup_raw(label_hnd, &ctx, name, SELABEL_X_EXT) < 0) {
297 ErrorF("SELinux: a property label lookup failed!\n");
298 return BadValue;
300 /* Get a SID for context */
301 if (avc_context_to_sid_raw(ctx, sid_rtn) < 0) {
302 ErrorF("SELinux: a context_to_SID_raw call failed!\n");
303 freecon(ctx);
304 return BadAlloc;
306 freecon(ctx);
307 return Success;
311 * Returns the object class corresponding to the given resource type.
313 security_class_t
314 SELinuxTypeToClass(RESTYPE type)
316 void *tmp;
318 tmp = SELinuxArrayGet(&arr_types, type & TypeMask);
319 if (!tmp) {
320 unsigned long class = SECCLASS_X_RESOURCE;
322 if (type & RC_DRAWABLE)
323 class = SECCLASS_X_DRAWABLE;
324 else if (type == X11_RESTYPE_GC)
325 class = SECCLASS_X_GC;
326 else if (type == X11_RESTYPE_FONT)
327 class = SECCLASS_X_FONT;
328 else if (type == X11_RESTYPE_CURSOR)
329 class = SECCLASS_X_CURSOR;
330 else if (type == X11_RESTYPE_COLORMAP)
331 class = SECCLASS_X_COLORMAP;
332 else {
333 /* Need to do a string lookup */
334 const char *str = LookupResourceName(type);
336 if (!strcmp(str, "PICTURE"))
337 class = SECCLASS_X_DRAWABLE;
338 else if (!strcmp(str, "GLYPHSET"))
339 class = SECCLASS_X_FONT;
342 tmp = (void *) class;
343 SELinuxArraySet(&arr_types, type & TypeMask, tmp);
346 return (security_class_t) (unsigned long) tmp;
349 char *
350 SELinuxDefaultClientLabel(void)
352 char *ctx;
354 if (selabel_lookup_raw(label_hnd, &ctx, "remote", SELABEL_X_CLIENT) < 0)
355 FatalError("SELinux: failed to look up remote-client context\n");
357 return ctx;
360 void
361 SELinuxLabelInit(void)
363 struct selinux_opt selabel_option = { SELABEL_OPT_VALIDATE, (char *) 1 };
365 label_hnd = selabel_open(SELABEL_CTX_X, &selabel_option, 1);
366 if (!label_hnd)
367 FatalError("SELinux: Failed to open x_contexts mapping in policy\n");
370 void
371 SELinuxLabelReset(void)
373 selabel_close(label_hnd);
374 label_hnd = NULL;
376 /* Free local state */
377 SELinuxArrayFree(&arr_types, 0);
378 SELinuxArrayFree(&arr_events, 0);
379 SELinuxArrayFree(&arr_atoms, 1);