All of lore.kernel.org
 help / color / mirror / Atom feed
* v4 Add role attribute support to libsepol
@ 2011-07-25  1:23 Harry Ciao
  2011-07-25  1:23 ` [v4 PATCH 1/6] Add role attribute support when compiling modules Harry Ciao
                   ` (6 more replies)
  0 siblings, 7 replies; 8+ messages in thread
From: Harry Ciao @ 2011-07-25  1:23 UTC (permalink / raw)
  To: cpebenito, slawrence, method; +Cc: selinux



Differences from v3 patchset
-----------------------------
1. For the 0002 patch, 
   Introduce MOD_POLICYDB_VERSION_ROLEATTRIB(== 13) and bump
   MOD_POLICYDB_VERSION_MAX to it.

   When read from or write to pp, take care of the flavor flag and roles
   ebitmap only when the pp's version is no less than
   MOD_POLICYDB_VERSION_ROLEATTRIB.
   
  
Tests I've done
-----------------
0. Build tests:
   . revert this patchset, re-install libsepol/checkpolicy packages and
     build modules(have no flavor/roles); apply this patchset, re-install
     everything, the updated tools could handle old version modules in a
     decent manner.
   
   . in write_binary_policy() in checkmodule.c, trigger policy module
     downgrade by adding "policyvers = MOD_POLICYDB_VERSION_MAX - 1"; apply
     this patchset, the updated tools could generate and process old version
     modules correctly.

1. test_t is able to transition into rpm_t, but could not direclty transition
   into rpm_script_t, semanage_t, load_policy_t/setfiles_t:
   
   sh-3.2# sesearch -SCA -s test_t -t rpm_t -c process -p transition
   Found 1 semantic av rules:
      allow test_t rpm_t : process transition ; 
   
   sh-3.2# sesearch -SCA -s test_t -t rpm_script_t -c process -p transition
   
   sh-3.2# sesearch -SCA -s test_t -t semanage_t -c process -p transition
   
   sh-3.2# sesearch -SCA -s test_t -t load_policy_t -c process -p transition
   
   sh-3.2# sesearch -SCA -s test_t -t setfiles_t -c process -p transition
   
2. rpm_t is able to transition into rpm_script_t, but could not directly
   transition into semanage_t, load_policy_t/setfiles_t:
   
   sh-3.2# sesearch -SCA -s rpm_t -t rpm_script_t -c process -p transition
   Found 1 semantic av rules:
      allow rpm_t rpm_script_t : process transition ; 
   
   sh-3.2# sesearch -SCA -s rpm_t -t semanage_t -c process -p transition
   
   sh-3.2# sesearch -SCA -s rpm_t -t load_policy_t -c process -p transition
   
   sh-3.2# sesearch -SCA -s rpm_t -t setfiles_t -c process -p transition
   
3. rpm_script_t is able to transition into semanage_t, but could not directly
   transition into load_policy_t/setfiles_t:
   
   sh-3.2# sesearch -SCA -s rpm_script_t -t semanage_t -c process -p transition
   Found 1 semantic av rules:
      allow rpm_script_t semanage_t : process transition ; 
   
   sh-3.2# sesearch -SCA -s rpm_script_t -t load_policy_t -c process -p transition
   
   sh-3.2# sesearch -SCA -s rpm_script_t -t setfiles_t -c process -p transition
   
4. semanage_t is able to transition into load_policy_t & setfiles_t:
   
   sh-3.2# sesearch -SCA -s semanage_t -t load_policy_t -c process -p transition
   Found 1 semantic av rules:
      allow semanage_t load_policy_t : process transition ; 
   
   sh-3.2# sesearch -SCA -s semanage_t -t setfiles_t -c process -p transition
   Found 1 semantic av rules:
      allow semanage_t setfiles_t : process transition ; 
   
5. test_r is able to type with rpm_t, rpm_script_t, semanage_t, setfiles_t
   and load_policy_t:
   
   sh-3.2# compute_create root:test_r:test_t:s0 system_u:object_r:rpm_exec_t:s0 process
   root:test_r:rpm_t:s0
   sh-3.2# 
   
   sh-3.2# compute_create root:test_r:rpm_script_t:s0 system_u:object_r:semanage_exec_t:s0 process
   root:test_r:semanage_t:s0
   sh-3.2# 
   
   sh-3.2# compute_create root:test_r:semanage_t:s0 system_u:object_r:setfiles_exec_t:s0 process
   root:test_r:setfiles_t:s0
   sh-3.2# 
   
   sh-3.2# compute_create root:test_r:semanage_t:s0 system_u:object_r:load_policy_exec_t:s0 process
   root:test_r:load_policy_t:s0
   sh-3.2# 
   
6. Use the apol tool to analyze what types the test_r role could type with:
   (Since the apol installed on Ubuntu so far only support max version .24,
    we need to setup "policy-version = 24" in semanage.conf)
   
   test_r (28 types)
       chfn_t
       chkpwd_t
       consoletype_t
       ddclient_t
       dhcpc_t
       hostname_t
       ifconfig_t
       insmod_t
       iptables_t
       load_policy_t
       loadkeys_t
       netutils_t
       newrole_t
       pam_t
       passwd_t
       ping_t
       pppd_t
       pptp_t
       rpm_script_t
       rpm_t
       semanage_t
       setfiles_t
       test_t
       traceroute_t
       updpwd_t
       user_home_t
       usernetctl_t
       utempter_t
   
   rpm_roles (2 types)
       rpm_script_t
       rpm_t
   
   semanage_roles (3 types)
       load_policy_t
       semanage_t
       setfiles_t

--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [v4 PATCH 1/6] Add role attribute support when compiling modules.
  2011-07-25  1:23 v4 Add role attribute support to libsepol Harry Ciao
@ 2011-07-25  1:23 ` Harry Ciao
  2011-07-25  1:23 ` [v4 PATCH 2/6] Add role attribute support when generating pp files Harry Ciao
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Harry Ciao @ 2011-07-25  1:23 UTC (permalink / raw)
  To: cpebenito, slawrence, method; +Cc: selinux

1. Add a uint32_t "flavor" field and an ebitmap "roles" to the
role_datum_t structure;

2. Add a new "attribute_role" statement and its handler to declare
a role attribute;

3. Modify declare_role() to setup role_datum_t.flavor according
to the isattr argument;

4. Add a new "roleattribute" rule and its handler, which will record
the regular role's (policy value - 1) into the role attribute's
role_datum_t.roles ebitmap;

5. Modify the syntax for the role-types rule only to define the
role-type associations;

6. Add a new role-attr rule to support the declaration of a single
role, and optionally the role attribute that the role belongs to;

7. Check if the new_role used in role-transition rule is a regular role;

8. Support to require a role attribute;

9. Modify symtab_insert() to allow multiple declarations only for
the regular role, while a role attribute can't be declared more than once
and can't share a same name with another regular role.

Signed-off-by: Harry Ciao <qingtao.cao@windriver.com>
---
 checkpolicy/module_compiler.c              |   67 ++++++++++++-
 checkpolicy/module_compiler.h              |    4 +-
 checkpolicy/policy_define.c                |  152 +++++++++++++++++++++++++++-
 checkpolicy/policy_define.h                |    3 +
 checkpolicy/policy_parse.y                 |   18 +++-
 checkpolicy/policy_scan.l                  |    4 +
 libsepol/include/sepol/policydb/policydb.h |    4 +
 libsepol/src/policydb.c                    |   21 ++++
 8 files changed, 265 insertions(+), 8 deletions(-)

diff --git a/checkpolicy/module_compiler.c b/checkpolicy/module_compiler.c
index 0946ff6..1c1d1d5 100644
--- a/checkpolicy/module_compiler.c
+++ b/checkpolicy/module_compiler.c
@@ -200,7 +200,7 @@ static int role_implicit_bounds(hashtab_t roles_tab,
 	return 0;
 }
 
-role_datum_t *declare_role(void)
+role_datum_t *declare_role(unsigned char isattr)
 {
 	char *id = queue_remove(id_queue), *dest_id = NULL;
 	role_datum_t *role = NULL, *dest_role = NULL;
@@ -217,7 +217,7 @@ role_datum_t *declare_role(void)
 		return NULL;
 	}
 	role_datum_init(role);
