diff --git a/parser/parser.h b/parser/parser.h index b72c60167..581a87afa 100644 --- a/parser/parser.h +++ b/parser/parser.h @@ -394,6 +394,8 @@ extern char *process_var(const char *var); extern int parse_mode(const char *mode); extern int parse_X_mode(const char *X, int valid, const char *str_mode, int *mode, int fail); void parse_label(char **ns, char **name, const char *label); +void parse_named_transition_target(struct named_transition *nt, + const char *target); extern struct cod_entry *new_entry(char *ns, char *id, int mode, char *link_id); /* returns -1 if value != true or false, otherwise 0 == false, 1 == true */ diff --git a/parser/parser_misc.c b/parser/parser_misc.c index a0e62ea8c..a13f71cf1 100644 --- a/parser/parser_misc.c +++ b/parser/parser_misc.c @@ -615,6 +615,19 @@ void parse_label(char **ns, char **name, const char *label) *name = _name; } +void parse_named_transition_target(struct named_transition *nt, + const char *target) +{ + memset(nt, 0, sizeof(*nt)); + if (!target) { + /* Return with nt->present set to 0 (thanks to the memset) */ + return; + } + + parse_label(&nt->ns, &nt->name, target); + nt->present = 1; +} + struct cod_entry *new_entry(char *ns, char *id, int mode, char *link_id) { struct cod_entry *entry = NULL; diff --git a/parser/parser_yacc.y b/parser/parser_yacc.y index c116e619e..1f004805c 100644 --- a/parser/parser_yacc.y +++ b/parser/parser_yacc.y @@ -258,8 +258,6 @@ void add_local_entry(Profile *prof); %type opt_profile_flag %type opt_flags %type opt_perm_mode -%type opt_ns -%type ns_id %type opt_id %type opt_prefix %type dbus_perm @@ -299,11 +297,6 @@ opt_profile_flag: { /* nothing */ $$ = 0; } | TOK_PROFILE { $$ = 1; } | hat_start { $$ = 2; } -ns_id: TOK_COLON id_or_var TOK_COLON { $$ = $2; } - -opt_ns: { /* nothing */ $$ = NULL; } - | ns_id { $$ = $1; } - opt_id: { /* nothing */ $$ = NULL; } | TOK_ID { $$ = $1; } @@ -1053,21 +1046,12 @@ id_or_var: TOK_SET_VAR { $$ = $1; }; opt_named_transition: { /* nothing */ - $$.present = 0; - $$.ns = NULL; - $$.name = NULL; + parse_named_transition_target(&$$, NULL); } | TOK_ARROW id_or_var { - $$.present = 1; - $$.ns = NULL; - $$.name = $2; - } - | TOK_ARROW ns_id id_or_var - { - $$.present = 1; - $$.ns = $2; - $$.name = $3; + parse_named_transition_target(&$$, $2); + free($2); }; rule: file_rule { $$ = $1; } @@ -1508,27 +1492,25 @@ change_profile_head: TOK_CHANGE_PROFILE opt_id $$ = $2; } -change_profile: change_profile_head TOK_END_OF_RULE +change_profile: change_profile_head opt_named_transition TOK_END_OF_RULE { struct cod_entry *entry; - char *rule = strdup("**"); - if (!rule) - yyerror(_("Memory allocation error.")); - PDEBUG("Matched change_profile,\n"); - entry = new_entry(NULL, rule, AA_CHANGE_PROFILE, $1); - if (!entry) - yyerror(_("Memory allocation error.")); - PDEBUG("change_profile,\n"); - $$ = entry; - }; -change_profile: change_profile_head TOK_ARROW opt_ns TOK_ID TOK_END_OF_RULE - { - struct cod_entry *entry; - PDEBUG("Matched change_profile: tok_id (:%s://%s)\n", $3 ? $3 : "", $4); - entry = new_entry($3, $4, AA_CHANGE_PROFILE, $1); + if ($2.present) { + PDEBUG("Matched change_profile: tok_id (:%s://%s)\n", + $2.ns ? $2.ns : "", $2.name); + entry = new_entry($2.ns, $2.name, AA_CHANGE_PROFILE, $1); + } else { + char *rule = strdup("**"); + if (!rule) + yyerror(_("Memory allocation error.")); + + PDEBUG("Matched change_profile,\n"); + entry = new_entry(NULL, rule, AA_CHANGE_PROFILE, $1); + } if (!entry) yyerror(_("Memory allocation error.")); + PDEBUG("change_profile.entry: (%s)\n", entry->name); $$ = entry; }; diff --git a/tests/regression/apparmor/changeprofile.sh b/tests/regression/apparmor/changeprofile.sh index a00e24ee4..dea28d6f1 100755 --- a/tests/regression/apparmor/changeprofile.sh +++ b/tests/regression/apparmor/changeprofile.sh @@ -29,6 +29,7 @@ fqsubbase="$pwd/changeprofile" fqsubtest="$fqsubbase//$subtest" subtest2="$pwd//sub2" subtest3="$pwd//sub3" +nstest=":ns:changeprofile" touch $file $subfile @@ -70,3 +71,10 @@ runchecktest "CHANGEPROFILE_RE (nochange access file)" pass nochange $file runchecktest_errno EACCES "CHANGEPROFILE_RE (nochange access subfile)" fail nochange $subfile runchecktest_errno EACCES "CHANGEPROFILE_RE (access file)" fail $fqsubtest $file runchecktest "CHANGEPROFILE_RE (access sub file)" pass $fqsubtest $subfile + +genprofile --stdin < ${nstest}, } +$nstest { $subfile ${okperm}, } +EOF +runchecktest "CHANGEPROFILE_NS (access sub file)" pass $nstest $subfile +runchecktest "CHANGEPROFILE_NS (access file)" fail $nstest $file