Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
libsepol,checkpolicy: convert rangetrans and filenametrans to hashtabs
range transition and name-based type transition rules were originally
simple unordered lists.  They were converted to hashtabs in the kernel
by commit 2f3e82d694d3d7a2db019db1bb63385fbc1066f3 ("selinux: convert range
transition list to a hashtab") and by commit
2463c26d50adc282d19317013ba0ff473823ca47 ("SELinux: put name based
create rules in a hashtable"), but left unchanged in libsepol and
checkpolicy. Convert libsepol and checkpolicy to use the same hashtabs
as the kernel for the range transitions and name-based type transitions.

With this change and the preceding one, it is possible to directly compare
a policy file generated by libsepol/checkpolicy and the kernel-generated
/sys/fs/selinux/policy pseudo file after normalizing them both through
checkpolicy.  To do so, you can run the following sequence of commands:

checkpolicy -M -b /etc/selinux/targeted/policy/policy.30 -o policy.1
checkpolicy -M -b /sys/fs/selinux/policy -o policy.2
cmp policy.1 policy.2

Normalizing the two files via checkpolicy is still necessary to ensure
consistent ordering of the avtab entries.  There may still be potential
for other areas of difference, e.g. xperms entries may lack a well-defined
order.

Signed-off-by: Stephen Smalley <sds@tycho.nsa.gov>
  • Loading branch information
stephensmalley committed Nov 28, 2016
1 parent 2e47b69 commit 8fdb225
Show file tree
Hide file tree
Showing 9 changed files with 604 additions and 328 deletions.
57 changes: 31 additions & 26 deletions checkpolicy/policy_define.c
Expand Up @@ -3220,11 +3220,12 @@ int define_filename_trans(void)
ebitmap_t e_tclasses;
ebitmap_node_t *snode, *tnode, *cnode;
filename_trans_t *ft;
filename_trans_datum_t *ftdatum;
filename_trans_rule_t *ftr;
type_datum_t *typdatum;
uint32_t otype;
unsigned int c, s, t;
int add;
int add, rc;

if (pass == 1) {
/* stype */
Expand Down Expand Up @@ -3308,40 +3309,44 @@ int define_filename_trans(void)
ebitmap_for_each_bit(&e_ttypes, tnode, t) {
if (!ebitmap_node_get_bit(tnode, t))
continue;

for (ft = policydbp->filename_trans; ft; ft = ft->next) {
if (ft->stype == (s + 1) &&
ft->ttype == (t + 1) &&
ft->tclass == (c + 1) &&
!strcmp(ft->name, name)) {
yyerror2("duplicate filename transition for: filename_trans %s %s %s:%s",
name,
policydbp->p_type_val_to_name[s],
policydbp->p_type_val_to_name[t],
policydbp->p_class_val_to_name[c]);
goto bad;
}
}

ft = malloc(sizeof(*ft));

ft = calloc(1, sizeof(*ft));
if (!ft) {
yyerror("out of memory");
goto bad;
}
memset(ft, 0, sizeof(*ft));

ft->next = policydbp->filename_trans;
policydbp->filename_trans = ft;

ft->stype = s+1;
ft->ttype = t+1;
ft->tclass = c+1;
ft->name = strdup(name);
if (!ft->name) {
yyerror("out of memory");
goto bad;
}
ft->stype = s + 1;
ft->ttype = t + 1;
ft->tclass = c + 1;
ft->otype = otype;

ftdatum = hashtab_search(policydbp->filename_trans,
(hashtab_key_t)ft);
if (ftdatum) {
yyerror2("duplicate filename transition for: filename_trans %s %s %s:%s",
name,
policydbp->p_type_val_to_name[s],
policydbp->p_type_val_to_name[t],
policydbp->p_class_val_to_name[c]);
goto bad;
}

ftdatum = calloc(1, sizeof(*ftdatum));
if (!ftdatum) {
yyerror("out of memory");
goto bad;
}
rc = hashtab_insert(policydbp->filename_trans,
(hashtab_key_t)ft,
ftdatum);
if (rc) {
yyerror("out of memory");
goto bad;
}
}
}

Expand Down
36 changes: 28 additions & 8 deletions checkpolicy/test/dispol.c
Expand Up @@ -330,18 +330,38 @@ static void display_role_trans(policydb_t *p, FILE *fp)
}
}

struct filenametr_display_args {
policydb_t *p;
FILE *fp;
};

static int filenametr_display(hashtab_key_t key,
hashtab_datum_t datum,
void *ptr)
{
struct filename_trans *ft = (struct filename_trans *)key;
struct filename_trans_datum *ftdatum = datum;
struct filenametr_display_args *args = ptr;
policydb_t *p = args->p;
FILE *fp = args->fp;

display_id(p, fp, SYM_TYPES, ft->stype - 1, "");
display_id(p, fp, SYM_TYPES, ft->ttype - 1, "");
display_id(p, fp, SYM_CLASSES, ft->tclass - 1, ":");
display_id(p, fp, SYM_TYPES, ftdatum->otype - 1, "");
fprintf(fp, " %s\n", ft->name);
return 0;
}


