Merge "sepolicy:  remove block_device access from install_recovery"
diff --git a/adbd.te b/adbd.te
index f5cebd2..c80dba4 100644
--- a/adbd.te
+++ b/adbd.te
@@ -80,3 +80,5 @@
 allow adbd kernel:security read_policy;
 
 allow adbd surfaceflinger_service:service_manager find;
+allow adbd bootchart_data_file:dir search;
+allow adbd bootchart_data_file:file r_file_perms;
diff --git a/file.te b/file.te
index ae1079c..a017383 100644
--- a/file.te
+++ b/file.te
@@ -79,6 +79,8 @@
 type gps_data_file, file_type, data_file_type;
 # /data/property
 type property_data_file, file_type, data_file_type;
+# /data/bootchart
+type bootchart_data_file, file_type, data_file_type;
 
 # /data/misc subdirectories
 type adb_keys_file, file_type, data_file_type;
diff --git a/file_contexts b/file_contexts
index 04fa4c7..d510476 100644
--- a/file_contexts
+++ b/file_contexts
@@ -227,6 +227,9 @@
 /data/misc/wifi/hostapd(/.*)?   u:object_r:wpa_socket:s0
 /data/misc/zoneinfo(/.*)?       u:object_r:zoneinfo_data_file:s0
 
+# Bootchart data
+/data/bootchart(/.*)?		u:object_r:bootchart_data_file:s0
+
 # coredump directory for userdebug/eng devices
 /cores(/.*)?                    u:object_r:coredump_file:s0
 
diff --git a/init.te b/init.te
index 1283ec7..d81f5af 100644
--- a/init.te
+++ b/init.te
@@ -1,5 +1,5 @@
 # init switches to init domain (via init.rc).
-type init, domain;
+type init, domain, mlstrustedsubject;
 permissive_or_unconfined(init)
 tmpfs_domain(init)
 
@@ -164,6 +164,11 @@
 # Set UID and GID for services.
 allow init self:capability { setuid setgid };
 
+# For bootchart to read the /proc/$pid/cmdline file of each process,
+# we need to have following line to allow init to have access
+# to different domains.
+r_dir_file(init, domain)
+
 # Use setexeccon(), setfscreatecon(), and setsockcreatecon().
 # setexec is for services with seclabel options.
 # setfscreate is for labeling directories and socket files.
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/shell.te b/shell.te
index 6af3717..d31a496 100644
--- a/shell.te
+++ b/shell.te
@@ -64,3 +64,9 @@
 # allow shell to look through /proc/ for ps, top
 allow shell domain:dir { search open read getattr };
 allow shell domain:{ file lnk_file } { open read getattr };
+
+# enable shell domain to read/write files/dirs for bootchart data
+# User will creates the start and stop file via adb shell
+# and read other files created by init process under /data/bootchart
+allow shell bootchart_data_file:dir rw_dir_perms;
+allow shell bootchart_data_file:file create_file_perms;
diff --git a/tools/check_seapp.c b/tools/check_seapp.c
index 90fa0a4..d5d15b0 100644
--- a/tools/check_seapp.c
+++ b/tools/check_seapp.c
@@ -165,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 },
@@ -248,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);
 
@@ -284,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)) {
@@ -524,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)
@@ -549,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 */
@@ -612,7 +591,7 @@
 			free_kvp(k);
 		}
 	}
-	exit(EXIT_FAILURE);
+	return NULL;
 }
 
 /**
@@ -936,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 */