xselinux: Factor out some dynamic array code into common helpers.

Signed-off-by: Eamon Walsh <ewalsh@tycho.nsa.gov>
This commit is contained in:
Eamon Walsh 2009-08-31 21:20:53 -04:00
parent ae8891ba0b
commit 0493935691

View File

@ -32,21 +32,60 @@ typedef struct {
SELinuxObjectRec sel; SELinuxObjectRec sel;
} SELinuxAtomRec; } SELinuxAtomRec;
/* dynamic array */
typedef struct {
unsigned size;
void **array;
} SELinuxArrayRec;
/* labeling handle */ /* labeling handle */
static struct selabel_handle *label_hnd; static struct selabel_handle *label_hnd;
/* Array of object classes indexed by resource type */ /* Array of object classes indexed by resource type */
static security_class_t *knownTypes; SELinuxArrayRec arr_types;
static unsigned numKnownTypes;
/* Array of event SIDs indexed by event type */ /* Array of event SIDs indexed by event type */
static security_id_t *knownEvents; SELinuxArrayRec arr_events;
static unsigned numKnownEvents;
/* Array of property and selection SID structures */ /* Array of property and selection SID structures */
static SELinuxAtomRec *knownAtoms; SELinuxArrayRec arr_atoms;
static unsigned numKnownAtoms;
/*
* Dynamic array helpers
*/
static void *
SELinuxArrayGet(SELinuxArrayRec *rec, unsigned key)
{
return (rec->size > key) ? rec->array[key] : 0;
}
static int
SELinuxArraySet(SELinuxArrayRec *rec, unsigned key, void *val)
{
if (key >= rec->size) {
/* Need to increase size of array */
rec->array = xrealloc(rec->array, (key + 1) * sizeof(val));
if (!rec->array)
return FALSE;
memset(rec->array + rec->size, 0, (key - rec->size + 1) * sizeof(val));
rec->size = key + 1;
}
rec->array[key] = val;
return TRUE;
}
static void
SELinuxArrayFree(SELinuxArrayRec *rec, int free_elements)
{
if (free_elements) {
unsigned i = rec->size;
while (i)
xfree(rec->array[--i]);
}
xfree(rec->array);
rec->size = 0;
rec->array = NULL;
}
/* /*
* Looks up a name in the selection or property mappings * Looks up a name in the selection or property mappings
@ -87,26 +126,23 @@ SELinuxAtomToSIDLookup(Atom atom, SELinuxObjectRec *obj, int map, int polymap)
int int
SELinuxAtomToSID(Atom atom, int prop, SELinuxObjectRec **obj_rtn) SELinuxAtomToSID(Atom atom, int prop, SELinuxObjectRec **obj_rtn)
{ {
SELinuxAtomRec *rec;
SELinuxObjectRec *obj; SELinuxObjectRec *obj;
int rc, map, polymap; int rc, map, polymap;
if (atom >= numKnownAtoms) { rec = SELinuxArrayGet(&arr_atoms, atom);
/* Need to increase size of atoms array */ if (!rec) {
unsigned size = sizeof(SELinuxAtomRec); rec = xcalloc(1, sizeof(SELinuxAtomRec));
knownAtoms = xrealloc(knownAtoms, (atom + 1) * size); if (!rec || !SELinuxArraySet(&arr_atoms, atom, rec))
if (!knownAtoms)
return BadAlloc; return BadAlloc;
memset(knownAtoms + numKnownAtoms, 0,
(atom - numKnownAtoms + 1) * size);
numKnownAtoms = atom + 1;
} }
if (prop) { if (prop) {
obj = &knownAtoms[atom].prp; obj = &rec->prp;
map = SELABEL_X_PROP; map = SELABEL_X_PROP;
polymap = SELABEL_X_POLYPROP; polymap = SELABEL_X_POLYPROP;
} else { } else {
obj = &knownAtoms[atom].sel; obj = &rec->sel;
map = SELABEL_X_SELN; map = SELABEL_X_SELN;
polymap = SELABEL_X_POLYSELN; polymap = SELABEL_X_POLYSELN;
} }
@ -218,36 +254,33 @@ SELinuxEventToSID(unsigned type, security_id_t sid_of_window,
SELinuxObjectRec *sid_return) SELinuxObjectRec *sid_return)
{ {
const char *name = LookupEventName(type); const char *name = LookupEventName(type);
security_id_t sid;
security_context_t ctx; security_context_t ctx;
type &= 127; type &= 127;
if (type >= numKnownEvents) { sid = SELinuxArrayGet(&arr_events, type);
/* Need to increase size of classes array */ if (!sid) {
unsigned size = sizeof(security_id_t);
knownEvents = xrealloc(knownEvents, (type + 1) * size);
if (!knownEvents)
return BadAlloc;
memset(knownEvents + numKnownEvents, 0,
(type - numKnownEvents + 1) * size);
numKnownEvents = type + 1;
}
if (!knownEvents[type]) {
/* Look in the mappings of event names to contexts */ /* Look in the mappings of event names to contexts */
if (selabel_lookup_raw(label_hnd, &ctx, name, SELABEL_X_EVENT) < 0) { if (selabel_lookup_raw(label_hnd, &ctx, name, SELABEL_X_EVENT) < 0) {
ErrorF("SELinux: an event label lookup failed!\n"); ErrorF("SELinux: an event label lookup failed!\n");
return BadValue; return BadValue;
} }
/* Get a SID for context */ /* Get a SID for context */
if (avc_context_to_sid_raw(ctx, knownEvents + type) < 0) { if (avc_context_to_sid_raw(ctx, &sid) < 0) {
ErrorF("SELinux: a context_to_SID_raw call failed!\n"); ErrorF("SELinux: a context_to_SID_raw call failed!\n");
freecon(ctx);
return BadAlloc; return BadAlloc;
} }
freecon(ctx); freecon(ctx);
/* Cache the SID value */
if (!SELinuxArraySet(&arr_events, type, sid)) {
sidput(sid);
return BadAlloc;
}
} }
/* Perform a transition to obtain the final SID */ /* Perform a transition to obtain the final SID */
if (avc_compute_create(sid_of_window, knownEvents[type], SECCLASS_X_EVENT, if (avc_compute_create(sid_of_window, sid, SECCLASS_X_EVENT,
&sid_return->sid) < 0) { &sid_return->sid) < 0) {
ErrorF("SELinux: a compute_create call failed!\n"); ErrorF("SELinux: a compute_create call failed!\n");
return BadValue; return BadValue;
@ -282,44 +315,36 @@ SELinuxExtensionToSID(const char *name, security_id_t *sid_rtn)
security_class_t security_class_t
SELinuxTypeToClass(RESTYPE type) SELinuxTypeToClass(RESTYPE type)
{ {
RESTYPE fulltype = type; void *tmp;
type &= TypeMask;
if (type >= numKnownTypes) { tmp = SELinuxArrayGet(&arr_types, type & TypeMask);
/* Need to increase size of classes array */ if (!tmp) {
unsigned size = sizeof(security_class_t); unsigned long class = SECCLASS_X_RESOURCE;
knownTypes = xrealloc(knownTypes, (type + 1) * size);
if (!knownTypes) if (type & RC_DRAWABLE)
return 0; class = SECCLASS_X_DRAWABLE;
memset(knownTypes + numKnownTypes, 0, else if (type == RT_GC)
(type - numKnownTypes + 1) * size); class = SECCLASS_X_GC;
numKnownTypes = type + 1; else if (type == RT_FONT)
class = SECCLASS_X_FONT;
else if (type == RT_CURSOR)
class = SECCLASS_X_CURSOR;
else if (type == RT_COLORMAP)
class = SECCLASS_X_COLORMAP;
else {
/* Need to do a string lookup */
const char *str = LookupResourceName(type);
if (!strcmp(str, "PICTURE"))
class = SECCLASS_X_DRAWABLE;
else if (!strcmp(str, "GLYPHSET"))
class = SECCLASS_X_FONT;
}
tmp = (void *)class;
SELinuxArraySet(&arr_types, type & TypeMask, tmp);
} }
if (!knownTypes[type]) { return (security_class_t)(unsigned long)tmp;
const char *str;
knownTypes[type] = SECCLASS_X_RESOURCE;
if (fulltype & RC_DRAWABLE)
knownTypes[type] = SECCLASS_X_DRAWABLE;
if (fulltype == RT_GC)
knownTypes[type] = SECCLASS_X_GC;
if (fulltype == RT_FONT)
knownTypes[type] = SECCLASS_X_FONT;
if (fulltype == RT_CURSOR)
knownTypes[type] = SECCLASS_X_CURSOR;
if (fulltype == RT_COLORMAP)
knownTypes[type] = SECCLASS_X_COLORMAP;
/* Need to do a string lookup */
str = LookupResourceName(fulltype);
if (!strcmp(str, "PICTURE"))
knownTypes[type] = SECCLASS_X_DRAWABLE;
if (!strcmp(str, "GLYPHSET"))
knownTypes[type] = SECCLASS_X_FONT;
}
return knownTypes[type];
} }
security_context_t security_context_t
@ -350,15 +375,7 @@ SELinuxLabelReset(void)
label_hnd = NULL; label_hnd = NULL;
/* Free local state */ /* Free local state */
xfree(knownAtoms); SELinuxArrayFree(&arr_types, 0);
knownAtoms = NULL; SELinuxArrayFree(&arr_events, 0);
numKnownAtoms = 0; SELinuxArrayFree(&arr_atoms, 1);
xfree(knownEvents);
knownEvents = NULL;
numKnownEvents = 0;
xfree(knownTypes);
knownTypes = NULL;
numKnownTypes = 0;
} }