summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephen Smalley <sds@tycho.nsa.gov>2012-02-21 14:25:48 -0500
committerStephen Smalley <sds@tycho.nsa.gov>2012-02-21 14:25:48 -0500
commit6617731185f5d7c899b376d1bfa2dea11eb494a0 (patch)
tree555a23782f8ea2b3cdd369d2b5cd9ccad3128bf9
parentb1db49d77789525ac1f4e73e978e35694f21ea1a (diff)
parentfb82f8ed213dd54eebc6bdd5557984c3ba870496 (diff)
downloadlibsepol-6617731185f5d7c899b376d1bfa2dea11eb494a0.tar.gz
-rw-r--r--ChangeLog25
-rw-r--r--VERSION2
-rw-r--r--include/Makefile4
-rw-r--r--include/sepol/handle.h7
-rw-r--r--include/sepol/policydb/conditional.h6
-rw-r--r--include/sepol/policydb/ebitmap.h6
-rw-r--r--include/sepol/policydb/policydb.h5
-rw-r--r--man/Makefile4
-rw-r--r--src/Makefile2
-rw-r--r--src/conditional.c22
-rw-r--r--src/ebitmap.c76
-rw-r--r--src/expand.c149
-rw-r--r--src/handle.c15
-rw-r--r--src/handle.h2
-rw-r--r--src/libsepol.map2
-rw-r--r--src/link.c20
-rw-r--r--src/policydb.c15
-rw-r--r--src/private.h3
-rw-r--r--src/write.c60
19 files changed, 400 insertions, 25 deletions
diff --git a/ChangeLog b/ChangeLog
index 8d9c9c0..f835678 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,28 @@
+2.1.4 2011-10-03
+ * regenerate .pc on VERSION change
+ * Move ebitmap_* functions from mcstrans to libsepol
+ * expand: do filename_trans type comparison on mapped representation
+
+2.1.3 2011-09-15
+ * Skip writing role attributes for policy.X and
+ * Indicate when boolean is indeed a tunable.
+ * Separate tunable from boolean during compile.
+ * Write and read TUNABLE flags in related
+ * Copy and check the cond_bool_datum_t.flags during link.
+ * Permanently discard disabled branches of tunables in
+ * Skip tunable identifier and cond_node_t in expansion.
+ * Create a new preserve_tunables flag
+ * Preserve tunables when required by semodule program.
+ * setools expects expand_module_avrules to be an exported
+ * tree: default make target to all not
+
+2.1.2 2011-08-03
+ * Only call role_fix_callback for base.p_roles during expansion.
+ * use mapped role number instead of module role number
+
+2.1.1 2011-08-01
+ * Minor fix to reading policy with filename transition rules
+
2.1.0 2011-07-27
* Release, minor version bump
diff --git a/VERSION b/VERSION
index 7ec1d6d..7d2ed7c 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.1.0
+2.1.4
diff --git a/include/Makefile b/include/Makefile
index 0cd00ab..2ef418c 100644
--- a/include/Makefile
+++ b/include/Makefile
@@ -2,7 +2,9 @@
PREFIX ?= $(DESTDIR)/usr
INCDIR ?= $(PREFIX)/include/sepol
-install:
+all:
+
+install: all
test -d $(INCDIR) || install -m 755 -d $(INCDIR)
test -d $(INCDIR)/policydb || install -m 755 -d $(INCDIR)/policydb
install -m 644 $(wildcard sepol/*.h) $(INCDIR)
diff --git a/include/sepol/handle.h b/include/sepol/handle.h
index 19be326..115bda1 100644
--- a/include/sepol/handle.h
+++ b/include/sepol/handle.h
@@ -24,4 +24,11 @@ void sepol_set_expand_consume_base(sepol_handle_t * sh, int consume_base);
/* Destroy a sepol handle. */
void sepol_handle_destroy(sepol_handle_t *);
+/* Get whether or not needless unused branch of tunables would be preserved */
+int sepol_get_preserve_tunables(sepol_handle_t * sh);
+
+/* Set whether or not to preserve the needless unused branch of tunables,
+ * 0 is default and discard such branch, 1 preserves them */
+void sepol_set_preserve_tunables(sepol_handle_t * sh, int preserve_tunables);
+
#endif
diff --git a/include/sepol/policydb/conditional.h b/include/sepol/policydb/conditional.h
index a8ed694..48ec106 100644
--- a/include/sepol/policydb/conditional.h
+++ b/include/sepol/policydb/conditional.h
@@ -77,15 +77,17 @@ 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;
+ /* a tunable conditional, calculated and used at expansion */
+#define COND_NODE_FLAGS_TUNABLE 0x01
+ uint32_t flags;
} cond_node_t;
extern int cond_evaluate_expr(policydb_t * p, cond_expr_t * expr);
diff --git a/include/sepol/policydb/ebitmap.h b/include/sepol/policydb/ebitmap.h
index 410c15c..214da95 100644
--- a/include/sepol/policydb/ebitmap.h
+++ b/include/sepol/policydb/ebitmap.h
@@ -76,6 +76,12 @@ static inline int ebitmap_node_get_bit(ebitmap_node_t * n, unsigned int bit)
extern int ebitmap_cmp(const ebitmap_t * e1, const ebitmap_t * e2);
extern int ebitmap_or(ebitmap_t * dst, const ebitmap_t * e1, const ebitmap_t * e2);
extern int ebitmap_union(ebitmap_t * dst, const ebitmap_t * e1);
+extern int ebitmap_and(ebitmap_t *dst, ebitmap_t *e1, ebitmap_t *e2);
+extern int ebitmap_xor(ebitmap_t *dst, ebitmap_t *e1, ebitmap_t *e2);
+extern int ebitmap_not(ebitmap_t *dst, ebitmap_t *e1, unsigned int maxbit);
+extern int ebitmap_andnot(ebitmap_t *dst, ebitmap_t *e1, ebitmap_t *e2, unsigned int maxbit);
+extern unsigned int ebitmap_cardinality(ebitmap_t *e1);
+extern int ebitmap_hamming_distance(ebitmap_t * e1, ebitmap_t * e2);
extern int ebitmap_cpy(ebitmap_t * dst, const ebitmap_t * src);
extern int ebitmap_contains(const ebitmap_t * e1, const ebitmap_t * e2);
extern int ebitmap_get_bit(const ebitmap_t * e, unsigned int bit);
diff --git a/include/sepol/policydb/policydb.h b/include/sepol/policydb/policydb.h
index 5320bc8..1848a7b 100644
--- a/include/sepol/policydb/policydb.h
+++ b/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/man/Makefile b/man/Makefile
index b96bc94..1192433 100644
--- a/man/Makefile
+++ b/man/Makefile
@@ -2,7 +2,9 @@
MAN8DIR ?= $(DESTDIR)/usr/share/man/man8
MAN3DIR ?= $(DESTDIR)/usr/share/man/man3
-install:
+all:
+
+install: all
mkdir -p $(MAN3DIR)
mkdir -p $(MAN8DIR)
install -m 644 man3/*.3 $(MAN3DIR)
diff --git a/src/Makefile b/src/Makefile
index 73fdef8..cd8e767 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -27,7 +27,7 @@ $(LIBSO): $(LOBJS)
$(CC) $(CFLAGS) $(LDFLAGS) -shared -o $@ $^ -Wl,-soname,$(LIBSO),--version-script=libsepol.map,-z,defs
ln -sf $@ $(TARGET)
-$(LIBPC): $(LIBPC).in
+$(LIBPC): $(LIBPC).in ../VERSION
sed -e 's/@VERSION@/$(VERSION)/; s:@prefix@:$(PREFIX):; s:@libdir@:$(LIBBASE):; s:@includedir@:$(INCLUDEDIR):' < $< > $@
%.o: %.c
diff --git a/src/conditional.c b/src/conditional.c
index 1482387..ea47cdd 100644
--- a/src/conditional.c
+++ b/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/src/ebitmap.c b/src/ebitmap.c
index cc6a915..be6b591 100644
--- a/src/ebitmap.c
+++ b/src/ebitmap.c
@@ -71,6 +71,82 @@ int ebitmap_union(ebitmap_t * dst, const ebitmap_t * e1)
return 0;
}
+int ebitmap_and(ebitmap_t *dst, ebitmap_t *e1, ebitmap_t *e2)
+{
+ unsigned int i, length = min(ebitmap_length(e1), ebitmap_length(e2));
+ ebitmap_init(dst);
+ for (i=0; i < length; i++) {
+ if (ebitmap_get_bit(e1, i) && ebitmap_get_bit(e2, i)) {
+ int rc = ebitmap_set_bit(dst, i, 1);
+ if (rc < 0)
+ return rc;
+ }
+ }
+ return 0;
+}
+
+int ebitmap_xor(ebitmap_t *dst, ebitmap_t *e1, ebitmap_t *e2)
+{
+ unsigned int i, length = max(ebitmap_length(e1), ebitmap_length(e2));
+ ebitmap_init(dst);
+ for (i=0; i < length; i++) {
+ int val = ebitmap_get_bit(e1, i) ^ ebitmap_get_bit(e2, i);
+ int rc = ebitmap_set_bit(dst, i, val);
+ if (rc < 0)
+ return rc;
+ }
+ return 0;
+}
+
+int ebitmap_not(ebitmap_t *dst, ebitmap_t *e1, unsigned int maxbit)
+{
+ unsigned int i;
+ ebitmap_init(dst);
+ for (i=0; i < maxbit; i++) {
+ int val = ebitmap_get_bit(e1, i);
+ int rc = ebitmap_set_bit(dst, i, !val);
+ if (rc < 0)
+ return rc;
+ }
+ return 0;
+}
+
+int ebitmap_andnot(ebitmap_t *dst, ebitmap_t *e1, ebitmap_t *e2, unsigned int maxbit)
+{
+ ebitmap_t e3;
+ ebitmap_init(dst);
+ int rc = ebitmap_not(&e3, e2, maxbit);
+ if (rc < 0)
+ return rc;
+ rc = ebitmap_and(dst, e1, &e3);
+ ebitmap_destroy(&e3);
+ if (rc < 0)
+ return rc;
+ return 0;
+}
+
+unsigned int ebitmap_cardinality(ebitmap_t *e1)
+{
+ unsigned int i, count = 0;
+ for (i=ebitmap_startbit(e1); i < ebitmap_length(e1); i++)
+ if (ebitmap_get_bit(e1, i))
+ count++;
+ return count;
+}
+
+int ebitmap_hamming_distance(ebitmap_t * e1, ebitmap_t * e2)
+{
+ if (ebitmap_cmp(e1, e2))
+ return 0;
+ ebitmap_t tmp;
+ int rc = ebitmap_xor(&tmp, e1, e2);
+ if (rc < 0)
+ return -1;
+ int distance = ebitmap_cardinality(&tmp);
+ ebitmap_destroy(&tmp);
+ return distance;
+}
+
int ebitmap_cmp(const ebitmap_t * e1, const ebitmap_t * e2)
{
ebitmap_node_t *n1, *n2;
diff --git a/src/expand.c b/src/expand.c
index b42acbe..493e478 100644
--- a/src/expand.c
+++ b/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;
}
@@ -1249,23 +1255,26 @@ static int copy_role_trans(expand_state_t * state, role_trans_rule_t * rules)
cur_trans = state->out->role_tr;
while (cur_trans) {
+ unsigned int mapped_role;
+
+ mapped_role = state->rolemap[cur->new_role - 1];
+
if ((cur_trans->role ==
i + 1) &&
(cur_trans->type ==
j + 1) &&
(cur_trans->tclass ==
k + 1)) {
- if (cur_trans->
- new_role ==
- cur->new_role) {
+ if (cur_trans->new_role == mapped_role) {
break;
} else {
ERR(state->handle,
- "Conflicting role trans rule %s %s : %s %s",
+ "Conflicting role trans rule %s %s : %s { %s vs %s }",
state->out->p_role_val_to_name[i],
state->out->p_type_val_to_name[j],
state->out->p_class_val_to_name[k],
- state->out->p_role_val_to_name[cur->new_role - 1]);
+ state->out->p_role_val_to_name[mapped_role - 1],
+ state->out->p_role_val_to_name[cur_trans->new_role - 1]);
return -1;
}
}
@@ -1320,6 +1329,8 @@ static int expand_filename_trans(expand_state_t *state, filename_trans_rule_t *r
cur_rule = rules;
while (cur_rule) {
+ uint32_t mapped_otype;
+
ebitmap_init(&stypes);
ebitmap_init(&ttypes);
@@ -1335,6 +1346,8 @@ static int expand_filename_trans(expand_state_t *state, filename_trans_rule_t *r
return -1;
}
+ mapped_otype = state->typemap[cur_rule->otype - 1];
+
ebitmap_for_each_bit(&stypes, snode, i) {
if (!ebitmap_node_get_bit(snode, i))
continue;
@@ -1349,7 +1362,7 @@ static int expand_filename_trans(expand_state_t *state, filename_trans_rule_t *r
(cur_trans->tclass == cur_rule->tclass) &&
(!strcmp(cur_trans->name, cur_rule->name))) {
/* duplicate rule, who cares */
- if (cur_trans->otype == cur_rule->otype)
+ if (cur_trans->otype == mapped_otype)
break;
ERR(state->handle, "Conflicting filename trans rules %s %s %s : %s otype1:%s otype2:%s",
@@ -1358,7 +1371,7 @@ static int expand_filename_trans(expand_state_t *state, filename_trans_rule_t *r
state->out->p_type_val_to_name[j],
state->out->p_class_val_to_name[cur_trans->tclass - 1],
state->out->p_type_val_to_name[cur_trans->otype - 1],
- state->out->p_type_val_to_name[state->typemap[cur_rule->otype - 1] - 1]);
+ state->out->p_type_val_to_name[mapped_otype - 1]);
return -1;
}
@@ -1388,7 +1401,7 @@ static int expand_filename_trans(expand_state_t *state, filename_trans_rule_t *r
new_trans->stype = i + 1;
new_trans->ttype = j + 1;
new_trans->tclass = cur_rule->tclass;
- new_trans->otype = state->typemap[cur_rule->otype - 1];
+ new_trans->otype = mapped_otype;
}
}
@@ -1937,6 +1950,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;
@@ -2662,6 +2682,106 @@ int expand_module_avrules(sepol_handle_t * handle, policydb_t * base,
return copy_and_expand_avrule_block(&state);
}
+static void discard_tunables(sepol_handle_t *sh, policydb_t *pol)
+{
+ avrule_block_t *block;
+ avrule_decl_t *decl;
+ cond_node_t *cur_node;
+ cond_expr_t *cur_expr;
+ int cur_state, preserve_tunables = 0;
+ avrule_t *tail, *to_be_appended;
+
+ if (sh && sh->preserve_tunables)
+ preserve_tunables = 1;
+
+ /* Iterate through all cond_node of all enabled decls, if a cond_node
+ * is about tunable, calculate its state value and concatenate one of
+ * its avrule list to the current decl->avrules list. On the other
+ * hand, the disabled unused branch of a tunable would be discarded.
+ *
+ * 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 are requested to be preserved then they would be
+ * "transformed" as booleans by having their TUNABLE flag cleared.
+ */
+ 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++;
+ }
+
+ /* bool_copy_callback() at link phase has ensured
+ * that no mixture of tunables and booleans in one
+ * expression. However, this would be broken by the
+ * request to preserve tunables */
+ if (!preserve_tunables)
+ assert(!(booleans && tunables));
+
+ if (booleans || preserve_tunables) {
+ cur_node->flags &= ~COND_NODE_FLAGS_TUNABLE;
+ if (tunables) {
+ for (i = 0; i < tunables; i++)
+ tmp[i]->flags &= ~COND_BOOL_FLAGS_TUNABLE;
+ }
+ } else {
+ 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;
+
+ /* Now that the effective branch has been
+ * appended, neutralize its original pointer */
+ if (cur_state == 1)
+ cur_node->avtrue_list = NULL;
+ else
+ cur_node->avfalse_list = NULL;
+
+ /* Update the tail of decl->avrules for
+ * further concatenation */
+ while (tail && tail->next)
+ tail = tail->next;
+ }
+ }
+ }
+}
+
/* Linking should always be done before calling expand, even if
* there is only a base since all optionals are dealt with at link time
* the base passed in should be indexed and avrule blocks should be
@@ -2675,6 +2795,16 @@ int expand_module(sepol_handle_t * handle,
expand_state_t state;
avrule_block_t *curblock;
+ /* 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. Whereas
+ * the disabled unused branch would be discarded.
+ *
+ * Originally this function is called at the very end of link phase,
+ * however, we need to keep the linked policy intact for analysis
+ * purpose. */
+ discard_tunables(handle, base);
+
expand_state_init(&state);
state.verbose = verbose;
@@ -2832,9 +2962,6 @@ int expand_module(sepol_handle_t * handle,
if (hashtab_map
(decl->p_roles.table, role_copy_callback, &state))
goto cleanup;
- if (hashtab_map
- (decl->p_roles.table, role_fix_callback, &state))
- goto cleanup;
/* copy users */
if (hashtab_map
diff --git a/src/handle.c b/src/handle.c
index 191ac57..2e9a4ad 100644
--- a/src/handle.c
+++ b/src/handle.c
@@ -18,9 +18,24 @@ sepol_handle_t *sepol_handle_create(void)
sh->disable_dontaudit = 0;
sh->expand_consume_base = 0;
+ /* by default needless unused branch of tunables would be discarded */
+ sh->preserve_tunables = 0;
+
return sh;
}
+int sepol_get_preserve_tunables(sepol_handle_t *sh)
+{
+ assert(sh != NULL);
+ return sh->preserve_tunables;
+}
+
+void sepol_set_preserve_tunables(sepol_handle_t * sh, int preserve_tunables)
+{
+ assert(sh !=NULL);
+ sh->preserve_tunables = preserve_tunables;
+}
+
int sepol_get_disable_dontaudit(sepol_handle_t *sh)
{
assert(sh !=NULL);
diff --git a/src/handle.h b/src/handle.h
index 254fbd8..7728d04 100644
--- a/src/handle.h
+++ b/src/handle.h
@@ -17,7 +17,7 @@ struct sepol_handle {
int disable_dontaudit;
int expand_consume_base;
-
+ int preserve_tunables;
};
#endif
diff --git a/src/libsepol.map b/src/libsepol.map
index 719e5b7..c6bb788 100644
--- a/src/libsepol.map
+++ b/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;
@@ -15,5 +16,6 @@
sepol_get_disable_dontaudit;
sepol_set_disable_dontaudit;
sepol_set_expand_consume_base;
+ sepol_get_preserve_tunables; sepol_set_preserve_tunables;
local: *;
};
diff --git a/src/link.c b/src/link.c
index 421c47b..ee9675b 100644
--- a/src/link.c
+++ b/src/link.c
@@ -587,7 +587,18 @@ 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() or vice versa).
+ *
+ * This is not allowed and bail out with errors */
+ ERR(state->handle,
+ "%s: Mismatch between boolean/tunable definition "
+ "and usage for %s", state->cur_mod_name, id);
+ return -1;
}
/* Get the scope info for this boolean to see if this is the declaration,
@@ -595,9 +606,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->flags = booldatum->flags;
+ }
state->cur->map[SYM_BOOLS][booldatum->s.value - 1] = base_bool->s.value;
return 0;
diff --git a/src/policydb.c b/src/policydb.c
index 53d0fda..136b450 100644
--- a/src/policydb.c
+++ b/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
@@ -2327,6 +2341,7 @@ int filename_trans_read(filename_trans_t **t, struct policy_file *fp)
lft->next = ft;
else
*t = ft;
+ lft = ft;
rc = next_entry(buf, fp, sizeof(uint32_t));
if (rc < 0)
return -1;
diff --git a/src/private.h b/src/private.h
index fd6cf33..a2188d4 100644
--- a/src/private.h
+++ b/src/private.h
@@ -40,6 +40,9 @@
#undef min
#define min(a,b) (((a) < (b)) ? (a) : (b))
+#undef max
+#define max(a,b) ((a) >= (b) ? (a) : (b))
+
#define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))
/* Policy compatibility information. */
diff --git a/src/write.c b/src/write.c
index 290e036..e34ab52 100644
--- a/src/write.c
+++ b/src/write.c
@@ -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;
+ /*
+ * Role attributes are redundant for policy.X, skip them
+ * when writing the roles symbol table. They are also skipped
+ * when pp is downgraded.
+ *
+ * Their numbers would be deducted in policydb_write().
+ */
+ if ((role->flavor == ROLE_ATTRIB) &&
+ ((p->policy_type == POLICY_KERN) ||
+ (p->policy_type != POLICY_KERN &&
+ p->policyvers < MOD_POLICYDB_VERSION_ROLEATTRIB)))
+ return POLICYDB_SUCCESS;
+
len = strlen(key);
items = 0;
buf[items++] = cpu_to_le32(len);
@@ -1795,6 +1826,19 @@ static int type_attr_uncount(hashtab_key_t key __attribute__ ((unused)),
return 0;
}
+static int role_attr_uncount(hashtab_key_t key __attribute__ ((unused)),
+ hashtab_datum_t datum, void *args)
+{
+ role_datum_t *role = datum;
+ uint32_t *p_nel = args;
+
+ if (role->flavor == ROLE_ATTRIB) {
+ /* uncount attribute from total number of roles */
+ (*p_nel)--;
+ }
+ return 0;
+}
+
/*
* Write the configuration data in a policy database
* structure to a policy database binary representation
@@ -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);
- buf[1] = cpu_to_le32(p->symtab[i].table->nel);
+ buf[1] = p->symtab[i].table->nel;
/*
* A special case when writing type/attribute symbol table.
@@ -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]);
}
+
+ /*
+ * Another special case when writing role/attribute symbol
+ * table, role attributes are redundant for policy.X, or
+ * when the pp's version is not big enough. So deduct
+ * their numbers from p_roles.table->nel.
+ */
+ if ((i == SYM_ROLES) &&
+ ((p->policy_type == POLICY_KERN) ||
+ (p->policy_type != POLICY_KERN &&
+ p->policyvers < MOD_POLICYDB_VERSION_ROLEATTRIB)))
+ hashtab_map(p->symtab[i].table, role_attr_uncount, &buf[1]);
+
+ buf[1] = cpu_to_le32(buf[1]);
items = put_entry(buf, sizeof(uint32_t), 2, fp);
if (items != 2)
return POLICYDB_ERROR;