Extend recovery and updater to support setting file security contexts.

Extend minzip, recovery, and updater to set the security context on
files based on the file_contexts configuration included in the package.

Change-Id: Ied379f266a16c64f2b4dca15dc39b98fcce16f29
diff --git a/minzip/Android.mk b/minzip/Android.mk
index b1ee674..6c1d096 100644
--- a/minzip/Android.mk
+++ b/minzip/Android.mk
@@ -11,7 +11,13 @@
 LOCAL_C_INCLUDES += \
 	external/zlib \
 	external/safe-iop/include
-	
+
+ifeq ($(HAVE_SELINUX),true)
+LOCAL_C_INCLUDES += external/libselinux/include
+LOCAL_STATIC_LIBRARIES += libselinux
+LOCAL_CFLAGS += -DHAVE_SELINUX
+endif
+
 LOCAL_MODULE := libminzip
 
 LOCAL_CFLAGS += -Wall
diff --git a/minzip/DirUtil.c b/minzip/DirUtil.c
index 20c89cd..0d49b57 100644
--- a/minzip/DirUtil.c
+++ b/minzip/DirUtil.c
@@ -54,7 +54,8 @@
 
 int
 dirCreateHierarchy(const char *path, int mode,
-        const struct utimbuf *timestamp, bool stripFileName)
+        const struct utimbuf *timestamp, bool stripFileName,
+        struct selabel_handle *sehnd)
 {
     DirStatus ds;
 
@@ -144,7 +145,25 @@
         } else if (ds == DMISSING) {
             int err;
 
+#ifdef HAVE_SELINUX
+            char *secontext = NULL;
+
+            if (sehnd) {
+                selabel_lookup(sehnd, &secontext, cpath, mode);
+                setfscreatecon(secontext);
+            }
+#endif
+
             err = mkdir(cpath, mode);
+
+#ifdef HAVE_SELINUX
+
+            if (secontext) {
+                freecon(secontext);
+                setfscreatecon(NULL);
+            }
+#endif
+
             if (err != 0) {
                 free(cpath);
                 return -1;
diff --git a/minzip/DirUtil.h b/minzip/DirUtil.h
index 5d881f5..1f378b7 100644
--- a/minzip/DirUtil.h
+++ b/minzip/DirUtil.h
@@ -20,6 +20,13 @@
 #include <stdbool.h>
 #include <utime.h>
 
+#ifdef HAVE_SELINUX
+#include <selinux/selinux.h>
+#include <selinux/label.h>
+#else
+struct selabel_handle;
+#endif
+
 /* Like "mkdir -p", try to guarantee that all directories
  * specified in path are present, creating as many directories
  * as necessary.  The specified mode is passed to all mkdir
@@ -34,7 +41,8 @@
  * (usually if some element of path is not a directory).
  */
 int dirCreateHierarchy(const char *path, int mode,
-        const struct utimbuf *timestamp, bool stripFileName);
+        const struct utimbuf *timestamp, bool stripFileName,
+        struct selabel_handle* sehnd);
 
 /* rm -rf <path>
  */
diff --git a/minzip/Zip.c b/minzip/Zip.c
index 46d2f82..54d5d55 100644
--- a/minzip/Zip.c
+++ b/minzip/Zip.c
@@ -930,7 +930,8 @@
 bool mzExtractRecursive(const ZipArchive *pArchive,
                         const char *zipDir, const char *targetDir,
                         int flags, const struct utimbuf *timestamp,
-                        void (*callback)(const char *fn, void *), void *cookie)
+                        void (*callback)(const char *fn, void *), void *cookie,
+                        struct selabel_handle *sehnd)
 {
     if (zipDir[0] == '/') {
         LOGE("mzExtractRecursive(): zipDir must be a relative path.\n");
@@ -1045,7 +1046,7 @@
         if (pEntry->fileName[pEntry->fileNameLen-1] == '/') {
             if (!(flags & MZ_EXTRACT_FILES_ONLY)) {
                 int ret = dirCreateHierarchy(
-                        targetFile, UNZIP_DIRMODE, timestamp, false);
+                        targetFile, UNZIP_DIRMODE, timestamp, false, sehnd);
                 if (ret != 0) {
                     LOGE("Can't create containing directory for \"%s\": %s\n",
                             targetFile, strerror(errno));
@@ -1059,7 +1060,7 @@
              * the containing directory exists.
              */
             int ret = dirCreateHierarchy(
-                    targetFile, UNZIP_DIRMODE, timestamp, true);
+                    targetFile, UNZIP_DIRMODE, timestamp, true, sehnd);
             if (ret != 0) {
                 LOGE("Can't create containing directory for \"%s\": %s\n",
                         targetFile, strerror(errno));
@@ -1113,7 +1114,25 @@
                 /* The entry is a regular file.
                  * Open the target for writing.
                  */
+
+#ifdef HAVE_SELINUX
+                char *secontext = NULL;
+
+                if (sehnd) {
+                    selabel_lookup(sehnd, &secontext, targetFile, UNZIP_FILEMODE);
+                    setfscreatecon(secontext);
+                }
+#endif
+
                 int fd = creat(targetFile, UNZIP_FILEMODE);
+
+#ifdef HAVE_SELINUX
+                if (secontext) {
+                    freecon(secontext);
+                    setfscreatecon(NULL);
+                }
+#endif
+
                 if (fd < 0) {
                     LOGE("Can't create target file \"%s\": %s\n",
                             targetFile, strerror(errno));
diff --git a/minzip/Zip.h b/minzip/Zip.h
index 9f99fba..0b1c9d5 100644
--- a/minzip/Zip.h
+++ b/minzip/Zip.h
@@ -14,6 +14,13 @@
 #include "Hash.h"
 #include "SysUtil.h"
 
+#ifdef HAVE_SELINUX
+#include <selinux/selinux.h>
+#include <selinux/label.h>
+#else
+struct selabel_handle;
+#endif
+
 /*
  * One entry in the Zip archive.  Treat this as opaque -- use accessors below.
  *
@@ -208,6 +215,7 @@
 bool mzExtractRecursive(const ZipArchive *pArchive,
         const char *zipDir, const char *targetDir,
         int flags, const struct utimbuf *timestamp,
-        void (*callback)(const char *fn, void*), void *cookie);
+        void (*callback)(const char *fn, void*), void *cookie,
+        struct selabel_handle *sehnd);
 
 #endif /*_MINZIP_ZIP*/