Restore contexts when doing mkdierhier in libtar
Do a restore of loaded file contexts to /data/media directory. This will help denials to be prevented when internal storage is wiped.

Change-Id: Ie49bbfa48d2f3ee4f08376d9c1877b92c051017c
diff --git a/fixPermissions.cpp b/fixPermissions.cpp
index 40ac516..12ce0b5 100644
--- a/fixPermissions.cpp
+++ b/fixPermissions.cpp
@@ -74,18 +74,48 @@
 	struct selinux_opt selinux_options[] = {
 		{ SELABEL_OPT_PATH, "/file_contexts" }
 	};
+
 	selinux_handle = selabel_open(SELABEL_CTX_FILE, selinux_options, 1);
+
 	if (!selinux_handle)
 		printf("No file contexts for SELinux\n");
 	else
 		printf("SELinux contexts loaded from /file_contexts\n");
+
 	d = opendir("/data/data");
+
 	while (( de = readdir(d)) != NULL) {
 		stat(de->d_name, &sb);
 		string f = "/data/data/";
 		f = f + de->d_name;
 		restorecon(f, &sb);
 	}
+	closedir(d);
+	return 0;
+}
+
+int fixPermissions::fixDataInternalContexts(void) {
+	DIR *d;
+	struct dirent *de;
+	struct stat sb;
+	string dir;
+
+	if (TWFunc::Path_Exists("/data/media")) {
+		dir = "/data/media";
+	}
+	else {
+		dir = "/data/media/0";
+	}
+	LOGINFO("Fixing %s contexts\n", dir.c_str());
+	d = opendir(dir.c_str());
+
+	while (( de = readdir(d)) != NULL) {
+		stat(de->d_name, &sb);
+		string f;
+		f = dir + de->d_name;
+		restorecon(f, &sb);
+	}
+	closedir(d);
 	return 0;
 }
 #endif
@@ -173,8 +203,9 @@
 		}
 	}
 	#ifdef HAVE_SELINUX
-	gui_print("Fixing /data/data contexts.\n");
+	gui_print("Fixing /data/data/ contexts.\n");
 	fixDataDataContexts();
+	fixDataInternalContexts();
 	#endif
 	gui_print("Done fixing permissions.\n");
 	return 0;
diff --git a/fixPermissions.hpp b/fixPermissions.hpp
index 6439dac..48a5207 100644
--- a/fixPermissions.hpp
+++ b/fixPermissions.hpp
@@ -17,6 +17,7 @@
 class fixPermissions {
 	public:
 		int fixPerms(bool enable_debug, bool remove_data_for_missing_apps);
+		int fixDataInternalContexts(void);
 
 	private:
 		int pchown(std::string fn, int puid, int pgid);
@@ -28,8 +29,8 @@
 		int fixDataApps();
 		int fixAllFiles(string directory, int gid, int uid, string file_perms);
 		int fixDataData(string dataDir);
-		int fixDataDataContexts(void);
 		int restorecon(std::string entry, struct stat *sb);
+		int fixDataDataContexts(void);
 
 		struct package {
 			string pkgName;
@@ -45,6 +46,6 @@
 		bool remove_data;
 		bool multi_user;
 		package* head;
-		package* temp;		
+		package* temp;
 		string packageFile;
 };
diff --git a/libtar/extract.c b/libtar/extract.c
index 8081aa2..d9ab788 100644
--- a/libtar/extract.c
+++ b/libtar/extract.c
@@ -159,11 +159,14 @@
 	if((t->options & TAR_STORE_SELINUX) && t->th_buf.selinux_context != NULL)
 	{
 #ifdef DEBUG
-		printf("    Restoring SELinux context %s to file %s\n", t->th_buf.selinux_context, realname);
+		printf("   Restoring SELinux context %s to file %s\n", t->th_buf.selinux_context, realname);
 #endif
 		if (lsetfilecon(realname, t->th_buf.selinux_context) < 0) {
 			fprintf(stderr, "Failed to restore SELinux context %s!\n", strerror(errno));
 		}
+		if (lsetfilecon(dirname(realname), t->th_buf.selinux_context) < 0) {
+			fprintf(stderr, "Failed to restore SELinux context %s!\n", strerror(errno));
+		}
 	}
 #endif
 
diff --git a/libtar/wrapper.c b/libtar/wrapper.c
index dab7e00..708c845 100644
--- a/libtar/wrapper.c
+++ b/libtar/wrapper.c
@@ -80,12 +80,6 @@
 		       "\"%s\")\n", buf);
 #endif
 		printf("item name: '%s'\n", filename);
-		/*
-		if (strcmp(filename, "/") == 0) {
-			printf("skipping /\n");
-			continue;
-		}
-		*/
 		if (tar_extract_file(t, buf, prefix) != 0)
 			return -1;
 	}
diff --git a/partition.cpp b/partition.cpp
index 95f6bca..974f7e4 100644
--- a/partition.cpp
+++ b/partition.cpp
@@ -40,6 +40,7 @@
 #include "twrpDigest.hpp"
 #include "twrpTar.hpp"
 #include "twrpDU.hpp"
+#include "fixPermissions.hpp"
 extern "C" {
 	#include "mtdutils/mtdutils.h"
 	#include "mtdutils/mounts.h"
@@ -1511,6 +1512,9 @@
 
 bool TWPartition::Wipe_Data_Without_Wiping_Media() {
 	string dir;
+	#ifdef HAVE_SELINUX
+	fixPermissions perms;
+	#endif
 
 	// This handles wiping data on devices with "sdcard" in /data/media
 	if (!Mount(true))
@@ -1541,6 +1545,10 @@
 		}
 		closedir(d);
 
+		#ifdef HAVE_SELINUX
+		perms.fixDataInternalContexts();
+		#endif
+
 		gui_print("Done.\n");
 		return true;
 	}
@@ -1811,12 +1819,19 @@
 void TWPartition::Recreate_Media_Folder(void) {
 	string Command;
 
+	#ifdef HAVE_SELINUX
+	fixPermissions perms;
+	#endif
+
 	if (!Mount(true)) {
 		LOGERR("Unable to recreate /data/media folder.\n");
 	} else if (!TWFunc::Path_Exists("/data/media")) {
 		PartitionManager.Mount_By_Path(Symlink_Mount_Point, true);
 		LOGINFO("Recreating /data/media folder.\n");
 		mkdir("/data/media", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); 
+		#ifdef HAVE_SELINUX
+		perms.fixDataInternalContexts();
+		#endif
 		PartitionManager.UnMount_By_Path(Symlink_Mount_Point, true);
 	}
 }