Update to libsepol 2.1.8.

Change-Id: I7d848ee312d4c706162a822d2031f37a5557ed5f
Signed-off-by: Stephen Smalley <sds@tycho.nsa.gov>
diff --git a/ChangeLog b/ChangeLog
index f835678..75bf7b4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,22 @@
+2.1.8 2011-09-13
+	* fix neverallow checking on attributes
+	* Move context_copy() after switch block in ocontext_copy_*().
+	* check for missing initial SID labeling statement.
+	* Add always_check_network policy capability
+	* role_fix_callback skips out-of-scope roles during expansion.
+
+2.1.7 2011-06-28
+	* reserve policycapability for redhat testing of ptrace child
+	* cosmetic changes to make the source easier to read
+	* prepend instead of append to filename_trans list
+	* Android/MacOS X build support
+
+2.1.6 2011-04-23
+	* allocate enough space to hold filename in trans rules
+
+2.1.5 2011-03-28
+	* checkpolicy: implement new default labeling behaviors
+
 2.1.4 2011-10-03
 	* regenerate .pc on VERSION change
 	* Move ebitmap_* functions from mcstrans to libsepol
diff --git a/VERSION b/VERSION
index 7d2ed7c..ebf14b4 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.1.4
+2.1.8
diff --git a/include/sepol/policydb/polcaps.h b/include/sepol/policydb/polcaps.h
index 40c0a48..f90a48d 100644
--- a/include/sepol/policydb/polcaps.h
+++ b/include/sepol/policydb/polcaps.h
@@ -5,6 +5,8 @@
 enum {
 	POLICYDB_CAPABILITY_NETPEER,
 	POLICYDB_CAPABILITY_OPENPERM,
+	POLICYDB_CAPABILITY_REDHAT1, /* reserved for RH testing of ptrace_child */
+	POLICYDB_CAPABILITY_ALWAYSNETWORK,
 	__POLICYDB_CAPABILITY_MAX
 };
 #define POLICYDB_CAPABILITY_MAX (__POLICYDB_CAPABILITY_MAX - 1)
diff --git a/include/sepol/policydb/policydb.h b/include/sepol/policydb/policydb.h
index 1848a7b..f53a499 100644
--- a/include/sepol/policydb/policydb.h
+++ b/include/sepol/policydb/policydb.h
@@ -111,6 +111,19 @@
 	symtab_t permissions;	/* class-specific permission symbol table */
 	constraint_node_t *constraints;	/* constraints on class permissions */
 	constraint_node_t *validatetrans;	/* special transition rules */
+/* Options how a new object user and role should be decided */
+#define DEFAULT_SOURCE		1
+#define DEFAULT_TARGET		2
+	char default_user;
+	char default_role;
+/* Options how a new object range should be decided */
+#define DEFAULT_SOURCE_LOW	1
+#define DEFAULT_SOURCE_HIGH	2
+#define DEFAULT_SOURCE_LOW_HIGH	3
+#define DEFAULT_TARGET_LOW	4
+#define DEFAULT_TARGET_HIGH	5
+#define DEFAULT_TARGET_LOW_HIGH	6
+	char default_range;
 } class_datum_t;
 
 /* Role attributes */
@@ -667,10 +680,11 @@
 #define POLICYDB_VERSION_BOUNDARY	24
 #define POLICYDB_VERSION_FILENAME_TRANS	25
 #define POLICYDB_VERSION_ROLETRANS	26
+#define POLICYDB_VERSION_NEW_OBJECT_DEFAULTS	27
 
 /* Range of policy versions we understand*/
 #define POLICYDB_VERSION_MIN	POLICYDB_VERSION_BASE
-#define POLICYDB_VERSION_MAX	POLICYDB_VERSION_ROLETRANS
+#define POLICYDB_VERSION_MAX	POLICYDB_VERSION_NEW_OBJECT_DEFAULTS
 
 /* Module versions and specific changes*/
 #define MOD_POLICYDB_VERSION_BASE		4
@@ -686,9 +700,10 @@
 #define MOD_POLICYDB_VERSION_ROLETRANS		12
 #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_MIN MOD_POLICYDB_VERSION_BASE
