From: Christian Göttsche <cgzones@xxxxxxxxxxxxxx> Clear the identifier queue after pass 1 to void unhandled identifiers from pass 1 leaking into pass 2 and leading to confusing error messages. For example for the following policy the error changes from 'no user name' to 'unknown role j': class C sid S class C { P } ; user U roles j; sid S s:l:q:q:q While on it call set_source_file() from init_parser(). Signed-off-by: Christian Göttsche <cgzones@xxxxxxxxxxxxxx> --- checkpolicy/fuzz/checkpolicy-fuzzer.c | 10 +++------- checkpolicy/parse_util.c | 9 +++------ checkpolicy/policy_define.c | 7 +++++-- checkpolicy/queue.c | 18 ++++++++++++++++++ checkpolicy/queue.h | 1 + 5 files changed, 30 insertions(+), 15 deletions(-) diff --git a/checkpolicy/fuzz/checkpolicy-fuzzer.c b/checkpolicy/fuzz/checkpolicy-fuzzer.c index 331201c0..c99ef412 100644 --- a/checkpolicy/fuzz/checkpolicy-fuzzer.c +++ b/checkpolicy/fuzz/checkpolicy-fuzzer.c @@ -25,11 +25,10 @@ extern unsigned int policydb_errors; extern int yynerrs; extern FILE *yyin; -extern void init_parser(int); +extern void init_parser(int pass, const char *input_name); extern int yyparse(void); extern void yyrestart(FILE *); extern int yylex_destroy(void); -extern void set_source_file(const char *name); jmp_buf fuzzing_pre_parse_stack_state; @@ -87,8 +86,6 @@ static int read_source_policy(policydb_t *p, const uint8_t *data, size_t size) rewind(yyin); - set_source_file("fuzz-input"); - id_queue = queue_create(); if (id_queue == NULL) { fclose(yyin); @@ -99,7 +96,7 @@ static int read_source_policy(policydb_t *p, const uint8_t *data, size_t size) policydbp = p; mlspol = p->mls; - init_parser(1); + init_parser(1, "fuzz-input-1"); if (setjmp(fuzzing_pre_parse_stack_state) != 0) { queue_destroy(id_queue); @@ -119,8 +116,7 @@ static int read_source_policy(policydb_t *p, const uint8_t *data, size_t size) } rewind(yyin); - init_parser(2); - set_source_file("fuzz-input"); + init_parser(2, "fuzz-input-2"); yyrestart(yyin); rc = yyparse(); diff --git a/checkpolicy/parse_util.c b/checkpolicy/parse_util.c index eda814e1..389c9ff3 100644 --- a/checkpolicy/parse_util.c +++ b/checkpolicy/parse_util.c @@ -23,7 +23,7 @@ /* these are defined in policy_parse.y and are needed for read_source_policy */ extern FILE *yyin; -extern void init_parser(int); +extern void init_parser(int pass, const char *input_name); extern int yyparse(void); extern void yyrestart(FILE *); extern int yylex_destroy(void); @@ -31,7 +31,6 @@ extern queue_t id_queue; extern unsigned int policydb_errors; extern policydb_t *policydbp; extern int mlspol; -extern void set_source_file(const char *name); int read_source_policy(policydb_t * p, const char *file, const char *progname) { @@ -42,7 +41,6 @@ int read_source_policy(policydb_t * p, const char *file, const char *progname) fprintf(stderr, "%s: unable to open %s: %s\n", progname, file, strerror(errno)); return -1; } - set_source_file(file); id_queue = queue_create(); if (id_queue == NULL) { @@ -58,7 +56,7 @@ int read_source_policy(policydb_t * p, const char *file, const char *progname) goto cleanup; } - init_parser(1); + init_parser(1, file); if (yyparse() || policydb_errors) { fprintf(stderr, "%s: error(s) encountered while parsing configuration\n", @@ -66,8 +64,7 @@ int read_source_policy(policydb_t * p, const char *file, const char *progname) goto cleanup; } rewind(yyin); - init_parser(2); - set_source_file(file); + init_parser(2, file); yyrestart(yyin); if (yyparse() || policydb_errors) { fprintf(stderr, diff --git a/checkpolicy/policy_define.c b/checkpolicy/policy_define.c index a056be67..f19e9f6d 100644 --- a/checkpolicy/policy_define.c +++ b/checkpolicy/policy_define.c @@ -58,7 +58,7 @@ #include "module_compiler.h" #include "policy_define.h" -extern void init_parser(int pass_number); +extern void init_parser(int pass_number, const char *input_name); __attribute__ ((format(printf, 1, 2))) extern void yyerror2(const char *fmt, ...); @@ -71,17 +71,20 @@ extern unsigned long policydb_lineno; extern unsigned long source_lineno; extern unsigned int policydb_errors; extern char source_file[PATH_MAX]; +extern void set_source_file(const char *name); extern int yywarn(const char *msg); extern int yyerror(const char *msg); /* initialize all of the state variables for the scanner/parser */ -void init_parser(int pass_number) +void init_parser(int pass_number, const char *input_name) { policydb_lineno = 1; source_lineno = 1; policydb_errors = 0; pass = pass_number; + set_source_file(input_name); + queue_clear(id_queue); } void yyerror2(const char *fmt, ...) diff --git a/checkpolicy/queue.c b/checkpolicy/queue.c index 9f4c651a..5eee2871 100644 --- a/checkpolicy/queue.c +++ b/checkpolicy/queue.c @@ -104,6 +104,24 @@ queue_element_t queue_head(queue_t q) return q->head->element; } +void queue_clear(queue_t q) +{ + queue_node_ptr_t p, temp; + + if (!q) + return; + + p = q->head; + while (p != NULL) { + free(p->element); + temp = p; + p = p->next; + free(temp); + } + + q->head = q->tail = NULL; +} + void queue_destroy(queue_t q) { queue_node_ptr_t p, temp; diff --git a/checkpolicy/queue.h b/checkpolicy/queue.h index 45116dee..3ce2e5bd 100644 --- a/checkpolicy/queue.h +++ b/checkpolicy/queue.h @@ -33,6 +33,7 @@ int queue_insert(queue_t, queue_element_t); int queue_push(queue_t, queue_element_t); queue_element_t queue_remove(queue_t); queue_element_t queue_head(queue_t); +void queue_clear(queue_t); void queue_destroy(queue_t); /* -- 2.47.1