diff --git a/parser/parser.h b/parser/parser.h index e9b4f4b3e..a4630f859 100644 --- a/parser/parser.h +++ b/parser/parser.h @@ -38,6 +38,7 @@ struct cod_pattern { struct cod_entry { char *namespace; char *name; + char *link_name; struct codomain *codomain; /* Special codomain defined * just for this executable */ int mode; /* mode is 'or' of AA_* bits */ @@ -194,7 +195,8 @@ extern int get_keyword_token(const char *keyword); extern int name_to_capability(const char *keyword); extern char *process_var(const char *var); extern int parse_mode(const char *mode); -extern struct cod_entry *new_entry(char *namespace, char *id, int mode); +extern struct cod_entry *new_entry(char *namespace, char *id, int mode, + char *link_id); extern struct aa_network_entry *new_network_ent(unsigned int family, unsigned int type, unsigned int protocol); diff --git a/parser/parser_lex.l b/parser/parser_lex.l index f65f2b47b..51d81c578 100644 --- a/parser/parser_lex.l +++ b/parser/parser_lex.l @@ -78,6 +78,7 @@ FLAGCLOSE_PAREN \) FLAGSEP \, EQUALS = ADD_ASSIGN \+= +ARROW -> %x SUB_NAME %x NETWORK_MODE @@ -211,6 +212,11 @@ ADD_ASSIGN \+= BEGIN(SUB_NAME); return TOK_SEP; } +{ARROW} { + PDEBUG("Matched a arrow\n"); + yylval = (YYSTYPE) yytext; + return TOK_ARROW; + } {EQUALS} { PDEBUG("Matched equals for assignment\n"); BEGIN(ASSIGN_MODE); diff --git a/parser/parser_merge.c b/parser/parser_merge.c index f1f7f65fb..86fcba200 100644 --- a/parser/parser_merge.c +++ b/parser/parser_merge.c @@ -91,6 +91,8 @@ static int process_file_entries(struct codomain *cod) } cur->mode |= next->mode; free(next->name); + if (next->link_name) + free(next->link_name); free(next); table[n] = NULL; } else { diff --git a/parser/parser_misc.c b/parser/parser_misc.c index 87f45150c..8d96fd6f2 100644 --- a/parser/parser_misc.c +++ b/parser/parser_misc.c @@ -60,6 +60,7 @@ static struct keyword_table keyword_table[] = { {"defined", TOK_DEFINED}, {"change_profile", TOK_CHANGE_PROFILE}, {"unsafe", TOK_UNSAFE}, + {"link", TOK_LINK}, /* terminate */ {NULL, 0} }; @@ -608,7 +609,7 @@ int parse_mode(const char *str_mode) return mode; } -struct cod_entry *new_entry(char *namespace, char *id, int mode) +struct cod_entry *new_entry(char *namespace, char *id, int mode, char *link_id) { struct cod_entry *entry = NULL; @@ -618,6 +619,7 @@ struct cod_entry *new_entry(char *namespace, char *id, int mode) entry->namespace = namespace; entry->name = id; + entry->link_name = link_id; entry->mode = mode; entry->deny = FALSE; @@ -641,6 +643,7 @@ struct cod_entry *copy_cod_entry(struct cod_entry *orig) entry->namespace = orig->namespace ? strdup(orig->namespace) : NULL; entry->name = strdup(orig->name); + entry->link_name = orig->link_name ? strdup(orig->link_name) : NULL; entry->mode = orig->mode; entry->deny = orig->deny; @@ -664,6 +667,8 @@ void free_cod_entries(struct cod_entry *list) free(list->namespace); if (list->name) free(list->name); + if (list->link_name) + free(list->link_name); if (list->pat.regex) free(list->pat.regex); if (list->pat.compiled) @@ -732,6 +737,9 @@ void debug_cod_entries(struct cod_entry *list) if (item->namespace) printf("\tNamespace:\t(%s)\n", item->namespace); + if (AA_LINK_BITS & item->mode) + printf("\tlink:\t(%s)\n", item->link_name ? item->link_name : "/**"); + } } diff --git a/parser/parser_regex.c b/parser/parser_regex.c index 2013ec27b..c59e69f36 100644 --- a/parser/parser_regex.c +++ b/parser/parser_regex.c @@ -512,8 +512,12 @@ static int process_dfa_entry(aare_ruleset_t *dfarules, struct cod_entry *entry) /* add the pair rule */ char lbuf[PATH_MAX + 8]; int perms = AA_LINK_BITS & entry->mode; - perms |= LINK_TO_LINK_SUBSET(perms); - sprintf(lbuf, "%s///**", entry->name); + if (entry->link_name) { + sprintf(lbuf, "%s//%s", entry->name, entry->link_name); + } else { + perms |= LINK_TO_LINK_SUBSET(perms); + sprintf(lbuf, "%s///**", entry->name); + } ptype = convert_aaregex_to_pcre(lbuf, 0, tbuf, PATH_MAX + 8); if (ptype == ePatternInvalid) return FALSE; diff --git a/parser/parser_yacc.y b/parser/parser_yacc.y index f76a041bd..7faf03939 100644 --- a/parser/parser_yacc.y +++ b/parser/parser_yacc.y @@ -67,7 +67,8 @@ struct value_list { }; void free_value_list(struct value_list *list); -struct cod_entry *do_file_rule(char *namespace, char *id, int mode); +struct cod_entry *do_file_rule(char *namespace, char *id, int mode, + char *link_id); %} @@ -78,6 +79,7 @@ struct cod_entry *do_file_rule(char *namespace, char *id, int mode); %token TOK_MODE %token TOK_END_OF_RULE %token TOK_EQUALS +%token TOK_ARROW %token TOK_ADD_ASSIGN %token TOK_SET_VAR %token TOK_BOOL_VAR @@ -91,6 +93,7 @@ struct cod_entry *do_file_rule(char *namespace, char *id, int mode); %token TOK_HAT %token TOK_UNSAFE %token TOK_COLON +%token TOK_LINK /* capabilities */ %token TOK_CAPABILITY @@ -513,12 +516,12 @@ id_or_var: TOK_SET_VAR { $$ = $1; }; rule: id_or_var file_mode TOK_END_OF_RULE { - $$ = do_file_rule(NULL, $1, $2); + $$ = do_file_rule(NULL, $1, $2, NULL); }; rule: file_mode id_or_var TOK_END_OF_RULE { - $$ = do_file_rule(NULL, $2, $1 & ~ALL_AA_EXEC_UNSAFE); + $$ = do_file_rule(NULL, $2, $1 & ~ALL_AA_EXEC_UNSAFE, NULL); }; rule: TOK_UNSAFE file_mode id_or_var TOK_END_OF_RULE @@ -526,7 +529,8 @@ rule: TOK_UNSAFE file_mode id_or_var TOK_END_OF_RULE int mode = (($2 & AA_EXEC_BITS) << 7) & ALL_AA_EXEC_UNSAFE; if (!($2 & AA_EXEC_BITS)) yyerror(_("unsafe rule missing exec permissions")); - $$ = do_file_rule(NULL, $3, ($2 & ~ALL_AA_EXEC_UNSAFE) | mode); + $$ = do_file_rule(NULL, $3, ($2 & ~ALL_AA_EXEC_UNSAFE) | mode, + NULL); }; rule: id_or_var file_mode id_or_var @@ -538,6 +542,32 @@ rule: id_or_var file_mode id_or_var yyerror(_("missing an end of line character? (entry: %s)"), $1); }; +rule: TOK_LINK TOK_ID TOK_ARROW TOK_ID TOK_END_OF_RULE + { + struct cod_entry *entry; + PDEBUG("Matched: link tok_id (%s) -> (%s)\n", $2, $4); + entry = new_entry(NULL, $2, AA_LINK_BITS, $4); + if (!entry) + yyerror(_("Memory allocation error.")); + PDEBUG("rule.entry: link (%s)\n", entry->name); + $$ = entry; + }; + +rule: TOK_LINK file_mode TOK_ID TOK_ARROW TOK_ID TOK_END_OF_RULE + { + struct cod_entry *entry; + PDEBUG("Matched: link tok_id (%s) -> (%s)\n", $3, $5); + if ($2 & ~AA_LINK_BITS) { + yyerror(_("only link perms can be specified in a link rule.")); + } else { + entry = new_entry(NULL, $3, $2, $5); + if (!entry) + yyerror(_("Memory allocation error.")); + } + PDEBUG("rule.entry: link (%s)\n", entry->name); + $$ = entry; + }; + hat: hat_start TOK_ID flags TOK_OPEN rules TOK_CLOSE { struct codomain *cod = $5; @@ -610,7 +640,7 @@ change_profile: TOK_CHANGE_PROFILE TOK_ID TOK_END_OF_RULE { struct cod_entry *entry; PDEBUG("Matched change_profile: tok_id (%s)\n", $2); - entry = new_entry(NULL, $2, AA_CHANGE_PROFILE); + entry = new_entry(NULL, $2, AA_CHANGE_PROFILE, NULL); if (!entry) yyerror(_("Memory allocation error.")); PDEBUG("change_profile.entry: (%s)\n", entry->name); @@ -621,7 +651,7 @@ change_profile: TOK_CHANGE_PROFILE TOK_ID TOK_COLON TOK_ID TOK_END_OF_RULE { struct cod_entry *entry; PDEBUG("Matched change_profile: tok_id (%s:%s)\n", $2, $4); - entry = new_entry($2, $4, AA_CHANGE_PROFILE); + entry = new_entry($2, $4, AA_CHANGE_PROFILE, NULL); if (!entry) yyerror(_("Memory allocation error.")); PDEBUG("change_profile.entry: (%s)\n", entry->name); @@ -685,11 +715,12 @@ void free_value_list(struct value_list *list) } } -struct cod_entry *do_file_rule(char *namespace, char *id, int mode) +struct cod_entry *do_file_rule(char *namespace, char *id, int mode, + char *link_id) { struct cod_entry *entry; PDEBUG("Matched: tok_id (%s) tok_mode (0x%x)\n", id, mode); - entry = new_entry(namespace, id, mode); + entry = new_entry(namespace, id, mode, link_id); if (!entry) yyerror(_("Memory allocation error.")); PDEBUG("rule.entry: (%s)\n", entry->name);