Update to checkpolicy 2.4.

Update to current upstream checkpolicy release.
Includes a variety of bug and memory leak fixes, performance
optimizations for neverallow checking, and improved error
reporting.

Depends on libsepol 2.4.

Change-Id: If08ba195e156dd23bc07e2005d803abbed4a90bc
Signed-off-by: Stephen Smalley <sds@tycho.nsa.gov>
diff --git a/ChangeLog b/ChangeLog
index 0c76070..127cd6a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2.4 2015-02-02
+	* Fix bugs found by hardened gcc flags, from Nicolas Iooss.
+	* Add missing semicolon in cond_else parser rule, from Steven Capelli.
+	* Clear errno before call to strtol(3) from Dan Albert.
+	* Global C++11 compatibility from Dan Albert.
+	* Allow libsepol C++ static library on device from Daniel Cashman.
+
+2.3 2014-05-06
+	* Add Android support for building dispol.
+	* Report source file and line information for neverallow failures.
+	* Prevent incompatible option combinations for checkmodule.
+	* Drop -lselinux from LDLIBS for test programs; not used.
+	* Add debug feature to display constraints/validatetrans from Richard Haines.
+
 2.2 2013-10-30
 	* Fix hyphen usage in man pages from Laurent Bigonville.
 	* handle-unknown / -U required argument fix from Laurent Bigonville.
diff --git a/VERSION b/VERSION
index 8bbe6cf..6b4950e 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.2
+2.4
diff --git a/checkmodule.c b/checkmodule.c
index 41ebab5..0255928 100644
--- a/checkmodule.c
+++ b/checkmodule.c
@@ -41,13 +41,13 @@
 extern int mlspol;
 
 static int handle_unknown = SEPOL_DENY_UNKNOWN;
-static char *txtfile = "policy.conf";
-static char *binfile = "policy";
+static const char *txtfile = "policy.conf";
+static const char *binfile = "policy";
 
 unsigned int policy_type = POLICY_BASE;
 unsigned int policyvers = MOD_POLICYDB_VERSION_MAX;
 
-static int read_binary_policy(policydb_t * p, char *file, char *progname)
+static int read_binary_policy(policydb_t * p, const char *file, const char *progname)
 {
 	int fd;
 	struct stat sb;
@@ -108,7 +108,7 @@
 	return 0;
 }
 
