[libsepol] Update to latest patches from eparis/Upstream

Daniel J Walsh dwalsh at fedoraproject.org
Fri Jan 25 14:22:01 UTC 2013


commit 6e6c78000da4d679ad2554737e46fabb53b8c2a8
Author: Dan Walsh <dwalsh at redhat.com>
Date:   Fri Jan 25 09:21:55 2013 -0500

    Update to latest patches from eparis/Upstream

 libsepol-rhat.patch |  697 ++++++++++++++++++++++++++++++---------------------
 libsepol.spec       |    5 +-
 2 files changed, 419 insertions(+), 283 deletions(-)
---
diff --git a/libsepol-rhat.patch b/libsepol-rhat.patch
index d9167f4..8fae03e 100644
--- a/libsepol-rhat.patch
+++ b/libsepol-rhat.patch
@@ -93,7 +93,7 @@ index 16c89f3..84cfaf8 100644
  		}
  	}
 diff --git a/libsepol/src/expand.c b/libsepol/src/expand.c
-index 2003eb6..34e764b 100644
+index 2003eb6..0ca8448 100644
 --- a/libsepol/src/expand.c
 +++ b/libsepol/src/expand.c
 @@ -49,6 +49,82 @@ typedef struct expand_state {
@@ -179,24 +179,25 @@ index 2003eb6..34e764b 100644
  static void expand_state_init(expand_state_t * state)
  {
  	memset(state, 0, sizeof(expand_state_t));
-@@ -306,6 +382,16 @@ static int constraint_node_clone(constraint_node_t ** dst,
+@@ -306,6 +382,17 @@ static int constraint_node_clone(constraint_node_t ** dst,
  			new_expr->op = expr->op;
  			if (new_expr->expr_type == CEXPR_NAMES) {
  				if (new_expr->attr & CEXPR_TYPE) {
-+                    /*
-+                     * Copy over constraint policy source types and/or
-+                     * attributes for sepol_compute_av_reason_buffer(3) so that
-+                     * utilities can analyse constraint errors.
-+                     */
++					/*
++					 * Copy over constraint policy source types and/or
++					 * attributes for sepol_compute_av_reason_buffer(3) so that
++					 * utilities can analyse constraint errors.
++					 */
 +					if (map_ebitmap(&expr->type_names->types,
-+                                &new_expr->type_names->types, state->typemap)) {
-+                        ERR(NULL, "Failed to map type_names->types");
++							&new_expr->type_names->types,
++							state->typemap)) {
++						ERR(NULL, "Failed to map type_names->types");
 +						goto out_of_mem;
-+                    }
++					}
  					/* Type sets require expansion and conversion. */
  					if (expand_convert_type_set(state->out,
  								    state->
-@@ -377,6 +463,13 @@ static int class_copy_default_new_object(expand_state_t *state,
+@@ -377,6 +464,13 @@ static int class_copy_default_new_object(expand_state_t *state,
  		}
  		newdatum->default_role = olddatum->default_role;
  	}
@@ -210,7 +211,7 @@ index 2003eb6..34e764b 100644
  	if (olddatum->default_range) {
  		if (newdatum->default_range && olddatum->default_range != newdatum->default_range) {
  			ERR(state->handle, "Found conflicting default range definitions");
-@@ -812,6 +905,7 @@ static int role_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
+@@ -812,6 +906,7 @@ static int role_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
  		new_id = strdup(id);
  		if (!new_id) {
  			ERR(state->handle, "Out of memory!");
@@ -218,7 +219,7 @@ index 2003eb6..34e764b 100644
  			return -1;
  		}
  
-@@ -877,9 +971,13 @@ int mls_semantic_level_expand(mls_semantic_level_t * sl, mls_level_t * l,
+@@ -877,9 +972,13 @@ int mls_semantic_level_expand(mls_semantic_level_t * sl, mls_level_t * l,
  
  	l->sens = sl->sens;
  	levdatum = (level_datum_t *) hashtab_search(p->p_levels.table,
@@ -235,7 +236,7 @@ index 2003eb6..34e764b 100644
  	for (cat = sl->cat; cat; cat = cat->next) {
  		if (cat->low > cat->high) {
  			ERR(h, "Category range is not valid %s.%s",
-@@ -963,6 +1061,7 @@ static int user_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
+@@ -963,6 +1062,7 @@ static int user_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
  		new_id = strdup(id);
  		if (!new_id) {
  			ERR(state->handle, "Out of memory!");
@@ -243,7 +244,7 @@ index 2003eb6..34e764b 100644
  			return -1;
  		}
  		ret = hashtab_insert(state->out->p_users.table,
-@@ -1357,10 +1456,20 @@ static int copy_role_trans(expand_state_t * state, role_trans_rule_t * rules)
+@@ -1357,10 +1457,20 @@ static int copy_role_trans(expand_state_t * state, role_trans_rule_t * rules)
  static int expand_filename_trans(expand_state_t *state, filename_trans_rule_t *rules)
  {
  	unsigned int i, j;
@@ -265,7 +266,7 @@ index 2003eb6..34e764b 100644
  
  	cur_rule = rules;
  	while (cur_rule) {
-@@ -1383,6 +1492,14 @@ static int expand_filename_trans(expand_state_t *state, filename_trans_rule_t *r
+@@ -1383,6 +1493,14 @@ static int expand_filename_trans(expand_state_t *state, filename_trans_rule_t *r
  
  		mapped_otype = state->typemap[cur_rule->otype - 1];
  
@@ -280,7 +281,7 @@ index 2003eb6..34e764b 100644
  		ebitmap_for_each_bit(&stypes, snode, i) {
  			if (!ebitmap_node_get_bit(snode, i))
  				continue;
-@@ -1390,16 +1507,14 @@ static int expand_filename_trans(expand_state_t *state, filename_trans_rule_t *r
+@@ -1390,16 +1508,14 @@ static int expand_filename_trans(expand_state_t *state, filename_trans_rule_t *r
  				if (!ebitmap_node_get_bit(tnode, j))
  					continue;
  
@@ -300,7 +301,7 @@ index 2003eb6..34e764b 100644
  						ERR(state->handle, "Conflicting filename trans rules %s %s %s : %s otype1:%s otype2:%s",
  						    cur_trans->name,
  						    state->out->p_type_val_to_name[i],
-@@ -1407,7 +1522,7 @@ static int expand_filename_trans(expand_state_t *state, filename_trans_rule_t *r
+@@ -1407,7 +1523,7 @@ static int expand_filename_trans(expand_state_t *state, filename_trans_rule_t *r
  						    state->out->p_class_val_to_name[cur_trans->tclass - 1],
  						    state->out->p_type_val_to_name[cur_trans->otype - 1],
  						    state->out->p_type_val_to_name[mapped_otype - 1]);
@@ -309,7 +310,7 @@ index 2003eb6..34e764b 100644
  						return -1;
  					}
  					cur_trans = cur_trans->next;
-@@ -1422,8 +1537,6 @@ static int expand_filename_trans(expand_state_t *state, filename_trans_rule_t *r
+@@ -1422,8 +1538,6 @@ static int expand_filename_trans(expand_state_t *state, filename_trans_rule_t *r
  					return -1;
  				}
  				memset(new_trans, 0, sizeof(*new_trans));
@@ -318,7 +319,7 @@ index 2003eb6..34e764b 100644
  
  				new_trans->name = strdup(cur_rule->name);
  				if (!new_trans->name) {
-@@ -1434,9 +1547,16 @@ static int expand_filename_trans(expand_state_t *state, filename_trans_rule_t *r
+@@ -1434,9 +1548,16 @@ static int expand_filename_trans(expand_state_t *state, filename_trans_rule_t *r
  				new_trans->ttype = j + 1;
  				new_trans->tclass = cur_rule->tclass;
  				new_trans->otype = mapped_otype;
@@ -335,7 +336,7 @@ index 2003eb6..34e764b 100644
  		ebitmap_destroy(&stypes);
  		ebitmap_destroy(&ttypes);
  
-@@ -1981,6 +2101,8 @@ static int cond_node_copy(expand_state_t * state, cond_node_t * cn)
+@@ -1981,6 +2102,8 @@ static int cond_node_copy(expand_state_t * state, cond_node_t * cn)
  	}
  
  	if (cond_node_map_bools(state, tmp)) {
@@ -344,7 +345,7 @@ index 2003eb6..34e764b 100644
  		ERR(state->handle, "Error mapping booleans");
  		return -1;
  	}
-@@ -2037,14 +2159,13 @@ static int ocontext_copy_xen(expand_state_t *state)
+@@ -2037,14 +2160,13 @@ static int ocontext_copy_xen(expand_state_t *state)
  			else
  				state->out->ocontexts[i] = n;
  			l = n;
@@ -364,7 +365,7 @@ index 2003eb6..34e764b 100644
  				n->sid[0] = c->sid[0];
  				break;
  			case OCON_XEN_PIRQ:
-@@ -2067,11 +2188,6 @@ static int ocontext_copy_xen(expand_state_t *state)
+@@ -2067,11 +2189,6 @@ static int ocontext_copy_xen(expand_state_t *state)
  				ERR(state->handle, "Unknown ocontext");
  				return -1;
  			}
@@ -376,7 +377,7 @@ index 2003eb6..34e764b 100644
  		}
  	}
  	return 0;
-@@ -2096,14 +2212,12 @@ static int ocontext_copy_selinux(expand_state_t *state)
+@@ -2096,14 +2213,12 @@ static int ocontext_copy_selinux(expand_state_t *state)
  			else
  				state->out->ocontexts[i] = n;
  			l = n;
@@ -395,7 +396,7 @@ index 2003eb6..34e764b 100644
  				n->sid[0] = c->sid[0];
  				break;
  			case OCON_FS:	/* FALLTHROUGH */
-@@ -2147,10 +2261,6 @@ static int ocontext_copy_selinux(expand_state_t *state)
+@@ -2147,10 +2262,6 @@ static int ocontext_copy_selinux(expand_state_t *state)
  				ERR(state->handle, "Unknown ocontext");
  				return -1;
  			}
@@ -406,7 +407,7 @@ index 2003eb6..34e764b 100644
  		}
  	}
  	return 0;
-@@ -2188,9 +2298,15 @@ static int genfs_copy(expand_state_t * state)
+@@ -2188,9 +2299,15 @@ static int genfs_copy(expand_state_t * state)
  		memset(newgenfs, 0, sizeof(genfs_t));
  		newgenfs->fstype = strdup(genfs->fstype);
  		if (!newgenfs->fstype) {
@@ -422,7 +423,7 @@ index 2003eb6..34e764b 100644
  
  		l = NULL;
  		for (c = genfs->head; c; c = c->next) {
-@@ -2203,6 +2319,7 @@ static int genfs_copy(expand_state_t * state)
+@@ -2203,6 +2320,7 @@ static int genfs_copy(expand_state_t * state)
  			newc->u.name = strdup(c->u.name);
  			if (!newc->u.name) {
  				ERR(state->handle, "Out of memory!");
@@ -430,7 +431,7 @@ index 2003eb6..34e764b 100644
  				return -1;
  			}
  			newc->v.sclass = c->v.sclass;
-@@ -2213,12 +2330,6 @@ static int genfs_copy(expand_state_t * state)
+@@ -2213,12 +2331,6 @@ static int genfs_copy(expand_state_t * state)
  				newgenfs->head = newc;
  			l = newc;
  		}
@@ -443,7 +444,7 @@ index 2003eb6..34e764b 100644
  	}
  	return 0;
  }
-@@ -3009,7 +3120,8 @@ int expand_module(sepol_handle_t * handle,
+@@ -3009,7 +3121,8 @@ int expand_module(sepol_handle_t * handle,
  	}
  
  	cond_optimize_lists(state.out->cond_list);
@@ -747,7 +748,7 @@ index b5b807e..1665ede 100644
  		ERR(file->handle, "offset greater than file size (at %u, "
  		    "offset %zu -> %zu", nsec, off[nsec - 1],
 diff --git a/libsepol/src/policydb.c b/libsepol/src/policydb.c
-index ff292f6..ef0252a 100644
+index ff292f6..00cf6a8 100644
 --- a/libsepol/src/policydb.c
 +++ b/libsepol/src/policydb.c
 @@ -158,6 +158,20 @@ static struct policydb_compat_info policydb_compat[] = {
@@ -849,21 +850,18 @@ index ff292f6..ef0252a 100644
  		hashtab_destroy(symtab[i].table);
  	}
  }
-@@ -1995,8 +2037,11 @@ static int read_cons_helper(policydb_t * p, constraint_node_t ** nodep,
- 				depth++;
- 				if (ebitmap_read(&e->names, fp))
- 					return -1;
--				if (p->policy_type != POLICY_KERN &&
--				    type_set_read(e->type_names, fp))
-+				if ((p->policy_type != POLICY_KERN &&
-+						type_set_read(e->type_names, fp)) ||
-+						((p->policy_type == POLICY_KERN &&
-+						p->policyvers >= POLICYDB_VERSION_CONSTRAINT_NAMES) &&
-+						type_set_read(e->type_names, fp)))
+@@ -1998,6 +2040,10 @@ static int read_cons_helper(policydb_t * p, constraint_node_t ** nodep,
+ 				if (p->policy_type != POLICY_KERN &&
+ 				    type_set_read(e->type_names, fp))
  					return -1;
++				else if (p->policy_type == POLICY_KERN &&
++					 p->policyvers >= POLICYDB_VERSION_CONSTRAINT_NAMES &&
++					 type_set_read(e->type_names, fp))
++					return -1;
  				break;
  			default:
-@@ -2097,6 +2142,16 @@ static int class_read(policydb_t * p, hashtab_t h, struct policy_file *fp)
+ 				return -1;
+@@ -2097,6 +2143,16 @@ static int class_read(policydb_t * p, hashtab_t h, struct policy_file *fp)
  		cladatum->default_range = le32_to_cpu(buf[2]);
  	}
  
@@ -881,24 +879,22 @@ index ff292f6..ef0252a 100644
  		goto bad;
  
 diff --git a/libsepol/src/services.c b/libsepol/src/services.c
-index 9c2920c..9b42d8d 100644
+index 9c2920c..e235ae4 100644
 --- a/libsepol/src/services.c
 +++ b/libsepol/src/services.c
-@@ -43,6 +43,13 @@
+@@ -43,6 +43,11 @@
   * Implementation of the security services.
   */
  
-+/* The maximum size of the malloc'd sepol_compute_av_reason_buffer() */
-+#define REASON_BUF_SIZE 30000
-+/* The maximum size of each malloc'd expression buffer */
-+#define EXPR_BUF_SIZE 1000
-+/* Number expressions in a constraint - max seen in MLS policy is 21 */
-+#define EXPR_BUFFERS 30
++/* The initial sizes malloc'd for sepol_compute_av_reason_buffer() support */
++#define REASON_BUF_SIZE 2048
++#define EXPR_BUF_SIZE 1024
++#define STACK_LEN 32
 +
  #include <stdlib.h>
  #include <sys/types.h>
  #include <sys/socket.h>
-@@ -54,6 +61,7 @@
+@@ -54,6 +59,7 @@
  #include <sepol/policydb/services.h>
  #include <sepol/policydb/conditional.h>
  #include <sepol/policydb/flask.h>
@@ -906,88 +902,97 @@ index 9c2920c..9b42d8d 100644
  
  #include "debug.h"
  #include "private.h"
-@@ -70,6 +78,31 @@ static int selinux_enforcing = 1;
+@@ -70,6 +76,50 @@ static int selinux_enforcing = 1;
  static sidtab_t mysidtab, *sidtab = &mysidtab;
  static policydb_t mypolicydb, *policydb = &mypolicydb;
  
-+/* Stack services for RPN to infix conversion. Size is num of expr bufs */
-+char *stack[EXPR_BUFFERS];
-+int tos = 0;
-+ 
-+void push(char * expr_ptr)
++/* Used by sepol_compute_av_reason_buffer() to keep track of entries */
++static int reason_buf_used;
++static int reason_buf_len;
++
++/* Stack services for RPN to infix conversion. */
++static char **stack;
++static int stack_len;
++static int next_stack_entry;
++
++static void push(char * expr_ptr)
 +{
-+	if (tos >= EXPR_BUFFERS) {
-+		ERR(NULL, "Stack is full");
-+		return;
++	if (next_stack_entry >= stack_len) {
++		char **new_stack = stack;
++		int new_stack_len;
++
++		if (stack_len == 0)
++			new_stack_len = STACK_LEN;
++		else
++			new_stack_len = stack_len * 2;
++
++		new_stack = realloc(stack, new_stack_len * sizeof(*stack));
++		if (!new_stack) {
++			ERR(NULL, "unable to allocate stack space");
++			return;
++		}
++		stack_len = new_stack_len;
++		stack = new_stack;
 +	}
-+	stack[tos] = expr_ptr;
-+	tos++;
++	stack[next_stack_entry] = expr_ptr;
++	next_stack_entry++;
 +}
-+ 
-+char *pop()
++
++static char *pop(void)
 +{
-+	tos--;
-+	if (tos < 0) {
-+		ERR(NULL, "Stack is Empty");
++	next_stack_entry--;
++	if (next_stack_entry < 0) {
++		next_stack_entry = 0;
++		ERR(NULL, "pop called with no stack entries");
 +		return NULL;
 +	}
-+	return (char *)stack[tos];
++	return stack[next_stack_entry];
 +}
 +/* End Stack services */
 +
  int hidden sepol_set_sidtab(sidtab_t * s)
  {
  	sidtab = s;
-@@ -112,20 +145,118 @@ int sepol_set_policydb_from_file(FILE * fp)
+@@ -112,20 +162,195 @@ int sepol_set_policydb_from_file(FILE * fp)
  static uint32_t latest_granting = 0;
  
  /*
 - * Return the boolean value of a constraint expression 
 - * when it is applied to the specified source and target 
-+ * This function will process policy version >=
-+ * POLICYDB_VERSION_CONSTRAINT_NAMES as they contain a list
-+ * of types and/or attributes defined in the policy source.
++ * cat_expr_buf adds a string to an expression buffer and handles realloc's if
++ * buffer is too small. The array of expression text buffer pointers and its
++ * counter are globally defined here as constraint_expr_eval_reason() sets
++ * them up and cat_expr_buf updates the e_buf pointer if the buffer is realloc'ed.
 + */
-+int get_type_set_list(constraint_expr_t * e, char * e_buf)
-+{
-+	ebitmap_t *types;
-+	types = &e->type_names->types;
++static int expr_counter;
++static char **expr_list;
++static int expr_buf_used;
++static int expr_buf_len;
 +
-+	int rc = 0;
-+	unsigned int i;
-+	char tmp_buf[100];
-+	/* if ->names is 0, then output string <empty_set> */
-+	int empty_set = 0;
-+
-+	char *list_buf;
-+	list_buf = malloc(EXPR_BUF_SIZE);
-+	if (!list_buf) {
-+		ERR(NULL, "malloc failed to allocate list buffer");
-+		return -ENOMEM;
-+	}
-+	memset(list_buf, '\0', EXPR_BUF_SIZE);
-+
-+	/*
-+	 * Process list of names that have been defined in the policy source.
-+	 */
-+	for (i = ebitmap_startbit(types); i < ebitmap_length(types); i++) {
-+		if ((rc = ebitmap_get_bit(types, i)) == 0)
-+			continue;
-+		/* Collect entries */
-+		snprintf(tmp_buf, sizeof(tmp_buf), "%s ", policydb->p_type_val_to_name[i]);
-+		strncat(list_buf, tmp_buf, EXPR_BUF_SIZE);
-+		empty_set++;
-+	}
-+
-+	strncat(e_buf, "{ POLICY_SOURCE: ", EXPR_BUF_SIZE);
-+	if (empty_set == 0)
-+		strncat(e_buf, "<empty_set> ", EXPR_BUF_SIZE);
-+	else {
-+		strncat(e_buf, list_buf, EXPR_BUF_SIZE);
++static void cat_expr_buf(char *e_buf, char *string)
++{
++	int len, new_buf_len;
++	char *p, *new_buf = e_buf;
++
++	while (1) {
++		p = e_buf + expr_buf_used;
++		len = snprintf(p, expr_buf_len - expr_buf_used, "%s", string);
++		if (len < 0 || len >= expr_buf_len - expr_buf_used) {
++			new_buf_len = expr_buf_len + EXPR_BUF_SIZE;
++			new_buf = realloc(e_buf, new_buf_len);
++			if (!new_buf) {
++				ERR(NULL, "failed to realloc expr buffer");
++				return;
++			}
++			/* Update the new ptr in the expr list and locally + new len */
++			expr_list[expr_counter] = new_buf;
++			e_buf = new_buf;
++			expr_buf_len = new_buf_len;
++		} else {
++			expr_buf_used += len;
++			return;
++		}
 +	}
-+	strncat(e_buf, "} ", EXPR_BUF_SIZE);
-+	free(list_buf);
-+	return 0;
 +}
 +
 +/*
@@ -999,33 +1004,120 @@ index 9c2920c..9b42d8d 100644
 + * contain a list of types and attributes that were defined in the
 + * policy source.
 + */
-+int get_names_list(constraint_expr_t * e, int type, char * e_buf)
++static void get_names_list(constraint_expr_t *e, int type)
 +{
-+	/* If no buffer set then just return. */
-+	if (!e_buf)
-+		return 0;
++	ebitmap_t *types;
++	types = &e->type_names->types;
++	int rc = 0;
++	unsigned int i;
++	char tmp_buf[128];
++	/* if -type_names->types is 0, then output string <empty_set> */
++	int empty_set = 0;
 +
 +	if (policydb->policy_type == POLICY_KERN &&
 +			policydb->policyvers >= POLICYDB_VERSION_CONSTRAINT_NAMES &&
 +			type == CEXPR_TYPE) {
-+		/* Process >= POLICYDB_VERSION_CONSTRAINT_NAMES with CEXPR_TYPE */
-+		get_type_set_list(e, e_buf);
-+		return 0;
++		/*
++		 * Process >= POLICYDB_VERSION_CONSTRAINT_NAMES with CEXPR_TYPE, then
++		 * obtain the list of names defined in the policy source.
++		 */
++		cat_expr_buf(expr_list[expr_counter], "{ POLICY_SOURCE: ");
++		for (i = ebitmap_startbit(types); i < ebitmap_length(types); i++) {
++			if ((rc = ebitmap_get_bit(types, i)) == 0)
++				continue;
++			/* Collect entries */
++			snprintf(tmp_buf, sizeof(tmp_buf), "%s ", policydb->p_type_val_to_name[i]);
++			cat_expr_buf(expr_list[expr_counter], tmp_buf);
++			empty_set++;
++		}
++		if (empty_set == 0)
++			cat_expr_buf(expr_list[expr_counter], "<empty_set> ");
++		cat_expr_buf(expr_list[expr_counter], "} ");
 +	}
-+	return 0;
++	return;
 +}
 +
-+static void msgcat(char *e_buf, char *src, char *tgt, char *rel, int failed) {
++static void msgcat(char *src, char *tgt, char *rel, int failed)
++{
 +	char tmp_buf[1024];
-+	if (e_buf) {
-+		if (failed)
-+			snprintf(tmp_buf, sizeof(tmp_buf), "(%s %s %s -Fail-) ",
-+					src, rel, tgt);
-+		else
-+			snprintf(tmp_buf, sizeof(tmp_buf), "(%s %s %s -Pass-) ",
-+					src, rel, tgt);
-+		strncat(e_buf, tmp_buf, EXPR_BUF_SIZE);
++	if (failed)
++		snprintf(tmp_buf, sizeof(tmp_buf), "(%s %s %s -Fail-) ",
++				src, rel, tgt);
++	else
++		snprintf(tmp_buf, sizeof(tmp_buf), "(%s %s %s -Pass-) ",
++				src, rel, tgt);
++	cat_expr_buf(expr_list[expr_counter], tmp_buf);
++}
++
++/* Returns a buffer with class, statement type and permissions */
++static char *get_class_info(sepol_security_class_t tclass,
++							constraint_node_t *constraint,
++							context_struct_t * xcontext)
++{
++	constraint_expr_t *e;
++	int mls, state_num;
++
++	/* Find if MLS statement or not */
++	mls = 0;
++	for (e = constraint->expr; e; e = e->next) {
++		if (e->attr >= CEXPR_L1L2) {
++			mls = 1;
++			break;
++		}
++	}
++
++	/* Determine statement type */
++	char *statements[] = {
++        "constrain ",			/* 0 */
++		"mlsconstrain ",		/* 1 */
++        "validatetrans ",		/* 2 */
++		"mlsvalidatetrans ",	/* 3 */
++        0 };
++
++	if (xcontext == NULL)
++		state_num = mls + 0;
++	else
++		state_num = mls + 2;
++
++	int class_buf_len = 0;
++	int new_class_buf_len;
++	int len, buf_used;
++	char *class_buf = NULL, *p;
++	char *new_class_buf = NULL;
++
++	while (1) {
++		new_class_buf_len = class_buf_len + EXPR_BUF_SIZE;
++		new_class_buf = realloc(class_buf, new_class_buf_len);
++			if (!new_class_buf)
++				return NULL;
++		class_buf_len = new_class_buf_len;
++		class_buf = new_class_buf;
++		buf_used = 0;
++		p = class_buf;
++
++		/* Add statement type */
++		len = snprintf(p, class_buf_len - buf_used, "%s", statements[state_num]);
++		if (len < 0 || len >= class_buf_len - buf_used)
++			continue;
++
++		/* Add class entry */
++		p += len;
++		buf_used += len;
++		len = snprintf(p, class_buf_len - buf_used, "%s ",
++				policydb->p_class_val_to_name[tclass - 1]);
++		if (len < 0 || len >= class_buf_len - buf_used)
++			continue;
++
++		/* Add permission entries */
++		p += len;
++		buf_used += len;
++		len = snprintf(p, class_buf_len - buf_used, "{%s } (",
++				sepol_av_to_string(policydb, tclass, constraint->permissions));
++		if (len < 0 || len >= class_buf_len - buf_used)
++			continue;
++		break;
 +	}
++	return class_buf;
 +}
 +
 +/*
@@ -1057,23 +1149,17 @@ index 9c2920c..9b42d8d 100644
 -				constraint_expr_t * cexpr)
 +				sepol_security_class_t tclass,
 +				constraint_node_t *constraint,
-+				char ** r_buf,
++				char **r_buf,
 +				unsigned int flags)
  {
  	uint32_t val1, val2;
  	context_struct_t *c;
-@@ -135,56 +266,138 @@ static int constraint_expr_eval(context_struct_t * scontext,
+@@ -135,56 +360,135 @@ static int constraint_expr_eval(context_struct_t * scontext,
  	int s[CEXPR_MAXDEPTH];
  	int sp = -1;
  
 -	for (e = cexpr; e; e = e->next) {
-+	char tmp_buf[EXPR_BUF_SIZE];
-+
-+	/* The array of expression text buffer pointers and counter */
-+	char *expr_buf[EXPR_BUFFERS] = {NULL};
-+	int expr_counter = 0;
-+	/* Hold class and perm list */
-+	char *class_buf;
++	char tmp_buf[128];
 +
 +/*
 + * Define the s_t_x_num values that make up r1, t2 etc. in text strings
@@ -1094,64 +1180,68 @@ index 9c2920c..9b42d8d 100644
 +
 +	int rc = 0, x;
 +
-+	/* Buffer to hold class & perm list */
-+	class_buf = malloc(EXPR_BUF_SIZE);
++	char *class_buf = NULL;
++
++	class_buf = get_class_info(tclass, constraint, xcontext);
 +	if (!class_buf) {
-+		ERR(NULL, "malloc failed to allocate class buffer");
++		ERR(NULL, "failed to allocate class buffer");
 +		return -ENOMEM;
 +	}
-+	memset(class_buf, '\0', EXPR_BUF_SIZE);
 +
-+	/* Get constraint statement type */
-+	strncpy(tmp_buf, "constrain ", sizeof(tmp_buf));
++	/* Original function but with buffer support */
++	int expr_list_len = 0;
++	expr_counter = 0;
++	expr_list = NULL;
 +	for (e = constraint->expr; e; e = e->next) {
-+		if (e->attr >= CEXPR_L1L2) {
-+			strncpy(tmp_buf, "mlsconstrain ", sizeof(tmp_buf));
-+			break;
-+		}
-+	}
-+	strncat(class_buf, tmp_buf, EXPR_BUF_SIZE);
++		/* Allocate a stack to hold expression buffer entries */
++		if (expr_counter >= expr_list_len) {
++			char **new_expr_list = expr_list;
++			int new_expr_list_len;
 +
-+	/* Get class entry */
-+	snprintf(tmp_buf, sizeof(tmp_buf), "%s ", policydb->p_class_val_to_name[tclass - 1]);
-+	strncat(class_buf, tmp_buf, EXPR_BUF_SIZE);
++			if (expr_list_len == 0)
++				new_expr_list_len = STACK_LEN;
++			else
++				new_expr_list_len = expr_list_len * 2;
 +
-+	/* Get permission entries from the constraint node. */
-+	snprintf(tmp_buf, sizeof(tmp_buf), "{%s } (", sepol_av_to_string(policydb, tclass,
-+			constraint->permissions));
-+	strncat(class_buf, tmp_buf, EXPR_BUF_SIZE);
++			new_expr_list = realloc(expr_list, new_expr_list_len * sizeof(*expr_list));
++			if (!new_expr_list) {
++				ERR(NULL, "failed to allocate expr buffer stack");
++				return -ENOMEM;
++			}
++			expr_list_len = new_expr_list_len;
++			expr_list = new_expr_list;
++		}
 +
-+	/* Original function but with buffer support */
-+	for (e = constraint->expr; e; e = e->next) {
-+		/* malloc a buffer to store each expression text component */
-+		expr_buf[expr_counter] = malloc(EXPR_BUF_SIZE);
-+		if (!expr_buf[expr_counter]) {
-+			ERR(NULL, "malloc failed to allocate expr buffer");
++		/*
++		 * malloc a buffer to store each expression text component. If the
++		 * buffer is too small cat_expr_buf() will realloc extra space.
++		 */
++		expr_buf_len = EXPR_BUF_SIZE;
++		expr_list[expr_counter] = malloc(expr_buf_len);
++		if (!expr_list[expr_counter]) {
++			ERR(NULL, "failed to allocate expr buffer");
 +			return -ENOMEM;
 +		}
-+		memset(expr_buf[expr_counter], '\0', EXPR_BUF_SIZE);
++		expr_buf_used = 0;
 +
 +		/* Now process each expression of the constraint */
  		switch (e->expr_type) {
  		case CEXPR_NOT:
  			BUG_ON(sp < 0);
  			s[sp] = !s[sp];
-+			if (*r_buf)
-+				strncat(expr_buf[expr_counter], "not", EXPR_BUF_SIZE);
++			cat_expr_buf(expr_list[expr_counter], "not");
  			break;
  		case CEXPR_AND:
  			BUG_ON(sp < 1);
  			sp--;
  			s[sp] &= s[sp + 1];
-+			if (*r_buf)
-+				strncat(expr_buf[expr_counter], "and", EXPR_BUF_SIZE);
++			cat_expr_buf(expr_list[expr_counter], "and");
  			break;
  		case CEXPR_OR:
  			BUG_ON(sp < 1);
  			sp--;
  			s[sp] |= s[sp + 1];
-+			if (*r_buf)
-+				strncat(expr_buf[expr_counter], "or", EXPR_BUF_SIZE);
++			cat_expr_buf(expr_list[expr_counter], "or");
  			break;
  		case CEXPR_ATTR:
  			if (sp == (CEXPR_MAXDEPTH - 1))
@@ -1176,30 +1266,29 @@ index 9c2920c..9b42d8d 100644
  				val2 = tcontext->role;
  				r1 = policydb->role_val_to_struct[val1 - 1];
  				r2 = policydb->role_val_to_struct[val2 - 1];
-+				if (*r_buf) {
-+					name1 = policydb->p_role_val_to_name[r1->s.value - 1];
-+					name2 = policydb->p_role_val_to_name[r2->s.value - 1];
-+					snprintf(tmp_buf,sizeof(tmp_buf), "r1=%s", name1);
-+					free(src); src = strdup(tmp_buf);
-+					snprintf(tmp_buf,sizeof(tmp_buf), "r2=%s ", name2);
-+					free(tgt); tgt = strdup(tmp_buf);
-+				}
++				name1 = policydb->p_role_val_to_name[r1->s.value - 1];
++				name2 = policydb->p_role_val_to_name[r2->s.value - 1];
++				snprintf(tmp_buf, sizeof(tmp_buf), "r1=%s", name1);
++				free(src); src = strdup(tmp_buf);
++				snprintf(tmp_buf, sizeof(tmp_buf), "r2=%s ", name2);
++				free(tgt); tgt = strdup(tmp_buf);
++
  				switch (e->op) {
  				case CEXPR_DOM:
 -					s[++sp] =
 -					    ebitmap_get_bit(&r1->dominates,
 -							    val2 - 1);
 +					s[++sp] = ebitmap_get_bit(&r1->dominates, val2 - 1);
-+					msgcat(expr_buf[expr_counter++], src, tgt, "dom",
-+							s[sp] == 0);
++					msgcat(src, tgt, "dom", s[sp] == 0);
++					expr_counter++;
  					continue;
  				case CEXPR_DOMBY:
 -					s[++sp] =
 -					    ebitmap_get_bit(&r2->dominates,
 -							    val1 - 1);
 +					s[++sp] = ebitmap_get_bit(&r2->dominates, val1 - 1);
-+					msgcat(expr_buf[expr_counter++], src, tgt,
-+							"domby", s[sp] == 0);
++					msgcat(src, tgt, "domby", s[sp] == 0);
++					expr_counter++;
  					continue;
  				case CEXPR_INCOMP:
 -					s[++sp] =
@@ -1209,12 +1298,12 @@ index 9c2920c..9b42d8d 100644
 -								 val1 - 1));
 +					s[++sp] = (!ebitmap_get_bit(&r1->dominates, val2 - 1)
 +						 && !ebitmap_get_bit(&r2->dominates, val1 - 1));
-+					msgcat(expr_buf[expr_counter++], src, tgt,
-+						"incomp", s[sp] == 0);
++					msgcat(src, tgt, "incomp", s[sp] == 0);
++					expr_counter++;
  					continue;
  				default:
  					break;
-@@ -193,110 +406,286 @@ static int constraint_expr_eval(context_struct_t * scontext,
+@@ -193,110 +497,325 @@ static int constraint_expr_eval(context_struct_t * scontext,
  			case CEXPR_L1L2:
  				l1 = &(scontext->range.level[0]);
  				l2 = &(tcontext->range.level[0]);
@@ -1256,28 +1345,28 @@ index 9c2920c..9b42d8d 100644
  				switch (e->op) {
  				case CEXPR_EQ:
  					s[++sp] = mls_level_eq(l1, l2);
-+					msgcat(expr_buf[expr_counter++], src, tgt,
-+							"eq", s[sp] == 0);
++					msgcat(src, tgt, "eq", s[sp] == 0);
++					expr_counter++;
  					continue;
  				case CEXPR_NEQ:
  					s[++sp] = !mls_level_eq(l1, l2);
-+					msgcat(expr_buf[expr_counter++], src, tgt, "neq",
-+							s[sp] == 0);
++					msgcat(src, tgt, "neq", s[sp] == 0);
++					expr_counter++;
  					continue;
  				case CEXPR_DOM:
  					s[++sp] = mls_level_dom(l1, l2);
-+					msgcat(expr_buf[expr_counter++], src, tgt, "dom",
-+							s[sp] == 0);
++					msgcat(src, tgt, "dom", s[sp] == 0);
++					expr_counter++;
  					continue;
  				case CEXPR_DOMBY:
  					s[++sp] = mls_level_dom(l2, l1);
-+					msgcat(expr_buf[expr_counter++], src, tgt,
-+							"domby", s[sp] == 0);
++					msgcat(src, tgt, "domby", s[sp] == 0);
++					expr_counter++;
  					continue;
  				case CEXPR_INCOMP:
  					s[++sp] = mls_level_incomp(l2, l1);
-+					msgcat(expr_buf[expr_counter++], src, tgt,
-+							"incomp", s[sp] == 0);
++					msgcat(src, tgt, "incomp", s[sp] == 0);
++					expr_counter++;
  					continue;
  				default:
  					BUG();
@@ -1294,11 +1383,11 @@ index 9c2920c..9b42d8d 100644
  			switch (e->op) {
  			case CEXPR_EQ:
  				s[++sp] = (val1 == val2);
-+				msgcat(expr_buf[expr_counter], src, tgt, "eq", s[sp] == 0);
++				msgcat(src, tgt, "eq", s[sp] == 0);
  				break;
  			case CEXPR_NEQ:
  				s[++sp] = (val1 != val2);
-+				msgcat(expr_buf[expr_counter], src, tgt, "neq", s[sp] == 0);
++				msgcat(src, tgt, "neq", s[sp] == 0);
  				break;
  			default:
  				BUG();
@@ -1334,33 +1423,26 @@ index 9c2920c..9b42d8d 100644
 +				u_r_t = CEXPR_USER;
  				val1 = c->user;
 -			else if (e->attr & CEXPR_ROLE)
-+				if (*r_buf) {
-+					name1 = policydb->p_user_val_to_name[val1 - 1];
-+					snprintf(tmp_buf,sizeof(tmp_buf), "u%d=%s ",
-+							s_t_x_num, name1);
-+					free(src); src = strdup(tmp_buf);
-+				}
++				name1 = policydb->p_user_val_to_name[val1 - 1];
++				snprintf(tmp_buf, sizeof(tmp_buf), "u%d=%s ",
++						s_t_x_num, name1);
++				free(src); src = strdup(tmp_buf);
 +			}
 +			else if (e->attr & CEXPR_ROLE) {
 +				u_r_t = CEXPR_ROLE;
  				val1 = c->role;
 -			else if (e->attr & CEXPR_TYPE)
-+				if (*r_buf) {
-+					name1 = policydb->p_role_val_to_name[val1 - 1];
-+					snprintf(tmp_buf,sizeof(tmp_buf),
-+							"r%d=%s ", s_t_x_num, name1);
-+					free(src); src = strdup(tmp_buf);
-+				}
++				name1 = policydb->p_role_val_to_name[val1 - 1];
++				snprintf(tmp_buf, sizeof(tmp_buf), "r%d=%s ", s_t_x_num, name1);
++				free(src); src = strdup(tmp_buf);
 +			}
 +			else if (e->attr & CEXPR_TYPE) {
 +				u_r_t = CEXPR_TYPE;
  				val1 = c->type;
-+				if (*r_buf) {
-+					name1 = policydb->p_type_val_to_name[val1 - 1];
-+					snprintf(tmp_buf,sizeof(tmp_buf),
-+							"t%d=%s ", s_t_x_num, name1);
-+					free(src); src = strdup(tmp_buf);
-+				}
++				name1 = policydb->p_type_val_to_name[val1 - 1];
++				snprintf(tmp_buf, sizeof(tmp_buf),
++						"t%d=%s ", s_t_x_num, name1);
++				free(src); src = strdup(tmp_buf);
 +			}
  			else {
  				BUG();
@@ -1386,9 +1468,9 @@ index 9c2920c..9b42d8d 100644
 +				}
 +
  				s[++sp] = ebitmap_get_bit(&e->names, val1 - 1);
-+				msgcat(expr_buf[expr_counter], src, tgt, "eq", s[sp] == 0);
++				msgcat(src, tgt, "eq", s[sp] == 0);
 +				if (s[sp] == 0) {
-+					get_names_list(e, u_r_t, expr_buf[expr_counter]);
++					get_names_list(e, u_r_t);
 +				}
  				break;
 +
@@ -1409,9 +1491,9 @@ index 9c2920c..9b42d8d 100644
 +				}
 +
  				s[++sp] = !ebitmap_get_bit(&e->names, val1 - 1);
-+				msgcat(expr_buf[expr_counter], src, tgt, "neq", s[sp] == 0);
++				msgcat(src, tgt, "neq", s[sp] == 0);
 +				if (s[sp] == 0) {
-+					get_names_list(e, u_r_t, expr_buf[expr_counter]);
++					get_names_list(e, u_r_t);
 +				}
  				break;
  			default:
@@ -1424,33 +1506,45 @@ index 9c2920c..9b42d8d 100644
  			BUG();
 -			return 0;
 +			goto out;
- 		}
++		}
 +		expr_counter++;
- 	}
- 
++	}
++
 +	/*
 +	 * At this point each expression of the constraint is in
-+	 * expr_buf[n+1] and in RPN format. Now convert to 'infix'
++	 * expr_list[n+1] and in RPN format. Now convert to 'infix'
 +	 */
 +
 +	/*
-+	 * Zero expr_counter to detect if 'BUG(); goto out;' was called
-+	 * as we need to release any used expr_buf malloc's. Normally they
-+	 * are released by the RPN to infix code.
++	 * Save expr count but zero expr_counter to detect if 'BUG(); goto out;'
++	 * was called as we need to release any used expr_list malloc's. Normally
++	 * they are released by the RPN to infix code.
 +	 */
++	int expr_count = expr_counter;
 +	expr_counter = 0;
 +
-+	/* The array of expression answer buffer pointers and counter */
-+	char *answer_buf[EXPR_BUFFERS] = {NULL};
++	/*
++	 * The array of expression answer buffer pointers and counter. Generate
++	 * the same number of answer buffer entries as expression buffers (as
++	 * there will never be more required).
++	 */
++	char **answer_list;
 +	int answer_counter = 0;
-+	/* pop operands */
++
++	answer_list = malloc(expr_count * sizeof(*answer_list));
++	if (!answer_list) {
++		ERR(NULL, "failed to allocate answer stack");
++		return -ENOMEM;
++	}
++
++	/* The pop operands */
 +	char *a;
 +	char *b;
 +	int a_len, b_len;
 +
 +	/* Convert constraint from RPN to infix notation. */
-+	for (x = 0; expr_buf[x] != NULL; x++) {
-+		if (strncmp(expr_buf[x], "and", 3) == 0 || strncmp(expr_buf[x],
++	for (x = 0; x != expr_count; x++) {
++		if (strncmp(expr_list[x], "and", 3) == 0 || strncmp(expr_list[x],
 +					"or", 2) == 0) {
 +			b = pop();
 +			b_len = strlen(b);
@@ -1458,61 +1552,95 @@ index 9c2920c..9b42d8d 100644
 +			a_len = strlen(a);
 +
 +			/* get a buffer to hold the answer */
-+			answer_buf[answer_counter] = malloc(a_len + b_len + 8);
-+			if (!answer_buf[answer_counter]) {
-+				ERR(NULL, "malloc failed to allocate answer buffer");
++			answer_list[answer_counter] = malloc(a_len + b_len + 8);
++			if (!answer_list[answer_counter]) {
++				ERR(NULL, "failed to allocate answer buffer");
 +				return -ENOMEM;
 +			}
-+			memset(answer_buf[answer_counter], '\0', a_len + b_len + 8);
++			memset(answer_list[answer_counter], '\0', a_len + b_len + 8);
 +
-+			sprintf(answer_buf[answer_counter], "%s %s %s", a, expr_buf[x], b);
-+			push(answer_buf[answer_counter++]);
++			sprintf(answer_list[answer_counter], "%s %s %s", a, expr_list[x], b);
++			push(answer_list[answer_counter++]);
 +			free(a);
 +			free(b);
-+		} else if (strncmp(expr_buf[x], "not", 3) == 0) {
++		} else if (strncmp(expr_list[x], "not", 3) == 0) {
 +			b = pop();
 +			b_len = strlen(b);
 +
-+			answer_buf[answer_counter] = malloc(b_len + 8);
-+			if (!answer_buf[answer_counter]) {
-+				ERR(NULL, "malloc failed to allocate answer buffer");
++			answer_list[answer_counter] = malloc(b_len + 8);
++			if (!answer_list[answer_counter]) {
++				ERR(NULL, "failed to allocate answer buffer");
 +				return -ENOMEM;
 +			}
-+			memset(answer_buf[answer_counter], '\0', b_len + 8);
++			memset(answer_list[answer_counter], '\0', b_len + 8);
 +
 +			if (strncmp(b, "not", 3) == 0)
-+				sprintf(answer_buf[answer_counter], "%s (%s)", expr_buf[x], b);
++				sprintf(answer_list[answer_counter], "%s (%s)", expr_list[x], b);
 +			else
-+				sprintf(answer_buf[answer_counter], "%s%s", expr_buf[x], b);
-+			push(answer_buf[answer_counter++]);
++				sprintf(answer_list[answer_counter], "%s%s", expr_list[x], b);
++			push(answer_list[answer_counter++]);
 +			free(b);
 +		} else {
-+			push(expr_buf[x]);
-+		}
-+	}
++			push(expr_list[x]);
+ 		}
+ 	}
 +	/* Get the final answer from tos and build constraint text */
 +	a = pop();
+ 
++	/* Constraint calculation: rc = 0 is denied, rc = 1 is granted */
++	sprintf(tmp_buf,"Constraint %s\n", s[0] ? "GRANTED" : "DENIED");
++
++	int len, new_buf_len;
++	char *p, **new_buf = r_buf;
++	/*
++	 * These contain the constraint components that are added to the
++	 * callers reason buffer.
++	 */
++	char *buffers[] = { class_buf, a, "); ", tmp_buf, 0 };
 +
-+	if (*r_buf) {
-+		if ((s[0] == 0) || ((s[0] == 1 && (flags & SHOW_GRANTED) == SHOW_GRANTED))) {
-+			strncat(*r_buf, class_buf, REASON_BUF_SIZE);
-+			strncat(*r_buf, a, REASON_BUF_SIZE);
-+		    strncat(*r_buf, "); ", REASON_BUF_SIZE);
-+	        /* Constraint calculation: rc = 0 is denied, rc = 1 is granted */
-+	        sprintf(tmp_buf,"Constraint %s\n", s[0] ? "GRANTED" : "DENIED");
-+            strncat(*r_buf, tmp_buf, REASON_BUF_SIZE);
-+    	}
++	/*
++	 * This will add the constraints to the callers reason buffer (who is
++	 * responsible for freeing the memory). It will handle any realloc's
++	 * should the buffer be too short.
++	 * The reason_buf_used and reason_buf_len counters are defined globally
++	 * as multiple constraints can be in the buffer.
++	 */
++	if (r_buf && ((s[0] == 0) || ((s[0] == 1 &&
++				(flags & SHOW_GRANTED) == SHOW_GRANTED)))) {
++		for (x = 0; buffers[x] != NULL; x++) {
++			while (1) {
++				p = *r_buf + reason_buf_used;
++				len = snprintf(p, reason_buf_len - reason_buf_used, "%s", buffers[x]);
++				if (len < 0 || len >= reason_buf_len - reason_buf_used) {
++					new_buf_len = reason_buf_len + REASON_BUF_SIZE;
++					*new_buf = realloc(*r_buf, new_buf_len);
++					if (!new_buf) {
++						ERR(NULL, "failed to realloc reason buffer");
++						goto out1;
++					}
++					**r_buf = **new_buf;
++					reason_buf_len = new_buf_len;
++					continue;
++				} else {
++					reason_buf_used += len;
++					break;
++				}
++			}
++		}
 +	}
-+	free(a);
++
++out1:
 +	rc = s[0];
++	free(a);
 +
 +out:
 +	free(class_buf);
 +	free(src); 
 +	free(tgt);
++
 +	if (expr_counter) {
-+		for (x = 0; expr_buf[x] != NULL; x++)
-+			free(expr_buf[x]);
++		for (x = 0; expr_list[x] != NULL; x++)
++			free(expr_list[x]);
 +	}
  	BUG_ON(sp != 0);
 -	return s[0];
@@ -1520,29 +1648,29 @@ index 9c2920c..9b42d8d 100644
  }
  
  /*
-@@ -308,7 +697,9 @@ static int context_struct_compute_av(context_struct_t * scontext,
+@@ -308,7 +827,9 @@ static int context_struct_compute_av(context_struct_t * scontext,
  				     sepol_security_class_t tclass,
  				     sepol_access_vector_t requested,
  				     struct sepol_av_decision *avd,
 -				     unsigned int *reason)
 +				     unsigned int *reason,
-+				     char *r_buf,
++				     char **r_buf,
 +					 unsigned int flags)
  {
  	constraint_node_t *constraint;
  	struct role_allow *ra;
-@@ -383,8 +774,8 @@ static int context_struct_compute_av(context_struct_t * scontext,
+@@ -383,8 +904,8 @@ static int context_struct_compute_av(context_struct_t * scontext,
  	constraint = tclass_datum->constraints;
  	while (constraint) {
  		if ((constraint->permissions & (avd->allowed)) &&
 -		    !constraint_expr_eval(scontext, tcontext, NULL,
 -					  constraint->expr)) {
 +		    !constraint_expr_eval_reason(scontext, tcontext, NULL,
-+					  tclass, constraint, &r_buf, flags)) {
++					  tclass, constraint, r_buf, flags)) {
  			avd->allowed =
  			    (avd->allowed) & ~(constraint->permissions);
  		}
-@@ -459,8 +850,8 @@ int hidden sepol_validate_transition(sepol_security_id_t oldsid,
+@@ -459,8 +980,8 @@ int hidden sepol_validate_transition(sepol_security_id_t oldsid,
  
  	constraint = tclass_datum->validatetrans;
  	while (constraint) {
@@ -1553,7 +1681,7 @@ index 9c2920c..9b42d8d 100644
  			return -EPERM;
  		}
  		constraint = constraint->next;
-@@ -493,11 +884,58 @@ int hidden sepol_compute_av_reason(sepol_security_id_t ssid,
+@@ -493,11 +1014,59 @@ int hidden sepol_compute_av_reason(sepol_security_id_t ssid,
  	}
  
  	rc = context_struct_compute_av(scontext, tcontext, tclass,
@@ -1564,9 +1692,9 @@ index 9c2920c..9b42d8d 100644
  }
  
 +/* 
-+ * sepol_compute_av_reason_buffer - the reason buffer is malloc'd
-+ * to REASON_BUF_SIZE that seems okay for the Reference Policy.
-+ * TODO manage size using realloc at some stage.
++ * sepol_compute_av_reason_buffer - the reason buffer is malloc'd to
++ * REASON_BUF_SIZE. If the buffer size is exceeded, then it is realloc'd
++ * in the constraint_expr_eval_reason() function.
 + */
 +int hidden sepol_compute_av_reason_buffer(sepol_security_id_t ssid,
 +				   sepol_security_id_t tsid,
@@ -1577,14 +1705,17 @@ index 9c2920c..9b42d8d 100644
 +				   char **reason_buf,
 +				   unsigned int flags)
 +{
-+	char *r_buf = NULL;
-+
-+	r_buf = malloc(REASON_BUF_SIZE);
-+	if (!r_buf) {
-+		ERR(NULL, "malloc failed to allocate constraint reason buffer");
++	*reason_buf = malloc(REASON_BUF_SIZE);
++	if (!*reason_buf) {
++		ERR(NULL, "failed to allocate reason buffer");
 +		return -ENOMEM;
 +	}
-+	memset(r_buf, '\0', REASON_BUF_SIZE);
++	/*
++	 * These are defined globally as the buffer can contain multiple
++	 * constraint statements so need to keep track
++	 */
++	reason_buf_used = 0;
++	reason_buf_len = REASON_BUF_SIZE;
 +
 +	context_struct_t *scontext = 0, *tcontext = 0;
 +	int rc = 0;
@@ -1603,17 +1734,15 @@ index 9c2920c..9b42d8d 100644
 +	}
 +
 +	rc = context_struct_compute_av(scontext, tcontext, tclass,
-+					   requested, avd, reason, r_buf, flags);
-+	*reason_buf = r_buf;
-+
-+	  out:
++					   requested, avd, reason, reason_buf, flags);
++out:
 +	return rc;
 +}
 +
  int hidden sepol_compute_av(sepol_security_id_t ssid,
  			    sepol_security_id_t tsid,
  			    sepol_security_class_t tclass,
-@@ -510,6 +948,66 @@ int hidden sepol_compute_av(sepol_security_id_t ssid,
+@@ -510,6 +1079,70 @@ int hidden sepol_compute_av(sepol_security_id_t ssid,
  }
  
  /*
@@ -1655,7 +1784,7 @@ index 9c2920c..9b42d8d 100644
 +	}
 +	tclass_datum = policydb->class_val_to_struct[tclass - 1];
 +
-+	/* Check for unique perms then the common ones */
++	/* Check for unique perms then the common ones (if any) */
 +	perm_datum = (perm_datum_t *)
 +			hashtab_search(tclass_datum->permissions.table,
 +			(hashtab_key_t)perm_name);
@@ -1664,14 +1793,18 @@ index 9c2920c..9b42d8d 100644
 +		return STATUS_SUCCESS;
 +	}
 +
++	if (tclass_datum->comdatum == NULL)
++	   	goto out;
++
 +	perm_datum = (perm_datum_t *)
 +			hashtab_search(tclass_datum->comdatum->permissions.table,
 +			(hashtab_key_t)perm_name);
++
 +	if (perm_datum != NULL) {
 +		*av = 0x1 << (perm_datum->s.value - 1);
 +		return STATUS_SUCCESS;
-+	}	
-+
++	}
++out:	
 +	ERR(NULL, "could not convert %s to av bit", perm_name);
 +   	return STATUS_ERR;
 +}
@@ -1680,7 +1813,7 @@ index 9c2920c..9b42d8d 100644
   * Write the security context string representation of 
   * the context associated with `sid' into a dynamically
   * allocated string of the correct size.  Set `*scontext'
-@@ -1337,7 +1835,7 @@ int hidden sepol_get_user_sids(sepol_security_id_t fromsid,
+@@ -1337,7 +1970,7 @@ int hidden sepol_get_user_sids(sepol_security_id_t fromsid,
  			rc = context_struct_compute_av(fromcon, &usercon,
  						       SECCLASS_PROCESS,
  						       PROCESS__TRANSITION,
diff --git a/libsepol.spec b/libsepol.spec
index 4e83c0f..28e8b6e 100644
--- a/libsepol.spec
+++ b/libsepol.spec
@@ -1,7 +1,7 @@
 Summary: SELinux binary policy manipulation library 
 Name: libsepol
 Version: 2.1.8
-Release: 6%{?dist}
+Release: 7%{?dist}
 License: LGPLv2+
 Group: System Environment/Libraries
 Source: http://www.nsa.gov/selinux/archives/libsepol-%{version}.tgz
@@ -101,6 +101,9 @@ exit 0
 /%{_lib}/libsepol.so.1
 
 %changelog
+* Fri Jan 25 2013 Dan Walsh <dwalsh at redhat.com> - 2.1.8-7
+- Update to latest patches from eparis/Upstream
+
 * Tue Jan 8 2013 Dan Walsh <dwalsh at redhat.com> - 2.1.8-6
 - Fix libsepol.stack messages in audit2allow/audit2why
 


More information about the scm-commits mailing list