diff --git a/parser/dbus.c b/parser/dbus.c index e86e7c9ef..43c1066c5 100644 --- a/parser/dbus.c +++ b/parser/dbus.c @@ -38,16 +38,6 @@ int parse_dbus_mode(const char *str_mode, int *mode, int fail) return parse_X_mode("DBus", AA_VALID_DBUS_PERMS, str_mode, mode, fail); } -static void move_conditional_value(char **dst_ptr, struct cond_entry *cond_ent) -{ - if (*dst_ptr) - yyerror("dbus conditional \"%s\" can only be specified once\n", - cond_ent->name); - - *dst_ptr = cond_ent->vals->value; - cond_ent->vals->value = NULL; -} - void dbus_rule::move_conditionals(struct cond_entry *conds) { struct cond_entry *cond_ent; @@ -61,17 +51,17 @@ void dbus_rule::move_conditionals(struct cond_entry *conds) cond_ent->name); if (strcmp(cond_ent->name, "bus") == 0) { - move_conditional_value(&bus, cond_ent); + move_conditional_value("dbus", &bus, cond_ent); } else if (strcmp(cond_ent->name, "name") == 0) { - move_conditional_value(&name, cond_ent); + move_conditional_value("dbus", &name, cond_ent); } else if (strcmp(cond_ent->name, "label") == 0) { - move_conditional_value(&peer_label, cond_ent); + move_conditional_value("dbus", &peer_label, cond_ent); } else if (strcmp(cond_ent->name, "path") == 0) { - move_conditional_value(&path, cond_ent); + move_conditional_value("dbus", &path, cond_ent); } else if (strcmp(cond_ent->name, "interface") == 0) { - move_conditional_value(&interface, cond_ent); + move_conditional_value("dbus", &interface, cond_ent); } else if (strcmp(cond_ent->name, "member") == 0) { - move_conditional_value(&member, cond_ent); + move_conditional_value("dbus", &member, cond_ent); } else { yyerror("invalid dbus conditional \"%s\"\n", cond_ent->name); diff --git a/parser/parser.h b/parser/parser.h index 7539be2ef..8bc97c177 100644 --- a/parser/parser.h +++ b/parser/parser.h @@ -78,6 +78,12 @@ struct cond_entry { struct cond_entry *next; }; +struct cond_entry_list { + char *name; + + struct cond_entry *list; +}; + struct cod_entry { char *ns; char *name; @@ -362,6 +368,8 @@ extern struct value_list *dup_value_list(struct value_list *list); extern void free_value_list(struct value_list *list); extern void print_value_list(struct value_list *list); extern struct cond_entry *new_cond_entry(char *name, int eq, struct value_list *list); +extern void move_conditional_value(const char *rulename, char **dst_ptr, + struct cond_entry *cond_ent); extern void free_cond_entry(struct cond_entry *ent); extern void free_cond_list(struct cond_entry *ents); extern void print_cond_entry(struct cond_entry *ent); diff --git a/parser/parser_lex.l b/parser/parser_lex.l index 21d81705d..f42c18a97 100644 --- a/parser/parser_lex.l +++ b/parser/parser_lex.l @@ -301,19 +301,21 @@ LT_EQUAL <= } { + {VARIABLE_NAME}/{WS}*={WS}*\( { + /* we match to the = in the lexer so that we can switch scanner + * state. By the time the parser see the = it may be too late + * as bison may have requested the next token from the scanner + */ + yylval.id = processid(yytext, yyleng); + PUSH_AND_RETURN(EXTCONDLIST_MODE, TOK_CONDLISTID); + } {VARIABLE_NAME}/{WS}*= { /* we match to the = in the lexer so that we can switch scanner * state. By the time the parser see the = it may be too late * as bison may have requested the next token from the scanner */ - int token = get_keyword_token(yytext); - - if (token == TOK_PEER) { - PUSH_AND_RETURN(EXTCONDLIST_MODE, TOK_CONDLISTID); - } else { - yylval.id = processid(yytext, yyleng); - PUSH_AND_RETURN(EXTCOND_MODE, TOK_CONDID); - } + yylval.id = processid(yytext, yyleng); + PUSH_AND_RETURN(EXTCOND_MODE, TOK_CONDID); } {VARIABLE_NAME}/{WS}+in{WS}*\( { /* we match to 'in' in the lexer so that we can switch scanner diff --git a/parser/parser_misc.c b/parser/parser_misc.c index 23cb5d0dd..eaf88eb62 100644 --- a/parser/parser_misc.c +++ b/parser/parser_misc.c @@ -1150,6 +1150,17 @@ void print_value_list(struct value_list *list) } } +void move_conditional_value(const char *rulename, char **dst_ptr, + struct cond_entry *cond_ent) +{ + if (*dst_ptr) + yyerror("%s conditional \"%s\" can only be specified once\n", + rulename, cond_ent->name); + + *dst_ptr = cond_ent->vals->value; + cond_ent->vals->value = NULL; +} + struct cond_entry *new_cond_entry(char *name, int eq, struct value_list *list) { struct cond_entry *ent = (struct cond_entry *) calloc(1, sizeof(struct cond_entry)); diff --git a/parser/parser_yacc.y b/parser/parser_yacc.y index c880faf49..6ae3b5b22 100644 --- a/parser/parser_yacc.y +++ b/parser/parser_yacc.y @@ -166,6 +166,7 @@ void add_local_entry(Profile *prof); %token TOK_FLAGS %code requires { + #include "parser.h" #include "profile.h" #include "mount.h" #include "dbus.h" @@ -194,6 +195,7 @@ void add_local_entry(Profile *prof); char *var_val; struct value_list *val_list; struct cond_entry *cond_entry; + struct cond_entry_list cond_entry_list; int boolean; struct named_transition transition; struct prefixes prefix; @@ -219,8 +221,8 @@ void add_local_entry(Profile *prof); %type mnt_rule %type opt_conds %type cond -%type cond_list -%type opt_cond_list +%type cond_list +%type opt_cond_list %type flags %type flagvals %type flagval @@ -1145,10 +1147,11 @@ opt_conds: { /* nothing */ $$ = NULL; } cond_list: TOK_CONDLISTID TOK_EQUALS TOK_OPENPAREN opt_conds TOK_CLOSEPAREN { - $$ = $4; + $$.name = $1; + $$.list = $4; } -opt_cond_list: { /* nothing */ $$ = NULL; } +opt_cond_list: { /* nothing */ $$ = { NULL, NULL }; } | cond_list { $$ = $1; } mnt_rule: TOK_MOUNT opt_conds opt_id TOK_END_OF_RULE @@ -1232,7 +1235,12 @@ dbus_rule: TOK_DBUS opt_dbus_perm opt_conds opt_cond_list TOK_END_OF_RULE { dbus_rule *ent; - ent = new dbus_rule($2, $3, $4); + if ($4.name) { + if (strcmp($4.name, "peer") != 0) + yyerror(_("dbus rule: invalid conditional group %s=()"), $4.name); + free($4.name); + } + ent = new dbus_rule($2, $3, $4.list); if (!ent) { yyerror(_("Memory allocation error.")); } @@ -1273,12 +1281,7 @@ opt_signal_perm: { /* nothing */ $$ = 0; } signal_rule: TOK_SIGNAL opt_signal_perm opt_conds TOK_END_OF_RULE { - signal_rule *ent = new signal_rule($2, $3, NULL); - $$ = ent; - } - | TOK_SIGNAL opt_signal_perm opt_conds TOK_ID TOK_END_OF_RULE - { - signal_rule *ent = new signal_rule($2, $3, $4); + signal_rule *ent = new signal_rule($2, $3); $$ = ent; } diff --git a/parser/signal.c b/parser/signal.c index de6fc8aba..e12a8f4dd 100644 --- a/parser/signal.c +++ b/parser/signal.c @@ -165,6 +165,8 @@ void signal_rule::move_conditionals(struct cond_entry *conds) yyerror("keyword \"in\" is not allowed in signal rules\n"); if (strcmp(cond_ent->name, "set") == 0) { extract_sigs(&cond_ent->vals); + } else if (strcmp(cond_ent->name, "peer") == 0) { + move_conditional_value("signal", &peer_label, cond_ent); } else { yyerror("invalid signal rule conditional \"%s\"\n", cond_ent->name); @@ -172,9 +174,8 @@ void signal_rule::move_conditionals(struct cond_entry *conds) } } -signal_rule::signal_rule(int mode_p, struct cond_entry *conds, - char *peer): - signals(), peer_label(peer), audit(0), deny(0) +signal_rule::signal_rule(int mode_p, struct cond_entry *conds): + signals(), peer_label(NULL), audit(0), deny(0) { if (mode_p) { mode = mode_p; diff --git a/parser/signal.h b/parser/signal.h index e798b8c41..afdb10057 100644 --- a/parser/signal.h +++ b/parser/signal.h @@ -43,7 +43,7 @@ public: int audit; int deny; - signal_rule(int mode, struct cond_entry *conds, char *peer); + signal_rule(int mode, struct cond_entry *conds); virtual ~signal_rule() { signals.clear(); free(peer_label);