userland support for new range_transition statements
PATCH 2/2 userland support for new range_transition statements
This patch introduces support for kernel policy format version 21, base policy format version 6, and policy module format 6. These new formats allow for the definition of range_transitions on security classes other than "process". The new module and base formats (both 6) also move expansion of the range_transition statements from compile time to the actual expansion phase. This change should allow for using range_transitions in policy modules (with a bit more work in the future) with another change in format.
The current range_transition statements are of the form:
range_transition <source types> <target types> <new range>
These statements affect process transitions only. The new supported format is:
range_transition <source types> <target types>:<target classes> <new range>
With this format it is possible to to specify a new range for operations such as file creation. The old style statements are still allowed and they implicitly refer to the "process" security class, thereby retaining the same behavior as before.
The new kernel format now stores the security class on which the rule operates. When dealing with older kernel policy formats, the "process" security class is implicit.
The new module and base formats now store a representation of the rule just (the new addition to the avrule_decl structure) and are expanded at the proper time. The previous implementation expanded the rules at compilation time and could produce an incomplete set of transitions if type attributes were used in the statement.
Here is how range_transition statements are handled for the various formats:
for kernel policy version up to 18, there are no range_transition for kernel policy versions 19 and 20, a list of old-style (no class specified)
range_trans structures are encoded
for kernel policy versions 21 and up, a list of new-style (class specified)
range_trans structures are encoded
for base policy versions up to 5, there are no range_transitions for base policy version 5, a compile-time generated list of old-style (no
class specified) range_trans structures are encoded as they are in kernel formats 19 and 20
for base policy versions 6 and up, an expressive rule stating the intention
of the statement is stored - that will be properly linked and expanded for further usage
for module policy versions up to 6, there are no range_transitions for base policy versions 6 and up, an expressive rule stating the intention
of the statement is stored jut like in base policy version 6 (of course we still need more work to get them in there, but the format is supportive).
checkpolicy/module_compiler.c | 12 ++ checkpolicy/module_compiler.h | 1 checkpolicy/policy_parse.y | 155 ++++++++++++++-------------- libsepol/include/sepol/policydb/mls_types.h | 6 + libsepol/include/sepol/policydb/policydb.h | 24 +++- libsepol/src/avrule_block.c | 1 libsepol/src/expand.c | 118 +++++++++++++++++++-- libsepol/src/mls.c | 21 +-- libsepol/src/policydb.c | 154 ++++++++++++++++++++++++++- libsepol/src/write.c | 74 ++++++++++++- 10 files changed, 452 insertions(+), 114 deletions(-)
include/sepol/policydb/policydb.h +0 -0
@@ -164,9 +164,10 @@
} cat_datum_t;
typedef struct range_trans {
- uint32_t dom; /* current process domain */
- uint32_t type; /* program executable type */
- mls_range_t range; /* new range */
+ uint32_t source_type;
+ uint32_t target_type;
+ uint32_t target_class;
+ mls_range_t target_range; struct range_trans *next; } range_trans_t;
@@ -224,6 +225,14 @@
struct role_allow_rule *next; } role_allow_rule_t;
+typedef struct range_trans_rule {
+ type_set_t stypes;
+ type_set_t ttypes;
+ class_perm_node_t *classes; /* only class is used */
+ mls_range_t trange;
+ struct range_trans_rule *next;
+} range_trans_rule_t;
+
/*
* The configuration data includes security contexts for
* initial SIDs, unlabeled file systems, TCP and UDP port numbers,
@@ -321,6 +330,7 @@
avrule_t *avrules; role_trans_rule_t *role_tr_rules; role_allow_rule_t *role_allow_rules;
+ range_trans_rule_t *range_tr_rules;
scope_index_t required; /* symbols needed to activate this block */
scope_index_t declared; /* symbols declared within this block */
@@ -506,6 +516,8 @@
extern void role_allow_rule_init(role_allow_rule_t * x); extern void role_allow_rule_destroy(role_allow_rule_t * x); extern void role_allow_rule_list_destroy(role_allow_rule_t * x); +extern void range_trans_rule_init(range_trans_rule_t *x); +extern void range_trans_rule_list_destroy(range_trans_rule_t *x); extern void type_datum_init(type_datum_t * x);
extern void type_datum_destroy(type_datum_t * x); extern void user_datum_init(user_datum_t * x);
@@ -555,18 +567,20 @@
#define POLICYDB_VERSION_VALIDATETRANS 19
#define POLICYDB_VERSION_MLS 19
#define POLICYDB_VERSION_AVTAB 20
+#define POLICYDB_VERSION_RANGETRANS 21
/* Range of policy versions we understand*/
#define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE
-#define POLICYDB_VERSION_MAX POLICYDB_VERSION_AVTAB
+#define POLICYDB_VERSION_MAX POLICYDB_VERSION_RANGETRANS
/* Module versions and specific changes*/
#define MOD_POLICYDB_VERSION_BASE 4
#define MOD_POLICYDB_VERSION_VALIDATETRANS 5
#define MOD_POLICYDB_VERSION_MLS 5
+#define MOD_POLICYDB_VERSION_RANGETRANS 6
#define MOD_POLICYDB_VERSION_MIN MOD_POLICYDB_VERSION_BASE -#define MOD_POLICYDB_VERSION_MAX MOD_POLICYDB_VERSION_MLS +#define MOD_POLICYDB_VERSION_MAX MOD_POLICYDB_VERSION_RANGETRANS
#define POLICYDB_CONFIG_MLS 1
include/sepol/policydb/mls_types.h +0 -0
@@ -107,4 +107,10 @@
return -1; }
+static inline int mls_range_eq(struct mls_range *r1, struct mls_range *r2) +{
+ return (mls_level_eq(&r1->level[0], &r2->level[0]) &&
+ mls_level_eq(&r1->level[1], &r2->level[1]));
+}
+
#endif
src/policydb.c +0 -0
@@ -48,6 +48,7 @@
#include <sepol/policydb/conditional.h>
#include <sepol/policydb/avrule_block.h>
#include <sepol/policydb/util.h>
+#include <sepol/policydb/flask.h>
#include "private.h"
#include "debug.h"
@@ -92,6 +93,12 @@
.ocon_num = OCON_NODE6 + 1,
},
{+ .type = POLICY_KERN,
+ .version = POLICYDB_VERSION_RANGETRANS,
+ .sym_num = SYM_NUM,
+ .ocon_num = OCON_NODE6 + 1,
+ },
+ {
.type = POLICY_BASE,
.version = MOD_POLICYDB_VERSION_BASE,
.sym_num = SYM_NUM,
@@ -104,6 +111,12 @@
.ocon_num = OCON_NODE6 + 1,
},
{+ .type = POLICY_BASE,
+ .version = MOD_POLICYDB_VERSION_RANGETRANS,
+ .sym_num = SYM_NUM,
+ .ocon_num = OCON_NODE6 + 1,
+ },
+ {
.type = POLICY_MOD,
.version = MOD_POLICYDB_VERSION_BASE,
.sym_num = SYM_NUM,
@@ -114,7 +127,13 @@
.version = MOD_POLICYDB_VERSION_MLS, .sym_num = SYM_NUM, .ocon_num = 0,
- }
+ },
+ {
+ .type = POLICY_MOD,
+ .version = MOD_POLICYDB_VERSION_RANGETRANS,
+ .sym_num = SYM_NUM,
+ .ocon_num = 0
+ },
};
#if 0
@@ -307,6 +326,42 @@
} }
+void range_trans_rule_init(range_trans_rule_t *x) +{
+ memset(x, 0, sizeof(*x));
+ type_set_init(&x->stypes);
+ type_set_init(&x->ttypes);
+ mls_level_init(&x->trange.level[0]);
+ mls_level_init(&x->trange.level[1]);
+}
+
+static void range_trans_rule_destroy(range_trans_rule_t *x) +{
+ class_perm_node_t *cur, *next;
+
+ type_set_destroy(&x->stypes);
+ type_set_destroy(&x->ttypes);
+ mls_level_destroy(&x->trange.level[0]);
+ mls_level_destroy(&x->trange.level[1]);
+
+ next = x->classes;
+ while (next) {
+ cur = next;
+ next = cur->next;
+ free(cur);
+ }
+}
+
+void range_trans_rule_list_destroy(range_trans_rule_t *x) +{
+ while (x != NULL) {
+ range_trans_rule_t *next = x->next;
+ range_trans_rule_destroy(x);
+ free(x);
+ x = next;
+ }
+}
+
void avrule_list_destroy(avrule_t * x)
{
avrule_t *next, *cur;@@ -954,15 +1009,15 @@
for (rt = p->range_tr; rt; rt = rt->next) {
if (lrt) {
- ebitmap_destroy(&lrt->range.level[0].cat);
- ebitmap_destroy(&lrt->range.level[1].cat);
+ ebitmap_destroy(&lrt->target_range.level[0].cat);
+ ebitmap_destroy(&lrt->target_range.level[1].cat);
free(lrt);
}
lrt = rt;
}
if (lrt) {
- ebitmap_destroy(&lrt->range.level[0].cat);
- ebitmap_destroy(&lrt->range.level[1].cat);
+ ebitmap_destroy(&lrt->target_range.level[0].cat);
+ ebitmap_destroy(&lrt->target_range.level[1].cat);
free(lrt);
}@@ -2260,6 +2315,8 @@
uint32_t *buf, nel; range_trans_t *rt, *lrt; unsigned int i;
+ int new_rangetr = (p->policy_type == POLICY_KERN &&
+ p->policyvers >= POLICYDB_VERSION_RANGETRANS);
buf = next_entry(fp, sizeof(uint32_t)); if (!buf) @@ -2277,9 +2334,16 @@ buf = next_entry(fp, (sizeof(uint32_t) * 2)); if (!buf) return -1;
- rt->dom = le32_to_cpu(buf[0]);
- rt->type = le32_to_cpu(buf[1]);
- if (mls_read_range_helper(&rt->range, fp))
+ rt->source_type = le32_to_cpu(buf[0]);
+ rt->target_type = le32_to_cpu(buf[1]);
+ if (new_rangetr) {
+ buf = next_entry(fp, (sizeof(uint32_t)));
+ if (!buf)
+ return -1;
+ rt->target_class = le32_to_cpu(buf[0]);
+ } else
+ rt->target_class = SECCLASS_PROCESS;
+ if (mls_read_range_helper(&rt->target_range, fp))
return -1; lrt = rt; } @@ -2393,6 +2457,73 @@ return 0; }
+static int range_trans_rule_read(range_trans_rule_t **r, struct policy_file *fp) +{
+ uint32_t *buf, nel, nclass;
+ unsigned int i, j;
+ range_trans_rule_t *rt, *lrt = NULL;
+ class_perm_node_t *cp, *lcp = NULL;
+
+ buf = next_entry(fp, sizeof(uint32_t));
+ if (!buf)
+ return -1;
+ nel = le32_to_cpu(buf[0]);
+ for (i = 0; i < nel; i++) {
+ rt = malloc(sizeof(range_trans_rule_t));
+ if (!rt) {
+ return -1;
+ }
+ range_trans_rule_init(rt);
+
+ if (type_set_read(&rt->stypes, fp))
+ return -1;
+
+ if (type_set_read(&rt->ttypes, fp))
+ return -1;
+
+ buf = next_entry(fp, sizeof(uint32_t));
+ if (!buf)
+ return -1;
+
+ nclass = le32_to_cpu(buf[0]);
+ rt->classes = NULL;
+ lcp = NULL;
+ for (j = 0; j < nclass; j++) {
+ cp = (class_perm_node_t *)malloc(
+ sizeof(class_perm_node_t));
+ if (!cp)
+ return -1;
+ class_perm_node_init(cp);
+
+ buf = next_entry(fp, sizeof(uint32_t));
+ if (!buf) {
+ free(cp);
+ return -1;
+ }
+
+ /* note that we care about the class, not the data */
+ cp->class = le32_to_cpu(buf[0]);
+
+ if (lcp)
+ lcp->next = cp;
+ else
+ rt->classes = cp;
+ lcp = cp;
+ }
+
+ if (mls_read_range_helper(&rt->trange, fp))
+ return -1;
+
+ if (lrt)
+ lrt->next = rt;
+ else
+ *r = rt;
+ lrt = rt;
+ }
+
+ return 0;
+}
+
static int scope_index_read(scope_index_t * scope_index,
unsigned int num_scope_syms, struct policy_file *fp)
{
@@ -2440,6 +2571,10 @@
role_allow_rule_read(&decl->role_allow_rules, fp) == -1) {
return -1;
}+ if (p->policyvers >= MOD_POLICYDB_VERSION_RANGETRANS &&
+ range_trans_rule_read(&decl->range_tr_rules, fp) == -1) {
+ return -1;
+ }
if (scope_index_read(&decl->required, num_scope_syms, fp) == -1 ||
scope_index_read(&decl->declared, num_scope_syms, fp) == -1) {
return -1;
@@ -2835,7 +2970,8 @@
if ((p->policy_type == POLICY_KERN
&& p->policyvers >= POLICYDB_VERSION_MLS)
|| (p->policy_type == POLICY_BASE
- && p->policyvers >= MOD_POLICYDB_VERSION_MLS)) {
+ && p->policyvers >= MOD_POLICYDB_VERSION_MLS
+ && p->policyvers < MOD_POLICYDB_VERSION_RANGETRANS)) {
if (range_read(p, fp)) {
goto bad;
}src/mls.c +0 -0
@@ -607,23 +607,20 @@
sepol_security_class_t tclass,
uint32_t specified, context_struct_t * newcontext)
{
+ range_trans_t *rtr;
if (!policydb->mls)
return 0;
switch (specified) {
case AVTAB_TRANSITION:- if (tclass == SECCLASS_PROCESS) {
- range_trans_t *rangetr;
-
- /* Look for a range transition rule. */
- for (rangetr = policydb->range_tr; rangetr;
- rangetr = rangetr->next) {
- if (rangetr->dom == scontext->type &&
- rangetr->type == tcontext->type) {
- /* Set the range from the rule */
- return mls_range_set(newcontext,
- &rangetr->range);
- }
+ /* Look for a range transition rule. */
+ for (rtr = policydb->range_tr; rtr; rtr = rtr->next) {
+ if (rtr->source_type == scontext->type &&
+ rtr->target_type == tcontext->type &&
+ rtr->target_class == tclass) {
+ /* Set the range from the rule */
+ return mls_range_set(newcontext,
+ &rtr->target_range); } } /* Fallthrough */
src/avrule_block.c +0 -0
@@ -99,6 +99,7 @@
avrule_list_destroy(x->avrules); role_trans_rule_list_destroy(x->role_tr_rules); role_allow_rule_list_destroy(x->role_allow_rules); + range_trans_rule_list_destroy(x->range_tr_rules); scope_index_destroy(&x->required); scope_index_destroy(&x->declared); symtabs_destroy(x->symtab);
src/expand.c +0 -0
@@ -958,6 +958,99 @@
return 0; }
+static int expand_range_trans(expand_state_t *state, range_trans_rule_t *rules) +{
+ unsigned int i, j;
+ range_trans_t *rt, *lrt, *cur_rt;
+ range_trans_rule_t *rule;
+ class_perm_node_t *cp;
+
+ ebitmap_t stypes, ttypes;
+ ebitmap_node_t *snode, *tnode;
+
+ /* start appending at the end of the current list */
+ for (lrt = state->out->range_tr; lrt && lrt->next; lrt = lrt->next)
+ ;
+
+ for (rule = rules; rule; rule = rule->next) {
+ ebitmap_init(&stypes);
+ ebitmap_init(&ttypes);
+
+ /* expand the type sets */
+ if (expand_convert_type_set(state->out, state->typemap,
+ &rule->stypes, &stypes, 1)) {
+ ERR(state->handle, "Out of memory!");
+ return -1;
+ }
+ if (expand_convert_type_set(state->out, state->typemap,
+ &rule->ttypes, &ttypes, 1)) {
+ ERR(state->handle, "Out of memory!");
+ return -1;
+ }
+
+ /* loop on source type */
+ ebitmap_for_each_bit(&stypes, snode, i) {
+ if (!ebitmap_node_get_bit(snode, i))
+ continue;
+ /* loop on target type */
+ ebitmap_for_each_bit(&ttypes, tnode, j) {
+ if (!ebitmap_node_get_bit(tnode, j))
+ continue;
+ /* loop on target class */
+ for (cp = rule->classes; cp; cp = cp->next) {
+
+ /* check for duplicates/conflicts */
+ for (cur_rt = state->out->range_tr; cur_rt; cur_rt = cur_rt->next) {
+ if ((cur_rt->source_type == i + 1) &&
+ (cur_rt->target_type == j + 1) &&
+ (cur_rt->target_class == cp->class)) {
+ if (mls_range_eq(&cur_rt->target_range, &rule->trange)) {
+ /* duplicate */
+ break;
+ } else {
+ /* conflict */
+ ERR(state->handle,
+ "Conflicting range trans rule %s %s : %s", + state->out->p_type_val_to_name[i], + state->out->p_type_val_to_name[j], + state->out->p_class_val_to_name[cp->class]);
+ return -1;
+ }
+ }
+ }
+ if (cur_rt) /* this is a dup - skip */
+ continue;
+
+ rt = (range_trans_t *)malloc(sizeof(range_trans_t));
+ if (!rt) {
+ ERR(state->handle, "Out of memory!");
+ return -1;
+ }
+ memset(rt, 0, sizeof(range_trans_t));
+ rt->source_type = i + 1;
+ rt->target_type = j + 1;
+ rt->target_class = cp->class;
+ if (mls_range_cpy(&rt->target_range, &rule->trange)) {
+ ERR(state->handle, "Out of memory!");
+ return -1;
+ }
+ if (lrt) {
+ lrt->next = rt;
+ } else {
+ state->out->range_tr = rt;
+ }
+ lrt = rt;
+ }
+ }
+ }
+
+ ebitmap_destroy(&stypes);
+ ebitmap_destroy(&ttypes);
+ }
+
+ return 0;
+}
+
/* Search for an AV tab node within a hash table with the given key.
* If the node does not exist, create it and return it; otherwise
* return the pre-existing one.
@@ -1500,12 +1593,13 @@
goto out_of_mem; } memset(new_range, 0, sizeof(*new_range));
- new_range->dom = state->typemap[range->dom - 1];
- new_range->type = state->typemap[range->type - 1];
- if (mls_level_clone
- (&new_range->range.level[0], &range->range.level[0]) == -1
- || mls_level_clone(&new_range->range.level[1],
- &range->range.level[1])) {
+ new_range->source_type = state->typemap[range->source_type - 1];
+ new_range->target_type = state->typemap[range->target_type - 1];
+ new_range->target_class = range->target_class;
+ if (mls_level_clone(&new_range->target_range.level[0],
+ &range->target_range.level[0]) ||
+ mls_level_clone(&new_range->target_range.level[1],
+ &range->target_range.level[1])) {
goto out_of_mem;
}
new_range->next = NULL;
@@ -1522,8 +1616,8 @@
out_of_mem:
ERR(state->handle, "Out of memory!");
if (new_range) {
- ebitmap_destroy(&new_range->range.level[0].cat);
- ebitmap_destroy(&new_range->range.level[1].cat);
+ ebitmap_destroy(&new_range->target_range.level[0].cat);
+ ebitmap_destroy(&new_range->target_range.level[1].cat);
free(new_range);
}
return -1;
@@ -2030,6 +2124,11 @@
goto cleanup;
}+ /* expand the range transition rules */
+ if ((base->policyvers >= MOD_POLICYDB_VERSION_RANGETRANS) &&
+ expand_range_trans(&state, decl->range_tr_rules))
+ goto cleanup;
+
/* copy rules */
cur_avrule = decl->avrules;
while (cur_avrule != NULL) {
@@ -2072,7 +2171,8 @@
if (genfs_copy(&state))
goto cleanup;- if (range_trans_clone(&state) == -1) {
+ if ((base->policyvers < MOD_POLICYDB_VERSION_RANGETRANS) &&
+ range_trans_clone(&state) == -1) {
goto cleanup;
}src/write.c +0 -0
@@ -39,6 +39,7 @@
#include <sepol/policydb/policydb.h>
#include <sepol/policydb/conditional.h>
#include <sepol/policydb/expand.h>
+#include <sepol/policydb/flask.h>
#include "debug.h"
#include "private.h"
@@ -1124,21 +1125,36 @@
{
size_t nel, items;
struct range_trans *rt;
- uint32_t buf[32];
+ uint32_t buf[2];
+ int new_rangetr = (p->policy_type == POLICY_KERN &&
+ p->policyvers >= POLICYDB_VERSION_RANGETRANS);
nel = 0;- for (rt = p->range_tr; rt; rt = rt->next)
- nel++;
+ for (rt = p->range_tr; rt; rt = rt->next) {
+ /* all range_transitions are written for the new format, only
+ process related range_transitions are written for the old
+ format, so count accordingly */
+ if (new_rangetr || rt->target_class == SECCLASS_PROCESS)
+ nel++;
+ }
buf[0] = cpu_to_le32(nel);
items = put_entry(buf, sizeof(uint32_t), 1, fp);
if (items != 1)
return -1;
for (rt = p->range_tr; rt; rt = rt->next) {- buf[0] = cpu_to_le32(rt->dom);
- buf[1] = cpu_to_le32(rt->type);
+ if (!new_rangetr && rt->target_class != SECCLASS_PROCESS)
+ continue;
+ buf[0] = cpu_to_le32(rt->source_type);
+ buf[1] = cpu_to_le32(rt->target_type); items = put_entry(buf, sizeof(uint32_t), 2, fp); if (items != 2) return -1;
- if (mls_write_range_helper(&rt->range, fp))
+ if (new_rangetr) {
+ buf[0] = cpu_to_le32(rt->target_class);
+ items = put_entry(buf, sizeof(uint32_t), 1, fp);
+ if (items != 1)
+ return -1;
+ }
+ if (mls_write_range_helper(&rt->target_range, fp))
return -1; } return 0; @@ -1264,6 +1280,45 @@ return 0; }
+static int range_trans_rule_write(range_trans_rule_t *t, struct policy_file *fp) +{
+ int nel = 0, nclass;
+ size_t items;
+ uint32_t buf[1];
+ range_trans_rule_t *rt;
+ class_perm_node_t *cp;
+
+ for (rt = t; rt; rt = rt->next)
+ nel++;
+ buf[0] = cpu_to_le32(nel);
+ items = put_entry(buf, sizeof(uint32_t), 1, fp);
+ if (items != 1)
+ return -1;
+ for (rt = t; rt; rt = rt->next) {
+ if (type_set_write(&rt->stypes, fp))
+ return -1;
+ if (type_set_write(&rt->ttypes, fp))
+ return -1;
+ nclass = 0;
+ for (cp = rt->classes; cp; cp = cp->next)
+ nclass++;
+ buf[0] = cpu_to_le32(nclass);
+ items = put_entry(buf, sizeof(uint32_t), 1, fp);
+ if (items != 1)
+ return -1;
+ for (cp = rt->classes; cp; cp = cp->next) {
+ /* note that we care about the class, not the data */
+ buf[0] = cpu_to_le32(cp->class);
+ items = put_entry(buf, sizeof(uint32_t), 1, fp);
+ if (items != 1)
+ return -1;
+ }
+ if (mls_write_range_helper(&rt->trange, fp))
+ return -1;
+ }
+ return 0;
+}
+
static int scope_index_write(scope_index_t * scope_index,
unsigned int num_scope_syms,
struct policy_file *fp)
@@ -1304,6 +1359,10 @@
role_allow_rule_write(decl->role_allow_rules, fp) == -1) {
return -1;
}+ if (p->policyvers >= MOD_POLICYDB_VERSION_RANGETRANS &&
+ range_trans_rule_write(decl->range_tr_rules, fp) == -1) {
+ return -1;
+ }
if (scope_index_write(&decl->required, num_scope_syms, fp) == -1 ||
scope_index_write(&decl->declared, num_scope_syms, fp) == -1) {
return -1;
@@ -1525,7 +1584,8 @@
if ((p->policyvers >= POLICYDB_VERSION_MLS
&& p->policy_type == POLICY_KERN)
|| (p->policyvers >= MOD_POLICYDB_VERSION_MLS
- && p->policy_type == POLICY_BASE)) {
+ && p->policyvers < MOD_POLICYDB_VERSION_MLS
+ && p->policy_type == POLICY_BASE) ) {
if (range_write(p, fp)) {
return -1;
}module_compiler.c +0 -0
@@ -1105,6 +1105,18 @@
decl->role_allow_rules = role_allow_rules; }
+/* this doesn't actually append, but really prepends it */ +void append_range_trans(range_trans_rule_t * range_tr_rules) +{
+ avrule_decl_t *decl = stack_top->decl;
+
+ /* range transitions are not allowed within conditionals */
+ assert(stack_top->type == 1);
+
+ range_tr_rules->next = decl->range_tr_rules;
+ decl->range_tr_rules = range_tr_rules;
+}
+
int begin_optional(int pass)
{
avrule_block_t *block = NULL;policy_parse.y +0 -0
@@ -101,7 +101,7 @@
static role_datum_t *merge_roles_dom(role_datum_t *r1,role_datum_t *r2); static role_datum_t *define_role_dom(role_datum_t *r); static int define_role_trans(void);
-static int define_range_trans(void);
+static int define_range_trans(int class_specified);
static int define_role_allow(void);
static int define_constraint(constraint_expr_t *expr); static int define_validatetrans(constraint_expr_t *expr);
@@ -436,7 +436,9 @@
{if (define_compute_type(AVRULE_CHANGE)) return -1;}
;range_trans_def : RANGE_TRANSITION names names mls_range_def ';'
- { if (define_range_trans()) return -1; }
+ { if (define_range_trans(0)) return -1; }
+ | RANGE_TRANSITION names names ':' names mls_range_def ';'
+ { if (define_range_trans(1)) return -1; }
; te_avtab_def : allow_def | auditallow_def @@ -4472,15 +4474,15 @@ return define_genfs_context_helper(queue_remove(id_queue), has_type); }
-static int define_range_trans(void) +static int define_range_trans(int class_specified)
{
char *id;
level_datum_t *levdatum = 0;- mls_range_t range;
- type_set_t doms, types;
- ebitmap_node_t *snode, *tnode;
- range_trans_t *rt = 0;
- unsigned int i, j;
+ class_datum_t *cladatum;
+ class_perm_node_t *classes = NULL, *cp;
+ mls_range_t trange;
+ type_set_t stypes, ttypes;
+ range_trans_rule_t *rule;
int l, add = 1;
if (!mlspol) {
@@ -4493,6 +4495,9 @@
free(id);
while ((id = queue_remove(id_queue)))
free(id);
+ if (class_specified)
+ while ((id = queue_remove(id_queue)))
+ free(id);
id = queue_remove(id_queue);
free(id);
for (l = 0; l < 2; l++) {
@@ -4507,19 +4512,65 @@
return 0;
}- type_set_init(&doms);
- type_set_init(&types);
+ type_set_init(&stypes);
+ type_set_init(&ttypes);
while ((id = queue_remove(id_queue))) {
- if (set_types(&doms, id, &add, 0))
+ if (set_types(&stypes, id, &add, 0))
return -1;
}
add = 1;
while ((id = queue_remove(id_queue))) {
- if (set_types(&types, id, &add, 0))
+ if (set_types(&ttypes, id, &add, 0))
return -1;
}+ if (class_specified) {
+ while ((id = queue_remove(id_queue))) {
+ if (!is_id_in_scope(SYM_CLASSES, id)) {
+ yyerror2("class %s is not within scope", id);
+ free(id);
+ return -1;
+ }
+ cladatum = hashtab_search(policydbp->p_classes.table,
+ id);
+ if (!cladatum) {
+ sprintf(errormsg, "unknown class %s", id);
+ yyerror(errormsg);
+ return -1;
+ }
+
+ cp = malloc(sizeof(class_perm_node_t));
+ if (!cp) {
+ yyerror("out of memory");
+ return -1;
+ }
+ class_perm_node_init(cp);
+ cp->class = cladatum->value;
+ cp->next = classes;
+ classes = cp;
+ }
+ } else {
+ cladatum = hashtab_search(policydbp->p_classes.table,
+ "process");
+ if (!cladatum) {
+ sprintf(errormsg, "could not find process class for "
+ "legacy range_transition statement\n");
+ yyerror(errormsg);
+ return -1;
+ }
+
+ cp = malloc(sizeof(class_perm_node_t));
+ if (!cp) {
+ yyerror("out of memory");
+ return -1;
+ }
+ class_perm_node_init(cp);
+ cp->class = cladatum->value;
+ cp->next = classes;
+ classes = cp;
+ }
+
id = (char *)queue_remove(id_queue);
if (!id) {
yyerror("no range in range_transition definition?");
@@ -4529,19 +4580,20 @@
levdatum = hashtab_search(policydbp->p_levels.table, id);
if (!levdatum) {
sprintf(errormsg,
- "unknown level %s used in range_transition definition",
- id);
+ "unknown level %s used in range_transition "
+ "definition", id);
yyerror(errormsg);
free(id);
return -1;
}
free(id);- range.level[l].sens = levdatum->level->sens;
+ trange.level[l].sens = levdatum->level->sens;
- ebitmap_init(&range.level[l].cat);
+ ebitmap_init(&trange.level[l].cat);
while ((id = queue_remove(id_queue))) {
- if (parse_categories(id, levdatum, &range.level[l].cat)) {
+ if (parse_categories(id, levdatum,
+ &trange.level[l].cat)) {
free(id);
return -1;
}
@@ -4553,72 +4605,31 @@
break;
}
if (l == 0) {
- range.level[1].sens = range.level[0].sens;
- if (ebitmap_cpy(&range.level[1].cat, &range.level[0].cat)) {
+ if (mls_level_cpy(&trange.level[1], &trange.level[0])) {
yyerror("out of memory");
return -1;
}
}
-
- if (!mls_level_dom(&range.level[1], &range.level[0])) {
+ if (!mls_level_dom(&trange.level[1], &trange.level[0])) {
yyerror
("range_transition high level does not dominate low level");
return -1;
}- /* FIXME: this expands type_sets at compile time which is inappropriate, the type_sets
- * should be stored which is a format change */
- ebitmap_for_each_bit(&doms.types, snode, i) {
- if (!ebitmap_node_get_bit(snode, i))
- continue;
- ebitmap_for_each_bit(&types.types, tnode, j) {
- if (!ebitmap_node_get_bit(tnode, j))
- continue;
+ rule = malloc(sizeof(struct range_trans_rule));
+ if (!rule) {
+ yyerror("out of memory");
+ return -1;
+ }
+ memset(rule, 0, sizeof(struct range_trans_rule));
+ rule->stypes = stypes;
+ rule->ttypes = ttypes;
+ rule->classes = classes;
+ if (mls_range_cpy(&rule->trange, &trange))
+ return -1;
- for (rt = policydbp->range_tr; rt; rt = rt->next) {
- if (rt->dom == (i + 1) && rt->type == (j + 1)) {
- sprintf(errormsg,
- "duplicate range_transition defined for (%s,%s)",
- policydbp->
- p_type_val_to_name[i],
- policydbp->
- p_type_val_to_name[j]);
- yyerror(errormsg);
- return -1;
- }
- }
+ append_range_trans(rule);
- rt = malloc(sizeof(range_trans_t));
- if (!rt) {
- yyerror("out of memory");
- return -1;
- }
- memset(rt, 0, sizeof(range_trans_t));
- rt->dom = i + 1;
- rt->type = j + 1;
- rt->range.level[0].sens = range.level[0].sens;
- if (ebitmap_cpy(&rt->range.level[0].cat,
- &range.level[0].cat)) {
- yyerror("out of memory");
- free(rt);
- return -1;
- }
- rt->range.level[1].sens = range.level[1].sens;
- if (ebitmap_cpy(&rt->range.level[1].cat,
- &range.level[1].cat)) {
- yyerror("out of memory");
- free(rt);
- return -1;
- }
- rt->next = policydbp->range_tr;
- policydbp->range_tr = rt;
- }
- }
-
- type_set_destroy(&doms);
- type_set_destroy(&types);
- ebitmap_destroy(&range.level[0].cat);
- ebitmap_destroy(&range.level[1].cat); return 0; }
module_compiler.h +0 -0
@@ -77,6 +77,7 @@
void append_avrule(avrule_t * avrule);
void append_role_trans(role_trans_rule_t * role_tr_rules); void append_role_allow(role_allow_rule_t * role_allow_rules); +void append_range_trans(range_trans_rule_t * range_tr_rules);
/* Create a new optional block and add it to the global policy.
* During the second pass resolve the block's requirements. Return 0
Signature · 6 lines
Darrel -- This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
Quoted 4 lines · Darrel Goeddel
Index:
libsepol/src/policydb.c
===================================================================src/policydb.c +0
-0
<snip>
Quoted 10 lines
src/policydb.c +10
-0+static int range_trans_rule_read (range_trans_rule_t **r,struct policy_file *fp) +{ +uint32_t *buf, nel, nclass; +unsigned int i, j; +range_trans_rule_t *rt, *lrt =NULL ; +class_perm_node_t *cp, *lcp =NULL ; + + buf =next_entry (fp,sizeof (uint32_t )); +if (!buf) +return -1 ;
src/policydb.c
Quoted 10 lines
src/policydb.c +10
-0+ nel =le32_to_cpu (buf[0 ]); +for (i =0 ; i < nel; i++) { + rt =malloc (sizeof (range_trans_rule_t)); +if (!rt) { +return -1 ; + } +range_trans_rule_init (rt); + +if (type_set_read (&rt->stypes, fp)) +return -1 ;
Leaks rt. I'd suggest linking rt into the list earlier as we do elsewhere, so that it can be freed upon policydb_destroy.
src/policydb.c
Quoted 13 lines
src/policydb.c +13
-0+ nclass =le32_to_cpu (buf[0 ]); + rt->classes =NULL ; + lcp =NULL ; +for (j =0 ; j < nclass; j++) { + cp = (class_perm_node_t *)malloc ( +sizeof (class_perm_node_t)); +if (!cp) +return -1 ; +class_perm_node_init (cp); + + buf =next_entry (fp,sizeof (uint32_t )); +if (!buf) { +free (cp);
Or just move the code to link it into the list prior to this, so that it can be freed on the policydb_destroy path.
Quoted 25 lines
Index:
libsepol/src/expand.c
===================================================================src/expand.c +17
-0@@ -958,6 +958,99 @@return 0 ; } +static int expand_range_trans (expand_state_t *state,range_trans_rule_t *rules) +{ +unsigned int i, j; +range_trans_t *rt, *lrt, *cur_rt; +range_trans_rule_t *rule; +class_perm_node_t *cp; + +ebitmap_t stypes, ttypes; +ebitmap_node_t *snode, *tnode; + +/* start appending at the end of the current list */ +for (lrt = state->out->range_tr; lrt && lrt->next; lrt = lrt->next) + ; + +for (rule = rules; rule; rule = rule->next) { +ebitmap_init (&stypes); +ebitmap_init (&ttypes);
src/expand.c line 987
Quoted 10 lines
src/expand.c +10
-0+ +/* expand the type sets */ +if (expand_convert_type_set (state->out, state->typemap, + &rule->stypes, &stypes,1 )) { +ERR (state->handle,"Out of memory!" ); +return -1 ; + } +if (expand_convert_type_set (state->out, state->typemap, + &rule->ttypes, &ttypes,1 )) { +ERR (state->handle,"Out of memory!" );
Leaks stypes. Need an error exit path that does clean up.
Quoted 20 lines
src/expand.c +20
-0+return -1 ; + } + +/* loop on source type */ +ebitmap_for_each_bit (&stypes, snode, i) { +if (!ebitmap_node_get_bit (snode, i)) +continue ; +/* loop on target type */ +ebitmap_for_each_bit (&ttypes, tnode, j) { +if (!ebitmap_node_get_bit (tnode, j)) +continue ; +/* loop on target class */ +for (cp = rule->classes; cp; cp = cp->next) { + +/* check for duplicates/conflicts */ +for (cur_rt = state->out->range_tr; cur_rt; cur_rt = cur_rt->next) { +if ((cur_rt->source_type == i +1 ) && + (cur_rt->target_type == j +1 ) && + (cur_rt->target_class == cp->class)) { +if (mls_range_eq (&cur_rt->target_range, &rule->trange)) {
src/expand.c line 1017
Quoted 10 lines
src/expand.c +10
-0+/* duplicate */ +break ; + }else { +/* conflict */ +ERR (state->handle, +"Conflicting range trans rule %s %s : %s" , + state->out->p_type_val_to_name[i], + state->out->p_type_val_to_name[j], + state->out->p_class_val_to_name[cp->class]); +return -1 ;
Leaks stypes and ttypes.
src/expand.c line 1025
Quoted 8 lines
src/expand.c +8
-0+return -1 ; + } +memset (rt,0 ,sizeof (range_trans_t)); + rt->source_type = i +1 ; + rt->target_type = j +1 ; + rt->target_class = cp->class; +if (mls_range_cpy (&rt->target_range, &rule->trange)) { +ERR (state->handle,"Out of memory!" );
Leaks stypes, ttypes, and rt.
Signature · 8 lines
Stephen Smalley National Security Agency -- This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
Quoted 16 lines · Stephen Smalley
Quoted 16 lines
(quoted diff) +16
-0+static int range_trans_rule_read(range_trans_rule_t **r, struct policy_file *fp) +{ + uint32_t *buf, nel, nclass; + unsigned int i, j; + range_trans_rule_t *rt, *lrt = NULL; + class_perm_node_t *cp, *lcp = NULL; + + buf = next_entry(fp, sizeof(uint32_t)); + if (!buf) + return -1; + nel = le32_to_cpu(buf[0]); + for (i = 0; i < nel; i++) { + rt = malloc(sizeof(range_trans_rule_t)); + if (!rt) { + return -1; + }
Quoted 8 lines
Review
Quoted 4 lines
(quoted diff) +4
-0+ range_trans_rule_init(rt); + + if (type_set_read(&rt->stypes, fp)) + return -1;Leaks rt. I'd suggest linking rt into the list earlier as we do elsewhere, so that it can be freed upon
policydb_destroy.
<snip - more error path fixups >
Quoted 11 lines
Review
Quoted 8 lines
(quoted diff) +8
-0+ return -1; + } + memset(rt, 0, sizeof(range_trans_t)); + rt->source_type = i + 1; + rt->target_type = j + 1; + rt->target_class = cp->class; + if (mls_range_cpy(&rt->target_range, &rule->trange)) { + ERR(state->handle, "Out of memory!");Leaks stypes, ttypes, and rt.
Thanks for catching those - I knew there was something else I needed to do ;) I'll have to look at the code I modeled those functions after to see if they have the same issues... I'll post a new version of this patch (I'll wait a bit to see if there is other feedback) later.
Signature · 6 lines
Darrel -- This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
On Fri, 2006-07-28 at 10:13 -0500, Darrel Goeddel wrote:
<snip>
Review
Quoted 4 lines
(quoted diff) +4
-0+typedef struct range_trans_rule { + type_set_t stypes; + type_set_t ttypes; + class_perm_node_t *classes; /* only class is used */
Is class_perm_node_t the correct choice? What about an ebitmap for the classes? It is easier to manage and you don't end up wasting space for perms when they aren't used.
<snip>
Quoted 83 lines
(quoted diff) +83
-0+static int expand_range_trans(expand_state_t *state, range_trans_rule_t *rules) +{ + unsigned int i, j; + range_trans_t *rt, *lrt, *cur_rt; + range_trans_rule_t *rule; + class_perm_node_t *cp; + + ebitmap_t stypes, ttypes; + ebitmap_node_t *snode, *tnode; + + /* start appending at the end of the current list */ + for (lrt = state->out->range_tr; lrt && lrt->next; lrt = lrt->next) + ; + + for (rule = rules; rule; rule = rule->next) { + ebitmap_init(&stypes); + ebitmap_init(&ttypes); + + /* expand the type sets */ + if (expand_convert_type_set(state->out, state->typemap, + &rule->stypes, &stypes, 1)) { + ERR(state->handle, "Out of memory!"); + return -1; + } + if (expand_convert_type_set(state->out, state->typemap, + &rule->ttypes, &ttypes, 1)) { + ERR(state->handle, "Out of memory!"); + return -1; + } + + /* loop on source type */ + ebitmap_for_each_bit(&stypes, snode, i) { + if (!ebitmap_node_get_bit(snode, i)) + continue; + /* loop on target type */ + ebitmap_for_each_bit(&ttypes, tnode, j) { + if (!ebitmap_node_get_bit(tnode, j)) + continue; + /* loop on target class */ + for (cp = rule->classes; cp; cp = cp->next) { + + /* check for duplicates/conflicts */ + for (cur_rt = state->out->range_tr; cur_rt; cur_rt = cur_rt->next) { + if ((cur_rt->source_type == i + 1) && + (cur_rt->target_type == j + 1) && + (cur_rt->target_class == cp->class)) { + if (mls_range_eq(&cur_rt->target_range, &rule->trange)) { + /* duplicate */ + break; + } else { + /* conflict */ + ERR(state->handle, + "Conflicting range trans rule %s %s : %s", + state->out->p_type_val_to_name[i], + state->out->p_type_val_to_name[j], + state->out->p_class_val_to_name[cp->class]); + return -1; + } + } + } + if (cur_rt) /* this is a dup - skip */ + continue; + + rt = (range_trans_t *)malloc(sizeof(range_trans_t)); + if (!rt) { + ERR(state->handle, "Out of memory!"); + return -1; + } + memset(rt, 0, sizeof(range_trans_t)); + rt->source_type = i + 1; + rt->target_type = j + 1; + rt->target_class = cp->class; + if (mls_range_cpy(&rt->target_range, &rule->trange)) { + ERR(state->handle, "Out of memory!"); + return -1; + } + if (lrt) { + lrt->next = rt; + } else { + state->out->range_tr = rt; + } + lrt = rt; + }
Review
Quoted 10 lines
(quoted diff) +10
-0+ } + } + + ebitmap_destroy(&stypes); + ebitmap_destroy(&ttypes); + } + + return 0; +} +
Splitting this into some helper functions would make it more readable.
<snip>
Quoted 20 lines
Index:
libsepol/src/write.c
===================================================================src/write.c +4
-1@@ -39,6 +39,7 @@#include <sepol/policydb/policydb.h> #include <sepol/policydb/conditional.h> #include <sepol/policydb/expand.h> +#include <sepol/policydb/flask.h> #include "debug.h" #include "private.h" @@ -1124,21 +1125,36 @@ {size_t nel, items;struct range_trans *rt; -uint32_t buf[32 ]; +uint32_t buf[2 ]; +int new_rangetr = (p->policy_type ==POLICY_KERN && + p->policyvers >=POLICYDB_VERSION_RANGETRANS );
src/write.c line 1138
Quoted 10 lines
src/write.c +7
-2nel =0 ; -for (rt = p->range_tr; rt; rt = rt->next) - nel++; +for (rt = p->range_tr; rt; rt = rt->next) { +/* all range_transitions are written for the new format, only +process related range_transitions are written for the old +format, so count accordingly */ +if (new_rangetr || rt->target_class ==SECCLASS_PROCESS ) + nel++; + }
So there is no warning or indication that rules are being dropped? At some point it would be nice to let the user know that they are compiling a policy aimed at the new format but outputting an older policy.
Overall this looks good - again, thanks for taking the time to make it more complete. Seems like once we can require MLS symbols in modules it won't be too difficult to get range trans working with this change.
Karl
--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
Quoted 12 lines · Karl MacMillan
On Fri, 2006-07-28 at 10:13 -0500, Darrel Goeddel wrote:
<snip>Review
Quoted 4 lines
(quoted diff) +4
-0+typedef struct range_trans_rule { + type_set_t stypes; + type_set_t ttypes; + class_perm_node_t *classes; /* only class is used */Is
class_perm_node_tthe correct choice? What about an ebitmap for the classes? It is easier to manage and you don't end up wasting space for perms when they aren't used.
Using an ebitmap for classes does seem much nicer. I looked at the type transition rules before writing this and the list of classes from the avtab rules stuck with me. I'll make the change and see how it looks.
Quoted 90 lines
<snip>
Quoted 88 lines
(quoted diff) +88
-0+static int expand_range_trans(expand_state_t *state, range_trans_rule_t *rules) +{ + unsigned int i, j; + range_trans_t *rt, *lrt, *cur_rt; + range_trans_rule_t *rule; + class_perm_node_t *cp; + + ebitmap_t stypes, ttypes; + ebitmap_node_t *snode, *tnode; + + /* start appending at the end of the current list */ + for (lrt = state->out->range_tr; lrt && lrt->next; lrt = lrt->next) + ; + + for (rule = rules; rule; rule = rule->next) { + ebitmap_init(&stypes); + ebitmap_init(&ttypes); + + /* expand the type sets */ + if (expand_convert_type_set(state->out, state->typemap, + &rule->stypes, &stypes, 1)) { + ERR(state->handle, "Out of memory!"); + return -1; + } + if (expand_convert_type_set(state->out, state->typemap, + &rule->ttypes, &ttypes, 1)) { + ERR(state->handle, "Out of memory!"); + return -1; + } + + /* loop on source type */ + ebitmap_for_each_bit(&stypes, snode, i) { + if (!ebitmap_node_get_bit(snode, i)) + continue; + /* loop on target type */ + ebitmap_for_each_bit(&ttypes, tnode, j) { + if (!ebitmap_node_get_bit(tnode, j)) + continue; + /* loop on target class */ + for (cp = rule->classes; cp; cp = cp->next) { + + /* check for duplicates/conflicts */ + for (cur_rt = state->out->range_tr; cur_rt; cur_rt = cur_rt->next) { + if ((cur_rt->source_type == i + 1) && + (cur_rt->target_type == j + 1) && + (cur_rt->target_class == cp->class)) { + if (mls_range_eq(&cur_rt->target_range, &rule->trange)) { + /* duplicate */ + break; + } else { + /* conflict */ + ERR(state->handle, + "Conflicting range trans rule %s %s : %s", + state->out->p_type_val_to_name[i], + state->out->p_type_val_to_name[j], + state->out->p_class_val_to_name[cp->class]); + return -1; + } + } + } + if (cur_rt) /* this is a dup - skip */ + continue; + + rt = (range_trans_t *)malloc(sizeof(range_trans_t)); + if (!rt) { + ERR(state->handle, "Out of memory!"); + return -1; + } + memset(rt, 0, sizeof(range_trans_t)); + rt->source_type = i + 1; + rt->target_type = j + 1; + rt->target_class = cp->class; + if (mls_range_cpy(&rt->target_range, &rule->trange)) { + ERR(state->handle, "Out of memory!"); + return -1; + } + if (lrt) { + lrt->next = rt; + } else { + state->out->range_tr = rt; + } + lrt = rt; + } + } + } + + ebitmap_destroy(&stypes); + ebitmap_destroy(&ttypes);
Quoted 8 lines
Review
Quoted 5 lines
(quoted diff) +5
-0+ } + + return 0; +} +Splitting this into some helper functions would make it more readable.
Yeah. I tried some breakups before but I really didn't find much that helped. I'll try again. I still code at the console sometimes and I hate yelling at myself for things like this ;)
Quoted 29 lines
<snip>
Quoted 27 lines
Index:
libsepol/src/write.c
===================================================================src/write.c +8
-3@@ -39,6 +39,7 @@#include <sepol/policydb/policydb.h> #include <sepol/policydb/conditional.h> #include <sepol/policydb/expand.h> +#include <sepol/policydb/flask.h> #include "debug.h" #include "private.h" @@ -1124,21 +1125,36 @@ {size_t nel, items;struct range_trans *rt; -uint32_t buf[32 ]; +uint32_t buf[2 ]; +int new_rangetr = (p->policy_type ==POLICY_KERN && + p->policyvers >=POLICYDB_VERSION_RANGETRANS ); nel =0 ; -for (rt = p->range_tr; rt; rt = rt->next) - nel++; +for (rt = p->range_tr; rt; rt = rt->next) { +/* all range_transitions are written for the new format, only +process related range_transitions are written for the old +format, so count accordingly */
Quoted 8 lines
src/write.c line 1138
Quoted 3 lines
src/write.c +3
-0+if (new_rangetr || rt->target_class ==SECCLASS_PROCESS ) + nel++; + }So there is no warning or indication that rules are being dropped? At some point it would be nice to let the user know that they are compiling a policy aimed at the new format but outputting an older policy.
Correct. I think you inadvertently pointed out some tests I forgot to run - I have not compiled/tested monolithic policies with this patchset. I am assuming that you can still specify an older output format when compiling monolithically unlike the modular case where it always writes the newest formats. There we would be able to print out a warning about unsupported bits being discarded. The case I have tested with this code path is libselinux downgrading a version 21 policy to version 20 for use in an older kernel. In that case, I really don't see an appropriate feedback mechanism. Any thoughts on that case? Warn about policy downgrades in some manner?
Quoted 3 lines
Overall this looks good - again, thanks for taking the time to make it more complete. Seems like once we can require MLS symbols in modules it won't be too difficult to get range trans working with this change.
Cool. Thanks for taking at look at that.
Quoted 1 line
Karl
Signature · 6 lines
Darrel -- This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
Quoted 9 lines · Darrel Goeddel
Correct. I think you inadvertently pointed out some tests I forgot to run - I have not compiled/tested monolithic policies with this patchset. I am assuming that you can still specify an older output format when compiling monolithically unlike the modular case where it always writes the newest formats. There we would be able to print out a warning about unsupported bits being discarded. The case I have tested with this code path is libselinux downgrading a version 21 policy to version 20 for use in an older kernel. In that case, I really don't see an appropriate feedback mechanism. Any thoughts on that case? Warn about policy downgrades in some manner?
policydb_write() calls WARN() in the case where it has to discard booleans and conditional rules upon downgrading to a policy version that doesn't support them. Likewise, a single warning message would be suitable if you encounter any range transitions with non-process class and are writing a policy with a lower version.
Signature · 8 lines
Stephen Smalley National Security Agency -- This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
include/sepol/policydb/policydb.h (working copy)
Quoted 13 lines · Darrel Goeddel
Index:
libsepol/include/sepol/policydb/policydb.h
===================================================================include/sepol/policydb/policydb.h (working copy) renamed from include/sepol/policydb/policydb.h (revision 38) +8
-0+typedef struct range_trans_rule { + type_set_t stypes; + type_set_t ttypes; + class_perm_node_t *classes; /* only class is used */ + mls_range_t trange; + struct range_trans_rule *next; +} range_trans_rule_t; +
Are we sure that mls_range_t is semantic enough to store the rule, even in a module situation where all the symbols are not present?
<snip>
include/sepol/policydb/policydb.h (working copy) line 2974
Quoted 8 lines
return -1;include/sepol/policydb/policydb.h (working copy) renamed from include/sepol/policydb/policydb.h (revision 38) +2
-1@@ -2835,7 +2970,8 @@ if ((p->policy_type == POLICY_KERN && p->policyvers >= POLICYDB_VERSION_MLS) || (p->policy_type == POLICY_BASE - && p->policyvers >= MOD_POLICYDB_VERSION_MLS)) { + && p->policyvers >= MOD_POLICYDB_VERSION_MLS + && p->policyvers < MOD_POLICYDB_VERSION_RANGETRANS)) {
man, this conditional is getting out of hand :\
<snip>
Quoted 13 lines
include/sepol/policydb/policydb.h (working copy) renamed from include/sepol/policydb/policydb.h (revision 38) +12
-0+static int expand_range_trans(expand_state_t *state, range_trans_rule_t *rules) +{ + unsigned int i, j; + range_trans_t *rt, *lrt, *cur_rt; + range_trans_rule_t *rule; + class_perm_node_t *cp; + + ebitmap_t stypes, ttypes; + ebitmap_node_t *snode, *tnode; + + /* start appending at the end of the current list */ + for (lrt = state->out->range_tr; lrt && lrt->next; lrt =
Quoted 2 lines
lrt->next)
+ ;
I know the current code is like this, it was probably done that way to match the pre-module compiler behavior but we could probably change these to prepend, for simpler code.
<snip>
Quoted 9 lines
+ rt = (
range_trans_t
*)malloc(sizeof(range_trans_t));include/sepol/policydb/policydb.h (working copy) renamed from include/sepol/policydb/policydb.h (revision 38) +2
-0+ if (!rt) { + ERR(state->handle,"Out of memory!");
include/sepol/policydb/policydb.h (working copy) renamed from include/sepol/policydb/policydb.h (revision 38) +3
-0+ return -1; + } + memset(rt, 0,
sizeof(range_trans_t));
It is my preference to have initializers for structs but even if not the current trend in this library is to turn malloc/memset into calloc. (Though I'd really prefer an initializer just so that these sites don't have to be audited when the struct changes)
<snip>
include/sepol/policydb/policydb.h (working copy)
Quoted 5 lines
include/sepol/policydb/policydb.h (working copy) renamed from include/sepol/policydb/policydb.h (revision 38) +5
-0+ new_range->target_class = range->target_class; + if (mls_level_clone(&new_range->target_range.level[0], + &range->target_range.level[0]) || + mls_level_clone(&new_range->target_range.level[1], + &range->target_range.level[1])) {
can we break these into separate calls? It is easier to read IMO
<snip>
Quoted 9 lines
items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return -1; for (rt = p->range_tr; rt; rt = rt->next) {include/sepol/policydb/policydb.h (working copy) renamed from include/sepol/policydb/policydb.h (revision 38) +1
-2- buf[0] = cpu_to_le32(rt->dom); - buf[1] = cpu_to_le32(rt->type); + if (!new_rangetr && rt->target_class !=
SECCLASS_PROCESS)
+ continue;
I think this was mentioned in another email but a WARN() should probably be put here
<snip>
include/sepol/policydb/policydb.h (working copy)
Quoted 6 lines
include/sepol/policydb/policydb.h (working copy) renamed from include/sepol/policydb/policydb.h (revision 38) +6
-0+ rule = malloc(sizeof(struct range_trans_rule)); + if (!rule) { + yyerror("out of memory"); + return -1; + } + memset(rule, 0, sizeof(struct range_trans_rule));
init?
In addition to the other comments this looks pretty good. I hope that we'll be able to use this format change to allow range_trans in modules.
--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
Quoted 8 lines · Joshua Brindle
Quoted 4 lines · Darrel Goeddel
Index:
libsepol/include/sepol/policydb/policydb.h
===================================================================include/sepol/policydb/policydb.h (working copy) renamed from include/sepol/policydb/policydb.h (revision 38) +0
-0
Quoted 12 lines
include/sepol/policydb/policydb.h (working copy)
Quoted 8 lines
include/sepol/policydb/policydb.h (working copy) renamed from include/sepol/policydb/policydb.h (revision 38) +8
-0+typedef struct range_trans_rule { + type_set_t stypes; + type_set_t ttypes; + class_perm_node_t *classes; /* only class is used */ + mls_range_t trange; + struct range_trans_rule *next; +} range_trans_rule_t; +Are we sure that
mls_range_tis semantic enough to store the rule, even in a module situation where all the symbols are not present?
Hmmm... I assume that you have MLS requirements in mind when you say that, especially the '.' notation. The problem is that if we specify "s4:c0.c12" as the range, how do we know what will be between c0 and c12 (they are arbitrary names). Are you suggesting possibly storing the string and figuring the whole thing out at expand time?
We could also make sensitivity and category names non-arbitrary and force the naming convention of s# and c# ;) Translations take care of human-readable for us now...
Quoted 12 lines
Quoted 12 lines
+static int
expand_range_trans(expand_state_t *state, range_trans_rule_t *rules)include/sepol/policydb/policydb.h (working copy) renamed from include/sepol/policydb/policydb.h (revision 38) +10
-0+{ + unsigned int i, j; + range_trans_t *rt, *lrt, *cur_rt; + range_trans_rule_t *rule; + class_perm_node_t *cp; + + ebitmap_t stypes, ttypes; + ebitmap_node_t *snode, *tnode; + + /* start appending at the end of the current list */
Quoted 8 lines
Quoted 3 lines
+ for (lrt =
state->out->range_tr; lrt &&lrt->next; lrt =lrt->next)
+ ;I know the current code is like this, it was probably done that way to match the pre-module compiler behavior but we could probably change these to prepend, for simpler code.
I'll look at that.
Quoted 11 lines
Quoted 9 lines
+ rt = (
range_trans_t
*)malloc(sizeof(range_trans_t));include/sepol/policydb/policydb.h (working copy) renamed from include/sepol/policydb/policydb.h (revision 38) +2
-0+ if (!rt) { + ERR(state->handle,"Out of memory!");
include/sepol/policydb/policydb.h (working copy) renamed from include/sepol/policydb/policydb.h (revision 38) +3
-0+ return -1; + } + memset(rt, 0,
sizeof(range_trans_t));
Quoted 4 lines
It is my preference to have initializers for structs but even if not the current trend in this library is to turn malloc/memset into calloc. (Though I'd really prefer an initializer just so that these sites don't have to be audited when the struct changes)
I'll check on this as well - I'll at least change to calloc.
Quoted 8 lines
include/sepol/policydb/policydb.h (working copy)
Quoted 5 lines
include/sepol/policydb/policydb.h (working copy) renamed from include/sepol/policydb/policydb.h (revision 38) +5
-0+ new_range->target_class = range->target_class; + if (mls_level_clone(&new_range->target_range.level[0], + &range->target_range.level[0]) || + mls_level_clone(&new_range->target_range.level[1], + &range->target_range.level[1])) {can we break these into separate calls? It is easier to read IMO
Yep.
Quoted 11 lines
Quoted 9 lines
items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return -1; for (rt = p->range_tr; rt; rt = rt->next) {include/sepol/policydb/policydb.h (working copy) renamed from include/sepol/policydb/policydb.h (revision 38) +1
-2- buf[0] = cpu_to_le32(rt->dom); - buf[1] = cpu_to_le32(rt->type); + if (!new_rangetr && rt->target_class !=
SECCLASS_PROCESS)
+ continue;
Quoted 2 lines
I think this was mentioned in another email but a
WARN()should probably be put here
Will do.
Quoted 9 lines
include/sepol/policydb/policydb.h (working copy)
Quoted 6 lines
include/sepol/policydb/policydb.h (working copy) renamed from include/sepol/policydb/policydb.h (revision 38) +6
-0+ rule = malloc(sizeof(struct range_trans_rule)); + if (!rule) { + yyerror("out of memory"); + return -1; + } + memset(rule, 0, sizeof(struct range_trans_rule));init?
Sounds like a plan.
Quoted 2 lines
In addition to the other comments this looks pretty good. I hope that we'll be able to use this format change to allow
range_transin modules.
Cool. I hope to have a revision of the patch that includes your all of the feedback received so far (except the mls_range_t in the range_trans_rule_t - I think there will be more discussion there) by tomorrow afternoon.
Signature · 6 lines
Darrel -- This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
Quoted 22 lines · Darrel Goeddel
Quoted 8 lines · Joshua Brindle
Quoted 4 lines · Darrel Goeddel
Index:
libsepol/include/sepol/policydb/policydb.h
===================================================================include/sepol/policydb/policydb.h (working copy) renamed from include/sepol/policydb/policydb.h (revision 38) +0
-0Quoted 12 lines
include/sepol/policydb/policydb.h (working copy)
Quoted 8 lines
include/sepol/policydb/policydb.h (working copy) renamed from include/sepol/policydb/policydb.h (revision 38) +8
-0+typedef struct range_trans_rule { + type_set_t stypes; + type_set_t ttypes; + class_perm_node_t *classes; /* only class is used */ + mls_range_t trange; + struct range_trans_rule *next; +} range_trans_rule_t; +Are we sure that
mls_range_tis semantic enough to store the rule, even in a module situation where all the symbols are not present?
Quoted 6 lines
Hmmm... I assume that you have MLS requirements in mind when you say that, especially the '.' notation. The problem is that if we specify "s4:c0.c12" as the range, how do we know what will be between c0 and c12 (they are arbitrary names). Are you suggesting possibly storing the string and figuring the whole thing out at expand time?
Or storing the start and end of the range. This seems analogous to attributes to me and we defer interpreting them until expand time.
Karl
--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
Quoted 34 lines · Karl MacMillan
Quoted 24 lines · Darrel Goeddel
Quoted 9 lines · Joshua Brindle
Quoted 4 lines · Darrel Goeddel
Index:
libsepol/include/sepol/policydb/policydb.h
===================================================================include/sepol/policydb/policydb.h (working copy) renamed from include/sepol/policydb/policydb.h (revision 38) +0
-0Quoted 12 lines
include/sepol/policydb/policydb.h (working copy)
Quoted 8 lines
include/sepol/policydb/policydb.h (working copy) renamed from include/sepol/policydb/policydb.h (revision 38) +8
-0+typedef struct range_trans_rule { + type_set_t stypes; + type_set_t ttypes; + class_perm_node_t *classes; /* only class is used */ + mls_range_t trange; + struct range_trans_rule *next; +} range_trans_rule_t; +Are we sure that
mls_range_tis semantic enough to store the rule, even in a module situation where all the symbols are not present?Quoted 6 lines
Hmmm... I assume that you have MLS requirements in mind when you say that, especially the '.' notation. The problem is that if we specify "s4:c0.c12" as the range, how do we know what will be between c0 and c12 (they are arbitrary names). Are you suggesting possibly storing the string and figuring the whole thing out at expand time?
Quoted 2 lines
Or storing the start and end of the range. This seems analogous to attributes to me and we defer interpreting them until expand time.
A level can contain any combination of category ranges and single categories such as "s3:c0,c4,c10.c20,c24,c30.c38". It seems like we would need a list of structs to represent each piece semantically (single cat c0, single cat c4, range of cats from c10 to c20, ...) - the string seems to do that nicely. To use the above level, we would require the sensitivity s3 and the categories c0, c4, c10, c20, c24, c30, and c38. At expansion time, the string would tell us that we really wanted the categories in between c10 and c20, as well as the categories in between c30 and c38, to be included as well.
Signature · 6 lines
Darrel -- This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
Quoted 44 lines
From: Darrel Goeddel [mailto:[email protected]]
Quoted 9 lines · Karl MacMillan
Quoted 7 lines · Darrel Goeddel
Quoted 5 lines · Joshua Brindle
Quoted 2 lines · Darrel Goeddel
Index:
libsepol/include/sepol/policydb/policydb.h
===================================================================
Quoted 16 lines
Quoted 16 lines
Quoted 15 lines
include/sepol/policydb/policydb.h (working copy)
Quoted 11 lines
include/sepol/policydb/policydb.h (working copy) renamed from include/sepol/policydb/policydb.h (revision 38) +7
-0+typedef struct range_trans_rule { + type_set_t stypes; + type_set_t ttypes; + class_perm_node_t *classes; /* only class is used */ + mls_range_t trange; + struct range_trans_rule *next; } range_trans_rule_t; +Are we sure that
mls_range_tis semantic enough to store the rule, even in a module situation where all the symbols are not present?Quoted 1 line
Quoted 1 line
Hmmm... I assume that you have MLS requirements in mind
when you say
Quoted 1 line
Quoted 1 line
that, especially the '.' notation. The problem is that if
we specify
Quoted 1 line
Quoted 1 line
"s4:c0.c12" as the range, how do we know what will be
between c0 and
Quoted 1 line
Quoted 1 line
c12 (they are arbitrary names). Are you suggesting
possibly storing
Quoted 6 lines
Quoted 2 lines
the string and figuring the whole thing out at expand time?
Or storing the start and end of the range. This seems analogous to attributes to me and we defer interpreting them until expand time.
Quoted 11 lines
A level can contain any combination of category ranges and single categories such as "s3:c0,c4,c10.c20,c24,c30.c38". It seems like we would need a list of structs to represent each piece semantically (single cat c0, single cat c4, range of cats from c10 to c20, ...) - the string seems to do that nicely. To use the above level, we would require the sensitivity s3 and the categories c0, c4, c10, c20, c24, c30, and c38. At expansion time, the string would tell us that we really wanted the categories in between c10 and c20, as well as the categories in between c30 and c38, to be included as well.
This is what I was thinking, there is no way to show the intent of categories once you flatten it to an ebitmap. What kind of data structures are you thinking?
--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
Quoted 34 lines
From: Darrel Goeddel [mailto:[email protected]]
Quoted 8 lines · Joshua Brindle
Quoted 4 lines · Darrel Goeddel
Index:
libsepol/include/sepol/policydb/policydb.h
===================================================================include/sepol/policydb/policydb.h (working copy) renamed from include/sepol/policydb/policydb.h (revision 38) +0
-0Quoted 10 lines
include/sepol/policydb/policydb.h (working copy)
Quoted 7 lines
include/sepol/policydb/policydb.h (working copy) renamed from include/sepol/policydb/policydb.h (revision 38) +7
-0+typedef struct range_trans_rule { + type_set_t stypes; + type_set_t ttypes; + class_perm_node_t *classes; /* only class is used */ + mls_range_t trange; + struct range_trans_rule *next; } range_trans_rule_t; +Are we sure that
mls_range_tis semantic enough to storethe rule, even
Quoted 1 line
in a module situation where all the symbols are not present?
Hmmm... I assume that you have MLS requirements in mind when you say that,
especially the '.' notation. The problem is that if we specify "s4:c0.c12" as
the range, how do we know what will be between c0 and c12 (they are arbitrary
names). Are you suggesting possibly storing the string and figuring the whole
thing out at expand time?
Quoted 6 lines
We could also make sensitivity and category names non-arbitrary and force the
naming convention of s# and c# ;) Translations take care of human-readable for
us now...
I understand the desire to do this and chances are the sensitivies and categories in the policy will never change but I'd also like to stay away from hard coded policy logic (I'm sure others feel the same way). I think we are going to have to just store the levels as strings in the modular format and do sanity checks at expand time (eg., if s12-s0 is in a policy it will compile fine but the expander will bail).
I'm not really sure where the best place to do this is, one option is to use the entire range "s0-s12.c1.c12" as the symbol key in the level symtab (very strange and awkward, I don't really like it). Otherwise we can add a string to range_trans_rule_t and store it there, also non-standard. When doing this we should go ahead and fix user as well since users aren't allowed in mls modules now.
--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
Quoted 46 lines · Joshua Brindle
Quoted 28 lines
From: Darrel Goeddel [mailto:[email protected]]
Quoted 9 lines · Joshua Brindle
Quoted 4 lines · Darrel Goeddel
Index:
libsepol/include/sepol/policydb/policydb.h
===================================================================include/sepol/policydb/policydb.h (working copy) renamed from include/sepol/policydb/policydb.h (revision 38) +0
-0Quoted 10 lines
include/sepol/policydb/policydb.h (working copy)
Quoted 7 lines
include/sepol/policydb/policydb.h (working copy) renamed from include/sepol/policydb/policydb.h (revision 38) +7
-0+typedef struct range_trans_rule { + type_set_t stypes; + type_set_t ttypes; + class_perm_node_t *classes; /* only class is used */ + mls_range_t trange; + struct range_trans_rule *next; } range_trans_rule_t; +Are we sure that
mls_range_tis semantic enough to storethe rule, even
Quoted 1 line
in a module situation where all the symbols are not present?
Quoted 9 lines
Hmmm... I assume that you have MLS requirements in mind when you say that, especially the '.' notation. The problem is that if we specify "s4:c0.c12" as the range, how do we know what will be between c0 and c12 (they are arbitrary names). Are you suggesting possibly storing the string and figuring the whole thing out at expand time?
We could also make sensitivity and category names non-arbitrary and force the naming convention of s# and c# ;) Translations take care of human-readable for us now...
I understand the desire to do this and chances are the sensitivies and categories in the policy will never change but I'd also like to stay away from hard coded policy logic (I'm sure others feel the same way). I think we are going to have to just store the levels as strings in the modular format and do sanity checks at expand time (eg., if s12-s0 is in a policy it will compile fine but the expander will bail).
Quoted 6 lines
I'm not really sure where the best place to do this is, one option is to use the entire range "s0-s12.c1.c12" as the symbol key in the level symtab (very strange and awkward, I don't really like it). Otherwise we can add a string to
range_trans_rule_tand store it there, also non-standard. When doing this we should go ahead and fix user as well since users aren't allowed in mls modules now.
I think the string may be easiest. Otherwise a list of structs like:
struct mls_cat_component {
int start;
int stop;
struct mls_cat_component *next;
} mls_cat_component_tcould be used. Where something like c0,c4,c10.c20,c25 would be represented as:
start=1
stop=1
next=......start=4
stop=4
next=......start=c10
stop=c20
next=......start=25
stop=25
next=NULLI can play with working something up based on storing the string rather than the mls_range_t just to see what it would look like. I'm not sure going with a more complicated structure based method really buys us much. If there are other structure ideas - I'd sure like to investigate them.
BTW, sorry for the delay, I was unavailable yesterday...
Signature · 6 lines
Darrel -- This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
Quoted 2 lines
From: Darrel Goeddel [mailto:[email protected]]
Quoted 1 line
I think the string may be easiest. Otherwise a list of structs
like:
Quoted 10 lines
struct mls_cat_component { int start; int stop; struct mls_cat_component *next; } mls_cat_component_tcould be used. Where something like c0,c4,c10.c20,c25 would be represented as:
Quoted 10 lines
start=1
stop=1
next=......start=4
stop=4
next=......start=c10
stop=c20
next=......start=25
stop=25
next=NULLShould start/stop be datum values or just pointers to the datum?
Quoted 8 lines
I can play with working something up based on storing the string rather than the
mls_range_tjust to see what it would look like. I'm not sure going with a more complicated structure based method really buys us much. If there are other structure ideas - I'd sure like to investigate them.BTW, sorry for the delay, I was unavailable yesterday...
How likely is it that the mls component in the context will ever change? There is an interesting benefit to making the mls component opaque to the compiler and the module format (by storing a string) but it also makes error checking harder. Then again, right now you can only do syntactic checking anyway since we don't know the level/cat configuration from a module.
One other thing, we need a require syntax for these things, we have been using each symbol type so s1-s10:c0,c4,c10.c20 would look like
Require {
sens s1, s10;
cats c0, c4, c10, c20;
}Which ensures the symbols are present but not that they make sense, we have a similar problem with class requires since the permissions for the class may not be there, the error must be handled at link time, likewise this would also.
Another option we threw around when thinking about this problem was using the entire component as the symbol:
Require {
level s1-s10:c0,c4,c10.c20;
}I'm not sure which is more appropriate, since MLS does not view each cat as a separate entity the second one seems more within the model but it isn't a real symbol in terms of the symbol tables (unless we turn it into one)
I think the latter might be the best bet, the entire level could be a symbol and the mls_range_rule_t (or whatever) would just have the value of the level. Then at expand time the mls_range_rule_t gets converted into an mls_range_t and the symbol is interpreted and checked for validity.
I'm dubious about using the same symbol table to store sens (s1) and levels (s1-s10:c0) but adding a new symtab that is missing in the kernel format while the sens and cats are unused in the module format seems silly.
I'm also a little skeptical about having levels in this fashion at all, categories are a local configuration and, in general, we've been pushing local configurations to libsemanage. Granted policy modules have file contexts with levels but they can still be overridden locally. I almost think the policy modules need to be using symbolic names so that they can be converted to the local system configuration, throwing translation into the expander mix seems fairly non-ideal though, what are your thoughts on this?
--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
Quoted 26 lines · Joshua Brindle
Quoted 3 lines
From: Darrel Goeddel [mailto:[email protected]]
Quoted 1 line
I think the string may be easiest. Otherwise a list of structs
like:
Quoted 11 lines
struct mls_cat_component { int start; int stop; struct mls_cat_component *next; } mls_cat_component_tcould be used. Where something like c0,c4,c10.c20,c25 would be represented as:
start=1
stop=1
next=......start=4Quoted 7 lines
stop=4 next=......start=c10 stop=c20 next=......start=25 stop=25 next=NULL
Quoted 1 line
Should start/stop be datum values or just pointers to the datum?
datum values - they would map to the values that are represented by the "required" items. So for the above context we would require the following (as you stated below):
Require {
sens s1, s10;
cats c0, c4, c10, c20, c25;
}Let's say that maps to the following datum values for the module:
s1=0, s10=1, c0=0, c4=1, c10=2, c20=3, c25=4
then the representation for the cats (in the module) would be:
start=0
stop=0
next=......start=1
stop=1
next=......start=2
stop=3
next=......start=4
stop=4
next=NULLThose datum values would need to be mapped to the "real" values when the policy is linked to the base which contains the definitions like this:
s1=1, s10=10, c0=0, c4=4, c10=10, c20=20, c25=25
The representation for the modules when it is linked and expanded would then turn out to be what I had originally (without the 'c's in the 3rd member - that was a mistake...)
As you can see, this would require a lot more logic than just interpreting the string at expand time. Unless, I'm way off on this one - I still need to study up on the linking...
<snip>
Quoted 1 line
How likely is it that the mls component in the context will ever change?
I'm not sure I follow you on this - are you asking about future format changes for a context? If so, I'd hope that it wouldn't ;)
Quoted 5 lines
There is an interesting benefit to making the mls component opaque to the compiler and the module format (by storing a string) but it also makes error checking harder. Then again, right now you can only do syntactic checking anyway since we don't know the level/cat configuration from a module.
What is the interesting benefit?
Quoted 8 lines
One other thing, we need a require syntax for these things, we have been using each symbol type so s1-s10:c0,c4,c10.c20 would look like
Require { sens s1, s10; cats c0, c4, c10, c20; }
Quoted 4 lines
Which ensures the symbols are present but not that they make sense, we have a similar problem with class requires since the permissions for the class may not be there, the error must be handled at link time, likewise this would also.
This is what I was thinking.
Quoted 11 lines
Another option we threw around when thinking about this problem was using the entire component as the symbol:
Require { level s1-s10:c0,c4,c10.c20; }I'm not sure which is more appropriate, since MLS does not view each cat as a separate entity the second one seems more within the model but it isn't a real symbol in terms of the symbol tables (unless we turn it into one)
Quoted 5 lines
I think the latter might be the best bet, the entire level could be a symbol and the
mls_range_rule_t(or whatever) would just have the value of the level. Then at expand time themls_range_rule_tgets converted into anmls_range_tand the symbol is interpreted and checked for validity.
Wouldn't this mean that the base module would have to define every possible combination of sensitivities and categories? That would make things a bit unmanageable.
Quoted 5 lines
I'm dubious about using the same symbol table to store sens (s1) and levels (s1-s10:c0) but adding a new symtab that is missing in the kernel format while the sens and cats are unused in the module format seems silly.
Quoted 8 lines
I'm also a little skeptical about having levels in this fashion at all, categories are a local configuration and, in general, we've been pushing local configurations to libsemanage. Granted policy modules have file contexts with levels but they can still be overridden locally. I almost think the policy modules need to be using symbolic names so that they can be converted to the local system configuration, throwing translation into the expander mix seems fairly non-ideal though, what are your thoughts on this?
I don't look at categories and sensitivities s local configuration at all - they are a defined part of the policy. A human-readable translation for what the level means is a local configuration. It is really the same story for types - I can use security_t in my module, but I am making assumptions about what security_t means in the base policy. When I put s4:c0,c5,c100.c150 into a module, I am making the same assumptions.
As for putting the translations into the policy - that doesn't work out very well. I believe that we experimented with that a long time ago and found it to be a complete nightmare. IMO, the correct place for translations would be at the level of a tool that would help create policy modules.
Signature · 6 lines
Darrel -- This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
Quoted 10 lines
From: Darrel Goeddel [mailto:[email protected]]
Quoted 2 lines · Joshua Brindle
Should start/stop be datum values or just pointers to the datum?
datum values - they would map to the values that are represented by the "required" items. So for the above context we would require the following (as you stated below):
right
Quoted 9 lines
The representation for the modules when it is linked and expanded would then turn out to be what I had originally (without the 'c's in the 3rd member - that was a mistake...)
As you can see, this would require a lot more logic than just interpreting the string at expand time. Unless, I'm way off on this one - I still need to study up on the linking...
It's a little more logic but pretty much the same thing we have to do everywhere else.
Quoted 4 lines
<snip>
Quoted 1 line
There is an interesting benefit to making the mls component
Quoted 9 lines
opaque to
Quoted 1 line
the compiler and the module format (by storing a string)
but it also
Quoted 3 lines
makes error checking harder. Then again, right now you can only do syntactic checking anyway since we don't know the level/cat configuration from a module.
What is the interesting benefit?
The benefit is that if the mls context structure ever changes the format won't, only the expander will have to be changed to deal with it. This might not be compelling since you indicate it'll never happen
Quoted 11 lines
Quoted 2 lines
I think the latter might be the best bet, the entire level
could be a
Quoted 4 lines
symbol and the
mls_range_rule_t(or whatever) would just have the value of the level. Then at expand time themls_range_rule_tgets converted into anmls_range_tand the symbol is interpreted and checked for validity.Wouldn't this mean that the base module would have to define every possible combination of sensitivities and categories? That would make things a bit unmanageable.
No, the required range would be interpreted the same way that any other range is. Every complete range used within a module (or optional block) would have to be required though, but I'm not sure how big of a deal that is, how many different combinations are typically used? Now that users aren't even put in the policy for different mls ranges I assume it is very few.
Quoted 9 lines
I don't look at categories and sensitivities s local configuration at all - they are a defined part of the policy.
A human-readable translation for what the level means is a
local configuration. It is really the same story for types - I can usesecurity_tin my module, but I am making assumptions about whatsecurity_tmeans in the base policy. When I put s4:c0,c5,c100.c150 into a module, I am making the same assumptions.
Not sure about this, SystemHigh is not the same on every system, how does a module reconcile that? You are right about the typespace which is something we want to address, refpolicy interfaces introduced encapsulation where modules don't know about other modules types, unfortunately since its all compile time now the encapsulation isn't enforced but interfaces in the language would be able to do that.
Quoted 6 lines
As for putting the translations into the policy - that doesn't work out very well. I believe that we experimented with that a long time ago and found it to be a complete nightmare. IMO, the correct place for translations would be at the level of a tool that would help create policy modules.
I understand that, I'm just wondering how one could ever distribute a module with any mls range to different sites. If everyone is using refpolicy the types are known to be the same, that isn't the case with sensitivities and categories since they truly are a local configuration via the translations.
--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
Quoted 4 lines · Joshua Brindle
Quoted 4 lines
From: Darrel Goeddel [mailto:[email protected]]
Joshua Brindle wrote:
<snip>
Quoted 9 lines
Quoted 1 line
Wouldn't this mean that the base module would have to define every possible combination of sensitivities and categories? That would make things a bit unmanageable.
No, the required range would be interpreted the same way that any other range is. Every complete range used within a module (or optional block) would have to be required though, but I'm not sure how big of a deal that is, how many different combinations are typically used? Now that users aren't even put in the policy for different mls ranges I assume it is very few.
There are environments that use thousands of combinations.
Quoted 11 lines
Quoted 3 lines
I don't look at categories and sensitivities s local configuration at all - they are a defined part of the policy. A human-readable translation for what the level means is a local configuration. It is really the same story for types - I can use
security_tin my module, but I am making assumptions about whatsecurity_tmeans in the base policy. When I put s4:c0,c5,c100.c150 into a module, I am making the same assumptions.Not sure about this, SystemHigh is not the same on every system, how does a module reconcile that? You are right about the typespace which is something we want to address, refpolicy interfaces introduced encapsulation where modules don't know about other modules types, unfortunately since its all compile time now the encapsulation isn't enforced but interfaces in the language would be able to do that.
True, SystemHigh may not be the same on every system. The policy would have to have knowledge of the label encoding scheme of the target. Typically, an environment will have a approved scheme that is used by all systems.
(actually SystemHigh is probably the same because it should be the highest sensitivity and all cats, but other labels such as secret, unclass, etc. may have different encodings for different sites)
Quoted 9 lines
Quoted 2 lines
As for putting the translations into the policy - that doesn't work out very well. I believe that we experimented with that a long time ago and found it to be a complete nightmare. IMO, the correct place for translations would be at the level of a tool that would help create policy modules.
I understand that, I'm just wondering how one could ever distribute a module with any mls range to different sites. If everyone is using refpolicy the types are known to be the same, that isn't the case with sensitivities and categories since they truly are a local configuration via the translations.
Yep. In practice, that "local" configuration is generally not local to a specific system, rather it is common to the entire enterprise. It is a customer or site configuration, not necessarily a machine configuration. Policy for that environment must be aware of the labeling scheme.
I hope I got that right...
Signature · 6 lines
Darrel -- This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
What's new: This revision of the patch should address all comments so far except for the ongoing discussion about whether or not the mls_range_t in the range_trans_rule_t will be semantic enough for module support (it will not be, but a replacement has not been decided on...). In particular:
- memory leaks should be taken care of
- the classes are now represented as and ebitmap
- some crappy code has been refactored into a helper function
- a warning is issued when rules are dropped due to a policy downgrade
- some general code readability enhancements are included
- better structure initialization is used
- a few more mls helper functions have been added
I can send an incremental patch for perusal if anyone wants it.
This patch has also been rebased to version 45 of the svn tree (no real changes for that).
Introduce support for kernel policy format version 21, base policy format version 6, and policy module format 6. These new formats allow for the definition of range_transitions on security classes other than "process". The
new module and base formats (both 6) also move expansion of the range_transition statements from compile time to the actual expansion phase. This change should allow for using range_transitions in policy modules (with a bit more work in the future) with another change in format.
The current range_transition statements are of the form:
range_transition <source types> <target types> <new range>
These statements affect process transitions only. The new supported format is:
range_transition <source types> <target types>:<target classes> <new range>
With this format it is possible to to specify a new range for operations such as file creation. The old style statements are still allowed and they implicitly refer to the "process" security class, thereby retaining the same behavior as before.
The new kernel format now stores the security class on which the rule operates. When dealing with older kernel policy formats, the "process" security class is implicit.
The new module and base formats now store a representation of the rule just (the new addition to the avrule_decl structure) and are expanded at the proper time. The previous implementation expanded the rules at compilation time and could produce an incomplete set of transitions if type attributes were used in the statement. Here is how range_transition statements are handled for the various formats:
for kernel policy version up to 18, there are no range_transition
for kernel policy versions 19 and 20, a list of old-style (no class specified)
range_trans structures are encoded
for kernel policy versions 21 and up, a list of new-style (class specified)
range_trans structures are encoded
for base policy versions up to 5, there are no range_transitions for base policy version 5, a compile-time generated list of old-style (no
class specified) range_trans structures are encoded as they are in kernel formats 19 and 20
for base policy versions 6 and up, an expressive rule stating the intention
of the statement is stored - that will be properly linked and expanded for further usage
for module policy versions up to 6, there are no range_transitions for base policy versions 6 and up, an expressive rule stating the intention
of the statement is stored jut like in base policy version 6 (of course we still need more work to get them in there, but the format is supportive).
include/sepol/policydb/policydb.h +0 -0
@@ -164,9 +164,10 @@
} cat_datum_t;
typedef struct range_trans {
- uint32_t dom; /* current process domain */
- uint32_t type; /* program executable type */
- mls_range_t range; /* new range */
+ uint32_t source_type;
+ uint32_t target_type;
+ uint32_t target_class;
+ mls_range_t target_range; struct range_trans *next; } range_trans_t;
@@ -224,6 +225,14 @@
struct role_allow_rule *next; } role_allow_rule_t;
+typedef struct range_trans_rule {
+ type_set_t stypes;
+ type_set_t ttypes;
+ ebitmap_t tclasses;
+ mls_range_t trange;
+ struct range_trans_rule *next;
+} range_trans_rule_t;
+
/*
* The configuration data includes security contexts for
* initial SIDs, unlabeled file systems, TCP and UDP port numbers,
@@ -321,6 +330,7 @@
avrule_t *avrules; role_trans_rule_t *role_tr_rules; role_allow_rule_t *role_allow_rules;
+ range_trans_rule_t *range_tr_rules;
scope_index_t required; /* symbols needed to activate this block */
scope_index_t declared; /* symbols declared within this block */
@@ -506,6 +516,9 @@
extern void role_allow_rule_init(role_allow_rule_t * x); extern void role_allow_rule_destroy(role_allow_rule_t * x); extern void role_allow_rule_list_destroy(role_allow_rule_t * x); +extern void range_trans_rule_init(range_trans_rule_t *x); +extern void range_trans_rule_destroy(range_trans_rule_t *x); +extern void range_trans_rule_list_destroy(range_trans_rule_t *x); extern void type_datum_init(type_datum_t * x);
extern void type_datum_destroy(type_datum_t * x); extern void user_datum_init(user_datum_t * x);
@@ -555,18 +568,20 @@
#define POLICYDB_VERSION_VALIDATETRANS 19
#define POLICYDB_VERSION_MLS 19
#define POLICYDB_VERSION_AVTAB 20
+#define POLICYDB_VERSION_RANGETRANS 21
/* Range of policy versions we understand*/
#define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE
-#define POLICYDB_VERSION_MAX POLICYDB_VERSION_AVTAB
+#define POLICYDB_VERSION_MAX POLICYDB_VERSION_RANGETRANS
/* Module versions and specific changes*/
#define MOD_POLICYDB_VERSION_BASE 4
#define MOD_POLICYDB_VERSION_VALIDATETRANS 5
#define MOD_POLICYDB_VERSION_MLS 5
+#define MOD_POLICYDB_VERSION_RANGETRANS 6
#define MOD_POLICYDB_VERSION_MIN MOD_POLICYDB_VERSION_BASE -#define MOD_POLICYDB_VERSION_MAX MOD_POLICYDB_VERSION_MLS +#define MOD_POLICYDB_VERSION_MAX MOD_POLICYDB_VERSION_RANGETRANS
#define POLICYDB_CONFIG_MLS 1
include/sepol/policydb/mls_types.h +0 -0
@@ -107,4 +107,22 @@
return -1; }
+static inline void mls_range_init(struct mls_range *r)
+{
+ mls_level_init(&r->level[0]);
+ mls_level_init(&r->level[1]);
+}
+
+static inline void mls_range_destroy(struct mls_range *r)
+{
+ mls_level_destroy(&r->level[0]);
+ mls_level_destroy(&r->level[1]);
+}
+
+static inline int mls_range_eq(struct mls_range *r1, struct mls_range *r2) +{
+ return (mls_level_eq(&r1->level[0], &r2->level[0]) &&
+ mls_level_eq(&r1->level[1], &r2->level[1]));
+}
+
#endif
include/sepol/policydb/context.h +0 -0
@@ -36,8 +36,7 @@
static inline void mls_context_init(context_struct_t * c) {
- mls_level_init(&c->range.level[0]);
- mls_level_init(&c->range.level[1]);
+ mls_range_init(&c->range);
}
static inline int mls_context_cpy(context_struct_t * dst, @@ -62,8 +61,7 @@
if (c == NULL) return;
- mls_level_destroy(&c->range.level[0]);
- mls_level_destroy(&c->range.level[1]);
+ mls_range_destroy(&c->range); mls_context_init(c); }
src/policydb.c +0 -0
@@ -48,6 +48,7 @@
#include <sepol/policydb/conditional.h>
#include <sepol/policydb/avrule_block.h>
#include <sepol/policydb/util.h>
+#include <sepol/policydb/flask.h>
#include "private.h"
#include "debug.h"
@@ -92,6 +93,12 @@
.ocon_num = OCON_NODE6 + 1,
},
{+ .type = POLICY_KERN,
+ .version = POLICYDB_VERSION_RANGETRANS,
+ .sym_num = SYM_NUM,
+ .ocon_num = OCON_NODE6 + 1,
+ },
+ {
.type = POLICY_BASE,
.version = MOD_POLICYDB_VERSION_BASE,
.sym_num = SYM_NUM,
@@ -104,6 +111,12 @@
.ocon_num = OCON_NODE6 + 1,
},
{+ .type = POLICY_BASE,
+ .version = MOD_POLICYDB_VERSION_RANGETRANS,
+ .sym_num = SYM_NUM,
+ .ocon_num = OCON_NODE6 + 1,
+ },
+ {
.type = POLICY_MOD,
.version = MOD_POLICYDB_VERSION_BASE,
.sym_num = SYM_NUM,
@@ -114,7 +127,13 @@
.version = MOD_POLICYDB_VERSION_MLS, .sym_num = SYM_NUM, .ocon_num = 0,
- }
+ },
+ {
+ .type = POLICY_MOD,
+ .version = MOD_POLICYDB_VERSION_RANGETRANS,
+ .sym_num = SYM_NUM,
+ .ocon_num = 0
+ },
};
#if 0
@@ -307,6 +326,32 @@
} }
+void range_trans_rule_init(range_trans_rule_t *x) +{
+ type_set_init(&x->stypes);
+ type_set_init(&x->ttypes);
+ ebitmap_init(&x->tclasses);
+ mls_range_init(&x->trange);
+}
+
+void range_trans_rule_destroy(range_trans_rule_t *x) +{
+ type_set_destroy(&x->stypes);
+ type_set_destroy(&x->ttypes);
+ ebitmap_destroy(&x->tclasses);
+ mls_range_destroy(&x->trange);
+}
+
+void range_trans_rule_list_destroy(range_trans_rule_t *x) +{
+ while (x != NULL) {
+ range_trans_rule_t *next = x->next;
+ range_trans_rule_destroy(x);
+ free(x);
+ x = next;
+ }
+}
+
void avrule_list_destroy(avrule_t * x)
{
avrule_t *next, *cur;@@ -954,15 +999,15 @@
for (rt = p->range_tr; rt; rt = rt->next) {
if (lrt) {
- ebitmap_destroy(&lrt->range.level[0].cat);
- ebitmap_destroy(&lrt->range.level[1].cat);
+ ebitmap_destroy(&lrt->target_range.level[0].cat);
+ ebitmap_destroy(&lrt->target_range.level[1].cat);
free(lrt);
}
lrt = rt;
}
if (lrt) {
- ebitmap_destroy(&lrt->range.level[0].cat);
- ebitmap_destroy(&lrt->range.level[1].cat);
+ ebitmap_destroy(&lrt->target_range.level[0].cat);
+ ebitmap_destroy(&lrt->target_range.level[1].cat);
free(lrt);
}@@ -2260,6 +2305,8 @@
uint32_t *buf, nel; range_trans_t *rt, *lrt; unsigned int i;
+ int new_rangetr = (p->policy_type == POLICY_KERN &&
+ p->policyvers >= POLICYDB_VERSION_RANGETRANS);
buf = next_entry(fp, sizeof(uint32_t)); if (!buf) @@ -2277,9 +2324,16 @@ buf = next_entry(fp, (sizeof(uint32_t) * 2)); if (!buf) return -1;
- rt->dom = le32_to_cpu(buf[0]);
- rt->type = le32_to_cpu(buf[1]);
- if (mls_read_range_helper(&rt->range, fp))
+ rt->source_type = le32_to_cpu(buf[0]);
+ rt->target_type = le32_to_cpu(buf[1]);
+ if (new_rangetr) {
+ buf = next_entry(fp, (sizeof(uint32_t)));
+ if (!buf)
+ return -1;
+ rt->target_class = le32_to_cpu(buf[0]);
+ } else
+ rt->target_class = SECCLASS_PROCESS;
+ if (mls_read_range_helper(&rt->target_range, fp))
return -1; lrt = rt; } @@ -2393,6 +2447,46 @@ return 0; }
+static int range_trans_rule_read(range_trans_rule_t **r, struct policy_file *fp) +{
+ uint32_t *buf, nel;
+ unsigned int i;
+ range_trans_rule_t *rt, *lrt = NULL;
+
+ buf = next_entry(fp, sizeof(uint32_t));
+ if (!buf)
+ return -1;
+ nel = le32_to_cpu(buf[0]);
+ for (i = 0; i < nel; i++) {
+ rt = malloc(sizeof(range_trans_rule_t));
+ if (!rt) {
+ return -1;
+ }
+ range_trans_rule_init(rt);
+
+ if (lrt)
+ lrt->next = rt;
+ else
+ *r = rt;
+
+ if (type_set_read(&rt->stypes, fp))
+ return -1;
+
+ if (type_set_read(&rt->ttypes, fp))
+ return -1;
+
+ if (ebitmap_read(&rt->tclasses, fp))
+ return -1;
+
+ if (mls_read_range_helper(&rt->trange, fp))
+ return -1;
+
+ lrt = rt;
+ }
+
+ return 0;
+}
+
static int scope_index_read(scope_index_t * scope_index,
unsigned int num_scope_syms, struct policy_file *fp)
{
@@ -2440,6 +2534,10 @@
role_allow_rule_read(&decl->role_allow_rules, fp) == -1) {
return -1;
}+ if (p->policyvers >= MOD_POLICYDB_VERSION_RANGETRANS &&
+ range_trans_rule_read(&decl->range_tr_rules, fp) == -1) {
+ return -1;
+ }
if (scope_index_read(&decl->required, num_scope_syms, fp) == -1 ||
scope_index_read(&decl->declared, num_scope_syms, fp) == -1) {
return -1;
@@ -2835,7 +2933,8 @@
if ((p->policy_type == POLICY_KERN
&& p->policyvers >= POLICYDB_VERSION_MLS)
|| (p->policy_type == POLICY_BASE
- && p->policyvers >= MOD_POLICYDB_VERSION_MLS)) {
+ && p->policyvers >= MOD_POLICYDB_VERSION_MLS
+ && p->policyvers < MOD_POLICYDB_VERSION_RANGETRANS)) {
if (range_read(p, fp)) {
goto bad;
}src/mls.c +0 -0
@@ -607,23 +607,20 @@
sepol_security_class_t tclass,
uint32_t specified, context_struct_t * newcontext)
{
+ range_trans_t *rtr;
if (!policydb->mls)
return 0;
switch (specified) {
case AVTAB_TRANSITION:- if (tclass == SECCLASS_PROCESS) {
- range_trans_t *rangetr;
-
- /* Look for a range transition rule. */
- for (rangetr = policydb->range_tr; rangetr;
- rangetr = rangetr->next) {
- if (rangetr->dom == scontext->type &&
- rangetr->type == tcontext->type) {
- /* Set the range from the rule */
- return mls_range_set(newcontext,
- &rangetr->range);
- }
+ /* Look for a range transition rule. */
+ for (rtr = policydb->range_tr; rtr; rtr = rtr->next) {
+ if (rtr->source_type == scontext->type &&
+ rtr->target_type == tcontext->type &&
+ rtr->target_class == tclass) {
+ /* Set the range from the rule */
+ return mls_range_set(newcontext,
+ &rtr->target_range); } } /* Fallthrough */
src/avrule_block.c +0 -0
@@ -99,6 +99,7 @@
avrule_list_destroy(x->avrules); role_trans_rule_list_destroy(x->role_tr_rules); role_allow_rule_list_destroy(x->role_allow_rules); + range_trans_rule_list_destroy(x->range_tr_rules); scope_index_destroy(&x->required); scope_index_destroy(&x->declared); symtabs_destroy(x->symtab);
src/expand.c +0 -0
@@ -958,6 +958,112 @@
return 0; }
+static int exp_rangetr_helper(uint32_t stype, uint32_t ttype, uint32_t tclass,
+ mls_range_t *trange, expand_state_t *state)
+{
+ range_trans_t *rt, *check_rt = state->out->range_tr;
+
+ /* check for duplicates/conflicts */
+ while (check_rt) {
+ if ((check_rt->source_type == stype) &&
+ (check_rt->target_type == ttype) &&
+ (check_rt->target_class == tclass)) {
+ if (mls_range_eq(&check_rt->target_range, trange)) {
+ /* duplicate */
+ break;
+ } else {
+ /* conflict */
+ ERR(state->handle,
+ "Conflicting range trans rule %s %s : %s", + state->out->p_type_val_to_name[stype - 1], + state->out->p_type_val_to_name[ttype - 1], + state->out->p_class_val_to_name[tclass]);
+ return -1;
+ }
+ }
+ check_rt = check_rt->next;
+ }
+ if (check_rt) /* this is a dup - skip */
+ return 0;
+
+ rt = (range_trans_t *)calloc(1, sizeof(range_trans_t));
+ if (!rt) {
+ ERR(state->handle, "Out of memory!");
+ return -1;
+ }
+
+ rt->next = state->out->range_tr;
+ state->out->range_tr = rt;
+
+ rt->source_type = stype;
+ rt->target_type = ttype;
+ rt->target_class = tclass;
+ if (mls_range_cpy(&rt->target_range, trange)) {
+ ERR(state->handle, "Out of memory!");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int expand_range_trans(expand_state_t *state, range_trans_rule_t *rules) +{
+ unsigned int i, j, k;
+ range_trans_rule_t *rule;
+
+ ebitmap_t stypes, ttypes;
+ ebitmap_node_t *snode, *tnode, *cnode;
+
+ for (rule = rules; rule; rule = rule->next) {
+ ebitmap_init(&stypes);
+ ebitmap_init(&ttypes);
+
+ /* expand the type sets */
+ if (expand_convert_type_set(state->out, state->typemap,
+ &rule->stypes, &stypes, 1)) {
+ ERR(state->handle, "Out of memory!");
+ return -1;
+ }
+ if (expand_convert_type_set(state->out, state->typemap,
+ &rule->ttypes, &ttypes, 1)) {
+ ebitmap_destroy(&stypes);
+ ERR(state->handle, "Out of memory!");
+ return -1;
+ }
+
+ /* loop on source type */
+ ebitmap_for_each_bit(&stypes, snode, i) {
+ if (!ebitmap_node_get_bit(snode, i))
+ continue;
+ /* loop on target type */
+ ebitmap_for_each_bit(&ttypes, tnode, j) {
+ if (!ebitmap_node_get_bit(tnode, j))
+ continue;
+ /* loop on target class */
+ ebitmap_for_each_bit(&rule->tclasses, cnode, k) {
+ if (!ebitmap_node_get_bit(cnode, k))
+ continue;
+
+ if (exp_rangetr_helper(i + 1,
+ j + 1,
+ k,
+ &rule->trange,
+ state)){+ ebitmap_destroy(&stypes);
+ ebitmap_destroy(&ttypes);
+ return -1;
+ }
+ }
+ }
+ }
+
+ ebitmap_destroy(&stypes);
+ ebitmap_destroy(&ttypes);
+ }
+
+ return 0;
+}
+
/* Search for an AV tab node within a hash table with the given key.
* If the node does not exist, create it and return it; otherwise
* return the pre-existing one.
@@ -1500,14 +1606,17 @@
goto out_of_mem; } memset(new_range, 0, sizeof(*new_range));
- new_range->dom = state->typemap[range->dom - 1];
- new_range->type = state->typemap[range->type - 1];
- if (mls_level_clone
- (&new_range->range.level[0], &range->range.level[0]) == -1
- || mls_level_clone(&new_range->range.level[1],
- &range->range.level[1])) {
+ new_range->source_type = state->typemap[range->source_type - 1];
+ new_range->target_type = state->typemap[range->target_type - 1];
+ new_range->target_class = range->target_class;
+ if (mls_level_clone(&new_range->target_range.level[0],
+ &range->target_range.level[0])) {
goto out_of_mem;
}+ if (mls_level_clone(&new_range->target_range.level[1],
+ &range->target_range.level[1])) {
+ goto out_of_mem;
+ }
new_range->next = NULL;
if (last_new_range == NULL) {
state->out->range_tr = last_new_range = new_range;
@@ -1522,8 +1631,8 @@
out_of_mem:
ERR(state->handle, "Out of memory!");
if (new_range) {
- ebitmap_destroy(&new_range->range.level[0].cat);
- ebitmap_destroy(&new_range->range.level[1].cat);
+ ebitmap_destroy(&new_range->target_range.level[0].cat);
+ ebitmap_destroy(&new_range->target_range.level[1].cat);
free(new_range);
}
return -1;
@@ -2030,6 +2139,11 @@
goto cleanup;
}+ /* expand the range transition rules */
+ if ((base->policyvers >= MOD_POLICYDB_VERSION_RANGETRANS) &&
+ expand_range_trans(&state, decl->range_tr_rules))
+ goto cleanup;
+
/* copy rules */
cur_avrule = decl->avrules;
while (cur_avrule != NULL) {
@@ -2072,7 +2186,8 @@
if (genfs_copy(&state))
goto cleanup;- if (range_trans_clone(&state) == -1) {
+ if ((base->policyvers < MOD_POLICYDB_VERSION_RANGETRANS) &&
+ range_trans_clone(&state) == -1) {
goto cleanup;
}src/write.c +0 -0
@@ -39,6 +39,7 @@
#include <sepol/policydb/policydb.h>
#include <sepol/policydb/conditional.h>
#include <sepol/policydb/expand.h>
+#include <sepol/policydb/flask.h>
#include "debug.h"
#include "private.h"
@@ -1124,21 +1125,44 @@
{
size_t nel, items;
struct range_trans *rt;- uint32_t buf[32];
+ uint32_t buf[2];
+ int new_rangetr = (p->policy_type == POLICY_KERN &&
+ p->policyvers >= POLICYDB_VERSION_RANGETRANS);
+ int warning_issued = 0;
+
nel = 0;
- for (rt = p->range_tr; rt; rt = rt->next)
- nel++;
+ for (rt = p->range_tr; rt; rt = rt->next) {
+ /* all range_transitions are written for the new format, only
+ process related range_transitions are written for the old
+ format, so count accordingly */
+ if (new_rangetr || rt->target_class == SECCLASS_PROCESS)
+ nel++;
+ }
buf[0] = cpu_to_le32(nel);
items = put_entry(buf, sizeof(uint32_t), 1, fp);
if (items != 1)
return -1;
for (rt = p->range_tr; rt; rt = rt->next) {- buf[0] = cpu_to_le32(rt->dom);
- buf[1] = cpu_to_le32(rt->type);
+ if (!new_rangetr && rt->target_class != SECCLASS_PROCESS) {
+ if (!warning_issued)
+ WARN(fp->handle, "Discarding range_transition "
+ "rules for security classes other than "
+ "\"process\"");
+ warning_issued = 1;
+ continue;
+ }
+ buf[0] = cpu_to_le32(rt->source_type);
+ buf[1] = cpu_to_le32(rt->target_type); items = put_entry(buf, sizeof(uint32_t), 2, fp); if (items != 2) return -1;
- if (mls_write_range_helper(&rt->range, fp))
+ if (new_rangetr) {
+ buf[0] = cpu_to_le32(rt->target_class);
+ items = put_entry(buf, sizeof(uint32_t), 1, fp);
+ if (items != 1)
+ return -1;
+ }
+ if (mls_write_range_helper(&rt->target_range, fp))
return -1; } return 0; @@ -1264,6 +1288,32 @@ return 0; }
+static int range_trans_rule_write(range_trans_rule_t *t, struct policy_file *fp) +{
+ int nel = 0;
+ size_t items;
+ uint32_t buf[1];
+ range_trans_rule_t *rt;
+
+ for (rt = t; rt; rt = rt->next)
+ nel++;
+ buf[0] = cpu_to_le32(nel);
+ items = put_entry(buf, sizeof(uint32_t), 1, fp);
+ if (items != 1)
+ return -1;
+ for (rt = t; rt; rt = rt->next) {
+ if (type_set_write(&rt->stypes, fp))
+ return -1;
+ if (type_set_write(&rt->ttypes, fp))
+ return -1;
+ if (ebitmap_write(&rt->tclasses, fp))
+ return -1;
+ if (mls_write_range_helper(&rt->trange, fp))
+ return -1;
+ }
+ return 0;
+}
+
static int scope_index_write(scope_index_t * scope_index,
unsigned int num_scope_syms,
struct policy_file *fp)
@@ -1304,6 +1354,10 @@
role_allow_rule_write(decl->role_allow_rules, fp) == -1) {
return -1;
}+ if (p->policyvers >= MOD_POLICYDB_VERSION_RANGETRANS &&
+ range_trans_rule_write(decl->range_tr_rules, fp) == -1) {
+ return -1;
+ }
if (scope_index_write(&decl->required, num_scope_syms, fp) == -1 ||
scope_index_write(&decl->declared, num_scope_syms, fp) == -1) {
return -1;
@@ -1525,7 +1579,8 @@
if ((p->policyvers >= POLICYDB_VERSION_MLS
&& p->policy_type == POLICY_KERN)
|| (p->policyvers >= MOD_POLICYDB_VERSION_MLS
- && p->policy_type == POLICY_BASE)) {
+ && p->policyvers < MOD_POLICYDB_VERSION_MLS
+ && p->policy_type == POLICY_BASE) ) {
if (range_write(p, fp)) {
return -1;
}module_compiler.c +0 -0
@@ -1097,6 +1097,18 @@
decl->role_allow_rules = role_allow_rules; }
+/* this doesn't actually append, but really prepends it */ +void append_range_trans(range_trans_rule_t * range_tr_rules) +{
+ avrule_decl_t *decl = stack_top->decl;
+
+ /* range transitions are not allowed within conditionals */
+ assert(stack_top->type == 1);
+
+ range_tr_rules->next = decl->range_tr_rules;
+ decl->range_tr_rules = range_tr_rules;
+}
+
int begin_optional(int pass)
{
avrule_block_t *block = NULL;policy_parse.y +0 -0
@@ -101,7 +101,7 @@
static role_datum_t *merge_roles_dom(role_datum_t *r1,role_datum_t *r2); static role_datum_t *define_role_dom(role_datum_t *r); static int define_role_trans(void);
-static int define_range_trans(void);
+static int define_range_trans(int class_specified);
static int define_role_allow(void);
static int define_constraint(constraint_expr_t *expr); static int define_validatetrans(constraint_expr_t *expr);
@@ -436,7 +436,9 @@
{if (define_compute_type(AVRULE_CHANGE)) return -1;}
;range_trans_def : RANGE_TRANSITION names names mls_range_def ';'
- { if (define_range_trans()) return -1; }
+ { if (define_range_trans(0)) return -1; }
+ | RANGE_TRANSITION names names ':' names mls_range_def ';'
+ { if (define_range_trans(1)) return -1; }
; te_avtab_def : allow_def | auditallow_def @@ -4472,15 +4474,12 @@ return define_genfs_context_helper(queue_remove(id_queue), has_type); }
-static int define_range_trans(void) +static int define_range_trans(int class_specified)
{
char *id;
level_datum_t *levdatum = 0;- mls_range_t range;
- type_set_t doms, types;
- ebitmap_node_t *snode, *tnode;
- range_trans_t *rt = 0;
- unsigned int i, j;
+ class_datum_t *cladatum;
+ range_trans_rule_t *rule;
int l, add = 1;
if (!mlspol) {
@@ -4493,6 +4492,9 @@
free(id);
while ((id = queue_remove(id_queue)))
free(id);
+ if (class_specified)
+ while ((id = queue_remove(id_queue)))
+ free(id);
id = queue_remove(id_queue);
free(id);
for (l = 0; l < 2; l++) {
@@ -4507,43 +4509,78 @@
return 0;
}- type_set_init(&doms);
- type_set_init(&types);
+ rule = malloc(sizeof(struct range_trans_rule));
+ if (!rule) {
+ yyerror("out of memory");
+ return -1;
+ }
+ range_trans_rule_init(rule);
while ((id = queue_remove(id_queue))) {
- if (set_types(&doms, id, &add, 0))
- return -1;
+ if (set_types(&rule->stypes, id, &add, 0))
+ goto out;
}
add = 1;
while ((id = queue_remove(id_queue))) {
- if (set_types(&types, id, &add, 0))
- return -1;
+ if (set_types(&rule->ttypes, id, &add, 0))
+ goto out;
}+ if (class_specified) {
+ while ((id = queue_remove(id_queue))) {
+ if (!is_id_in_scope(SYM_CLASSES, id)) {
+ yyerror2("class %s is not within scope", id);
+ free(id);
+ goto out;
+ }
+ cladatum = hashtab_search(policydbp->p_classes.table,
+ id);
+ if (!cladatum) {
+ sprintf(errormsg, "unknown class %s", id);
+ yyerror(errormsg);
+ goto out;
+ }
+
+ ebitmap_set_bit(&rule->tclasses, cladatum->s.value,
+ TRUE);
+ free(id);
+ }
+ } else {
+ cladatum = hashtab_search(policydbp->p_classes.table,
+ "process");
+ if (!cladatum) {
+ sprintf(errormsg, "could not find process class for "
+ "legacy range_transition statement\n");
+ yyerror(errormsg);
+ goto out;
+ }
+
+ ebitmap_set_bit(&rule->tclasses, cladatum->s.value, TRUE);
+ }
+
id = (char *)queue_remove(id_queue);
if (!id) {
yyerror("no range in range_transition definition?");
- return -1;
+ goto out;
}
for (l = 0; l < 2; l++) {
levdatum = hashtab_search(policydbp->p_levels.table, id);
if (!levdatum) {
sprintf(errormsg,
- "unknown level %s used in range_transition definition",
- id);
+ "unknown level %s used in range_transition "
+ "definition", id);
yyerror(errormsg);
free(id);
- return -1;
+ goto out;
}
free(id);- range.level[l].sens = levdatum->level->sens;
+ rule->trange.level[l].sens = levdatum->level->sens;
- ebitmap_init(&range.level[l].cat);
-
while ((id = queue_remove(id_queue))) {
- if (parse_categories(id, levdatum, &range.level[l].cat)) {
+ if (parse_categories(id, levdatum,
+ &rule->trange.level[l].cat)) {
free(id);
- return -1;
+ goto out;
}
free(id);
}
@@ -4553,73 +4590,24 @@
break;
}
if (l == 0) {
- range.level[1].sens = range.level[0].sens;
- if (ebitmap_cpy(&range.level[1].cat, &range.level[0].cat)) {
+ if (mls_level_cpy(&rule->trange.level[1],
+ &rule->trange.level[0])) {
yyerror("out of memory");
- return -1;
+ goto out;
}
}-
- if (!mls_level_dom(&range.level[1], &range.level[0])) {
- yyerror
- ("range_transition high level does not dominate low level");
- return -1;
+ if (!mls_level_dom(&rule->trange.level[1], &rule->trange.level[0])) {
+ yyerror("range_transition high level does not dominate "
+ "low level");
+ goto out; }
- /* FIXME: this expands type_sets at compile time which is inappropriate, the type_sets
- * should be stored which is a format change */
- ebitmap_for_each_bit(&doms.types, snode, i) {
- if (!ebitmap_node_get_bit(snode, i))
- continue;
- ebitmap_for_each_bit(&types.types, tnode, j) {
- if (!ebitmap_node_get_bit(tnode, j))
- continue;
-
- for (rt = policydbp->range_tr; rt; rt = rt->next) {
- if (rt->dom == (i + 1) && rt->type == (j + 1)) {
- sprintf(errormsg,
- "duplicate range_transition defined for (%s,%s)",
- policydbp->
- p_type_val_to_name[i],
- policydbp->
- p_type_val_to_name[j]);
- yyerror(errormsg);
- return -1;
- }
- }
-
- rt = malloc(sizeof(range_trans_t));
- if (!rt) {
- yyerror("out of memory");
- return -1;
- }
- memset(rt, 0, sizeof(range_trans_t));
- rt->dom = i + 1;
- rt->type = j + 1;
- rt->range.level[0].sens = range.level[0].sens;
- if (ebitmap_cpy(&rt->range.level[0].cat,
- &range.level[0].cat)) {
- yyerror("out of memory");
- free(rt);
- return -1;
- }
- rt->range.level[1].sens = range.level[1].sens;
- if (ebitmap_cpy(&rt->range.level[1].cat,
- &range.level[1].cat)) {
- yyerror("out of memory");
- free(rt);
- return -1;
- }
- rt->next = policydbp->range_tr;
- policydbp->range_tr = rt;
- }
- }
-
- type_set_destroy(&doms);
- type_set_destroy(&types);
- ebitmap_destroy(&range.level[0].cat);
- ebitmap_destroy(&range.level[1].cat);
+ append_range_trans(rule); return 0;
+
+out:
+ range_trans_rule_destroy(rule);
+ return -1;
}
module_compiler.h +0 -0
@@ -77,6 +77,7 @@
void append_avrule(avrule_t * avrule);
void append_role_trans(role_trans_rule_t * role_tr_rules); void append_role_allow(role_allow_rule_t * role_allow_rules); +void append_range_trans(range_trans_rule_t * range_tr_rules);
/* Create a new optional block and add it to the global policy.
* During the second pass resolve the block's requirements. Return 0
Signature · 6 lines
Darrel -- This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
Quoted 2 lines
From: Darrel Goeddel [mailto:[email protected]]
Sorry it took so long to reply to this.
Quoted 3 lines
for module policy versions up to 6, there are no
range_transitionsfor base policy versions 6 and up, an
This is only per the grammar right? You are writing range_trans_rule_t's in every avrule block so version 6 does support them, just not the grammar yet.
Review line 334
Quoted 11 lines
#if 0
(quoted diff) +6
-0@@ -307,6 +326,32 @@ } } +void range_trans_rule_init(range_trans_rule_t *x) { + type_set_init(&x->stypes); + type_set_init(&x->ttypes); + ebitmap_init(&x->tclasses); + mls_range_init(&x->trange); +}
x->next = NULL?
That's all I have, looks good sans the semantic range representation.
--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
Quoted 29 lines · Joshua Brindle
Quoted 2 lines
From: Darrel Goeddel [mailto:[email protected]]
Sorry it took so long to reply to this.
Quoted 3 lines
for module policy versions up to 6, there are no
range_transitionsfor base policy versions 6 and up, anThis is only per the grammar right? You are writing range_trans_rule_t's in every avrule block so version 6 does support them, just not the grammar yet.
Review line 334
Quoted 11 lines
#if 0
(quoted diff) +6
-0@@ -307,6 +326,32 @@ } } +void range_trans_rule_init(range_trans_rule_t *x) { + type_set_init(&x->stypes); + type_set_init(&x->ttypes); + ebitmap_init(&x->tclasses); + mls_range_init(&x->trange); +}
x->next= NULL?
Quoted 2 lines
That's all I have, looks good sans the semantic range representation.
I vote we punt on this - it is only needed for modules and this work won't get us module support without another format change anyway (to support mls requirements). If this is going to make fc6 it needs to be done soon and I would rather be close and in fc6 than perfect and not.
Karl
Quoted 5 lines
--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
Quoted 26 lines · Karl MacMillan
Quoted 25 lines · Joshua Brindle
Quoted 2 lines
From: Darrel Goeddel [mailto:[email protected]]
Sorry it took so long to reply to this.
Quoted 2 lines
for module policy versions up to 6, there are no
range_transitionsfor base policy versions 6 and up, anThis is only per the grammar right? You are writing range_trans_rule_t's in every avrule block so version 6 does support them, just not the grammar yet.
Review line 334
Quoted 11 lines
#if 0
(quoted diff) +6
-0@@ -307,6 +326,32 @@ } } +void range_trans_rule_init(range_trans_rule_t *x) { + type_set_init(&x->stypes); + type_set_init(&x->ttypes); + ebitmap_init(&x->tclasses); + mls_range_init(&x->trange); +}
x->next= NULL?
Quoted 8 lines
Quoted 2 lines
That's all I have, looks good sans the semantic range representation.
I vote we punt on this - it is only needed for modules and this work won't get us module support without another format change anyway (to support mls requirements). If this is going to make fc6 it needs to be done soon and I would rather be close and in fc6 than perfect and not.
I think we are close on the semantic representation, punting on it now means 2 module format changes, I'd much prefer something that is usable now and won't need an explicit format change later, even if it isn't perfect.
--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
Quoted 33 lines · Joshua Brindle
Quoted 31 lines · Karl MacMillan
Quoted 27 lines · Joshua Brindle
Quoted 1 line
From: Darrel Goeddel [mailto:[email protected]]
Sorry it took so long to reply to this.
Quoted 2 lines
for module policy versions up to 6, there are no
range_transitions
for base policy versions 6 and up, anThis is only per the grammar right? You are writing range_trans_rule_t's in every avrule block so version 6 does support them, just not the grammar yet.
Review line 334
Quoted 11 lines
#if 0
(quoted diff) +6
-0@@ -307,6 +326,32 @@ } } +void range_trans_rule_init(range_trans_rule_t *x) { + type_set_init(&x->stypes); + type_set_init(&x->ttypes); + ebitmap_init(&x->tclasses); + mls_range_init(&x->trange); +}
x->next= NULL?That's all I have, looks good sans the semantic range representation.
Quoted 7 lines
Quoted 5 lines
I vote we punt on this - it is only needed for modules and this work won't get us module support without another format change anyway (to support mls requirements). If this is going to make fc6 it needs to be done soon and I would rather be close and in fc6 than perfect and not.
I think we are close on the semantic representation, punting on it now means 2 module format changes, I'd much prefer something that is usable now and won't need an explicit format change later, even if it isn't perfect.
Getting modules to work sure would be nice... I originally wanted to get the format good enough to support this so we could get module support with only logic changes later on. It was my understanding that we would not have to change the format for the mls requirements because we already have the symbol tables in there. What do people think are the front runners for changes on the following 2 issues:
1) how to represent the mls component in the range_trans_rule_t (as well as the range and level in user_datum_t).
I'm still leaning toward the string method. I haven't had the opportunity to try this, but my assumption is that it would work nicely. This method would only need further work for checking requirements (symbols only). The linked struct method would require mappings as well. I'm not sure how much that involves, but I assume it can't be that bad because everything else does it. I'd love to see prototypes of both if anyone has a few extra cycles ;)
2) how to handle mls requirements.
My preference at this point would be to require each component separately.
(e.g. s1:c0,c4.c10,c30 would have:
Require {
sens s1;
cats c0, c4, c10, c30;
}
That should work just fine for the current format. Making a requirement
on the whole range seems to require too many extra changes for little
benefit IMO.That said, punting would not be a huge problem if we can get updates into FC RHEL when the userspace work for modular support is complete. This is desired either way, but I was concerned that a format change may may people more wary about the update, even though it would be completely backwards compatible. The only real drawback to not getting the format tweaked now is that it will introduce more "if (version < MOD_POLICYDB...)" into the code. Unfortunately, resources and time are limited as far as I can see...
Signature · 6 lines
Darrel -- This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
Quoted 1 line · Darrel Goeddel
Joshua Brindle wrote:
<snip>
Quoted 16 lines
Quoted 5 lines
I think we are close on the semantic representation, punting on it now means 2 module format changes, I'd much prefer something that is usable now and won't need an explicit format change later, even if it isn't perfect.
Getting modules to work sure would be nice... I originally wanted to get the format good enough to support this so we could get module support with only logic changes later on. It was my understanding that we would not have to change the format for the mls requirements because we already have the symbol tables in there. What do people think are the front runners for changes on the following 2 issues:
1) how to represent the mls component in the
range_trans_rule_t(as well as the range and level inuser_datum_t).
Quoted 8 lines
I'm still leaning toward the string method. I haven't had the opportunity to try this, but my assumption is that it would work nicely. This method would only need further work for checking requirements (symbols only). The linked struct method would require mappings as well. I'm not sure how much that involves, but I assume it can't be that bad because everything else does it. I'd love to see prototypes of both if anyone has a few extra cycles ;)
I very much prefer the structures. Using the string requires all users of libsepol to parse the string - currently we push all parsing to checkpolicy and sepol includes a structured, semantic representation of the data.
Quoted 12 lines
2) how to handle mls requirements.
My preference at this point would be to require each component separately. (e.g. s1:c0,c4.c10,c30 would have: Require { sens s1; cats c0, c4, c10, c30; } That should work just fine for the current format. Making a requirement on the whole range seems to require too many extra changes for little benefit IMO.
I agree.
Quoted 8 lines
That said, punting would not be a huge problem if we can get updates into FC RHEL when the userspace work for modular support is complete. This is desired either way, but I was concerned that a format change may may people more wary about the update, even though it would be completely backwards compatible. The only real drawback to not getting the format tweaked now is that it will introduce more "if (version <
MOD_POLICYDB...)" into the code. Unfortunately, resources and time are limited as far as I can see...
It would definitely be better to get the support in now, but I think that we are in real danger of missing already.
Karl
--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
RE: [PATCH 2/2 take 2] userland support for new range_transitionstatements
Quoted 5 lines
From: Karl MacMillan [mailto:[email protected]]
Quoted 1 line · Darrel Goeddel
Joshua Brindle wrote:
Quoted 8 lines
<snip>
I very much prefer the structures. Using the string requires all users of libsepol to parse the string - currently we push all parsing to checkpolicy and sepol includes a structured, semantic representation of the data.
At this point I prefer the structures to but I disagree with your justification, policydb is owned by libsepol, no user of libsepol should be parsing the string (which would only exist in the linked copy, other out-of-tree users like apol only operate on the expanded copy).
Quoted 10 lines
Quoted 3 lines
2) how to handle mls requirements.
My preference at this point would be to require each
component separately.
Quoted 6 lines
(e.g. s1:c0,c4.c10,c30 would have: Require { sens s1; cats c0, c4, c10, c30; } That should work just fine for the current format.
Quoted 8 lines
Making a requirement
Quoted 1 line
on the whole range seems to require too many extra
changes for little
Quoted 2 lines
benefit IMO.
I agree.
That's fine, and easier to accomplish since there are already sens and cats tables in every avrule_decl block, the logic to require them can be easily copied from other symbols.
Quoted 10 lines
Quoted 1 line
That said, punting would not be a huge problem if we can
get updates
Quoted 1 line
into FC RHEL when the userspace work for modular support is
complete.
Quoted 1 line
This is desired either way, but I was concerned that a
format change
Quoted 4 lines
may may people more wary about the update, even though it would be completely backwards compatible. The only real drawback to not getting the format tweaked now is that it will introduce more "if (version <
MOD_POLICYDB...)" into the code. Unfortunately,
Quoted 6 lines
resources and time are limited as far as I can see...
Quoted 1 line
It would definitely be better to get the support in now, but I think that we are in real danger of missing already.
Refpolicy needs this support badly, right now all range_transitions are moved into base breaking encapsulation since modules don't support them.
I vote for doing the structured semantic representation, getting everything merged so that it makes it in for sure and then working on the module changes (which should be very small but something unexpected might pop out). That way the new range_trans are available and hopefully the module support gets in after that.
One other thing, since there is now a unit test suite in libsepol I'd like to see some unit tests for the new structures, I know there is a time crunch right now but I think they should be written as soon as they can be.
--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
Quoted 7 lines · Joshua Brindle
Quoted 2 lines
From: Darrel Goeddel [mailto:[email protected]]
Sorry it took so long to reply to this.
Quoted 6 lines
Quoted 1 line
for module policy versions up to 6, there are no
range_transitionsfor base policy versions 6 and up, anThis is only per the grammar right? You are writing range_trans_rule_t's in every avrule block so version 6 does support them, just not the grammar yet.
Yes, the module format version 6 does include range_trans_t's, it just writes 0 rules because there is no way to specify them.
Quoted 5 lines
Quoted 5 lines
#if 0
(quoted diff) +0
-0@@ -307,6 +326,32 @@ } }
Quoted 9 lines
Review line 334
Quoted 6 lines
(quoted diff) +6
-0+void range_trans_rule_init(range_trans_rule_t *x) { + type_set_init(&x->stypes); + type_set_init(&x->ttypes); + ebitmap_init(&x->tclasses); + mls_range_init(&x->trange); +}
x->next= NULL?
D'oh. Will initialize...
Signature · 6 lines
Darrel -- This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.