Index: libsepol/include/sepol/policydb/policydb.h
===================================================================
--- libsepol/include/sepol/policydb/policydb.h (revision 2854)
+++ libsepol/include/sepol/policydb/policydb.h (working copy)
@@ -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
Index: libsepol/src/policydb.c
===================================================================
--- libsepol/src/policydb.c (revision 2854)
+++ libsepol/src/policydb.c (working copy)
@@ -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 {
Index: libsepol/src/expand.c
===================================================================
--- libsepol/src/expand.c (revision 2854)
+++ libsepol/src/expand.c (working copy)
@@ -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;
Index: libsepol/src/write.c
===================================================================
--- libsepol/src/write.c (revision 2854)
+++ libsepol/src/write.c (working copy)
@@ -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 {
Index: libsepol/src/link.c
===================================================================
--- libsepol/src/link.c (revision 2854)
+++ libsepol/src/link.c (working copy)
@@ -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;
Index: checkpolicy/test/dismod.c
===================================================================
--- checkpolicy/test/dismod.c (revision 2854)
+++ checkpolicy/test/dismod.c (working copy)
@@ -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
===================================================================
--- checkpolicy/test/dispol.c (revision 2854)
+++ checkpolicy/test/dispol.c (working copy)
@@ -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
===================================================================
--- checkpolicy/test/Makefile (revision 2854)
+++ checkpolicy/test/Makefile (working copy)
@@ -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)
Index: checkpolicy/policy_define.c
===================================================================
--- checkpolicy/policy_define.c (revision 2854)
+++ checkpolicy/policy_define.c (working copy)
@@ -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
===================================================================
--- checkpolicy/policy_scan.l (revision 2854)
+++ checkpolicy/policy_scan.l (working copy)
@@ -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 |
Index: checkpolicy/policy_define.h
===================================================================
--- checkpolicy/policy_define.h (revision 2854)
+++ checkpolicy/policy_define.h (working copy)
@@ -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
===================================================================
--- checkpolicy/module_compiler.c (revision 2854)
+++ checkpolicy/module_compiler.c (working copy)
@@ -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
===================================================================
--- checkpolicy/policy_parse.y (revision 2854)
+++ checkpolicy/policy_parse.y (working copy)
@@ -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; }
;
Index: checkpolicy/module_compiler.h
===================================================================
--- checkpolicy/module_compiler.h (revision 2854)
+++ checkpolicy/module_compiler.h (working copy)
@@ -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