-#define MOD_POLICYDB_VERSION_MAX MOD_POLICYDB_VERSION_TUNABLE_SEP
+#define MOD_POLICYDB_VERSION_MAX MOD_POLICYDB_VERSION_NEW_OBJECT_DEFAULTS
 
 #define POLICYDB_CONFIG_MLS    1
 
diff --git a/src/expand.c b/src/expand.c
index 493e478..2003eb6 100644
--- a/src/expand.c
+++ b/src/expand.c
@@ -358,6 +358,35 @@
 	return -1;
 }
 
+static int class_copy_default_new_object(expand_state_t *state,
+					 class_datum_t *olddatum,
+					 class_datum_t *newdatum)
+{
+	if (olddatum->default_user) {
+		if (newdatum->default_user && olddatum->default_user != newdatum->default_user) {
+			ERR(state->handle, "Found conflicting default user definitions");
+			return SEPOL_ENOTSUP;
+		}
+		newdatum->default_user = olddatum->default_user;
+
+	}
+	if (olddatum->default_role) {
+		if (newdatum->default_role && olddatum->default_role != newdatum->default_role) {
+			ERR(state->handle, "Found conflicting default role definitions");
+			return SEPOL_ENOTSUP;
+		}
+		newdatum->default_role = olddatum->default_role;
+	}
+	if (olddatum->default_range) {
+		if (newdatum->default_range && olddatum->default_range != newdatum->default_range) {
+			ERR(state->handle, "Found conflicting default range definitions");
+			return SEPOL_ENOTSUP;
+		}
+		newdatum->default_range = olddatum->default_range;
+	}
+	return 0;
+}
+
 static int class_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
 			       void *data)
 {
@@ -393,6 +422,12 @@
 	new_class->s.value = class->s.value;
 	state->out->p_classes.nprim++;
 
+	ret = class_copy_default_new_object(state, class, new_class);
+	if (ret) {
+		free(new_class);
+		return ret;
+	}
+	
 	new_id = strdup(id);
 	if (!new_id) {
 		ERR(state->handle, "Out of memory!");
@@ -688,6 +723,11 @@
 		return 0;
 	}
 
+	if (!is_id_enabled(id, state->base, SYM_ROLES)) {
+		/* identifier's scope is not enabled */
+		return 0;
+	}
+
 	if (role->flavor != ROLE_ATTRIB)
 		return 0;
 
@@ -1317,16 +1357,11 @@
 static int expand_filename_trans(expand_state_t *state, filename_trans_rule_t *rules)
 {
 	unsigned int i, j;
-	filename_trans_t *new_trans, *tail, *cur_trans;
+	filename_trans_t *new_trans, *cur_trans;
 	filename_trans_rule_t *cur_rule;
 	ebitmap_t stypes, ttypes;
 	ebitmap_node_t *snode, *tnode;
 
-	/* start at the end of the list */
-	tail = state->out->filename_trans;
-	while (tail && tail->next)
-		tail = tail->next;
-
 	cur_rule = rules;
 	while (cur_rule) {
 		uint32_t mapped_otype;
@@ -1387,11 +1422,8 @@
 					return -1;
 				}
 				memset(new_trans, 0, sizeof(*new_trans));
-				if (tail)
-					tail->next = new_trans;
-				else
-					state->out->filename_trans = new_trans;
-				tail = new_trans;
+				new_trans->next = state->out->filename_trans;
+				state->out->filename_trans = new_trans;
 
 				new_trans->name = strdup(cur_rule->name);
 				if (!new_trans->name) {
@@ -1791,58 +1823,36 @@
 			continue;
 		if (source_rule->flags & RULE_SELF) {
 			if (source_rule->specified & AVRULE_AV) {
-				if ((retval =
-				     expand_avrule_helper(handle,
-							  source_rule->
-							  specified, cond, i, i,
-							  source_rule->perms,
-							  dest_avtab,
-							  enabled)) !=
-				    EXPAND_RULE_SUCCESS) {
+				retval = expand_avrule_helper(handle, source_rule->specified,
+							      cond, i, i, source_rule->perms,
+							      dest_avtab, enabled);
+				if (retval != EXPAND_RULE_SUCCESS)
 					return retval;
-				}
 			} else {
-				if ((retval =
-				     expand_terule_helper(handle, p,
-							  typemap,
-							  source_rule->
-							  specified, cond,
-							  other, i, i,
-							  source_rule->perms,
-							  dest_avtab,
-							  enabled)) !=
-				    EXPAND_RULE_SUCCESS) {
+				retval = expand_terule_helper(handle, p, typemap,
+							      source_rule->specified, cond,
+							      other, i, i, source_rule->perms,
+							      dest_avtab, enabled);
+				if (retval != EXPAND_RULE_SUCCESS)
 					return retval;
-				}
 			}
 		}
 		ebitmap_for_each_bit(ttypes, tnode, j) {
 			if (!ebitmap_node_get_bit(tnode, j))
 				continue;
 			if (source_rule->specified & AVRULE_AV) {
-				if ((retval =
-				     expand_avrule_helper(handle,
-							  source_rule->
-							  specified, cond, i, j,
-							  source_rule->perms,
-							  dest_avtab,
-							  enabled)) !=
-				    EXPAND_RULE_SUCCESS) {
+				retval = expand_avrule_helper(handle, source_rule->specified,
+							      cond, i, j, source_rule->perms,
+							      dest_avtab, enabled);
+				if (retval != EXPAND_RULE_SUCCESS)
 					return retval;
-				}
 			} else {
-				if ((retval =
-				     expand_terule_helper(handle, p,
-							  typemap,
-							  source_rule->
-							  specified, cond,
-							  other, i, j,
-							  source_rule->perms,
-							  dest_avtab,
-							  enabled)) !=
-				    EXPAND_RULE_SUCCESS) {
+				retval = expand_terule_helper(handle, p, typemap,
+							      source_rule->specified, cond,
+							      other, i, j, source_rule->perms,
+							      dest_avtab, enabled);
+				if (retval != EXPAND_RULE_SUCCESS)
 					return retval;
-				}
 			}
 		}
 	}
@@ -2027,13 +2037,14 @@
 			else
 				state->out->ocontexts[i] = n;
 			l = n;
-			if (context_copy(&n->context[0], &c->context[0],
-				state)) {
-				ERR(state->handle, "Out of memory!");
-				return -1;
-			}
 			switch (i) {
 			case OCON_XEN_ISID:
+				if (c->context[0].user == 0) {
+					ERR(state->handle,
+					    "Missing context for %s initial sid",
+					    c->u.name);
+					return -1;
+				}
 				n->sid[0] = c->sid[0];
 				break;
 			case OCON_XEN_PIRQ:
@@ -2056,6 +2067,11 @@
 				ERR(state->handle, "Unknown ocontext");
 				return -1;
 			}
+			if (context_copy(&n->context[0], &c->context[0],
+				state)) {
+				ERR(state->handle, "Out of memory!");
+				return -1;
+			}
 		}
 	}
 	return 0;