-
+	role->flavor = isattr ? ROLE_ATTRIB : ROLE_ROLE;
 	retval =
 	    declare_symbol(SYM_ROLES, id, (hashtab_datum_t *) role, &value,
 			   &value);
@@ -254,6 +254,7 @@ role_datum_t *declare_role(void)
 			}
 			role_datum_init(dest_role);
 			dest_role->s.value = value;
+			dest_role->flavor = isattr ? ROLE_ATTRIB : ROLE_ROLE;
 			if (role_implicit_bounds(roles_tab, dest_id, dest_role)) {
 				free(dest_id);
 				role_datum_destroy(dest_role);
@@ -548,6 +549,55 @@ type_datum_t *get_local_type(char *id, uint32_t value, unsigned char isattr)
 	return dest_typdatum;
 }
 
+/* Return a role_datum_t for the local avrule_decl with the given ID.
+ * If it does not exist, create one with the same value as 'value'.
+ * This function assumes that the ID is within scope.  c.f.,
+ * is_id_in_scope().
+ *
+ * NOTE: this function usurps ownership of id afterwards.  The caller
+ * shall not reference it nor free() it afterwards.
+ */
+role_datum_t *get_local_role(char *id, uint32_t value, unsigned char isattr)
+{
+	role_datum_t *dest_roledatum;
+	hashtab_t roles_tab;
+
+	assert(stack_top->type == 1);
+
+	if (stack_top->parent == NULL) {
+		/* in global, so use global symbol table */
+		roles_tab = policydbp->p_roles.table;
+	} else {
+		roles_tab = stack_top->decl->p_roles.table;
+	}
+
+	dest_roledatum = hashtab_search(roles_tab, id);
+	if (!dest_roledatum) {
+		dest_roledatum = (role_datum_t *)malloc(sizeof(role_datum_t));
+		if (dest_roledatum == NULL) {
+			free(id);
+			return NULL;
+		}
+
+		role_datum_init(dest_roledatum);
+		dest_roledatum->s.value = value;
+		dest_roledatum->flavor = isattr ? ROLE_ATTRIB : ROLE_ROLE;
+
+		if (hashtab_insert(roles_tab, id, dest_roledatum)) {
+			free(id);
+			role_datum_destroy(dest_roledatum);
+			free(dest_roledatum);
+			return NULL;
+		}
+	} else {
+		free(id);
+		if (dest_roledatum->flavor != isattr ? ROLE_ATTRIB : ROLE_ROLE)
+			return NULL;
+	}
+	
+	return dest_roledatum;
+}
+
 /* Given the current parse stack, returns 1 if a requirement would be
  * allowed here or 0 if not.  For example, the ELSE branch may never
  * have its own requirements.
@@ -812,7 +862,7 @@ int require_class(int pass)
 	return -1;
 }
 
-int require_role(int pass)
+static int require_role_or_attribute(int pass, unsigned char isattr)
 {
 	char *id = queue_remove(id_queue);
 	role_datum_t *role = NULL;
@@ -831,6 +881,7 @@ int require_role(int pass)
 		return -1;
 	}
 	role_datum_init(role);
+	role->flavor = isattr ? ROLE_ATTRIB : ROLE_ROLE;
 	retval =
 	    require_symbol(SYM_ROLES, id, (hashtab_datum_t *) role,
 			   &role->s.value, &role->s.value);
@@ -870,6 +921,16 @@ int require_role(int pass)
 	}
 }
 
+int require_role(int pass)
+{
+	return require_role_or_attribute(pass, 0);
+}
+
+int require_attribute_role(int pass)
+{
+	return require_role_or_attribute(pass, 1);
+}
+
 static int require_type_or_attribute(int pass, unsigned char isattr)
 {
 	char *id = queue_remove(id_queue);
diff --git a/checkpolicy/module_compiler.h b/checkpolicy/module_compiler.h
index ae33753..45a21cd 100644
--- a/checkpolicy/module_compiler.h
+++ b/checkpolicy/module_compiler.h
@@ -30,11 +30,12 @@ int declare_symbol(uint32_t symbol_type,
 		   hashtab_key_t key, hashtab_datum_t datum,
 		   uint32_t * dest_value, uint32_t * datum_value);
 
-role_datum_t *declare_role(void);
+role_datum_t *declare_role(unsigned char isattr);
 type_datum_t *declare_type(unsigned char primary, unsigned char isattr);
 user_datum_t *declare_user(void);
 
 type_datum_t *get_local_type(char *id, uint32_t value, unsigned char isattr);
+role_datum_t *get_local_role(char *id, uint32_t value, unsigned char isattr);
 
 /* Add a symbol to the current avrule_block's require section.  Note
  * that a module may not both declare and require the same symbol.
@@ -54,6 +55,7 @@ int require_class(int pass);
 int require_role(int pass);
 int require_type(int pass);
 int require_attribute(int pass);
+int require_attribute_role(int pass);
 int require_user(int pass);
 int require_bool(int pass);
 int require_sens(int pass);
diff --git a/checkpolicy/policy_define.c b/checkpolicy/policy_define.c
index f75a682..92646a0 100644
--- a/checkpolicy/policy_define.c
+++ b/checkpolicy/policy_define.c
@@ -1774,6 +1774,9 @@ int define_te_avtab(int which)
 	return 0;
 }
 
+/* The role-types rule is no longer used to declare regular role or
+ * role attribute, but solely aimed for declaring role-types associations.
+ */
 int define_role_types(void)
 {
 	role_datum_t *role;
@@ -1786,9 +1789,25 @@ int define_role_types(void)
 		return 0;
 	}
 
