Skip to content

Commit 0ab542a

Browse files
committed
libsepol: Expand role attributes when expanding instead of when linking
Role attributes are being expanded during the linking phase rather than during the expand phase. This might be due to some concern over role attributes not being kept for the kernel policy. Instead of this, expand role attributes during the expand phase. One extra step is needed to make sure the pp and mod files end up the same as before. The role attributes in the base policy need to be expanded as well as those in the kernel policy. This is because of a side effect that occurs when compiling a base module. When a base module is compiled it is linked and expanded inorder to verify that linking and expansion will work. Even though the resulting kernel policy is discarded, the base module is changed because the linking phase expands the role attributes in the base module. With this change the pp files, mod files, and the final binary file (bin file) produced are identical to ones produced by an old toolchain without these changes. The only file that is different is the linked binary (lnk file). In the old toolchain, all roles in blocks are added to the role in the global scope and the role attributes are expanded, but this will be done again when the policy is expanded. Expanding a linked binary created with these patches using the old toolchain will produce the same kernel binary policy. Expanding a linked binary created with the old toolchain using the new toolchain will also produce the same kernel binary policy. Signed-off-by: James Carter <jwcart2@gmail.com>
1 parent 3e4a708 commit 0ab542a

File tree

2 files changed

+126
-182
lines changed

2 files changed

+126
-182
lines changed

libsepol/src/expand.c

Lines changed: 126 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -824,27 +824,18 @@ static int role_types_copy_callback(hashtab_key_t key, hashtab_datum_t datum, vo
824824
return 0;
825825
}
826826

