diff mbox series

[3/4] libsepol: Check that initial sid indexes are within the valid range

Message ID 20181011123549.14875-4-jwcart2@tycho.nsa.gov (mailing list archive)
State Not Applicable
Headers show
Series libsepol: Cleanup initial sid handling when writing CIL and policy.conf files | expand

Commit Message

James Carter Oct. 11, 2018, 12:35 p.m. UTC
When writing CIL from a policy module or when writing CIL or policy.conf
from a kernel binary policy, check that the initial sid index is within
the valid range of the selinux_sid_to_str[] array (or xen_sid_to_str[]
array for a XEN policy). If it is not, then create a unique name
("UNKNOWN"+index) for the initial sid.

Signed-off-by: James Carter <jwcart2@tycho.nsa.gov>
---
 libsepol/src/kernel_to_cil.c    | 42 +++++++++++++++++++++++++--------
 libsepol/src/kernel_to_common.h |  4 ++++
 libsepol/src/kernel_to_conf.c   | 42 +++++++++++++++++++++++++--------
 libsepol/src/module_to_cil.c    | 25 ++++++++++++++------
 4 files changed, 86 insertions(+), 27 deletions(-)
diff mbox series

Patch

diff --git a/libsepol/src/kernel_to_cil.c b/libsepol/src/kernel_to_cil.c
index c2a733ee..d173144e 100644
--- a/libsepol/src/kernel_to_cil.c
+++ b/libsepol/src/kernel_to_cil.c
@@ -529,23 +529,31 @@  exit:
 	return rc;
 }
 
