@@ -132,7 +132,7 @@ static int render_av_rule(avtab_key_t * key, avtab_datum_t * datum, uint32_t wha
if (key->specified & AVTAB_TRANSITION) {
fprintf(fp, "type_transition ");
render_key(key, p, fp);
- render_type(datum->data, p, fp);
+ render_type(datum->trans->otype, p, fp);
fprintf(fp, ";\n");
}
if (key->specified & AVTAB_MEMBER) {
@@ -975,28 +975,34 @@ static int __cil_insert_type_rule(policydb_t *pdb, uint32_t kind, uint32_t src,
int rc = SEPOL_OK;
avtab_key_t avtab_key;
avtab_datum_t avtab_datum;
+ avtab_trans_t trans;
avtab_ptr_t existing;
avtab_key.source_type = src;
avtab_key.target_type = tgt;
avtab_key.target_class = obj;
+ memset(&avtab_datum, 0, sizeof(avtab_datum_t));
+ memset(&trans, 0, sizeof(avtab_trans_t));
+
switch (kind) {
case CIL_TYPE_TRANSITION:
avtab_key.specified = AVTAB_TRANSITION;
+ trans.otype = res;
+ avtab_datum.trans = &trans;
break;
case CIL_TYPE_CHANGE:
avtab_key.specified = AVTAB_CHANGE;
+ avtab_datum.data = res;
break;
case CIL_TYPE_MEMBER:
avtab_key.specified = AVTAB_MEMBER;
+ avtab_datum.data = res;
break;
default:
rc = SEPOL_ERR;
goto exit;
}
-
- avtab_datum.data = res;
existing = avtab_search_node(&pdb->te_avtab, &avtab_key);
if (existing) {
@@ -1004,13 +1010,17 @@ static int __cil_insert_type_rule(policydb_t *pdb, uint32_t kind, uint32_t src,
* A warning should have been previously given if there is a
* non-duplicate rule using the same key.
*/
- if (existing->datum.data != res) {
+ uint32_t existing_otype =
+ existing->key.specified & AVTAB_TRANSITION
+ ? existing->datum.trans->otype
+ : existing->datum.data;
+ if (existing_otype != res) {
cil_log(CIL_ERR, "Conflicting type rules (scontext=%s tcontext=%s tclass=%s result=%s), existing=%s\n",
pdb->p_type_val_to_name[src - 1],
pdb->p_type_val_to_name[tgt - 1],
pdb->p_class_val_to_name[obj - 1],
pdb->p_type_val_to_name[res - 1],
- pdb->p_type_val_to_name[existing->datum.data - 1]);
+ pdb->p_type_val_to_name[existing_otype - 1]);
cil_log(CIL_ERR, "Expanded from type rule (scontext=%s tcontext=%s tclass=%s result=%s)\n",
cil_rule->src_str, cil_rule->tgt_str, cil_rule->obj_str, cil_rule->result_str);
rc = SEPOL_ERR;
@@ -1037,13 +1047,17 @@ static int __cil_insert_type_rule(policydb_t *pdb, uint32_t kind, uint32_t src,
search_datum = cil_cond_av_list_search(&avtab_key, other_list);
if (search_datum == NULL) {
- if (existing->datum.data != res) {
+ uint32_t existing_otype =
+ existing->key.specified & AVTAB_TRANSITION
+ ? existing->datum.trans->otype
+ : existing->datum.data;
+ if (existing_otype != res) {
cil_log(CIL_ERR, "Conflicting type rules (scontext=%s tcontext=%s tclass=%s result=%s), existing=%s\n",
pdb->p_type_val_to_name[src - 1],
pdb->p_type_val_to_name[tgt - 1],
pdb->p_class_val_to_name[obj - 1],
pdb->p_type_val_to_name[res - 1],
- pdb->p_type_val_to_name[existing->datum.data - 1]);
+ pdb->p_type_val_to_name[existing_otype - 1]);
cil_log(CIL_ERR, "Expanded from type rule (scontext=%s tcontext=%s tclass=%s result=%s)\n",
cil_rule->src_str, cil_rule->tgt_str, cil_rule->obj_str, cil_rule->result_str);
rc = SEPOL_ERR;
@@ -70,6 +70,10 @@ typedef struct avtab_key {
uint16_t specified; /* what fields are specified */
} avtab_key_t;
+typedef struct avtab_trans {
+ uint32_t otype; /* resulting type of the new object */
+} avtab_trans_t;
+
typedef struct avtab_extended_perms {
#define AVTAB_XPERMS_IOCTLFUNCTION 0x01
@@ -81,7 +85,8 @@ typedef struct avtab_extended_perms {
} avtab_extended_perms_t;
typedef struct avtab_datum {
- uint32_t data; /* access vector or type */
+ uint32_t data; /* access vector, member or change value */
+ avtab_trans_t *trans; /* transition value */
avtab_extended_perms_t *xperms;
} avtab_datum_t;
@@ -94,6 +94,7 @@ avtab_insert_node(avtab_t * h, int hvalue, avtab_ptr_t prev, avtab_key_t * key,
avtab_datum_t * datum)
{
avtab_ptr_t newnode;
+ avtab_trans_t *trans;
avtab_extended_perms_t *xperms;
newnode = (avtab_ptr_t) malloc(sizeof(struct avtab_node));
@@ -117,6 +118,16 @@ avtab_insert_node(avtab_t * h, int hvalue, avtab_ptr_t prev, avtab_key_t * key,
* So copy data so it is set in the avtab
*/
newnode->datum.data = datum->data;
+ } else if (key->specified & AVTAB_TRANSITION) {
+ trans = calloc(1, sizeof(*trans));
+ if (trans == NULL) {
+ free(newnode);
+ return NULL;
+ }
+ if (datum->trans) /* else caller populates transition */
+ *trans = *(datum->trans);
+
+ newnode->datum.trans = trans;
} else {
newnode->datum = *datum;
}
@@ -317,6 +328,8 @@ void avtab_destroy(avtab_t * h)
while (cur != NULL) {
if (cur->key.specified & AVTAB_XPERMS) {
free(cur->datum.xperms);
+ } else if (cur->key.specified & AVTAB_TRANSITION) {
+ free(cur->datum.trans);
}
temp = cur;
cur = cur->next;
@@ -440,6 +453,7 @@ int avtab_read_item(struct policy_file *fp, uint32_t vers, avtab_t * a,
uint32_t buf32[8], items, items2, val;
avtab_key_t key;
avtab_datum_t datum;
+ avtab_trans_t trans;
avtab_extended_perms_t xperms;
unsigned set;
unsigned int i;
@@ -447,6 +461,7 @@ int avtab_read_item(struct policy_file *fp, uint32_t vers, avtab_t * a,
memset(&key, 0, sizeof(avtab_key_t));
memset(&datum, 0, sizeof(avtab_datum_t));
+ memset(&trans, 0, sizeof(avtab_trans_t));
memset(&xperms, 0, sizeof(avtab_extended_perms_t));
if (vers < POLICYDB_VERSION_AVTAB) {
@@ -509,7 +524,14 @@ int avtab_read_item(struct policy_file *fp, uint32_t vers, avtab_t * a,
return -1;
}
key.specified = spec_order[i] | enabled;
- datum.data = le32_to_cpu(buf32[items++]);
+ if (key.specified & AVTAB_TRANSITION) {
+ trans.otype =
+ le32_to_cpu(buf32[items++]);
+ datum.trans = &trans;
+ } else {
+ datum.data =
+ le32_to_cpu(buf32[items++]);
+ }
rc = insertf(a, &key, &datum, p);
if (rc)
return rc;
@@ -571,6 +593,14 @@ int avtab_read_item(struct policy_file *fp, uint32_t vers, avtab_t * a,
for (i = 0; i < ARRAY_SIZE(xperms.perms); i++)
xperms.perms[i] = le32_to_cpu(buf32[i]);
datum.xperms = &xperms;
+ } else if (key.specified & AVTAB_TRANSITION) {
+ rc = next_entry(buf32, fp, sizeof(uint32_t));
+ if (rc < 0) {
+ ERR(fp->handle, "truncated entry");
+ return -1;
+ }
+ trans.otype = le32_to_cpu(*buf32);
+ datum.trans = &trans;
} else {
rc = next_entry(buf32, fp, sizeof(uint32_t));
if (rc < 0) {
@@ -1746,7 +1746,7 @@ static int expand_terule_helper(sepol_handle_t * handle,
if (conflict) {
avdatump = &node->datum;
if (specified & AVRULE_TRANSITION) {
- oldtype = avdatump->data;
+ oldtype = avdatump->trans->otype;
} else if (specified & AVRULE_MEMBER) {
oldtype = avdatump->data;
} else if (specified & AVRULE_CHANGE) {
@@ -1789,7 +1789,11 @@ static int expand_terule_helper(sepol_handle_t * handle,
}
avdatump = &node->datum;
- avdatump->data = remapped_data;
+ if (specified & AVRULE_TRANSITION) {
+ avdatump->trans->otype = remapped_data;
+ } else {
+ avdatump->data = remapped_data;
+ }
cur = cur->next;
}
@@ -1703,7 +1703,8 @@ static char *xperms_to_str(avtab_extended_perms_t *xperms)
static char *avtab_node_to_str(struct policydb *pdb, avtab_key_t *key, avtab_datum_t *datum)
{
- uint32_t data = datum->data;
+ uint32_t data = key->specified & AVTAB_TRANSITION
+ ? datum->trans->otype : datum->data;
type_datum_t *type;
const char *flavor, *tgt;
char *src, *class, *perms, *new;
@@ -1681,7 +1681,8 @@ exit:
static char *avtab_node_to_str(struct policydb *pdb, avtab_key_t *key, avtab_datum_t *datum)
{
- uint32_t data = datum->data;
+ uint32_t data = key->specified & AVTAB_TRANSITION
+ ? datum->trans->otype : datum->data;
type_datum_t *type;
const char *flavor, *src, *tgt, *class, *perms, *new;
char *rule = NULL;
@@ -308,6 +308,8 @@ static void optimize_avtab(policydb_t *p, const struct type_vec *type_map)
*cur = tmp->next;
if (tmp->key.specified & AVTAB_XPERMS)
free(tmp->datum.xperms);
+ if (tmp->key.specified & AVTAB_TRANSITION)
+ free(tmp->datum.trans);
free(tmp);
tab->nel--;
@@ -427,6 +429,8 @@ static void optimize_cond_avtab(policydb_t *p, const struct type_vec *type_map)
*cur = tmp->next;
if (tmp->key.specified & AVTAB_XPERMS)
free(tmp->datum.xperms);
+ if (tmp->key.specified & AVTAB_TRANSITION)
+ free(tmp->datum.trans);
free(tmp);
tab->nel--;
@@ -832,7 +832,9 @@ static int validate_avtab_key_and_datum(avtab_key_t *k, avtab_datum_t *d, void *
if (validate_avtab_key(k, 0, margs->policy, margs->flavors))
return -1;
- if ((k->specified & AVTAB_TYPE) && validate_simpletype(d->data, margs->policy, margs->flavors))
+ uint32_t otype = k->specified & AVTAB_TRANSITION
+ ? d->trans->otype : d->data;
+ if ((k->specified & AVTAB_TYPE) && validate_simpletype(otype, margs->policy, margs->flavors))
return -1;
if ((k->specified & AVTAB_XPERMS) && validate_xperms(d->xperms))
@@ -1423,7 +1423,10 @@ static int sepol_compute_sid(sepol_security_id_t ssid,
if (avdatum) {
/* Use the type from the type transition/member/change rule. */
- newcontext.type = avdatum->data;
+ if (specified & AVTAB_TRANSITION)
+ newcontext.type = avdatum->trans->otype;
+ else
+ newcontext.type = avdatum->data;
}
/* Check for class-specific changes. */
@@ -190,14 +190,20 @@ static int avtab_write_item(policydb_t * p,
ERR(fp->handle, "missing node");
return POLICYDB_ERROR;
}
- buf32[items++] =
- cpu_to_le32(node->datum.data);
+ uint32_t data =
+ node->key.specified & AVTAB_TRANSITION
+ ? node->datum.trans->otype
+ : node->datum.data;
+ buf32[items++] = cpu_to_le32(data);
set--;
node->merged = 1;
}
}
} else {
- buf32[items++] = cpu_to_le32(cur->datum.data);
+ uint32_t data = cur->key.specified & AVTAB_TRANSITION
+ ? cur->datum.trans->otype
+ : cur->datum.data;
+ buf32[items++] = cpu_to_le32(data);
cur->merged = 1;
set--;
}
@@ -256,6 +262,11 @@ static int avtab_write_item(policydb_t * p,
items = put_entry(buf32, sizeof(uint32_t),8,fp);
if (items != 8)
return POLICYDB_ERROR;
+ } else if (cur->key.specified & AVTAB_TRANSITION) {
+ buf32[0] = cpu_to_le32(cur->datum.trans->otype);
+ items = put_entry(buf32, sizeof(uint32_t), 1, fp);
+ if (items != 1)
+ return POLICYDB_ERROR;
} else {
buf32[0] = cpu_to_le32(cur->datum.data);
items = put_entry(buf32, sizeof(uint32_t), 1, fp);