summaryrefslogtreecommitdiffstats
path: root/libqpol/src
diff options
context:
space:
mode:
Diffstat (limited to 'libqpol/src')
-rw-r--r--libqpol/src/Makefile.am1
-rw-r--r--libqpol/src/libqpol.map1
-rw-r--r--libqpol/src/module_compiler.c12
-rw-r--r--libqpol/src/module_compiler.h1
-rw-r--r--libqpol/src/policy_define.c188
-rw-r--r--libqpol/src/policy_define.h2
-rw-r--r--libqpol/src/policy_parse.y13
-rw-r--r--libqpol/src/policy_scan.l1
8 files changed, 216 insertions, 3 deletions
diff --git a/libqpol/src/Makefile.am b/libqpol/src/Makefile.am
index 34d87a6..0889a61 100644
--- a/libqpol/src/Makefile.am
+++ b/libqpol/src/Makefile.am
@@ -48,6 +48,7 @@ libqpol_a_SOURCES = \
syn_rule_internal.h \
syn_rule_query.c \
terule_query.c \
+ ftrule_query.c \
type_query.c \
user_query.c \
util.c \
diff --git a/libqpol/src/libqpol.map b/libqpol/src/libqpol.map
index dd293bc..6973cca 100644
--- a/libqpol/src/libqpol.map
+++ b/libqpol/src/libqpol.map
@@ -34,6 +34,7 @@ VERS_1.2 {
qpol_policy_reevaluate_conds;
qpol_portcon_*;
qpol_range_trans_*;
+ qpol_filename_trans_*;
qpol_role_*;
qpol_syn_avrule_*;
qpol_syn_terule_*;
diff --git a/libqpol/src/module_compiler.c b/libqpol/src/module_compiler.c
index dc19798..b06e285 100644
--- a/libqpol/src/module_compiler.c
+++ b/libqpol/src/module_compiler.c
@@ -1247,6 +1247,18 @@ void append_role_allow(role_allow_rule_t * role_allow_rules)
}
/* 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 --git a/libqpol/src/module_compiler.h b/libqpol/src/module_compiler.h
index 489086d..d46dca6 100644
--- a/libqpol/src/module_compiler.h
+++ b/libqpol/src/module_compiler.h
@@ -86,6 +86,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 --git a/libqpol/src/policy_define.c b/libqpol/src/policy_define.c
index c94f7aa..fad6b60 100644
--- a/libqpol/src/policy_define.c
+++ b/libqpol/src/policy_define.c
@@ -2132,7 +2132,9 @@ int define_role_trans(void)
free(id);
/* This ebitmap business is just to ensure that there are not conflicting role_trans rules */
-#ifdef HAVE_SEPOL_USER_ROLE_MAPPING
+#ifdef HAVE_SEPOL_ROLE_ATTRS
+ if (role_set_expand(&roles, &e_roles, policydbp, NULL, NULL))
+#elif HAVE_SEPOL_USER_ROLE_MAPPING
if (role_set_expand(&roles, &e_roles, policydbp, NULL))
#else
if (role_set_expand(&roles, &e_roles, policydbp))
@@ -2226,6 +2228,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 --git a/libqpol/src/policy_define.h b/libqpol/src/policy_define.h
index 7be626c..f273fed 100644
--- a/libqpol/src/policy_define.h
+++ b/libqpol/src/policy_define.h
@@ -26,6 +26,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);
@@ -58,6 +59,7 @@ int define_range_trans(int class_specified);
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 --git a/libqpol/src/policy_parse.y b/libqpol/src/policy_parse.y
index 84f4114..dc16c6f 100644
--- a/libqpol/src/policy_parse.y
+++ b/libqpol/src/policy_parse.y
@@ -98,6 +98,7 @@ extern char *qpol_src_inputlim;/* end of data */
%type <require_func> require_decl_def
%token PATH
+%token FILENAME
%token CLONE
%token COMMON
%token CLASS
@@ -360,7 +361,10 @@ cond_rule_def : cond_transition_def
| require_block
{ $$ = NULL; }
;
-cond_transition_def : TYPE_TRANSITION names names ':' names identifier ';'
+cond_transition_def : TYPE_TRANSITION names names ':' names identifier filename ';'
+ { $$ = 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 ';'
@@ -395,7 +399,9 @@ cond_dontaudit_def : DONTAUDIT names names ':' names names ';'
{ $$ = 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 filename ';'
+ {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;}
@@ -752,6 +758,9 @@ identifier : IDENTIFIER
path : PATH
{ if (insert_id(yytext,0)) return -1; }
;
+filename : FILENAME
+ { yytext[strlen(yytext) - 1] = '\0'; if (insert_id(yytext + 1,0)) return -1; }
+ ;
number : NUMBER
{ $$ = strtoul(yytext,NULL,0); }
;
diff --git a/libqpol/src/policy_scan.l b/libqpol/src/policy_scan.l
index 75485f3..30203cd 100644
--- a/libqpol/src/policy_scan.l
+++ b/libqpol/src/policy_scan.l
@@ -235,6 +235,7 @@ POLICYCAP { return(POLICYCAP); }
permissive |
PERMISSIVE { return(PERMISSIVE); }
"/"({alnum}|[_\.\-/])* { return(PATH); }
+\"({alnum}|[_\.\-])+\" { return(FILENAME); }
{letter}({alnum}|[_\-])*([\.]?({alnum}|[_\-]))* { return(IDENTIFIER); }
{digit}+|0x{hexval}+ { return(NUMBER); }
{digit}{1,3}(\.{digit}{1,3}){3} { return(IPV4_ADDR); }