-static int write_sids_to_cil(FILE *out, const char *const *sid_to_str, struct ocontext *isids)
+static int write_sids_to_cil(FILE *out, const char *const *sid_to_str,
+			     unsigned num_sids, struct ocontext *isids)
 {
 	struct ocontext *isid;
 	struct strs *strs;
 	char *sid;
 	char *prev;
+	char unknown[17];
 	unsigned i;
 	int rc;
 
-	rc = strs_init(&strs, SECINITSID_NUM+1);
+	rc = strs_init(&strs, num_sids+1);
 	if (rc != 0) {
 		goto exit;
 	}
 
 	for (isid = isids; isid != NULL; isid = isid->next) {
 		i = isid->sid[0];
-		rc = strs_add_at_index(strs, (char *)sid_to_str[i], i);
+		if (i < num_sids) {
+			sid = (char *)sid_to_str[i];
+		} else {
+			snprintf(unknown, 17, "%s%u", "UNKNOWN", i);
+			sid = strdup(unknown);
+		}
+		rc = strs_add_at_index(strs, sid, i);
 		if (rc != 0) {
 			goto exit;
 		}
@@ -577,6 +585,10 @@  static int write_sids_to_cil(FILE *out, const char *const *sid_to_str, struct oc
 	sepol_printf(out, "))\n");
 
 exit:
+	for (i=num_sids; i<strs_num_items(strs); i++) {
+		sid = strs_read_at_index(strs, i);
+		free(sid);
+	}
 	strs_destroy(&strs);
 	if (rc != 0) {
 		sepol_log_err("Error writing sid rules to CIL\n");
@@ -590,9 +602,11 @@  static int write_sid_decl_rules_to_cil(FILE *out, struct policydb *pdb)
 	int rc = 0;
 
 	if (pdb->target_platform == SEPOL_TARGET_SELINUX) {
-		rc = write_sids_to_cil(out, selinux_sid_to_str, pdb->ocontexts[0]);
+		rc = write_sids_to_cil(out, selinux_sid_to_str, SELINUX_SID_SZ,
+				       pdb->ocontexts[0]);
 	} else if (pdb->target_platform == SEPOL_TARGET_XEN) {
-		rc = write_sids_to_cil(out, xen_sid_to_str, pdb->ocontexts[0]);
+		rc = write_sids_to_cil(out, xen_sid_to_str, XEN_SID_SZ,
+				       pdb->ocontexts[0]);
 	} else {
 		sepol_log_err("Unknown target platform: %i", pdb->target_platform);
 		rc = -1;
@@ -2479,11 +2493,12 @@  exit:
 	return ctx;
 }
 
-static int write_sid_context_rules_to_cil(FILE *out, struct policydb *pdb, const char *const *sid_to_str)
+static int write_sid_context_rules_to_cil(FILE *out, struct policydb *pdb, const char *const *sid_to_str, unsigned num_sids)
 {
 	struct ocontext *isid;
 	struct strs *strs;
-	const char *sid;
+	char *sid;
+	char unknown[17];
 	char *ctx, *rule;
 	unsigned i;
 	int rc = -1;
@@ -2495,7 +2510,13 @@  static int write_sid_context_rules_to_cil(FILE *out, struct policydb *pdb, const
 
 	for (isid = pdb->ocontexts[0]; isid != NULL; isid = isid->next) {
 		i = isid->sid[0];
-		sid = sid_to_str[i];
+		if (i < num_sids) {
+			sid = (char *)sid_to_str[i];
+		} else {
+			snprintf(unknown, 17, "%s%u", "UNKNOWN", i);
+			sid = unknown;
+		}
+
 		ctx = context_to_str(pdb, &isid->context[0]);
 		if (!ctx) {
 			rc = -1;
@@ -2531,7 +2552,8 @@  exit:
 
 static int write_selinux_isid_rules_to_cil(FILE *out, struct policydb *pdb)
 {
-	return write_sid_context_rules_to_cil(out, pdb, selinux_sid_to_str);
+	return write_sid_context_rules_to_cil(out, pdb, selinux_sid_to_str,
+					      SELINUX_SID_SZ);
 }
 
 static int write_selinux_fsuse_rules_to_cil(FILE *out, struct policydb *pdb)
@@ -2884,7 +2906,7 @@  exit:
 
 static int write_xen_isid_rules_to_cil(FILE *out, struct policydb *pdb)
 {
-	return write_sid_context_rules_to_cil(out, pdb, xen_sid_to_str);
+	return write_sid_context_rules_to_cil(out, pdb, xen_sid_to_str, XEN_SID_SZ);
 }
 
 static int write_xen_pirq_rules_to_cil(FILE *out, struct policydb *pdb)
diff --git a/libsepol/src/kernel_to_common.h b/libsepol/src/kernel_to_common.h
index 7c5edbd6..dacfe97e 100644
--- a/libsepol/src/kernel_to_common.h
+++ b/libsepol/src/kernel_to_common.h
@@ -43,6 +43,8 @@  static const char * const selinux_sid_to_str[] = {
 	"devnull",
 };
 
+#define SELINUX_SID_SZ (sizeof(selinux_sid_to_str)/sizeof(selinux_sid_to_str[0]))
+
 static const char * const xen_sid_to_str[] = {
 	"null",
 	"xen",
@@ -57,6 +59,8 @@  static const char * const xen_sid_to_str[] = {
 	"device",
 };
 
+#define XEN_SID_SZ (sizeof(xen_sid_to_str)/sizeof(xen_sid_to_str[0]))
+
 static const uint32_t avtab_flavors[] = {
 	AVTAB_ALLOWED,
 	AVTAB_AUDITALLOW,
diff --git a/libsepol/src/kernel_to_conf.c b/libsepol/src/kernel_to_conf.c
index a98b5ca9..7e04a13b 100644
--- a/libsepol/src/kernel_to_conf.c
+++ b/libsepol/src/kernel_to_conf.c
@@ -428,22 +428,30 @@  static int write_class_decl_rules_to_conf(FILE *out, struct policydb *pdb)
 	return 0;
 }
 
-static int write_sids_to_conf(FILE *out, const char *const *sid_to_str, struct ocontext *isids)
+static int write_sids_to_conf(FILE *out, const char *const *sid_to_str,
+			      unsigned num_sids, struct ocontext *isids)
 {
 	struct ocontext *isid;
 	struct strs *strs;
 	char *sid;
+	char unknown[17];
 	unsigned i;
 	int rc;
 
-	rc = strs_init(&strs, SECINITSID_NUM+1);
+	rc = strs_init(&strs, num_sids+1);
 	if (rc != 0) {
 		goto exit;
 	}
 
 	for (isid = isids; isid != NULL; isid = isid->next) {
 		i = isid->sid[0];
-		rc = strs_add_at_index(strs, (char *)sid_to_str[i], i);
+		if (i < num_sids) {
+			sid = (char *)sid_to_str[i];
+		} else {
+			snprintf(unknown, 17, "%s%u", "UNKNOWN", i);
+			sid = strdup(unknown);
+		}
+		rc = strs_add_at_index(strs, sid, i);
 		if (rc != 0) {
 			goto exit;
 		}
@@ -458,6 +466,10 @@  static int write_sids_to_conf(FILE *out, const char *const *sid_to_str, struct o
 	}
 
 exit:
+	for (i=num_sids; i<strs_num_items(strs); i++) {
+		sid = strs_read_at_index(strs, i);
+		free(sid);
+	}
 	strs_destroy(&strs);
 	if (rc != 0) {
 		sepol_log_err("Error writing sid rules to policy.conf\n");
@@ -471,9 +483,11 @@  static int write_sid_decl_rules_to_conf(FILE *out, struct policydb *pdb)
 	int rc = 0;
 
 	if (pdb->target_platform == SEPOL_TARGET_SELINUX) {
-		rc = write_sids_to_conf(out, selinux_sid_to_str, pdb->ocontexts[0]);
+		rc = write_sids_to_conf(out, selinux_sid_to_str, SELINUX_SID_SZ,
+					pdb->ocontexts[0]);
 	} else if (pdb->target_platform == SEPOL_TARGET_XEN) {
-		rc = write_sids_to_conf(out, xen_sid_to_str, pdb->ocontexts[0]);
+		rc = write_sids_to_conf(out, xen_sid_to_str, XEN_SID_SZ,
+					pdb->ocontexts[0]);
 	} else {
 		sepol_log_err("Unknown target platform: %i", pdb->target_platform);
 		rc = -1;
@@ -2339,11 +2353,12 @@  static char *context_to_str(struct policydb *pdb, struct context_struct *con)
 	return ctx;
 }
 
-static int write_sid_context_rules_to_conf(FILE *out, struct policydb *pdb, const char *const *sid_to_str)
+static int write_sid_context_rules_to_conf(FILE *out, struct policydb *pdb, const char *const *sid_to_str, unsigned num_sids)
 {
 	struct ocontext *isid;
 	struct strs *strs;
-	const char *sid;
+	char *sid;
+	char unknown[17];
 	char *ctx, *rule;
 	unsigned i;
 	int rc;
@@ -2355,7 +2370,13 @@  static int write_sid_context_rules_to_conf(FILE *out, struct policydb *pdb, cons
 
 	for (isid = pdb->ocontexts[0]; isid != NULL; isid = isid->next) {
 		i = isid->sid[0];
-		sid = sid_to_str[i];
+		if (i < num_sids) {
+			sid = (char *)sid_to_str[i];
+		} else {
+			snprintf(unknown, 17, "%s%u", "UNKNOWN", i);
+			sid = unknown;
+		}
+
 		ctx = context_to_str(pdb, &isid->context[0]);
 		if (!ctx) {
 			rc = -1;
@@ -2391,7 +2412,8 @@  exit:
 
 static int write_selinux_isid_rules_to_conf(FILE *out, struct policydb *pdb)
 {
-	return write_sid_context_rules_to_conf(out, pdb, selinux_sid_to_str);
+	return write_sid_context_rules_to_conf(out, pdb, selinux_sid_to_str,
+					       SELINUX_SID_SZ);
 }
 
 static int write_selinux_fsuse_rules_to_conf(FILE *out, struct policydb *pdb)
@@ -2745,7 +2767,7 @@  exit:
 
 static int write_xen_isid_rules_to_conf(FILE *out, struct policydb *pdb)
 {
-	return write_sid_context_rules_to_conf(out, pdb, xen_sid_to_str);
+	return write_sid_context_rules_to_conf(out, pdb, xen_sid_to_str, XEN_SID_SZ);
 }
 
 
diff --git a/libsepol/src/module_to_cil.c b/libsepol/src/module_to_cil.c
index 8ab0dfce..7fc29cbd 100644
--- a/libsepol/src/module_to_cil.c
+++ b/libsepol/src/module_to_cil.c
@@ -2548,23 +2548,33 @@  static int context_to_cil(struct policydb *pdb, struct context_struct *con)
 }
 
 static int ocontext_isid_to_cil(struct policydb *pdb, const char *const *sid_to_string,
-				struct ocontext *isids)
+				unsigned num_sids, struct ocontext *isids)
 {
 	int rc = -1;
 
 	struct ocontext *isid;
 
 	struct sid_item {
-		const char *sid_key;
+		char *sid_key;
 		struct sid_item *next;
 	};
 
 	struct sid_item *head = NULL;
 	struct sid_item *item = NULL;
+	char *sid;
+	char unknown[17];
+	unsigned i;
 
 	for (isid = isids; isid != NULL; isid = isid->next) {
-		cil_println(0, "(sid %s)", sid_to_string[isid->sid[0]]);
-		cil_printf("(sidcontext %s ", sid_to_string[isid->sid[0]]);
+		i = isid->sid[0];
+		if (i < num_sids) {
+			sid = (char*)sid_to_string[i];
+		} else {
+			snprintf(unknown, 17, "%s%u", "UNKNOWN", i);
+			sid = unknown;
+		}
+		cil_println(0, "(sid %s)", sid);
+		cil_printf("(sidcontext %s ", sid);
 		context_to_cil(pdb, &isid->context[0]);
 		cil_printf(")\n");
 
@@ -2576,7 +2586,7 @@  static int ocontext_isid_to_cil(struct policydb *pdb, const char *const *sid_to_
 			rc = -1;
 			goto exit;
 		}
-		item->sid_key = sid_to_string[isid->sid[0]];
+		item->sid_key = strdup(sid);
 		item->next = head;
 		head = item;
 	}
@@ -2595,6 +2605,7 @@  exit:
 	while(head) {
 		item = head;
 		head = item->next;
+		free(item->sid_key);
 		free(item);
 	}
 	return rc;
@@ -2604,7 +2615,7 @@  static int ocontext_selinux_isid_to_cil(struct policydb *pdb, struct ocontext *i
 {
 	int rc = -1;
 
-	rc = ocontext_isid_to_cil(pdb, selinux_sid_to_str, isids);
+	rc = ocontext_isid_to_cil(pdb, selinux_sid_to_str, SELINUX_SID_SZ, isids);
 	if (rc != 0) {
 		goto exit;
 	}
@@ -2833,7 +2844,7 @@  static int ocontext_xen_isid_to_cil(struct policydb *pdb, struct ocontext *isids
 {
 	int rc = -1;
 
-	rc = ocontext_isid_to_cil(pdb, xen_sid_to_str, isids);
+	rc = ocontext_isid_to_cil(pdb, xen_sid_to_str, XEN_SID_SZ, isids);
 	if (rc != 0) {
 		goto exit;
 	}