xselinux: Factor out some dynamic array code into common helpers.
Signed-off-by: Eamon Walsh <ewalsh@tycho.nsa.gov>
This commit is contained in:
parent
ae8891ba0b
commit
0493935691
|
@ -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;
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user