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 #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 */
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
56 SELinuxArrayGet(SELinuxArrayRec
* rec
, unsigned key
)
58 return (rec
->size
> key
) ? rec
->array
[key
] : 0;
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
));
69 memset(rec
->array
+ rec
->size
, 0, (key
- rec
->size
+ 1) * sizeof(val
));
73 rec
->array
[key
] = val
;
78 SELinuxArrayFree(SELinuxArrayRec
* rec
, int free_elements
)
81 unsigned i
= rec
->size
;
84 free(rec
->array
[--i
]);
93 * Looks up a name in the selection or property mappings
96 SELinuxAtomToSIDLookup(Atom atom
, SELinuxObjectRec
* obj
, int map
, int polymap
)
98 const char *name
= NameForAtom(atom
);
104 /* Look in the mappings of names to contexts */
105 if (selabel_lookup_raw(label_hnd
, &ctx
, name
, map
) == 0) {
108 else if (errno
!= ENOENT
) {
109 ErrorF("SELinux: a property label lookup failed!\n");
112 else if (selabel_lookup_raw(label_hnd
, &ctx
, name
, polymap
) < 0) {
113 ErrorF("SELinux: a property label lookup failed!\n");
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");
128 * Looks up the SID corresponding to the given property or selection atom
131 SELinuxAtomToSID(Atom atom
, int prop
, SELinuxObjectRec
** obj_rtn
)
134 SELinuxObjectRec
*obj
;
135 int rc
, map
, polymap
;
137 rec
= SELinuxArrayGet(&arr_atoms
, atom
);
139 rec
= calloc(1, sizeof(SELinuxAtomRec
));
140 if (!rec
|| !SELinuxArraySet(&arr_atoms
, atom
, rec
))
146 map
= SELABEL_X_PROP
;
147 polymap
= SELABEL_X_POLYPROP
;
151 map
= SELABEL_X_SELN
;
152 polymap
= SELABEL_X_POLYSELN
;
156 rc
= SELinuxAtomToSIDLookup(atom
, obj
, map
, polymap
);
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
)
175 SELinuxObjectRec
*obj
;
178 /* Get the default context and polyinstantiation bit */
179 rc
= SELinuxAtomToSID(selection
, 0, &obj
);
183 /* Check for an override context next */
184 if (subj
->sel_use_sid
) {
185 tsid
= subj
->sel_use_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");
200 *poly_rtn
= obj
->poly
;
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
)
212 SELinuxObjectRec
*obj
;
213 security_id_t tsid
, tsid2
;
215 /* Get the default context and polyinstantiation bit */
216 rc
= SELinuxAtomToSID(property
, 1, &obj
);
220 /* Check for an override context next */
221 if (subj
->prp_use_sid
) {
222 tsid
= subj
->prp_use_sid
;
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");
232 /* Polyinstantiate if necessary to obtain the final SID */
235 if (avc_compute_member(subj
->sid
, tsid2
,
236 SECCLASS_X_PROPERTY
, &tsid
) < 0) {
237 ErrorF("SELinux: a compute_member call failed!\n");
244 *poly_rtn
= obj
->poly
;
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
);
261 sid
= SELinuxArrayGet(&arr_events
, type
);
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");
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");
275 /* Cache the SID value */
276 if (!SELinuxArraySet(&arr_events
, type
, sid
))
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");
291 SELinuxExtensionToSID(const char *name
, security_id_t
* sid_rtn
)
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");
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");
311 * Returns the object class corresponding to the given resource type.
314 SELinuxTypeToClass(RESTYPE type
)
318 tmp
= SELinuxArrayGet(&arr_types
, type
& TypeMask
);
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
;
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
;
350 SELinuxDefaultClientLabel(void)
354 if (selabel_lookup_raw(label_hnd
, &ctx
, "remote", SELABEL_X_CLIENT
) < 0)
355 FatalError("SELinux: failed to look up remote-client context\n");
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);
367 FatalError("SELinux: Failed to open x_contexts mapping in policy\n");
371 SELinuxLabelReset(void)
373 selabel_close(label_hnd
);
376 /* Free local state */
377 SELinuxArrayFree(&arr_types
, 0);
378 SELinuxArrayFree(&arr_events
, 0);
379 SELinuxArrayFree(&arr_atoms
, 1);