Merge "bootchart: add policy rules for bootchart"
diff --git a/README b/README
index 83ee7a2..46f58b5 100644
--- a/README
+++ b/README
@@ -1,3 +1,9 @@
+This directory contains the core Android SELinux policy configuration.
+It defines the domains and types for the AOSP services and apps common to
+all devices.  Device-specific policy should be placed under a
+separate device/<vendor>/<board>/sepolicy subdirectory and linked
+into the policy build as described below.
+
 Policy Generation:
 
 Additional, per device, policy files can be added into the
diff --git a/domain.te b/domain.te
index 731e0c4..1e3b2fb 100644
--- a/domain.te
+++ b/domain.te
@@ -362,3 +362,7 @@
 # that over time, the kernel global tables used to implement SysV IPCs will fill
 # up.
 neverallow domain domain:{ shm sem msg msgq } *;
+
+# Do not mount on top of symlinks, fifos, or sockets.
+# Feature parity with Chromium LSM.
+neverallow domain { file_type fs_type dev_type }:{ lnk_file fifo_file sock_file } mounton;
diff --git a/seapp_contexts b/seapp_contexts
index 4469b75..8b2b59c 100644
--- a/seapp_contexts
+++ b/seapp_contexts
@@ -5,7 +5,6 @@
 #	seinfo (string)
 #	name (string)
 #	path (string)
-#	sebool (string)
 # isSystemServer=true can only be used once.
 # An unspecified isSystemServer defaults to false.
 # isOwner=true will only match for the owner/primary user.
@@ -27,7 +26,6 @@
 #	  (6) Specified seinfo= string before unspecified seinfo= string.
 #	  (7) Specified name= string before unspecified name= string.
 #	  (8) Specified path= string before unspecified path= string.
-#	  (9) Specified sebool= string before unspecified sebool= string.
 #
 # Outputs:
 #	domain (string)
diff --git a/tools/check_seapp.c b/tools/check_seapp.c
index af780a3..d5d15b0 100644
--- a/tools/check_seapp.c
+++ b/tools/check_seapp.c
@@ -36,6 +36,12 @@
 	map_matched
 };
 
+const char *map_match_str[] = {
+	"do not match",
+	"match on all inputs",
+	"match on everything"
+};
+
 /**
  * Whether or not the "key" from a key vaue pair is considered an
  * input or an output.
@@ -126,9 +132,6 @@
 /** Set to !0 to enable verbose logging */
 static int logging_verbose = 0;
 
-/** set to !0 to enable strict checking of duplicate entries */
-static int is_strict = 0;
-
 /** file handle to the output file */
 static FILE *output_file = NULL;
 
@@ -162,7 +165,6 @@
                 { .name = "seinfo",         .type = dt_string, .dir = dir_in,  .data = NULL },
                 { .name = "name",           .type = dt_string, .dir = dir_in,  .data = NULL },
                 { .name = "path",           .type = dt_string, .dir = dir_in,  .data = NULL },
-                { .name = "sebool",         .type = dt_string, .dir = dir_in,  .data = NULL },
                 /*Outputs*/
                 { .name = "domain",         .type = dt_string, .dir = dir_out, .data = NULL },
                 { .name = "type",           .type = dt_string, .dir = dir_out, .data = NULL },
@@ -245,11 +247,9 @@
 
 	int rc = 1;
 	int ret = 1;
-	int resp;
 	char *key = m->name;
 	char *value = m->data;
 	data_type type = m->type;
-	sepol_bool_key_t *se_key;
 
 	log_info("Validating %s=%s\n", key, value);
 
@@ -281,34 +281,6 @@
 	if (!pol.policy_file) {
 		goto out;
 	}
-	else if (!strcasecmp(key, "sebool")) {
-
-		ret = sepol_bool_key_create(pol.handle, value, &se_key);
-		if (ret < 0) {
-			log_error("Could not create selinux boolean key, error: %s\n",
-					strerror(errno));
-			rc = 0;
-			goto out;
-		}
-
-		ret = sepol_bool_exists(pol.handle, pol.db, se_key, &resp);
-		if (ret < 0) {
-			log_error("Could not check selinux boolean, error: %s\n",
-					strerror(errno));
-			rc = 0;
-			sepol_bool_key_free(se_key);
-			goto out;
-		}
-
-		if(!resp) {
-			log_error("Could not find selinux boolean \"%s\" on line: %d in file: %s\n",
-					value, lineno, out_file_name);
-			rc = 0;
-			sepol_bool_key_free(se_key);
-			goto out;
-		}
-		sepol_bool_key_free(se_key);
-	}
 	else if (!strcasecmp(key, "type") || !strcasecmp(key, "domain")) {
 
 		if(!check_type(pol.db, value)) {
@@ -521,6 +493,10 @@
 	rule_map *new_map = NULL;
 	kvp *k = NULL;
 	key_map *r = NULL, *x = NULL;
+	bool seen[KVP_NUM_OF_RULES];
+
+	for (i = 0; i < KVP_NUM_OF_RULES; i++)
+		seen[i] = false;
 
 	new_map = calloc(1, (num_of_keys * sizeof(key_map)) + sizeof(rule_map));
 	if (!new_map)
@@ -546,6 +522,12 @@
 				continue;
 			}
 
+			if (seen[j]) {
+					log_error("Duplicated key: %s\n", k->key);
+					goto err;
+			}
+			seen[j] = true;
+
 			memcpy(r, x, sizeof(key_map));
 
 			/* Assign rule map value to one from file */
@@ -609,7 +591,7 @@
 			free_kvp(k);
 		}
 	}
