[libsepol/f18] Fix libsepol.stack messages in audit2allow/audit2why

Daniel J Walsh dwalsh at fedoraproject.org
Mon Jan 21 19:14:31 UTC 2013


commit 4bfa0bd3df1db3a85541466fd21dccc5ba30f120
Author: Dan Walsh <dwalsh at redhat.com>
Date:   Mon Jan 21 13:14:22 2013 -0600

    Fix libsepol.stack messages in audit2allow/audit2why

 libsepol-rhat.patch | 1594 +++++++++++++++++++++++++++++++++++++++++++++++++--
 libsepol.spec       |   28 +-
 2 files changed, 1579 insertions(+), 43 deletions(-)
---
diff --git a/libsepol-rhat.patch b/libsepol-rhat.patch
index 257b5d3..d9167f4 100644
--- a/libsepol-rhat.patch
+++ b/libsepol-rhat.patch
@@ -1,18 +1,99 @@
-diff --git a/libsepol/include/sepol/policydb/polcaps.h b/libsepol/include/sepol/policydb/polcaps.h
-index f90a48d..9152446 100644
---- a/libsepol/include/sepol/policydb/polcaps.h
-+++ b/libsepol/include/sepol/policydb/polcaps.h
-@@ -5,7 +5,7 @@
- enum {
- 	POLICYDB_CAPABILITY_NETPEER,
- 	POLICYDB_CAPABILITY_OPENPERM,
--	POLICYDB_CAPABILITY_REDHAT1, /* reserved for RH testing of ptrace_child */
-+	POLICYDB_CAPABILITY_PTRACE_CHILD,
- 	POLICYDB_CAPABILITY_ALWAYSNETWORK,
- 	__POLICYDB_CAPABILITY_MAX
- };
+diff --git a/libsepol/include/sepol/policydb/policydb.h b/libsepol/include/sepol/policydb/policydb.h
+index f53a499..0165eed 100644
+--- a/libsepol/include/sepol/policydb/policydb.h
++++ b/libsepol/include/sepol/policydb/policydb.h
+@@ -116,6 +116,7 @@ typedef struct class_datum {
+ #define DEFAULT_TARGET		2
+ 	char default_user;
+ 	char default_role;
++	char default_type;
+ /* Options how a new object range should be decided */
+ #define DEFAULT_SOURCE_LOW	1
+ #define DEFAULT_SOURCE_HIGH	2
+@@ -681,10 +682,12 @@ extern int policydb_set_target_platform(policydb_t *p, int platform);
+ #define POLICYDB_VERSION_FILENAME_TRANS	25
+ #define POLICYDB_VERSION_ROLETRANS	26
+ #define POLICYDB_VERSION_NEW_OBJECT_DEFAULTS	27
++#define POLICYDB_VERSION_DEFAULT_TYPE	28
++#define POLICYDB_VERSION_CONSTRAINT_NAMES	29
+ 
+ /* Range of policy versions we understand*/
+ #define POLICYDB_VERSION_MIN	POLICYDB_VERSION_BASE
+-#define POLICYDB_VERSION_MAX	POLICYDB_VERSION_NEW_OBJECT_DEFAULTS
++#define POLICYDB_VERSION_MAX	POLICYDB_VERSION_CONSTRAINT_NAMES
+ 
+ /* Module versions and specific changes*/
+ #define MOD_POLICYDB_VERSION_BASE		4
+@@ -701,9 +704,11 @@ extern int policydb_set_target_platform(policydb_t *p, int platform);
+ #define MOD_POLICYDB_VERSION_ROLEATTRIB		13
+ #define MOD_POLICYDB_VERSION_TUNABLE_SEP	14
+ #define MOD_POLICYDB_VERSION_NEW_OBJECT_DEFAULTS	15
++#define MOD_POLICYDB_VERSION_DEFAULT_TYPE	16
++#define MOD_POLICYDB_VERSION_CONSTRAINT_NAMES	17
+ 
+ #define MOD_POLICYDB_VERSION_MIN MOD_POLICYDB_VERSION_BASE
+-#define MOD_POLICYDB_VERSION_MAX MOD_POLICYDB_VERSION_NEW_OBJECT_DEFAULTS
++#define MOD_POLICYDB_VERSION_MAX MOD_POLICYDB_VERSION_CONSTRAINT_NAMES
+ 
+ #define POLICYDB_CONFIG_MLS    1
+ 
+diff --git a/libsepol/include/sepol/policydb/services.h b/libsepol/include/sepol/policydb/services.h
+index aef0c7b..1969a10 100644
+--- a/libsepol/include/sepol/policydb/services.h
++++ b/libsepol/include/sepol/policydb/services.h
+@@ -58,6 +58,38 @@ extern int sepol_compute_av_reason(sepol_security_id_t ssid,
+ 				   struct sepol_av_decision *avd,
+ 				   unsigned int *reason);
+ 
++/* 
++ * Same as above, but also returns the constraint expression calculations
++ * whether allowed or denied in a buffer. This buffer is allocated by
++ * this call and must be free'd by the caller using free(3). The contraint
++ * buffer will contain any constraints in infix notation.
++ * If the SHOW_GRANTED flag is set it will show granted and denied
++ * constraints. The default is to show only denied constraints.
++ */
++#define SHOW_GRANTED      1
++extern int sepol_compute_av_reason_buffer(sepol_security_id_t ssid,
++				   sepol_security_id_t tsid,
++				   sepol_security_class_t tclass,
++				   sepol_access_vector_t requested,
++				   struct sepol_av_decision *avd,
++				   unsigned int *reason,
++				   char **reason_buf,
++				   unsigned int flags);
++/*
++ * Return a class ID associated with the class string representation
++ * specified by `class_name'.
++ */
++extern int sepol_class_name_to_id(const char *class_name,
++					sepol_security_class_t  *tclass);
++
++/*
++ * Return a permission av bit associated with tclass and the string
++ * representation of the `perm_name'.
++ */
++extern int sepol_perm_name_to_av(sepol_security_class_t tclass,
++					const char *perm_name,
++					sepol_access_vector_t *av);
++
+ /*
+  * Compute a SID to use for labeling a new object in the 
+  * class `tclass' based on a SID pair.  
+diff --git a/libsepol/src/avrule_block.c b/libsepol/src/avrule_block.c
+index 16c89f3..84cfaf8 100644
+--- a/libsepol/src/avrule_block.c
++++ b/libsepol/src/avrule_block.c
+@@ -61,7 +61,6 @@ avrule_decl_t *avrule_decl_create(uint32_t decl_id)
+ 	for (i = 0; i < SYM_NUM; i++) {
+ 		if (symtab_init(&decl->symtab[i], symtab_sizes[i])) {
+ 			avrule_decl_destroy(decl);
+-			free(decl);
+ 			return NULL;
+ 		}
+ 	}
 diff --git a/libsepol/src/expand.c b/libsepol/src/expand.c
-index 2003eb6..a2d209c 100644
+index 2003eb6..34e764b 100644
 --- a/libsepol/src/expand.c
 +++ b/libsepol/src/expand.c
 @@ -49,6 +49,82 @@ typedef struct expand_state {
@@ -98,7 +179,71 @@ index 2003eb6..a2d209c 100644
  static void expand_state_init(expand_state_t * state)
  {
  	memset(state, 0, sizeof(expand_state_t));
-@@ -1357,10 +1433,20 @@ static int copy_role_trans(expand_state_t * state, role_trans_rule_t * rules)
+@@ -306,6 +382,16 @@ 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.
++                     */
++					if (map_ebitmap(&expr->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,
+ 		}
+ 		newdatum->default_role = olddatum->default_role;
+ 	}
++	if (olddatum->default_type) {
++		if (newdatum->default_type && olddatum->default_type != newdatum->default_type) {
++			ERR(state->handle, "Found conflicting default type definitions");
++			return SEPOL_ENOTSUP;
++		}
++		newdatum->default_type = olddatum->default_type;
++	}
+ 	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,
+ 		new_id = strdup(id);
+ 		if (!new_id) {
+ 			ERR(state->handle, "Out of memory!");
++			free(new_role);
+ 			return -1;
+ 		}
+ 
+@@ -877,9 +971,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,
+-						    p->p_sens_val_to_name[l->
+-									  sens -
+-									  1]);
++						    p->p_sens_val_to_name[l->sens - 1]);
++	if (!levdatum) {
++		ERR(h, "%s: Impossible situation found, nothing in p_levels.table.\n",
++		    __func__);
++		errno = ENOENT;
++		return -1;
++	}
+ 	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,
+ 		new_id = strdup(id);
+ 		if (!new_id) {
+ 			ERR(state->handle, "Out of memory!");
++			free(new_user);
+ 			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)
  static int expand_filename_trans(expand_state_t *state, filename_trans_rule_t *rules)
  {
  	unsigned int i, j;
@@ -120,7 +265,7 @@ index 2003eb6..a2d209c 100644
  
  	cur_rule = rules;
  	while (cur_rule) {
-@@ -1383,6 +1469,14 @@ static int expand_filename_trans(expand_state_t *state, filename_trans_rule_t *r
+@@ -1383,6 +1492,14 @@ static int expand_filename_trans(expand_state_t *state, filename_trans_rule_t *r
  
  		mapped_otype = state->typemap[cur_rule->otype - 1];
  
@@ -135,7 +280,7 @@ index 2003eb6..a2d209c 100644
  		ebitmap_for_each_bit(&stypes, snode, i) {
  			if (!ebitmap_node_get_bit(snode, i))
  				continue;
-@@ -1390,16 +1484,14 @@ static int expand_filename_trans(expand_state_t *state, filename_trans_rule_t *r
+@@ -1390,16 +1507,14 @@ static int expand_filename_trans(expand_state_t *state, filename_trans_rule_t *r
  				if (!ebitmap_node_get_bit(tnode, j))
  					continue;
  
@@ -155,7 +300,7 @@ index 2003eb6..a2d209c 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 +1499,7 @@ static int expand_filename_trans(expand_state_t *state, filename_trans_rule_t *r
+@@ -1407,7 +1522,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]);
@@ -164,7 +309,7 @@ index 2003eb6..a2d209c 100644
  						return -1;
  					}
  					cur_trans = cur_trans->next;
-@@ -1422,8 +1514,6 @@ static int expand_filename_trans(expand_state_t *state, filename_trans_rule_t *r
+@@ -1422,8 +1537,6 @@ static int expand_filename_trans(expand_state_t *state, filename_trans_rule_t *r
  					return -1;
  				}
  				memset(new_trans, 0, sizeof(*new_trans));
@@ -173,7 +318,7 @@ index 2003eb6..a2d209c 100644
  
  				new_trans->name = strdup(cur_rule->name);
  				if (!new_trans->name) {
-@@ -1434,9 +1524,16 @@ static int expand_filename_trans(expand_state_t *state, filename_trans_rule_t *r
+@@ -1434,9 +1547,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;
@@ -190,7 +335,16 @@ index 2003eb6..a2d209c 100644
  		ebitmap_destroy(&stypes);
  		ebitmap_destroy(&ttypes);
  
-@@ -2037,14 +2134,13 @@ static int ocontext_copy_xen(expand_state_t *state)
+@@ -1981,6 +2101,8 @@ static int cond_node_copy(expand_state_t * state, cond_node_t * cn)
+ 	}
+ 
+ 	if (cond_node_map_bools(state, tmp)) {
++		cond_node_destroy(tmp);
++		free(tmp);
+ 		ERR(state->handle, "Error mapping booleans");
+ 		return -1;
+ 	}
+@@ -2037,14 +2159,13 @@ static int ocontext_copy_xen(expand_state_t *state)
  			else
  				state->out->ocontexts[i] = n;
  			l = n;
@@ -210,7 +364,7 @@ index 2003eb6..a2d209c 100644
  				n->sid[0] = c->sid[0];
  				break;
  			case OCON_XEN_PIRQ:
-@@ -2067,11 +2163,6 @@ static int ocontext_copy_xen(expand_state_t *state)
+@@ -2067,11 +2188,6 @@ static int ocontext_copy_xen(expand_state_t *state)
  				ERR(state->handle, "Unknown ocontext");
  				return -1;
  			}
@@ -222,7 +376,7 @@ index 2003eb6..a2d209c 100644
  		}
  	}
  	return 0;
-@@ -2096,14 +2187,12 @@ static int ocontext_copy_selinux(expand_state_t *state)
+@@ -2096,14 +2212,12 @@ static int ocontext_copy_selinux(expand_state_t *state)
  			else
  				state->out->ocontexts[i] = n;
  			l = n;
@@ -241,7 +395,7 @@ index 2003eb6..a2d209c 100644
  				n->sid[0] = c->sid[0];
  				break;
  			case OCON_FS:	/* FALLTHROUGH */
-@@ -2147,10 +2236,6 @@ static int ocontext_copy_selinux(expand_state_t *state)
+@@ -2147,10 +2261,6 @@ static int ocontext_copy_selinux(expand_state_t *state)
  				ERR(state->handle, "Unknown ocontext");
  				return -1;
  			}
@@ -252,16 +406,1384 @@ index 2003eb6..a2d209c 100644
  		}
  	}
  	return 0;
-diff --git a/libsepol/src/polcaps.c b/libsepol/src/polcaps.c
-index 43a71a7..7615a9b 100644
---- a/libsepol/src/polcaps.c
-+++ b/libsepol/src/polcaps.c
-@@ -8,7 +8,7 @@
- static const char *polcap_names[] = {
- 	"network_peer_controls",	/* POLICYDB_CAPABILITY_NETPEER */
- 	"open_perms",			/* POLICYDB_CAPABILITY_OPENPERM */
--	"redhat1",			/* POLICYDB_CAPABILITY_REDHAT1, aka ptrace_child */
-+	"ptrace_child",			/* POLICYDB_CAPABILITY_PTRACE_CHILD */
- 	"always_check_network",		/* POLICYDB_CAPABILITY_ALWAYSNETWORK */
- 	NULL
+@@ -2188,9 +2298,15 @@ static int genfs_copy(expand_state_t * state)
+ 		memset(newgenfs, 0, sizeof(genfs_t));
+ 		newgenfs->fstype = strdup(genfs->fstype);
+ 		if (!newgenfs->fstype) {
++			free(newgenfs);
+ 			ERR(state->handle, "Out of memory!");
+ 			return -1;
+ 		}
++		if (!end)
++			state->out->genfs = newgenfs;
++		else
++			end->next = newgenfs;
++		end = newgenfs;
+ 
+ 		l = NULL;
+ 		for (c = genfs->head; c; c = c->next) {
+@@ -2203,6 +2319,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!");
++				free(newc);
+ 				return -1;
+ 			}
+ 			newc->v.sclass = c->v.sclass;
+@@ -2213,12 +2330,6 @@ static int genfs_copy(expand_state_t * state)
+ 				newgenfs->head = newc;
+ 			l = newc;
+ 		}
+-		if (!end) {
+-			state->out->genfs = newgenfs;
+-		} else {
+-			end->next = newgenfs;
+-		}
+-		end = newgenfs;
+ 	}
+ 	return 0;
+ }
+@@ -3009,7 +3120,8 @@ int expand_module(sepol_handle_t * handle,
+ 	}
+ 
+ 	cond_optimize_lists(state.out->cond_list);
+-	evaluate_conds(state.out);
++	if (evaluate_conds(state.out))
++		goto cleanup;
+ 
+ 	/* copy ocontexts */
+ 	if (ocontext_copy(&state, out->target_platform))
+diff --git a/libsepol/src/genbools.c b/libsepol/src/genbools.c
+index 612ff9a..6a06ec9 100644
+--- a/libsepol/src/genbools.c
++++ b/libsepol/src/genbools.c
+@@ -33,7 +33,7 @@ static char *strtrim(char *dest, char *source, int size)
+ static int process_boolean(char *buffer, char *name, int namesize, int *val)
+ {
+ 	char name1[BUFSIZ];
+-	char *ptr;
++	char *ptr = NULL;
+ 	char *tok = strtok_r(buffer, "=", &ptr);
+ 	if (tok) {
+ 		strncpy(name1, tok, BUFSIZ - 1);
+diff --git a/libsepol/src/genusers.c b/libsepol/src/genusers.c
+index 37528e2..7826b71 100644
+--- a/libsepol/src/genusers.c
++++ b/libsepol/src/genusers.c
+@@ -92,22 +92,32 @@ static int load_users(struct policydb *policydb, const char *path)
+ 		} else {
+ 			char *id = strdup(q);
+ 
++			if (!id) {
++				ERR(NULL, "out of memory");
++				free(buffer);
++				fclose(fp);
++				return -1;
++			}
++
+ 			/* Adding a new user definition. */
+-			usrdatum =
+-			    (user_datum_t *) malloc(sizeof(user_datum_t));
+-			if (!id || !usrdatum) {
++			usrdatum = malloc(sizeof(user_datum_t));
++			if (!usrdatum) {
+ 				ERR(NULL, "out of memory");
+ 				free(buffer);
++				free(id);
+ 				fclose(fp);
+ 				return -1;
+ 			}
+-			memset(usrdatum, 0, sizeof(user_datum_t));
++
++			user_datum_init(usrdatum);
+ 			usrdatum->s.value = ++policydb->p_users.nprim;
+-			ebitmap_init(&usrdatum->roles.roles);
+ 			if (hashtab_insert(policydb->p_users.table,
+ 					   id, (hashtab_datum_t) usrdatum)) {
+ 				ERR(NULL, "out of memory");
+ 				free(buffer);
++				free(id);
++				user_datum_destroy(usrdatum);
++				free(usrdatum);
+ 				fclose(fp);
+ 				return -1;
+ 			}
+diff --git a/libsepol/src/link.c b/libsepol/src/link.c
+index 01d3231..31b955c 100644
+--- a/libsepol/src/link.c
++++ b/libsepol/src/link.c
+@@ -223,6 +223,13 @@ static int class_copy_default_new_object(link_state_t *state,
+ 		}
+ 		newdatum->default_role = olddatum->default_role;
+ 	}
++	if (olddatum->default_type) {
++		if (newdatum->default_type && olddatum->default_type != newdatum->default_type) {
++			ERR(state->handle, "Found conflicting default type definitions");
++			return SEPOL_ENOTSUP;
++		}
++		newdatum->default_type = olddatum->default_type;
++	}
+ 	if (olddatum->default_range) {
+ 		if (newdatum->default_range && olddatum->default_range != newdatum->default_range) {
+ 			ERR(state->handle, "Found conflicting default range definitions");
+@@ -676,13 +683,17 @@ static int sens_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
+ 			    "%s: Modules may not declare new sensitivities.",
+ 			    state->cur_mod_name);
+ 			return SEPOL_ENOTSUP;
+-		}
+-		if (scope->scope == SCOPE_REQ) {
++		} else if (scope->scope == SCOPE_REQ) {
+ 			/* unmet requirement */
+ 			ERR(state->handle,
+ 			    "%s: Sensitivity %s not declared by base.",
+ 			    state->cur_mod_name, id);
+ 			return SEPOL_ENOTSUP;
++		} else {
++			ERR(state->handle,
++			    "%s: has an unknown scope: %d\n",
++			    state->cur_mod_name, scope->scope);
++			return SEPOL_ENOTSUP;
+ 		}
+ 	}
+ 
+@@ -704,8 +715,7 @@ static int cat_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
+ 
+ 	base_cat = hashtab_search(state->base->p_cats.table, id);
+ 	if (!base_cat) {
+-		scope =
+-		    hashtab_search(state->cur->policy->p_cat_scope.table, id);
++		scope = hashtab_search(state->cur->policy->p_cat_scope.table, id);
+ 		if (!scope)
+ 			return SEPOL_ERR;
+ 		if (scope->scope == SCOPE_DECL) {
+@@ -714,13 +724,18 @@ static int cat_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
+ 			    "%s: Modules may not declare new categories.",
+ 			    state->cur_mod_name);
+ 			return SEPOL_ENOTSUP;
+-		}
+-		if (scope->scope == SCOPE_REQ) {
++		} else if (scope->scope == SCOPE_REQ) {
+ 			/* unmet requirement */
+ 			ERR(state->handle,
+ 			    "%s: Category %s not declared by base.",
+ 			    state->cur_mod_name, id);
+ 			return SEPOL_ENOTSUP;
++		} else {
++			/* unknown scope?  malformed policy? */
++			ERR(state->handle,
++			    "%s: has an unknown scope: %d\n",
++			    state->cur_mod_name, scope->scope);
++			return SEPOL_ENOTSUP;
+ 		}
+ 	}
+ 
+@@ -2001,6 +2016,7 @@ static int is_decl_requires_met(link_state_t * state,
+ 			struct find_perm_arg fparg;
+ 			class_datum_t *cladatum;
+ 			uint32_t perm_value = j + 1;
++			int rc;
+ 			scope_datum_t *scope;
+ 
+ 			if (!ebitmap_node_get_bit(node, j)) {
+@@ -2022,11 +2038,13 @@ static int is_decl_requires_met(link_state_t * state,
+ 			fparg.valuep = perm_value;
+ 			fparg.key = NULL;
+ 
+-			hashtab_map(cladatum->permissions.table, find_perm,
++			(void)hashtab_map(cladatum->permissions.table, find_perm,
+ 				    &fparg);
+-			if (fparg.key == NULL && cladatum->comdatum != NULL)
+-				hashtab_map(cladatum->comdatum->permissions.
+-					    table, find_perm, &fparg);
++			if (fparg.key == NULL && cladatum->comdatum != NULL) {
++				rc = hashtab_map(cladatum->comdatum->permissions.table,
++						 find_perm, &fparg);
++				assert(rc == 1);
++			}
+ 			perm_id = fparg.key;
+ 
+ 			assert(perm_id != NULL);
+@@ -2050,6 +2068,7 @@ static int debug_requirements(link_state_t * state, policydb_t * p)
+ 	int ret;
+ 	avrule_block_t *cur;
+ 	missing_requirement_t req;
++	memset(&req, 0, sizeof(req));
+ 
+ 	for (cur = p->global; cur != NULL; cur = cur->next) {
+ 		if (cur->enabled != NULL)
+@@ -2062,34 +2081,27 @@ static int debug_requirements(link_state_t * state, policydb_t * p)
+ 			char *mod_name = cur->branch_list->module_name ?
+ 			    cur->branch_list->module_name : "BASE";
+ 			if (req.symbol_type == SYM_CLASSES) {
+-
+ 				struct find_perm_arg fparg;
+ 
+ 				class_datum_t *cladatum;
+-				cladatum =
+-				    p->class_val_to_struct[req.symbol_value -
+-							   1];
++				cladatum = p->class_val_to_struct[req.symbol_value - 1];
+ 
+ 				fparg.valuep = req.perm_value;
+ 				fparg.key = NULL;
+-				hashtab_map(cladatum->permissions.table,
+-					    find_perm, &fparg);
++				(void)hashtab_map(cladatum->permissions.table,
++						  find_perm, &fparg);
+ 
+ 				if (cur->flags & AVRULE_OPTIONAL) {
+ 					ERR(state->handle,
+ 					    "%s[%d]'s optional requirements were not met: class %s, permission %s",
+ 					    mod_name, cur->branch_list->decl_id,
+-					    p->p_class_val_to_name[req.
+-								   symbol_value
+-								   - 1],
++					    p->p_class_val_to_name[req.symbol_value - 1],
+ 					    fparg.key);
+ 				} else {
+ 					ERR(state->handle,
+ 					    "%s[%d]'s global requirements were not met: class %s, permission %s",
+ 					    mod_name, cur->branch_list->decl_id,
+-					    p->p_class_val_to_name[req.
+-								   symbol_value
+-								   - 1],
++					    p->p_class_val_to_name[req.symbol_value - 1],
+ 					    fparg.key);
+ 				}
+ 			} else {
+@@ -2137,7 +2149,7 @@ static void print_missing_requirements(link_state_t * state,
+ 
+ 		fparg.valuep = req->perm_value;
+ 		fparg.key = NULL;
+-		hashtab_map(cladatum->permissions.table, find_perm, &fparg);
++		(void)hashtab_map(cladatum->permissions.table, find_perm, &fparg);
+ 
+ 		ERR(state->handle,
+ 		    "%s's global requirements were not met: class %s, permission %s",
+@@ -2148,8 +2160,7 @@ static void print_missing_requirements(link_state_t * state,
+ 		    "%s's global requirements were not met: %s %s",
+ 		    mod_name,
+ 		    symtab_names[req->symbol_type],
+-		    p->sym_val_to_name[req->symbol_type][req->symbol_value -
+-							 1]);
++		    p->sym_val_to_name[req->symbol_type][req->symbol_value - 1]);
+ 	}
+ }
+ 
+diff --git a/libsepol/src/module.c b/libsepol/src/module.c
+index b5b807e..1665ede 100644
+--- a/libsepol/src/module.c
++++ b/libsepol/src/module.c
+@@ -59,21 +59,34 @@ static int policy_file_seek(struct policy_file *fp, size_t offset)
+ 	}
+ }
+ 
+-static size_t policy_file_length(struct policy_file *fp)
++static int policy_file_length(struct policy_file *fp, size_t *out)
+ {
+ 	long prev_offset, end_offset;
++	int rc;
+ 	switch (fp->type) {
+ 	case PF_USE_STDIO:
+ 		prev_offset = ftell(fp->fp);
+-		fseek(fp->fp, 0L, SEEK_END);
++		if (prev_offset < 0)
++			return prev_offset;
++		rc = fseek(fp->fp, 0L, SEEK_END);
++		if (rc < 0)
++			return rc;
+ 		end_offset = ftell(fp->fp);
+-		fseek(fp->fp, prev_offset, SEEK_SET);
+-		return end_offset;
++		if (end_offset < 0)
++			return end_offset;
++		rc = fseek(fp->fp, prev_offset, SEEK_SET);
++		if (rc < 0)
++			return rc;
++		*out = end_offset;
++		break;
+ 	case PF_USE_MEMORY:
+-		return fp->size;
++		*out = fp->size;
++		break;;
+ 	default:
+-		return 0;
++		*out = 0;
++		break;
+ 	}
++	return 0;
+ }
+ 
+ static int module_package_init(sepol_module_package_t * p)
+@@ -103,10 +116,17 @@ static int set_char(char **field, char *data, size_t len)
+ 
+ int sepol_module_package_create(sepol_module_package_t ** p)
+ {
++	int rc;
++
+ 	*p = calloc(1, sizeof(sepol_module_package_t));
+ 	if (!(*p))
+ 		return -1;
+-	return module_package_init(*p);
++
++	rc = module_package_init(*p);
++	if (rc < 0)
++		free(*p);
++
++	return rc;
+ }
+ 
+ hidden_def(sepol_module_package_create)
+@@ -413,7 +433,10 @@ static int module_package_read_offsets(sepol_module_package_t * mod,
+ 		}
+ 	}
+ 
+-	off[nsec] = policy_file_length(file);
++	rc = policy_file_length(file, &off[nsec]);
++	if (rc < 0)
++		goto err;
++
+ 	if (nsec && off[nsec] < off[nsec-1]) {
+ 		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
+--- a/libsepol/src/policydb.c
++++ b/libsepol/src/policydb.c
+@@ -158,6 +158,20 @@ static struct policydb_compat_info policydb_compat[] = {
+ 	 .target_platform = SEPOL_TARGET_SELINUX,
+ 	},
+ 	{
++	 .type = POLICY_KERN,
++	 .version = POLICYDB_VERSION_DEFAULT_TYPE,
++	 .sym_num = SYM_NUM,
++	 .ocon_num = OCON_NODE6 + 1,
++	 .target_platform = SEPOL_TARGET_SELINUX,
++	},
++	{
++	 .type = POLICY_KERN,
++	 .version = POLICYDB_VERSION_CONSTRAINT_NAMES,
++	 .sym_num = SYM_NUM,
++	 .ocon_num = OCON_NODE6 + 1,
++	 .target_platform = SEPOL_TARGET_SELINUX,
++	},
++	{
+ 	 .type = POLICY_BASE,
+ 	 .version = MOD_POLICYDB_VERSION_BASE,
+ 	 .sym_num = SYM_NUM,
+@@ -242,6 +256,20 @@ static struct policydb_compat_info policydb_compat[] = {
+ 	 .target_platform = SEPOL_TARGET_SELINUX,
+ 	},
+ 	{
++	 .type = POLICY_BASE,
++	 .version = MOD_POLICYDB_VERSION_DEFAULT_TYPE,
++	 .sym_num = SYM_NUM,
++	 .ocon_num = OCON_NODE6 + 1,
++	 .target_platform = SEPOL_TARGET_SELINUX,
++	},
++	{
++	 .type = POLICY_BASE,
++	 .version = MOD_POLICYDB_VERSION_CONSTRAINT_NAMES,
++	 .sym_num = SYM_NUM,
++	 .ocon_num = OCON_NODE6 + 1,
++	 .target_platform = SEPOL_TARGET_SELINUX,
++	},
++	{
+ 	 .type = POLICY_MOD,
+ 	 .version = MOD_POLICYDB_VERSION_BASE,
+ 	 .sym_num = SYM_NUM,
+@@ -325,6 +353,20 @@ static struct policydb_compat_info policydb_compat[] = {
+ 	 .ocon_num = 0,
+ 	 .target_platform = SEPOL_TARGET_SELINUX,
+ 	},
++	{
++	 .type = POLICY_MOD,
++	 .version = MOD_POLICYDB_VERSION_DEFAULT_TYPE,
++	 .sym_num = SYM_NUM,
++	 .ocon_num = 0,
++	 .target_platform = SEPOL_TARGET_SELINUX,
++	},
++	{
++	 .type = POLICY_MOD,
++	 .version = MOD_POLICYDB_VERSION_CONSTRAINT_NAMES,
++	 .sym_num = SYM_NUM,
++	 .ocon_num = 0,
++	 .target_platform = SEPOL_TARGET_SELINUX,
++	},
  };
+ 
+ #if 0
+@@ -1074,7 +1116,7 @@ static int common_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p
+ 	if (key)
+ 		free(key);
+ 	comdatum = (common_datum_t *) datum;
+-	hashtab_map(comdatum->permissions.table, perm_destroy, 0);
++	(void)hashtab_map(comdatum->permissions.table, perm_destroy, 0);
+ 	hashtab_destroy(comdatum->permissions.table);
+ 	free(datum);
+ 	return 0;
+@@ -1093,7 +1135,7 @@ static int class_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p
+ 	if (cladatum == NULL) {
+ 		return 0;
+ 	}
+-	hashtab_map(cladatum->permissions.table, perm_destroy, 0);
++	(void)hashtab_map(cladatum->permissions.table, perm_destroy, 0);
+ 	hashtab_destroy(cladatum->permissions.table);
+ 	constraint = cladatum->constraints;
+ 	while (constraint) {
+@@ -1261,7 +1303,7 @@ void policydb_destroy(policydb_t * p)
+ 	free(p->decl_val_to_struct);
+ 
+ 	for (i = 0; i < SYM_NUM; i++) {
+-		hashtab_map(p->scope[i].table, scope_destroy, 0);
++		(void)hashtab_map(p->scope[i].table, scope_destroy, 0);
+ 		hashtab_destroy(p->scope[i].table);
+ 	}
+ 	avrule_block_list_destroy(p->global);
+@@ -1351,7 +1393,7 @@ void symtabs_destroy(symtab_t * symtab)
+ {
+ 	int i;
+ 	for (i = 0; i < SYM_NUM; i++) {
+-		hashtab_map(symtab[i].table, destroy_f[i], 0);
++		(void)hashtab_map(symtab[i].table, destroy_f[i], 0);
+ 		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)))
+ 					return -1;
+ 				break;
+ 			default:
+@@ -2097,6 +2142,16 @@ static int class_read(policydb_t * p, hashtab_t h, struct policy_file *fp)
+ 		cladatum->default_range = le32_to_cpu(buf[2]);
+ 	}
+ 
++	if ((p->policy_type == POLICY_KERN &&
++	     p->policyvers >= POLICYDB_VERSION_DEFAULT_TYPE) ||
++	    (p->policy_type == POLICY_BASE &&
++	     p->policyvers >= MOD_POLICYDB_VERSION_DEFAULT_TYPE)) {
++		rc = next_entry(buf, fp, sizeof(uint32_t));
++		if (rc < 0)
++			goto bad;
++		cladatum->default_type = le32_to_cpu(buf[0]);
++	}
++
+ 	if (hashtab_insert(h, key, cladatum))
+ 		goto bad;
+ 
+diff --git a/libsepol/src/services.c b/libsepol/src/services.c
+index 9c2920c..9b42d8d 100644
+--- a/libsepol/src/services.c
++++ b/libsepol/src/services.c
+@@ -43,6 +43,13 @@
+  * 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
++
+ #include <stdlib.h>
+ #include <sys/types.h>
+ #include <sys/socket.h>
+@@ -54,6 +61,7 @@
+ #include <sepol/policydb/services.h>
+ #include <sepol/policydb/conditional.h>
+ #include <sepol/policydb/flask.h>
++#include <sepol/policydb/util.h>
+ 
+ #include "debug.h"
+ #include "private.h"
+@@ -70,6 +78,31 @@ 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)
++{
++	if (tos >= EXPR_BUFFERS) {
++		ERR(NULL, "Stack is full");
++		return;
++	}
++	stack[tos] = expr_ptr;
++	tos++;
++}
++ 
++char *pop()
++{
++	tos--;
++	if (tos < 0) {
++		ERR(NULL, "Stack is Empty");
++		return NULL;
++	}
++	return (char *)stack[tos];
++}
++/* 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)
+ 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.
++ */
++int get_type_set_list(constraint_expr_t * e, char * e_buf)
++{
++	ebitmap_t *types;
++	types = &e->type_names->types;
++
++	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);
++	}
++	strncat(e_buf, "} ", EXPR_BUF_SIZE);
++	free(list_buf);
++	return 0;
++}
++
++/*
++ * If the POLICY_KERN version is < POLICYDB_VERSION_CONSTRAINT_NAMES,
++ * then just return.
++ *
++ * If the POLICY_KERN version is >= POLICYDB_VERSION_CONSTRAINT_NAMES,
++ * then for 'types' only, read the types_names->types list as it will
++ * 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)
++{
++	/* If no buffer set then just return. */
++	if (!e_buf)
++		return 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;
++	}
++	return 0;
++}
++
++static void msgcat(char *e_buf, 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);
++	}
++}
++
++/*
++ * Modified version of constraint_expr_eval that will process each
++ * constraint as before but adds the information to text buffers that
++ * will hold various components. The expression will be in RPN format,
++ * therefore there is a stack based RPN to infix converter to produce
++ * the final readable constraint.
++ *
++ * Return the boolean value of a constraint expression
++ * when it is applied to the specified source and target
+  * security contexts.
+  *
+  * xcontext is a special beast...  It is used by the validatetrans rules
+  * only.  For these rules, scontext is the context before the transition,
+  * tcontext is the context after the transition, and xcontext is the context
+  * of the process performing the transition.  All other callers of
+- * constraint_expr_eval should pass in NULL for xcontext.
++ * constraint_expr_eval_reason should pass in NULL for xcontext.
++ * 
++ * This function will also build a buffer as the constraint is processed
++ * for analysis. If this option is not required, then:
++ *      'tclass' should be '0' and r_buf MUST be NULL.
+  */
+-static int constraint_expr_eval(context_struct_t * scontext,
++static int constraint_expr_eval_reason(context_struct_t * scontext,
+ 				context_struct_t * tcontext,
+ 				context_struct_t * xcontext,
+-				constraint_expr_t * cexpr)
++				sepol_security_class_t tclass,
++				constraint_node_t *constraint,
++				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,
+ 	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;
++
++/*
++ * Define the s_t_x_num values that make up r1, t2 etc. in text strings
++ * Set 1 = source, 2 = target, 3 = xcontext for validatetrans
++ */
++#define SOURCE  1
++#define TARGET  2
++#define XTARGET 3
++
++	int s_t_x_num = SOURCE;
++
++	/* Set 0 = fail, u = CEXPR_USER, r = CEXPR_ROLE, t = CEXPR_TYPE */
++	int u_r_t = 0;
++
++	char *name1, *name2;
++	char *src = NULL;
++	char *tgt = NULL;
++
++	int rc = 0, x;
++
++	/* Buffer to hold class & perm list */
++	class_buf = malloc(EXPR_BUF_SIZE);
++	if (!class_buf) {
++		ERR(NULL, "malloc 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));
++	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);
++
++	/* 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);
++
++	/* 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);
++
++	/* 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");
++			return -ENOMEM;
++		}
++		memset(expr_buf[expr_counter], '\0', EXPR_BUF_SIZE);
++
++		/* 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);
+ 			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);
+ 			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);
+ 			break;
+ 		case CEXPR_ATTR:
+ 			if (sp == (CEXPR_MAXDEPTH - 1))
+-				return 0;
++				goto out;
++
+ 			switch (e->attr) {
+ 			case CEXPR_USER:
+ 				val1 = scontext->user;
+ 				val2 = tcontext->user;
++				free(src); src = strdup("u1");
++				free(tgt); tgt = strdup("u2");
+ 				break;
+ 			case CEXPR_TYPE:
+ 				val1 = scontext->type;
+ 				val2 = tcontext->type;
++				free(src); src = strdup("t1");
++				free(tgt); tgt = strdup("t2");
+ 				break;
+ 			case CEXPR_ROLE:
+ 				val1 = scontext->role;
+ 				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);
++				}
+ 				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);
+ 					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);
+ 					continue;
+ 				case CEXPR_INCOMP:
+-					s[++sp] =
+-					    (!ebitmap_get_bit
+-					     (&r1->dominates, val2 - 1)
+-					     && !ebitmap_get_bit(&r2->dominates,
+-								 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);
+ 					continue;
+ 				default:
+ 					break;
+@@ -193,110 +406,286 @@ static int constraint_expr_eval(context_struct_t * scontext,
+ 			case CEXPR_L1L2:
+ 				l1 = &(scontext->range.level[0]);
+ 				l2 = &(tcontext->range.level[0]);
++				free(src); src = strdup("l1");
++				free(tgt); tgt = strdup("l2");
+ 				goto mls_ops;
+ 			case CEXPR_L1H2:
+ 				l1 = &(scontext->range.level[0]);
+ 				l2 = &(tcontext->range.level[1]);
++				free(src); src = strdup("l1");
++				free(tgt); tgt = strdup("h2");
+ 				goto mls_ops;
+ 			case CEXPR_H1L2:
+ 				l1 = &(scontext->range.level[1]);
+ 				l2 = &(tcontext->range.level[0]);
++				free(src); src = strdup("h1");
++				free(tgt); tgt = strdup("L2");
+ 				goto mls_ops;
+ 			case CEXPR_H1H2:
+ 				l1 = &(scontext->range.level[1]);
+ 				l2 = &(tcontext->range.level[1]);
++				free(src); src = strdup("h1");
++				free(tgt); tgt = strdup("h2");
+ 				goto mls_ops;
+ 			case CEXPR_L1H1:
+ 				l1 = &(scontext->range.level[0]);
+ 				l2 = &(scontext->range.level[1]);
++				free(src); src = strdup("l1");
++				free(tgt); tgt = strdup("h1");
+ 				goto mls_ops;
+ 			case CEXPR_L2H2:
+ 				l1 = &(tcontext->range.level[0]);
+ 				l2 = &(tcontext->range.level[1]);
+-				goto mls_ops;
+-			      mls_ops:
++				free(src); src = strdup("l2");
++				free(tgt); tgt = strdup("h2");
++			mls_ops:
+ 				switch (e->op) {
+ 				case CEXPR_EQ:
+ 					s[++sp] = mls_level_eq(l1, l2);
++					msgcat(expr_buf[expr_counter++], src, tgt,
++							"eq", s[sp] == 0);
+ 					continue;
+ 				case CEXPR_NEQ:
+ 					s[++sp] = !mls_level_eq(l1, l2);
++					msgcat(expr_buf[expr_counter++], src, tgt, "neq",
++							s[sp] == 0);
+ 					continue;
+ 				case CEXPR_DOM:
+ 					s[++sp] = mls_level_dom(l1, l2);
++					msgcat(expr_buf[expr_counter++], src, tgt, "dom",
++							s[sp] == 0);
+ 					continue;
+ 				case CEXPR_DOMBY:
+ 					s[++sp] = mls_level_dom(l2, l1);
++					msgcat(expr_buf[expr_counter++], src, tgt,
++							"domby", s[sp] == 0);
+ 					continue;
+ 				case CEXPR_INCOMP:
+ 					s[++sp] = mls_level_incomp(l2, l1);
++					msgcat(expr_buf[expr_counter++], src, tgt,
++							"incomp", s[sp] == 0);
+ 					continue;
+ 				default:
+ 					BUG();
+-					return 0;
++					goto out;
+ 				}
+ 				break;
+ 			default:
+ 				BUG();
+-				return 0;
++				goto out;
+ 			}
+ 
+ 			switch (e->op) {
+ 			case CEXPR_EQ:
+ 				s[++sp] = (val1 == val2);
++				msgcat(expr_buf[expr_counter], 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);
+ 				break;
+ 			default:
+ 				BUG();
+-				return 0;
++				goto out;
+ 			}
+ 			break;
+ 		case CEXPR_NAMES:
+ 			if (sp == (CEXPR_MAXDEPTH - 1))
+-				return 0;
++				goto out;
++			s_t_x_num = SOURCE;
+ 			c = scontext;
+-			if (e->attr & CEXPR_TARGET)
++			if (e->attr & CEXPR_TARGET) {
++				s_t_x_num = TARGET;
+ 				c = tcontext;
+-			else if (e->attr & CEXPR_XTARGET) {
++			} else if (e->attr & CEXPR_XTARGET) {
++				s_t_x_num = XTARGET;
+ 				c = xcontext;
+-				if (!c) {
+-					BUG();
+-					return 0;
+-				}
+ 			}
+-			if (e->attr & CEXPR_USER)
++			if (!c) {
++				BUG();
++				goto out;
++			}
++			if (e->attr & CEXPR_USER) {
++				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);
++				}
++			}
++			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);
++				}
++			}
++			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);
++				}
++			}
+ 			else {
+ 				BUG();
+-				return 0;
++				goto out;
+ 			}
+ 
+ 			switch (e->op) {
+ 			case CEXPR_EQ:
++				switch (u_r_t) {
++				case CEXPR_USER:
++					free(tgt); tgt=strdup("USER_ENTRY");
++					break;
++				case CEXPR_ROLE:
++					free(tgt); tgt=strdup("ROLE_ENTRY");
++					break;
++				case CEXPR_TYPE:
++					free(tgt); tgt=strdup("TYPE_ENTRY");
++					break;
++				default:
++					ERR(NULL, "unrecognized u_r_t Value: %d", u_r_t);
++					break;
++				}
++
+ 				s[++sp] = ebitmap_get_bit(&e->names, val1 - 1);
++				msgcat(expr_buf[expr_counter], src, tgt, "eq", s[sp] == 0);
++				if (s[sp] == 0) {
++					get_names_list(e, u_r_t, expr_buf[expr_counter]);
++				}
+ 				break;
++
+ 			case CEXPR_NEQ:
++				switch (u_r_t) {
++				case CEXPR_USER:
++					free(tgt); tgt=strdup("USER_ENTRY");
++					break;
++				case CEXPR_ROLE:
++					free(tgt); tgt=strdup("ROLE_ENTRY");
++					break;
++				case CEXPR_TYPE:
++					free(tgt); tgt=strdup("TYPE_ENTRY");
++					break;
++				default:
++					ERR(NULL, "unrecognized u_r_t Value: %d", u_r_t);
++					break;
++				}
++
+ 				s[++sp] = !ebitmap_get_bit(&e->names, val1 - 1);
++				msgcat(expr_buf[expr_counter], src, tgt, "neq", s[sp] == 0);
++				if (s[sp] == 0) {
++					get_names_list(e, u_r_t, expr_buf[expr_counter]);
++				}
+ 				break;
+ 			default:
+ 				BUG();
+-				return 0;
++				goto out;
+ 			}
+ 			break;
+ 		default:
+ 			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'
++	 */
++
++	/*
++	 * 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.
++	 */
++	expr_counter = 0;
++
++	/* The array of expression answer buffer pointers and counter */
++	char *answer_buf[EXPR_BUFFERS] = {NULL};
++	int answer_counter = 0;
++	/* 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],
++					"or", 2) == 0) {
++			b = pop();
++			b_len = strlen(b);
++			a = pop();
++			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");
++				return -ENOMEM;
++			}
++			memset(answer_buf[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++]);
++			free(a);
++			free(b);
++		} else if (strncmp(expr_buf[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");
++				return -ENOMEM;
++			}
++			memset(answer_buf[answer_counter], '\0', b_len + 8);
++
++			if (strncmp(b, "not", 3) == 0)
++				sprintf(answer_buf[answer_counter], "%s (%s)", expr_buf[x], b);
++			else
++				sprintf(answer_buf[answer_counter], "%s%s", expr_buf[x], b);
++			push(answer_buf[answer_counter++]);
++			free(b);
++		} else {
++			push(expr_buf[x]);
++		}
++	}
++	/* Get the final answer from tos and build constraint text */
++	a = pop();
++
++	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);
++    	}
++	}
++	free(a);
++	rc = s[0];
++
++out:
++	free(class_buf);
++	free(src); 
++	free(tgt);
++	if (expr_counter) {
++		for (x = 0; expr_buf[x] != NULL; x++)
++			free(expr_buf[x]);
++	}
+ 	BUG_ON(sp != 0);
+-	return s[0];
++	return rc;
+ }
+ 
+ /*
+@@ -308,7 +697,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,
++					 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,
+ 	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)) {
+ 			avd->allowed =
+ 			    (avd->allowed) & ~(constraint->permissions);
+ 		}
+@@ -459,8 +850,8 @@ int hidden sepol_validate_transition(sepol_security_id_t oldsid,
+ 
+ 	constraint = tclass_datum->validatetrans;
+ 	while (constraint) {
+-		if (!constraint_expr_eval(ocontext, ncontext, tcontext,
+-					  constraint->expr)) {
++		if (!constraint_expr_eval_reason(ocontext, ncontext, tcontext,
++					  0, constraint, NULL, 0)) {
+ 			return -EPERM;
+ 		}
+ 		constraint = constraint->next;
+@@ -493,11 +884,58 @@ int hidden sepol_compute_av_reason(sepol_security_id_t ssid,
+ 	}
+ 
+ 	rc = context_struct_compute_av(scontext, tcontext, tclass,
+-				       requested, avd, reason);
++					requested, avd, reason, NULL, 0);
+       out:
+ 	return rc;
+ }
+ 
++/* 
++ * 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.
++ */
++int hidden sepol_compute_av_reason_buffer(sepol_security_id_t ssid,
++				   sepol_security_id_t tsid,
++				   sepol_security_class_t tclass,
++				   sepol_access_vector_t requested,
++				   struct sepol_av_decision *avd,
++				   unsigned int *reason,
++				   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");
++		return -ENOMEM;
++	}
++	memset(r_buf, '\0', REASON_BUF_SIZE);
++
++	context_struct_t *scontext = 0, *tcontext = 0;
++	int rc = 0;
++
++	scontext = sepol_sidtab_search(sidtab, ssid);
++	if (!scontext) {
++		ERR(NULL, "unrecognized SID %d", ssid);
++		rc = -EINVAL;
++		goto out;
++	}
++	tcontext = sepol_sidtab_search(sidtab, tsid);
++	if (!tcontext) {
++		ERR(NULL, "unrecognized SID %d", tsid);
++		rc = -EINVAL;
++		goto out;
++	}
++
++	rc = context_struct_compute_av(scontext, tcontext, tclass,
++					   requested, avd, reason, r_buf, flags);
++	*reason_buf = r_buf;
++
++	  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,
+ }
+ 
+ /*
++ * Return a class ID associated with the class string specified by
++ * class_name.
++ */
++int hidden sepol_class_name_to_id(const char *class_name,
++			sepol_security_class_t *tclass)
++{
++	char *class = NULL;
++	sepol_security_class_t id;
++
++	for (id = 1; ; id++) {
++		if ((class = policydb->p_class_val_to_name[id - 1]) == NULL) {
++			ERR(NULL, "could not convert %s to class id", class_name);
++			return STATUS_ERR;
++		}
++		if ((strcmp(class, class_name)) == 0) {
++			*tclass = id;
++			return STATUS_SUCCESS;
++		}
++	}
++}
++
++/*
++ * Return access vector bit associated with the class ID and permission
++ * string.
++ */
++int hidden sepol_perm_name_to_av(sepol_security_class_t tclass,
++					const char *perm_name,
++					sepol_access_vector_t *av)
++{
++	class_datum_t *tclass_datum;
++	perm_datum_t *perm_datum;
++
++	if (!tclass || tclass > policydb->p_classes.nprim) {
++		ERR(NULL, "unrecognized class %d", tclass);
++		return -EINVAL;
++	}
++	tclass_datum = policydb->class_val_to_struct[tclass - 1];
++
++	/* Check for unique perms then the common ones */
++	perm_datum = (perm_datum_t *)
++			hashtab_search(tclass_datum->permissions.table,
++			(hashtab_key_t)perm_name);
++	if (perm_datum != NULL) {
++		*av = 0x1 << (perm_datum->s.value - 1);
++		return STATUS_SUCCESS;
++	}
++
++	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;
++	}	
++
++	ERR(NULL, "could not convert %s to av bit", perm_name);
++   	return STATUS_ERR;
++}
++
++/*
+  * 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,
+ 			rc = context_struct_compute_av(fromcon, &usercon,
+ 						       SECCLASS_PROCESS,
+ 						       PROCESS__TRANSITION,
+-						       &avd, &reason);
++						       &avd, &reason, NULL, 0);
+ 			if (rc || !(avd.allowed & PROCESS__TRANSITION))
+ 				continue;
+ 			rc = sepol_sidtab_context_to_sid(sidtab, &usercon,
+diff --git a/libsepol/src/write.c b/libsepol/src/write.c
+index 22e6143..6fe73e6 100644
+--- a/libsepol/src/write.c
++++ b/libsepol/src/write.c
+@@ -893,8 +893,11 @@ static int write_cons_helper(policydb_t * p,
+ 				if (ebitmap_write(&e->names, fp)) {
+ 					return POLICYDB_ERROR;
+ 				}
+-				if (p->policy_type != POLICY_KERN &&
+-				    type_set_write(e->type_names, fp)) {
++				if ((p->policy_type != POLICY_KERN &&
++						type_set_write(e->type_names, fp)) ||
++						(p->policy_type == POLICY_KERN &&
++						(p->policyvers >= POLICYDB_VERSION_CONSTRAINT_NAMES) &&
++						type_set_write(e->type_names, fp))) {
+ 					return POLICYDB_ERROR;
+ 				}
+ 				break;
+@@ -988,6 +991,16 @@ static int class_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
+ 			return POLICYDB_ERROR;
+ 	}
+ 
++	if ((p->policy_type == POLICY_KERN &&
++	     p->policyvers >= POLICYDB_VERSION_DEFAULT_TYPE) ||
++	    (p->policy_type == POLICY_BASE &&
++	     p->policyvers >= MOD_POLICYDB_VERSION_DEFAULT_TYPE)) {
++		buf[0] = cpu_to_le32(cladatum->default_type);
++		items = put_entry(buf, sizeof(uint32_t), 1, fp);
++		if (items != 1)
++			return POLICYDB_ERROR;
++	}
++
+ 	return POLICYDB_SUCCESS;
+ }
+ 
+@@ -1795,34 +1808,38 @@ static int scope_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
+ 	uint32_t static_buf[32], *dyn_buf = NULL, *buf;
+ 	size_t key_len = strlen(key);
+ 	unsigned int items = 2 + scope->decl_ids_len, i;
++	int rc;
+ 
++	buf = static_buf;
+ 	if (items >= (sizeof(static_buf) / 4)) {
+ 		/* too many things required, so dynamically create a
+ 		 * buffer.  this would have been easier with C99's
+ 		 * dynamic arrays... */
+-		if ((dyn_buf = malloc(items * sizeof(*dyn_buf))) == NULL) {
+-			return POLICYDB_ERROR;
+-		}
++		rc = POLICYDB_ERROR;
++		dyn_buf = malloc(items * sizeof(*dyn_buf));
++		if (!dyn_buf)
++			goto err;
+ 		buf = dyn_buf;
+-	} else {
+-		buf = static_buf;
+ 	}
+ 	buf[0] = cpu_to_le32(key_len);
++
++	rc = POLICYDB_ERROR;
+ 	if (put_entry(buf, sizeof(*buf), 1, fp) != 1 ||
+-	    put_entry(key, 1, key_len, fp) != key_len) {
+-		return POLICYDB_ERROR;
+-	}
++	    put_entry(key, 1, key_len, fp) != key_len)
++		goto err;
+ 	buf[0] = cpu_to_le32(scope->scope);
+ 	buf[1] = cpu_to_le32(scope->decl_ids_len);
+-	for (i = 0; i < scope->decl_ids_len; i++) {
++
++	for (i = 0; i < scope->decl_ids_len; i++)
+ 		buf[2 + i] = cpu_to_le32(scope->decl_ids[i]);
+-	}
+-	if (put_entry(buf, sizeof(*buf), items, fp) != items) {
+-		free(dyn_buf);
+-		return POLICYDB_ERROR;
+-	}
++
++	rc = POLICYDB_ERROR;
++	if (put_entry(buf, sizeof(*buf), items, fp) != items)
++		goto err;
++	rc = POLICYDB_SUCCESS;
++err:
+ 	free(dyn_buf);
+-	return POLICYDB_SUCCESS;
++	return rc;
+ }
+ 
+ static int type_attr_uncount(hashtab_key_t key __attribute__ ((unused)),
+@@ -2006,7 +2023,7 @@ int policydb_write(policydb_t * p, struct policy_file *fp)
+ 		    ((p->policy_type == POLICY_KERN) ||
+ 		     (p->policy_type != POLICY_KERN &&
+ 		      p->policyvers < MOD_POLICYDB_VERSION_ROLEATTRIB)))
+-			hashtab_map(p->symtab[i].table, role_attr_uncount, &buf[1]);
++			(void)hashtab_map(p->symtab[i].table, role_attr_uncount, &buf[1]);
+ 
+ 		buf[1] = cpu_to_le32(buf[1]);
+ 		items = put_entry(buf, sizeof(uint32_t), 2, fp);
diff --git a/libsepol.spec b/libsepol.spec
index eb67dab..4e83c0f 100644
--- a/libsepol.spec
+++ b/libsepol.spec
@@ -1,11 +1,12 @@
 Summary: SELinux binary policy manipulation library 
 Name: libsepol
 Version: 2.1.8
