export expand_module_avrules

This commit is contained in:
Dan Walsh 2011-09-01 17:07:56 -04:00
parent 6eec04097e
commit 3c75a3b3ff
2 changed files with 374 additions and 6 deletions

View File

@ -1,8 +1,373 @@
diff --git a/libsepol/include/sepol/policydb/conditional.h b/libsepol/include/sepol/policydb/conditional.h
index a8ed694..1fd1638 100644
--- a/libsepol/include/sepol/policydb/conditional.h
+++ b/libsepol/include/sepol/policydb/conditional.h
@@ -77,15 +77,16 @@ typedef struct cond_node {
/* these true/false lists point into te_avtab when that is used */
cond_av_list_t *true_list;
cond_av_list_t *false_list;
- /* and these are using during parsing and for modules */
+ /* and these are used during parsing and for modules */
avrule_t *avtrue_list;
avrule_t *avfalse_list;
/* these fields are not written to binary policy */
unsigned int nbools;
uint32_t bool_ids[COND_MAX_BOOLS];
uint32_t expr_pre_comp;
- /* */
struct cond_node *next;
+#define COND_NODE_FLAGS_TUNABLE 0x01 /* a tunable conditional */
+ uint32_t flags;
} cond_node_t;
extern int cond_evaluate_expr(policydb_t * p, cond_expr_t * expr);
diff --git a/libsepol/include/sepol/policydb/policydb.h b/libsepol/include/sepol/policydb/policydb.h
index 5320bc8..1848a7b 100644
--- a/libsepol/include/sepol/policydb/policydb.h
+++ b/libsepol/include/sepol/policydb/policydb.h
@@ -210,6 +210,8 @@ typedef struct range_trans {
typedef struct cond_bool_datum {
symtab_datum_t s;
int state;
+#define COND_BOOL_FLAGS_TUNABLE 0x01 /* is this a tunable? */
+ uint32_t flags;
} cond_bool_datum_t;
struct cond_node;
@@ -683,9 +685,10 @@ extern int policydb_set_target_platform(policydb_t *p, int platform);
#define MOD_POLICYDB_VERSION_FILENAME_TRANS 11
#define MOD_POLICYDB_VERSION_ROLETRANS 12
#define MOD_POLICYDB_VERSION_ROLEATTRIB 13
+#define MOD_POLICYDB_VERSION_TUNABLE_SEP 14
#define MOD_POLICYDB_VERSION_MIN MOD_POLICYDB_VERSION_BASE
-#define MOD_POLICYDB_VERSION_MAX MOD_POLICYDB_VERSION_ROLEATTRIB
+#define MOD_POLICYDB_VERSION_MAX MOD_POLICYDB_VERSION_TUNABLE_SEP
#define POLICYDB_CONFIG_MLS 1
diff --git a/libsepol/src/conditional.c b/libsepol/src/conditional.c
index 1482387..ea47cdd 100644
--- a/libsepol/src/conditional.c
+++ b/libsepol/src/conditional.c
@@ -160,6 +160,7 @@ cond_node_t *cond_node_create(policydb_t * p, cond_node_t * node)
for (i = 0; i < min(node->nbools, COND_MAX_BOOLS); i++)
new_node->bool_ids[i] = node->bool_ids[i];
new_node->expr_pre_comp = node->expr_pre_comp;
+ new_node->flags = node->flags;
}
return new_node;
@@ -563,8 +564,8 @@ static int bool_isvalid(cond_bool_datum_t * b)
return 1;
}
-int cond_read_bool(policydb_t * p
- __attribute__ ((unused)), hashtab_t h,
+int cond_read_bool(policydb_t * p,
+ hashtab_t h,
struct policy_file *fp)
{
char *key = 0;
@@ -596,6 +597,15 @@ int cond_read_bool(policydb_t * p
if (rc < 0)
goto err;
key[len] = 0;
+
+ if (p->policy_type != POLICY_KERN &&
+ p->policyvers >= MOD_POLICYDB_VERSION_TUNABLE_SEP) {
+ rc = next_entry(buf, fp, sizeof(uint32_t));
+ if (rc < 0)
+ goto err;
+ booldatum->flags = le32_to_cpu(buf[0]);
+ }
+
if (hashtab_insert(h, key, booldatum))
goto err;
@@ -810,6 +820,14 @@ static int cond_read_node(policydb_t * p, cond_node_t * node, void *fp)
goto err;
}
+ if (p->policy_type != POLICY_KERN &&
+ p->policyvers >= MOD_POLICYDB_VERSION_TUNABLE_SEP) {
+ rc = next_entry(buf, fp, sizeof(uint32_t));
+ if (rc < 0)
+ goto err;
+ node->flags = le32_to_cpu(buf[0]);
+ }
+
return 0;
err:
cond_node_destroy(node);
diff --git a/libsepol/src/expand.c b/libsepol/src/expand.c
index 06f11f4..4458de6 100644
--- a/libsepol/src/expand.c
+++ b/libsepol/src/expand.c
@@ -1014,6 +1014,11 @@ static int bool_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
return 0;
}
+ if (bool->flags & COND_BOOL_FLAGS_TUNABLE) {
+ /* Skip tunables */
+ return 0;
+ }
+
if (state->verbose)
INFO(state->handle, "copying boolean %s", id);
@@ -1046,6 +1051,7 @@ static int bool_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
state->boolmap[bool->s.value - 1] = new_bool->s.value;
new_bool->state = bool->state;
+ new_bool->flags = bool->flags;
return 0;
}
@@ -1940,6 +1946,13 @@ static int cond_node_copy(expand_state_t * state, cond_node_t * cn)
if (cond_node_copy(state, cn->next)) {
return -1;
}
+
+ /* If current cond_node_t is of tunable, its effective branch
+ * has been appended to its home decl->avrules list during link
+ * and now we should just skip it. */
+ if (cn->flags & COND_NODE_FLAGS_TUNABLE)
+ return 0;
+
if (cond_normalize_expr(state->base, cn)) {
ERR(state->handle, "Error while normalizing conditional");
return -1;
diff --git a/libsepol/src/libsepol.map b/libsepol/src/libsepol.map
index 719e5b7..4044977 100644
--- a/libsepol/src/libsepol.map
+++ b/libsepol/src/libsepol.map
@@ -1,5 +1,6 @@
{
global:
+ expand_module_avrules;
sepol_module_package_*; sepol_link_modules; sepol_expand_module; sepol_link_packages;
sepol_bool_*; sepol_genbools*;
sepol_context_*; sepol_mls_*; sepol_check_context;
diff --git a/libsepol/src/link.c b/libsepol/src/link.c
index 421c47b..4b0fd16 100644
--- a/libsepol/src/link.c
+++ b/libsepol/src/link.c
@@ -587,7 +587,17 @@ static int bool_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
}
state->base->p_bools.nprim++;
base_bool = new_bool;
-
+ base_bool->flags = booldatum->flags;
+ } else if ((booldatum->flags & COND_BOOL_FLAGS_TUNABLE) !=
+ (base_bool->flags & COND_BOOL_FLAGS_TUNABLE)) {
+ /* A mismatch between boolean/tunable declaration
+ * and usage(for example, a boolean used in the
+ * tunable_policy macro), then the tunables would
+ * be filtered out and only the effective branch
+ * of the cond_node would be preserved. */
+ INFO(state->handle,
+ "%s: Mismatch between boolean/tunable definition "
+ "and usage for %s", state->cur_mod_name, id);
}
/* Get the scope info for this boolean to see if this is the declaration,
@@ -595,9 +605,12 @@ static int bool_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
scope = hashtab_search(state->cur->policy->p_bools_scope.table, id);
if (!scope)
return SEPOL_ERR;
- if (scope->scope == SCOPE_DECL)
+ if (scope->scope == SCOPE_DECL) {
base_bool->state = booldatum->state;
-
+ /* Only the declaration rather than requirement
+ * decides if it is a boolean or tunable. */
+ base_bool->state = booldatum->state;
+ }
state->cur->map[SYM_BOOLS][booldatum->s.value - 1] = base_bool->s.value;
return 0;
@@ -2451,6 +2464,92 @@ static int populate_roleattributes(link_state_t *state, policydb_t *pol)
return 0;
}
+static void separate_tunables(link_state_t *state, policydb_t *pol)
+{
+ avrule_block_t *block;
+ avrule_decl_t *decl;
+ cond_node_t *cur_node;
+ cond_expr_t *cur_expr;
+ int cur_state;
+ avrule_t *tail, *to_be_appended;
+
+ if (state->verbose)
+ INFO(state->handle, "Separating tunables from booleans.");
+
+ /* Iterate through all cond_node of all enabled decls, if a cond_node
+ * is about tunable, caculate its state value and concatenate one of
+ * its avrule list to the current decl->avrules list.
+ *
+ * Note, such tunable cond_node would be skipped over in expansion,
+ * so we won't have to worry about removing it from decl->cond_list
+ * here :-)
+ *
+ * If tunables and booleans co-exist in the expression of a cond_node,
+ * then tunables would be "transformed" as booleans.
+ */
+ for (block = pol->global; block != NULL; block = block->next) {
+ decl = block->enabled;
+ if (decl == NULL || decl->enabled == 0)
+ continue;
+
+ tail = decl->avrules;
+ while (tail && tail->next)
+ tail = tail->next;
+
+ for (cur_node = decl->cond_list; cur_node != NULL;
+ cur_node = cur_node->next) {
+ int booleans, tunables, i;
+ cond_bool_datum_t *booldatum;
+ cond_bool_datum_t *tmp[COND_EXPR_MAXDEPTH];
+
+ booleans = tunables = 0;
+ memset(tmp, 0, sizeof(cond_bool_datum_t *) * COND_EXPR_MAXDEPTH);
+
+ for (cur_expr = cur_node->expr; cur_expr != NULL;
+ cur_expr = cur_expr->next) {
+ if (cur_expr->expr_type != COND_BOOL)
+ continue;
+ booldatum = pol->bool_val_to_struct[cur_expr->bool - 1];
+ if (booldatum->flags & COND_BOOL_FLAGS_TUNABLE)
+ tmp[tunables++] = booldatum;
+ else
+ booleans++;
+ }
+
+ if (tunables && booleans) {
+ /* Tunable mixed with boolean */
+ for (i = 0; i < tunables; i++)
+ tmp[i]->flags &= ~COND_BOOL_FLAGS_TUNABLE;
+ } else if (tunables && !booleans) {
+ /* Pure tunable conditional */
+ cur_node->flags |= COND_NODE_FLAGS_TUNABLE;
+ cur_state = cond_evaluate_expr(pol, cur_node->expr);
+ if (cur_state == -1) {
+ printf("Expression result was "
+ "undefined, skipping all"
+ "rules\n");
+ continue;
+ }
+
+ to_be_appended = (cur_state == 1) ?
+ cur_node->avtrue_list : cur_node->avfalse_list;
+
+ if (tail)
+ tail->next = to_be_appended;
+ else
+ tail = decl->avrules = to_be_appended;
+
+ /* Update the tail of decl->avrules for
+ * further concatenation */
+ while (tail && tail->next)
+ tail = tail->next;
+
+ cur_node->avtrue_list = cur_node->avfalse_list = NULL;
+ }
+ }
+ }
+}
+
/* Link a set of modules into a base module. This process is somewhat
* similar to an actual compiler: it requires a set of order dependent
* steps. The base and every module must have been indexed prior to
@@ -2587,6 +2686,11 @@ int link_modules(sepol_handle_t * handle,
&state))
goto cleanup;
+ /* Append tunable's avtrue_list or avfalse_list to the avrules list
+ * of its home decl depending on its state value, so that the effect
+ * rules of a tunable would be added to te_avtab permanently. */
+ separate_tunables(&state, state.base);
+
retval = 0;
cleanup:
for (i = 0; modules != NULL && i < len; i++) {
diff --git a/libsepol/src/policydb.c b/libsepol/src/policydb.c
index 017aeca..136b450 100644
--- a/libsepol/src/policydb.c
+++ b/libsepol/src/policydb.c
@@ -221,6 +221,13 @@ static struct policydb_compat_info policydb_compat[] = {
.target_platform = SEPOL_TARGET_SELINUX,
},
{
+ .type = POLICY_BASE,
+ .version = MOD_POLICYDB_VERSION_TUNABLE_SEP,
+ .sym_num = SYM_NUM,
+ .ocon_num = OCON_NODE6 + 1,
+ .target_platform = SEPOL_TARGET_SELINUX,
+ },
+ {
.type = POLICY_MOD,
.version = MOD_POLICYDB_VERSION_BASE,
.sym_num = SYM_NUM,
@@ -290,6 +297,13 @@ static struct policydb_compat_info policydb_compat[] = {
.ocon_num = 0,
.target_platform = SEPOL_TARGET_SELINUX,
},
+ {
+ .type = POLICY_MOD,
+ .version = MOD_POLICYDB_VERSION_TUNABLE_SEP,
+ .sym_num = SYM_NUM,
+ .ocon_num = 0,
+ .target_platform = SEPOL_TARGET_SELINUX,
+ },
};
#if 0
diff --git a/libsepol/src/write.c b/libsepol/src/write.c
index 290e036..7257b0b 100644
index 290e036..e34ab52 100644
--- a/libsepol/src/write.c
+++ b/libsepol/src/write.c
@@ -972,6 +972,19 @@ static int role_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
@@ -607,6 +607,7 @@ static int cond_write_bool(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
unsigned int items, items2;
struct policy_data *pd = ptr;
struct policy_file *fp = pd->fp;
+ struct policydb *p = pd->p;
booldatum = (cond_bool_datum_t *) datum;
@@ -621,6 +622,15 @@ static int cond_write_bool(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
items = put_entry(key, 1, len, fp);
if (items != len)
return POLICYDB_ERROR;
+
+ if (p->policy_type != POLICY_KERN &&
+ p->policyvers >= MOD_POLICYDB_VERSION_TUNABLE_SEP) {
+ buf[0] = cpu_to_le32(booldatum->flags);
+ items = put_entry(buf, sizeof(uint32_t), 1, fp);
+ if (items != 1)
+ return POLICYDB_ERROR;
+ }
+
return POLICYDB_SUCCESS;
}
@@ -727,6 +737,14 @@ static int cond_write_node(policydb_t * p,
return POLICYDB_ERROR;
}
+ if (p->policy_type != POLICY_KERN &&
+ p->policyvers >= MOD_POLICYDB_VERSION_TUNABLE_SEP) {
+ buf[0] = cpu_to_le32(node->flags);
+ items = put_entry(buf, sizeof(uint32_t), 1, fp);
+ if (items != 1)
+ return POLICYDB_ERROR;
+ }
+
return POLICYDB_SUCCESS;
}
@@ -972,6 +990,19 @@ static int role_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
role = (role_datum_t *) datum;
@ -22,7 +387,7 @@ index 290e036..7257b0b 100644
len = strlen(key);
items = 0;
buf[items++] = cpu_to_le32(len);
@@ -1795,6 +1808,19 @@ static int type_attr_uncount(hashtab_key_t key __attribute__ ((unused)),
@@ -1795,6 +1826,19 @@ static int type_attr_uncount(hashtab_key_t key __attribute__ ((unused)),
return 0;
}
@ -42,7 +407,7 @@ index 290e036..7257b0b 100644
/*
* Write the configuration data in a policy database
* structure to a policy database binary representation
@@ -1926,7 +1952,7 @@ int policydb_write(policydb_t * p, struct policy_file *fp)
@@ -1926,7 +1970,7 @@ int policydb_write(policydb_t * p, struct policy_file *fp)
num_syms = info->sym_num;
for (i = 0; i < num_syms; i++) {
buf[0] = cpu_to_le32(p->symtab[i].nprim);
@ -51,7 +416,7 @@ index 290e036..7257b0b 100644
/*
* A special case when writing type/attribute symbol table.
@@ -1939,6 +1965,20 @@ int policydb_write(policydb_t * p, struct policy_file *fp)
@@ -1939,6 +1983,20 @@ int policydb_write(policydb_t * p, struct policy_file *fp)
p->policy_type == POLICY_KERN) {
hashtab_map(p->symtab[i].table, type_attr_uncount, &buf[1]);
}

View File

@ -1,7 +1,7 @@
Summary: SELinux binary policy manipulation library
Name: libsepol
Version: 2.1.2
Release: 1%{?dist}
Release: 2%{?dist}
License: LGPLv2+
Group: System Environment/Libraries
Source: http://www.nsa.gov/selinux/archives/libsepol-%{version}.tgz
@ -98,6 +98,9 @@ exit 0
/%{_lib}/libsepol.so.1
%changelog
* Thu Sep 1 2011 Dan Walsh <dwalsh@redhat.com> - 2.1.2-2
- export expand_module_avrules
* Thu Aug 18 2011 Dan Walsh <dwalsh@redhat.com> - 2.1.2-0
- Update to upstream
* Only call role_fix_callback for base.p_roles during expansion.