-static int write_binary_policy(policydb_t * p, char *file, char *progname)
+static int write_binary_policy(policydb_t * p, const char *file, char *progname)
 {
 	FILE *outfp = NULL;
 	struct policy_file pf;
@@ -161,7 +161,7 @@
 
 int main(int argc, char **argv)
 {
-	char *file = txtfile, *outfile = NULL;
+	const char *file = txtfile, *outfile = NULL;
 	unsigned int binary = 0;
 	int ch;
 	int show_version = 0;
@@ -224,8 +224,12 @@
 	}
 
 	if (handle_unknown && (policy_type != POLICY_BASE)) {
-		printf("Handling of unknown classes and permissions is only ");
-		printf("valid in the base module\n");
+		fprintf(stderr, "%s:  Handling of unknown classes and permissions is only valid in the base module.\n", argv[0]);
+		exit(1);
+	}
+
+	if (binary && (policy_type != POLICY_BASE)) {
+		fprintf(stderr, "%s:  -b and -m are incompatible with each other.\n", argv[0]);
 		exit(1);
 	}
 
diff --git a/checkpolicy.c b/checkpolicy.c
index 2a09734..61a2e89 100644
--- a/checkpolicy.c
+++ b/checkpolicy.c
@@ -96,8 +96,8 @@
 extern int mlspol;
 
 static int handle_unknown = SEPOL_DENY_UNKNOWN;
-static char *txtfile = "policy.conf";
-static char *binfile = "policy";
+static const char *txtfile = "policy.conf";
+static const char *binfile = "policy";
 
 unsigned int policyvers = POLICYDB_VERSION_MAX;
 
@@ -289,9 +289,9 @@
 
 extern char *av_to_string(uint32_t tclass, sepol_access_vector_t av);
 
-int display_bools()
+int display_bools(void)
 {
-	int i;
+	uint32_t i;
 
 	for (i = 0; i < policydbp->p_bools.nprim; i++) {
 		printf("%s : %d\n", policydbp->p_bool_val_to_name[i],
@@ -335,7 +335,7 @@
 	}
 }
 
-int display_cond_expressions()
+int display_cond_expressions(void)
 {
 	cond_node_t *cur;
 
@@ -361,7 +361,7 @@
 	return 0;
 }
 
-static int check_level(hashtab_key_t key, hashtab_datum_t datum, void *arg)
+static int check_level(hashtab_key_t key, hashtab_datum_t datum, void *arg __attribute__ ((unused)))
 {
 	level_datum_t *levdatum = (level_datum_t *) datum;
 
@@ -377,11 +377,12 @@
 int main(int argc, char **argv)
 {
 	sepol_security_class_t tclass;
-	sepol_security_id_t ssid, tsid, *sids;
+	sepol_security_id_t ssid, tsid, *sids, oldsid, newsid, tasksid;
 	sepol_security_context_t scontext;
 	struct sepol_av_decision avd;
 	class_datum_t *cladatum;
-	char ans[80 + 1], *file = txtfile, *outfile = NULL, *path, *fstype;
+	const char *file = txtfile;
+	char ans[80 + 1], *outfile = NULL, *path, *fstype;
 	size_t scontext_len, pathlen;
 	unsigned int i;
 	unsigned int protocol, port;
@@ -395,6 +396,9 @@
 	char *name;
 	int state;
 	int show_version = 0;
+	char *reason_buf = NULL;
+	unsigned int reason;
+	int flags;
 	struct policy_file pf;
 	struct option long_options[] = {
 		{"output", required_argument, NULL, 'o'},
@@ -646,6 +650,8 @@
 	printf("f)  display conditional bools\n");
 	printf("g)  display conditional expressions\n");
 	printf("h)  change a boolean value\n");
+	printf("i)  display constraint expressions\n");
+	printf("j)  display validatetrans expressions\n");
 #ifdef EQUIVTYPES
 	printf("z)  Show equivalent types\n");
 #endif
@@ -1062,6 +1068,109 @@
 			change_bool(name, state);
 			free(name);
 			break;
+		case 'i':
+			printf("source sid?  ");
+			FGETS(ans, sizeof(ans), stdin);
+			ssid = atoi(ans);
+
+			printf("target sid?  ");
+			FGETS(ans, sizeof(ans), stdin);
+			tsid = atoi(ans);
+
+			printf("target class?  ");
+			FGETS(ans, sizeof(ans), stdin);
+			if (isdigit(ans[0])) {
+				tclass = atoi(ans);
+				if (!tclass
+				    || tclass > policydb.p_classes.nprim) {
+					printf("\nNo such class.\n");
+					break;
+				}
+				cladatum =
+				    policydb.class_val_to_struct[tclass - 1];
+			} else {
+				ans[strlen(ans) - 1] = 0;
+				cladatum =
+				    (class_datum_t *) hashtab_search(policydb.
+								     p_classes.
+								     table,
+								     ans);
+				if (!cladatum) {
+					printf("\nNo such class\n");
+					break;
+				}
+				tclass = cladatum->s.value;
+			}
+
+			flags = SHOW_GRANTED;
+			if (sepol_compute_av_reason_buffer(ssid, tsid,
+					tclass, 0, &avd, &reason,
+					&reason_buf, flags)) {
+				printf("\nconstraint error\n");
+				break;
+			}
+			if (reason_buf) {
+				printf("\nConstraint expressions:\n%s",
+						reason_buf);
+				free(reason_buf);
+			} else {
+				printf("\nNo constraints found.\n");
+			}
+			break;
+		case 'j':
+			printf("old sid?  ");
+			FGETS(ans, sizeof(ans), stdin);
+			oldsid = atoi(ans);
+
+			printf("new sid?  ");
+			FGETS(ans, sizeof(ans), stdin);
+			newsid = atoi(ans);
+
+			printf("task sid?  ");
+			FGETS(ans, sizeof(ans), stdin);
+			tasksid = atoi(ans);
+
+			printf("target class?  ");
+			FGETS(ans, sizeof(ans), stdin);
+			if (isdigit(ans[0])) {
+				tclass = atoi(ans);
+				if (!tclass
+				    || tclass > policydb.p_classes.nprim) {
+					printf("\nNo such class.\n");
+					break;
+				}
+				cladatum =
+				    policydb.class_val_to_struct[tclass - 1];
+			} else {
+				ans[strlen(ans) - 1] = 0;
+				cladatum =
+				    (class_datum_t *) hashtab_search(policydb.
+								     p_classes.
+								     table,
+								     ans);
+				if (!cladatum) {
+					printf("\nNo such class\n");
+					break;
+				}
+				tclass = cladatum->s.value;
+			}
+
+			flags = SHOW_GRANTED;
+			if (sepol_validate_transition_reason_buffer(oldsid,
+						newsid, tasksid, tclass,
+						&reason_buf, flags)) {
+				printf("\nvalidatetrans error\n");
+				break;
+			}
+			if (reason_buf) {
+				printf("\nValidatetrans expressions:\n%s",
+						reason_buf);
+				free(reason_buf);
+			} else {
+				printf(
+				    "\nNo validatetrans expressions found.\n");
+			}
+			break;
 #ifdef EQUIVTYPES
 		case 'z':
 			identify_equiv_types();
diff --git a/module_compiler.c b/module_compiler.c
index ffffaf1..d7f27f5 100644
--- a/module_compiler.c
+++ b/module_compiler.c
@@ -39,8 +39,9 @@
 
 extern policydb_t *policydbp;
 extern queue_t id_queue;
-extern int yyerror(char *msg);
-extern void yyerror2(char *fmt, ...);
+extern int yyerror(const char *msg);
+__attribute__ ((format(printf, 1, 2)))
+extern void yyerror2(const char *fmt, ...);
 
 static int push_stack(int stack_type, ...);
 static void pop_stack(void);
@@ -700,7 +701,7 @@
 	assert(class_value >= 1);
 	scope = &decl->required;
 	if (class_value > scope->class_perms_len) {
-		int i;
+		uint32_t i;
 		ebitmap_t *new_map = realloc(scope->class_perms_map,
 					     class_value * sizeof(*new_map));
 		if (new_map == NULL) {
@@ -1224,7 +1225,7 @@
 
 static int is_scope_in_stack(scope_datum_t * scope, scope_stack_t * stack)
 {
-	int i;
+	uint32_t i;
 	if (stack == NULL) {
 		return 0;	/* no matching scope found */
 	}
@@ -1445,7 +1446,7 @@
 	return -1;
 }
 
-int end_optional(int pass)
+int end_optional(int pass __attribute__ ((unused)))
 {
 	/* once nested conditionals are allowed, do the stack unfolding here */
 	pop_stack();
@@ -1481,7 +1482,7 @@
 
 static int copy_requirements(avrule_decl_t * dest, scope_stack_t * stack)
 {
-	int i;
+	uint32_t i;
 	if (stack == NULL) {
 		return 0;
 	}
diff --git a/policy_define.c b/policy_define.c
index cfd255e..a6c5d65 100644
--- a/policy_define.c
+++ b/policy_define.c
@@ -63,8 +63,8 @@
 extern unsigned int policydb_errors;
 extern char source_file[PATH_MAX];
 
-extern int yywarn(char *msg);
-extern int yyerror(char *msg);
+extern int yywarn(const char *msg);
+extern int yyerror(const char *msg);
 
 #define ERRORMSG_LEN 255
 static char errormsg[ERRORMSG_LEN + 1] = {0};
@@ -81,7 +81,8 @@
 	pass = pass_number;
 }
 
-void yyerror2(char *fmt, ...)
+__attribute__ ((format(printf, 1, 2)))
+void yyerror2(const char *fmt, ...)
 {
 	va_list ap;
 	va_start(ap, fmt);
@@ -106,7 +107,7 @@
 	return 0;
 }
 
-int insert_id(char *id, int push)
+int insert_id(const char *id, int push)
 {
 	char *newid = 0;
 	int error;
@@ -827,7 +828,7 @@
 int define_dominance(void)
 {
 	level_datum_t *datum;
-	int order;
+	uint32_t order;
 	char *id;
 
 	if (!mlspol) {
@@ -994,7 +995,7 @@
 	return -1;
 }
 
-static int clone_level(hashtab_key_t key, hashtab_datum_t datum, void *arg)
+static int clone_level(hashtab_key_t key __attribute__ ((unused)), hashtab_datum_t datum, void *arg)
 {
 	level_datum_t *levdatum = (level_datum_t *) datum;
 	mls_level_t *level = (mls_level_t *) arg, *newlevel;
@@ -2122,8 +2123,8 @@
 }
 
 /* This function eliminates the ordering dependency of role dominance rule */
-static int dominate_role_recheck(hashtab_key_t key, hashtab_datum_t datum,
-				 void *arg)
+static int dominate_role_recheck(hashtab_key_t key __attribute__ ((unused)),
+				 hashtab_datum_t datum, void *arg)
 {
 	role_datum_t *rdp = (role_datum_t *) arg;
 	role_datum_t *rdatum = (role_datum_t *) datum;
@@ -3442,7 +3443,7 @@
 	return 0;
 }
 
-static int parse_semantic_categories(char *id, level_datum_t * levdatum,
+static int parse_semantic_categories(char *id, level_datum_t * levdatum __attribute__ ((unused)),
 				     mls_semantic_cat_t ** cats)
 {
 	cat_datum_t *cdatum;
@@ -3959,7 +3960,7 @@
 	newc->u.iomem.high_iomem = high;
 
 	if (low > high) {
-		yyerror2("low memory 0x%x exceeds high memory 0x%x", low, high);
+		yyerror2("low memory 0x%lx exceeds high memory 0x%lx", low, high);
 		free(newc);
 		return -1;
 	}
@@ -3971,12 +3972,12 @@
 
 	head = policydbp->ocontexts[OCON_XEN_IOMEM];
 	for (l = NULL, c = head; c; l = c, c = c->next) {
-		unsigned int low2, high2;
+		uint32_t low2, high2;
 
 		low2 = c->u.iomem.low_iomem;
 		high2 = c->u.iomem.high_iomem;
 		if (low <= high2 && low2 <= high) {
-			yyerror2("iomemcon entry for 0x%x-0x%x overlaps with "
+			yyerror2("iomemcon entry for 0x%lx-0x%lx overlaps with "
 				"earlier entry 0x%x-0x%x", low, high,
 				low2, high2);
 			goto bad;
@@ -4023,7 +4024,7 @@
 	newc->u.ioport.high_ioport = high;
 
 	if (low > high) {
-		yyerror2("low ioport 0x%x exceeds high ioport 0x%x", low, high);
+		yyerror2("low ioport 0x%lx exceeds high ioport 0x%lx", low, high);
 		free(newc);
 		return -1;
 	}
@@ -4035,12 +4036,12 @@
 
 	head = policydbp->ocontexts[OCON_XEN_IOPORT];
 	for (l = NULL, c = head; c; l = c, c = c->next) {
-		unsigned int low2, high2;
+		uint32_t low2, high2;
 
 		low2 = c->u.ioport.low_ioport;
 		high2 = c->u.ioport.high_ioport;
 		if (low <= high2 && low2 <= high) {
-			yyerror2("ioportcon entry for 0x%x-0x%x overlaps with"
+			yyerror2("ioportcon entry for 0x%lx-0x%lx overlaps with"
 				"earlier entry 0x%x-0x%x", low, high,
 				low2, high2);
 			goto bad;
@@ -4096,7 +4097,7 @@
 
 		device2 = c->u.device;
 		if (device == device2) {
-			yyerror2("duplicate pcidevicecon entry for 0x%x ",
+			yyerror2("duplicate pcidevicecon entry for 0x%lx",
 				 device);
 			goto bad;
 		}
diff --git a/policy_define.h b/policy_define.h
index 8bfd8f6..4ef0f4f 100644
--- a/policy_define.h
+++ b/policy_define.h
@@ -64,7 +64,7 @@
 int define_type(int alias);
 int define_user(void);
 int define_validatetrans(constraint_expr_t *expr);
-int insert_id(char *id,int push);
+int insert_id(const char *id,int push);
 int insert_separator(int push);
 role_datum_t *define_role_dom(role_datum_t *r);
 role_datum_t *merge_roles_dom(role_datum_t *r1,role_datum_t *r2);
diff --git a/policy_parse.y b/policy_parse.y
index b40f413..15c8997 100644
--- a/policy_parse.y
+++ b/policy_parse.y
@@ -58,10 +58,10 @@
 
 extern char yytext[];
 extern int yylex(void);
-extern int yywarn(char *msg);
-extern int yyerror(char *msg);
+extern int yywarn(const char *msg);
+extern int yyerror(const char *msg);
 
-typedef int (* require_func_t)();
+typedef int (* require_func_t)(int pass);
 
 %}
 
@@ -356,6 +356,7 @@
 			{ $$ = $3; }
 			| /* empty */ 
 			{ $$ = NULL; }
+			;
 cond_expr               : '(' cond_expr ')'
 			{ $$ = $2;}
 			| NOT cond_expr
diff --git a/policy_scan.l b/policy_scan.l
index 454bb84..3a73962 100644
--- a/policy_scan.l
+++ b/policy_scan.l
@@ -25,7 +25,7 @@
 #include <stdint.h>
 #include <string.h>
 
-typedef int (* require_func_t)();
+typedef int (* require_func_t)(void);
 
 #ifdef ANDROID
 #include "policy_parse.h"
@@ -35,7 +35,7 @@
 
 static char linebuf[2][255];
 static unsigned int lno = 0;
-int yywarn(char *msg);
+int yywarn(const char *msg);
 
 void set_source_file(const char *name);
 
@@ -272,7 +272,7 @@
 "*"				{ return(yytext[0]); } 
 .                               { yywarn("unrecognized character");}
 %%
-int yyerror(char *msg)
+int yyerror(const char *msg)
 {
 	if (source_file[0])
 		fprintf(stderr, "%s:%ld:",
@@ -288,7 +288,7 @@
 	return -1;
 }
 
-int yywarn(char *msg)
+int yywarn(const char *msg)
 {
 	if (source_file[0])
 		fprintf(stderr, "%s:%ld:",
diff --git a/test/Makefile b/test/Makefile
index 63b4d24..c2367e1 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -9,7 +9,7 @@
 CFLAGS ?= -g -Wall -W -Werror -O2 -pipe
 override CFLAGS += -I$(INCLUDEDIR)
 
-LDLIBS=-lfl -lselinux $(LIBDIR)/libsepol.a -L$(LIBDIR)
+LDLIBS=-lfl $(LIBDIR)/libsepol.a -L$(LIBDIR)
 
 all: dispol dismod
 
diff --git a/test/dismod.c b/test/dismod.c
index 96ef047..db9ae55 100644
--- a/test/dismod.c
+++ b/test/dismod.c
@@ -65,7 +65,7 @@
 	"levels ", "cats   ", "attribs"
 };
 
-void usage(char *progname)
+void usage(const char *progname)
 {
 	printf("usage:  %s binary_pol_file\n\n", progname);
 	exit(1);
@@ -99,7 +99,7 @@
 }
 
 static void display_id(policydb_t * p, FILE * fp, uint32_t symbol_type,
-		       uint32_t symbol_value, char *prefix)
+		       uint32_t symbol_value, const char *prefix)
 {
 	char *id = p->sym_val_to_name[symbol_type][symbol_value];
 	scope_datum_t *scope =
@@ -269,7 +269,7 @@
 
 	cur = avrule->perms;
 	while (cur) {
-		display_id(policy, fp, SYM_CLASSES, cur->class - 1, "");
+		display_id(policy, fp, SYM_CLASSES, cur->tclass - 1, "");
 		cur = cur->next;
 	}
 
@@ -278,7 +278,7 @@
 	fprintf(fp, " ");
 
 	if (avrule->specified & (AVRULE_AV | AVRULE_NEVERALLOW)) {
-		render_access_mask(avrule->perms->data, avrule->perms->class,
+		render_access_mask(avrule->perms->data, avrule->perms->tclass,
 				   policy, fp);
 	} else if (avrule->specified & AVRULE_TYPE) {
 		display_id(policy, fp, SYM_TYPES, avrule->perms->data - 1, "");
@@ -807,7 +807,7 @@
 	}
 }
 
-int menu()
+int menu(void)
 {
 	printf("\nSelect a command:\n");
 	printf("1)  display unconditional AVTAB\n");
diff --git a/test/dispol.c b/test/dispol.c
index f41acdc..9d66358 100644
--- a/test/dispol.c
+++ b/test/dispol.c
@@ -37,7 +37,7 @@
 
 static policydb_t policydb;
 
-void usage(char *progname)
+void usage(const char *progname)
 {
 	printf("usage:  %s binary_pol_file\n\n", progname);
 	exit(1);
@@ -320,9 +320,9 @@
 }
 
 static void display_id(policydb_t *p, FILE *fp, uint32_t symbol_type,
-		       uint32_t symbol_value, char *prefix)
+		       uint32_t symbol_value, const char *prefix)
 {
-	char *id = p->sym_val_to_name[symbol_type][symbol_value];
+	const char *id = p->sym_val_to_name[symbol_type][symbol_value];
 	fprintf(fp, " %s%s", prefix, id);
 }
 
@@ -369,7 +369,7 @@
 	}
 }
 
-int menu()
+int menu(void)
 {
 	printf("\nSelect a command:\n");
 	printf("1)  display unconditional AVTAB\n");