* [PATCH 2/2] userland support for new range_transition statements
@ 2006-07-28 15:13 Darrel Goeddel
2006-07-31 16:40 ` Stephen Smalley
` (3 more replies)
0 siblings, 4 replies; 25+ messages in thread
From: Darrel Goeddel @ 2006-07-28 15:13 UTC (permalink / raw)
To: 'SELinux List'; +Cc: Stephen Smalley, Eric Paris, Joshua Brindle
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(-)
Index: libsepol/include/sepol/policydb/policydb.h
===================================================================
--- libsepol/include/sepol/policydb/policydb.h (revision 38)
+++ libsepol/include/sepol/policydb/policydb.h (working copy)
@@ -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
Index: libsepol/include/sepol/policydb/mls_types.h
===================================================================
--- libsepol/include/sepol/policydb/mls_types.h (revision 38)
+++ libsepol/include/sepol/policydb/mls_types.h (working copy)
@@ -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
Index: libsepol/src/policydb.c
===================================================================
--- libsepol/src/policydb.c (revision 38)
+++ libsepol/src/policydb.c (working copy)
@@ -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;
}
Index: libsepol/src/mls.c
===================================================================
--- libsepol/src/mls.c (revision 38)
+++ libsepol/src/mls.c (working copy)
@@ -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 */
Index: libsepol/src/avrule_block.c
===================================================================
--- libsepol/src/avrule_block.c (revision 38)
+++ libsepol/src/avrule_block.c (working copy)
@@ -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);
Index: libsepol/src/expand.c
===================================================================
--- libsepol/src/expand.c (revision 38)
+++ libsepol/src/expand.c (working copy)
@@ -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;
}
Index: libsepol/src/write.c
===================================================================
--- libsepol/src/write.c (revision 38)
+++ libsepol/src/write.c (working copy)
@@ -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;
}
Index: checkpolicy/module_compiler.c
===================================================================
--- checkpolicy/module_compiler.c (revision 38)
+++ checkpolicy/module_compiler.c (working copy)
@@ -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;
Index: checkpolicy/policy_parse.y
===================================================================
--- checkpolicy/policy_parse.y (revision 38)
+++ checkpolicy/policy_parse.y (working copy)
@@ -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;
}
Index: checkpolicy/module_compiler.h
===================================================================
--- checkpolicy/module_compiler.h (revision 38)
+++ checkpolicy/module_compiler.h (working copy)
@@ -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
--
Darrel
--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 2/2] userland support for new range_transition statements
2006-07-28 15:13 [PATCH 2/2] userland support for new range_transition statements Darrel Goeddel
@ 2006-07-31 16:40 ` Stephen Smalley
2006-07-31 18:25 ` Darrel Goeddel
2006-07-31 18:29 ` Karl MacMillan
` (2 subsequent siblings)
3 siblings, 1 reply; 25+ messages in thread
From: Stephen Smalley @ 2006-07-31 16:40 UTC (permalink / raw)
To: Darrel Goeddel; +Cc: 'SELinux List', Eric Paris, Joshua Brindle
On Fri, 2006-07-28 at 10:13 -0500, Darrel Goeddel wrote:
> Index: libsepol/src/policydb.c
> ===================================================================
> --- libsepol/src/policydb.c (revision 38)
> +++ libsepol/src/policydb.c (working copy)
<snip>
> +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;
Leaks rt. I'd suggest linking rt into the list earlier as we do
elsewhere, so that it can be freed upon policydb_destroy.
> + 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.
> Index: libsepol/src/expand.c
> ===================================================================
> --- libsepol/src/expand.c (revision 38)
> +++ libsepol/src/expand.c (working copy)
> @@ -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!");
Leaks stypes. Need an error exit path that does clean up.
> + 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;
Leaks stypes and ttypes.
> + 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.
--
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 majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 2/2] userland support for new range_transition statements
2006-07-31 16:40 ` Stephen Smalley
@ 2006-07-31 18:25 ` Darrel Goeddel
0 siblings, 0 replies; 25+ messages in thread
From: Darrel Goeddel @ 2006-07-31 18:25 UTC (permalink / raw)
To: Stephen Smalley; +Cc: 'SELinux List', Eric Paris, Joshua Brindle
Stephen Smalley wrote:
>>+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;
>
>
> 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 >
>>+ 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.
--
Darrel
--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 2/2] userland support for new range_transition statements
2006-07-28 15:13 [PATCH 2/2] userland support for new range_transition statements Darrel Goeddel
2006-07-31 16:40 ` Stephen Smalley
@ 2006-07-31 18:29 ` Karl MacMillan
2006-07-31 18:54 ` Darrel Goeddel
2006-08-01 13:14 ` Joshua Brindle
2006-08-04 17:10 ` [PATCH 2/2 take 2] " Darrel Goeddel
3 siblings, 1 reply; 25+ messages in thread
From: Karl MacMillan @ 2006-07-31 18:29 UTC (permalink / raw)
To: Darrel Goeddel
Cc: 'SELinux List', Stephen Smalley, Eric Paris,
Joshua Brindle
On Fri, 2006-07-28 at 10:13 -0500, Darrel Goeddel wrote:
<snip>
> +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>
> +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;
> +}
> +
Splitting this into some helper functions would make it more readable.
<snip>
> Index: libsepol/src/write.c
> ===================================================================
> --- libsepol/src/write.c (revision 38)
> +++ libsepol/src/write.c (working copy)
> @@ -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++;
> + }
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 majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 2/2] userland support for new range_transition statements
2006-07-31 18:29 ` Karl MacMillan
@ 2006-07-31 18:54 ` Darrel Goeddel
2006-07-31 20:52 ` Stephen Smalley
0 siblings, 1 reply; 25+ messages in thread
From: Darrel Goeddel @ 2006-07-31 18:54 UTC (permalink / raw)
To: Karl MacMillan
Cc: 'SELinux List', Stephen Smalley, Eric Paris,
Joshua Brindle
Karl MacMillan wrote:
> On Fri, 2006-07-28 at 10:13 -0500, Darrel Goeddel wrote:
> <snip>
>
>>+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.
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.
> <snip>
>
>>+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;
>>+}
>>+
>
>
> 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 ;)
> <snip>
>
>>Index: libsepol/src/write.c
>>===================================================================
>>--- libsepol/src/write.c (revision 38)
>>+++ libsepol/src/write.c (working copy)
>>@@ -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++;
>>+ }
>
>
> 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?
> 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.
> Karl
--
Darrel
--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 2/2] userland support for new range_transition statements
2006-07-31 18:54 ` Darrel Goeddel
@ 2006-07-31 20:52 ` Stephen Smalley
0 siblings, 0 replies; 25+ messages in thread
From: Stephen Smalley @ 2006-07-31 20:52 UTC (permalink / raw)
To: Darrel Goeddel
Cc: Karl MacMillan, 'SELinux List', Eric Paris,
Joshua Brindle
On Mon, 2006-07-31 at 13:54 -0500, Darrel Goeddel wrote:
> 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.
--
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 majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 2/2] userland support for new range_transition statements
2006-07-28 15:13 [PATCH 2/2] userland support for new range_transition statements Darrel Goeddel
2006-07-31 16:40 ` Stephen Smalley
2006-07-31 18:29 ` Karl MacMillan
@ 2006-08-01 13:14 ` Joshua Brindle
2006-08-02 16:38 ` Darrel Goeddel
2006-08-04 17:10 ` [PATCH 2/2 take 2] " Darrel Goeddel
3 siblings, 1 reply; 25+ messages in thread
From: Joshua Brindle @ 2006-08-01 13:14 UTC (permalink / raw)
To: Darrel Goeddel; +Cc: SELinux List, Stephen Smalley, Eric Paris
On Fri, 2006-07-28 at 11:13 -0400, Darrel Goeddel wrote:
> Index: libsepol/include/sepol/policydb/policydb.h
> ===================================================================
> --- libsepol/include/sepol/policydb/policydb.h (revision 38)
> +++ libsepol/include/sepol/policydb/policydb.h (working copy)
> +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>
> 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)) {
man, this conditional is getting out of hand :\
<snip>
> +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)
> + ;
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>
> + 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));
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>
> + 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>
> 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;
I think this was mentioned in another email but a WARN() should probably
be put here
<snip>
> + 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 majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 2/2] userland support for new range_transition statements
2006-08-01 13:14 ` Joshua Brindle
@ 2006-08-02 16:38 ` Darrel Goeddel
2006-08-02 19:51 ` Karl MacMillan
2006-08-03 15:55 ` Joshua Brindle
0 siblings, 2 replies; 25+ messages in thread
From: Darrel Goeddel @ 2006-08-02 16:38 UTC (permalink / raw)
To: Joshua Brindle; +Cc: SELinux List, Stephen Smalley, Eric Paris
Joshua Brindle wrote:
> On Fri, 2006-07-28 at 11:13 -0400, Darrel Goeddel wrote:
>
>>Index: libsepol/include/sepol/policydb/policydb.h
>>===================================================================
>>--- libsepol/include/sepol/policydb/policydb.h (revision 38)
>>+++ libsepol/include/sepol/policydb/policydb.h (working copy)
>
>
>>+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?
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...
>>+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)
>>+ ;
>
>
> 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.
>>+ 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));
>
>
> 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.
>>+ 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.
>> 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;
>
>
> I think this was mentioned in another email but a WARN() should probably
> be put here
Will do.
>>+ 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.
> 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.
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.
--
Darrel
--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 2/2] userland support for new range_transition statements
2006-08-02 16:38 ` Darrel Goeddel
@ 2006-08-02 19:51 ` Karl MacMillan
2006-08-02 21:59 ` Darrel Goeddel
2006-08-03 15:55 ` Joshua Brindle
1 sibling, 1 reply; 25+ messages in thread
From: Karl MacMillan @ 2006-08-02 19:51 UTC (permalink / raw)
To: Darrel Goeddel; +Cc: Joshua Brindle, SELinux List, Stephen Smalley, Eric Paris
On Wed, 2006-08-02 at 11:38 -0500, Darrel Goeddel wrote:
> Joshua Brindle wrote:
> > On Fri, 2006-07-28 at 11:13 -0400, Darrel Goeddel wrote:
> >
> >>Index: libsepol/include/sepol/policydb/policydb.h
> >>===================================================================
> >>--- libsepol/include/sepol/policydb/policydb.h (revision 38)
> >>+++ libsepol/include/sepol/policydb/policydb.h (working copy)
> >
> >
> >>+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?
>
> 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 majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 2/2] userland support for new range_transition statements
2006-08-02 19:51 ` Karl MacMillan
@ 2006-08-02 21:59 ` Darrel Goeddel
2006-08-03 12:01 ` Joshua Brindle
0 siblings, 1 reply; 25+ messages in thread
From: Darrel Goeddel @ 2006-08-02 21:59 UTC (permalink / raw)
To: Karl MacMillan; +Cc: Joshua Brindle, SELinux List, Stephen Smalley, Eric Paris
Karl MacMillan wrote:
> On Wed, 2006-08-02 at 11:38 -0500, Darrel Goeddel wrote:
>
>>Joshua Brindle wrote:
>>
>>>On Fri, 2006-07-28 at 11:13 -0400, Darrel Goeddel wrote:
>>>
>>>
>>>>Index: libsepol/include/sepol/policydb/policydb.h
>>>>===================================================================
>>>>--- libsepol/include/sepol/policydb/policydb.h (revision 38)
>>>>+++ libsepol/include/sepol/policydb/policydb.h (working copy)
>>>
>>>
>>>>+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?
>>
>>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.
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.
--
Darrel
--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.
^ permalink raw reply [flat|nested] 25+ messages in thread
* RE: [PATCH 2/2] userland support for new range_transition statements
2006-08-02 21:59 ` Darrel Goeddel
@ 2006-08-03 12:01 ` Joshua Brindle
0 siblings, 0 replies; 25+ messages in thread
From: Joshua Brindle @ 2006-08-03 12:01 UTC (permalink / raw)
To: Darrel Goeddel, Karl MacMillan; +Cc: SELinux List, Stephen Smalley, Eric Paris
> From: Darrel Goeddel [mailto:dgoeddel@trustedcs.com]
>
> Karl MacMillan wrote:
> > On Wed, 2006-08-02 at 11:38 -0500, Darrel Goeddel wrote:
> >
> >>Joshua Brindle wrote:
> >>
> >>>On Fri, 2006-07-28 at 11:13 -0400, Darrel Goeddel wrote:
> >>>
> >>>
> >>>>Index: libsepol/include/sepol/policydb/policydb.h
> >>>>==========================================================
> =========
> >>>>--- libsepol/include/sepol/policydb/policydb.h (revision 38)
> >>>>+++ libsepol/include/sepol/policydb/policydb.h (working copy)
> >>>
> >>>
> >>>>+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?
> >>
> >>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.
>
> 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 majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.
^ permalink raw reply [flat|nested] 25+ messages in thread
* RE: [PATCH 2/2] userland support for new range_transition statements
2006-08-02 16:38 ` Darrel Goeddel
2006-08-02 19:51 ` Karl MacMillan
@ 2006-08-03 15:55 ` Joshua Brindle
2006-08-04 16:13 ` Darrel Goeddel
1 sibling, 1 reply; 25+ messages in thread
From: Joshua Brindle @ 2006-08-03 15:55 UTC (permalink / raw)
To: Darrel Goeddel; +Cc: SELinux List, Stephen Smalley, Eric Paris
> From: Darrel Goeddel [mailto:dgoeddel@trustedcs.com]
>
> Joshua Brindle wrote:
> > On Fri, 2006-07-28 at 11:13 -0400, Darrel Goeddel wrote:
> >
> >>Index: libsepol/include/sepol/policydb/policydb.h
> >>===================================================================
> >>--- libsepol/include/sepol/policydb/policydb.h (revision 38)
> >>+++ libsepol/include/sepol/policydb/policydb.h (working copy)
> >
> >
> >>+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?
>
> 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).
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 majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 2/2] userland support for new range_transition statements
2006-08-03 15:55 ` Joshua Brindle
@ 2006-08-04 16:13 ` Darrel Goeddel
2006-08-07 13:18 ` Joshua Brindle
0 siblings, 1 reply; 25+ messages in thread
From: Darrel Goeddel @ 2006-08-04 16:13 UTC (permalink / raw)
To: Joshua Brindle; +Cc: SELinux List, Stephen Smalley, Eric Paris
Joshua Brindle wrote:
>>From: Darrel Goeddel [mailto:dgoeddel@trustedcs.com]
>>
>>Joshua Brindle wrote:
>>
>>>On Fri, 2006-07-28 at 11:13 -0400, Darrel Goeddel wrote:
>>>
>>>
>>>>Index: libsepol/include/sepol/policydb/policydb.h
>>>>===================================================================
>>>>--- libsepol/include/sepol/policydb/policydb.h (revision 38)
>>>>+++ libsepol/include/sepol/policydb/policydb.h (working copy)
>>>
>>>
>>>>+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?
>>
>>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).
>
> 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.
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_t
could 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=NULL
I 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...
--
Darrel
--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 2/2 take 2] userland support for new range_transition statements
2006-07-28 15:13 [PATCH 2/2] userland support for new range_transition statements Darrel Goeddel
` (2 preceding siblings ...)
2006-08-01 13:14 ` Joshua Brindle
@ 2006-08-04 17:10 ` Darrel Goeddel
2006-08-08 22:25 ` Joshua Brindle
3 siblings, 1 reply; 25+ messages in thread
From: Darrel Goeddel @ 2006-08-04 17:10 UTC (permalink / raw)
To: Darrel Goeddel
Cc: 'SELinux List', Stephen Smalley, Eric Paris,
Joshua Brindle
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).
Index: libsepol/include/sepol/policydb/policydb.h
===================================================================
--- libsepol/include/sepol/policydb/policydb.h (revision 45)
+++ libsepol/include/sepol/policydb/policydb.h (working copy)
@@ -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
Index: libsepol/include/sepol/policydb/mls_types.h
===================================================================
--- libsepol/include/sepol/policydb/mls_types.h (revision 45)
+++ libsepol/include/sepol/policydb/mls_types.h (working copy)
@@ -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
Index: libsepol/include/sepol/policydb/context.h
===================================================================
--- libsepol/include/sepol/policydb/context.h (revision 45)
+++ libsepol/include/sepol/policydb/context.h (working copy)
@@ -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);
}
Index: libsepol/src/policydb.c
===================================================================
--- libsepol/src/policydb.c (revision 45)
+++ libsepol/src/policydb.c (working copy)
@@ -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;
}
Index: libsepol/src/mls.c
===================================================================
--- libsepol/src/mls.c (revision 45)
+++ libsepol/src/mls.c (working copy)
@@ -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 */
Index: libsepol/src/avrule_block.c
===================================================================
--- libsepol/src/avrule_block.c (revision 45)
+++ libsepol/src/avrule_block.c (working copy)
@@ -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);
Index: libsepol/src/expand.c
===================================================================
--- libsepol/src/expand.c (revision 45)
+++ libsepol/src/expand.c (working copy)
@@ -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;
}
Index: libsepol/src/write.c
===================================================================
--- libsepol/src/write.c (revision 45)
+++ libsepol/src/write.c (working copy)
@@ -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;
}
Index: checkpolicy/module_compiler.c
===================================================================
--- checkpolicy/module_compiler.c (revision 45)
+++ checkpolicy/module_compiler.c (working copy)
@@ -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;
Index: checkpolicy/policy_parse.y
===================================================================
--- checkpolicy/policy_parse.y (revision 45)
+++ checkpolicy/policy_parse.y (working copy)
@@ -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;
}
Index: checkpolicy/module_compiler.h
===================================================================
--- checkpolicy/module_compiler.h (revision 45)
+++ checkpolicy/module_compiler.h (working copy)
@@ -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
--
Darrel
--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.
^ permalink raw reply [flat|nested] 25+ messages in thread
* RE: [PATCH 2/2] userland support for new range_transition statements
2006-08-04 16:13 ` Darrel Goeddel
@ 2006-08-07 13:18 ` Joshua Brindle
2006-08-08 14:48 ` Darrel Goeddel
0 siblings, 1 reply; 25+ messages in thread
From: Joshua Brindle @ 2006-08-07 13:18 UTC (permalink / raw)
To: Darrel Goeddel; +Cc: SELinux List, Stephen Smalley, Eric Paris, Karl MacMillan
> From: Darrel Goeddel [mailto:dgoeddel@trustedcs.com]
> > 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_t
>
> could 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=NULL
>
Should start/stop be datum values or just pointers to the datum?
> I 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...
>
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 majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 2/2] userland support for new range_transition statements
2006-08-07 13:18 ` Joshua Brindle
@ 2006-08-08 14:48 ` Darrel Goeddel
2006-08-08 22:45 ` Joshua Brindle
0 siblings, 1 reply; 25+ messages in thread
From: Darrel Goeddel @ 2006-08-08 14:48 UTC (permalink / raw)
To: Joshua Brindle; +Cc: SELinux List, Stephen Smalley, Eric Paris, Karl MacMillan
Joshua Brindle wrote:
>>From: Darrel Goeddel [mailto:dgoeddel@trustedcs.com]
>>
>>>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_t
>>
>>could 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=NULL
>>
>
>
> 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=NULL
Those 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>
> 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 ;)
> 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?
> 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.
This is what I was thinking.
> 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.
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.
> 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?
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.
--
Darrel
--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.
^ permalink raw reply [flat|nested] 25+ messages in thread
* RE: [PATCH 2/2 take 2] userland support for new range_transition statements
2006-08-04 17:10 ` [PATCH 2/2 take 2] " Darrel Goeddel
@ 2006-08-08 22:25 ` Joshua Brindle
2006-08-09 13:09 ` Karl MacMillan
2006-08-09 14:29 ` [PATCH 2/2 take 2] userland support for new range_transition statements Darrel Goeddel
0 siblings, 2 replies; 25+ messages in thread
From: Joshua Brindle @ 2006-08-08 22:25 UTC (permalink / raw)
To: Darrel Goeddel; +Cc: SELinux List, Stephen Smalley, Eric Paris
> From: Darrel Goeddel [mailto:dgoeddel@trustedcs.com]
>
Sorry it took so long to reply to this.
>
> for module policy versions up to 6, there are no
> range_transitions for 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.
> #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);
> +}
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 majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.
^ permalink raw reply [flat|nested] 25+ messages in thread
* RE: [PATCH 2/2] userland support for new range_transition statements
2006-08-08 14:48 ` Darrel Goeddel
@ 2006-08-08 22:45 ` Joshua Brindle
2006-08-09 15:00 ` Darrel Goeddel
0 siblings, 1 reply; 25+ messages in thread
From: Joshua Brindle @ 2006-08-08 22:45 UTC (permalink / raw)
To: Darrel Goeddel; +Cc: SELinux List, Stephen Smalley, Eric Paris, Karl MacMillan
> From: Darrel Goeddel [mailto:dgoeddel@trustedcs.com]
>
> Joshua Brindle wrote:
> >
> > 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
>
> 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.
> <snip>
>
>
> > 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?
>
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
> >
> > 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.
>
> 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.
> 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.
>
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.
> 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 majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.
^ permalink raw reply [flat|nested] 25+ messages in thread
* RE: [PATCH 2/2 take 2] userland support for new range_transition statements
2006-08-08 22:25 ` Joshua Brindle
@ 2006-08-09 13:09 ` Karl MacMillan
2006-08-09 13:31 ` Joshua Brindle
2006-08-09 14:29 ` [PATCH 2/2 take 2] userland support for new range_transition statements Darrel Goeddel
1 sibling, 1 reply; 25+ messages in thread
From: Karl MacMillan @ 2006-08-09 13:09 UTC (permalink / raw)
To: Joshua Brindle; +Cc: Darrel Goeddel, SELinux List, Stephen Smalley, Eric Paris
On Tue, 2006-08-08 at 18:25 -0400, Joshua Brindle wrote:
> > From: Darrel Goeddel [mailto:dgoeddel@trustedcs.com]
> >
>
> Sorry it took so long to reply to this.
>
> >
> > for module policy versions up to 6, there are no
> > range_transitions for 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.
>
>
> > #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);
> > +}
>
> x->next = NULL?
>
>
> 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
>
> --
> This message was distributed to subscribers of the selinux mailing list.
> If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov 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 majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 2/2 take 2] userland support for new range_transition statements
2006-08-09 13:09 ` Karl MacMillan
@ 2006-08-09 13:31 ` Joshua Brindle
2006-08-09 15:06 ` Darrel Goeddel
0 siblings, 1 reply; 25+ messages in thread
From: Joshua Brindle @ 2006-08-09 13:31 UTC (permalink / raw)
To: Karl MacMillan; +Cc: Darrel Goeddel, SELinux List, Stephen Smalley, Eric Paris
Karl MacMillan wrote:
> On Tue, 2006-08-08 at 18:25 -0400, Joshua Brindle wrote:
>>> From: Darrel Goeddel [mailto:dgoeddel@trustedcs.com]
>>>
>> Sorry it took so long to reply to this.
>>
>>> for module policy versions up to 6, there are no
>>> range_transitions for 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.
>>
>>
>>> #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);
>>> +}
>> x->next = NULL?
>>
>>
>> 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 majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 2/2 take 2] userland support for new range_transition statements
2006-08-08 22:25 ` Joshua Brindle
2006-08-09 13:09 ` Karl MacMillan
@ 2006-08-09 14:29 ` Darrel Goeddel
1 sibling, 0 replies; 25+ messages in thread
From: Darrel Goeddel @ 2006-08-09 14:29 UTC (permalink / raw)
To: Joshua Brindle; +Cc: SELinux List, Stephen Smalley, Eric Paris
Joshua Brindle wrote:
>>From: Darrel Goeddel [mailto:dgoeddel@trustedcs.com]
>>
>
>
> Sorry it took so long to reply to this.
>
>
>> for module policy versions up to 6, there are no
>>range_transitions for 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.
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.
>> #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);
>>+}
>
>
> x->next = NULL?
D'oh. Will initialize...
--
Darrel
--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 2/2] userland support for new range_transition statements
2006-08-08 22:45 ` Joshua Brindle
@ 2006-08-09 15:00 ` Darrel Goeddel
0 siblings, 0 replies; 25+ messages in thread
From: Darrel Goeddel @ 2006-08-09 15:00 UTC (permalink / raw)
To: Joshua Brindle
Cc: SELinux List, Stephen Smalley, Eric Paris, Karl MacMillan,
Chad Hanson
Joshua Brindle wrote:
>>From: Darrel Goeddel [mailto:dgoeddel@trustedcs.com]
>>
>>Joshua Brindle wrote:
>>
<snip>
>>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.
>
>>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.
>>
>
>
> 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)
>>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...
--
Darrel
--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 2/2 take 2] userland support for new range_transition statements
2006-08-09 13:31 ` Joshua Brindle
@ 2006-08-09 15:06 ` Darrel Goeddel
2006-08-09 15:13 ` Karl MacMillan
0 siblings, 1 reply; 25+ messages in thread
From: Darrel Goeddel @ 2006-08-09 15:06 UTC (permalink / raw)
To: Joshua Brindle; +Cc: Karl MacMillan, SELinux List, Stephen Smalley, Eric Paris
Joshua Brindle wrote:
> Karl MacMillan wrote:
>
>> On Tue, 2006-08-08 at 18:25 -0400, Joshua Brindle wrote:
>>
>>>> From: Darrel Goeddel [mailto:dgoeddel@trustedcs.com]
>>>
>>> Sorry it took so long to reply to this.
>>>
>>>> for module policy versions up to 6, there are no range_transitions
>>>> for 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.
>>>
>>>
>>>> #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);
>>>> +}
>>>
>>> x->next = NULL?
>>>
>>> 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.
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...
--
Darrel
--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 2/2 take 2] userland support for new range_transition statements
2006-08-09 15:06 ` Darrel Goeddel
@ 2006-08-09 15:13 ` Karl MacMillan
2006-08-09 15:39 ` [PATCH 2/2 take 2] userland support for new range_transitionstatements Joshua Brindle
0 siblings, 1 reply; 25+ messages in thread
From: Karl MacMillan @ 2006-08-09 15:13 UTC (permalink / raw)
To: Darrel Goeddel; +Cc: Joshua Brindle, SELinux List, Stephen Smalley, Eric Paris
On Wed, 2006-08-09 at 10:06 -0500, Darrel Goeddel wrote:
> Joshua Brindle wrote:
<snip>
> >
> > 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 ;)
>
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.
> 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.
> 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 majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.
^ permalink raw reply [flat|nested] 25+ messages in thread
* RE: [PATCH 2/2 take 2] userland support for new range_transitionstatements
2006-08-09 15:13 ` Karl MacMillan
@ 2006-08-09 15:39 ` Joshua Brindle
0 siblings, 0 replies; 25+ messages in thread
From: Joshua Brindle @ 2006-08-09 15:39 UTC (permalink / raw)
To: Karl MacMillan, Darrel Goeddel; +Cc: SELinux List, Stephen Smalley, Eric Paris
> From: Karl MacMillan [mailto:kmacmillan@mentalrootkit.com]
>
> On Wed, 2006-08-09 at 10:06 -0500, Darrel Goeddel wrote:
> > Joshua Brindle wrote:
>
> <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).
> > 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.
>
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.
> > 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.
>
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 majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.
^ permalink raw reply [flat|nested] 25+ messages in thread
end of thread, other threads:[~2006-08-09 15:39 UTC | newest]
Thread overview: 25+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-07-28 15:13 [PATCH 2/2] userland support for new range_transition statements Darrel Goeddel
2006-07-31 16:40 ` Stephen Smalley
2006-07-31 18:25 ` Darrel Goeddel
2006-07-31 18:29 ` Karl MacMillan
2006-07-31 18:54 ` Darrel Goeddel
2006-07-31 20:52 ` Stephen Smalley
2006-08-01 13:14 ` Joshua Brindle
2006-08-02 16:38 ` Darrel Goeddel
2006-08-02 19:51 ` Karl MacMillan
2006-08-02 21:59 ` Darrel Goeddel
2006-08-03 12:01 ` Joshua Brindle
2006-08-03 15:55 ` Joshua Brindle
2006-08-04 16:13 ` Darrel Goeddel
2006-08-07 13:18 ` Joshua Brindle
2006-08-08 14:48 ` Darrel Goeddel
2006-08-08 22:45 ` Joshua Brindle
2006-08-09 15:00 ` Darrel Goeddel
2006-08-04 17:10 ` [PATCH 2/2 take 2] " Darrel Goeddel
2006-08-08 22:25 ` Joshua Brindle
2006-08-09 13:09 ` Karl MacMillan
2006-08-09 13:31 ` Joshua Brindle
2006-08-09 15:06 ` Darrel Goeddel
2006-08-09 15:13 ` Karl MacMillan
2006-08-09 15:39 ` [PATCH 2/2 take 2] userland support for new range_transitionstatements Joshua Brindle
2006-08-09 14:29 ` [PATCH 2/2 take 2] userland support for new range_transition statements Darrel Goeddel
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.