-Release: 2%{?dist}
+Release: 6%{?dist}
 License: LGPLv2+
 Group: System Environment/Libraries
 Source: http://www.nsa.gov/selinux/archives/libsepol-%{version}.tgz
 Patch: libsepol-rhat.patch
+Patch1: tmp.patch
 URL: http://www.selinuxproject.org
 BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
 
@@ -46,6 +47,7 @@ needed for developing applications that manipulate binary policies.
 %prep
 %setup -q
 %patch -p2 -b .rhat
+%patch1 -p2 -b .tmp
 
 # sparc64 is an -fPIC arch, so we need to fix it here
 %ifarch sparc64
@@ -99,6 +101,18 @@ exit 0
 /%{_lib}/libsepol.so.1
 
 %changelog
+* Tue Jan 8 2013 Dan Walsh <dwalsh at redhat.com> - 2.1.8-6
+- Fix libsepol.stack messages in audit2allow/audit2why
+
+* Fri Jan 4 2013 Dan Walsh <dwalsh at redhat.com> - 2.1.8-5
+- Update to latest patches from eparis/Upstream
+
+* Tue Nov 27 2012 Dan Walsh <dwalsh at redhat.com> - 2.1.8-4
+- Update Richard Haines patch to show constraint information
+
+* Mon Nov 19 2012 Dan Walsh <dwalsh at redhat.com> - 2.1.8-3
+- Add sepol_compute_av_reason_buffer patch from Richard Haines
+
 * Wed Sep 19 2012 Dan Walsh <dwalsh at redhat.com> - 2.1.8-2
 - Revert patch that was attempting to expand filetrans attributes, but is breaking filetrans rules
 