827-
/* For the role attribute in the base module, escalate its counterpart's
828-
* types.types ebitmap in the out module to the counterparts of all the
829-
* regular role that belongs to the current role attribute. Note, must be
830-
* invoked after role_copy_callback so that state->rolemap is available.
831-
*/
832-
static int role_fix_callback(hashtab_key_t key, hashtab_datum_t datum,
833-
void *data)
827+
static int role_roles_copy_callback(hashtab_key_t key, hashtab_datum_t datum, void *data)
834828
{
835-
char *id, *base_reg_role_id;
836-
role_datum_t *role, *new_role, *regular_role;
829+
char *id;
830+
role_datum_t *role, *new_role;
837831
expand_state_t *state;
838-
ebitmap_node_t *rnode;
839-
unsigned int i;
840-
ebitmap_t mapped_roles;
832+
ebitmap_t mapped;
841833

842834
id = key;
843-
role = (role_datum_t *)datum;
835+
role = (role_datum_t *) datum;
844836
state = (expand_state_t *)data;
845837

846-
if (strcmp(id, OBJECT_R) == 0) {
847-
/* object_r is never a role attribute by far */
838+
if (role->flavor != ROLE_ATTRIB) {
848839
return 0;
849840
}
850841

@@ -853,39 +844,107 @@ static int role_fix_callback(hashtab_key_t key, hashtab_datum_t datum,
853844
return 0;
854845
}
855846

856-
if (role->flavor != ROLE_ATTRIB)
857-
return 0;
858-
859847
if (state->verbose)
860-
INFO(state->handle, "fixing role attribute %s", id);
848+
INFO(state->handle, "copying roles for role %s", id);
861849

862-
new_role =
863-
(role_datum_t *)hashtab_search(state->out->p_roles.table, id);
864-
865-
assert(new_role != NULL && new_role->flavor == ROLE_ATTRIB);
850+
new_role = (role_datum_t *)hashtab_search(state->out->p_roles.table, id);
851+
if (!new_role) {
852+
ERR(state->handle, "Could not find role %s", id);
853+
return -1;
854+
}
866855

867-
ebitmap_init(&mapped_roles);
868-
if (map_ebitmap(&role->roles, &mapped_roles, state->rolemap))
856+
/* convert roles in the role datum in the global symtab */
857+
if (map_ebitmap(&role->roles, &mapped, state->rolemap))
869858
return -1;
870-
if (ebitmap_union(&new_role->roles, &mapped_roles)) {
859+
if (ebitmap_union(&new_role->roles, &mapped)) {
871860
ERR(state->handle, "Out of memory!");
872-
ebitmap_destroy(&mapped_roles);
861+
ebitmap_destroy(&mapped);
873862
return -1;
874863
}
875-
ebitmap_destroy(&mapped_roles);
864+
ebitmap_destroy(&mapped);
865+
866+
return 0;
867+
}
868+
static int expand_role_attributes_in_attributes(sepol_handle_t *handle, policydb_t *p)
869+
{
870+
ebitmap_t attrs, roles;
871+
ebitmap_node_t *ni, *nj;
872+
unsigned int i, j, reps = 0, done = 0;
873+
role_datum_t *rd, *ad;
874+
875+
ebitmap_init(&attrs);
876+
for (i=0; i < p->p_roles.nprim; i++) {
877+
rd = p->role_val_to_struct[i];
878+
if (rd->flavor == ROLE_ATTRIB) {
879+
ebitmap_set_bit(&attrs, i, 1);
880+
}
881+
}
882+
883+
while (!done && reps < p->p_roles.nprim) {
884+
done = 1;
885+
reps++;
886+
ebitmap_for_each_positive_bit(&attrs, ni, i) {
887+
rd = p->role_val_to_struct[i];
888+
if (ebitmap_match_any(&rd->roles, &attrs)) {
889+
done = 0;
890+
if (ebitmap_get_bit(&rd->roles, i)) {
891+
ERR(handle, "Before: attr has own bit set: %d\n", i);
892+
}
893+
ebitmap_init(&roles);
894+
ebitmap_for_each_positive_bit(&rd->roles, nj, j) {
895+
if (ebitmap_get_bit(&attrs, j)) {
896+
ad = p->role_val_to_struct[j];
897+
ebitmap_union(&roles, &ad->roles);
898+
ebitmap_set_bit(&rd->roles, j, 0);
899+
}
900+
}
901+
ebitmap_union(&rd->roles, &roles);
902+
ebitmap_destroy(&roles);
903+
if (ebitmap_get_bit(&rd->roles, i)) {
904+
ERR(handle, "After: attr has own bit set: %d\n", i);
905+
done = 1; /* Just end early */
906+
}
907+
}
908+
}
909+
}
876910

877-
ebitmap_for_each_positive_bit(&role->roles, rnode, i) {
878-
/* take advantage of sym_val_to_name[]
879-
* of the base module */
880-
base_reg_role_id = state->base->p_role_val_to_name[i];
881-
regular_role = (role_datum_t *)hashtab_search(
882-
state->out->p_roles.table,
883-
base_reg_role_id);
884-
assert(regular_role != NULL &&
885-
regular_role->flavor == ROLE_ROLE);
886-
887-
if (ebitmap_union(&regular_role->types.types,
888-
&new_role->types.types)) {
911+
if (reps >= p->p_roles.nprim) {
912+
ERR(handle, "Had to bail: reps = %u\n", reps);
913+
}
914+
915+
ebitmap_destroy(&attrs);
916+
917+
return 0;
918+
}
919+
920+
/* For the role attribute in the base module, escalate its counterpart's
921+
* types.types ebitmap in the out module to the counterparts of all the
922+
* regular role that belongs to the current role attribute. Note, must be
923+
* invoked after role_copy_callback so that state->rolemap is available.
924+
*/
925+
static int role_fix_callback(hashtab_key_t key, hashtab_datum_t datum,
926+
void *data)
927+
{
928+
char *id;
929+
role_datum_t *attr, *role;
930+
expand_state_t *state;
931+
ebitmap_node_t *rnode;
932+
unsigned int i;
933+
934+
id = key;
935+
attr = (role_datum_t *)datum;
936+
state = (expand_state_t *)data;
937+
938+
if (attr->flavor != ROLE_ATTRIB)
939+
return 0;
940+
941+
if (state->verbose)
942+
INFO(state->handle, "fixing role attribute %s", id);
943+
944+
ebitmap_for_each_positive_bit(&attr->roles, rnode, i) {
945+
role = state->out->role_val_to_struct[i];
946+
assert(role != NULL && role->flavor == ROLE_ROLE);
947+
if (ebitmap_union(&role->types.types, &attr->types.types)) {
889948
ERR(state->handle, "Out of memory!");
890949
return -1;
891950
}
@@ -2494,7 +2553,7 @@ int expand_rule(sepol_handle_t * handle,
24942553
* the regular role belongs to could be properly handled by
24952554
* copy_role_trans and copy_role_allow.
24962555
*/
2497-
int role_set_expand(role_set_t * x, ebitmap_t * r, policydb_t * out, policydb_t * base, uint32_t * rolemap)
2556+
int role_set_expand(role_set_t * x, ebitmap_t * r, policydb_t * out, __attribute__ ((unused)) policydb_t * base, uint32_t * rolemap)
24982557
{
24992558
unsigned int i;
25002559
ebitmap_node_t *rnode;
@@ -2515,29 +2574,25 @@ int role_set_expand(role_set_t * x, ebitmap_t * r, policydb_t * out, policydb_t
25152574
ebitmap_init(&roles);
25162575

25172576
if (rolemap) {
2518-
assert(base != NULL);
2519-
ebitmap_for_each_positive_bit(&x->roles, rnode, i) {
2520-
/* take advantage of p_role_val_to_struct[]
2521-
* of the base module */
2522-
role = base->role_val_to_struct[i];
2577+
if (map_ebitmap(&x->roles, &mapped_roles, rolemap))
2578+
goto bad;
2579+
ebitmap_for_each_positive_bit(&mapped_roles, rnode, i) {
2580+
role = out->role_val_to_struct[i];
25232581
assert(role != NULL);
25242582
if (role->flavor == ROLE_ATTRIB) {
2525-
if (ebitmap_union(&roles,
2526-
&role->roles))
2583+
if (ebitmap_union(&roles, &role->roles))
25272584
goto bad;
25282585
} else {
25292586
if (ebitmap_set_bit(&roles, i, 1))
25302587
goto bad;
25312588
}
25322589
}
2533-
if (map_ebitmap(&roles, &mapped_roles, rolemap))
2534-
goto bad;
25352590
} else {
2536-
if (ebitmap_cpy(&mapped_roles, &x->roles))
2591+
if (ebitmap_cpy(&roles, &x->roles))
25372592
goto bad;
25382593
}
25392594

2540-
ebitmap_for_each_positive_bit(&mapped_roles, rnode, i) {
2595+
ebitmap_for_each_positive_bit(&roles, rnode, i) {
25412596
if (ebitmap_set_bit(r, i, 1))
25422597
goto bad;
25432598
}
@@ -3138,6 +3193,8 @@ int expand_module(sepol_handle_t * handle,
31383193
goto cleanup;
31393194
if (hashtab_map(state.base->p_roles.table, role_types_copy_callback, &state))
31403195
goto cleanup;
3196+
if (hashtab_map(state.base->p_roles.table, role_roles_copy_callback, &state))
3197+
goto cleanup;
31413198
for (curblock = state.base->global; curblock != NULL;
31423199
curblock = curblock->next) {
31433200
avrule_decl_t *decl = curblock->enabled;
@@ -3149,9 +3206,25 @@ int expand_module(sepol_handle_t * handle,
31493206
goto cleanup;
31503207
if (hashtab_map(decl->p_roles.table, role_types_copy_callback, &state))
31513208
goto cleanup;
3209+
if (hashtab_map(decl->p_roles.table, role_roles_copy_callback, &state))
3210+
goto cleanup;
3211+
}
3212+
/* Expand any role attributes found in the roles ebitmap of each role attribute */
3213+
if (expand_role_attributes_in_attributes(state.handle, state.out)) {
3214+
goto cleanup;
31523215
}
3216+
/* When compiling a base module, the base module is linked and expanded (to
3217+
* verify that it could be done) and the resulting kernel module is discarded.
3218+
* But the base module is changed while linking because role attributes are
3219+
* expanded while linking instead of being expanded when expanding.
3220+
* To duplicate that behavior, expand the base module role attributes.
3221+
*/
3222+
if (expand_role_attributes_in_attributes(state.handle, state.base)) {
3223+
goto cleanup;
3224+
}
3225+
31533226
/* Copy types in role attribute to all roles that belongs to it */
3154-
if (hashtab_map(state.base->p_roles.table, role_fix_callback, &state))
3227+
if (hashtab_map(state.out->p_roles.table, role_fix_callback, &state))
31553228
goto cleanup;
31563229

31573230
/* copy MLS's sensitivity level and categories - this needs to be done

libsepol/src/link.c

Lines changed: 0 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -2366,120 +2366,6 @@ static int prepare_base(link_state_t * state, uint32_t num_mod_decls)
23662366
return 0;
23672367
}
23682368

2369-
static int expand_role_attributes(hashtab_key_t key, hashtab_datum_t datum,
2370-
void * data)
2371-
{
2372-
char *id;
2373-
role_datum_t *role, *sub_attr;
2374-
link_state_t *state;
2375-
unsigned int i;
2376-
ebitmap_node_t *rnode;
2377-
2378-
id = key;
2379-
role = (role_datum_t *)datum;
2380-
state = (link_state_t *)data;
2381-
2382-
if (strcmp(id, OBJECT_R) == 0){
2383-
/* object_r is never a role attribute by far */
2384-
return 0;
2385-
}
2386-
2387-
if (role->flavor != ROLE_ATTRIB)
2388-
return 0;
2389-
2390-
if (state->verbose)
2391-
INFO(state->handle, "expanding role attribute %s", id);
2392-
2393-
restart:
2394-
ebitmap_for_each_positive_bit(&role->roles, rnode, i) {
2395-
sub_attr = state->base->role_val_to_struct[i];
2396-
if (sub_attr->flavor != ROLE_ATTRIB)
2397-
continue;
2398-
2399-
/* remove the sub role attribute from the parent
2400-
* role attribute's roles ebitmap */
2401-
if (ebitmap_set_bit(&role->roles, i, 0))
2402-
return -1;
2403-
2404-
/* loop dependency of role attributes */
2405-
if (sub_attr->s.value == role->s.value)
2406-
continue;
2407-
2408-
/* now go on to expand a sub role attribute
2409-
* by escalating its roles ebitmap */
2410-
if (ebitmap_union(&role->roles, &sub_attr->roles)) {
2411-
ERR(state->handle, "Out of memory!");
2412-
return -1;
2413-
}
2414-
2415-
/* sub_attr->roles may contain other role attributes,
2416-
* re-scan the parent role attribute's roles ebitmap */
2417-
goto restart;
2418-
}
2419-
2420-
return 0;
2421-
}
2422-
2423-
/* For any role attribute in a declaration's local symtab[SYM_ROLES] table,
2424-
* copy its roles ebitmap into its duplicate's in the base->p_roles.table.
2425-
*/
2426-
static int populate_decl_roleattributes(hashtab_key_t key,
2427-
hashtab_datum_t datum,
2428-
void *data)
2429-
{
2430-
char *id = key;
2431-
role_datum_t *decl_role, *base_role;
2432-
link_state_t *state = (link_state_t *)data;
2433-
2434-
decl_role = (role_datum_t *)datum;
2435-
2436-
if (strcmp(id, OBJECT_R) == 0) {
2437-
/* object_r is never a role attribute by far */
2438-
return 0;
2439-
}
2440-
2441-
if (decl_role->flavor != ROLE_ATTRIB)
2442-
return 0;
2443-
2444-
base_role = (role_datum_t *)hashtab_search(state->base->p_roles.table,
2445-
id);
2446-
assert(base_role != NULL && base_role->flavor == ROLE_ATTRIB);
2447-
2448-
if (ebitmap_union(&base_role->roles, &decl_role->roles)) {
2449-
ERR(state->handle, "Out of memory!");
2450-
return -1;
2451-
}
2452-
2453-
return 0;
2454-
}
2455-
2456-
static int populate_roleattributes(link_state_t *state, policydb_t *pol)
2457-
{
2458-
avrule_block_t *block;
2459-
avrule_decl_t *decl;
2460-
2461-
if (state->verbose)
2462-
INFO(state->handle, "Populating role-attribute relationship "
2463-
"from enabled declarations' local symtab.");
2464-
2465-
/* Iterate through all of the blocks skipping the first(which is the
2466-
* global block, is required to be present and can't have an else).
2467-
* If the block is disabled or not having an enabled decl, skip it.
2468-
*/
2469-
for (block = pol->global->next; block != NULL; block = block->next)
2470-
{
2471-
decl = block->enabled;
2472-
if (decl == NULL || decl->enabled == 0)
2473-
continue;
2474-
2475-
if (hashtab_map(decl->symtab[SYM_ROLES].table,
2476-
populate_decl_roleattributes, state))
2477-
return -1;
2478-
}
2479-
2480-
return 0;
2481-
}
2482-
24832369
/* Link a set of modules into a base module. This process is somewhat
24842370
* similar to an actual compiler: it requires a set of order dependent
24852371
* steps. The base and every module must have been indexed prior to
@@ -2576,21 +2462,6 @@ int link_modules(sepol_handle_t * handle,
25762462
goto cleanup;
25772463
}
25782464

2579-
/* Now that all role attribute's roles ebitmap have been settled,
2580-
* escalate sub role attribute's roles ebitmap into that of parent.
2581-
*
2582-
* First, since some role-attribute relationships could be recorded
2583-
* in some decl's local symtab(see get_local_role()), we need to
2584-
* populate them up to the base.p_roles table. */
2585-
if (populate_roleattributes(&state, state.base)) {
2586-
retval = SEPOL_EREQ;
2587-
goto cleanup;
2588-
}
2589-
2590-
/* Now do the escalation. */
2591-
if (hashtab_map(state.base->p_roles.table, expand_role_attributes,
2592-
&state))
2593-
goto cleanup;
25942465

25952466
retval = 0;
25962467
cleanup:

0 commit comments

Comments
 (0)