diff mbox series

[5/5] checkpolicy: clear queue between parser passes

Message ID 20250115131329.132477-4-cgoettsche@seltendoof.de (mailing list archive)
State New
Headers show
Series [1/5] libselinux: set errno in failure case | expand

Commit Message

Christian Göttsche Jan. 15, 2025, 1:13 p.m. UTC
From: Christian Göttsche <cgzones@googlemail.com>

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@googlemail.com>
---
 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 mbox series

Patch

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);
 
 /*