2011-03-29 14:24:42

by Daniel Walsh

[permalink] [raw]
Subject: [refpolicy] Fwd: [PATCH] checkpolicy: add support for using last path component in type transition rules

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Any idea on how you what you would like to call these interfaces?

files_etc_named_filetrans', `
gen_require(`
type etc_t;
')

type_transition $1 etc_t:file $2 $3;
')

interface(`sysnet_etc_filetrans_resolve_conf',`
gen_require(`
type net_conf_t;
')

files_etc_named_filetrans($1, net_conf_t, resolv.conf)
')

sysnet_etc_filetrans_resolv_conf(unconfined_t)



- -------- Original Message --------
Subject: [PATCH] checkpolicy: add support for using last path component
in type transition rules
Date: Mon, 28 Mar 2011 14:00:19 -0400
From: Eric Paris <[email protected]>
To: selinux at tycho.nsa.gov
CC: method at manicmethod.com, sds at tycho.nsa.gov

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 <[email protected]>
- ---

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



- --
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo at tycho.nsa.gov
with
the words "unsubscribe selinux" without quotes as the message.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (GNU/Linux)
Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org/

iEYEARECAAYFAk2R66oACgkQrlYvE4MpobNp2wCgg1NH+5glq95MSAqNj4n0tn6+
vJcAnRseDzVAo77D7U9KRQjmIvUREiXo
=Uk+m
-----END PGP SIGNATURE-----


2011-03-29 14:53:40

by cpebenito

[permalink] [raw]
Subject: [refpolicy] Fwd: [PATCH] checkpolicy: add support for using last path component in type transition rules

On 03/29/11 10:24, Daniel J Walsh wrote:
> Any idea on how you what you would like to call these interfaces?
>
> files_etc_named_filetrans', `
> gen_require(`
> type etc_t;
> ')
>
> type_transition $1 etc_t:file $2 $3;
> ')
>
> interface(`sysnet_etc_filetrans_resolve_conf',`
> gen_require(`
> type net_conf_t;
> ')
>
> files_etc_named_filetrans($1, net_conf_t, resolv.conf)
> ')
>
> sysnet_etc_filetrans_resolv_conf(unconfined_t)

I have two thoughts:

name_filetrans_pattern() and files_etc_name_filetrans()

or

nametrans_pattern() and files_etc_nametrans()


I like the second option because its shorter, but the first option is
probably the best choice as its more precise. It also is future-proof,
in case the named type_transition statement is extended to some other
objects (e.g. KaiGai already feels it will be useful for databases).


> -------- Original Message --------
> Subject: [PATCH] checkpolicy: add support for using last path component
> in type transition rules
> Date: Mon, 28 Mar 2011 14:00:19 -0400
> From: Eric Paris <[email protected]>
> To: selinux at tycho.nsa.gov
> CC: method at manicmethod.com, sds at tycho.nsa.gov
>
> 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 <[email protected]>
> ---
[patch cut]

--
Chris PeBenito
Tresys Technology, LLC
http://www.tresys.com | oss.tresys.com

2011-03-29 20:25:08

by Daniel Walsh

[permalink] [raw]
Subject: [refpolicy] Fwd: [PATCH] checkpolicy: add support for using last path component in type transition rules

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 03/29/2011 10:53 AM, Christopher J. PeBenito wrote:
> On 03/29/11 10:24, Daniel J Walsh wrote:
>> Any idea on how you what you would like to call these interfaces?
>>
>> files_etc_named_filetrans', `
>> gen_require(`
>> type etc_t;
>> ')
>>
>> type_transition $1 etc_t:file $2 $3;
>> ')
>>
>> interface(`sysnet_etc_filetrans_resolve_conf',`
>> gen_require(`
>> type net_conf_t;
>> ')
>>
>> files_etc_named_filetrans($1, net_conf_t, resolv.conf)
>> ')
>>
>> sysnet_etc_filetrans_resolv_conf(unconfined_t)
>
> I have two thoughts:
>
> name_filetrans_pattern() and files_etc_name_filetrans()
>
> or
>
> nametrans_pattern() and files_etc_nametrans()
>
>
> I like the second option because its shorter, but the first option is
> probably the best choice as its more precise. It also is future-proof,
> in case the named type_transition statement is extended to some other
> objects (e.g. KaiGai already feels it will be useful for databases).
>
>

Another option would be to do something like:

define(`filetrans_pattern',`
allow $1 $2:dir rw_dir_perms;
type_transition $1 $2:$4 $3 $5;
')

interface(`files_etc_filetrans',`
gen_require(`
type etc_t;
')

filetrans_pattern($1, etc_t, $2, $3, $4)
')

interface(`sysnet_etc_filetrans_config',`
gen_require(`
type net_conf_t;
')

files_etc_filetrans($1, net_conf_t, file, $2)
')

sysnet_etc_filetrans_config(unconfined_t, resolv.conf)
sysnet_etc_filetrans_config(NetworkManager_t)

Seems to work.



-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (GNU/Linux)
Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org/

iEYEARECAAYFAk2SQCAACgkQrlYvE4MpobPfWwCfakjd3wiadx6o0nnMtRsKZqr6
sjwAoKijIrw9fmj9MEc1zPvGhb5rdMdj
=PkQH
-----END PGP SIGNATURE-----

2011-04-07 13:48:56

by cpebenito

[permalink] [raw]
Subject: [refpolicy] Fwd: [PATCH] checkpolicy: add support for using last path component in type transition rules

On 3/29/2011 4:25 PM, Daniel J Walsh wrote:
> On 03/29/2011 10:53 AM, Christopher J. PeBenito wrote:
>> On 03/29/11 10:24, Daniel J Walsh wrote:
>>> Any idea on how you what you would like to call these interfaces?
>>>
>>> files_etc_named_filetrans', `
>>> gen_require(`
>>> type etc_t;
>>> ')
>>>
>>> type_transition $1 etc_t:file $2 $3;
>>> ')
>>>
>>> interface(`sysnet_etc_filetrans_resolve_conf',`
>>> gen_require(`
>>> type net_conf_t;
>>> ')
>>>
>>> files_etc_named_filetrans($1, net_conf_t, resolv.conf)
>>> ')
>>>
>>> sysnet_etc_filetrans_resolv_conf(unconfined_t)
>>
>> I have two thoughts:
>>
>> name_filetrans_pattern() and files_etc_name_filetrans()
>>
>> or
>>
>> nametrans_pattern() and files_etc_nametrans()
>>
>>
>> I like the second option because its shorter, but the first option is
>> probably the best choice as its more precise. It also is future-proof,
>> in case the named type_transition statement is extended to some other
>> objects (e.g. KaiGai already feels it will be useful for databases).
>>
>>
>
> Another option would be to do something like:
>
> define(`filetrans_pattern',`
> allow $1 $2:dir rw_dir_perms;
> type_transition $1 $2:$4 $3 $5;
> ')
>
> interface(`files_etc_filetrans',`
> gen_require(`
> type etc_t;
> ')
>
> filetrans_pattern($1, etc_t, $2, $3, $4)
> ')
>
> interface(`sysnet_etc_filetrans_config',`
> gen_require(`
> type net_conf_t;
> ')
>
> files_etc_filetrans($1, net_conf_t, file, $2)
> ')
>
> sysnet_etc_filetrans_config(unconfined_t, resolv.conf)
> sysnet_etc_filetrans_config(NetworkManager_t)
>
> Seems to work.

I like this idea. It doesn't seem that there are any objections. I'm
checking with the CIL guys to see if it will be problematic to support
this. I don't think there will be a problem. If not, we can move
forward with this implementation.

--
Chris PeBenito
Tresys Technology, LLC
http://www.tresys.com | oss.tresys.com