Re: [PATCH] checkpolicy: add support for using last path component in type transition rules

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

 



On 03/28/2011 02:00 PM, Eric Paris wrote:
> This patch adds support for using the last path component as part of the
> information in making labeling decisions for new objects.  A example
> rule looks like so:
> 
> type_transition unconfined_t etc_t:file system_conf_t eric;
> 
> This rule says if unconfined_t creates a file in a directory labeled
> etc_t and the last path component is "eric" (no globbing, no matching
> magic, just exact strcmp) it should be labeled system_conf_t.
> 
> The kernel and policy representation does not have support for such
> rules in conditionals, and thus policy explicitly notes that fact if
> such a rule is added to a conditional.
> 
> Signed-off-by: Eric Paris <eparis@xxxxxxxxxx>
> ---
> 
> diff -up checkpolicy-2.0.23/module_compiler.c.eparis2 checkpolicy-2.0.23/module_compiler.c
> --- checkpolicy-2.0.23/module_compiler.c.eparis2	2010-12-21 16:35:45.000000000 -0500
> +++ checkpolicy-2.0.23/module_compiler.c	2011-03-23 14:19:51.152530839 -0400
> @@ -1313,6 +1313,18 @@ void append_role_allow(role_allow_rule_t
>  }
>  
>  /* this doesn't actually append, but really prepends it */
> +void append_filename_trans(filename_trans_rule_t * filename_trans_rules)
> +{
> +	avrule_decl_t *decl = stack_top->decl;
> +
> +	/* filename transitions are not allowed within conditionals */
> +	assert(stack_top->type == 1);
> +
> +	filename_trans_rules->next = decl->filename_trans_rules;
> +	decl->filename_trans_rules = filename_trans_rules;
> +}
> +
> +/* this doesn't actually append, but really prepends it */
>  void append_range_trans(range_trans_rule_t * range_tr_rules)
>  {
>  	avrule_decl_t *decl = stack_top->decl;
> diff -up checkpolicy-2.0.23/module_compiler.h.eparis2 checkpolicy-2.0.23/module_compiler.h
> --- checkpolicy-2.0.23/module_compiler.h.eparis2	2010-12-21 16:35:45.000000000 -0500
> +++ checkpolicy-2.0.23/module_compiler.h	2011-03-23 14:19:51.154531123 -0400
> @@ -80,6 +80,7 @@ void append_avrule(avrule_t * avrule);
>  void append_role_trans(role_trans_rule_t * role_tr_rules);
>  void append_role_allow(role_allow_rule_t * role_allow_rules);
>  void append_range_trans(range_trans_rule_t * range_tr_rules);
> +void append_filename_trans(filename_trans_rule_t * filename_trans_rules);
>  
>  /* Create a new optional block and add it to the global policy.
>   * During the second pass resolve the block's requirements.  Return 0
> diff -up checkpolicy-2.0.23/policy_define.c.eparis2 checkpolicy-2.0.23/policy_define.c
> --- checkpolicy-2.0.23/policy_define.c.eparis2	2010-12-21 16:35:45.000000000 -0500
> +++ checkpolicy-2.0.23/policy_define.c	2011-03-28 13:50:57.667710915 -0400
> @@ -2196,6 +2196,190 @@ int define_role_allow(void)
>  	return 0;
>  }
>  
> +avrule_t *define_cond_filename_trans(void)
> +{
> +	yyerror("type transitions with a filename not allowed inside "
> +		"conditionals\n");
> +	return COND_ERR;
> +}
> +
> +int define_filename_trans(void)
> +{
> +	char *id, *name = NULL;
> +	type_set_t stypes, ttypes;
> +	ebitmap_t e_stypes, e_ttypes;
> +	ebitmap_t e_tclasses;
> +	ebitmap_node_t *snode, *tnode, *cnode;
> +	filename_trans_t *ft;
> +	filename_trans_rule_t *ftr;
> +	class_datum_t *cladatum;
> +	type_datum_t *typdatum;
> +	uint32_t otype;
> +	unsigned int c, s, t;
> +	int add;
> +
> +	if (pass == 1) {
> +		/* stype */
> +		while ((id = queue_remove(id_queue)))
> +			free(id);
> +		/* ttype */
> +		while ((id = queue_remove(id_queue)))
> +			free(id);
> +		/* tclass */
> +		while ((id = queue_remove(id_queue)))
> +			free(id);
> +		/* otype */
> +		id = queue_remove(id_queue);
> +		free(id);
> +		/* name */
> +		id = queue_remove(id_queue);
> +		free(id);
> +		return 0;
> +	}
> +
> +
> +	add = 1;
> +	type_set_init(&stypes);
> +	while ((id = queue_remove(id_queue))) {
> +		if (set_types(&stypes, id, &add, 0))
> +			goto bad;
> +	}
> +
> +	add =1;
> +	type_set_init(&ttypes);
> +	while ((id = queue_remove(id_queue))) {
> +		if (set_types(&ttypes, id, &add, 0))
> +			goto bad;
> +	}
> +
> +	ebitmap_init(&e_tclasses);
> +	while ((id = queue_remove(id_queue))) {
> +		if (!is_id_in_scope(SYM_CLASSES, id)) {
> +			yyerror2("class %s is not within scope", id);
> +			free(id);
> +			goto bad;
> +		}
> +		cladatum = hashtab_search(policydbp->p_classes.table, id);
> +		if (!cladatum) {
> +			yyerror2("unknown class %s", id);
> +			goto bad;
> +		}
> +		if (ebitmap_set_bit(&e_tclasses, cladatum->s.value - 1, TRUE)) {
> +			yyerror("Out of memory");
> +			goto bad;
> +		}
> +		free(id);
> +	}
> +
> +	id = (char *)queue_remove(id_queue);
> +	if (!id) {
> +		yyerror("no otype in transition definition?");
> +		goto bad;
> +	}
> +	if (!is_id_in_scope(SYM_TYPES, id)) {
> +		yyerror2("type %s is not within scope", id);
> +		free(id);
> +		goto bad;
> +	}
> +	typdatum = hashtab_search(policydbp->p_types.table, id);
> +	if (!typdatum) {
> +		yyerror2("unknown type %s used in transition definition", id);
> +		goto bad;
> +	}
> +	free(id);
> +	otype = typdatum->s.value;
> +
> +	name = queue_remove(id_queue);
> +	if (!name) {
> +		yyerror("no pathname specified in filename_trans definition?");
> +		goto bad;
> +	}
> +
> +	/* We expand the class set into seperate rules.  We expand the types
> +	 * just to make sure there are not duplicates.  They will get turned
> +	 * into seperate rules later */
> +	ebitmap_init(&e_stypes);
> +	if (type_set_expand(&stypes, &e_stypes, policydbp, 1))
> +		goto bad;
> +
> +	ebitmap_init(&e_ttypes);
> +	if (type_set_expand(&ttypes, &e_ttypes, policydbp, 1))
> +		goto bad;
> +
> +	ebitmap_for_each_bit(&e_tclasses, cnode, c) {
> +		if (!ebitmap_node_get_bit(cnode, c))
> +			continue;
> +		ebitmap_for_each_bit(&e_stypes, snode, s) {
> +			if (!ebitmap_node_get_bit(snode, s))
> +				continue;
> +			ebitmap_for_each_bit(&e_ttypes, tnode, t) {
> +				if (!ebitmap_node_get_bit(tnode, t))
> +					continue;
> +	
> +				for (ft = policydbp->filename_trans; ft; ft = ft->next) {
> +					if (ft->stype == (s + 1) &&
> +					    ft->ttype == (t + 1) &&
> +					    ft->tclass == (c + 1) &&
> +					    !strcmp(ft->name, name)) {
> +						yyerror2("duplicate filename transition for: filename_trans %s %s %s:%s",
> +							 name, 
> +							 policydbp->p_type_val_to_name[s],
> +							 policydbp->p_type_val_to_name[t],
> +							 policydbp->p_class_val_to_name[c]);
> +						goto bad;
> +					}
> +				}
> +	
> +				ft = malloc(sizeof(*ft));
> +				if (!ft) {
> +					yyerror("out of memory");
> +					goto bad;
> +				}
> +				memset(ft, 0, sizeof(*ft));
> +	
> +				ft->next = policydbp->filename_trans;
> +				policydbp->filename_trans = ft;
> +	
> +				ft->name = strdup(name);
> +				if (!ft->name) {
> +					yyerror("out of memory");
> +					goto bad;
> +				}
> +				ft->stype = s + 1;
> +				ft->ttype = t + 1;
> +				ft->tclass = c + 1;
> +				ft->otype = otype;
> +			}
> +		}
> +	
> +		/* Now add the real rule since we didn't find any duplicates */
> +		ftr = malloc(sizeof(*ftr));
> +		if (!ftr) {
> +			yyerror("out of memory");
> +			goto bad;
> +		}
> +		filename_trans_rule_init(ftr);
> +		append_filename_trans(ftr);
> +
> +		ftr->name = strdup(name);
> +		ftr->stypes = stypes;
> +		ftr->ttypes = ttypes;
> +		ftr->tclass = c + 1;
> +		ftr->otype = otype;
> +	}
> +
> +	free(name);
> +	ebitmap_destroy(&e_stypes);
> +	ebitmap_destroy(&e_ttypes);
> +	ebitmap_destroy(&e_tclasses);
> +
> +	return 0;
> +
> +bad:
> +	free(name);
> +	return -1;
> +}
> +
>  static constraint_expr_t *constraint_expr_clone(constraint_expr_t * expr)
>  {
>  	constraint_expr_t *h = NULL, *l = NULL, *e, *newe;
> diff -up checkpolicy-2.0.23/policy_define.h.eparis2 checkpolicy-2.0.23/policy_define.h
> --- checkpolicy-2.0.23/policy_define.h.eparis2	2010-12-21 16:35:45.000000000 -0500
> +++ checkpolicy-2.0.23/policy_define.h	2011-03-28 13:50:05.489297128 -0400
> @@ -16,6 +16,7 @@
>  avrule_t *define_cond_compute_type(int which);
>  avrule_t *define_cond_pol_list(avrule_t *avlist, avrule_t *stmt);
>  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_av_perms(int inherits);
> @@ -47,6 +48,7 @@ int define_range_trans(int class_specifi
>  int define_role_allow(void);
>  int define_role_trans(void);
>  int define_role_types(void);
> +int define_filename_trans(void);
>  int define_sens(void);
>  int define_te_avtab(int which);
>  int define_typealias(void);
> diff -up checkpolicy-2.0.23/policy_parse.y.eparis2 checkpolicy-2.0.23/policy_parse.y
> --- checkpolicy-2.0.23/policy_parse.y.eparis2	2011-03-23 14:19:51.133528148 -0400
> +++ checkpolicy-2.0.23/policy_parse.y	2011-03-28 13:49:03.489482156 -0400
> @@ -342,7 +342,10 @@ cond_rule_def           : cond_transitio
>  			| require_block
>  			{ $$ = NULL; }
>                          ;
> -cond_transition_def	: TYPE_TRANSITION names names ':' names identifier ';'
> +cond_transition_def	: TYPE_TRANSITION names names ':' names identifier identifier ';'
> +                        { $$ = define_cond_filename_trans() ;
> +                          if ($$ == COND_ERR) return -1;}
> +			| TYPE_TRANSITION names names ':' names identifier ';'
>                          { $$ = define_cond_compute_type(AVRULE_TRANSITION) ;
>                            if ($$ == COND_ERR) return -1;}
>                          | TYPE_MEMBER names names ':' names identifier ';'
> @@ -377,7 +380,10 @@ cond_dontaudit_def	: DONTAUDIT names nam
>  			{ $$ = define_cond_te_avtab(AVRULE_DONTAUDIT);
>                            if ($$ == COND_ERR) return -1; }
>  		        ;
> -transition_def		: TYPE_TRANSITION names names ':' names identifier ';'
> +			;
> +transition_def		: TYPE_TRANSITION  names names ':' names identifier identifier ';'
> +			{if (define_filename_trans()) return -1; }
> +			| TYPE_TRANSITION names names ':' names identifier ';'
>                          {if (define_compute_type(AVRULE_TRANSITION)) return -1;}
>                          | TYPE_MEMBER names names ':' names identifier ';'
>                          {if (define_compute_type(AVRULE_MEMBER)) return -1;}
> diff -up checkpolicy-2.0.23/test/dismod.c.eparis2 checkpolicy-2.0.23/test/dismod.c
> --- checkpolicy-2.0.23/test/dismod.c.eparis2	2011-03-23 14:19:51.142529423 -0400
> +++ checkpolicy-2.0.23/test/dismod.c	2011-03-23 14:19:51.160531973 -0400
> @@ -52,6 +52,7 @@
>  #define DISPLAY_AVBLOCK_ROLE_ALLOW	4
>  #define DISPLAY_AVBLOCK_REQUIRES	5
>  #define DISPLAY_AVBLOCK_DECLARES	6
> +#define DISPLAY_AVBLOCK_FILENAME_TRANS	7
>  
>  static policydb_t policydb;
>  extern unsigned int ss_initialized;
> @@ -480,6 +481,18 @@ void display_role_allow(role_allow_rule_
>  	}
>  }
>  
> +void display_filename_trans(filename_trans_rule_t * tr, policydb_t * p, FILE * fp)
> +{
> +	for (; tr; tr = tr->next) {
> +		fprintf(fp, "filename transition %s", tr->name);
> +		display_type_set(&tr->stypes, 0, p, fp);
> +		display_type_set(&tr->ttypes, 0, p, fp);
> +		display_id(p, fp, SYM_CLASSES, tr->tclass - 1, ":");
> +		display_id(p, fp, SYM_TYPES, tr->otype - 1, "");
> +		fprintf(fp, "\n");
> +	}
> +}
> +
>  int role_display_callback(hashtab_key_t key, hashtab_datum_t datum, void *data)
>  {
>  	role_datum_t *role;
> @@ -647,6 +660,11 @@ int display_avdecl(avrule_decl_t * decl,
>  			}
>  			break;
>  		}
> +	case DISPLAY_AVBLOCK_FILENAME_TRANS:
> +		display_filename_trans(decl->filename_trans_rules, policy,
> +				       out_fp);
> +			return -1;
> +		break;
>  	default:{
>  			assert(0);
>  		}
> @@ -812,6 +830,7 @@ int menu()
>  	printf("c)  Display policy capabilities\n");
>  	printf("l)  Link in a module\n");
>  	printf("u)  Display the unknown handling setting\n");
> +	printf("F)  Display filename_trans rules\n");
>  	printf("\n");
>  	printf("f)  set output file\n");
>  	printf("m)  display menu\n");
> @@ -947,6 +966,11 @@ int main(int argc, char **argv)
>  			if (out_fp != stdout)
>  				printf("\nOutput to file: %s\n", OutfileName);
>  			break;
> +		case 'F':
> +			fprintf(out_fp, "filename_trans rules:\n");
> +			display_avblock(DISPLAY_AVBLOCK_FILENAME_TRANS,
> +					0, &policydb, out_fp);
> +			break;
>  		case 'l':
>  			link_module(&policydb, out_fp);
>  			break;
> diff -up checkpolicy-2.0.23/test/dispol.c.eparis2 checkpolicy-2.0.23/test/dispol.c
> --- checkpolicy-2.0.23/test/dispol.c.eparis2	2010-12-21 16:35:45.000000000 -0500
> +++ checkpolicy-2.0.23/test/dispol.c	2011-03-23 14:19:51.162532256 -0400
> @@ -341,6 +341,21 @@ static void display_permissive(policydb_
>  	}
>  }
>  
> +static void display_filename_trans(policydb_t *p, FILE *fp)
> +{
> +	filename_trans_t *ft;
> +
> +	fprintf(fp, "filename_trans rules:\n");
> +	for (ft = p->filename_trans; ft; ft = ft->next) {
> +		fprintf(fp, "%s\n", ft->name);
> +		display_id(p, fp, SYM_TYPES, ft->stype - 1, "");
> +		display_id(p, fp, SYM_TYPES, ft->ttype - 1, "");
> +		display_id(p, fp, SYM_CLASSES, ft->tclass - 1, ":");
> +		display_id(p, fp, SYM_TYPES, ft->otype - 1, "");
> +		fprintf(fp, "\n");
> +	}
> +}
> +
>  int menu()
>  {
>  	printf("\nSelect a command:\n");
> @@ -355,6 +370,8 @@ int menu()
>  	printf("c)  display policy capabilities\n");
>  	printf("p)  display the list of permissive types\n");
>  	printf("u)  display unknown handling setting\n");
> +	printf("F)  display filename_trans rules\n");
> +	printf("\n");
>  	printf("f)  set output file\n");
>  	printf("m)  display menu\n");
>  	printf("q)  quit\n");
> @@ -492,6 +509,9 @@ int main(int argc, char **argv)
>  			if (out_fp != stdout)
>  				printf("\nOutput to file: %s\n", OutfileName);
>  			break;
> +		case 'F':
> +			display_filename_trans(&policydb, out_fp);
> +			break;
>  		case 'q':
>  			policydb_destroy(&policydb);
>  			exit(0);
> 
> 
> 

Applied to checkpolicy-2.0.25.

Thanks.


Semi related to the filename_trans, I noticed a libsepol wasn't emitting
a warning when filename_trans rules were dropped when it was
unsupported. I added this to libsepol-2.0.45. Below is the patch:

diff --git a/libsepol/src/write.c b/libsepol/src/write.c
index 4292026..9657e6c 100644
--- a/libsepol/src/write.c
+++ b/libsepol/src/write.c
@@ -1950,9 +1950,13 @@ int policydb_write(policydb_t * p, struct
policy_file *fp)
            return POLICYDB_ERROR;
        if (role_allow_write(p->role_allow, fp))
            return POLICYDB_ERROR;
-       if (p->policyvers >= POLICYDB_VERSION_FILENAME_TRANS &&
-           filename_trans_write(p->filename_trans, fp))
-           return POLICYDB_ERROR;
+       if (p->policyvers >= POLICYDB_VERSION_FILENAME_TRANS) {
+           if (filename_trans_write(p->filename_trans, fp))
+               return POLICYDB_ERROR;
+       } else {
+           if (p->filename_trans)
+               WARN(fp->handle, "Discarding filename type transition
rules");
+       }
    } else {
        if (avrule_block_write(p->global, num_syms, p, fp) == -1) {
            return POLICYDB_ERROR;




--
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