@@ -182,7 +196,7 @@ dup!
 	* setools expects expand_module_avrules to be an exported
 	* tree: default make target to all not
 
-* Thu Sep 14 2011 Dan Walsh <dwalsh at redhat.com> - 2.1.2-3
+* Thu Sep 15 2011 Dan Walsh <dwalsh at redhat.com> - 2.1.2-3
 - Add patch to handle preserving tunables
 
 * Thu Sep 1 2011 Dan Walsh <dwalsh at redhat.com> - 2.1.2-2
@@ -201,7 +215,7 @@ dup!
 - Update to upstream 
 	* Release, minor version bump
 
-* Thu May 3 2011 Dan Walsh <dwalsh at redhat.com> 2.0.45-1
+* Tue May 3 2011 Dan Walsh <dwalsh at redhat.com> 2.0.45-1
 - Update to upstream 
   * Warn if filename_trans rules are dropped by Steve Lawrence.
 
@@ -251,7 +265,7 @@ Resolves: #555835
 - Upgrade to latest from NSA
   * Add pkgconfig file from Eamon Walsh.
 
-* Tue Oct 14 2009 Dan Walsh <dwalsh at redhat.com> 2.0.39-1
+* Wed Oct 14 2009 Dan Walsh <dwalsh at redhat.com> 2.0.39-1
 - Upgrade to latest from NSA
   * Add support for building Xen policies from Paul Nuzzi.
 