-	if ((role = declare_role()) == NULL) {
+	id = (char *)queue_remove(id_queue);
+	if (!id) {
+		yyerror("no role name for role-types rule?");
+		return -1;
+	}
+
+	if (!is_id_in_scope(SYM_ROLES, id)) {
+		yyerror2("role %s is not within scope", id);
+		free(id);
+		return -1;
+	}
+
+	role = hashtab_search(policydbp->p_roles.table, id);
+	if (!role) {
+		yyerror2("unknown role %s", id);
+		free(id);
 		return -1;
 	}
+
 	while ((id = queue_remove(id_queue))) {
 		if (set_types(&role->types, id, &add, 0))
 			return -1;
@@ -1797,6 +1816,132 @@ int define_role_types(void)
 	return 0;
 }
 
+int define_attrib_role(void)
+{
+	if (pass == 2) {
+		free(queue_remove(id_queue));
+		return 0;
+	}
+
+	/* Declare a role attribute */
+	if (declare_role(TRUE) == NULL)
+		return -1;
+
+	return 0;
+}
+
+int define_role_attr(void)
+{
+	char *id;
+	role_datum_t *r, *attr;
+
+	if (pass == 2) {
+		while ((id = queue_remove(id_queue)))
+			free(id);
+		return 0;
+	}
+	
+	/* Declare a regular role */
+	if ((r = declare_role(FALSE)) == NULL)
+		return -1;
+
+	while ((id = queue_remove(id_queue))) {
+		if (!is_id_in_scope(SYM_ROLES, id)) {
+			yyerror2("attribute %s is not within scope", id);
+			free(id);
+			return -1;
+		}
+		attr = hashtab_search(policydbp->p_roles.table, id);
+		if (!attr) {
+			/* treat it as a fatal error */
+			yyerror2("role attribute %s is not declared", id);
+			free(id);
+			return -1;
+		}
+
+		if (attr->flavor != ROLE_ATTRIB) {
+			yyerror2("%s is a regular role, not an attribute", id);
+			free(id);
+			return -1;
+		}
+
+		if ((attr = get_local_role(id, attr->s.value, 1)) == NULL) {
+			yyerror("Out of memory!");
+			return -1;
+		}
+
+		if (ebitmap_set_bit(&attr->roles, (r->s.value - 1), TRUE)) {
+			yyerror("out of memory");
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
+int define_roleattribute(void)
+{
+	char *id;
+	role_datum_t *r, *attr;
+
+	if (pass == 2) {
+		while ((id = queue_remove(id_queue)))
+			free(id);
+		return 0;
+	}
+
+	id = (char *)queue_remove(id_queue);
+	if (!id) {
+		yyerror("no role name for roleattribute definition?");
+		return -1;
+	}
+
+	if (!is_id_in_scope(SYM_ROLES, id)) {
+		yyerror2("role %s is not within scope", id);
+		free(id);
+		return -1;
+	}
+	r = hashtab_search(policydbp->p_roles.table, id);
+	if (!r || r->flavor != ROLE_ROLE) {
+		yyerror2("unknown role %s, or not a regular role", id);
+		free(id);
+		return -1;
+	}
+
+	while ((id = queue_remove(id_queue))) {
+		if (!is_id_in_scope(SYM_ROLES, id)) {
+			yyerror2("attribute %s is not within scope", id);
+			free(id);
+			return -1;
+		}
+		attr = hashtab_search(policydbp->p_roles.table, id);
+		if (!attr) {
+			/* treat it as a fatal error */
+			yyerror2("role attribute %s is not declared", id);
+			free(id);
+			return -1;
+		}
+
+		if (attr->flavor != ROLE_ATTRIB) {
+			yyerror2("%s is a regular role, not an attribute", id);
+			free(id);
+			return -1;
+		}
+
+		if ((attr = get_local_role(id, attr->s.value, 1)) == NULL) {
+			yyerror("Out of memory!");
+			return -1;
+		}
+
+		if (ebitmap_set_bit(&attr->roles, (r->s.value - 1), TRUE)) {
+			yyerror("out of memory");
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
 role_datum_t *merge_roles_dom(role_datum_t * r1, role_datum_t * r2)
 {
 	role_datum_t *new;
@@ -2138,6 +2283,11 @@ int define_role_trans(int class_specified)
 		goto bad;
 	}
 
+	if (role->flavor != ROLE_ROLE) {
+		yyerror2("the new role %s must be a regular role", id);
+		goto bad;
+	}
+
 	/* This ebitmap business is just to ensure that there are not conflicting role_trans rules */
 	if (role_set_expand(&roles, &e_roles, policydbp, NULL))
 		goto bad;
diff --git a/checkpolicy/policy_define.h b/checkpolicy/policy_define.h
index 890a6af..fc8cd4d 100644
--- a/checkpolicy/policy_define.h
+++ b/checkpolicy/policy_define.h
@@ -19,6 +19,7 @@ avrule_t *define_cond_te_avtab(int which);
 avrule_t *define_cond_filename_trans(void);
 cond_expr_t *define_cond_expr(uint32_t expr_type, void *arg1, void* arg2);
 int define_attrib(void);
+int define_attrib_role(void);
 int define_av_perms(int inherits);
 int define_bool(void);
 int define_category(void);
@@ -48,6 +49,8 @@ int define_range_trans(int class_specified);
 int define_role_allow(void);
 int define_role_trans(int class_specified);
 int define_role_types(void);
+int define_role_attr(void);
+int define_roleattribute(void);
 int define_filename_trans(void);
 int define_sens(void);
 int define_te_avtab(int which);
diff --git a/checkpolicy/policy_parse.y b/checkpolicy/policy_parse.y
index 5305ac6..6567369 100644
--- a/checkpolicy/policy_parse.y
+++ b/checkpolicy/policy_parse.y
@@ -90,6 +90,8 @@ typedef int (* require_func_t)();
 %token INHERITS
 %token SID
 %token ROLE
+%token ROLEATTRIBUTE
+%token ATTRIBUTE_ROLE
 %token ROLES
 %token TYPEALIAS
 %token TYPEATTRIBUTE
@@ -253,10 +255,13 @@ te_rbac_decl		: te_decl
 			| policycap_def
 			| ';'
                         ;
-rbac_decl		: role_type_def
+rbac_decl		: attribute_role_def
+			| role_type_def
                         | role_dominance
                         | role_trans_def
  			| role_allow_def
+			| roleattribute_def
+			| role_attr_def
 			;
 te_decl			: attribute_def
                         | type_def
@@ -417,10 +422,13 @@ dontaudit_def		: DONTAUDIT names names ':' names names ';'
 neverallow_def		: NEVERALLOW names names ':' names names  ';'
 			{if (define_te_avtab(AVRULE_NEVERALLOW)) return -1; }
 		        ;
+attribute_role_def	: ATTRIBUTE_ROLE identifier ';'
+			{if (define_attrib_role()) return -1; }
 role_type_def		: ROLE identifier TYPES names ';'
 			{if (define_role_types()) return -1;}
- 			| ROLE identifier';'
- 			{if (define_role_types()) return -1;}
+			;
+role_attr_def		: ROLE identifier opt_attr_list ';'
+ 			{if (define_role_attr()) return -1;}
                         ;
 role_dominance		: DOMINANCE '{' roles '}'
 			;
@@ -442,6 +450,9 @@ role_def		: ROLE identifier_push ';'
 			| ROLE identifier_push '{' roles '}'
                         {$$ = define_role_dom((role_datum_t*)$4); if ($$ == 0) return -1;}
 			;
+roleattribute_def	: ROLEATTRIBUTE identifier id_comma_list ';'
+			{if (define_roleattribute()) return -1;}
+			;
 opt_constraints         : constraints
                         |
                         ;
@@ -803,6 +814,7 @@ require_class           : CLASS identifier names
 require_decl_def        : ROLE        { $$ = require_role; }
                         | TYPE        { $$ = require_type; }
                         | ATTRIBUTE   { $$ = require_attribute; }
+                        | ATTRIBUTE_ROLE   { $$ = require_attribute_role; }
                         | USER        { $$ = require_user; }
                         | BOOL        { $$ = require_bool; }
                         | SENSITIVITY { $$ = require_sens; }
diff --git a/checkpolicy/policy_scan.l b/checkpolicy/policy_scan.l
index 1e7e567..8abc4d9 100644
--- a/checkpolicy/policy_scan.l
+++ b/checkpolicy/policy_scan.l
@@ -76,6 +76,10 @@ ROLE |
 role				{ return(ROLE); }
 ROLES |
 roles				{ return(ROLES); }
+ROLEATTRIBUTE |
+roleattribute			{ return(ROLEATTRIBUTE);}
+ATTRIBUTE_ROLE |
+attribute_role			{ return(ATTRIBUTE_ROLE);}
 TYPES |
 types				{ return(TYPES); }
 TYPEALIAS |
diff --git a/libsepol/include/sepol/policydb/policydb.h b/libsepol/include/sepol/policydb/policydb.h
index eebf1a9..b59ab2e 100644
--- a/libsepol/include/sepol/policydb/policydb.h
+++ b/libsepol/include/sepol/policydb/policydb.h
@@ -120,6 +120,10 @@ typedef struct role_datum {
 	type_set_t types;	/* set of authorized types for role */
 	ebitmap_t cache;	/* This is an expanded set used for context validation during parsing */
 	uint32_t bounds;	/* bounds role, if exist */
+#define ROLE_ROLE 0		/* regular role in kernel policies */
+#define ROLE_ATTRIB 1		/* attribute */
+	uint32_t flavor;
+	ebitmap_t roles;	/* roles with this attribute */
 } role_datum_t;
 
 typedef struct role_trans {
diff --git a/libsepol/src/policydb.c b/libsepol/src/policydb.c
index 6d8ff91..eb6d590 100644
--- a/libsepol/src/policydb.c
+++ b/libsepol/src/policydb.c
@@ -350,6 +350,7 @@ void role_datum_init(role_datum_t * x)
 	ebitmap_init(&x->dominates);
 	type_set_init(&x->types);
 	ebitmap_init(&x->cache);
+	ebitmap_init(&x->roles);
 }
 
 void role_datum_destroy(role_datum_t * x)
@@ -358,6 +359,7 @@ void role_datum_destroy(role_datum_t * x)
 		ebitmap_destroy(&x->dominates);
 		type_set_destroy(&x->types);
 		ebitmap_destroy(&x->cache);
+		ebitmap_destroy(&x->roles);
 	}
 }
 
@@ -1429,6 +1431,25 @@ int symtab_insert(policydb_t * pol, uint32_t sym,
 		if (sym != SYM_ROLES && sym != SYM_USERS) {
 			return -2;
 		}
+		/* Further confine that a role attribute can't have the same
+		 * name as another regular role, and a role attribute can't
+		 * be declared more than once. */
+		if (sym == SYM_ROLES) {
+			role_datum_t *base_role;
+			role_datum_t *cur_role = (role_datum_t *)datum;
+		
+			base_role = (role_datum_t *)
+					hashtab_search(pol->symtab[sym].table,
+						       key);
+			assert(base_role != NULL);
+
+			if (!((base_role->flavor == ROLE_ROLE) &&
+			    (cur_role->flavor == ROLE_ROLE))) {
+				/* Only regular roles are allowed to have
+				 * multiple declarations. */
+				return -2;
+			}
+		}
 	} else if (scope_datum->scope == SCOPE_REQ && scope == SCOPE_DECL) {
 		scope_datum->scope = SCOPE_DECL;
 	} else if (scope_datum->scope != scope) {
-- 
1.7.0.4


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [v4 PATCH 2/6] Add role attribute support when generating pp files.
  2011-07-25  1:23 v4 Add role attribute support to libsepol Harry Ciao
  2011-07-25  1:23 ` [v4 PATCH 1/6] Add role attribute support when compiling modules Harry Ciao
@ 2011-07-25  1:23 ` Harry Ciao
  2011-07-25  1:23 ` [v4 PATCH 3/6] Add role attribute support when linking modules Harry Ciao
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Harry Ciao @ 2011-07-25  1:23 UTC (permalink / raw)
  To: cpebenito, slawrence, method; +Cc: selinux

Add support to read/write the flavor flag and roles ebitmap in the
role_datum_t structure from/to policy module, if its version is no less
than MOD_POLICYDB_VERSION_ROLEATTRIB.

Since the role ebitmap would be expanded and won't be written into
policy.X, neither is the flavor flag, kernel SELinux security server
needs no change, the maximum version number for policy.X needs no bump.

Signed-off-by: Harry Ciao <qingtao.cao@windriver.com>
---
 libsepol/include/sepol/policydb/policydb.h |    3 ++-
 libsepol/src/policydb.c                    |   26 ++++++++++++++++++++++++++
 libsepol/src/write.c                       |   11 +++++++++++
 3 files changed, 39 insertions(+), 1 deletions(-)

diff --git a/libsepol/include/sepol/policydb/policydb.h b/libsepol/include/sepol/policydb/policydb.h
index b59ab2e..5320bc8 100644
--- a/libsepol/include/sepol/policydb/policydb.h
+++ b/libsepol/include/sepol/policydb/policydb.h
@@ -682,9 +682,10 @@ extern int policydb_set_target_platform(policydb_t *p, int platform);
 #define MOD_POLICYDB_VERSION_BOUNDARY_ALIAS	10
 #define MOD_POLICYDB_VERSION_FILENAME_TRANS	11
 #define MOD_POLICYDB_VERSION_ROLETRANS		12
+#define MOD_POLICYDB_VERSION_ROLEATTRIB		13
 
 #define MOD_POLICYDB_VERSION_MIN MOD_POLICYDB_VERSION_BASE
-#define MOD_POLICYDB_VERSION_MAX MOD_POLICYDB_VERSION_ROLETRANS
+#define MOD_POLICYDB_VERSION_MAX MOD_POLICYDB_VERSION_ROLEATTRIB
 
 #define POLICYDB_CONFIG_MLS    1
 
diff --git a/libsepol/src/policydb.c b/libsepol/src/policydb.c
index eb6d590..9145f2a 100644
--- a/libsepol/src/policydb.c
+++ b/libsepol/src/policydb.c
@@ -214,6 +214,13 @@ static struct policydb_compat_info policydb_compat[] = {
 	 .target_platform = SEPOL_TARGET_SELINUX,
 	},
 	{
+	 .type = POLICY_BASE,
+	 .version = MOD_POLICYDB_VERSION_ROLEATTRIB,
+	 .sym_num = SYM_NUM,
+	 .ocon_num = OCON_NODE6 + 1,
+	 .target_platform = SEPOL_TARGET_SELINUX,
+	},
+	{
 	 .type = POLICY_MOD,
 	 .version = MOD_POLICYDB_VERSION_BASE,
 	 .sym_num = SYM_NUM,
@@ -276,6 +283,13 @@ static struct policydb_compat_info policydb_compat[] = {
 	 .ocon_num = 0,
 	 .target_platform = SEPOL_TARGET_SELINUX,
 	},
+	{
+	 .type = POLICY_MOD,
+	 .version = MOD_POLICYDB_VERSION_ROLEATTRIB,
+	 .sym_num = SYM_NUM,
+	 .ocon_num = 0,
+	 .target_platform = SEPOL_TARGET_SELINUX,
+	},
 };
 
 #if 0
@@ -2090,6 +2104,18 @@ static int role_read(policydb_t * p
 		if (type_set_read(&role->types, fp))
 			goto bad;
 	}
+	
+	if (p->policy_type != POLICY_KERN &&
+	    p->policyvers >= MOD_POLICYDB_VERSION_ROLEATTRIB) {
+		rc = next_entry(buf, fp, sizeof(uint32_t));
+		if (rc < 0)
+			goto bad;
+
+		role->flavor = le32_to_cpu(buf[0]);
+
+		if (ebitmap_read(&role->roles, fp))
+			goto bad;
+	}
 
 	if (strcmp(key, OBJECT_R) == 0) {
 		if (role->s.value != OBJECT_R_VAL) {
diff --git a/libsepol/src/write.c b/libsepol/src/write.c
index 9657e6c..290e036 100644
--- a/libsepol/src/write.c
+++ b/libsepol/src/write.c
@@ -996,6 +996,17 @@ static int role_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
 			return POLICYDB_ERROR;
 	}
 
+	if (p->policy_type != POLICY_KERN &&
+	    p->policyvers >= MOD_POLICYDB_VERSION_ROLEATTRIB) {
+		buf[0] = cpu_to_le32(role->flavor);
+		items = put_entry(buf, sizeof(uint32_t), 1, fp);
+		if (items != 1)
+			return POLICYDB_ERROR;
+
+		if (ebitmap_write(&role->roles, fp))
+			return POLICYDB_ERROR;
+	}
+
 	return POLICYDB_SUCCESS;
 }
 
-- 
1.7.0.4


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [v4 PATCH 3/6] Add role attribute support when linking modules.
  2011-07-25  1:23 v4 Add role attribute support to libsepol Harry Ciao
  2011-07-25  1:23 ` [v4 PATCH 1/6] Add role attribute support when compiling modules Harry Ciao
  2011-07-25  1:23 ` [v4 PATCH 2/6] Add role attribute support when generating pp files Harry Ciao
@ 2011-07-25  1:23 ` Harry Ciao
  2011-07-25  1:23 ` [v4 PATCH 4/6] Add role attribute support when expanding role_datum_t Harry Ciao
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Harry Ciao @ 2011-07-25  1:23 UTC (permalink / raw)
  To: cpebenito, slawrence, method; +Cc: selinux

Make the flavor flag and the roles ebitmap in role_datum_t structure
properly handled during module link process:

1. the flavor flag is copied into the base module;

2. if both the current module and the base module have defined or
required the same role, check if there is a discrepency in flavor;

3. remap the roles ebitmap and merge into its counterpart in the
base module;

Signed-off-by: Harry Ciao <qingtao.cao@windriver.com>
---
 libsepol/src/link.c |   42 ++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 40 insertions(+), 2 deletions(-)

diff --git a/libsepol/src/link.c b/libsepol/src/link.c
index 23dbb1b..53fcff9 100644
--- a/libsepol/src/link.c
+++ b/libsepol/src/link.c
@@ -312,7 +312,25 @@ static int role_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
 	role = (role_datum_t *) datum;
 
 	base_role = hashtab_search(state->base->p_roles.table, id);
-	if (base_role == NULL) {
+	if (base_role != NULL) {
+		/* role already exists.  check that it is what this
+		 * module expected.  duplicate declarations (e.g., two
+		 * modules both declare role foo_r) is checked during
+		 * scope_copy_callback(). */
+		if (role->flavor == ROLE_ATTRIB
+		    && base_role->flavor != ROLE_ATTRIB) {
+			ERR(state->handle,
+			    "%s: Expected %s to be a role attribute, but it was already declared as a regular role.",
+			    state->cur_mod_name, id);
+			return -1;
+		} else if (role->flavor != ROLE_ATTRIB
+			   && base_role->flavor == ROLE_ATTRIB) {
+			ERR(state->handle,
+			    "%s: Expected %s to be a regular role, but it was already declared as a role attribute.",
+			    state->cur_mod_name, id);
+			return -1;
+		}
+	} else {
 		if (state->verbose)
 			INFO(state->handle, "copying role %s", id);
 
@@ -326,8 +344,9 @@ static int role_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
 		}
 		role_datum_init(new_role);
 
-		/* new_role's dominates and types field will be copied
+		/* new_role's dominates, types and roles field will be copied
 		 * during role_fix_callback() */
+		new_role->flavor = role->flavor;
 		new_role->s.value = state->base->p_roles.nprim + 1;
 
 		ret = hashtab_insert(state->base->p_roles.table,
@@ -346,6 +365,7 @@ static int role_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
 			goto cleanup;
 		}
 		role_datum_init(new_role);
+		new_role->flavor = base_role->flavor;
 		new_role->s.value = base_role->s.value;
 		if ((new_id = strdup(id)) == NULL) {
 			goto cleanup;
@@ -1046,6 +1066,24 @@ static int role_fix_callback(hashtab_key_t key, hashtab_datum_t datum,
 		goto cleanup;
 	}
 	ebitmap_destroy(&e_tmp);
+	
+	if (role->flavor == ROLE_ATTRIB) {
+		ebitmap_init(&e_tmp);
+		ebitmap_for_each_bit(&role->roles, rnode, i) {
+			if (ebitmap_node_get_bit(rnode, i)) {
+				assert(mod->map[SYM_ROLES][i]);
+				if (ebitmap_set_bit
+				    (&e_tmp, mod->map[SYM_ROLES][i] - 1, 1)) {
+					goto cleanup;
+				}
+			}
+		}
+		if (ebitmap_union(&dest_role->roles, &e_tmp)) {
+			goto cleanup;
+		}
+		ebitmap_destroy(&e_tmp);
+	}
+
 	return 0;
 
       cleanup:
-- 
1.7.0.4


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [v4 PATCH 4/6] Add role attribute support when expanding role_datum_t.
  2011-07-25  1:23 v4 Add role attribute support to libsepol Harry Ciao
                   ` (2 preceding siblings ...)
  2011-07-25  1:23 ` [v4 PATCH 3/6] Add role attribute support when linking modules Harry Ciao
@ 2011-07-25  1:23 ` Harry Ciao
  2011-07-25  1:23 ` [v4 PATCH 5/6] Add role attribute support when expanding role_set_t Harry Ciao
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Harry Ciao @ 2011-07-25  1:23 UTC (permalink / raw)
  To: cpebenito, slawrence, method; +Cc: selinux

1. Copy the flavor flag into its counterpart in the out module;

2. Fix all role attributes in the base module:
2.1 remap the roles ebitmap and merge into its counterpart in the
out module;
2.2 escalate the types.types ebitmap of its counterpart in the out
module, to the counterparts for all the regular roles that belongs
to the current role attribute.

The role_fix_callback() must be called after role_copy_callback()
so that state->rolemap[] is available.

Signed-off-by: Harry Ciao <qingtao.cao@windriver.com>
---
 libsepol/src/expand.c |   75 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 75 insertions(+), 0 deletions(-)

diff --git a/libsepol/src/expand.c b/libsepol/src/expand.c
index b1af365..2dbbd27 100644
--- a/libsepol/src/expand.c
+++ b/libsepol/src/expand.c
@@ -664,6 +664,73 @@ static int role_remap_dominates(hashtab_key_t key __attribute__ ((unused)), hash
 	return 0;
 }
 
+/* For the role attribute in the base module, escalate its counterpart's
+ * types.types ebitmap in the out module to the counterparts of all the
+ * regular role that belongs to the current role attribute. Note, must be
+ * invoked after role_copy_callback so that state->rolemap is available.
+ */
+static int role_fix_callback(hashtab_key_t key, hashtab_datum_t datum,
+			     void *data)
+{
+	char *id, *base_reg_role_id;
+	role_datum_t *role, *new_role, *regular_role;
+	expand_state_t *state;
+	ebitmap_node_t *rnode;
+	unsigned int i;
+	ebitmap_t mapped_roles;
+
+	id = key;
+	role = (role_datum_t *)datum;
+	state = (expand_state_t *)data;
+
+	if (strcmp(id, OBJECT_R) == 0) {
+		/* object_r is never a role attribute by far */
+		return 0;
+	}
+
+	if (role->flavor != ROLE_ATTRIB)
+		return 0;
+
+	if (state->verbose)
+		INFO(state->handle, "fixing role attribute %s", id);
+
+	new_role =
+		(role_datum_t *)hashtab_search(state->out->p_roles.table, id);
+
+	assert(new_role != NULL && new_role->flavor == ROLE_ATTRIB);
+
+	ebitmap_init(&mapped_roles);
+	if (map_ebitmap(&role->roles, &mapped_roles, state->rolemap))
+		return -1;
+	if (ebitmap_union(&new_role->roles, &mapped_roles)) {
+		ERR(state->handle, "Out of memory!");
+		ebitmap_destroy(&mapped_roles);
+		return -1;
+	}
+	ebitmap_destroy(&mapped_roles);
+
+	ebitmap_for_each_bit(&role->roles, rnode, i) {
+		if (ebitmap_node_get_bit(rnode, i)) {
+			/* take advantage of sym_val_to_name[]
+			 * of the base module */
+			base_reg_role_id = state->base->p_role_val_to_name[i];
+			regular_role = (role_datum_t *)hashtab_search(
+						state->out->p_roles.table,
+						base_reg_role_id);
+			assert(regular_role != NULL && 
+			       regular_role->flavor == ROLE_ROLE);
+
+			if (ebitmap_union(&regular_role->types.types, 
+					  &new_role->types.types)) {
+				ERR(state->handle, "Out of memory!");
+				return -1;
+			}
+		}
+	}
+	
+	return 0;
+}
+
 static int role_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
 			      void *data)
 {
@@ -709,6 +776,7 @@ static int role_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
 		}
 
 		state->out->p_roles.nprim++;
+		new_role->flavor = role->flavor;
 		new_role->s.value = state->out->p_roles.nprim;
 		state->rolemap[role->s.value - 1] = new_role->s.value;
 		ret = hashtab_insert(state->out->p_roles.table,
@@ -2673,6 +2741,10 @@ int expand_module(sepol_handle_t * handle,
 	if (hashtab_map(state.base->p_roles.table,
 			role_bounds_copy_callback, &state))
 		goto cleanup;
+	/* escalate the type_set_t in a role attribute to all regular roles
+	 * that belongs to it. */
+	if (hashtab_map(state.base->p_roles.table, role_fix_callback, &state))
+		goto cleanup;
 
 	/* copy MLS's sensitivity level and categories - this needs to be done
 	 * before expanding users (they need to be indexed too) */
@@ -2725,6 +2797,9 @@ int expand_module(sepol_handle_t * handle,
 		if (hashtab_map
 		    (decl->p_roles.table, role_copy_callback, &state))
 			goto cleanup;
+		if (hashtab_map
+		    (decl->p_roles.table, role_fix_callback, &state))
+			goto cleanup;
 
 		/* copy users */
 		if (hashtab_map
-- 
1.7.0.4


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [v4 PATCH 5/6] Add role attribute support when expanding role_set_t.
  2011-07-25  1:23 v4 Add role attribute support to libsepol Harry Ciao
                   ` (3 preceding siblings ...)
  2011-07-25  1:23 ` [v4 PATCH 4/6] Add role attribute support when expanding role_datum_t Harry Ciao
@ 2011-07-25  1:23 ` Harry Ciao
  2011-07-25  1:23 ` [v4 PATCH 6/6] Support adding one role attribute into another Harry Ciao
  2011-07-25 15:42 ` v4 Add role attribute support to libsepol Steve Lawrence
  6 siblings, 0 replies; 8+ messages in thread
From: Harry Ciao @ 2011-07-25  1:23 UTC (permalink / raw)
  To: cpebenito, slawrence, method; +Cc: selinux

When the rolemap and pointer to the base module are available, if
a non-zero bit in role_set_t.roles is a role attribute, expand it
before remap.

Note, during module compile the rolemap may not be available, the
potential duplicates of a regular role and the role attribute that
the regular role belongs to could be properly handled by
copy_role_allow() and copy_role_trans() during module expansion.

Take advantage of the role_val_to_struct[] of the base module, since
when role_set_expand() is invoked, the role_val_to_struct[] of the
out module may have not been established yet.

Also cleanup the error handling of role_set_expand().

Signed-off-by: Harry Ciao <qingtao.cao@windriver.com>
---
 checkpolicy/policy_define.c              |    2 +-
 libsepol/include/sepol/policydb/expand.h |    2 +-
 libsepol/src/expand.c                    |   57 ++++++++++++++++++++++++------
 libsepol/src/policydb.c                  |    2 +-
 libsepol/src/users.c                     |    4 +-
 5 files changed, 51 insertions(+), 16 deletions(-)

diff --git a/checkpolicy/policy_define.c b/checkpolicy/policy_define.c
index 92646a0..6faaf94 100644
--- a/checkpolicy/policy_define.c
+++ b/checkpolicy/policy_define.c
@@ -2289,7 +2289,7 @@ int define_role_trans(int class_specified)
 	}
 
 	/* This ebitmap business is just to ensure that there are not conflicting role_trans rules */
-	if (role_set_expand(&roles, &e_roles, policydbp, NULL))
+	if (role_set_expand(&roles, &e_roles, policydbp, NULL, NULL))
 		goto bad;
 
 	if (type_set_expand(&types, &e_types, policydbp, 1))
diff --git a/libsepol/include/sepol/policydb/expand.h b/libsepol/include/sepol/policydb/expand.h
index 059b065..31e25ec 100644
--- a/libsepol/include/sepol/policydb/expand.h
+++ b/libsepol/include/sepol/policydb/expand.h
@@ -60,7 +60,7 @@ extern int expand_convert_type_set(policydb_t * p, uint32_t * typemap,
 				   unsigned char alwaysexpand);
 extern int type_set_expand(type_set_t * set, ebitmap_t * t, policydb_t * p,
 			   unsigned char alwaysexpand);
-extern int role_set_expand(role_set_t * x, ebitmap_t * r, policydb_t * p, uint32_t * rolemap);
+extern int role_set_expand(role_set_t * x, ebitmap_t * r, policydb_t * out, policydb_t * base, uint32_t * rolemap);
 extern int mls_semantic_level_expand(mls_semantic_level_t *sl, mls_level_t *l,
                                      policydb_t *p, sepol_handle_t *h);
 extern int mls_semantic_range_expand(mls_semantic_range_t *sr, mls_range_t *r,
diff --git a/libsepol/src/expand.c b/libsepol/src/expand.c
index 2dbbd27..b42acbe 100644
--- a/libsepol/src/expand.c
+++ b/libsepol/src/expand.c
@@ -981,7 +981,7 @@ static int user_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
 	ebitmap_init(&tmp_union);
 
 	/* get global roles for this user */
-	if (role_set_expand(&user->roles, &tmp_union, state->base, state->rolemap)) {
+	if (role_set_expand(&user->roles, &tmp_union, state->out, state->base, state->rolemap)) {
 		ERR(state->handle, "Out of memory!");
 		ebitmap_destroy(&tmp_union);
 		return -1;
@@ -1159,12 +1159,12 @@ static int copy_role_allows(expand_state_t * state, role_allow_rule_t * rules)
 		ebitmap_init(&roles);
 		ebitmap_init(&new_roles);
 
-		if (role_set_expand(&cur->roles, &roles, state->out, state->rolemap)) {
+		if (role_set_expand(&cur->roles, &roles, state->out, state->base, state->rolemap)) {
 			ERR(state->handle, "Out of memory!");
 			return -1;
 		}
 
-		if (role_set_expand(&cur->new_roles, &new_roles, state->out, state->rolemap)) {
+		if (role_set_expand(&cur->new_roles, &new_roles, state->out, state->base, state->rolemap)) {
 			ERR(state->handle, "Out of memory!");
 			return -1;
 		}
@@ -1228,7 +1228,7 @@ static int copy_role_trans(expand_state_t * state, role_trans_rule_t * rules)
 		ebitmap_init(&roles);
 		ebitmap_init(&types);
 
-		if (role_set_expand(&cur->roles, &roles, state->out, state->rolemap)) {
+		if (role_set_expand(&cur->roles, &roles, state->out, state->base, state->rolemap)) {
 			ERR(state->handle, "Out of memory!");
 			return -1;
 		}
@@ -2267,14 +2267,23 @@ int expand_rule(sepol_handle_t * handle,
 	return retval;
 }
 
-int role_set_expand(role_set_t * x, ebitmap_t * r, policydb_t * p, uint32_t * rolemap)
+/* Expand a role set into an ebitmap containing the roles.
+ * This handles the attribute and flags.
+ * Attribute expansion depends on if the rolemap is available.
+ * During module compile the rolemap is not available, the
+ * possible duplicates of a regular role and the role attribute
+ * the regular role belongs to could be properly handled by
+ * copy_role_trans and copy_role_allow.
+ */
+int role_set_expand(role_set_t * x, ebitmap_t * r, policydb_t * out, policydb_t * base, uint32_t * rolemap)
 {
 	unsigned int i;
 	ebitmap_node_t *rnode;
-	ebitmap_t mapped_roles;
+	ebitmap_t mapped_roles, roles;
+	policydb_t *p = out;
+	role_datum_t *role;
 
 	ebitmap_init(r);
-	ebitmap_init(&mapped_roles);
 
 	if (x->flags & ROLE_STAR) {
 		for (i = 0; i < p->p_roles.nprim++; i++)
@@ -2283,22 +2292,43 @@ int role_set_expand(role_set_t * x, ebitmap_t * r, policydb_t * p, uint32_t * ro
 		return 0;
 	}
 
+	ebitmap_init(&mapped_roles);
+	ebitmap_init(&roles);
+	
 	if (rolemap) {
-		if (map_ebitmap(&x->roles, &mapped_roles, rolemap))
-			return -1;
+		assert(base != NULL);
+		ebitmap_for_each_bit(&x->roles, rnode, i) {
+			if (ebitmap_node_get_bit(rnode, i)) {
+				/* take advantage of p_role_val_to_struct[]
+				 * of the base module */
+				role = base->role_val_to_struct[i];
+				assert(role != NULL);
+				if (role->flavor == ROLE_ATTRIB) {
+					if (ebitmap_union(&roles,
+							  &role->roles))
+						goto bad;
+				} else {
+					if (ebitmap_set_bit(&roles, i, 1))
+						goto bad;
+				}
+			}
+		}
+		if (map_ebitmap(&roles, &mapped_roles, rolemap))
+			goto bad;
 	} else {
 		if (ebitmap_cpy(&mapped_roles, &x->roles))
-			return -1;
+			goto bad;
 	}
 
 	ebitmap_for_each_bit(&mapped_roles, rnode, i) {
 		if (ebitmap_node_get_bit(rnode, i)) {
 			if (ebitmap_set_bit(r, i, 1))
-				return -1;
+				goto bad;
 		}
 	}
 
 	ebitmap_destroy(&mapped_roles);
+	ebitmap_destroy(&roles);
 
 	/* if role is to be complimented, invert the entire bitmap here */
 	if (x->flags & ROLE_COMP) {
@@ -2313,6 +2343,11 @@ int role_set_expand(role_set_t * x, ebitmap_t * r, policydb_t * p, uint32_t * ro
 		}
 	}
 	return 0;
+
+bad:
+	ebitmap_destroy(&mapped_roles);
+	ebitmap_destroy(&roles);
+	return -1;
 }
 
 /* Expand a type set into an ebitmap containing the types. This
diff --git a/libsepol/src/policydb.c b/libsepol/src/policydb.c
index 9145f2a..53d0fda 100644
--- a/libsepol/src/policydb.c
+++ b/libsepol/src/policydb.c
@@ -712,7 +712,7 @@ int policydb_user_cache(hashtab_key_t key
 	p = (policydb_t *) arg;
 
 	ebitmap_destroy(&user->cache);
-	if (role_set_expand(&user->roles, &user->cache, p, NULL)) {
+	if (role_set_expand(&user->roles, &user->cache, p, NULL, NULL)) {
 		return -1;
 	}
 
diff --git a/libsepol/src/users.c b/libsepol/src/users.c
index 17e1426..693210d 100644
--- a/libsepol/src/users.c
+++ b/libsepol/src/users.c
@@ -259,8 +259,8 @@ int sepol_user_modify(sepol_handle_t * handle,
 		name = NULL;
 
 		/* Expand roles */
-		if (role_set_expand
-		    (&usrdatum->roles, &usrdatum->cache, policydb, NULL)) {
+		if (role_set_expand(&usrdatum->roles, &usrdatum->cache,
+				    policydb, NULL, NULL)) {
 			ERR(handle, "unable to expand role set");
 			goto err;
 		}
-- 
1.7.0.4


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [v4 PATCH 6/6] Support adding one role attribute into another.
  2011-07-25  1:23 v4 Add role attribute support to libsepol Harry Ciao
                   ` (4 preceding siblings ...)
  2011-07-25  1:23 ` [v4 PATCH 5/6] Add role attribute support when expanding role_set_t Harry Ciao
@ 2011-07-25  1:23 ` Harry Ciao
  2011-07-25 15:42 ` v4 Add role attribute support to libsepol Steve Lawrence
  6 siblings, 0 replies; 8+ messages in thread
From: Harry Ciao @ 2011-07-25  1:23 UTC (permalink / raw)
  To: cpebenito, slawrence, method; +Cc: selinux

When the link process is completed, the types type_set_t and roles
ebitmap in a role attribute are settled, then we could go on to scan
all role attributes in the base->p_roles.table checking if any non-zero
bit in its roles ebitmap is indeed another role attribute.

If this is the case, then we need to escalate the roles ebitmap of
the sub role attribute into that of the parent, and remove the sub role
attribute from parent's roles ebitmap.

Since sub-attribute's roles ebitmap may further contain other role
attributes, we need to re-scan the updated parent's roles ebitmap.

Also if a loop dependency is detected, no escalation of sub-attribute's
roles ebitmap is needed.

Note, although in the link stage all role identifiers defined in any
block/decl of any module would be copied into the base->p_roles.table,
the role-attribute relationships could still be recorded in the decl's
local symtab[SYM_ROLES] table(see get_local_role()), so before all above
escalation of sub role attribute's roles ebitmap into that of parent ever
happens, all decl in the base->global list except the global block would
have to be traversed so as to populate potential role-attribute
relationships from decl up to the base module.

Signed-off-by: Harry Ciao <qingtao.cao@windriver.com>
---
 checkpolicy/policy_define.c |    5 +-
 libsepol/src/link.c         |  132 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 135 insertions(+), 2 deletions(-)

diff --git a/checkpolicy/policy_define.c b/checkpolicy/policy_define.c
index 6faaf94..ded27f7 100644
--- a/checkpolicy/policy_define.c
+++ b/checkpolicy/policy_define.c
@@ -1902,8 +1902,9 @@ int define_roleattribute(void)
 		return -1;
 	}
 	r = hashtab_search(policydbp->p_roles.table, id);
-	if (!r || r->flavor != ROLE_ROLE) {
-		yyerror2("unknown role %s, or not a regular role", id);
+	/* We support adding one role attribute into another */
+	if (!r) {
+		yyerror2("unknown role %s", id);
 		free(id);
 		return -1;
 	}
diff --git a/libsepol/src/link.c b/libsepol/src/link.c
index 53fcff9..421c47b 100644
--- a/libsepol/src/link.c
+++ b/libsepol/src/link.c
@@ -2335,6 +2335,122 @@ static int prepare_base(link_state_t * state, uint32_t num_mod_decls)
 	return 0;
 }
 
+static int expand_role_attributes(hashtab_key_t key, hashtab_datum_t datum,
+				  void * data)
+{
+	char *id;
+	role_datum_t *role, *sub_attr;
+	link_state_t *state;
+	unsigned int i;
+	ebitmap_node_t *rnode;
+
+	id = key;
+	role = (role_datum_t *)datum;
+	state = (link_state_t *)data;
+
+	if (strcmp(id, OBJECT_R) == 0){
+		/* object_r is never a role attribute by far */
+		return 0;
+	}
+
+	if (role->flavor != ROLE_ATTRIB)
+		return 0;
+
+	if (state->verbose)
+		INFO(state->handle, "expanding role attribute %s", id);
+
+restart:
+	ebitmap_for_each_bit(&role->roles, rnode, i) {
+		if (ebitmap_node_get_bit(rnode, i)) {
+			sub_attr = state->base->role_val_to_struct[i];
+			if (sub_attr->flavor != ROLE_ATTRIB)
+				continue;
+			
+			/* remove the sub role attribute from the parent
+			 * role attribute's roles ebitmap */
+			if (ebitmap_set_bit(&role->roles, i, 0))
+				return -1;
+
+			/* loop dependency of role attributes */
+			if (sub_attr->s.value == role->s.value)
+				continue;
+
+			/* now go on to expand a sub role attribute
+			 * by escalating its roles ebitmap */
+			if (ebitmap_union(&role->roles, &sub_attr->roles)) {
+				ERR(state->handle, "Out of memory!");
+				return -1;
+			}
+			
+			/* sub_attr->roles may contain other role attributes,
+			 * re-scan the parent role attribute's roles ebitmap */
+			goto restart;
+		}
+	}
+
+	return 0;
+}
+
+/* For any role attribute in a declaration's local symtab[SYM_ROLES] table,
+ * copy its roles ebitmap into its duplicate's in the base->p_roles.table.
+ */
+static int populate_decl_roleattributes(hashtab_key_t key, 
+					hashtab_datum_t datum,
+					void *data)
+{
+	char *id = key;
+	role_datum_t *decl_role, *base_role;
+	link_state_t *state = (link_state_t *)data;
+
+	decl_role = (role_datum_t *)datum;
+
+	if (strcmp(id, OBJECT_R) == 0) {
+		/* object_r is never a role attribute by far */
+		return 0;
+	}
+
+	if (decl_role->flavor != ROLE_ATTRIB)
+		return 0;
+
+	base_role = (role_datum_t *)hashtab_search(state->base->p_roles.table,
+						   id);
+	assert(base_role != NULL && base_role->flavor == ROLE_ATTRIB);
+
+	if (ebitmap_union(&base_role->roles, &decl_role->roles)) {
+		ERR(state->handle, "Out of memory!");
+		return -1;
+	}
+
+	return 0;
+}
+
+static int populate_roleattributes(link_state_t *state, policydb_t *pol)
+{
+	avrule_block_t *block;
+	avrule_decl_t *decl;
+
+	if (state->verbose)
+		INFO(state->handle, "Populating role-attribute relationship "
+			    "from enabled declarations' local symtab.");
+
+	/* Iterate through all of the blocks skipping the first(which is the
+	 * global block, is required to be present and can't have an else).
+	 * If the block is disabled or not having an enabled decl, skip it.
+	 */
+	for (block = pol->global->next; block != NULL; block = block->next)
+	{
+		decl = block->enabled;
+		if (decl == NULL || decl->enabled == 0)
+			continue;
+
+		if (hashtab_map(decl->symtab[SYM_ROLES].table, 
+				populate_decl_roleattributes, state))
+			return -1;
+	}
+
+	return 0;
+}
+
 /* Link a set of modules into a base module. This process is somewhat
  * similar to an actual compiler: it requires a set of order dependent
  * steps.  The base and every module must have been indexed prior to
@@ -2455,6 +2571,22 @@ int link_modules(sepol_handle_t * handle,
 		goto cleanup;
 	}
 
+	/* Now that all role attribute's roles ebitmap have been settled,
+	 * escalate sub role attribute's roles ebitmap into that of parent.
+	 *
+	 * First, since some role-attribute relationships could be recorded
+	 * in some decl's local symtab(see get_local_role()), we need to
+	 * populate them up to the base.p_roles table. */
+	if (populate_roleattributes(&state, state.base)) {
+		retval = SEPOL_EREQ;
+		goto cleanup;
+	}
+	
+	/* Now do the escalation. */
+	if (hashtab_map(state.base->p_roles.table, expand_role_attributes,
+			&state))
+		goto cleanup;
+
 	retval = 0;
       cleanup:
 	for (i = 0; modules != NULL && i < len; i++) {
-- 
1.7.0.4


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: v4 Add role attribute support to libsepol
  2011-07-25  1:23 v4 Add role attribute support to libsepol Harry Ciao
                   ` (5 preceding siblings ...)
  2011-07-25  1:23 ` [v4 PATCH 6/6] Support adding one role attribute into another Harry Ciao
@ 2011-07-25 15:42 ` Steve Lawrence
  6 siblings, 0 replies; 8+ messages in thread
From: Steve Lawrence @ 2011-07-25 15:42 UTC (permalink / raw)
  To: Harry Ciao; +Cc: cpebenito, method, selinux

On 07/24/2011 09:23 PM, Harry Ciao wrote:
> 
> 
> Differences from v3 patchset
> -----------------------------
> 1. For the 0002 patch, 
>    Introduce MOD_POLICYDB_VERSION_ROLEATTRIB(== 13) and bump
>    MOD_POLICYDB_VERSION_MAX to it.
> 
>    When read from or write to pp, take care of the flavor flag and roles
>    ebitmap only when the pp's version is no less than
>    MOD_POLICYDB_VERSION_ROLEATTRIB.
>    
>   
> Tests I've done
> -----------------
> 0. Build tests:
>    . revert this patchset, re-install libsepol/checkpolicy packages and
>      build modules(have no flavor/roles); apply this patchset, re-install
>      everything, the updated tools could handle old version modules in a
>      decent manner.
>    
>    . in write_binary_policy() in checkmodule.c, trigger policy module
>      downgrade by adding "policyvers = MOD_POLICYDB_VERSION_MAX - 1"; apply
>      this patchset, the updated tools could generate and process old version
>      modules correctly.
> 
> 1. test_t is able to transition into rpm_t, but could not direclty transition
>    into rpm_script_t, semanage_t, load_policy_t/setfiles_t:
>    
>    sh-3.2# sesearch -SCA -s test_t -t rpm_t -c process -p transition
>    Found 1 semantic av rules:
>       allow test_t rpm_t : process transition ; 
>    
>    sh-3.2# sesearch -SCA -s test_t -t rpm_script_t -c process -p transition
>    
>    sh-3.2# sesearch -SCA -s test_t -t semanage_t -c process -p transition
>    
>    sh-3.2# sesearch -SCA -s test_t -t load_policy_t -c process -p transition
>    
>    sh-3.2# sesearch -SCA -s test_t -t setfiles_t -c process -p transition
>    
> 2. rpm_t is able to transition into rpm_script_t, but could not directly
>    transition into semanage_t, load_policy_t/setfiles_t:
>    
>    sh-3.2# sesearch -SCA -s rpm_t -t rpm_script_t -c process -p transition
>    Found 1 semantic av rules:
>       allow rpm_t rpm_script_t : process transition ; 
>    
>    sh-3.2# sesearch -SCA -s rpm_t -t semanage_t -c process -p transition
>    
>    sh-3.2# sesearch -SCA -s rpm_t -t load_policy_t -c process -p transition
>    
>    sh-3.2# sesearch -SCA -s rpm_t -t setfiles_t -c process -p transition
>    
> 3. rpm_script_t is able to transition into semanage_t, but could not directly
>    transition into load_policy_t/setfiles_t:
>    
>    sh-3.2# sesearch -SCA -s rpm_script_t -t semanage_t -c process -p transition
>    Found 1 semantic av rules:
>       allow rpm_script_t semanage_t : process transition ; 
>    
>    sh-3.2# sesearch -SCA -s rpm_script_t -t load_policy_t -c process -p transition
>    
>    sh-3.2# sesearch -SCA -s rpm_script_t -t setfiles_t -c process -p transition
>    
> 4. semanage_t is able to transition into load_policy_t & setfiles_t:
>    
>    sh-3.2# sesearch -SCA -s semanage_t -t load_policy_t -c process -p transition
>    Found 1 semantic av rules:
>       allow semanage_t load_policy_t : process transition ; 
>    
>    sh-3.2# sesearch -SCA -s semanage_t -t setfiles_t -c process -p transition
>    Found 1 semantic av rules:
>       allow semanage_t setfiles_t : process transition ; 
>    
> 5. test_r is able to type with rpm_t, rpm_script_t, semanage_t, setfiles_t
>    and load_policy_t:
>    
>    sh-3.2# compute_create root:test_r:test_t:s0 system_u:object_r:rpm_exec_t:s0 process
>    root:test_r:rpm_t:s0
>    sh-3.2# 
>    
>    sh-3.2# compute_create root:test_r:rpm_script_t:s0 system_u:object_r:semanage_exec_t:s0 process
>    root:test_r:semanage_t:s0
>    sh-3.2# 
>    
>    sh-3.2# compute_create root:test_r:semanage_t:s0 system_u:object_r:setfiles_exec_t:s0 process
>    root:test_r:setfiles_t:s0
>    sh-3.2# 
>    
>    sh-3.2# compute_create root:test_r:semanage_t:s0 system_u:object_r:load_policy_exec_t:s0 process
>    root:test_r:load_policy_t:s0
>    sh-3.2# 
>    
> 6. Use the apol tool to analyze what types the test_r role could type with:
>    (Since the apol installed on Ubuntu so far only support max version .24,
>     we need to setup "policy-version = 24" in semanage.conf)
>    
>    test_r (28 types)
>        chfn_t
>        chkpwd_t
>        consoletype_t
>        ddclient_t
>        dhcpc_t
>        hostname_t
>        ifconfig_t
>        insmod_t
>        iptables_t
>        load_policy_t
>        loadkeys_t
>        netutils_t
>        newrole_t
>        pam_t
>        passwd_t
>        ping_t
>        pppd_t
>        pptp_t
>        rpm_script_t
>        rpm_t
>        semanage_t
>        setfiles_t
>        test_t
>        traceroute_t
>        updpwd_t
>        user_home_t
>        usernetctl_t
>        utempter_t
>    
>    rpm_roles (2 types)
>        rpm_script_t
>        rpm_t
>    
>    semanage_roles (3 types)
>        load_policy_t
>        semanage_t
>        setfiles_t


Applied in checkpolicy-2.0.27 and libsepol-2.0.46. Thanks.

- Steve

--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2011-07-25 15:42 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-07-25  1:23 v4 Add role attribute support to libsepol Harry Ciao
2011-07-25  1:23 ` [v4 PATCH 1/6] Add role attribute support when compiling modules Harry Ciao
2011-07-25  1:23 ` [v4 PATCH 2/6] Add role attribute support when generating pp files Harry Ciao
2011-07-25  1:23 ` [v4 PATCH 3/6] Add role attribute support when linking modules Harry Ciao
2011-07-25  1:23 ` [v4 PATCH 4/6] Add role attribute support when expanding role_datum_t Harry Ciao
2011-07-25  1:23 ` [v4 PATCH 5/6] Add role attribute support when expanding role_set_t Harry Ciao
2011-07-25  1:23 ` [v4 PATCH 6/6] Support adding one role attribute into another Harry Ciao
2011-07-25 15:42 ` v4 Add role attribute support to libsepol Steve Lawrence

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.