Re: [v2 PATCH 1/6] Add role attribute support when compiling modules.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 06/01/2011 04:57 AM, Harry Ciao wrote:
> 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;
> 
> Signed-off-by: Harry Ciao <qingtao.cao@xxxxxxxxxxxxx>
> ---
>  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                    |    2 +
>  8 files changed, 246 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)

I'm still looking at this patchset, but noticed some issue with this
function:

The declare_role function allows a role to be defined multiple times,
which is correct. However, if a role_attribute was defined with the same
name as a role, this function would not error, which I believe it should.

Also, attribute_role's should not be allowed to be defined twice (the
same restriction is applied to normal attributes).

>  {
>  	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 8274d36..d4cc18e 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
> @@ -252,10 +254,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
> @@ -415,10 +420,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 '}'
>  			;
> @@ -440,6 +448,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
>                          |
>                          ;
> @@ -804,6 +815,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 427c189..b24a087 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..feb35ae 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);
>  	}
>  }
>  


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


[Index of Archives]     [Selinux Refpolicy]     [Linux SGX]     [Fedora Users]     [Fedora Desktop]     [Yosemite Photos]     [Yosemite Camping]     [Yosemite Campsites]     [KDE Users]     [Gnome Users]

  Powered by Linux