@@ -2080,12 +2096,14 @@
 			else
 				state->out->ocontexts[i] = n;
 			l = n;
-			if (context_copy(&n->context[0], &c->context[0], state)) {
-				ERR(state->handle, "Out of memory!");
-				return -1;
-			}
 			switch (i) {
 			case OCON_ISID:
+				if (c->context[0].user == 0) {
+					ERR(state->handle,
+					    "Missing context for %s initial sid",
+					    c->u.name);
+					return -1;
+				}
 				n->sid[0] = c->sid[0];
 				break;
 			case OCON_FS:	/* FALLTHROUGH */
@@ -2129,6 +2147,10 @@
 				ERR(state->handle, "Unknown ocontext");
 				return -1;
 			}
+			if (context_copy(&n->context[0], &c->context[0], state)) {
+				ERR(state->handle, "Out of memory!");
+				return -1;
+			}
 		}
 	}
 	return 0;
@@ -3101,12 +3123,12 @@
 	newkey.target_class = k->target_class;
 	newkey.specified = k->specified;
 
-	if (stype && ttype) {
+	if (stype->flavor != TYPE_ATTRIB && ttype->flavor != TYPE_ATTRIB) {
 		/* Both are individual types, no expansion required. */
 		return expand_avtab_insert(expa, k, d);
 	}
 
-	if (stype) {
+	if (stype->flavor != TYPE_ATTRIB) {
 		/* Source is an individual type, target is an attribute. */
 		newkey.source_type = k->source_type;
 		ebitmap_for_each_bit(tattr, tnode, j) {
@@ -3120,7 +3142,7 @@
 		return 0;
 	}
 
-	if (ttype) {
+	if (ttype->flavor != TYPE_ATTRIB) {
 		/* Target is an individual type, source is an attribute. */
 		newkey.target_type = k->target_type;
 		ebitmap_for_each_bit(sattr, snode, i) {
@@ -3231,12 +3253,12 @@
 	newkey.target_class = k->target_class;
 	newkey.specified = k->specified;
 
-	if (stype && ttype) {
+	if (stype->flavor != TYPE_ATTRIB && ttype->flavor != TYPE_ATTRIB) {
 		/* Both are individual types, no expansion required. */
 		return expand_cond_insert(newl, expa, k, d);
 	}
 
-	if (stype) {
+	if (stype->flavor != TYPE_ATTRIB) {
 		/* Source is an individual type, target is an attribute. */
 		newkey.source_type = k->source_type;
 		ebitmap_for_each_bit(tattr, tnode, j) {
@@ -3250,7 +3272,7 @@
 		return 0;
 	}
 
-	if (ttype) {
+	if (ttype->flavor != TYPE_ATTRIB) {
 		/* Target is an individual type, source is an attribute. */
 		newkey.target_type = k->target_type;
 		ebitmap_for_each_bit(sattr, snode, i) {
diff --git a/src/link.c b/src/link.c
index ee9675b..01d3231 100644
--- a/src/link.c
+++ b/src/link.c
@@ -205,6 +205,34 @@
 	return ret;
 }
 
+static int class_copy_default_new_object(link_state_t *state,
+					 class_datum_t *olddatum,
+					 class_datum_t *newdatum)
+{
+	if (olddatum->default_user) {
+		if (newdatum->default_user && olddatum->default_user != newdatum->default_user) {
+			ERR(state->handle, "Found conflicting default user definitions");
+			return SEPOL_ENOTSUP;
+		}
+		newdatum->default_user = olddatum->default_user;
+	}
+	if (olddatum->default_role) {
+		if (newdatum->default_role && olddatum->default_role != newdatum->default_role) {
+			ERR(state->handle, "Found conflicting default role definitions");
+			return SEPOL_ENOTSUP;
+		}
+		newdatum->default_role = olddatum->default_role;
+	}
+	if (olddatum->default_range) {
+		if (newdatum->default_range && olddatum->default_range != newdatum->default_range) {
+			ERR(state->handle, "Found conflicting default range definitions");
+			return SEPOL_ENOTSUP;
+		}
+		newdatum->default_range = olddatum->default_range;
+	}
+	return 0;
+}
+
 static int class_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
 			       void *data)
 {
@@ -287,6 +315,11 @@
 	state->dest_class = new_class;
 	state->dest_class_name = (char *)key;
 
+	/* copy default new object rules */
+	ret = class_copy_default_new_object(state, cladatum, new_class);
+	if (ret)
+		return ret;
+
 	ret =
 	    hashtab_map(cladatum->permissions.table, permission_copy_callback,
 			state);
diff --git a/src/polcaps.c b/src/polcaps.c
index 71970b1..43a71a7 100644
--- a/src/polcaps.c
+++ b/src/polcaps.c
@@ -8,6 +8,8 @@
 static const char *polcap_names[] = {
 	"network_peer_controls",	/* POLICYDB_CAPABILITY_NETPEER */
 	"open_perms",			/* POLICYDB_CAPABILITY_OPENPERM */
+	"redhat1",			/* POLICYDB_CAPABILITY_REDHAT1, aka ptrace_child */
+	"always_check_network",		/* POLICYDB_CAPABILITY_ALWAYSNETWORK */
 	NULL
 };
 
diff --git a/src/policydb.c b/src/policydb.c
index 136b450..ff292f6 100644
--- a/src/policydb.c
+++ b/src/policydb.c
@@ -151,6 +151,13 @@
 	 .target_platform = SEPOL_TARGET_SELINUX,
 	},
 	{
+	 .type = POLICY_KERN,
+	 .version = POLICYDB_VERSION_NEW_OBJECT_DEFAULTS,
+	 .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,
@@ -228,6 +235,13 @@
 	 .target_platform = SEPOL_TARGET_SELINUX,
 	},
 	{
+	 .type = POLICY_BASE,
+	 .version = MOD_POLICYDB_VERSION_NEW_OBJECT_DEFAULTS,
+	 .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,
@@ -304,6 +318,13 @@
 	 .ocon_num = 0,
 	 .target_platform = SEPOL_TARGET_SELINUX,
 	},
+	{
+	 .type = POLICY_MOD,
+	 .version = MOD_POLICYDB_VERSION_NEW_OBJECT_DEFAULTS,
+	 .sym_num = SYM_NUM,
+	 .ocon_num = 0,
+	 .target_platform = SEPOL_TARGET_SELINUX,
+	},
 };
 
 #if 0
@@ -2064,6 +2085,18 @@
 			goto bad;
 	}
 
+	if ((p->policy_type == POLICY_KERN &&
+	     p->policyvers >= POLICYDB_VERSION_NEW_OBJECT_DEFAULTS) ||
+	    (p->policy_type == POLICY_BASE &&
+	     p->policyvers >= MOD_POLICYDB_VERSION_NEW_OBJECT_DEFAULTS)) {
+		rc = next_entry(buf, fp, sizeof(uint32_t) * 3);
+		if (rc < 0)
+			goto bad;
+		cladatum->default_user = le32_to_cpu(buf[0]);
+		cladatum->default_role = le32_to_cpu(buf[1]);
+		cladatum->default_range = le32_to_cpu(buf[2]);
+	}
+
 	if (hashtab_insert(h, key, cladatum))
 		goto bad;
 
@@ -2347,7 +2380,7 @@
 			return -1;
 		len = le32_to_cpu(buf[0]);
 
-		name = calloc(len, sizeof(*name));
+		name = calloc(len + 1, sizeof(*name));
 		if (!name)
 			return -1;
 
diff --git a/src/private.h b/src/private.h
index a2188d4..8a6d4bb 100644
--- a/src/private.h
+++ b/src/private.h
@@ -18,7 +18,7 @@
 
 #ifdef DARWIN
 #define __BYTE_ORDER  BYTE_ORDER
-#define __LITTLE_ENDIAN  LITTLE_ENDIAN 
+#define __LITTLE_ENDIAN  LITTLE_ENDIAN
 #endif
 
 #if __BYTE_ORDER == __LITTLE_ENDIAN
diff --git a/src/write.c b/src/write.c
index e34ab52..22e6143 100644
--- a/src/write.c
+++ b/src/write.c
@@ -976,6 +976,18 @@
 			return POLICYDB_ERROR;
 	}
 
+	if ((p->policy_type == POLICY_KERN &&
+	     p->policyvers >= POLICYDB_VERSION_NEW_OBJECT_DEFAULTS) ||
+	    (p->policy_type == POLICY_BASE &&
+	     p->policyvers >= MOD_POLICYDB_VERSION_NEW_OBJECT_DEFAULTS)) {
+		buf[0] = cpu_to_le32(cladatum->default_user);
+		buf[1] = cpu_to_le32(cladatum->default_role);
+		buf[2] = cpu_to_le32(cladatum->default_range);
+		items = put_entry(buf, sizeof(uint32_t), 3, fp);
+		if (items != 3)
+			return POLICYDB_ERROR;
+	}
+
 	return POLICYDB_SUCCESS;
 }