@@ -509,7 +523,7 @@ Resolves: #555835
     a policy requires the compatibility support for network checks
     to be enabled in the kernel.
 
-* Thu May 15 2006 Dan Walsh <dwalsh at redhat.com> 1.12.11-1
+* Thu May 18 2006 Dan Walsh <dwalsh at redhat.com> 1.12.11-1
 - Upgrade to latest from NSA
   * Merged patch to initialize sym_val_to_name arrays from Kevin Carr.
     Reworked to use calloc in the first place, and converted some other
@@ -616,7 +630,7 @@ Resolves: #555835
 - Upgrade to latest from NSA
   * Merged 2nd const in APIs patch from Ivan Gyurdiev.
 
-* Fri Jan 7 2006 Dan Walsh <dwalsh at redhat.com> 1.11.7-1
+* Fri Jan 6 2006 Dan Walsh <dwalsh at redhat.com> 1.11.7-1
 - Upgrade to latest from NSA
   * Merged const in APIs patch from Ivan Gyurdiev.
   * Merged compare2 function patch from Ivan Gyurdiev.
@@ -852,7 +866,7 @@ Resolves: #555835
   * Merged fix for sepol_enable/disable_debug from Ivan
   Gyurdiev.
 
-* Mon Sep 14 2005 Dan Walsh <dwalsh at redhat.com> 1.9.1-2
+* Wed Sep 14 2005 Dan Walsh <dwalsh at redhat.com> 1.9.1-2
 - Upgrade to latest from NSA
   * Merged stddef.h patch and debug conversion patch from 
   Ivan Gyurdiev.


More information about the scm-commits mailing list