-	exit(EXIT_FAILURE);
+	return NULL;
 }
 
 /**
@@ -622,7 +604,6 @@
 		        "and allows later declarations to override previous ones on a match.\n"
 		        "Options:\n"
 		        "-h - print this help message\n"
-			"-s - enable strict checking of duplicates. This causes the program to exit on a duplicate entry with a non-zero exit status\n"
 		        "-v - enable verbose debugging informations\n"
 		        "-p policy file - specify policy file for strict checking of output selectors against the policy\n"
 		        "-o output file - specify output file, default is stdout\n");
@@ -722,9 +703,6 @@
 		case 'p':
 			pol.policy_file_name = optarg;
 			break;
-		case 's':
-			is_strict = 1;
-			break;
 		case 'v':
 			log_set_verbose();
 			break;
@@ -822,7 +800,6 @@
 	ENTRY *f;
 	hash_entry *entry;
 	hash_entry *tmp;
-	char *preserved_key;
 
 	e.key = rm->key;
 
@@ -839,41 +816,12 @@
 		log_info("Existing entry found!\n");
 		tmp = (hash_entry *)f->data;
 		cmp = rule_map_cmp(rm, tmp->r);
-		log_info("Comparing on rule map ret: %d\n", cmp);
-		/* Override be freeing the old rule map and updating
-		   the pointer */
-		if(cmp != map_matched) {
-
-			/*
-			 * DO NOT free key pointers given to the hash map, instead
-			 * free the new key. The ordering here is critical!
-			 */
-			preserved_key = tmp->r->key;
-			rule_map_free(tmp->r, rule_map_preserve_key);
-/*  hdestroy() frees comparsion keys for non glibc */
-#ifdef __GLIBC__
-			free(rm->key);
-#endif
-			rm->key = preserved_key;
-			tmp->r = rm;
-		}
-		/* Duplicate */
-		else {
-			/* if is_strict is set, then don't allow duplicates */
-			if(is_strict) {
-				log_error("Duplicate line detected in file: %s\n"
-					"Lines %d and %d match!\n",
-					out_file_name, tmp->r->lineno, rm->lineno);
-				rule_map_free(rm, rule_map_destroy_key);
-				goto err;
-			}
-
-			/* Allow duplicates, just drop the entry*/
-			log_info("Duplicate line detected in file: %s\n"
-					"Lines %d and %d match!\n",
-					out_file_name, tmp->r->lineno, rm->lineno);
-			rule_map_free(rm, rule_map_destroy_key);
-		}
+		log_error("Duplicate line detected in file: %s\n"
+			  "Lines %d and %d %s!\n",
+			  out_file_name, tmp->r->lineno, rm->lineno,
+			  map_match_str[cmp]);
+		rule_map_free(rm, rule_map_destroy_key);
+		goto err;
 	}
 	/* It wasn't found, just add the rule map to the table */
 	else {
@@ -967,6 +915,8 @@
 		} /*End token parsing */
 
 		rule_map *r = rule_map_new(keys, token_cnt, lineno);
+		if (!r)
+			goto err;
 		rule_add(r);
 
 	} /* End file parsing */
diff --git a/unconfined.te b/unconfined.te
index d9a5b04..559ed59 100644
--- a/unconfined.te
+++ b/unconfined.te
@@ -43,8 +43,8 @@
     tun_socket
 } *;
 allow unconfineddomain domain:key *;
-allow unconfineddomain {fs_type -contextmount_type -sdcard_type}:{ dir lnk_file sock_file fifo_file } ~relabelto;
-allow unconfineddomain dev_type:{ dir lnk_file sock_file fifo_file } ~relabelto;
+allow unconfineddomain {fs_type -contextmount_type -sdcard_type}:{ dir lnk_file sock_file fifo_file } ~{ relabelto mounton };
+allow unconfineddomain dev_type:{ dir lnk_file sock_file fifo_file } ~{ relabelto mounton };
 allow unconfineddomain {
     file_type
     -keystore_data_file
@@ -55,7 +55,7 @@
     -shell_data_file
     -app_data_file
     -unlabeled
-}:{ dir lnk_file sock_file fifo_file } ~relabelto;
+}:{ dir lnk_file sock_file fifo_file } ~{ relabelto mounton };
 allow unconfineddomain exec_type:dir r_dir_perms;
 allow unconfineddomain exec_type:file { r_file_perms execute };
 allow unconfineddomain exec_type:lnk_file r_file_perms;