user_transition support for libsepol/checkpolicy
RFC PATCH 1/1 user_transition support for libsepol/checkpolicy
This implements user_transition in the toolchain. It should help on distro's like Ubuntu that can't use run_init due to the user not knowing the root password. It also seems like a more eloquent way to handle service restarts than assigning system_r to user accounts and having the daemons run as someuser:system_r:foo_t.
This has some issues in policy due to users not always being known in the policy (eg., semanage users). I hope Chris or Dan will be able to give some suggestions there.
The kernel patch (forthcoming after this is accepted) so far only implements the transition on process transitions. Later on I plan on doing a patch to expand role_transition to object classes (this is a change needed for policy rbac support to work). I suspect I'll do the same for user at that time. The question here is, do we think its worth it to do fine grained transitions like we did for range_trans? (I don't).
include/sepol/policydb/policydb.h +0 -0
@@ -156,6 +156,14 @@
mls_level_t exp_dfltlevel; /* expanded range used for validation */
} user_datum_t;
+typedef struct user_trans {
+ uint32_t user; /* current role */
+ uint32_t type; /* program executable type */
+ uint32_t new_user; /* new role */
+ struct user_trans *next;
+} user_trans_t;
+
+
/* Sensitivity attributes */
typedef struct level_datum {
mls_level_t *level; /* sensitivity and associated categories */
@@ -225,6 +233,13 @@
struct role_trans_rule *next; } role_trans_rule_t;
+typedef struct user_trans_rule {
+ ebitmap_t users; /* current role */
+ type_set_t types; /* program executable type */
+ uint32_t new_user; /* new role */
+ struct user_trans_rule *next;
+} user_trans_rule_t;
+
typedef struct role_allow_rule {
role_set_t roles; /* current role */
role_set_t new_roles; /* new roles */
@@ -348,6 +363,9 @@
char *module_name; struct avrule_decl *next;
+
+ user_trans_rule_t *user_tr_rules;
+
} avrule_decl_t;
typedef struct avrule_block {
@@ -470,6 +488,8 @@
ebitmap_t policycaps;
+ user_trans_t *user_tr;
+
unsigned policyvers; unsigned handle_unknown;
@@ -524,6 +544,9 @@
extern void role_trans_rule_init(role_trans_rule_t * x); extern void role_trans_rule_list_destroy(role_trans_rule_t * x);
+extern void user_trans_rule_init(user_trans_rule_t * x); +extern void user_trans_rule_list_destroy(user_trans_rule_t * x); +
extern void role_datum_init(role_datum_t * x);
extern void role_datum_destroy(role_datum_t * x); extern void role_allow_rule_init(role_allow_rule_t * x); @@ -588,10 +611,11 @@
#define POLICYDB_VERSION_AVTAB 20
#define POLICYDB_VERSION_RANGETRANS 21
#define POLICYDB_VERSION_POLCAP 22
+#define POLICYDB_VERSION_USERTRANS 23
/* Range of policy versions we understand*/
#define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE
-#define POLICYDB_VERSION_MAX POLICYDB_VERSION_POLCAP
+#define POLICYDB_VERSION_MAX POLICYDB_VERSION_USERTRANS
/* Module versions and specific changes*/
#define MOD_POLICYDB_VERSION_BASE 4
@@ -600,9 +624,10 @@
#define MOD_POLICYDB_VERSION_RANGETRANS 6
#define MOD_POLICYDB_VERSION_MLS_USERS 6
#define MOD_POLICYDB_VERSION_POLCAP 7
+#define MOD_POLICYDB_VERSION_USERTRANS 8
#define MOD_POLICYDB_VERSION_MIN MOD_POLICYDB_VERSION_BASE -#define MOD_POLICYDB_VERSION_MAX MOD_POLICYDB_VERSION_POLCAP +#define MOD_POLICYDB_VERSION_MAX MOD_POLICYDB_VERSION_USERTRANS
#define POLICYDB_CONFIG_MLS 1
src/policydb.c +0 -0
@@ -105,6 +105,12 @@
.ocon_num = OCON_NODE6 + 1,
},
{+ .type = POLICY_KERN,
+ .version = POLICYDB_VERSION_USERTRANS,
+ .sym_num = SYM_NUM,
+ .ocon_num = OCON_NODE6 + 1,
+ },
+ {
.type = POLICY_BASE,
.version = MOD_POLICYDB_VERSION_BASE,
.sym_num = SYM_NUM,
@@ -129,6 +135,12 @@
.ocon_num = OCON_NODE6 + 1,
},
{+ .type = POLICY_BASE,
+ .version = MOD_POLICYDB_VERSION_USERTRANS,
+ .sym_num = SYM_NUM,
+ .ocon_num = OCON_NODE6 + 1,
+ },
+ {
.type = POLICY_MOD,
.version = MOD_POLICYDB_VERSION_BASE,
.sym_num = SYM_NUM,
@@ -150,7 +162,14 @@
.type = POLICY_MOD,
.version = MOD_POLICYDB_VERSION_POLCAP,
.sym_num = SYM_NUM,
- .ocon_num = 0},
+ .ocon_num = 0
+ },
+ {
+ .type = POLICY_MOD,
+ .version = MOD_POLICYDB_VERSION_USERTRANS,
+ .sym_num = SYM_NUM,
+ .ocon_num = 0
+ },
};
#if 0
@@ -348,6 +367,30 @@
} }
+void user_trans_rule_init(user_trans_rule_t * x) +{
+ memset(x, 0, sizeof(*x));
+ ebitmap_init(&x->users);
+ type_set_init(&x->types);
+}
+
+void user_trans_rule_destroy(user_trans_rule_t * x) +{
+ if (x != NULL) {
+ ebitmap_init(&x->users);
+ type_set_destroy(&x->types);
+ }
+}
+
+void user_trans_rule_list_destroy(user_trans_rule_t * x) +{
+ while (x != NULL) {
+ user_trans_rule_t *next = x->next;
+ user_trans_rule_destroy(x);
+ free(x);
+ x = next;
+ }
+}
void role_allow_rule_init(role_allow_rule_t * x)
{
memset(x, 0, sizeof(role_allow_rule_t));
@@ -985,6 +1028,7 @@
unsigned int i;
role_allow_t *ra, *lra = NULL;
role_trans_t *tr, *ltr = NULL;
+ user_trans_t *ut, *lut = NULL;
range_trans_t *rt, *lrt = NULL;
if (!p)
@@ -1058,6 +1102,14 @@
if (ltr)
free(ltr);+ for (ut = p->user_tr; ut; ut = ut->next) {
+ if (lut)
+ free(lut);
+ lut = ut;
+ }
+ if (lut)
+ free(lut);
+
for (ra = p->role_allow; ra; ra = ra->next) {
if (lra)
free(lra);
@@ -1983,6 +2035,40 @@
return 0;
}+int user_trans_read(user_trans_t ** t, struct policy_file *fp) +{
+ unsigned int i; + uint32_t buf[3], nel; + user_trans_t *ut, *lut; + int rc;
+
+ rc = next_entry(buf, fp, sizeof(uint32_t));
+ if (rc < 0)
+ return -1;
+ nel = le32_to_cpu(buf[0]);
+ lut = NULL;
+ for (i = 0; i < nel; i++) {+ ut = calloc(1, sizeof(struct user_trans));
+ if (!ut) {
+ return -1;
+ }
+ if (lut) {
+ lut->next = ut;
+ } else {
+ *t = ut;
+ } + rc = next_entry(buf, fp, sizeof(uint32_t) * 3); + if (rc < 0) + return -1; + ut->user = le32_to_cpu(buf[0]); + ut->type = le32_to_cpu(buf[1]); + ut->new_user = le32_to_cpu(buf[2]); + lut = ut;
+ }
+ return 0;
+}
+
+
int role_allow_read(role_allow_t ** r, struct policy_file *fp)
{
unsigned int i;
@@ -2679,6 +2765,48 @@
return 0;
}+static int user_trans_rule_read(user_trans_rule_t ** u, struct policy_file *fp) +{
+ uint32_t buf[1], nel; + unsigned int i; + user_trans_rule_t *ut, *lut; + int rc;
+
+ rc = next_entry(buf, fp, sizeof(uint32_t));
+ if (rc < 0)
+ return -1;
+ nel = le32_to_cpu(buf[0]);
+ lut = NULL;
+ for (i = 0; i < nel; i++) {+ ut = malloc(sizeof(user_trans_rule_t));
+ if (!ut) {
+ return -1;
+ }
+ user_trans_rule_init(ut);
+
+ if (lut) {
+ lut->next = ut;
+ } else {
+ *u = ut;
+ }
+
+ if (ebitmap_read(&ut->users, fp))
+ return -1;
+
+ if (type_set_read(&ut->types, fp))
+ return -1;
+
+ rc = next_entry(buf, fp, sizeof(uint32_t));
+ if (rc < 0)
+ return -1;
+ ut->new_user = le32_to_cpu(buf[0]);
+ lut = ut;
+ }
+
+ return 0;
+}
+
+
static int role_allow_rule_read(role_allow_rule_t ** r, struct policy_file *fp)
{
unsigned int i;
@@ -2805,9 +2933,14 @@
if (cond_read_list(p, &decl->cond_list, fp) == -1 ||
avrule_read_list(p, &decl->avrules, fp) == -1 ||
role_trans_rule_read(&decl->role_tr_rules, fp) == -1 ||
- role_allow_rule_read(&decl->role_allow_rules, fp) == -1) {
+ role_allow_rule_read(&decl->role_allow_rules, fp) == -1)
+ {
return -1;
}+ if (p->policyvers >= MOD_POLICYDB_VERSION_USERTRANS) {
+ if (user_trans_rule_read(&decl->user_tr_rules, fp))
+ return -1;
+ }
if (p->policyvers >= MOD_POLICYDB_VERSION_RANGETRANS &&
range_trans_rule_read(&decl->range_tr_rules, fp) == -1) {
return -1;
@@ -3179,6 +3312,10 @@
goto bad;
if (role_trans_read(&p->role_tr, fp))
goto bad;+ if (r_policyvers >= POLICYDB_VERSION_USERTRANS) {
+ if (user_trans_read(&p->user_tr, fp))
+ goto bad;
+ }
if (role_allow_read(&p->role_allow, fp))
goto bad;
} else {src/expand.c +0 -0
@@ -1060,6 +1060,80 @@
return 0; }
+static int copy_user_trans(expand_state_t * state, user_trans_rule_t * rules) +{
+ unsigned int i, j;
+ user_trans_t *n, *l, *cur_trans;
+ user_trans_rule_t *cur;
+ ebitmap_t types;
+ ebitmap_node_t *rnode, *tnode;
+
+ /* start at the end of the list */
+ for (l = state->out->user_tr; l && l->next; l = l->next) ;
+
+ cur = rules;
+ while (cur) {
+ ebitmap_init(&types);
+
+ if (expand_convert_type_set
+ (state->out, state->typemap, &cur->types, &types, 1)) {
+ ERR(state->handle, "Out of memory!");
+ return -1;
+ }
+ ebitmap_for_each_bit(&cur->users, rnode, i) {
+ if (!ebitmap_node_get_bit(rnode, i))
+ continue;
+ ebitmap_for_each_bit(&types, tnode, j) {
+ if (!ebitmap_node_get_bit(tnode, j))
+ continue;
+
+ cur_trans = state->out->user_tr;
+ while (cur_trans) {
+ if ((cur_trans->user == i + 1) &&
+ (cur_trans->type == j + 1)) {
+ if (cur_trans->new_user ==
+ cur->new_user) {
+ break;
+ } else {
+ ERR(state->handle,
+ "Conflicting user trans rule %s %s : %s", + state->out->p_user_val_to_name[i], + state->out->p_type_val_to_name[j], + state->out->p_user_val_to_name[cur->new_user - 1]);
+ return -1;
+ }
+ }
+ cur_trans = cur_trans->next;
+ }
+ if (cur_trans)
+ continue;
+
+ n = (user_trans_t *)
+ malloc(sizeof(user_trans_t));
+ if (!n) {
+ ERR(state->handle, "Out of memory!");
+ return -1;
+ }
+ memset(n, 0, sizeof(user_trans_t));
+ n->user = i + 1;
+ n->type = j + 1;
+ n->new_user = cur->new_user;
+ if (l) {
+ l->next = n;
+ } else {
+ state->out->user_tr = n;
+ }
+ l = n;
+ }
+ }
+
+ ebitmap_destroy(&types);
+
+ cur = cur->next;
+ }
+ return 0;
+}
+
static int exp_rangetr_helper(uint32_t stype, uint32_t ttype, uint32_t tclass,
mls_semantic_range_t * trange, expand_state_t * state)
@@ -2163,6 +2237,9 @@
goto cleanup; }
+ if (copy_user_trans(state, decl->user_tr_rules))
+ goto cleanup;
+
/* expand the range transition rules */ if (expand_range_trans(state, decl->range_tr_rules)) goto cleanup;
src/write.c +0 -0
@@ -487,6 +487,31 @@
return POLICYDB_SUCCESS; }
+static int user_trans_write(user_trans_t * u, struct policy_file *fp) +{
+ user_trans_t *tr;
+ uint32_t buf[3];
+ size_t nel, items;
+
+ nel = 0;
+ for (tr = u; tr; tr = tr->next)
+ nel++;
+ buf[0] = cpu_to_le32(nel);
+ items = put_entry(buf, sizeof(uint32_t), 1, fp);
+ if (items != 1)
+ return POLICYDB_ERROR;
+ for (tr = u; tr; tr = tr->next) {
+ buf[0] = cpu_to_le32(tr->user);
+ buf[1] = cpu_to_le32(tr->type);
+ buf[2] = cpu_to_le32(tr->new_user);
+ items = put_entry(buf, sizeof(uint32_t), 3, fp);
+ if (items != 3)
+ return POLICYDB_ERROR;
+ }
+
+ return POLICYDB_SUCCESS;
+}
+
static int role_allow_write(role_allow_t * r, struct policy_file *fp)
{
role_allow_t *ra;
@@ -1325,6 +1350,32 @@
return POLICYDB_SUCCESS;
}+static int user_trans_rule_write(user_trans_rule_t * t, struct policy_file *fp) +{
+ int nel = 0;
+ size_t items;
+ uint32_t buf[1];
+ user_trans_rule_t *tr;
+
+ for (tr = t; tr; tr = tr->next)
+ nel++;
+ buf[0] = cpu_to_le32(nel);
+ items = put_entry(buf, sizeof(uint32_t), 1, fp);
+ if (items != 1)
+ return POLICYDB_ERROR;
+ for (tr = t; tr; tr = tr->next) {
+ if (ebitmap_write(&tr->users, fp))
+ return POLICYDB_ERROR;
+ if (type_set_write(&tr->types, fp))
+ return POLICYDB_ERROR;
+ buf[0] = cpu_to_le32(tr->new_user);
+ items = put_entry(buf, sizeof(uint32_t), 1, fp);
+ if (items != 1)
+ return POLICYDB_ERROR;
+ }
+ return POLICYDB_SUCCESS;
+}
+
static int role_allow_rule_write(role_allow_rule_t * r, struct policy_file *fp)
{
int nel = 0;
@@ -1414,6 +1465,10 @@
role_allow_rule_write(decl->role_allow_rules, fp) == -1) {
return POLICYDB_ERROR;
}+ if (p->policyvers >= MOD_POLICYDB_VERSION_USERTRANS) {
+ if (user_trans_rule_write(decl->user_tr_rules, fp))
+ return POLICYDB_ERROR;
+ }
if (p->policyvers >= MOD_POLICYDB_VERSION_RANGETRANS &&
range_trans_rule_write(decl->range_tr_rules, fp) == -1) {
return POLICYDB_ERROR;
@@ -1642,6 +1697,10 @@
}
if (role_trans_write(p->role_tr, fp))
return POLICYDB_ERROR;+ if (p->policyvers >= POLICYDB_VERSION_USERTRANS) {
+ if (user_trans_write(p->user_tr, fp))
+ return POLICYDB_ERROR;
+ }
if (role_allow_write(p->role_allow, fp))
return POLICYDB_ERROR;
} else {src/link.c +0 -0
@@ -848,6 +848,34 @@
return -1; }
+static int user_bitmap_or_convert(ebitmap_t * users, ebitmap_t * dst,
+ policy_module_t * mod, link_state_t * state)
+{
+ unsigned int i;
+ ebitmap_t tmp;
+ ebitmap_node_t *rnode;
+
+ ebitmap_init(&tmp);
+ ebitmap_for_each_bit(users, rnode, i) {
+ if (ebitmap_node_get_bit(rnode, i)) {
+ assert(mod->map[SYM_USERS][i]);
+ if (ebitmap_set_bit
+ (&tmp, mod->map[SYM_USERS][i] - 1, 1)) {
+ goto cleanup;
+ }
+ }
+ }
+ if (ebitmap_union(dst, &tmp)) {
+ goto cleanup;
+ }
+ ebitmap_destroy(&tmp);
+ return 0;
+ cleanup:
+ ERR(state->handle, "Out of memory!");
+ ebitmap_destroy(&tmp);
+ return -1;
+}
+
static int mls_level_convert(mls_semantic_level_t * src, mls_semantic_level_t * dst,
policy_module_t * mod, link_state_t * state)
{
@@ -1004,13 +1032,22 @@
link_state_t *state = (link_state_t *) data; policy_module_t *mod = state->cur; symtab_t *usertab;
+ scope_datum_t *scope;
user = (user_datum_t *) datum;
+ scope = hashtab_search(state->cur->policy->p_users_scope.table, key);
+ assert(scope);
+ if (scope->scope == SCOPE_REQ) {
+ //this is required user, no role or mls data
+ return 0;
+ }
+
if (state->dest_decl == NULL)
usertab = &state->base->p_users;
- else
+ else {
usertab = &state->dest_decl->p_users;+ }
new_user = hashtab_search(usertab->table, id); assert(new_user != NULL); @@ -1173,6 +1210,49 @@ return -1; }
+static int copy_user_trans_list(user_trans_rule_t * list,
+ user_trans_rule_t ** dst,
+ policy_module_t * module, link_state_t * state)
+{
+ user_trans_rule_t *cur, *new_rule = NULL, *tail;
+
+ cur = list;
+ tail = *dst;
+ while (tail && tail->next) {+ tail = tail->next;
+ }
+ while (cur) {
+ if ((new_rule =
+ (user_trans_rule_t *) malloc(sizeof(user_trans_rule_t))) ==
+ NULL) {
+ goto cleanup;
+ }
+ user_trans_rule_init(new_rule);
+
+ if (user_bitmap_or_convert(&cur->users, &new_rule->users, module, state))
+ goto cleanup;
+ if (type_set_or_convert(&cur->types, &new_rule->types, module, state)) {
+ goto cleanup;
+ }
+
+ new_rule->new_user = module->map[SYM_USERS][cur->new_user - 1];
+
+ if (*dst == NULL) {
+ *dst = new_rule;
+ } else {
+ tail->next = new_rule;
+ } + tail = new_rule; + cur = cur->next; + } + return 0; + cleanup: + ERR(state->handle, "Out of memory!"); + user_trans_rule_list_destroy(new_rule); + return -1;
+}
+
+
static int copy_role_allow_list(role_allow_rule_t * list,
role_allow_rule_t ** dst, policy_module_t * module, link_state_t * state)
@@ -1446,6 +1526,10 @@
return -1; }
+ if (copy_user_trans_list(src_decl->user_tr_rules, &dest_decl->user_tr_rules,
+ module, state))
+ return -1;
+
if (copy_range_trans_list(src_decl->range_tr_rules, &dest_decl->range_tr_rules, module, state)) return -1;
test/dismod.c +0 -0
@@ -354,6 +354,21 @@
return 0; }
+int display_user_set(ebitmap_t *u, policydb_t *p, FILE *fp) +{
+ ebitmap_node_t *node;
+ int i;
+
+ fprintf(fp, " { ");
+ ebitmap_for_each_bit(u, node, i) {
+ if (ebitmap_node_get_bit(node, i)) {
+ display_id(p, fp, SYM_USERS, i, "");
+ }
+ }
+ fprintf(fp, " } ");
+ return 0;
+}
+
int display_bools(policydb_t * p, FILE * fp)
{
int i;
@@ -461,7 +476,18 @@
fprintf(fp, "\n");
}
}+void display_user_trans(user_trans_rule_t * tr, policydb_t * p, FILE * fp)
+{
+ for (; tr; tr = tr->next) {
+ fprintf(fp, "user transition ");
+ display_user_set(&tr->users, p, fp);
+ display_type_set(&tr->types, 0, p, fp);
+ display_id(p, fp, SYM_USERS, tr->new_user - 1, " :");
+ fprintf(fp, "\n");
+ }
+}
+
void display_role_allow(role_allow_rule_t * ra, policydb_t * p, FILE * fp)
{
for (; ra; ra = ra->next) {
@@ -641,6 +667,10 @@
}
break;
}+ case 7:{
+ display_user_trans(decl->user_tr_rules, policy, out_fp);
+ break;
+ }
default:{
assert(0);
}
@@ -806,6 +836,7 @@
printf("c) Display policy capabilities\n");
printf("l) Link in a module\n");
printf("u) Display the unknown handling setting\n");
+ printf("U) Display user transitions\n");
printf("\n");
printf("f) set output file\n");
printf("m) display menu\n");
@@ -918,9 +949,11 @@
display_policycaps(&policydb, out_fp);
break;
case 'u':
- case 'U':
display_handle_unknown(&policydb, out_fp);
break;
+ case 'U':
+ display_avblock(7, 0, &policydb, out_fp);
+ break;
case 'f':
printf
("\nFilename for output (<CR> for screen output): ");test/dispol.c +0 -0
@@ -299,6 +299,18 @@
return 0; }
+static void display_user_transitions(policydb_t *p, FILE *fp) +{
+ user_trans_t *cur;
+ for (cur = p->user_tr; cur; cur = cur->next) {
+ fprintf(fp, "user_transition ");
+ fprintf(fp, "%s %s %s;\n",
+ p->p_user_val_to_name[cur->user - 1],
+ p->p_type_val_to_name[cur->type - 1],
+ p->p_user_val_to_name[cur->new_user - 1]);
+ }
+}
+
static void display_policycaps(policydb_t * p, FILE * fp)
{
ebitmap_node_t *node;
@@ -332,6 +344,7 @@
printf("\n");
printf("c) display policy capabilities\n");
printf("u) display unknown handling setting\n");
+ printf("U) display user transitions\n");
printf("f) set output file\n");
printf("m) display menu\n");
printf("q) quit\n");
@@ -448,9 +461,11 @@
display_policycaps(&policydb, out_fp);
break;
case 'u':
- case 'U':
display_handle_unknown(&policydb, out_fp);
break;
+ case 'U':
+ display_user_transitions(&policydb, out_fp);
+ break;
case 'f':
printf
("\nFilename for output (<CR> for screen output): ");test/Makefile +0 -0
@@ -6,7 +6,7 @@
LIBDIR=$(PREFIX)/lib
INCLUDEDIR ?= $(PREFIX)/include
-CFLAGS ?= -g -Wall -O2 -pipe
+CFLAGS ?= -g3 -gdwarf-2 -Wall -O0 -pipe
override CFLAGS += -I$(INCLUDEDIR)
LDLIBS=-lfl -lsepol -lselinux $(LIBDIR)/libsepol.a -L$(LIBDIR)
policy_define.c +0 -0
@@ -2020,6 +2020,76 @@
return -1; }
+int define_user_trans(void)
+{
+ char *id;
+ user_datum_t *user, *u;
+ ebitmap_t users;
+ type_set_t types; + struct user_trans_rule *rule = NULL; + int add = 1;
+
+ if (pass == 1) {
+ while ((id = queue_remove(id_queue)))
+ free(id);
+ while ((id = queue_remove(id_queue)))
+ free(id);
+ id = queue_remove(id_queue); + free(id); + return 0;
+ }
+
+ ebitmap_init(&users);
+ type_set_init(&types);
+
+ while ((id = queue_remove(id_queue))) {
+ u = hashtab_search(policydbp->p_users.table, id);
+ if (!u) {
+ yyerror2("unknown user %s", id);
+ free(id);
+ return -1;
+ }
+ if (ebitmap_set_bit(&users, u->s.value - 1, TRUE))
+ return -1;
+ }
+ while ((id = queue_remove(id_queue))) {
+ if (set_types(&types, id, &add, 0))
+ return -1;
+ }
+ id = (char *)queue_remove(id_queue);
+ if (!id) {
+ yyerror("no new user in transition definition?");
+ goto bad;
+ }
+ if (!is_id_in_scope(SYM_USERS, id)) {
+ yyerror2("user %s is not within scope", id);
+ free(id);
+ goto bad;
+ }
+ user = hashtab_search(policydbp->p_users.table, id);
+ if (!user) {
+ yyerror2("unknown user %s used in transition definition", id);
+ goto bad;
+ }
+ rule = malloc(sizeof(struct user_trans_rule));
+ if (!rule) {
+ yyerror("out of memory");
+ return -1;
+ }
+ memset(rule, 0, sizeof(struct user_trans_rule));
+ rule->users = users;
+ rule->types = types;
+ rule->new_user = user->s.value;
+
+ append_user_trans(rule);
+
+ return 0;
+
+ bad:
+ return -1;
+}
+
+
int define_role_allow(void)
{
char *id;policy_scan.l +0 -0
@@ -102,6 +102,8 @@
type_change { return(TYPE_CHANGE); }ROLE_TRANSITION |role_transition { return(ROLE_TRANSITION); }
+USER_TRANSITION |
+user_transition { return(USER_TRANSITION); }RANGE_TRANSITION |range_transition { return(RANGE_TRANSITION); }
SENSITIVITY |
policy_define.h +0 -0
@@ -42,6 +42,7 @@
int define_role_allow(void);
int define_role_trans(void);
int define_role_types(void);
+int define_user_trans(void);
int define_sens(void);
int define_te_avtab(int which);
int define_typealias(void);
module_compiler.c +0 -0
@@ -1214,6 +1214,17 @@
decl->role_tr_rules = role_tr_rules; }
+void append_user_trans(user_trans_rule_t * user_tr_rules) +{
+ avrule_decl_t *decl = stack_top->decl;
+
+ /* role transitions are not allowed within conditionals */
+ assert(stack_top->type == 1);
+
+ user_tr_rules->next = decl->user_tr_rules;
+ decl->user_tr_rules = user_tr_rules;
+}
+
/* this doesn't actually append, but really prepends it */ void append_role_allow(role_allow_rule_t * role_allow_rules) {
policy_parse.y +0 -0
@@ -103,6 +103,7 @@
%token TYPE_MEMBER
%token TYPE_CHANGE
%token ROLE_TRANSITION
+%token USER_TRANSITION
%token RANGE_TRANSITION
%token SENSITIVITY
%token DOMINANCE
@@ -261,6 +262,7 @@
| transition_def
| range_trans_def
| te_avtab_def
+ | user_trans_def
;
attribute_def : ATTRIBUTE identifier ';'
{ if (define_attrib()) return -1;}
@@ -411,6 +413,9 @@
role_trans_def : ROLE_TRANSITION names names identifier ';'
{if (define_role_trans()) return -1; }
;+user_trans_def : USER_TRANSITION names names identifier ';'
+ { if (define_user_trans()) return -1; }
+ ;role_allow_def : ALLOW names names ';'
{if (define_role_allow()) return -1; }
;module_compiler.h +0 -0
@@ -80,6 +80,7 @@
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); +void append_user_trans(user_trans_rule_t * user_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
--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
Quoted 5 lines · Joshua Brindle
This implements
user_transitionin the toolchain. It should help on distro's like Ubuntu that can't userun_initdue to the user not knowing the root password. It also seems like a more eloquent way to handle service restarts than assigningsystem_rto user accounts and having the daemons run as someuser:system_r:foo_t.
Yes, that's something that has been wanted in Fedora for quite some time.
The real issue with run_init isn't the re-authentication stage, as that can always be disabled via pam config (and was just a weak form of confirming user intent, not an authorization mechanism), but rather the difficulty in transparently interposing it into all situations where services get started/re-started. Only Gentoo seemed to have a good story there.
Quoted 3 lines
This has some issues in policy due to users not always being known in the policy (eg., semanage users). I hope Chris or Dan will be able to give some suggestions there.
I'm not sure why anyone needs to add users to policy via semanage users given the base set of generic users and the ability to map Linux users to them via seusers aka semanage login.
Quoted 6 lines
The kernel patch (forthcoming after this is accepted) so far only implements the transition on process transitions. Later on I plan on doing a patch to expand
role_transitionto object classes (this is a change needed for policy rbac support to work). I suspect I'll do the same for user at that time. The question here is, do we think its worth it to do fine grained transitions like we did forrange_trans? (I don't).
Offhand, I can't see a use for per-class user transitions, if that is what you mean.
I don't think per-class role transitions is really the fundamental obstacle to enabling use of roles on objects - more thought is required there. What will be fun there is role/type and user/range validation, which presently gets to ignore everything that has object_r.
Quoted 932 lines
Index:
libsepol/include/sepol/policydb/policydb.h
===================================================================include/sepol/policydb/policydb.h +27
-2@@ -156,6 +156,14 @@mls_level_t exp_dfltlevel;/* expanded range used for validation */ } user_datum_t; +typedef struct user_trans { +uint32_t user;/* current role */ +uint32_t type;/* program executable type */ +uint32_t new_user;/* new role */ +struct user_trans *next; +}user_trans_t ; + +/* Sensitivity attributes */ typedef struct level_datum { mls_level_t *level; /* sensitivity and associated categories */@@ -225,6 +233,13 @@struct role_trans_rule *next; } role_trans_rule_t; +typedef struct user_trans_rule { +ebitmap_t users;/* current role */ +type_set_t types;/* program executable type */ +uint32_t new_user;/* new role */ +struct user_trans_rule *next; +}user_trans_rule_t ; + typedef struct role_allow_rule { role_set_t roles; /* current role */ role_set_t new_roles; /* new roles */@@ -348,6 +363,9 @@char *module_name;struct avrule_decl *next; + +user_trans_rule_t *user_tr_rules; + } avrule_decl_t; typedef struct avrule_block {@@ -470,6 +488,8 @@ebitmap_t policycaps; +user_trans_t *user_tr; +unsigned policyvers;unsigned handle_unknown;@@ -524,6 +544,9 @@extern void role_trans_rule_init (role_trans_rule_t * x);extern void role_trans_rule_list_destroy (role_trans_rule_t * x); +extern void user_trans_rule_init (user_trans_rule_t * x); +extern void user_trans_rule_list_destroy (user_trans_rule_t * x); +extern void role_datum_init (role_datum_t * x);extern void role_datum_destroy (role_datum_t * x);extern void role_allow_rule_init (role_allow_rule_t * x);@@ -588,10 +611,11 @@#define POLICYDB_VERSION_AVTAB 20#define POLICYDB_VERSION_RANGETRANS 21#define POLICYDB_VERSION_POLCAP 22 +#define POLICYDB_VERSION_USERTRANS 23/* Range of policy versions we understand*/ #define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE -#define POLICYDB_VERSION_MAX POLICYDB_VERSION_POLCAP +#define POLICYDB_VERSION_MAX POLICYDB_VERSION_USERTRANS/* Module versions and specific changes*/ #define MOD_POLICYDB_VERSION_BASE 4@@ -600,9 +624,10 @@#define MOD_POLICYDB_VERSION_RANGETRANS 6#define MOD_POLICYDB_VERSION_MLS_USERS 6#define MOD_POLICYDB_VERSION_POLCAP 7 +#define MOD_POLICYDB_VERSION_USERTRANS 8#define MOD_POLICYDB_VERSION_MIN MOD_POLICYDB_VERSION_BASE -#define MOD_POLICYDB_VERSION_MAX MOD_POLICYDB_VERSION_POLCAP +#define MOD_POLICYDB_VERSION_MAX MOD_POLICYDB_VERSION_USERTRANS#define POLICYDB_CONFIG_MLS 1Index:
libsepol/src/policydb.c
===================================================================src/policydb.c +129
-1@@ -105,6 +105,12 @@ .ocon_num = OCON_NODE6 + 1, }, { + .type = POLICY_KERN, + .version = POLICYDB_VERSION_USERTRANS, + .sym_num = SYM_NUM, + .ocon_num = OCON_NODE6 + 1, + }, + { .type = POLICY_BASE, .version = MOD_POLICYDB_VERSION_BASE, .sym_num = SYM_NUM,@@ -129,6 +135,12 @@ .ocon_num = OCON_NODE6 + 1, }, { + .type = POLICY_BASE, + .version = MOD_POLICYDB_VERSION_USERTRANS, + .sym_num = SYM_NUM, + .ocon_num = OCON_NODE6 + 1, + }, + { .type = POLICY_MOD, .version = MOD_POLICYDB_VERSION_BASE, .sym_num = SYM_NUM,@@ -150,7 +162,14 @@ .type = POLICY_MOD, .version = MOD_POLICYDB_VERSION_POLCAP, .sym_num = SYM_NUM, - .ocon_num = 0}, + .ocon_num = 0 + }, + { + .type = POLICY_MOD, + .version = MOD_POLICYDB_VERSION_USERTRANS, + .sym_num = SYM_NUM, + .ocon_num =0 + }, };#if 0 @@ -348,6 +367,30 @@ } } +void user_trans_rule_init (user_trans_rule_t * x) +{ +memset (x,0 ,sizeof (*x)); +ebitmap_init (&x->users); +type_set_init (&x->types); +} + +void user_trans_rule_destroy (user_trans_rule_t * x) +{ +if (x !=NULL ) { +ebitmap_init (&x->users); +type_set_destroy (&x->types); + } +} + +void user_trans_rule_list_destroy (user_trans_rule_t * x) +{ +while (x !=NULL ) { +user_trans_rule_t *next = x->next; +user_trans_rule_destroy (x); +free (x); + x = next; + } +}void role_allow_rule_init (role_allow_rule_t * x) {memset (x,0 ,sizeof (role_allow_rule_t));@@ -985,6 +1028,7 @@unsigned int i;role_allow_t *ra, *lra =NULL ;role_trans_t *tr, *ltr =NULL ; +user_trans_t *ut, *lut =NULL ;range_trans_t *rt, *lrt =NULL ;if (!p)@@ -1058,6 +1102,14 @@if (ltr)free (ltr); +for (ut = p->user_tr; ut; ut = ut->next) { +if (lut) +free (lut); + lut = ut; + } +if (lut) +free (lut); +for (ra = p->role_allow; ra; ra = ra->next) {if (lra)free (lra);@@ -1983,6 +2035,40 @@return 0 ; } +int user_trans_read (user_trans_t ** t,struct policy_file *fp) +{ +unsigned int i; +uint32_t buf[3 ], nel; +user_trans_t *ut, *lut; +int rc; + + rc =next_entry (buf, fp,sizeof (uint32_t )); +if (rc <0 ) +return -1 ; + nel =le32_to_cpu (buf[0 ]); + lut =NULL ; +for (i =0 ; i < nel; i++) { + ut =calloc (1 ,sizeof (struct user_trans )); +if (!ut) { +return -1 ; + } +if (lut) { + lut->next = ut; + }else { + *t = ut; + } + rc =next_entry (buf, fp,sizeof (uint32_t ) *3 ); +if (rc <0 ) +return -1 ; + ut->user =le32_to_cpu (buf[0 ]); + ut->type =le32_to_cpu (buf[1 ]); + ut->new_user =le32_to_cpu (buf[2 ]); + lut = ut; + } +return 0 ; +} + +int role_allow_read (role_allow_t ** r,struct policy_file *fp) {unsigned int i;@@ -2679,6 +2765,48 @@return 0 ; } +static int user_trans_rule_read (user_trans_rule_t ** u,struct policy_file *fp) +{ +uint32_t buf[1 ], nel; +unsigned int i; +user_trans_rule_t *ut, *lut; +int rc; + + rc =next_entry (buf, fp,sizeof (uint32_t )); +if (rc <0 ) +return -1 ; + nel =le32_to_cpu (buf[0 ]); + lut =NULL ; +for (i =0 ; i < nel; i++) { + ut =malloc (sizeof (user_trans_rule_t)); +if (!ut) { +return -1 ; + } +user_trans_rule_init (ut); + +if (lut) { + lut->next = ut; + }else { + *u = ut; + } + +if (ebitmap_read (&ut->users, fp)) +return -1 ; + +if (type_set_read (&ut->types, fp)) +return -1 ; + + rc =next_entry (buf, fp,sizeof (uint32_t )); +if (rc <0 ) +return -1 ; + ut->new_user =le32_to_cpu (buf[0 ]); + lut = ut; + } + +return 0 ; +} + +static int
role_allow_rule_read(role_allow_rule_t ** r, struct policy_file *fp){ unsigned int i;src/policydb.c +10
-1@@ -2805,9 +2933,14 @@if (cond_read_list (p, &decl->cond_list, fp) ==-1 ||avrule_read_list (p, &decl->avrules, fp) ==-1 ||role_trans_rule_read (&decl->role_tr_rules, fp) ==-1 || -role_allow_rule_read (&decl->role_allow_rules, fp) ==-1 ) { +role_allow_rule_read (&decl->role_allow_rules, fp) ==-1 ) + {return -1 ; } +if (p->policyvers >=MOD_POLICYDB_VERSION_USERTRANS ) { +if (user_trans_rule_read (&decl->user_tr_rules, fp)) +return -1 ; + }if (p->policyvers >=MOD_POLICYDB_VERSION_RANGETRANS &&range_trans_rule_read (&decl->range_tr_rules, fp) ==-1 ) {return -1 ;@@ -3179,6 +3312,10 @@ goto bad;if (role_trans_read (&p->role_tr, fp)) goto bad; +if (r_policyvers >=POLICYDB_VERSION_USERTRANS ) { +if (user_trans_read (&p->user_tr, fp)) + goto bad; + }if (role_allow_read (&p->role_allow, fp)) goto bad; }else {Index:
libsepol/src/expand.c
===================================================================src/expand.c +74
-0@@ -1060,6 +1060,80 @@return 0 ; } +static int copy_user_trans (expand_state_t * state,user_trans_rule_t * rules) +{ +unsigned int i, j; +user_trans_t *n, *l, *cur_trans; +user_trans_rule_t *cur; +ebitmap_t types; +ebitmap_node_t *rnode, *tnode; + +/* start at the end of the list */ +for (l = state->out->user_tr; l && l->next; l = l->next) ; + + cur = rules; +while (cur) { +ebitmap_init (&types); + +if (expand_convert_type_set + (state->out, state->typemap, &cur->types, &types,1 )) { +ERR (state->handle,"Out of memory!" ); +return -1 ; + } +ebitmap_for_each_bit (&cur->users, rnode, i) { +if (!ebitmap_node_get_bit (rnode, i)) +continue ; +ebitmap_for_each_bit (&types, tnode, j) { +if (!ebitmap_node_get_bit (tnode, j)) +continue ; + + cur_trans = state->out->user_tr; +while (cur_trans) { +if ((cur_trans->user == i +1 ) && + (cur_trans->type == j +1 )) { +if (cur_trans->new_user == + cur->new_user) { +break ; + }else { +ERR (state->handle, +"Conflicting user trans rule %s %s : %s" , + state->out->p_user_val_to_name[i], + state->out->p_type_val_to_name[j], + state->out->p_user_val_to_name[cur->new_user -1 ]); +return -1 ; + } + } + cur_trans = cur_trans->next; + } +if (cur_trans) +continue ; + + n = (user_trans_t *) +malloc (sizeof (user_trans_t)); +if (!n) { +ERR (state->handle,"Out of memory!" ); +return -1 ; + } +memset (n,0 ,sizeof (user_trans_t)); + n->user = i +1 ; + n->type = j +1 ; + n->new_user = cur->new_user; +if (l) { + l->next = n; + }else { + state->out->user_tr = n; + } + l = n; + } + } + +ebitmap_destroy (&types); + + cur = cur->next; + } +return 0 ; +} +static int exp_rangetr_helper(uint32_t stype,
uint32_tttype,uint32_ttclass,
mls_semantic_range_t* trange,expand_state_t* state)src/expand.c +3
-0@@ -2163,6 +2237,9 @@ goto cleanup; } +if (copy_user_trans (state, decl->user_tr_rules)) + goto cleanup; +/* expand the range transition rules */ if (expand_range_trans (state, decl->range_tr_rules)) goto cleanup;Index:
libsepol/src/write.c
===================================================================src/write.c +51
-0@@ -487,6 +487,31 @@return POLICYDB_SUCCESS ; } +static int user_trans_write (user_trans_t * u,struct policy_file *fp) +{ +user_trans_t *tr; +uint32_t buf[3 ]; +size_t nel, items; + + nel =0 ; +for (tr = u; tr; tr = tr->next) + nel++; + buf[0 ] =cpu_to_le32 (nel); + items =put_entry (buf,sizeof (uint32_t ),1 , fp); +if (items !=1 ) +return POLICYDB_ERROR ; +for (tr = u; tr; tr = tr->next) { + buf[0 ] =cpu_to_le32 (tr->user); + buf[1 ] =cpu_to_le32 (tr->type); + buf[2 ] =cpu_to_le32 (tr->new_user); + items =put_entry (buf,sizeof (uint32_t ),3 , fp); +if (items !=3 ) +return POLICYDB_ERROR ; + } + +return POLICYDB_SUCCESS ; +} +static int role_allow_write (role_allow_t * r,struct policy_file *fp) {role_allow_t *ra;@@ -1325,6 +1350,32 @@return POLICYDB_SUCCESS ; } +static int user_trans_rule_write (user_trans_rule_t * t,struct policy_file *fp) +{ +int nel =0 ; +size_t items; +uint32_t buf[1 ]; +user_trans_rule_t *tr; + +for (tr = t; tr; tr = tr->next) + nel++; + buf[0 ] =cpu_to_le32 (nel); + items =put_entry (buf,sizeof (uint32_t ),1 , fp); +if (items !=1 ) +return POLICYDB_ERROR ; +for (tr = t; tr; tr = tr->next) { +if (ebitmap_write (&tr->users, fp)) +return POLICYDB_ERROR ; +if (type_set_write (&tr->types, fp)) +return POLICYDB_ERROR ; + buf[0 ] =cpu_to_le32 (tr->new_user); + items =put_entry (buf,sizeof (uint32_t ),1 , fp); +if (items !=1 ) +return POLICYDB_ERROR ; + } +return POLICYDB_SUCCESS ; +} +static int
role_allow_rule_write(role_allow_rule_t * r, struct policy_file *fp){ int nel = 0;src/write.c +8
-0@@ -1414,6 +1465,10 @@ role_allow_rule_write(decl->role_allow_rules, fp) == -1) {return POLICYDB_ERROR ; } +if (p->policyvers >=MOD_POLICYDB_VERSION_USERTRANS ) { +if (user_trans_rule_write (decl->user_tr_rules, fp)) +return POLICYDB_ERROR ; + }if (p->policyvers >=MOD_POLICYDB_VERSION_RANGETRANS &&range_trans_rule_write (decl->range_tr_rules, fp) ==-1 ) {return POLICYDB_ERROR ;@@ -1642,6 +1697,10 @@ }if (role_trans_write (p->role_tr, fp))return POLICYDB_ERROR ; +if (p->policyvers >=POLICYDB_VERSION_USERTRANS ) { +if (user_trans_write (p->user_tr, fp)) +return POLICYDB_ERROR ; + }if (role_allow_write (p->role_allow, fp))return POLICYDB_ERROR ; }else {Index:
libsepol/src/link.c
===================================================================src/link.c +28
-0@@ -848,6 +848,34 @@return -1 ; } +static int user_bitmap_or_convert (ebitmap_t * users,ebitmap_t * dst, +policy_module_t * mod,link_state_t * state) +{ +unsigned int i; +ebitmap_t tmp; +ebitmap_node_t *rnode; + +ebitmap_init (&tmp); +ebitmap_for_each_bit (users, rnode, i) { +if (ebitmap_node_get_bit (rnode, i)) { +assert (mod->map[SYM_USERS ][i]); +if (ebitmap_set_bit + (&tmp, mod->map[SYM_USERS ][i] -1 ,1 )) { + goto cleanup; + } + } + } +if (ebitmap_union (dst, &tmp)) { + goto cleanup; + } +ebitmap_destroy (&tmp); +return 0 ; + cleanup: +ERR (state->handle,"Out of memory!" ); +ebitmap_destroy (&tmp); +return -1 ; +} +static int mls_level_convert (mls_semantic_level_t * src,mls_semantic_level_t * dst,policy_module_t * mod,link_state_t * state){
src/link.c +24
-1@@ -1004,13 +1032,22 @@link_state_t *state = (link_state_t *) data;policy_module_t *mod = state->cur;symtab_t *usertab; +scope_datum_t *scope; user = (user_datum_t *) datum; + scope =hashtab_search (state->cur->policy->p_users_scope.table, key); +assert (scope); +if (scope->scope ==SCOPE_REQ ) { +//this is required user, no role or mls data +return 0 ; + } +if (state->dest_decl ==NULL ) usertab = &state->base->p_users; -else +else { usertab = &state->dest_decl->p_users; + } new_user =hashtab_search (usertab->table, id);assert (new_user !=NULL );@@ -1173,6 +1210,49 @@return -1 ; } +static int copy_user_trans_list (user_trans_rule_t * list, +user_trans_rule_t ** dst, +policy_module_t * module,link_state_t * state) +{ +user_trans_rule_t *cur, *new_rule =NULL , *tail; + + cur = list; + tail = *dst; +while (tail && tail->next) { + tail = tail->next; + } +while (cur) { + if ((new_rule = + (user_trans_rule_t *)malloc(sizeof(user_trans_rule_t))) ==
src/link.c +6
-0+ NULL) { + goto cleanup; + } +user_trans_rule_init (new_rule); + + if (user_bitmap_or_convert(&cur->users,
&new_rule->users, module, state))src/link.c +6
-0+ goto cleanup; +if (type_set_or_convert (&cur->types, &new_rule->types, module, state)) { + goto cleanup; + } + + new_rule->new_user =module->map[SYM_USERS][cur->new_user - 1];
src/link.c +17
-0+ +if (*dst ==NULL ) { + *dst = new_rule; + }else { + tail->next = new_rule; + } + tail = new_rule; + cur = cur->next; + } +return 0 ; + cleanup: +ERR (state->handle,"Out of memory!" ); +user_trans_rule_list_destroy (new_rule); +return -1 ; +} + +static int copy_role_allow_list(role_allow_rule_t * list,
role_allow_rule_t** dst,policy_module_t* module,link_state_t* state)src/link.c +4
-0@@ -1446,6 +1526,10 @@return -1 ; } +if (copy_user_trans_list (src_decl->user_tr_rules, &dest_decl->user_tr_rules, + module, state)) +return -1 ; +if (copy_range_trans_list (src_decl->range_tr_rules, &dest_decl->range_tr_rules, module, state))return -1;Index:
checkpolicy/test/dismod.c
===================================================================test/dismod.c +34
-1@@ -354,6 +354,21 @@return 0 ; } +int display_user_set (ebitmap_t *u,policydb_t *p,FILE *fp) +{ +ebitmap_node_t *node; +int i; + +fprintf (fp," { " ); +ebitmap_for_each_bit (u, node, i) { +if (ebitmap_node_get_bit (node, i)) { +display_id (p, fp,SYM_USERS , i,"" ); + } + } +fprintf (fp," } " ); +return 0 ; +} +int display_bools (policydb_t * p,FILE * fp) {int i;@@ -461,7 +476,18 @@fprintf (fp,"\n" ); } } +void display_user_trans (user_trans_rule_t * tr,policydb_t * p,FILE * fp) +{ +for (; tr; tr = tr->next) { +fprintf (fp,"user transition " ); +display_user_set (&tr->users, p, fp); +display_type_set (&tr->types,0 , p, fp); +display_id (p, fp,SYM_USERS , tr->new_user -1 ," :" ); +fprintf (fp,"\n" ); + } +} +void display_role_allow (role_allow_rule_t * ra,policydb_t * p,FILE * fp) {for (; ra; ra = ra->next) {@@ -641,6 +667,10 @@ }break ; } +case 7 :{ +display_user_trans (decl->user_tr_rules, policy, out_fp); +break ; + }default :{assert (0 ); }@@ -806,6 +836,7 @@printf ("c) Display policy capabilities\n" );printf ("l) Link in a module\n" );printf ("u) Display the unknown handling setting\n" ); +printf ("U) Display user transitions\n" );printf ("\n" );printf ("f) set output file\n" );printf ("m) display menu\n" );@@ -918,9 +949,11 @@display_policycaps (&policydb, out_fp);break ;case 'u' : -case 'U' :display_handle_unknown (&policydb, out_fp);break ; +case 'U' : +display_avblock (7 ,0 , &policydb, out_fp); +break ;case 'f' :printf ("\nFilename for output (<CR> for screen output): " );Index:
checkpolicy/test/dispol.c
===================================================================test/dispol.c +16
-1@@ -299,6 +299,18 @@return 0 ; } +static void display_user_transitions (policydb_t *p,FILE *fp) +{ +user_trans_t *cur; +for (cur = p->user_tr; cur; cur = cur->next) { +fprintf (fp,"user_transition " ); +fprintf (fp,"%s %s %s;\n" , + p->p_user_val_to_name[cur->user -1 ], + p->p_type_val_to_name[cur->type -1 ], + p->p_user_val_to_name[cur->new_user -1 ]); + } +} +static void display_policycaps (policydb_t * p,FILE * fp) {ebitmap_node_t *node;@@ -332,6 +344,7 @@printf ("\n" );printf ("c) display policy capabilities\n" );printf ("u) display unknown handling setting\n" ); +printf ("U) display user transitions\n" );printf ("f) set output file\n" );printf ("m) display menu\n" );printf ("q) quit\n" );@@ -448,9 +461,11 @@display_policycaps (&policydb, out_fp);break ;case 'u' : -case 'U' :display_handle_unknown (&policydb, out_fp);break ; +case 'U' : +display_user_transitions (&policydb, out_fp); +break ;case 'f' :printf ("\nFilename for output (<CR> for screen output): " );Index: checkpolicy/test/Makefile
===================================================================test/Makefile +0
-0@@ -6,7 +6,7 @@LIBDIR=$(PREFIX)/lib
INCLUDEDIR ?= $(PREFIX)/includetest/Makefile +1
-1-CFLAGS ?= -g -Wall -O2 -pipe +CFLAGS ?= -g3 -gdwarf-2 -Wall -O0 -pipeoverride CFLAGS += -I$(INCLUDEDIR)
LDLIBS=-lfl -lsepol -lselinux $(LIBDIR)/libsepol.a -L$(LIBDIR)
Index:checkpolicy/policy_define.c
===================================================================policy_define.c +70
-0@@ -2020,6 +2020,76 @@return -1 ; } +int define_user_trans (void ) +{ +char *id; +user_datum_t *user, *u; +ebitmap_t users; +type_set_t types; +struct user_trans_rule *rule =NULL ; +int add =1 ; + +if (pass ==1 ) { +while ((id =queue_remove (id_queue))) +free (id); +while ((id =queue_remove (id_queue))) +free (id); + id =queue_remove (id_queue); +free (id); +return 0 ; + } + +ebitmap_init (&users); +type_set_init (&types); + +while ((id =queue_remove (id_queue))) { + u =hashtab_search (policydbp->p_users.table, id); +if (!u) { +yyerror2 ("unknown user %s" , id); +free (id); +return -1 ; + } +if (ebitmap_set_bit (&users, u->s.value -1 , TRUE)) +return -1 ; + } +while ((id =queue_remove (id_queue))) { +if (set_types (&types, id, &add,0 )) +return -1 ; + } + id = (char *)queue_remove (id_queue); +if (!id) { +yyerror ("no new user in transition definition?" ); + goto bad; + } +if (!is_id_in_scope (SYM_USERS , id)) { +yyerror2 ("user %s is not within scope" , id); +free (id); + goto bad; + } + user =hashtab_search (policydbp->p_users.table, id); +if (!user) { +yyerror2 ("unknown user %s used in transition definition" , id); + goto bad; + } + rule =malloc (sizeof (struct user_trans_rule )); +if (!rule) { +yyerror ("out of memory" ); +return -1 ; + } +memset (rule,0 ,sizeof (struct user_trans_rule )); + rule->users = users; + rule->types = types; + rule->new_user = user->s.value; + +append_user_trans (rule); + +return 0 ; + + bad: +return -1 ; +} + +int define_role_allow (void ) {char *id;Index: checkpolicy/policy_scan.l
===================================================================policy_scan.l +0
-0@@ -102,6 +102,8 @@ type_change { return(TYPE_CHANGE); }
ROLE_TRANSITION|role_transition{return(ROLE_TRANSITION); }policy_scan.l +2
-0+USER_TRANSITION | +user_transition { return(USER_TRANSITION); }
RANGE_TRANSITION|range_transition{return(RANGE_TRANSITION); }
SENSITIVITY |
Index:checkpolicy/policy_define.h
===================================================================policy_define.h +1
-0@@ -42,6 +42,7 @@int define_role_allow (void );int define_role_trans (void );int define_role_types (void ); +int define_user_trans (void );int define_sens (void );int define_te_avtab (int which);int define_typealias (void );Index:
checkpolicy/module_compiler.c
===================================================================module_compiler.c +11
-0@@ -1214,6 +1214,17 @@ decl->role_tr_rules = role_tr_rules; } +void append_user_trans (user_trans_rule_t * user_tr_rules) +{ +avrule_decl_t *decl = stack_top->decl; + +/* role transitions are not allowed within conditionals */ +assert (stack_top->type ==1 ); + + user_tr_rules->next = decl->user_tr_rules; + decl->user_tr_rules = user_tr_rules; +} +/* this doesn't actually append, but really prepends it */ void append_role_allow (role_allow_rule_t * role_allow_rules) {Index: checkpolicy/policy_parse.y
===================================================================policy_parse.y +0
-0@@ -103,6 +103,7 @@%token
TYPE_MEMBER
%tokenTYPE_CHANGE
%tokenROLE_TRANSITION
+%tokenUSER_TRANSITION
%tokenRANGE_TRANSITION
%token SENSITIVITY
%token DOMINANCEpolicy_parse.y +1
-0@@ -261,6 +262,7 @@ | transition_def | range_trans_def | te_avtab_def + | user_trans_def ;
attribute_def: ATTRIBUTE identifier ';'{ if (define_attrib()) return -1;}policy_parse.y +0
-0@@ -411,6 +413,9 @@
role_trans_def:ROLE_TRANSITIONnames names identifier ';'{if (define_role_trans()) return -1; } ;policy_parse.y +3
-0+user_trans_def : USER_TRANSITION names names identifier ';' + { if (define_user_trans()) return -1; } + ;
role_allow_def: ALLOW names names ';'{if (define_role_allow()) return -1; } ;Index:
checkpolicy/module_compiler.h
===================================================================module_compiler.h +1
-0@@ -80,6 +80,7 @@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); +void append_user_trans (user_trans_rule_t * user_tr_rules);/* Create a new optional block and add it to the global policy. * During the second pass resolve the block's requirements. Return 0
Signature · 8 lines
Stephen Smalley National Security Agency -- This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
Quoted 38 lines · Stephen Smalley
Quoted 6 lines · Joshua Brindle
This implements
user_transitionin the toolchain. It should help on distro's like Ubuntu that can't userun_initdue to the user not knowing the root password. It also seems like a more eloquent way to handle service restarts than assigningsystem_rto user accounts and having the daemons run as someuser:system_r:foo_t.Yes, that's something that has been wanted in Fedora for quite some time.
The real issue with
run_initisn't the re-authentication stage, as that can always be disabled via pam config (and was just a weak form of confirming user intent, not an authorization mechanism), but rather the difficulty in transparently interposing it into all situations where services get started/re-started. Only Gentoo seemed to have a good story there.Quoted 4 lines
This has some issues in policy due to users not always being known in the policy (eg., semanage users). I hope Chris or Dan will be able to give some suggestions there.
I'm not sure why anyone needs to add users to policy via semanage users given the base set of generic users and the ability to map Linux users to them via seusers aka semanage login.
Quoted 7 lines
The kernel patch (forthcoming after this is accepted) so far only implements the transition on process transitions. Later on I plan on doing a patch to expand
role_transitionto object classes (this is a change needed for policy rbac support to work). I suspect I'll do the same for user at that time. The question here is, do we think its worth it to do fine grained transitions like we did forrange_trans? (I don't).
Quoted 8 lines
Offhand, I can't see a use for per-class user transitions, if that is what you mean.
I don't think per-class role transitions is really the fundamental obstacle to enabling use of roles on objects - more thought is required there. What will be fun there is role/type and user/range validation, which presently gets to ignore everything that has
object_r.
Ah, another thing. While going through the policyrep implementation the question of object_r came up. My thought is to start adding object_r magic into the toolchain (adding all types, etc) and eventually purge object_r from the kernel. at least one magic instance of object_r will be removed by object role_transitions, the others are really short circuits in the security server that can be removed after sufficient support is in the toolchain. What are your thoughts on that (for future reference)?
--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
Quoted 48 lines · Joshua Brindle
Quoted 38 lines · Stephen Smalley
Quoted 6 lines · Joshua Brindle
This implements
user_transitionin the toolchain. It should help on distro's like Ubuntu that can't userun_initdue to the user not knowing the root password. It also seems like a more eloquent way to handle service restarts than assigningsystem_rto user accounts and having the daemons run as someuser:system_r:foo_t.Yes, that's something that has been wanted in Fedora for quite some time.
The real issue with
run_initisn't the re-authentication stage, as that can always be disabled via pam config (and was just a weak form of confirming user intent, not an authorization mechanism), but rather the difficulty in transparently interposing it into all situations where services get started/re-started. Only Gentoo seemed to have a good story there.Quoted 4 lines
This has some issues in policy due to users not always being known in the policy (eg., semanage users). I hope Chris or Dan will be able to give some suggestions there.
I'm not sure why anyone needs to add users to policy via semanage users given the base set of generic users and the ability to map Linux users to them via seusers aka semanage login.
Quoted 7 lines
The kernel patch (forthcoming after this is accepted) so far only implements the transition on process transitions. Later on I plan on doing a patch to expand
role_transitionto object classes (this is a change needed for policy rbac support to work). I suspect I'll do the same for user at that time. The question here is, do we think its worth it to do fine grained transitions like we did forrange_trans? (I don't).Quoted 8 lines
Offhand, I can't see a use for per-class user transitions, if that is what you mean.
I don't think per-class role transitions is really the fundamental obstacle to enabling use of roles on objects - more thought is required there. What will be fun there is role/type and user/range validation, which presently gets to ignore everything that has
object_r.
Quoted 8 lines
Ah, another thing. While going through the policyrep implementation the question of
object_rcame up. My thought is to start addingobject_rmagic into the toolchain (adding all types, etc) and eventually purgeobject_rfrom the kernel. at least one magic instance ofobject_rwill be removed by objectrole_transitions, the others are really short circuits in the security server that can be removed after sufficient support is in the toolchain. What are your thoughts on that (for future reference)?
Well, the interesting question is what should the default role be in the new context in security_compute_sid, if not object_r. Even aside from the support for per-class role transitions. User defaults to the source context, type defaults to the related object context, and MLS range defaults to the low level of the source context. Role could be the subject's role or the related object's role.
Signature · 8 lines
Stephen Smalley National Security Agency -- This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
Quoted 57 lines · Stephen Smalley
Quoted 46 lines · Joshua Brindle
Quoted 44 lines · Stephen Smalley
Quoted 7 lines · Joshua Brindle
This implements
user_transitionin the toolchain. It should help on distro's like Ubuntu that can't userun_initdue to the user not knowing the root password. It also seems like a more eloquent way to handle service restarts than assigningsystem_rto user accounts and having the daemons run as someuser:system_r:foo_t.Yes, that's something that has been wanted in Fedora for quite some time.
The real issue with
run_initisn't the re-authentication stage, as that can always be disabled via pam config (and was just a weak form of confirming user intent, not an authorization mechanism), but rather the difficulty in transparently interposing it into all situations where services get started/re-started. Only Gentoo seemed to have a good story there.Quoted 5 lines
This has some issues in policy due to users not always being known in the policy (eg., semanage users). I hope Chris or Dan will be able to give some suggestions there.
I'm not sure why anyone needs to add users to policy via semanage users given the base set of generic users and the ability to map Linux users to them via seusers aka semanage login.
Quoted 8 lines
The kernel patch (forthcoming after this is accepted) so far only implements the transition on process transitions. Later on I plan on doing a patch to expand
role_transitionto object classes (this is a change needed for policy rbac support to work). I suspect I'll do the same for user at that time. The question here is, do we think its worth it to do fine grained transitions like we did forrange_trans? (I don't).Offhand, I can't see a use for per-class user transitions, if that is what you mean.
Quoted 8 lines
Quoted 6 lines
I don't think per-class role transitions is really the fundamental obstacle to enabling use of roles on objects - more thought is required there. What will be fun there is role/type and user/range validation, which presently gets to ignore everything that has
object_r.Ah, another thing. While going through the policyrep implementation the question of
object_rcame up. My thought is to start addingobject_rmagic into the toolchain (adding all types, etc) and eventually purgeobject_rfrom the kernel. at least one magic instance ofobject_rwill be removed by objectrole_transitions, the others are really short circuits in the security server that can be removed after sufficient support is in the toolchain. What are your thoughts on that (for future reference)?
Quoted 8 lines
Well, the interesting question is what should the default role be in the new context in
security_compute_sid, if notobject_r. Even aside from the support for per-class role transitions. User defaults to the source context, type defaults to the related object context, and MLS range defaults to the low level of the source context. Role could be the subject's role or the related object's role.
Good question. My original assumption was that we'd use the related object role. That would require that home directories be correctly labeled with the role of the user. If we start using the source role then things will quickly change from object_r to system_r, so maybe the policy should do that anyway. Chris, any opinions on this?
--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
Quoted 74 lines · Joshua Brindle
Quoted 64 lines · Stephen Smalley
Quoted 52 lines · Joshua Brindle
Quoted 41 lines · Stephen Smalley
Quoted 7 lines · Joshua Brindle
This implements
user_transitionin the toolchain. It should help on distro's like Ubuntu that can't userun_initdue to the user not knowing the root password. It also seems like a more eloquent way to handle service restarts than assigningsystem_rto user accounts and having the daemons run as someuser:system_r:foo_t.Yes, that's something that has been wanted in Fedora for quite some time.
The real issue with
run_initisn't the re-authentication stage, as that can always be disabled via pam config (and was just a weak form of confirming user intent, not an authorization mechanism), but rather the difficulty in transparently interposing it into all situations where services get started/re-started. Only Gentoo seemed to have a good story there.Quoted 5 lines
This has some issues in policy due to users not always being known in the policy (eg., semanage users). I hope Chris or Dan will be able to give some suggestions there.
I'm not sure why anyone needs to add users to policy via semanage users given the base set of generic users and the ability to map Linux users to them via seusers aka semanage login.
Quoted 8 lines
The kernel patch (forthcoming after this is accepted) so far only implements the transition on process transitions. Later on I plan on doing a patch to expand
role_transitionto object classes (this is a change needed for policy rbac support to work). I suspect I'll do the same for user at that time. The question here is, do we think its worth it to do fine grained transitions like we did forrange_trans? (I don't).Quoted 9 lines
Offhand, I can't see a use for per-class user transitions, if that is what you mean.
I don't think per-class role transitions is really the fundamental obstacle to enabling use of roles on objects - more thought is required there. What will be fun there is role/type and user/range validation, which presently gets to ignore everything that has
object_r.Quoted 9 lines
Ah, another thing. While going through the policyrep implementation the question of
object_rcame up. My thought is to start addingobject_rmagic into the toolchain (adding all types, etc) and eventually purgeobject_rfrom the kernel. at least one magic instance ofobject_rwill be removed by objectrole_transitions, the others are really short circuits in the security server that can be removed after sufficient support is in the toolchain. What are your thoughts on that (for future reference)?Quoted 8 lines
Well, the interesting question is what should the default role be in the new context in
security_compute_sid, if notobject_r. Even aside from the support for per-class role transitions. User defaults to the source context, type defaults to the related object context, and MLS range defaults to the low level of the source context. Role could be the subject's role or the related object's role.
Quoted 5 lines
Good question. My original assumption was that we'd use the related object role. That would require that home directories be correctly labeled with the role of the user. If we start using the source role then things will quickly change from
object_rtosystem_r, so maybe the policy should do that anyway. Chris, any opinions on this?
Yes, related object role would likely cause the least breakage. It would preserve the existing default for existing filesystems (as they already have object_r in the directory contexts), while allowing us to switch over to the user's role for home directories upon a relabel or new filesystem. Source role might create more conflicts, as we enforce the role/type relationship for contexts and there might be a mismatch between the creating process role and the parent directory type.
Signature · 8 lines
Stephen Smalley National Security Agency -- This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
Quoted 29 lines · Stephen Smalley
Quoted 22 lines · Joshua Brindle
Quoted 12 lines · Stephen Smalley
Quoted 9 lines · Joshua Brindle
Ah, another thing. While going through the policyrep implementation the question of
object_rcame up. My thought is to start addingobject_rmagic into the toolchain (adding all types, etc) and eventually purgeobject_rfrom the kernel. at least one magic instance ofobject_rwill be removed by objectrole_transitions, the others are really short circuits in the security server that can be removed after sufficient support is in the toolchain. What are your thoughts on that (for future reference)?Quoted 8 lines
Well, the interesting question is what should the default role be in the new context in
security_compute_sid, if notobject_r. Even aside from the support for per-class role transitions. User defaults to the source context, type defaults to the related object context, and MLS range defaults to the low level of the source context. Role could be the subject's role or the related object's role.Quoted 5 lines
Good question. My original assumption was that we'd use the related object role. That would require that home directories be correctly labeled with the role of the user. If we start using the source role then things will quickly change from
object_rtosystem_r, so maybe the policy should do that anyway. Chris, any opinions on this?
Quoted 7 lines
Yes, related object role would likely cause the least breakage. It would preserve the existing default for existing filesystems (as they already have
object_rin the directory contexts), while allowing us to switch over to the user's role for home directories upon a relabel or new filesystem. Source role might create more conflicts, as we enforce the role/type relationship for contexts and there might be a mismatch between the creating process role and the parent directory type.
Using the related object role seems right to me too.
Signature · 10 lines
Chris PeBenito Tresys Technology, LLC (410) 290-1411 x150 -- This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
Quoted 33 lines · Christopher J. PeBenito
Quoted 22 lines · Stephen Smalley
Quoted 18 lines · Joshua Brindle
Quoted 7 lines · Stephen Smalley
Quoted 3 lines · Joshua Brindle
Ah, another thing. While going through the policyrep implementation the question of
object_rcame up. My thought is to start addingobject_rmagic into the toolchain (adding all types, etc) and eventually purgeobject_rfrom the kernel. at least one magic instance ofobject_rwill be removed by objectrole_transitions, the others are really short circuits in the security server that can be removed after sufficient support is in the toolchain. What are your thoughts on that (for future reference)?Quoted 9 lines
Well, the interesting question is what should the default role be in the new context in
security_compute_sid, if notobject_r. Even aside from the support for per-class role transitions. User defaults to the source context, type defaults to the related object context, and MLS range defaults to the low level of the source context. Role could be the subject's role or the related object's role.Quoted 2 lines
Good question. My original assumption was that we'd use the related object role. That would require that home directories be correctly labeled with the role of the user. If we start using the source role then things will quickly change from
object_rtosystem_r, so maybe the policy should do that anyway. Chris, any opinions on this?Quoted 8 lines
Yes, related object role would likely cause the least breakage. It would preserve the existing default for existing filesystems (as they already have
object_rin the directory contexts), while allowing us to switch over to the user's role for home directories upon a relabel or new filesystem. Source role might create more conflicts, as we enforce the role/type relationship for contexts and there might be a mismatch between the creating process role and the parent directory type.
Quoted 2 lines
Using the related object role seems right to me too.
The inconsistency of handling parts of the context is a little troubling to me, half the context will be coming from the source and half from the object container. If this doesn't bother anyone else I suppose I'll try to ignore that OCD'ism of mine but I love it when the models we support work pretty seamlessly together and this seems like artifacts of them not doing that.
--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
Quoted 48 lines · Joshua Brindle
Quoted 44 lines · Christopher J. PeBenito
Quoted 33 lines · Stephen Smalley
Quoted 25 lines · Joshua Brindle
Quoted 14 lines · Stephen Smalley
Quoted 10 lines · Joshua Brindle
Ah, another thing. While going through the policyrep implementation the question of
object_rcame up. My thought is to start addingobject_rmagic into the toolchain (adding all types, etc) and eventually purgeobject_rfrom the kernel. at least one magic instance ofobject_rwill be removed by objectrole_transitions, the others are really short circuits in the security server that can be removed after sufficient support is in the toolchain. What are your thoughts on that (for future reference)?Quoted 9 lines
Well, the interesting question is what should the default role be in the new context in
security_compute_sid, if notobject_r. Even aside from the support for per-class role transitions. User defaults to the source context, type defaults to the related object context, and MLS range defaults to the low level of the source context. Role could be the subject's role or the related object's role.Quoted 6 lines
Good question. My original assumption was that we'd use the related object role. That would require that home directories be correctly labeled with the role of the user. If we start using the source role then things will quickly change from
object_rtosystem_r, so maybe the policy should do that anyway. Chris, any opinions on this?Quoted 8 lines
Yes, related object role would likely cause the least breakage. It would preserve the existing default for existing filesystems (as they already have
object_rin the directory contexts), while allowing us to switch over to the user's role for home directories upon a relabel or new filesystem. Source role might create more conflicts, as we enforce the role/type relationship for contexts and there might be a mismatch between the creating process role and the parent directory type.Quoted 2 lines
Using the related object role seems right to me too.
Quoted 6 lines
The inconsistency of handling parts of the context is a little troubling to me, half the context will be coming from the source and half from the object container. If this doesn't bother anyone else I suppose I'll try to ignore that OCD'ism of mine but I love it when the models we support work pretty seamlessly together and this seems like artifacts of them not doing that.
It's a logical consequence of the individual models, which are indeed different. I don't believe we can or want to make them all the same.
One thing that has come up previously though is that it would be convenient if we could specify the default inheritance behaviors in the policy configuration itself.
Signature · 8 lines
Stephen Smalley National Security Agency -- This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Quoted 79 lines · Stephen Smalley
Quoted 72 lines · Joshua Brindle
Quoted 63 lines · Stephen Smalley
Quoted 52 lines · Joshua Brindle
Quoted 41 lines · Stephen Smalley
Quoted 7 lines · Joshua Brindle
This implements
user_transitionin the toolchain. It should help on distro's like Ubuntu that can't userun_initdue to the user not knowing the root password. It also seems like a more eloquent way to handle service restarts than assigningsystem_rto user accounts and having the daemons run as someuser:system_r:foo_t.Yes, that's something that has been wanted in Fedora for quite some time.
The real issue with
run_initisn't the re-authentication stage, as that can always be disabled via pam config (and was just a weak form of confirming user intent, not an authorization mechanism), but rather the difficulty in transparently interposing it into all situations where services get started/re-started. Only Gentoo seemed to have a good story there.Quoted 5 lines
This has some issues in policy due to users not always being known in the policy (eg., semanage users). I hope Chris or Dan will be able to give some suggestions there.
I'm not sure why anyone needs to add users to policy via semanage users given the base set of generic users and the ability to map Linux users to them via seusers aka semanage login.
Quoted 8 lines
The kernel patch (forthcoming after this is accepted) so far only implements the transition on process transitions. Later on I plan on doing a patch to expand
role_transitionto object classes (this is a change needed for policy rbac support to work). I suspect I'll do the same for user at that time. The question here is, do we think its worth it to do fine grained transitions like we did forrange_trans? (I don't).Quoted 9 lines
Offhand, I can't see a use for per-class user transitions, if that is what you mean.
I don't think per-class role transitions is really the fundamental obstacle to enabling use of roles on objects - more thought is required there. What will be fun there is role/type and user/range validation, which presently gets to ignore everything that has
object_r.Quoted 9 lines
Ah, another thing. While going through the policyrep implementation the question of
object_rcame up. My thought is to start addingobject_rmagic into the toolchain (adding all types, etc) and eventually purgeobject_rfrom the kernel. at least one magic instance ofobject_rwill be removed by objectrole_transitions, the others are really short circuits in the security server that can be removed after sufficient support is in the toolchain. What are your thoughts on that (for future reference)?Quoted 8 lines
Well, the interesting question is what should the default role be in the new context in
security_compute_sid, if notobject_r. Even aside from the support for per-class role transitions. User defaults to the source context, type defaults to the related object context, and MLS range defaults to the low level of the source context. Role could be the subject's role or the related object's role.Quoted 5 lines
Good question. My original assumption was that we'd use the related object role. That would require that home directories be correctly labeled with the role of the user. If we start using the source role then things will quickly change from
object_rtosystem_r, so maybe the policy should do that anyway. Chris, any opinions on this?
Quoted 8 lines
Yes, related object role would likely cause the least breakage. It would preserve the existing default for existing filesystems (as they already have
object_rin the directory contexts), while allowing us to switch over to the user's role for home directories upon a relabel or new filesystem. Source role might create more conflicts, as we enforce the role/type relationship for contexts and there might be a mismatch between the creating process role and the parent directory type.
I am not sure where this is going, but I believe that separation based on role in the home directory is a mistake. It assumes that the home
directory will always be used by the same user with the same role. And
will not work when you have a network file system that supports labels.
In Red Hat I can login to people.redhat.com people.fedoraproject.com which I should use the guest_r. While logging into my laptop I would be unconfined_t and on test machines I might get staff_r or user_r. All of them would use the same homedirectory. So how would this work in this environment?
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.8 (GNU/Linux)
Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org
iEYEARECAAYFAkfqDU8ACgkQrlYvE4MpobPK2QCZARp10Z4BcqTHKGywNPo49F06 uJoAoLMYX3lHtyZkzDpS+BquTBFT4uoZ
=/URn
-----END PGP SIGNATURE-----
--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
Quoted 96 lines · Daniel J Walsh
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1Quoted 79 lines · Stephen Smalley
Quoted 72 lines · Joshua Brindle
Quoted 63 lines · Stephen Smalley
Quoted 52 lines · Joshua Brindle
Quoted 41 lines · Stephen Smalley
Quoted 7 lines · Joshua Brindle
This implements
user_transitionin the toolchain. It should help on distro's like Ubuntu that can't userun_initdue to the user not knowing the root password. It also seems like a more eloquent way to handle service restarts than assigningsystem_rto user accounts and having the daemons run as someuser:system_r:foo_t.Yes, that's something that has been wanted in Fedora for quite some time.
The real issue with
run_initisn't the re-authentication stage, as that can always be disabled via pam config (and was just a weak form of confirming user intent, not an authorization mechanism), but rather the difficulty in transparently interposing it into all situations where services get started/re-started. Only Gentoo seemed to have a good story there.Quoted 5 lines
This has some issues in policy due to users not always being known in the policy (eg., semanage users). I hope Chris or Dan will be able to give some suggestions there.
I'm not sure why anyone needs to add users to policy via semanage users given the base set of generic users and the ability to map Linux users to them via seusers aka semanage login.
Quoted 8 lines
The kernel patch (forthcoming after this is accepted) so far only implements the transition on process transitions. Later on I plan on doing a patch to expand
role_transitionto object classes (this is a change needed for policy rbac support to work). I suspect I'll do the same for user at that time. The question here is, do we think its worth it to do fine grained transitions like we did forrange_trans? (I don't).Quoted 9 lines
Offhand, I can't see a use for per-class user transitions, if that is what you mean.
I don't think per-class role transitions is really the fundamental obstacle to enabling use of roles on objects - more thought is required there. What will be fun there is role/type and user/range validation, which presently gets to ignore everything that has
object_r.Quoted 9 lines
Ah, another thing. While going through the policyrep implementation the question of
object_rcame up. My thought is to start addingobject_rmagic into the toolchain (adding all types, etc) and eventually purgeobject_rfrom the kernel. at least one magic instance ofobject_rwill be removed by objectrole_transitions, the others are really short circuits in the security server that can be removed after sufficient support is in the toolchain. What are your thoughts on that (for future reference)?Quoted 8 lines
Well, the interesting question is what should the default role be in the new context in
security_compute_sid, if notobject_r. Even aside from the support for per-class role transitions. User defaults to the source context, type defaults to the related object context, and MLS range defaults to the low level of the source context. Role could be the subject's role or the related object's role.Quoted 5 lines
Good question. My original assumption was that we'd use the related object role. That would require that home directories be correctly labeled with the role of the user. If we start using the source role then things will quickly change from
object_rtosystem_r, so maybe the policy should do that anyway. Chris, any opinions on this?Quoted 8 lines
Yes, related object role would likely cause the least breakage. It would preserve the existing default for existing filesystems (as they already have
object_rin the directory contexts), while allowing us to switch over to the user's role for home directories upon a relabel or new filesystem. Source role might create more conflicts, as we enforce the role/type relationship for contexts and there might be a mismatch between the creating process role and the parent directory type.I am not sure where this is going, but I believe that separation based on role in the home directory is a mistake. It assumes that the home
directory will always be used by the same user with the same role. And
will not work when you have a network file system that supports labels.
Quoted 5 lines
In Red Hat I can login to people.redhat.com people.fedoraproject.com which I should use the
guest_r. While logging into my laptop I would beunconfined_tand on test machines I might getstaff_roruser_r. All of them would use the same homedirectory. So how would this work in this environment?
That's an interesting question, and I know that in some operating systems, roles are actually separate user accounts altogether.
However, the mechanism being described here doesn't prevent you from continuing to use a generic role (object_r or otherwise) on all files; it just allows for people who want to apply distinct roles on files to do so.
Signature · 8 lines
Stephen Smalley National Security Agency -- This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Quoted 102 lines · Stephen Smalley
Quoted 95 lines · Daniel J Walsh
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1Quoted 78 lines · Stephen Smalley
Quoted 72 lines · Joshua Brindle
Quoted 63 lines · Stephen Smalley
Quoted 52 lines · Joshua Brindle
Quoted 41 lines · Stephen Smalley
Quoted 7 lines · Joshua Brindle
This implements
user_transitionin the toolchain. It should help on distro's like Ubuntu that can't userun_initdue to the user not knowing the root password. It also seems like a more eloquent way to handle service restarts than assigningsystem_rto user accounts and having the daemons run as someuser:system_r:foo_t.Yes, that's something that has been wanted in Fedora for quite some time.
The real issue with
run_initisn't the re-authentication stage, as that can always be disabled via pam config (and was just a weak form of confirming user intent, not an authorization mechanism), but rather the difficulty in transparently interposing it into all situations where services get started/re-started. Only Gentoo seemed to have a good story there.Quoted 5 lines
This has some issues in policy due to users not always being known in the policy (eg., semanage users). I hope Chris or Dan will be able to give some suggestions there.
I'm not sure why anyone needs to add users to policy via semanage users given the base set of generic users and the ability to map Linux users to them via seusers aka semanage login.
Quoted 8 lines
The kernel patch (forthcoming after this is accepted) so far only implements the transition on process transitions. Later on I plan on doing a patch to expand
role_transitionto object classes (this is a change needed for policy rbac support to work). I suspect I'll do the same for user at that time. The question here is, do we think its worth it to do fine grained transitions like we did forrange_trans? (I don't).Quoted 9 lines
Offhand, I can't see a use for per-class user transitions, if that is what you mean.
I don't think per-class role transitions is really the fundamental obstacle to enabling use of roles on objects - more thought is required there. What will be fun there is role/type and user/range validation, which presently gets to ignore everything that has
object_r.Quoted 9 lines
Ah, another thing. While going through the policyrep implementation the question of
object_rcame up. My thought is to start addingobject_rmagic into the toolchain (adding all types, etc) and eventually purgeobject_rfrom the kernel. at least one magic instance ofobject_rwill be removed by objectrole_transitions, the others are really short circuits in the security server that can be removed after sufficient support is in the toolchain. What are your thoughts on that (for future reference)?Quoted 8 lines
Well, the interesting question is what should the default role be in the new context in
security_compute_sid, if notobject_r. Even aside from the support for per-class role transitions. User defaults to the source context, type defaults to the related object context, and MLS range defaults to the low level of the source context. Role could be the subject's role or the related object's role.Quoted 5 lines
Good question. My original assumption was that we'd use the related object role. That would require that home directories be correctly labeled with the role of the user. If we start using the source role then things will quickly change from
object_rtosystem_r, so maybe the policy should do that anyway. Chris, any opinions on this?Quoted 8 lines
Yes, related object role would likely cause the least breakage. It would preserve the existing default for existing filesystems (as they already have
object_rin the directory contexts), while allowing us to switch over to the user's role for home directories upon a relabel or new filesystem. Source role might create more conflicts, as we enforce the role/type relationship for contexts and there might be a mismatch between the creating process role and the parent directory type.I am not sure where this is going, but I believe that separation based on role in the home directory is a mistake. It assumes that the home
directory will always be used by the same user with the same role. And
will not work when you have a network file system that supports labels.Quoted 5 lines
In Red Hat I can login to people.redhat.com people.fedoraproject.com which I should use the
guest_r. While logging into my laptop I would beunconfined_tand on test machines I might getstaff_roruser_r. All of them would use the same homedirectory. So how would this work in this environment?
Quoted 8 lines
That's an interesting question, and I know that in some operating systems, roles are actually separate user accounts altogether.
However, the mechanism being described here doesn't prevent you from continuing to use a generic role (
object_ror otherwise) on all files; it just allows for people who want to apply distinct roles on files to do so.
Well I guess I will be the first one to state that if this breaks the situation I stated above, I am not interested.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.8 (GNU/Linux)
Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org
iEYEARECAAYFAkfr+LYACgkQrlYvE4MpobOpRQCfSma66Z5JG6CV1bfAbd2xMJf8 MA4AoJbRYBB6coyQnnvIdH8kw0eE3Erq
=xtQ8
-----END PGP SIGNATURE-----
--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
Quoted 10 lines · Daniel J Walsh
I am not sure where this is going, but I believe that separation based on role in the home directory is a mistake. It assumes that the home directory will always be used by the same user with the same role. And will not work when you have a network file system that supports labels.
In Red Hat I can login to people.redhat.com people.fedoraproject.com which I should use the
guest_r. While logging into my laptop I would beunconfined_tand on test machines I might getstaff_roruser_r. All of them would use the same homedirectory. So how would this work in this environment?
If you have the same home directory contents (including .login, .bashrc, and equivalent files) and you can execute programs from the home directory, then how can you usefully have roles which are really different on different machines?
You could for example have guest_r on machine A mapping to sysadm_r on machine B (which I believe bears some similarity to the reclassification of documents when going between certain military organisations).
The idea of a network filesystem having the same labels on all machines where it is mounted even when there are differences in policy and/or user rights on those machines makes no sense to me.
Signature · 10 lines
[email protected] http://etbe.coker.com.au/ My Blog http://www.coker.com.au/sponsorship.html Sponsoring Free Software development -- This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Quoted 12 lines · Russell Coker
Quoted 10 lines · Daniel J Walsh
I am not sure where this is going, but I believe that separation based on role in the home directory is a mistake. It assumes that the home
directory will always be used by the same user with the same role. And
will not work when you have a network file system that supports labels.In Red Hat I can login to people.redhat.com people.fedoraproject.com which I should use the
guest_r. While logging into my laptop I would beunconfined_tand on test machines I might getstaff_roruser_r. All of them would use the same homedirectory. So how would this work in this environment?
Quoted 5 lines
If you have the same home directory contents (including .login, .bashrc, and equivalent files) and you can execute programs from the home directory, then how can you usefully have roles which are really different on different machines?
If I login to people.redhat.com I will log in as guest_t this type is not allowed to use the network, execute files in the home directory or run any setuid apps. If I as the guest_t user want to muck around with the .login file so that when I login to a different machine as unconfined_t, I don't see a problem. This is about defining roles and policy based on the machine you login to.
Quoted 4 lines
You could for example have
guest_ron machine A mapping tosysadm_ron machine B (which I believe bears some similarity to the reclassification of documents when going between certain military organisations).
This is not an MLS issue, and this does happen on MLS environments where they say the same user on one machine can get to Secret while on another machine he can get to TopSecret, I would surmise that bother users would have the same home dir, of course on the machine that is Secret he would not be able to access the top secret files.
Quoted 4 lines
The idea of a network filesystem having the same labels on all machines where it is mounted even when there are differences in policy and/or user rights on those machines makes no sense to me.
Well I would assume that the policy is the same on each machine except the default context that the user logs in as. And I have given you a descrete example of how things work at Red Hat. This is also how our customers expect this to work. CA/EATrust has made major money on this concept...
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.8 (GNU/Linux)
Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org
iEYEARECAAYFAkfr+hIACgkQrlYvE4MpobNidgCgnljhMx4GjdKbAdRzpUZUPGmN qqoAn27gqpThN26Si285ne2uLxEr22on
=/dFC
-----END PGP SIGNATURE-----
--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
Quoted 12 lines · Stephen Smalley
Quoted 6 lines · Joshua Brindle
This implements
user_transitionin the toolchain. It should help on distro's like Ubuntu that can't userun_initdue to the user not knowing the root password. It also seems like a more eloquent way to handle service restarts than assigningsystem_rto user accounts and having the daemons run as someuser:system_r:foo_t.Yes, that's something that has been wanted in Fedora for quite some time.
Quoted 8 lines
The real issue with
run_initisn't the re-authentication stage, as that can always be disabled via pam config (and was just a weak form of confirming user intent, not an authorization mechanism), but rather the difficulty in transparently interposing it into all situations where services get started/re-started. Only Gentoo seemed to have a good story there.
Do you have any comments on the patch? (Other than it needing to be rebased against permissive types?)
Also, if permissive types haven't hit akpm yet maybe we can merge the policy changes for both of these into 23?
I'm currently putting the user_transitions directly below the role_transitions in the on-disk format. I can change that if its easier but I doubt it matters, anything that reads policy will bail as soon as it doesn't understand that version.
Quoted 951 lines
Quoted 4 lines
This has some issues in policy due to users not always being known in the policy (eg., semanage users). I hope Chris or Dan will be able to give some suggestions there.
I'm not sure why anyone needs to add users to policy via semanage users given the base set of generic users and the ability to map Linux users to them via seusers aka semanage login.
Quoted 7 lines
The kernel patch (forthcoming after this is accepted) so far only implements the transition on process transitions. Later on I plan on doing a patch to expand
role_transitionto object classes (this is a change needed for policy rbac support to work). I suspect I'll do the same for user at that time. The question here is, do we think its worth it to do fine grained transitions like we did forrange_trans? (I don't).Offhand, I can't see a use for per-class user transitions, if that is what you mean.
I don't think per-class role transitions is really the fundamental obstacle to enabling use of roles on objects - more thought is required there. What will be fun there is role/type and user/range validation, which presently gets to ignore everything that has
object_r.Quoted 924 lines
Index:
libsepol/include/sepol/policydb/policydb.h
===================================================================include/sepol/policydb/policydb.h +27
-2@@ -156,6 +156,14 @@mls_level_t exp_dfltlevel;/* expanded range used for validation */ } user_datum_t; +typedef struct user_trans { +uint32_t user;/* current role */ +uint32_t type;/* program executable type */ +uint32_t new_user;/* new role */ +struct user_trans *next; +}user_trans_t ; + +/* Sensitivity attributes */ typedef struct level_datum { mls_level_t *level; /* sensitivity and associated categories */@@ -225,6 +233,13 @@struct role_trans_rule *next; } role_trans_rule_t; +typedef struct user_trans_rule { +ebitmap_t users;/* current role */ +type_set_t types;/* program executable type */ +uint32_t new_user;/* new role */ +struct user_trans_rule *next; +}user_trans_rule_t ; + typedef struct role_allow_rule { role_set_t roles; /* current role */ role_set_t new_roles; /* new roles */@@ -348,6 +363,9 @@char *module_name;struct avrule_decl *next; + +user_trans_rule_t *user_tr_rules; + } avrule_decl_t; typedef struct avrule_block {@@ -470,6 +488,8 @@ebitmap_t policycaps; +user_trans_t *user_tr; +unsigned policyvers;unsigned handle_unknown;@@ -524,6 +544,9 @@extern void role_trans_rule_init (role_trans_rule_t * x);extern void role_trans_rule_list_destroy (role_trans_rule_t * x); +extern void user_trans_rule_init (user_trans_rule_t * x); +extern void user_trans_rule_list_destroy (user_trans_rule_t * x); +extern void role_datum_init (role_datum_t * x);extern void role_datum_destroy (role_datum_t * x);extern void role_allow_rule_init (role_allow_rule_t * x);@@ -588,10 +611,11 @@#define POLICYDB_VERSION_AVTAB 20#define POLICYDB_VERSION_RANGETRANS 21#define POLICYDB_VERSION_POLCAP 22 +#define POLICYDB_VERSION_USERTRANS 23/* Range of policy versions we understand*/ #define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE -#define POLICYDB_VERSION_MAX POLICYDB_VERSION_POLCAP +#define POLICYDB_VERSION_MAX POLICYDB_VERSION_USERTRANS/* Module versions and specific changes*/ #define MOD_POLICYDB_VERSION_BASE 4@@ -600,9 +624,10 @@#define MOD_POLICYDB_VERSION_RANGETRANS 6#define MOD_POLICYDB_VERSION_MLS_USERS 6#define MOD_POLICYDB_VERSION_POLCAP 7 +#define MOD_POLICYDB_VERSION_USERTRANS 8#define MOD_POLICYDB_VERSION_MIN MOD_POLICYDB_VERSION_BASE -#define MOD_POLICYDB_VERSION_MAX MOD_POLICYDB_VERSION_POLCAP +#define MOD_POLICYDB_VERSION_MAX MOD_POLICYDB_VERSION_USERTRANS#define POLICYDB_CONFIG_MLS 1Index:
libsepol/src/policydb.c
===================================================================src/policydb.c +129
-1@@ -105,6 +105,12 @@ .ocon_num = OCON_NODE6 + 1, }, { + .type = POLICY_KERN, + .version = POLICYDB_VERSION_USERTRANS, + .sym_num = SYM_NUM, + .ocon_num = OCON_NODE6 + 1, + }, + { .type = POLICY_BASE, .version = MOD_POLICYDB_VERSION_BASE, .sym_num = SYM_NUM,@@ -129,6 +135,12 @@ .ocon_num = OCON_NODE6 + 1, }, { + .type = POLICY_BASE, + .version = MOD_POLICYDB_VERSION_USERTRANS, + .sym_num = SYM_NUM, + .ocon_num = OCON_NODE6 + 1, + }, + { .type = POLICY_MOD, .version = MOD_POLICYDB_VERSION_BASE, .sym_num = SYM_NUM,@@ -150,7 +162,14 @@ .type = POLICY_MOD, .version = MOD_POLICYDB_VERSION_POLCAP, .sym_num = SYM_NUM, - .ocon_num = 0}, + .ocon_num = 0 + }, + { + .type = POLICY_MOD, + .version = MOD_POLICYDB_VERSION_USERTRANS, + .sym_num = SYM_NUM, + .ocon_num =0 + }, };#if 0 @@ -348,6 +367,30 @@ } } +void user_trans_rule_init (user_trans_rule_t * x) +{ +memset (x,0 ,sizeof (*x)); +ebitmap_init (&x->users); +type_set_init (&x->types); +} + +void user_trans_rule_destroy (user_trans_rule_t * x) +{ +if (x !=NULL ) { +ebitmap_init (&x->users); +type_set_destroy (&x->types); + } +} + +void user_trans_rule_list_destroy (user_trans_rule_t * x) +{ +while (x !=NULL ) { +user_trans_rule_t *next = x->next; +user_trans_rule_destroy (x); +free (x); + x = next; + } +}void role_allow_rule_init (role_allow_rule_t * x) {memset (x,0 ,sizeof (role_allow_rule_t));@@ -985,6 +1028,7 @@unsigned int i;role_allow_t *ra, *lra =NULL ;role_trans_t *tr, *ltr =NULL ; +user_trans_t *ut, *lut =NULL ;range_trans_t *rt, *lrt =NULL ;if (!p)@@ -1058,6 +1102,14 @@if (ltr)free (ltr); +for (ut = p->user_tr; ut; ut = ut->next) { +if (lut) +free (lut); + lut = ut; + } +if (lut) +free (lut); +for (ra = p->role_allow; ra; ra = ra->next) {if (lra)free (lra);@@ -1983,6 +2035,40 @@return 0 ; } +int user_trans_read (user_trans_t ** t,struct policy_file *fp) +{ +unsigned int i; +uint32_t buf[3 ], nel; +user_trans_t *ut, *lut; +int rc; + + rc =next_entry (buf, fp,sizeof (uint32_t )); +if (rc <0 ) +return -1 ; + nel =le32_to_cpu (buf[0 ]); + lut =NULL ; +for (i =0 ; i < nel; i++) { + ut =calloc (1 ,sizeof (struct user_trans )); +if (!ut) { +return -1 ; + } +if (lut) { + lut->next = ut; + }else { + *t = ut; + } + rc =next_entry (buf, fp,sizeof (uint32_t ) *3 ); +if (rc <0 ) +return -1 ; + ut->user =le32_to_cpu (buf[0 ]); + ut->type =le32_to_cpu (buf[1 ]); + ut->new_user =le32_to_cpu (buf[2 ]); + lut = ut; + } +return 0 ; +} + +int role_allow_read (role_allow_t ** r,struct policy_file *fp) {unsigned int i;@@ -2679,6 +2765,48 @@return 0 ; } +static int user_trans_rule_read (user_trans_rule_t ** u,struct policy_file *fp) +{ +uint32_t buf[1 ], nel; +unsigned int i; +user_trans_rule_t *ut, *lut; +int rc; + + rc =next_entry (buf, fp,sizeof (uint32_t )); +if (rc <0 ) +return -1 ; + nel =le32_to_cpu (buf[0 ]); + lut =NULL ; +for (i =0 ; i < nel; i++) { + ut =malloc (sizeof (user_trans_rule_t)); +if (!ut) { +return -1 ; + } +user_trans_rule_init (ut); + +if (lut) { + lut->next = ut; + }else { + *u = ut; + } + +if (ebitmap_read (&ut->users, fp)) +return -1 ; + +if (type_set_read (&ut->types, fp)) +return -1 ; + + rc =next_entry (buf, fp,sizeof (uint32_t )); +if (rc <0 ) +return -1 ; + ut->new_user =le32_to_cpu (buf[0 ]); + lut = ut; + } + +return 0 ; +} + +static int role_allow_rule_read (role_allow_rule_t ** r,struct policy_file *fp) {unsigned int i;src/policydb.c +10
-1@@ -2805,9 +2933,14 @@if (cond_read_list (p, &decl->cond_list, fp) ==-1 ||avrule_read_list (p, &decl->avrules, fp) ==-1 ||role_trans_rule_read (&decl->role_tr_rules, fp) ==-1 || -role_allow_rule_read (&decl->role_allow_rules, fp) ==-1 ) { +role_allow_rule_read (&decl->role_allow_rules, fp) ==-1 ) + {return -1 ; } +if (p->policyvers >=MOD_POLICYDB_VERSION_USERTRANS ) { +if (user_trans_rule_read (&decl->user_tr_rules, fp)) +return -1 ; + }if (p->policyvers >=MOD_POLICYDB_VERSION_RANGETRANS &&range_trans_rule_read (&decl->range_tr_rules, fp) ==-1 ) {return -1 ;@@ -3179,6 +3312,10 @@ goto bad;if (role_trans_read (&p->role_tr, fp)) goto bad; +if (r_policyvers >=POLICYDB_VERSION_USERTRANS ) { +if (user_trans_read (&p->user_tr, fp)) + goto bad; + }if (role_allow_read (&p->role_allow, fp)) goto bad; }else {Index:
libsepol/src/expand.c
===================================================================src/expand.c +74
-0@@ -1060,6 +1060,80 @@return 0 ; } +static int copy_user_trans (expand_state_t * state,user_trans_rule_t * rules) +{ +unsigned int i, j; +user_trans_t *n, *l, *cur_trans; +user_trans_rule_t *cur; +ebitmap_t types; +ebitmap_node_t *rnode, *tnode; + +/* start at the end of the list */ +for (l = state->out->user_tr; l && l->next; l = l->next) ; + + cur = rules; +while (cur) { +ebitmap_init (&types); + +if (expand_convert_type_set + (state->out, state->typemap, &cur->types, &types,1 )) { +ERR (state->handle,"Out of memory!" ); +return -1 ; + } +ebitmap_for_each_bit (&cur->users, rnode, i) { +if (!ebitmap_node_get_bit (rnode, i)) +continue ; +ebitmap_for_each_bit (&types, tnode, j) { +if (!ebitmap_node_get_bit (tnode, j)) +continue ; + + cur_trans = state->out->user_tr; +while (cur_trans) { +if ((cur_trans->user == i +1 ) && + (cur_trans->type == j +1 )) { +if (cur_trans->new_user == + cur->new_user) { +break ; + }else { +ERR (state->handle, +"Conflicting user trans rule %s %s : %s" , + state->out->p_user_val_to_name[i], + state->out->p_type_val_to_name[j], + state->out->p_user_val_to_name[cur->new_user -1 ]); +return -1 ; + } + } + cur_trans = cur_trans->next; + } +if (cur_trans) +continue ; + + n = (user_trans_t *) +malloc (sizeof (user_trans_t)); +if (!n) { +ERR (state->handle,"Out of memory!" ); +return -1 ; + } +memset (n,0 ,sizeof (user_trans_t)); + n->user = i +1 ; + n->type = j +1 ; + n->new_user = cur->new_user; +if (l) { + l->next = n; + }else { + state->out->user_tr = n; + } + l = n; + } + } + +ebitmap_destroy (&types); + + cur = cur->next; + } +return 0 ; +} + static int exp_rangetr_helper(uint32_t stype, uint32_t ttype, uint32_t tclass, mls_semantic_range_t * trange,
expand_state_t* state)src/expand.c +3
-0@@ -2163,6 +2237,9 @@ goto cleanup; } +if (copy_user_trans (state, decl->user_tr_rules)) + goto cleanup; +/* expand the range transition rules */ if (expand_range_trans (state, decl->range_tr_rules)) goto cleanup;Index:
libsepol/src/write.c
===================================================================src/write.c +51
-0@@ -487,6 +487,31 @@return POLICYDB_SUCCESS ; } +static int user_trans_write (user_trans_t * u,struct policy_file *fp) +{ +user_trans_t *tr; +uint32_t buf[3 ]; +size_t nel, items; + + nel =0 ; +for (tr = u; tr; tr = tr->next) + nel++; + buf[0 ] =cpu_to_le32 (nel); + items =put_entry (buf,sizeof (uint32_t ),1 , fp); +if (items !=1 ) +return POLICYDB_ERROR ; +for (tr = u; tr; tr = tr->next) { + buf[0 ] =cpu_to_le32 (tr->user); + buf[1 ] =cpu_to_le32 (tr->type); + buf[2 ] =cpu_to_le32 (tr->new_user); + items =put_entry (buf,sizeof (uint32_t ),3 , fp); +if (items !=3 ) +return POLICYDB_ERROR ; + } + +return POLICYDB_SUCCESS ; +} +static int role_allow_write (role_allow_t * r,struct policy_file *fp) {role_allow_t *ra;@@ -1325,6 +1350,32 @@return POLICYDB_SUCCESS ; } +static int user_trans_rule_write (user_trans_rule_t * t,struct policy_file *fp) +{ +int nel =0 ; +size_t items; +uint32_t buf[1 ]; +user_trans_rule_t *tr; + +for (tr = t; tr; tr = tr->next) + nel++; + buf[0 ] =cpu_to_le32 (nel); + items =put_entry (buf,sizeof (uint32_t ),1 , fp); +if (items !=1 ) +return POLICYDB_ERROR ; +for (tr = t; tr; tr = tr->next) { +if (ebitmap_write (&tr->users, fp)) +return POLICYDB_ERROR ; +if (type_set_write (&tr->types, fp)) +return POLICYDB_ERROR ; + buf[0 ] =cpu_to_le32 (tr->new_user); + items =put_entry (buf,sizeof (uint32_t ),1 , fp); +if (items !=1 ) +return POLICYDB_ERROR ; + } +return POLICYDB_SUCCESS ; +} +static int role_allow_rule_write (role_allow_rule_t * r,struct policy_file *fp) {int nel = 0;src/write.c +8
-0@@ -1414,6 +1465,10 @@ role_allow_rule_write(decl->role_allow_rules, fp) == -1) {return POLICYDB_ERROR ; } +if (p->policyvers >=MOD_POLICYDB_VERSION_USERTRANS ) { +if (user_trans_rule_write (decl->user_tr_rules, fp)) +return POLICYDB_ERROR ; + }if (p->policyvers >=MOD_POLICYDB_VERSION_RANGETRANS &&range_trans_rule_write (decl->range_tr_rules, fp) ==-1 ) {return POLICYDB_ERROR ;@@ -1642,6 +1697,10 @@ }if (role_trans_write (p->role_tr, fp))return POLICYDB_ERROR ; +if (p->policyvers >=POLICYDB_VERSION_USERTRANS ) { +if (user_trans_write (p->user_tr, fp)) +return POLICYDB_ERROR ; + }if (role_allow_write (p->role_allow, fp))return POLICYDB_ERROR ; }else {Index:
libsepol/src/link.c
===================================================================src/link.c +52
-1@@ -848,6 +848,34 @@return -1 ; } +static int user_bitmap_or_convert (ebitmap_t * users,ebitmap_t * dst, +policy_module_t * mod,link_state_t * state) +{ +unsigned int i; +ebitmap_t tmp; +ebitmap_node_t *rnode; + +ebitmap_init (&tmp); +ebitmap_for_each_bit (users, rnode, i) { +if (ebitmap_node_get_bit (rnode, i)) { +assert (mod->map[SYM_USERS ][i]); +if (ebitmap_set_bit + (&tmp, mod->map[SYM_USERS ][i] -1 ,1 )) { + goto cleanup; + } + } + } +if (ebitmap_union (dst, &tmp)) { + goto cleanup; + } +ebitmap_destroy (&tmp); +return 0 ; + cleanup: +ERR (state->handle,"Out of memory!" ); +ebitmap_destroy (&tmp); +return -1 ; +} +static int mls_level_convert (mls_semantic_level_t * src,mls_semantic_level_t * dst,policy_module_t * mod,link_state_t * state) {@@ -1004,13 +1032,22 @@link_state_t *state = (link_state_t *) data;policy_module_t *mod = state->cur;symtab_t *usertab; +scope_datum_t *scope; user = (user_datum_t *) datum; + scope =hashtab_search (state->cur->policy->p_users_scope.table, key); +assert (scope); +if (scope->scope ==SCOPE_REQ ) { +//this is required user, no role or mls data +return 0 ; + } +if (state->dest_decl ==NULL ) usertab = &state->base->p_users; -else +else { usertab = &state->dest_decl->p_users; + } new_user =hashtab_search (usertab->table, id);assert (new_user !=NULL );@@ -1173,6 +1210,49 @@return -1 ; } +static int copy_user_trans_list (user_trans_rule_t * list, +user_trans_rule_t ** dst, +policy_module_t * module,link_state_t * state) +{ +user_trans_rule_t *cur, *new_rule =NULL , *tail; + + cur = list; + tail = *dst; +while (tail && tail->next) { + tail = tail->next; + } +while (cur) { + if ((new_rule = + (user_trans_rule_t *)malloc(sizeof(user_trans_rule_t))) ==
src/link.c +6
-0+ NULL) { + goto cleanup; + } +user_trans_rule_init (new_rule); + + if (user_bitmap_or_convert(&cur->users,
&new_rule->users, module, state))src/link.c +6
-0+ goto cleanup; +if (type_set_or_convert (&cur->types, &new_rule->types, module, state)) { + goto cleanup; + } + + new_rule->new_user =module->map[SYM_USERS][cur->new_user - 1];
src/link.c +17
-0+ +if (*dst ==NULL ) { + *dst = new_rule; + }else { + tail->next = new_rule; + } + tail = new_rule; + cur = cur->next; + } +return 0 ; + cleanup: +ERR (state->handle,"Out of memory!" ); +user_trans_rule_list_destroy (new_rule); +return -1 ; +} + +static int copy_role_allow_list(role_allow_rule_t * list,
role_allow_rule_t** dst,policy_module_t* module,link_state_t* state)src/link.c +4
-0@@ -1446,6 +1526,10 @@return -1 ; } +if (copy_user_trans_list (src_decl->user_tr_rules, &dest_decl->user_tr_rules, + module, state)) +return -1 ; +if (copy_range_trans_list (src_decl->range_tr_rules, &dest_decl->range_tr_rules, module, state))return -1;Index:
checkpolicy/test/dismod.c
===================================================================test/dismod.c +34
-1@@ -354,6 +354,21 @@return 0 ; } +int display_user_set (ebitmap_t *u,policydb_t *p,FILE *fp) +{ +ebitmap_node_t *node; +int i; + +fprintf (fp," { " ); +ebitmap_for_each_bit (u, node, i) { +if (ebitmap_node_get_bit (node, i)) { +display_id (p, fp,SYM_USERS , i,"" ); + } + } +fprintf (fp," } " ); +return 0 ; +} +int display_bools (policydb_t * p,FILE * fp) {int i;@@ -461,7 +476,18 @@fprintf (fp,"\n" ); } } +void display_user_trans (user_trans_rule_t * tr,policydb_t * p,FILE * fp) +{ +for (; tr; tr = tr->next) { +fprintf (fp,"user transition " ); +display_user_set (&tr->users, p, fp); +display_type_set (&tr->types,0 , p, fp); +display_id (p, fp,SYM_USERS , tr->new_user -1 ," :" ); +fprintf (fp,"\n" ); + } +} +void display_role_allow (role_allow_rule_t * ra,policydb_t * p,FILE * fp) {for (; ra; ra = ra->next) {@@ -641,6 +667,10 @@ }break ; } +case 7 :{ +display_user_trans (decl->user_tr_rules, policy, out_fp); +break ; + }default :{assert (0 ); }@@ -806,6 +836,7 @@printf ("c) Display policy capabilities\n" );printf ("l) Link in a module\n" );printf ("u) Display the unknown handling setting\n" ); +printf ("U) Display user transitions\n" );printf ("\n" );printf ("f) set output file\n" );printf ("m) display menu\n" );@@ -918,9 +949,11 @@display_policycaps (&policydb, out_fp);break ;case 'u' : -case 'U' :display_handle_unknown (&policydb, out_fp);break ; +case 'U' : +display_avblock (7 ,0 , &policydb, out_fp); +break ;case 'f' :printf ("\nFilename for output (<CR> for screen output): " );Index:
checkpolicy/test/dispol.c
===================================================================test/dispol.c +16
-1@@ -299,6 +299,18 @@return 0 ; } +static void display_user_transitions (policydb_t *p,FILE *fp) +{ +user_trans_t *cur; +for (cur = p->user_tr; cur; cur = cur->next) { +fprintf (fp,"user_transition " ); +fprintf (fp,"%s %s %s;\n" , + p->p_user_val_to_name[cur->user -1 ], + p->p_type_val_to_name[cur->type -1 ], + p->p_user_val_to_name[cur->new_user -1 ]); + } +} +static void display_policycaps (policydb_t * p,FILE * fp) {ebitmap_node_t *node;@@ -332,6 +344,7 @@printf ("\n" );printf ("c) display policy capabilities\n" );printf ("u) display unknown handling setting\n" ); +printf ("U) display user transitions\n" );printf ("f) set output file\n" );printf ("m) display menu\n" );printf ("q) quit\n" );@@ -448,9 +461,11 @@display_policycaps (&policydb, out_fp);break ;case 'u' : -case 'U' :display_handle_unknown (&policydb, out_fp);break ; +case 'U' : +display_user_transitions (&policydb, out_fp); +break ;case 'f' :printf ("\nFilename for output (<CR> for screen output): " );Index: checkpolicy/test/Makefile
===================================================================test/Makefile +0
-0@@ -6,7 +6,7 @@LIBDIR=$(PREFIX)/lib
INCLUDEDIR ?= $(PREFIX)/includetest/Makefile +1
-1-CFLAGS ?= -g -Wall -O2 -pipe +CFLAGS ?= -g3 -gdwarf-2 -Wall -O0 -pipeoverride CFLAGS += -I$(INCLUDEDIR)
LDLIBS=-lfl -lsepol -lselinux $(LIBDIR)/libsepol.a -L$(LIBDIR)
Index:checkpolicy/policy_define.c
===================================================================policy_define.c +70
-0@@ -2020,6 +2020,76 @@return -1 ; } +int define_user_trans (void ) +{ +char *id; +user_datum_t *user, *u; +ebitmap_t users; +type_set_t types; +struct user_trans_rule *rule =NULL ; +int add =1 ; + +if (pass ==1 ) { +while ((id =queue_remove (id_queue))) +free (id); +while ((id =queue_remove (id_queue))) +free (id); + id =queue_remove (id_queue); +free (id); +return 0 ; + } + +ebitmap_init (&users); +type_set_init (&types); + +while ((id =queue_remove (id_queue))) { + u =hashtab_search (policydbp->p_users.table, id); +if (!u) { +yyerror2 ("unknown user %s" , id); +free (id); +return -1 ; + } +if (ebitmap_set_bit (&users, u->s.value -1 , TRUE)) +return -1 ; + } +while ((id =queue_remove (id_queue))) { +if (set_types (&types, id, &add,0 )) +return -1 ; + } + id = (char *)queue_remove (id_queue); +if (!id) { +yyerror ("no new user in transition definition?" ); + goto bad; + } +if (!is_id_in_scope (SYM_USERS , id)) { +yyerror2 ("user %s is not within scope" , id); +free (id); + goto bad; + } + user =hashtab_search (policydbp->p_users.table, id); +if (!user) { +yyerror2 ("unknown user %s used in transition definition" , id); + goto bad; + } + rule =malloc (sizeof (struct user_trans_rule )); +if (!rule) { +yyerror ("out of memory" ); +return -1 ; + } +memset (rule,0 ,sizeof (struct user_trans_rule )); + rule->users = users; + rule->types = types; + rule->new_user = user->s.value; + +append_user_trans (rule); + +return 0 ; + + bad: +return -1 ; +} + +int define_role_allow (void ) {char *id;Index: checkpolicy/policy_scan.l
===================================================================policy_scan.l +0
-0@@ -102,6 +102,8 @@ type_change { return(TYPE_CHANGE); }
ROLE_TRANSITION|role_transition{return(ROLE_TRANSITION); }policy_scan.l +2
-0+USER_TRANSITION | +user_transition { return(USER_TRANSITION); }
RANGE_TRANSITION|range_transition{return(RANGE_TRANSITION); }
SENSITIVITY |
Index:checkpolicy/policy_define.h
===================================================================policy_define.h +1
-0@@ -42,6 +42,7 @@int define_role_allow (void );int define_role_trans (void );int define_role_types (void ); +int define_user_trans (void );int define_sens (void );int define_te_avtab (int which);int define_typealias (void );Index:
checkpolicy/module_compiler.c
===================================================================module_compiler.c +11
-0@@ -1214,6 +1214,17 @@ decl->role_tr_rules = role_tr_rules; } +void append_user_trans (user_trans_rule_t * user_tr_rules) +{ +avrule_decl_t *decl = stack_top->decl; + +/* role transitions are not allowed within conditionals */ +assert (stack_top->type ==1 ); + + user_tr_rules->next = decl->user_tr_rules; + decl->user_tr_rules = user_tr_rules; +} +/* this doesn't actually append, but really prepends it */ void append_role_allow (role_allow_rule_t * role_allow_rules) {Index: checkpolicy/policy_parse.y
===================================================================policy_parse.y +0
-0@@ -103,6 +103,7 @@%token
TYPE_MEMBER
%tokenTYPE_CHANGE
%tokenROLE_TRANSITION
+%tokenUSER_TRANSITION
%tokenRANGE_TRANSITION
%token SENSITIVITY
%token DOMINANCEpolicy_parse.y +1
-0@@ -261,6 +262,7 @@ | transition_def | range_trans_def | te_avtab_def + | user_trans_def ;
attribute_def: ATTRIBUTE identifier ';'{ if (define_attrib()) return -1;}policy_parse.y +0
-0@@ -411,6 +413,9 @@
role_trans_def:ROLE_TRANSITIONnames names identifier ';'{if (define_role_trans()) return -1; } ;policy_parse.y +3
-0+user_trans_def : USER_TRANSITION names names identifier ';' + { if (define_user_trans()) return -1; } + ;
role_allow_def: ALLOW names names ';'{if (define_role_allow()) return -1; } ;Index:
checkpolicy/module_compiler.h
===================================================================module_compiler.h +1
-0@@ -80,6 +80,7 @@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); +void append_user_trans (user_trans_rule_t * user_tr_rules);
Quoted 5 lines
module_compiler.h line 86
Quoted 5 lines
module_compiler.h +0
-0/* Create a new optional block and add it to the global policy. * During the second pass resolve the block's requirements. Return 0
--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
Quoted 6 lines · Stephen Smalley
The real issue with
run_initisn't the re-authentication stage, as that can always be disabled via pam config (and was just a weak form of confirming user intent, not an authorization mechanism), but rather the difficulty in transparently interposing it into all situations where services get started/re-started. Only Gentoo seemed to have a good story there.
In Red Hat distributions the command "service" is well documented, and last time I checked it was the only documented way of restarting daemons.
If the "service" command was modified to call run_init then a large part of that problem would be solved. It would not be unreasonable to demand that people who use the strict or mls policy also exclusively use "service" instead of running the script directly.
Quoted 3 lines
I'm not sure why anyone needs to add users to policy via semanage users given the base set of generic users and the ability to map Linux users to them via seusers aka semanage login.
Roles?
Also I like to be able to run "ls -Z" to see the SE Linux identity of the person who created the file.
Signature · 9 lines
[email protected] http://etbe.coker.com.au/ My Blog http://www.coker.com.au/sponsorship.html Sponsoring Free Software development -- This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
Quoted 11 lines · Russell Coker
Quoted 4 lines · Stephen Smalley
I'm not sure why anyone needs to add users to policy via semanage users given the base set of generic users and the ability to map Linux users to them via seusers aka semanage login.
Roles?
Also I like to be able to run "ls -Z" to see the SE Linux identity of the person who created the file.
Roles on objects will be my next patch after this one goes through. It will be necessary to implement the rbac separation in the policy that we've been talking about.
--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
Quoted 8 lines · Russell Coker
Quoted 6 lines · Stephen Smalley
The real issue with
run_initisn't the re-authentication stage, as that can always be disabled via pam config (and was just a weak form of confirming user intent, not an authorization mechanism), but rather the difficulty in transparently interposing it into all situations where services get started/re-started. Only Gentoo seemed to have a good story there.
Quoted 7 lines
In Red Hat distributions the command "service" is well documented, and last time I checked it was the only documented way of restarting daemons.
If the "service" command was modified to call
run_initthen a large part of that problem would be solved. It would not be unreasonable to demand that people who use the strict or mls policy also exclusively use "service" instead of running the script directly.
That was what we thought originally, and IIRC, Dan originally modified service to invoke run_init during early Fedora SELinux integration. Only to find out just how many things bypass it, like rpm %post scriptlets and admins from the shell ;)
Quoted 10 lines
Quoted 4 lines
I'm not sure why anyone needs to add users to policy via semanage users given the base set of generic users and the ability to map Linux users to them via seusers aka semanage login.
Roles?
Also I like to be able to run "ls -Z" to see the SE Linux identity of the person who created the file.
Signature · 8 lines
Stephen Smalley National Security Agency -- This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Quoted 17 lines · Stephen Smalley
Quoted 5 lines · Joshua Brindle
This implements
user_transitionin the toolchain. It should help on distro's like Ubuntu that can't userun_initdue to the user not knowing the root password. It also seems like a more eloquent way to handle service restarts than assigningsystem_rto user accounts and having the daemons run as someuser:system_r:foo_t.Yes, that's something that has been wanted in Fedora for quite some time.
The real issue with
run_initisn't the re-authentication stage, as that can always be disabled via pam config (and was just a weak form of confirming user intent, not an authorization mechanism), but rather the difficulty in transparently interposing it into all situations where services get started/re-started. Only Gentoo seemed to have a good story there.
Quoted 8 lines
Quoted 3 lines
This has some issues in policy due to users not always being known in the policy (eg., semanage users). I hope Chris or Dan will be able to give some suggestions there.
I'm not sure why anyone needs to add users to policy via semanage users given the base set of generic users and the ability to map Linux users to them via seusers aka semanage login.
Can we define users in modules? I envision and have provided modifications to do system-config-selinux for someone to take a guest_t and create a new role/type guest_plussendmail_t for a limited privileged login account that can connect to the sendmail port.
So once I have created this new User Type, I need a way to define the user. In Fedora right now, we define the xguest and guest accounts in the postinstall using semanage.
Quoted 943 lines
Quoted 6 lines
The kernel patch (forthcoming after this is accepted) so far only implements the transition on process transitions. Later on I plan on doing a patch to expand
role_transitionto object classes (this is a change needed for policy rbac support to work). I suspect I'll do the same for user at that time. The question here is, do we think its worth it to do fine grained transitions like we did forrange_trans? (I don't).Offhand, I can't see a use for per-class user transitions, if that is what you mean.
I don't think per-class role transitions is really the fundamental obstacle to enabling use of roles on objects - more thought is required there. What will be fun there is role/type and user/range validation, which presently gets to ignore everything that has
object_r.Quoted 928 lines
Index:
libsepol/include/sepol/policydb/policydb.h
===================================================================include/sepol/policydb/policydb.h +27
-2@@ -156,6 +156,14 @@mls_level_t exp_dfltlevel;/* expanded range used for validation */ } user_datum_t; +typedef struct user_trans { +uint32_t user;/* current role */ +uint32_t type;/* program executable type */ +uint32_t new_user;/* new role */ +struct user_trans *next; +}user_trans_t ; + +/* Sensitivity attributes */ typedef struct level_datum { mls_level_t *level; /* sensitivity and associated categories */@@ -225,6 +233,13 @@struct role_trans_rule *next; } role_trans_rule_t; +typedef struct user_trans_rule { +ebitmap_t users;/* current role */ +type_set_t types;/* program executable type */ +uint32_t new_user;/* new role */ +struct user_trans_rule *next; +}user_trans_rule_t ; + typedef struct role_allow_rule { role_set_t roles; /* current role */ role_set_t new_roles; /* new roles */@@ -348,6 +363,9 @@char *module_name;struct avrule_decl *next; + +user_trans_rule_t *user_tr_rules; + } avrule_decl_t; typedef struct avrule_block {@@ -470,6 +488,8 @@ebitmap_t policycaps; +user_trans_t *user_tr; +unsigned policyvers;unsigned handle_unknown;@@ -524,6 +544,9 @@extern void role_trans_rule_init (role_trans_rule_t * x);extern void role_trans_rule_list_destroy (role_trans_rule_t * x); +extern void user_trans_rule_init (user_trans_rule_t * x); +extern void user_trans_rule_list_destroy (user_trans_rule_t * x); +extern void role_datum_init (role_datum_t * x);extern void role_datum_destroy (role_datum_t * x);extern void role_allow_rule_init (role_allow_rule_t * x);@@ -588,10 +611,11 @@#define POLICYDB_VERSION_AVTAB 20#define POLICYDB_VERSION_RANGETRANS 21#define POLICYDB_VERSION_POLCAP 22 +#define POLICYDB_VERSION_USERTRANS 23/* Range of policy versions we understand*/ #define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE -#define POLICYDB_VERSION_MAX POLICYDB_VERSION_POLCAP +#define POLICYDB_VERSION_MAX POLICYDB_VERSION_USERTRANS/* Module versions and specific changes*/ #define MOD_POLICYDB_VERSION_BASE 4@@ -600,9 +624,10 @@#define MOD_POLICYDB_VERSION_RANGETRANS 6#define MOD_POLICYDB_VERSION_MLS_USERS 6#define MOD_POLICYDB_VERSION_POLCAP 7 +#define MOD_POLICYDB_VERSION_USERTRANS 8#define MOD_POLICYDB_VERSION_MIN MOD_POLICYDB_VERSION_BASE -#define MOD_POLICYDB_VERSION_MAX MOD_POLICYDB_VERSION_POLCAP +#define MOD_POLICYDB_VERSION_MAX MOD_POLICYDB_VERSION_USERTRANS#define POLICYDB_CONFIG_MLS 1Index:
libsepol/src/policydb.c
===================================================================src/policydb.c +129
-1@@ -105,6 +105,12 @@ .ocon_num = OCON_NODE6 + 1, }, { + .type = POLICY_KERN, + .version = POLICYDB_VERSION_USERTRANS, + .sym_num = SYM_NUM, + .ocon_num = OCON_NODE6 + 1, + }, + { .type = POLICY_BASE, .version = MOD_POLICYDB_VERSION_BASE, .sym_num = SYM_NUM,@@ -129,6 +135,12 @@ .ocon_num = OCON_NODE6 + 1, }, { + .type = POLICY_BASE, + .version = MOD_POLICYDB_VERSION_USERTRANS, + .sym_num = SYM_NUM, + .ocon_num = OCON_NODE6 + 1, + }, + { .type = POLICY_MOD, .version = MOD_POLICYDB_VERSION_BASE, .sym_num = SYM_NUM,@@ -150,7 +162,14 @@ .type = POLICY_MOD, .version = MOD_POLICYDB_VERSION_POLCAP, .sym_num = SYM_NUM, - .ocon_num = 0}, + .ocon_num = 0 + }, + { + .type = POLICY_MOD, + .version = MOD_POLICYDB_VERSION_USERTRANS, + .sym_num = SYM_NUM, + .ocon_num =0 + }, };#if 0 @@ -348,6 +367,30 @@ } } +void user_trans_rule_init (user_trans_rule_t * x) +{ +memset (x,0 ,sizeof (*x)); +ebitmap_init (&x->users); +type_set_init (&x->types); +} + +void user_trans_rule_destroy (user_trans_rule_t * x) +{ +if (x !=NULL ) { +ebitmap_init (&x->users); +type_set_destroy (&x->types); + } +} + +void user_trans_rule_list_destroy (user_trans_rule_t * x) +{ +while (x !=NULL ) { +user_trans_rule_t *next = x->next; +user_trans_rule_destroy (x); +free (x); + x = next; + } +}void role_allow_rule_init (role_allow_rule_t * x) {memset (x,0 ,sizeof (role_allow_rule_t));@@ -985,6 +1028,7 @@unsigned int i;role_allow_t *ra, *lra =NULL ;role_trans_t *tr, *ltr =NULL ; +user_trans_t *ut, *lut =NULL ;range_trans_t *rt, *lrt =NULL ;if (!p)@@ -1058,6 +1102,14 @@if (ltr)free (ltr); +for (ut = p->user_tr; ut; ut = ut->next) { +if (lut) +free (lut); + lut = ut; + } +if (lut) +free (lut); +for (ra = p->role_allow; ra; ra = ra->next) {if (lra)free (lra);@@ -1983,6 +2035,40 @@return 0 ; } +int user_trans_read (user_trans_t ** t,struct policy_file *fp) +{ +unsigned int i; +uint32_t buf[3 ], nel; +user_trans_t *ut, *lut; +int rc; + + rc =next_entry (buf, fp,sizeof (uint32_t )); +if (rc <0 ) +return -1 ; + nel =le32_to_cpu (buf[0 ]); + lut =NULL ; +for (i =0 ; i < nel; i++) { + ut =calloc (1 ,sizeof (struct user_trans )); +if (!ut) { +return -1 ; + } +if (lut) { + lut->next = ut; + }else { + *t = ut; + } + rc =next_entry (buf, fp,sizeof (uint32_t ) *3 ); +if (rc <0 ) +return -1 ; + ut->user =le32_to_cpu (buf[0 ]); + ut->type =le32_to_cpu (buf[1 ]); + ut->new_user =le32_to_cpu (buf[2 ]); + lut = ut; + } +return 0 ; +} + +int role_allow_read (role_allow_t ** r,struct policy_file *fp) {unsigned int i;@@ -2679,6 +2765,48 @@return 0 ; } +static int user_trans_rule_read (user_trans_rule_t ** u,struct policy_file *fp) +{ +uint32_t buf[1 ], nel; +unsigned int i; +user_trans_rule_t *ut, *lut; +int rc; + + rc =next_entry (buf, fp,sizeof (uint32_t )); +if (rc <0 ) +return -1 ; + nel =le32_to_cpu (buf[0 ]); + lut =NULL ; +for (i =0 ; i < nel; i++) { + ut =malloc (sizeof (user_trans_rule_t)); +if (!ut) { +return -1 ; + } +user_trans_rule_init (ut); + +if (lut) { + lut->next = ut; + }else { + *u = ut; + } + +if (ebitmap_read (&ut->users, fp)) +return -1 ; + +if (type_set_read (&ut->types, fp)) +return -1 ; + + rc =next_entry (buf, fp,sizeof (uint32_t )); +if (rc <0 ) +return -1 ; + ut->new_user =le32_to_cpu (buf[0 ]); + lut = ut; + } + +return 0 ; +} + +static int
role_allow_rule_read(role_allow_rule_t ** r, struct policy_file *fp){ unsigned int i;src/policydb.c +10
-1@@ -2805,9 +2933,14 @@if (cond_read_list (p, &decl->cond_list, fp) ==-1 ||avrule_read_list (p, &decl->avrules, fp) ==-1 ||role_trans_rule_read (&decl->role_tr_rules, fp) ==-1 || -role_allow_rule_read (&decl->role_allow_rules, fp) ==-1 ) { +role_allow_rule_read (&decl->role_allow_rules, fp) ==-1 ) + {return -1 ; } +if (p->policyvers >=MOD_POLICYDB_VERSION_USERTRANS ) { +if (user_trans_rule_read (&decl->user_tr_rules, fp)) +return -1 ; + }if (p->policyvers >=MOD_POLICYDB_VERSION_RANGETRANS &&range_trans_rule_read (&decl->range_tr_rules, fp) ==-1 ) {return -1 ;@@ -3179,6 +3312,10 @@ goto bad;if (role_trans_read (&p->role_tr, fp)) goto bad; +if (r_policyvers >=POLICYDB_VERSION_USERTRANS ) { +if (user_trans_read (&p->user_tr, fp)) + goto bad; + }if (role_allow_read (&p->role_allow, fp)) goto bad; }else {Index:
libsepol/src/expand.c
===================================================================src/expand.c +74
-0@@ -1060,6 +1060,80 @@return 0 ; } +static int copy_user_trans (expand_state_t * state,user_trans_rule_t * rules) +{ +unsigned int i, j; +user_trans_t *n, *l, *cur_trans; +user_trans_rule_t *cur; +ebitmap_t types; +ebitmap_node_t *rnode, *tnode; + +/* start at the end of the list */ +for (l = state->out->user_tr; l && l->next; l = l->next) ; + + cur = rules; +while (cur) { +ebitmap_init (&types); + +if (expand_convert_type_set + (state->out, state->typemap, &cur->types, &types,1 )) { +ERR (state->handle,"Out of memory!" ); +return -1 ; + } +ebitmap_for_each_bit (&cur->users, rnode, i) { +if (!ebitmap_node_get_bit (rnode, i)) +continue ; +ebitmap_for_each_bit (&types, tnode, j) { +if (!ebitmap_node_get_bit (tnode, j)) +continue ; + + cur_trans = state->out->user_tr; +while (cur_trans) { +if ((cur_trans->user == i +1 ) && + (cur_trans->type == j +1 )) { +if (cur_trans->new_user == + cur->new_user) { +break ; + }else { +ERR (state->handle, +"Conflicting user trans rule %s %s : %s" , + state->out->p_user_val_to_name[i], + state->out->p_type_val_to_name[j], + state->out->p_user_val_to_name[cur->new_user -1 ]); +return -1 ; + } + } + cur_trans = cur_trans->next; + } +if (cur_trans) +continue ; + + n = (user_trans_t *) +malloc (sizeof (user_trans_t)); +if (!n) { +ERR (state->handle,"Out of memory!" ); +return -1 ; + } +memset (n,0 ,sizeof (user_trans_t)); + n->user = i +1 ; + n->type = j +1 ; + n->new_user = cur->new_user; +if (l) { + l->next = n; + }else { + state->out->user_tr = n; + } + l = n; + } + } + +ebitmap_destroy (&types); + + cur = cur->next; + } +return 0 ; +} +static int exp_rangetr_helper(uint32_t stype,
uint32_tttype,uint32_ttclass,
mls_semantic_range_t* trange,expand_state_t* state)src/expand.c +3
-0@@ -2163,6 +2237,9 @@ goto cleanup; } +if (copy_user_trans (state, decl->user_tr_rules)) + goto cleanup; +/* expand the range transition rules */ if (expand_range_trans (state, decl->range_tr_rules)) goto cleanup;Index:
libsepol/src/write.c
===================================================================src/write.c +51
-0@@ -487,6 +487,31 @@return POLICYDB_SUCCESS ; } +static int user_trans_write (user_trans_t * u,struct policy_file *fp) +{ +user_trans_t *tr; +uint32_t buf[3 ]; +size_t nel, items; + + nel =0 ; +for (tr = u; tr; tr = tr->next) + nel++; + buf[0 ] =cpu_to_le32 (nel); + items =put_entry (buf,sizeof (uint32_t ),1 , fp); +if (items !=1 ) +return POLICYDB_ERROR ; +for (tr = u; tr; tr = tr->next) { + buf[0 ] =cpu_to_le32 (tr->user); + buf[1 ] =cpu_to_le32 (tr->type); + buf[2 ] =cpu_to_le32 (tr->new_user); + items =put_entry (buf,sizeof (uint32_t ),3 , fp); +if (items !=3 ) +return POLICYDB_ERROR ; + } + +return POLICYDB_SUCCESS ; +} +static int role_allow_write (role_allow_t * r,struct policy_file *fp) {role_allow_t *ra;@@ -1325,6 +1350,32 @@return POLICYDB_SUCCESS ; } +static int user_trans_rule_write (user_trans_rule_t * t,struct policy_file *fp) +{ +int nel =0 ; +size_t items; +uint32_t buf[1 ]; +user_trans_rule_t *tr; + +for (tr = t; tr; tr = tr->next) + nel++; + buf[0 ] =cpu_to_le32 (nel); + items =put_entry (buf,sizeof (uint32_t ),1 , fp); +if (items !=1 ) +return POLICYDB_ERROR ; +for (tr = t; tr; tr = tr->next) { +if (ebitmap_write (&tr->users, fp)) +return POLICYDB_ERROR ; +if (type_set_write (&tr->types, fp)) +return POLICYDB_ERROR ; + buf[0 ] =cpu_to_le32 (tr->new_user); + items =put_entry (buf,sizeof (uint32_t ),1 , fp); +if (items !=1 ) +return POLICYDB_ERROR ; + } +return POLICYDB_SUCCESS ; +} +static int
role_allow_rule_write(role_allow_rule_t * r, struct policy_file *fp){ int nel = 0;src/write.c +8
-0@@ -1414,6 +1465,10 @@ role_allow_rule_write(decl->role_allow_rules, fp) == -1) {return POLICYDB_ERROR ; } +if (p->policyvers >=MOD_POLICYDB_VERSION_USERTRANS ) { +if (user_trans_rule_write (decl->user_tr_rules, fp)) +return POLICYDB_ERROR ; + }if (p->policyvers >=MOD_POLICYDB_VERSION_RANGETRANS &&range_trans_rule_write (decl->range_tr_rules, fp) ==-1 ) {return POLICYDB_ERROR ;@@ -1642,6 +1697,10 @@ }if (role_trans_write (p->role_tr, fp))return POLICYDB_ERROR ; +if (p->policyvers >=POLICYDB_VERSION_USERTRANS ) { +if (user_trans_write (p->user_tr, fp)) +return POLICYDB_ERROR ; + }if (role_allow_write (p->role_allow, fp))return POLICYDB_ERROR ; }else {Index:
libsepol/src/link.c
===================================================================src/link.c +28
-0@@ -848,6 +848,34 @@return -1 ; } +static int user_bitmap_or_convert (ebitmap_t * users,ebitmap_t * dst, +policy_module_t * mod,link_state_t * state) +{ +unsigned int i; +ebitmap_t tmp; +ebitmap_node_t *rnode; + +ebitmap_init (&tmp); +ebitmap_for_each_bit (users, rnode, i) { +if (ebitmap_node_get_bit (rnode, i)) { +assert (mod->map[SYM_USERS ][i]); +if (ebitmap_set_bit + (&tmp, mod->map[SYM_USERS ][i] -1 ,1 )) { + goto cleanup; + } + } + } +if (ebitmap_union (dst, &tmp)) { + goto cleanup; + } +ebitmap_destroy (&tmp); +return 0 ; + cleanup: +ERR (state->handle,"Out of memory!" ); +ebitmap_destroy (&tmp); +return -1 ; +} +static int mls_level_convert (mls_semantic_level_t * src,mls_semantic_level_t * dst,policy_module_t * mod,link_state_t * state){
src/link.c +24
-1@@ -1004,13 +1032,22 @@link_state_t *state = (link_state_t *) data;policy_module_t *mod = state->cur;symtab_t *usertab; +scope_datum_t *scope; user = (user_datum_t *) datum; + scope =hashtab_search (state->cur->policy->p_users_scope.table, key); +assert (scope); +if (scope->scope ==SCOPE_REQ ) { +//this is required user, no role or mls data +return 0 ; + } +if (state->dest_decl ==NULL ) usertab = &state->base->p_users; -else +else { usertab = &state->dest_decl->p_users; + } new_user =hashtab_search (usertab->table, id);assert (new_user !=NULL );@@ -1173,6 +1210,49 @@return -1 ; } +static int copy_user_trans_list (user_trans_rule_t * list, +user_trans_rule_t ** dst, +policy_module_t * module,link_state_t * state) +{ +user_trans_rule_t *cur, *new_rule =NULL , *tail; + + cur = list; + tail = *dst; +while (tail && tail->next) { + tail = tail->next; + } +while (cur) { + if ((new_rule = + (user_trans_rule_t *)malloc(sizeof(user_trans_rule_t))) ==
src/link.c +6
-0+ NULL) { + goto cleanup; + } +user_trans_rule_init (new_rule); + + if (user_bitmap_or_convert(&cur->users,
&new_rule->users, module, state))src/link.c +6
-0+ goto cleanup; +if (type_set_or_convert (&cur->types, &new_rule->types, module, state)) { + goto cleanup; + } + + new_rule->new_user =module->map[SYM_USERS][cur->new_user - 1];
src/link.c +17
-0+ +if (*dst ==NULL ) { + *dst = new_rule; + }else { + tail->next = new_rule; + } + tail = new_rule; + cur = cur->next; + } +return 0 ; + cleanup: +ERR (state->handle,"Out of memory!" ); +user_trans_rule_list_destroy (new_rule); +return -1 ; +} + +static int copy_role_allow_list(role_allow_rule_t * list,
role_allow_rule_t** dst,policy_module_t* module,link_state_t* state)src/link.c +4
-0@@ -1446,6 +1526,10 @@return -1 ; } +if (copy_user_trans_list (src_decl->user_tr_rules, &dest_decl->user_tr_rules, + module, state)) +return -1 ; +if (copy_range_trans_list (src_decl->range_tr_rules, &dest_decl->range_tr_rules, module, state))return -1;Index:
checkpolicy/test/dismod.c
===================================================================test/dismod.c +34
-1@@ -354,6 +354,21 @@return 0 ; } +int display_user_set (ebitmap_t *u,policydb_t *p,FILE *fp) +{ +ebitmap_node_t *node; +int i; + +fprintf (fp," { " ); +ebitmap_for_each_bit (u, node, i) { +if (ebitmap_node_get_bit (node, i)) { +display_id (p, fp,SYM_USERS , i,"" ); + } + } +fprintf (fp," } " ); +return 0 ; +} +int display_bools (policydb_t * p,FILE * fp) {int i;@@ -461,7 +476,18 @@fprintf (fp,"\n" ); } } +void display_user_trans (user_trans_rule_t * tr,policydb_t * p,FILE * fp) +{ +for (; tr; tr = tr->next) { +fprintf (fp,"user transition " ); +display_user_set (&tr->users, p, fp); +display_type_set (&tr->types,0 , p, fp); +display_id (p, fp,SYM_USERS , tr->new_user -1 ," :" ); +fprintf (fp,"\n" ); + } +} +void display_role_allow (role_allow_rule_t * ra,policydb_t * p,FILE * fp) {for (; ra; ra = ra->next) {@@ -641,6 +667,10 @@ }break ; } +case 7 :{ +display_user_trans (decl->user_tr_rules, policy, out_fp); +break ; + }default :{assert (0 ); }@@ -806,6 +836,7 @@printf ("c) Display policy capabilities\n" );printf ("l) Link in a module\n" );printf ("u) Display the unknown handling setting\n" ); +printf ("U) Display user transitions\n" );printf ("\n" );printf ("f) set output file\n" );printf ("m) display menu\n" );@@ -918,9 +949,11 @@display_policycaps (&policydb, out_fp);break ;case 'u' : -case 'U' :display_handle_unknown (&policydb, out_fp);break ; +case 'U' : +display_avblock (7 ,0 , &policydb, out_fp); +break ;case 'f' :printf ("\nFilename for output (<CR> for screen output): " );Index:
checkpolicy/test/dispol.c
===================================================================test/dispol.c +16
-1@@ -299,6 +299,18 @@return 0 ; } +static void display_user_transitions (policydb_t *p,FILE *fp) +{ +user_trans_t *cur; +for (cur = p->user_tr; cur; cur = cur->next) { +fprintf (fp,"user_transition " ); +fprintf (fp,"%s %s %s;\n" , + p->p_user_val_to_name[cur->user -1 ], + p->p_type_val_to_name[cur->type -1 ], + p->p_user_val_to_name[cur->new_user -1 ]); + } +} +static void display_policycaps (policydb_t * p,FILE * fp) {ebitmap_node_t *node;@@ -332,6 +344,7 @@printf ("\n" );printf ("c) display policy capabilities\n" );printf ("u) display unknown handling setting\n" ); +printf ("U) display user transitions\n" );printf ("f) set output file\n" );printf ("m) display menu\n" );printf ("q) quit\n" );@@ -448,9 +461,11 @@display_policycaps (&policydb, out_fp);break ;case 'u' : -case 'U' :display_handle_unknown (&policydb, out_fp);break ; +case 'U' : +display_user_transitions (&policydb, out_fp); +break ;case 'f' :printf ("\nFilename for output (<CR> for screen output): " );Index: checkpolicy/test/Makefile
===================================================================test/Makefile +0
-0@@ -6,7 +6,7 @@LIBDIR=$(PREFIX)/lib
INCLUDEDIR ?= $(PREFIX)/includetest/Makefile +1
-1-CFLAGS ?= -g -Wall -O2 -pipe +CFLAGS ?= -g3 -gdwarf-2 -Wall -O0 -pipeoverride CFLAGS += -I$(INCLUDEDIR)
LDLIBS=-lfl -lsepol -lselinux $(LIBDIR)/libsepol.a -L$(LIBDIR)
Index:checkpolicy/policy_define.c
===================================================================policy_define.c +70
-0@@ -2020,6 +2020,76 @@return -1 ; } +int define_user_trans (void ) +{ +char *id; +user_datum_t *user, *u; +ebitmap_t users; +type_set_t types; +struct user_trans_rule *rule =NULL ; +int add =1 ; + +if (pass ==1 ) { +while ((id =queue_remove (id_queue))) +free (id); +while ((id =queue_remove (id_queue))) +free (id); + id =queue_remove (id_queue); +free (id); +return 0 ; + } + +ebitmap_init (&users); +type_set_init (&types); + +while ((id =queue_remove (id_queue))) { + u =hashtab_search (policydbp->p_users.table, id); +if (!u) { +yyerror2 ("unknown user %s" , id); +free (id); +return -1 ; + } +if (ebitmap_set_bit (&users, u->s.value -1 , TRUE)) +return -1 ; + } +while ((id =queue_remove (id_queue))) { +if (set_types (&types, id, &add,0 )) +return -1 ; + } + id = (char *)queue_remove (id_queue); +if (!id) { +yyerror ("no new user in transition definition?" ); + goto bad; + } +if (!is_id_in_scope (SYM_USERS , id)) { +yyerror2 ("user %s is not within scope" , id); +free (id); + goto bad; + } + user =hashtab_search (policydbp->p_users.table, id); +if (!user) { +yyerror2 ("unknown user %s used in transition definition" , id); + goto bad; + } + rule =malloc (sizeof (struct user_trans_rule )); +if (!rule) { +yyerror ("out of memory" ); +return -1 ; + } +memset (rule,0 ,sizeof (struct user_trans_rule )); + rule->users = users; + rule->types = types; + rule->new_user = user->s.value; + +append_user_trans (rule); + +return 0 ; + + bad: +return -1 ; +} + +int define_role_allow (void ) {char *id;Index: checkpolicy/policy_scan.l
===================================================================policy_scan.l +0
-0@@ -102,6 +102,8 @@ type_change { return(TYPE_CHANGE); }
ROLE_TRANSITION|role_transition{return(ROLE_TRANSITION); }policy_scan.l +2
-0+USER_TRANSITION | +user_transition { return(USER_TRANSITION); }
RANGE_TRANSITION|range_transition{return(RANGE_TRANSITION); }
SENSITIVITY |
Index:checkpolicy/policy_define.h
===================================================================policy_define.h +1
-0@@ -42,6 +42,7 @@int define_role_allow (void );int define_role_trans (void );int define_role_types (void ); +int define_user_trans (void );int define_sens (void );int define_te_avtab (int which);int define_typealias (void );Index:
checkpolicy/module_compiler.c
===================================================================module_compiler.c +11
-0@@ -1214,6 +1214,17 @@ decl->role_tr_rules = role_tr_rules; } +void append_user_trans (user_trans_rule_t * user_tr_rules) +{ +avrule_decl_t *decl = stack_top->decl; + +/* role transitions are not allowed within conditionals */ +assert (stack_top->type ==1 ); + + user_tr_rules->next = decl->user_tr_rules; + decl->user_tr_rules = user_tr_rules; +} +/* this doesn't actually append, but really prepends it */ void append_role_allow (role_allow_rule_t * role_allow_rules) {Index: checkpolicy/policy_parse.y
===================================================================policy_parse.y +0
-0@@ -103,6 +103,7 @@%token
TYPE_MEMBER
%tokenTYPE_CHANGE
%tokenROLE_TRANSITION
+%tokenUSER_TRANSITION
%tokenRANGE_TRANSITION
%token SENSITIVITY
%token DOMINANCEpolicy_parse.y +1
-0@@ -261,6 +262,7 @@ | transition_def | range_trans_def | te_avtab_def + | user_trans_def ;
attribute_def: ATTRIBUTE identifier ';'{ if (define_attrib()) return -1;}policy_parse.y +0
-0@@ -411,6 +413,9 @@
role_trans_def:ROLE_TRANSITIONnames names identifier ';'{if (define_role_trans()) return -1; } ;policy_parse.y +3
-0+user_trans_def : USER_TRANSITION names names identifier ';' + { if (define_user_trans()) return -1; } + ;
role_allow_def: ALLOW names names ';'{if (define_role_allow()) return -1; } ;Index:
checkpolicy/module_compiler.h
===================================================================module_compiler.h +1
-0@@ -80,6 +80,7 @@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); +void append_user_trans (user_trans_rule_t * user_tr_rules);
Quoted 4 lines
module_compiler.h line 86
Quoted 4 lines
module_compiler.h +0
-0/* Create a new optional block and add it to the global policy. * During the second pass resolve the block's requirements. Return 0
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.8 (GNU/Linux)
Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org
iEYEARECAAYFAkfqDBQACgkQrlYvE4MpobNITACfVxCGgzhZqkqNE4YfgIa1Gt/T z1kAn2Y7kxJFDnimNarKxbZyafpZzlJR
=xZWX
-----END PGP SIGNATURE-----
--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
Quoted 29 lines · Daniel J Walsh
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1Quoted 17 lines · Stephen Smalley
Quoted 5 lines · Joshua Brindle
This implements
user_transitionin the toolchain. It should help on distro's like Ubuntu that can't userun_initdue to the user not knowing the root password. It also seems like a more eloquent way to handle service restarts than assigningsystem_rto user accounts and having the daemons run as someuser:system_r:foo_t.Yes, that's something that has been wanted in Fedora for quite some time.
The real issue with
run_initisn't the re-authentication stage, as that can always be disabled via pam config (and was just a weak form of confirming user intent, not an authorization mechanism), but rather the difficulty in transparently interposing it into all situations where services get started/re-started. Only Gentoo seemed to have a good story there.Quoted 8 lines
Quoted 3 lines
This has some issues in policy due to users not always being known in the policy (eg., semanage users). I hope Chris or Dan will be able to give some suggestions there.
I'm not sure why anyone needs to add users to policy via semanage users given the base set of generic users and the ability to map Linux users to them via seusers aka semanage login.
Quoted 8 lines
Can we define users in modules? I envision and have provided modifications to do system-config-selinux for someone to take a
guest_tand create a new role/typeguest_plussendmail_tfor a limited privileged login account that can connect to the sendmail port.So once I have created this new User Type, I need a way to define the user. In Fedora right now, we define the xguest and guest accounts in the postinstall using semanage.
You can already define SELinux users in modules (after any TE/RBAC rules).
Signature · 8 lines
Stephen Smalley National Security Agency -- This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
Quoted 37 lines · Joshua Brindle
This implements
user_transitionin the toolchain. It should help on distro's like Ubuntu that can't userun_initdue to the user not knowing the root password. It also seems like a more eloquent way to handle service restarts than assigningsystem_rto user accounts and having the daemons run as someuser:system_r:foo_t.This has some issues in policy due to users not always being known in the policy (eg., semanage users). I hope Chris or Dan will be able to give some suggestions there.
The kernel patch (forthcoming after this is accepted) so far only implements the transition on process transitions. Later on I plan on doing a patch to expand
role_transitionto object classes (this is a change needed for policy rbac support to work). I suspect I'll do the same for user at that time. The question here is, do we think its worth it to do fine grained transitions like we did forrange_trans? (I don't).Index:
libsepol/include/sepol/policydb/policydb.h
===================================================================include/sepol/policydb/policydb.h +8
-0@@ -156,6 +156,14 @@mls_level_t exp_dfltlevel;/* expanded range used for validation */ } user_datum_t; +typedef struct user_trans { +uint32_t user;/* current role */ +uint32_t type;/* program executable type */ +uint32_t new_user;/* new role */ +struct user_trans *next; +}user_trans_t ; + +/* Sensitivity attributes */ typedef struct level_datum { mls_level_t *level; /* sensitivity and associated categories */
include/sepol/policydb/policydb.h line 241
Quoted 9 lines
include/sepol/policydb/policydb.h +6
-0@@ -225,6 +233,13 @@struct role_trans_rule *next; } role_trans_rule_t; +typedef struct user_trans_rule { +ebitmap_t users;/* current role */ +type_set_t types;/* program executable type */ +uint32_t new_user;/* new role */ +struct user_trans_rule *next; +}user_trans_rule_t ;
Possibly crazy idea - given the current trend, would it be better to just save the user transition rules in symbolic form in the module format. Would that simplify the link/expand code?
src/policydb.c line 372
Quoted 11 lines
Index:
libsepol/src/policydb.c
===================================================================src/policydb.c +3
-0@@ -348,6 +367,30 @@ } } +void user_trans_rule_init (user_trans_rule_t * x) +{ +memset (x,0 ,sizeof (*x));
Not unique to this patch, but it seems funny that we use memset followed by explicit initializers for fields that have them. And that as a result of the memset here, we don't calloc when allocate the structs.
src/policydb.c line 380
Quoted 8 lines
src/policydb.c +8
-0+ebitmap_init (&x->users); +type_set_init (&x->types); +} + +void user_trans_rule_destroy (user_trans_rule_t * x) +{ +if (x !=NULL ) { +ebitmap_init (&x->users);
Should be ebitmap_destroy, right?
src/policydb.c line 384
Quoted 4 lines
src/policydb.c +4
-0+type_set_destroy (&x->types); + } +} +
Usual boilerplate - make sure it runs under valgrind cleanly and doesn't introduce any (new) leaks on monolithic and modular build+link.
Signature · 8 lines
Stephen Smalley National Security Agency -- This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
Quoted 42 lines · Stephen Smalley
Quoted 40 lines · Joshua Brindle
This implements
user_transitionin the toolchain. It should help on distro's like Ubuntu that can't userun_initdue to the user not knowing the root password. It also seems like a more eloquent way to handle service restarts than assigningsystem_rto user accounts and having the daemons run as someuser:system_r:foo_t.This has some issues in policy due to users not always being known in the policy (eg., semanage users). I hope Chris or Dan will be able to give some suggestions there.
The kernel patch (forthcoming after this is accepted) so far only implements the transition on process transitions. Later on I plan on doing a patch to expand
role_transitionto object classes (this is a change needed for policy rbac support to work). I suspect I'll do the same for user at that time. The question here is, do we think its worth it to do fine grained transitions like we did forrange_trans? (I don't).Index:
libsepol/include/sepol/policydb/policydb.h
===================================================================include/sepol/policydb/policydb.h +8
-0@@ -156,6 +156,14 @@mls_level_t exp_dfltlevel;/* expanded range used for validation */ } user_datum_t; +typedef struct user_trans { +uint32_t user;/* current role */ +uint32_t type;/* program executable type */ +uint32_t new_user;/* new role */ +struct user_trans *next; +}user_trans_t ; + +/* Sensitivity attributes */ typedef struct level_datum { mls_level_t *level; /* sensitivity and associated categories */@@ -225,6 +233,13 @@struct role_trans_rule *next; } role_trans_rule_t;
Quoted 13 lines
include/sepol/policydb/policydb.h line 242
Quoted 7 lines
include/sepol/policydb/policydb.h +6
-0+typedef struct user_trans_rule { +ebitmap_t users;/* current role */ +type_set_t types;/* program executable type */ +uint32_t new_user;/* new role */ +struct user_trans_rule *next; +}user_trans_rule_t ;Possibly crazy idea - given the current trend, would it be better to just save the user transition rules in symbolic form in the module format. Would that simplify the link/expand code?
Possibly, I am hoping policyrep will supplant this code in the near future so I didn't think about it much. This is consistent with how we store other modular things.
Quoted 8 lines
Quoted 8 lines
Index:
libsepol/src/policydb.c
===================================================================src/policydb.c +0
-0@@ -348,6 +367,30 @@ } }
Quoted 10 lines
src/policydb.c line 373
Quoted 4 lines
src/policydb.c +3
-0+void user_trans_rule_init (user_trans_rule_t * x) +{ +memset (x,0 ,sizeof (*x));Not unique to this patch, but it seems funny that we use memset followed by explicit initializers for fields that have them. And that as a result of the memset here, we don't calloc when allocate the structs.
I would normally never memset a struct, rather than use an initializer but I was going for minimal changes here, I don't plan on this code being around for long.
Quoted 13 lines
src/policydb.c line 382
Quoted 9 lines
src/policydb.c +8
-0+ebitmap_init (&x->users); +type_set_init (&x->types); +} + +void user_trans_rule_destroy (user_trans_rule_t * x) +{ +if (x !=NULL ) { +ebitmap_init (&x->users);Should be
ebitmap_destroy, right?
Oops, yes
Quoted 8 lines
src/policydb.c line 387
Quoted 5 lines
src/policydb.c +4
-0+type_set_destroy (&x->types); + } +} +Usual boilerplate - make sure it runs under valgrind cleanly and doesn't introduce any (new) leaks on monolithic and modular build+link
This was an RFC patch and didn't go through any rigorous testing or valgrind (though I did ask for comments..) I recently found a bug in it so there will be another patch soon. Thanks for the comments.
--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
Quoted 80 lines · Joshua Brindle
Quoted 42 lines · Stephen Smalley
Quoted 40 lines · Joshua Brindle
This implements
user_transitionin the toolchain. It should help on distro's like Ubuntu that can't userun_initdue to the user not knowing the root password. It also seems like a more eloquent way to handle service restarts than assigningsystem_rto user accounts and having the daemons run as someuser:system_r:foo_t.This has some issues in policy due to users not always being known in the policy (eg., semanage users). I hope Chris or Dan will be able to give some suggestions there.
The kernel patch (forthcoming after this is accepted) so far only implements the transition on process transitions. Later on I plan on doing a patch to expand
role_transitionto object classes (this is a change needed for policy rbac support to work). I suspect I'll do the same for user at that time. The question here is, do we think its worth it to do fine grained transitions like we did forrange_trans? (I don't).Index:
libsepol/include/sepol/policydb/policydb.h
===================================================================include/sepol/policydb/policydb.h +8
-0@@ -156,6 +156,14 @@mls_level_t exp_dfltlevel;/* expanded range used for validation */ } user_datum_t; +typedef struct user_trans { +uint32_t user;/* current role */ +uint32_t type;/* program executable type */ +uint32_t new_user;/* new role */ +struct user_trans *next; +}user_trans_t ; + +/* Sensitivity attributes */ typedef struct level_datum { mls_level_t *level; /* sensitivity and associated categories */@@ -225,6 +233,13 @@struct role_trans_rule *next; } role_trans_rule_t;Quoted 13 lines
include/sepol/policydb/policydb.h line 242
Quoted 7 lines
include/sepol/policydb/policydb.h +6
-0+typedef struct user_trans_rule { +ebitmap_t users;/* current role */ +type_set_t types;/* program executable type */ +uint32_t new_user;/* new role */ +struct user_trans_rule *next; +}user_trans_rule_t ;Possibly crazy idea - given the current trend, would it be better to just save the user transition rules in symbolic form in the module format. Would that simplify the link/expand code?
Possibly, I am hoping policyrep will supplant this code in the near future so I didn't think about it much. This is consistent with how we store other modular things.
Quoted 8 lines
Quoted 8 lines
Index:
libsepol/src/policydb.c
===================================================================src/policydb.c +0
-0@@ -348,6 +367,30 @@ } }Quoted 10 lines
src/policydb.c line 373
Quoted 4 lines
src/policydb.c +3
-0+void user_trans_rule_init (user_trans_rule_t * x) +{ +memset (x,0 ,sizeof (*x));Not unique to this patch, but it seems funny that we use memset followed by explicit initializers for fields that have them. And that as a result of the memset here, we don't calloc when allocate the structs.
Quoted 3 lines
I would normally never memset a struct, rather than use an initializer but I was going for minimal changes here, I don't plan on this code being around for long.
Famous last words. Don't ever make that assumption ;) Especially given life cycles of distributions that might incorporate said code.
I know that this is consistent with how we store other modular things and that policyrep will "make all things better". But I'm wondering whether you could have greatly simplified even this "transient" implementation of user transition support by keeping it in symbolic form, even within a "binary" module format, to simplify linking and reduce likelihood of mapping errors.
Quoted 33 lines
Quoted 13 lines
src/policydb.c line 382
Quoted 9 lines
src/policydb.c +8
-0+ebitmap_init (&x->users); +type_set_init (&x->types); +} + +void user_trans_rule_destroy (user_trans_rule_t * x) +{ +if (x !=NULL ) { +ebitmap_init (&x->users);Should be
ebitmap_destroy, right?Oops, yes
Quoted 8 lines
src/policydb.c line 387
Quoted 5 lines
src/policydb.c +4
-0+type_set_destroy (&x->types); + } +} +Usual boilerplate - make sure it runs under valgrind cleanly and doesn't introduce any (new) leaks on monolithic and modular build+link
This was an RFC patch and didn't go through any rigorous testing or valgrind (though I did ask for comments..) I recently found a bug in it so there will be another patch soon. Thanks for the comments.
--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
Signature · 8 lines
Stephen Smalley National Security Agency -- This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
Quoted 83 lines · Stephen Smalley
Quoted 81 lines · Joshua Brindle
Quoted 43 lines · Stephen Smalley
Quoted 40 lines · Joshua Brindle
This implements
user_transitionin the toolchain. It should help on distro's like Ubuntu that can't userun_initdue to the user not knowing the root password. It also seems like a more eloquent way to handle service restarts than assigningsystem_rto user accounts and having the daemons run as someuser:system_r:foo_t.This has some issues in policy due to users not always being known in the policy (eg., semanage users). I hope Chris or Dan will be able to give some suggestions there.
The kernel patch (forthcoming after this is accepted) so far only implements the transition on process transitions. Later on I plan on doing a patch to expand
role_transitionto object classes (this is a change needed for policy rbac support to work). I suspect I'll do the same for user at that time. The question here is, do we think its worth it to do fine grained transitions like we did forrange_trans? (I don't).Index:
libsepol/include/sepol/policydb/policydb.h
===================================================================include/sepol/policydb/policydb.h +8
-0@@ -156,6 +156,14 @@mls_level_t exp_dfltlevel;/* expanded range used for validation */ } user_datum_t; +typedef struct user_trans { +uint32_t user;/* current role */ +uint32_t type;/* program executable type */ +uint32_t new_user;/* new role */ +struct user_trans *next; +}user_trans_t ; + +/* Sensitivity attributes */ typedef struct level_datum { mls_level_t *level; /* sensitivity and associated categories */@@ -225,6 +233,13 @@struct role_trans_rule *next; } role_trans_rule_t;Quoted 14 lines
include/sepol/policydb/policydb.h line 243
Quoted 8 lines
include/sepol/policydb/policydb.h +6
-0+typedef struct user_trans_rule { +ebitmap_t users;/* current role */ +type_set_t types;/* program executable type */ +uint32_t new_user;/* new role */ +struct user_trans_rule *next; +}user_trans_rule_t ;Possibly crazy idea - given the current trend, would it be better to just save the user transition rules in symbolic form in the module format. Would that simplify the link/expand code?
Possibly, I am hoping policyrep will supplant this code in the near future so I didn't think about it much. This is consistent with how we store other modular things.
Quoted 19 lines
src/policydb.c line 374
Quoted 13 lines
Index:
libsepol/src/policydb.c
===================================================================src/policydb.c +3
-0@@ -348,6 +367,30 @@ } } +void user_trans_rule_init (user_trans_rule_t * x) +{ +memset (x,0 ,sizeof (*x));Not unique to this patch, but it seems funny that we use memset followed by explicit initializers for fields that have them. And that as a result of the memset here, we don't calloc when allocate the structs.
Quoted 7 lines
Quoted 2 lines
I would normally never memset a struct, rather than use an initializer but I was going for minimal changes here, I don't plan on this code being around for long.
Famous last words. Don't ever make that assumption ;) Especially given life cycles of distributions that might incorporate said code.
I know, I typed it tongue-in-cheek.
Quoted 8 lines
I know that this is consistent with how we store other modular things and that policyrep will "make all things better". But I'm wondering whether you could have greatly simplified even this "transient" implementation of user transition support by keeping it in symbolic form, even within a "binary" module format, to simplify linking and reduce likelihood of mapping errors.
I understand and if there were more time I wouldn't mind doing it. Right now I wanted to push these through as fast as possible so that we could maybe get them in to Hardy, which as of right now has no solution to restart services other than rebooting.
This method is well understood in this codebase and chances are in mapping is broken one place its broken in five so I'm not entirely sure what it would gain us now.
On the note of getting this out quickly I'm hitting this strange kernel but where class_read says a common is unknown when I try to load a 23 policy, I'm currently working through that but building ubuntu kernels takes hours :X
Quoted 26 lines
Quoted 26 lines
Quoted 14 lines
src/policydb.c line 383
Quoted 10 lines
src/policydb.c +8
-0+ebitmap_init (&x->users); +type_set_init (&x->types); +} + +void user_trans_rule_destroy (user_trans_rule_t * x) +{ +if (x !=NULL ) { +ebitmap_init (&x->users);Should be
ebitmap_destroy, right?Oops, yes
Quoted 9 lines
src/policydb.c line 387
Quoted 6 lines
src/policydb.c +4
-0+type_set_destroy (&x->types); + } +} +Usual boilerplate - make sure it runs under valgrind cleanly and doesn't introduce any (new) leaks on monolithic and modular build+link
Quoted 8 lines
Quoted 8 lines
This was an RFC patch and didn't go through any rigorous testing or valgrind (though I did ask for comments..) I recently found a bug in it so there will be another patch soon. Thanks for the comments.
--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
Quoted 107 lines · Joshua Brindle
Quoted 85 lines · Stephen Smalley
Quoted 83 lines · Joshua Brindle
Quoted 43 lines · Stephen Smalley
Quoted 40 lines · Joshua Brindle
This implements
user_transitionin the toolchain. It should help on distro's like Ubuntu that can't userun_initdue to the user not knowing the root password. It also seems like a more eloquent way to handle service restarts than assigningsystem_rto user accounts and having the daemons run as someuser:system_r:foo_t.This has some issues in policy due to users not always being known in the policy (eg., semanage users). I hope Chris or Dan will be able to give some suggestions there.
The kernel patch (forthcoming after this is accepted) so far only implements the transition on process transitions. Later on I plan on doing a patch to expand
role_transitionto object classes (this is a change needed for policy rbac support to work). I suspect I'll do the same for user at that time. The question here is, do we think its worth it to do fine grained transitions like we did forrange_trans? (I don't).Index:
libsepol/include/sepol/policydb/policydb.h
===================================================================include/sepol/policydb/policydb.h +8
-0@@ -156,6 +156,14 @@mls_level_t exp_dfltlevel;/* expanded range used for validation */ } user_datum_t; +typedef struct user_trans { +uint32_t user;/* current role */ +uint32_t type;/* program executable type */ +uint32_t new_user;/* new role */ +struct user_trans *next; +}user_trans_t ; + +/* Sensitivity attributes */ typedef struct level_datum { mls_level_t *level; /* sensitivity and associated categories */@@ -225,6 +233,13 @@struct role_trans_rule *next; } role_trans_rule_t;Quoted 14 lines
include/sepol/policydb/policydb.h line 243
Quoted 8 lines
include/sepol/policydb/policydb.h +6
-0+typedef struct user_trans_rule { +ebitmap_t users;/* current role */ +type_set_t types;/* program executable type */ +uint32_t new_user;/* new role */ +struct user_trans_rule *next; +}user_trans_rule_t ;Possibly crazy idea - given the current trend, would it be better to just save the user transition rules in symbolic form in the module format. Would that simplify the link/expand code?
Possibly, I am hoping policyrep will supplant this code in the near future so I didn't think about it much. This is consistent with how we store other modular things.
Quoted 19 lines
src/policydb.c line 374
Quoted 13 lines
Index:
libsepol/src/policydb.c
===================================================================src/policydb.c +3
-0@@ -348,6 +367,30 @@ } } +void user_trans_rule_init (user_trans_rule_t * x) +{ +memset (x,0 ,sizeof (*x));Not unique to this patch, but it seems funny that we use memset followed by explicit initializers for fields that have them. And that as a result of the memset here, we don't calloc when allocate the structs.
Quoted 9 lines
Quoted 4 lines
I would normally never memset a struct, rather than use an initializer but I was going for minimal changes here, I don't plan on this code being around for long.
Famous last words. Don't ever make that assumption ;) Especially given life cycles of distributions that might incorporate said code.
I know, I typed it tongue-in-cheek.
Quoted 8 lines
I know that this is consistent with how we store other modular things and that policyrep will "make all things better". But I'm wondering whether you could have greatly simplified even this "transient" implementation of user transition support by keeping it in symbolic form, even within a "binary" module format, to simplify linking and reduce likelihood of mapping errors.
Quoted 4 lines
I understand and if there were more time I wouldn't mind doing it. Right now I wanted to push these through as fast as possible so that we could maybe get them in to Hardy, which as of right now has no solution to restart services other than rebooting.
Rushing through a new feature considered harmful. Look, Fedora has lived for years without this feature and works fine, albeit requiring adding system_r to user accounts and enabling DIRECT_INITRC=y in build.conf.
Quoted 8 lines
This method is well understood in this codebase and chances are in mapping is broken one place its broken in five so I'm not entirely sure what it would gain us now.
On the note of getting this out quickly I'm hitting this strange kernel but where
class_readsays a common is unknown when I try to load a 23 policy, I'm currently working through that but building ubuntu kernels takes hours :X
Cute. But a good example of why we shouldn't rush this out. And even if it is implemented tomorrow, what is the likelihood that the Ubuntu kernel folks are going to want to pull it into their existing kernel for this release - at such a late date?
Signature · 8 lines
Stephen Smalley National Security Agency -- This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
Quoted 113 lines · Stephen Smalley
Quoted 107 lines · Joshua Brindle
Quoted 85 lines · Stephen Smalley
Quoted 83 lines · Joshua Brindle
Quoted 43 lines · Stephen Smalley
Quoted 40 lines · Joshua Brindle
This implements
user_transitionin the toolchain. It should help on distro's like Ubuntu that can't userun_initdue to the user not knowing the root password. It also seems like a more eloquent way to handle service restarts than assigningsystem_rto user accounts and having the daemons run as someuser:system_r:foo_t.This has some issues in policy due to users not always being known in the policy (eg., semanage users). I hope Chris or Dan will be able to give some suggestions there.
The kernel patch (forthcoming after this is accepted) so far only implements the transition on process transitions. Later on I plan on doing a patch to expand
role_transitionto object classes (this is a change needed for policy rbac support to work). I suspect I'll do the same for user at that time. The question here is, do we think its worth it to do fine grained transitions like we did forrange_trans? (I don't).Index:
libsepol/include/sepol/policydb/policydb.h
===================================================================include/sepol/policydb/policydb.h +8
-0@@ -156,6 +156,14 @@mls_level_t exp_dfltlevel;/* expanded range used for validation */ } user_datum_t; +typedef struct user_trans { +uint32_t user;/* current role */ +uint32_t type;/* program executable type */ +uint32_t new_user;/* new role */ +struct user_trans *next; +}user_trans_t ; + +/* Sensitivity attributes */ typedef struct level_datum { mls_level_t *level; /* sensitivity and associated categories */@@ -225,6 +233,13 @@struct role_trans_rule *next; } role_trans_rule_t;Quoted 14 lines
include/sepol/policydb/policydb.h line 243
Quoted 8 lines
include/sepol/policydb/policydb.h +6
-0+typedef struct user_trans_rule { +ebitmap_t users;/* current role */ +type_set_t types;/* program executable type */ +uint32_t new_user;/* new role */ +struct user_trans_rule *next; +}user_trans_rule_t ;Possibly crazy idea - given the current trend, would it be better to just save the user transition rules in symbolic form in the module format. Would that simplify the link/expand code?
Possibly, I am hoping policyrep will supplant this code in the near future so I didn't think about it much. This is consistent with how we store other modular things.
Quoted 19 lines
src/policydb.c line 374
Quoted 13 lines
Index:
libsepol/src/policydb.c
===================================================================src/policydb.c +3
-0@@ -348,6 +367,30 @@ } } +void user_trans_rule_init (user_trans_rule_t * x) +{ +memset (x,0 ,sizeof (*x));Not unique to this patch, but it seems funny that we use memset followed by explicit initializers for fields that have them. And that as a result of the memset here, we don't calloc when allocate the structs.
Quoted 9 lines
Quoted 4 lines
I would normally never memset a struct, rather than use an initializer but I was going for minimal changes here, I don't plan on this code being around for long.
Famous last words. Don't ever make that assumption ;) Especially given life cycles of distributions that might incorporate said code.
I know, I typed it tongue-in-cheek.
Quoted 8 lines
I know that this is consistent with how we store other modular things and that policyrep will "make all things better". But I'm wondering whether you could have greatly simplified even this "transient" implementation of user transition support by keeping it in symbolic form, even within a "binary" module format, to simplify linking and reduce likelihood of mapping errors.
Quoted 4 lines
I understand and if there were more time I wouldn't mind doing it. Right now I wanted to push these through as fast as possible so that we could maybe get them in to Hardy, which as of right now has no solution to restart services other than rebooting.
Quoted 4 lines
Rushing through a new feature considered harmful. Look, Fedora has lived for years without this feature and works fine, albeit requiring adding
system_rto user accounts and enabling DIRECT_INITRC=y in build.conf.
Seriously - this sounds like a recipe for disaster; the last thing we want is to risk de-stabilizing the Ubuntu kernel with a last minute change, making selinux unusable there. Why not just follow the example of Fedora (and I assume Debian?) here for now and use the above workaround in policy, then you can switch to user transitions in the future once this feature has had time to bake in -mm for a bit and then gone into the mainline kernel.
Quoted 14 lines
Quoted 8 lines
This method is well understood in this codebase and chances are in mapping is broken one place its broken in five so I'm not entirely sure what it would gain us now.
On the note of getting this out quickly I'm hitting this strange kernel but where
class_readsays a common is unknown when I try to load a 23 policy, I'm currently working through that but building ubuntu kernels takes hours :XCute. But a good example of why we shouldn't rush this out. And even if it is implemented tomorrow, what is the likelihood that the Ubuntu kernel folks are going to want to pull it into their existing kernel for this release - at such a late date?
Signature · 8 lines
Stephen Smalley National Security Agency -- This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
Quoted 125 lines · Stephen Smalley
Quoted 115 lines · Stephen Smalley
Quoted 113 lines · Joshua Brindle
Quoted 91 lines · Stephen Smalley
Quoted 88 lines · Joshua Brindle
Quoted 44 lines · Stephen Smalley
Quoted 40 lines · Joshua Brindle
This implements
user_transitionin the toolchain. It should help on distro's like Ubuntu that can't userun_initdue to the user not knowing the root password. It also seems like a more eloquent way to handle service restarts than assigningsystem_rto user accounts and having the daemons run as someuser:system_r:foo_t.This has some issues in policy due to users not always being known in the policy (eg., semanage users). I hope Chris or Dan will be able to give some suggestions there.
The kernel patch (forthcoming after this is accepted) so far only implements the transition on process transitions. Later on I plan on doing a patch to expand
role_transitionto object classes (this is a change needed for policy rbac support to work). I suspect I'll do the same for user at that time. The question here is, do we think its worth it to do fine grained transitions like we did forrange_trans? (I don't).Index:
libsepol/include/sepol/policydb/policydb.h
===================================================================include/sepol/policydb/policydb.h +8
-0@@ -156,6 +156,14 @@mls_level_t exp_dfltlevel;/* expanded range used for validation */ } user_datum_t; +typedef struct user_trans { +uint32_t user;/* current role */ +uint32_t type;/* program executable type */ +uint32_t new_user;/* new role */ +struct user_trans *next; +}user_trans_t ; + +/* Sensitivity attributes */ typedef struct level_datum { mls_level_t *level; /* sensitivity and associated categories */@@ -225,6 +233,13 @@struct role_trans_rule *next; } role_trans_rule_t;Quoted 16 lines
include/sepol/policydb/policydb.h line 244
Quoted 9 lines
include/sepol/policydb/policydb.h +6
-0+typedef struct user_trans_rule { +ebitmap_t users;/* current role */ +type_set_t types;/* program executable type */ +uint32_t new_user;/* new role */ +struct user_trans_rule *next; +}user_trans_rule_t ;Possibly crazy idea - given the current trend, would it be better to just save the user transition rules in symbolic form in the module format. Would that simplify the link/expand code?
Possibly, I am hoping policyrep will supplant this code in the near future so I didn't think about it much. This is consistent with how we store other modular things.
Quoted 21 lines
Quoted 5 lines
Index:
libsepol/src/policydb.c
===================================================================src/policydb.c line 375
Quoted 9 lines
src/policydb.c +3
-0@@ -348,6 +367,30 @@ } } +void user_trans_rule_init (user_trans_rule_t * x) +{ +memset (x,0 ,sizeof (*x));Not unique to this patch, but it seems funny that we use memset followed by explicit initializers for fields that have them. And that as a result of the memset here, we don't calloc when allocate the structs.
Quoted 8 lines
Quoted 3 lines
I would normally never memset a struct, rather than use an initializer but I was going for minimal changes here, I don't plan on this code being around for long.
Famous last words. Don't ever make that assumption ;) Especially given life cycles of distributions that might incorporate said code.
I know, I typed it tongue-in-cheek.
Quoted 9 lines
I know that this is consistent with how we store other modular things and that policyrep will "make all things better". But I'm wondering whether you could have greatly simplified even this "transient" implementation of user transition support by keeping it in symbolic form, even within a "binary" module format, to simplify linking and reduce likelihood of mapping errors.
Quoted 7 lines
Quoted 2 lines
I understand and if there were more time I wouldn't mind doing it. Right now I wanted to push these through as fast as possible so that we could maybe get them in to Hardy, which as of right now has no solution to restart services other than rebooting.
Rushing through a new feature considered harmful. Look, Fedora has lived for years without this feature and works fine, albeit requiring adding
system_rto user accounts and enabling DIRECT_INITRC=y in build.conf.
Quoted 9 lines
Seriously - this sounds like a recipe for disaster; the last thing we want is to risk de-stabilizing the Ubuntu kernel with a last minute change, making selinux unusable there. Why not just follow the example of Fedora (and I assume Debian?) here for now and use the above workaround in policy, then you can switch to user transitions in the future once this feature has had time to bake in -mm for a bit and then gone into the mainline kernel.
Fair enough.
Quoted 10 lines
Quoted 10 lines
Quoted 4 lines
This method is well understood in this codebase and chances are in mapping is broken one place its broken in five so I'm not entirely sure what it would gain us now.
On the note of getting this out quickly I'm hitting this strange kernel but where
class_readsays a common is unknown when I try to load a 23 policy, I'm currently working through that but building ubuntu kernels takes hours :XCute. But a good example of why we shouldn't rush this out. And even if it is implemented tomorrow, what is the likelihood that the Ubuntu kernel folks are going to want to pull it into their existing kernel for this release - at such a late date?
--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.