diff options
author | Stephen Smalley <sds@tycho.nsa.gov> | 2012-02-21 14:25:48 -0500 |
---|---|---|
committer | Stephen Smalley <sds@tycho.nsa.gov> | 2012-02-21 14:25:48 -0500 |
commit | 6617731185f5d7c899b376d1bfa2dea11eb494a0 (patch) | |
tree | 555a23782f8ea2b3cdd369d2b5cd9ccad3128bf9 | |
parent | b1db49d77789525ac1f4e73e978e35694f21ea1a (diff) | |
parent | fb82f8ed213dd54eebc6bdd5557984c3ba870496 (diff) | |
download | libsepol-6617731185f5d7c899b376d1bfa2dea11eb494a0.tar.gz |
Merge branch 'upstream'android-sdk-support_r11android-sdk-adt_r20android-cts-4.2_r2android-cts-4.2_r1android-cts-4.1_r4android-cts-4.1_r2android-cts-4.1_r1android-4.2_r1android-4.2_pre3android-4.2_pre2.2android-4.2_pre2.1android-4.2_pre2android-4.2_pre1.1android-4.2_pre1android-4.2.2_r1.2android-4.2.2_r1.1android-4.2.2_r1android-4.2.1_r1.2android-4.2.1_r1.1android-4.2.1_r1android-4.1_pre2android-4.1_pre1android-4.1.2_r2.1android-4.1.2_r2android-4.1.2_r1android-4.1.1_r6.1android-4.1.1_r6android-4.1.1_r5android-4.1.1_r4android-4.1.1_r3android-4.1.1_r2android-4.1.1_r1.1android-4.1.1_r1android-4.1-sdk_pre1tools_r20jb-releasejb-mr1.1-releasejb-mr1.1-devjb-mr1-releasejb-mr1-factory-releasejb-mr1-devjb-mr0-releasejb-devics-plus-aosp
-rw-r--r-- | ChangeLog | 25 | ||||
-rw-r--r-- | VERSION | 2 | ||||
-rw-r--r-- | include/Makefile | 4 | ||||
-rw-r--r-- | include/sepol/handle.h | 7 | ||||
-rw-r--r-- | include/sepol/policydb/conditional.h | 6 | ||||
-rw-r--r-- | include/sepol/policydb/ebitmap.h | 6 | ||||
-rw-r--r-- | include/sepol/policydb/policydb.h | 5 | ||||
-rw-r--r-- | man/Makefile | 4 | ||||
-rw-r--r-- | src/Makefile | 2 | ||||
-rw-r--r-- | src/conditional.c | 22 | ||||
-rw-r--r-- | src/ebitmap.c | 76 | ||||
-rw-r--r-- | src/expand.c | 149 | ||||
-rw-r--r-- | src/handle.c | 15 | ||||
-rw-r--r-- | src/handle.h | 2 | ||||
-rw-r--r-- | src/libsepol.map | 2 | ||||
-rw-r--r-- | src/link.c | 20 | ||||
-rw-r--r-- | src/policydb.c | 15 | ||||
-rw-r--r-- | src/private.h | 3 | ||||
-rw-r--r-- | src/write.c | 60 |
19 files changed, 400 insertions, 25 deletions
@@ -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 @@ -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: *; }; @@ -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; |