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
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 #ifdef HAVE_DIX_CONFIG_H
21 #include <dix-config.h>
24 #include <selinux/label.h>
27 #include "xselinuxint.h"
29 /* selection and property atom cache */
42 static struct selabel_handle
*label_hnd
;
44 /* Array of object classes indexed by resource type */
45 SELinuxArrayRec arr_types
;
47 /* Array of event SIDs indexed by event type */
48 SELinuxArrayRec arr_events
;
50 /* Array of property and selection SID structures */
51 SELinuxArrayRec arr_atoms
;
54 * Dynamic array helpers
57 SELinuxArrayGet(SELinuxArrayRec
* rec
, unsigned key
)
59 return (rec
->size
> key
) ? rec
->array
[key
] : 0;
63 SELinuxArraySet(SELinuxArrayRec
* rec
, unsigned key
, void *val
)
65 if (key
>= rec
->size
) {
66 /* Need to increase size of array */
67 rec
->array
= realloc(rec
->array
, (key
+ 1) * sizeof(val
));
70 memset(rec
->array
+ rec
->size
, 0, (key
- rec
->size
+ 1) * sizeof(val
));
74 rec
->array
[key
] = val
;
79 SELinuxArrayFree(SELinuxArrayRec
* rec
, int free_elements
)
82 unsigned i
= rec
->size
;
85 free(rec
->array
[--i
]);
94 * Looks up a name in the selection or property mappings
97 SELinuxAtomToSIDLookup(Atom atom
, SELinuxObjectRec
* obj
, int map
, int polymap
)
99 const char *name
= NameForAtom(atom
);
100 security_context_t ctx
;
105 /* Look in the mappings of names to contexts */
106 if (selabel_lookup_raw(label_hnd
, &ctx
, name
, map
) == 0) {
109 else if (errno
!= ENOENT
) {
110 ErrorF("SELinux: a property label lookup failed!\n");
113 else if (selabel_lookup_raw(label_hnd
, &ctx
, name
, polymap
) < 0) {
114 ErrorF("SELinux: a property label lookup failed!\n");
118 /* Get a SID for context */
119 if (avc_context_to_sid_raw(ctx
, &obj
->sid
) < 0) {
120 ErrorF("SELinux: a context_to_SID_raw call failed!\n");
129 * Looks up the SID corresponding to the given property or selection atom
132 SELinuxAtomToSID(Atom atom
, int prop
, SELinuxObjectRec
** obj_rtn
)
135 SELinuxObjectRec
*obj
;
136 int rc
, map
, polymap
;
138 rec
= SELinuxArrayGet(&arr_atoms
, atom
);
140 rec
= calloc(1, sizeof(SELinuxAtomRec
));
141 if (!rec
|| !SELinuxArraySet(&arr_atoms
, atom
, rec
))
147 map
= SELABEL_X_PROP
;
148 polymap
= SELABEL_X_POLYPROP
;
152 map
= SELABEL_X_SELN
;
153 polymap
= SELABEL_X_POLYSELN
;
157 rc
= SELinuxAtomToSIDLookup(atom
, obj
, map
, polymap
);
169 * Looks up a SID for a selection/subject pair
172 SELinuxSelectionToSID(Atom selection
, SELinuxSubjectRec
* subj
,
173 security_id_t
* sid_rtn
, int *poly_rtn
)
176 SELinuxObjectRec
*obj
;
179 /* Get the default context and polyinstantiation bit */
180 rc
= SELinuxAtomToSID(selection
, 0, &obj
);
184 /* Check for an override context next */
185 if (subj
->sel_use_sid
) {
186 tsid
= subj
->sel_use_sid
;
192 /* Polyinstantiate if necessary to obtain the final SID */
193 if (obj
->poly
&& avc_compute_member(subj
->sid
, obj
->sid
,
194 SECCLASS_X_SELECTION
, &tsid
) < 0) {
195 ErrorF("SELinux: a compute_member call failed!\n");
201 *poly_rtn
= obj
->poly
;
206 * Looks up a SID for a property/subject pair
209 SELinuxPropertyToSID(Atom property
, SELinuxSubjectRec
* subj
,
210 security_id_t
* sid_rtn
, int *poly_rtn
)
213 SELinuxObjectRec
*obj
;
214 security_id_t tsid
, tsid2
;
216 /* Get the default context and polyinstantiation bit */
217 rc
= SELinuxAtomToSID(property
, 1, &obj
);
221 /* Check for an override context next */
222 if (subj
->prp_use_sid
) {
223 tsid
= subj
->prp_use_sid
;
227 /* Perform a transition */
228 if (avc_compute_create(subj
->sid
, obj
->sid
, SECCLASS_X_PROPERTY
, &tsid
) < 0) {
229 ErrorF("SELinux: a compute_create call failed!\n");
233 /* Polyinstantiate if necessary to obtain the final SID */
236 if (avc_compute_member(subj
->sid
, tsid2
,
237 SECCLASS_X_PROPERTY
, &tsid
) < 0) {
238 ErrorF("SELinux: a compute_member call failed!\n");
245 *poly_rtn
= obj
->poly
;
250 * Looks up the SID corresponding to the given event type
253 SELinuxEventToSID(unsigned type
, security_id_t sid_of_window
,
254 SELinuxObjectRec
* sid_return
)
256 const char *name
= LookupEventName(type
);
258 security_context_t ctx
;
262 sid
= SELinuxArrayGet(&arr_events
, type
);
264 /* Look in the mappings of event names to contexts */
265 if (selabel_lookup_raw(label_hnd
, &ctx
, name
, SELABEL_X_EVENT
) < 0) {
266 ErrorF("SELinux: an event label lookup failed!\n");
269 /* Get a SID for context */
270 if (avc_context_to_sid_raw(ctx
, &sid
) < 0) {
271 ErrorF("SELinux: a context_to_SID_raw call failed!\n");
276 /* Cache the SID value */
277 if (!SELinuxArraySet(&arr_events
, type
, sid
))
281 /* Perform a transition to obtain the final SID */
282 if (avc_compute_create(sid_of_window
, sid
, SECCLASS_X_EVENT
,
283 &sid_return
->sid
) < 0) {
284 ErrorF("SELinux: a compute_create call failed!\n");
292 SELinuxExtensionToSID(const char *name
, security_id_t
* sid_rtn
)
294 security_context_t ctx
;
296 /* Look in the mappings of extension names to contexts */
297 if (selabel_lookup_raw(label_hnd
, &ctx
, name
, SELABEL_X_EXT
) < 0) {
298 ErrorF("SELinux: a property label lookup failed!\n");
301 /* Get a SID for context */
302 if (avc_context_to_sid_raw(ctx
, sid_rtn
) < 0) {
303 ErrorF("SELinux: a context_to_SID_raw call failed!\n");
312 * Returns the object class corresponding to the given resource type.
315 SELinuxTypeToClass(RESTYPE type
)
319 tmp
= SELinuxArrayGet(&arr_types
, type
& TypeMask
);
321 unsigned long class = SECCLASS_X_RESOURCE
;
323 if (type
& RC_DRAWABLE
)
324 class = SECCLASS_X_DRAWABLE
;
325 else if (type
== RT_GC
)
326 class = SECCLASS_X_GC
;
327 else if (type
== RT_FONT
)
328 class = SECCLASS_X_FONT
;
329 else if (type
== RT_CURSOR
)
330 class = SECCLASS_X_CURSOR
;
331 else if (type
== RT_COLORMAP
)
332 class = SECCLASS_X_COLORMAP
;
334 /* Need to do a string lookup */
335 const char *str
= LookupResourceName(type
);
337 if (!strcmp(str
, "PICTURE"))
338 class = SECCLASS_X_DRAWABLE
;
339 else if (!strcmp(str
, "GLYPHSET"))
340 class = SECCLASS_X_FONT
;
343 tmp
= (void *) class;
344 SELinuxArraySet(&arr_types
, type
& TypeMask
, tmp
);
347 return (security_class_t
) (unsigned long) tmp
;
351 SELinuxDefaultClientLabel(void)
353 security_context_t ctx
;
355 if (selabel_lookup_raw(label_hnd
, &ctx
, "remote", SELABEL_X_CLIENT
) < 0)
356 FatalError("SELinux: failed to look up remote-client context\n");
362 SELinuxLabelInit(void)
364 struct selinux_opt selabel_option
= { SELABEL_OPT_VALIDATE
, (char *) 1 };
366 label_hnd
= selabel_open(SELABEL_CTX_X
, &selabel_option
, 1);
368 FatalError("SELinux: Failed to open x_contexts mapping in policy\n");
372 SELinuxLabelReset(void)
374 selabel_close(label_hnd
);
377 /* Free local state */
378 SELinuxArrayFree(&arr_types
, 0);
379 SELinuxArrayFree(&arr_events
, 0);
380 SELinuxArrayFree(&arr_atoms
, 1);