static void display_filename_trans(policydb_t *p, FILE *fp)
{
filename_trans_t *ft;
struct filenametr_display_args args;

fprintf(fp, "filename_trans rules:\n");
for (ft = p->filename_trans; ft; ft = ft->next) {
display_id(p, fp, SYM_TYPES, ft->stype - 1, "");
display_id(p, fp, SYM_TYPES, ft->ttype - 1, "");
display_id(p, fp, SYM_CLASSES, ft->tclass - 1, ":");
display_id(p, fp, SYM_TYPES, ft->otype - 1, "");
fprintf(fp, " %s\n", ft->name);
}
args.p = p;
args.fp = fp;
hashtab_map(p->filename_trans, filenametr_display, &args);
}

int menu(void)
Expand Down
79 changes: 48 additions & 31 deletions libsepol/cil/src/cil_binary.c
Expand Up @@ -1131,13 +1131,13 @@ int __cil_typetransition_to_avtab(policydb_t *pdb, const struct cil_db *db, stru
class_datum_t *sepol_obj = NULL;
struct cil_list *class_list;
type_datum_t *sepol_result = NULL;
filename_trans_t *new = NULL;
filename_trans_t *newkey = NULL;
filename_trans_datum_t *newdatum = NULL, *otype = NULL;
ebitmap_t src_bitmap, tgt_bitmap;
ebitmap_node_t *node1, *node2;
unsigned int i, j;
struct cil_list_item *c;
char *name = DATUM(typetrans->name)->name;
uint32_t *otype = NULL;

if (name == CIL_KEY_STAR) {
struct cil_type_rule trans;
Expand Down Expand Up @@ -1177,20 +1177,20 @@ int __cil_typetransition_to_avtab(policydb_t *pdb, const struct cil_db *db, stru
rc = __cil_get_sepol_class_datum(pdb, DATUM(c->data), &sepol_obj);
if (rc != SEPOL_OK) goto exit;

new = cil_malloc(sizeof(*new));
memset(new, 0, sizeof(*new));
new->stype = sepol_src->s.value;
new->ttype = sepol_tgt->s.value;
new->tclass = sepol_obj->s.value;
new->otype = sepol_result->s.value;
new->name = cil_strdup(name);
newkey = cil_calloc(1, sizeof(*newkey));
newdatum = cil_calloc(1, sizeof(*newdatum));
newkey->stype = sepol_src->s.value;
newkey->ttype = sepol_tgt->s.value;
newkey->tclass = sepol_obj->s.value;
newkey->name = cil_strdup(name);
newdatum->otype = sepol_result->s.value;

rc = hashtab_insert(filename_trans_table, (hashtab_key_t)new, &(new->otype));
rc = hashtab_insert(filename_trans_table, (hashtab_key_t)newkey, newdatum);
if (rc != SEPOL_OK) {
if (rc == SEPOL_EEXIST) {
add = CIL_FALSE;
otype = hashtab_search(filename_trans_table, (hashtab_key_t)new);
if (new->otype != *otype) {
otype = hashtab_search(filename_trans_table, (hashtab_key_t)newkey);
if (newdatum->otype != otype->otype) {
cil_log(CIL_ERR, "Conflicting name type transition rules\n");
} else {
rc = SEPOL_OK;
Expand All @@ -1201,11 +1201,17 @@ int __cil_typetransition_to_avtab(policydb_t *pdb, const struct cil_db *db, stru
}

if (add == CIL_TRUE) {
new->next = pdb->filename_trans;
pdb->filename_trans = new;
rc = hashtab_insert(pdb->filename_trans,
(hashtab_key_t)newkey,
newdatum);
if (rc != SEPOL_OK) {
cil_log(CIL_ERR, "Out of memory\n");
goto exit;
}
} else {
free(new->name);
free(new);
free(newkey->name);
free(newkey);
free(newdatum);
if (rc != SEPOL_OK) {
goto exit;
}
Expand Down Expand Up @@ -2943,7 +2949,8 @@ int cil_rangetransition_to_policydb(policydb_t *pdb, const struct cil_db *db, st
type_datum_t *sepol_tgt = NULL;
class_datum_t *sepol_class = NULL;
struct cil_list *class_list;
range_trans_t *new;
range_trans_t *newkey = NULL;
struct mls_range *newdatum = NULL;
ebitmap_t src_bitmap, tgt_bitmap;
ebitmap_node_t *node1, *node2;
unsigned int i, j;
Expand Down Expand Up @@ -2975,24 +2982,25 @@ int cil_rangetransition_to_policydb(policydb_t *pdb, const struct cil_db *db, st
rc = __cil_get_sepol_class_datum(pdb, DATUM(c->data), &sepol_class);
if (rc != SEPOL_OK) goto exit;

new = cil_malloc(sizeof(*new));
memset(new, 0, sizeof(range_trans_t));
new->source_type = sepol_src->s.value;
new->target_type = sepol_tgt->s.value;
new->target_class = sepol_class->s.value;
rc = __cil_levelrange_to_mls_range(pdb, rangetrans->range, &new->target_range);
newkey = cil_calloc(1, sizeof(*newkey));
newdatum = cil_calloc(1, sizeof(*newdatum));
newkey->source_type = sepol_src->s.value;
newkey->target_type = sepol_tgt->s.value;
newkey->target_class = sepol_class->s.value;
rc = __cil_levelrange_to_mls_range(pdb, rangetrans->range, newdatum);
if (rc != SEPOL_OK) {
free(new);
free(newkey);
free(newdatum);
goto exit;
}

rc = SEPOL_OK;
rc = hashtab_insert(range_trans_table, (hashtab_key_t)new, &(new->target_range));
rc = hashtab_insert(range_trans_table, (hashtab_key_t)newkey, newdatum);
if (rc != SEPOL_OK) {
if (rc == SEPOL_EEXIST) {
add = CIL_FALSE;
o_range = hashtab_search(range_trans_table, (hashtab_key_t)new);
if (!mls_range_eq(&new->target_range, o_range)) {
o_range = hashtab_search(range_trans_table, (hashtab_key_t)newkey);
if (!mls_range_eq(newdatum, o_range)) {
cil_log(CIL_ERR, "Conflicting Range transition rules\n");
} else {
rc = SEPOL_OK;
Expand All @@ -3003,11 +3011,20 @@ int cil_rangetransition_to_policydb(policydb_t *pdb, const struct cil_db *db, st
}

if (add == CIL_TRUE) {
new->next = pdb->range_tr;
pdb->range_tr = new;
rc = hashtab_insert(pdb->range_tr,
(hashtab_key_t)newkey,
newdatum);
if (rc != SEPOL_OK) {
mls_range_destroy(newdatum);
free(newdatum);
free(newkey);
cil_log(CIL_ERR, "Out of memory\n");
goto exit;
}
} else {
mls_range_destroy(&new->target_range);
free(new);
mls_range_destroy(newdatum);
free(newdatum);
free(newkey);
if (rc != SEPOL_OK) {
goto exit;
}
Expand Down
40 changes: 40 additions & 0 deletions libsepol/include/sepol/policydb/context.h
Expand Up @@ -50,6 +50,46 @@ static inline int mls_context_cpy(context_struct_t * dst,
return 0;
}

/*
* Sets both levels in the MLS range of 'dst' to the low level of 'src'.
*/
static inline int mls_context_cpy_low(context_struct_t *dst, context_struct_t *src)
{
int rc;

dst->range.level[0].sens = src->range.level[0].sens;
rc = ebitmap_cpy(&dst->range.level[0].cat, &src->range.level[0].cat);
if (rc)
goto out;

dst->range.level[1].sens = src->range.level[0].sens;
rc = ebitmap_cpy(&dst->range.level[1].cat, &src->range.level[0].cat);
if (rc)
ebitmap_destroy(&dst->range.level[0].cat);
out:
return rc;
}

/*
* Sets both levels in the MLS range of 'dst' to the high level of 'src'.
*/
static inline int mls_context_cpy_high(context_struct_t *dst, context_struct_t *src)
{
int rc;

dst->range.level[0].sens = src->range.level[1].sens;
rc = ebitmap_cpy(&dst->range.level[0].cat, &src->range.level[1].cat);
if (rc)
goto out;

dst->range.level[1].sens = src->range.level[1].sens;
rc = ebitmap_cpy(&dst->range.level[1].cat, &src->range.level[1].cat);
if (rc)
ebitmap_destroy(&dst->range.level[0].cat);
out:
return rc;
}

static inline int mls_context_cmp(context_struct_t * c1, context_struct_t * c2)
{
return (mls_level_eq(&c1->range.level[0], &c2->range.level[0]) &&
Expand Down
18 changes: 9 additions & 9 deletions libsepol/include/sepol/policydb/policydb.h
Expand Up @@ -162,10 +162,12 @@ typedef struct filename_trans {
uint32_t ttype;
uint32_t tclass;
char *name;
uint32_t otype;
struct filename_trans *next;
} filename_trans_t;

typedef struct filename_trans_datum {
uint32_t otype; /* expected of new object */
} filename_trans_datum_t;

/* Type attributes */
typedef struct type_datum {
symtab_datum_t s;
Expand Down Expand Up @@ -218,8 +220,6 @@ typedef struct range_trans {
uint32_t source_type;
uint32_t target_type;
uint32_t target_class;
mls_range_t target_range;
struct range_trans *next;
} range_trans_t;

/* Boolean data type */
Expand Down Expand Up @@ -555,9 +555,6 @@ typedef struct policydb {
/* role transitions */
role_trans_t *role_tr;

/* type transition rules with a 'name' component */
filename_trans_t *filename_trans;

/* role allows */
role_allow_t *role_allow;

Expand All @@ -570,8 +567,11 @@ typedef struct policydb {
fixed labeling behavior. */
genfs_t *genfs;

/* range transitions */
range_trans_t *range_tr;
/* range transitions table (range_trans_key -> mls_range) */
hashtab_t range_tr;

/* file transitions with the last path component */
hashtab_t filename_trans;

ebitmap_t *type_attr_map;

Expand Down

0 comments on commit 8fdb225

Please sign in to comment.