Run restorecon after init creates a symlink or writes to a file.

Init currently sets the SELinux context on a mkdir but not on
other operations.  This patch modifies it to do so when creating
symlinks, writing to a file, or copying a file.

Test: Built, flashed, and booted.  Added fake init entries and
verified that they received the proper SELinux context.

Change-Id: I836b570fef81d74f3b6c8e7ce0274e94ca7b12d3
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 950a551..f584021 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -65,6 +65,7 @@
 #include "property_service.h"
 #include "reboot.h"
 #include "rlimit_parser.h"
+#include "selinux.h"
 #include "service.h"
 #include "subcontext.h"
 #include "util.h"
@@ -641,8 +642,26 @@
     return Success();
 }
 
+static int MakeSymlink(const std::string& target, const std::string& linkpath) {
+    std::string secontext;
+    // Passing 0 for mode should work.
+    if (SelabelLookupFileContext(linkpath, 0, &secontext) && !secontext.empty()) {
+        setfscreatecon(secontext.c_str());
+    }
+
+    int rc = symlink(target.c_str(), linkpath.c_str());
+
+    if (!secontext.empty()) {
+        int save_errno = errno;
+        setfscreatecon(nullptr);
+        errno = save_errno;
+    }
+
+    return rc;
+}
+
 static Result<Success> do_symlink(const BuiltinArguments& args) {
-    if (symlink(args[1].c_str(), args[2].c_str()) < 0) {
+    if (MakeSymlink(args[1], args[2]) < 0) {
         // The symlink builtin is often used to create symlinks for older devices to be backwards
         // compatible with new paths, therefore we skip reporting this error.
         if (errno == EEXIST && android::base::GetMinimumLogSeverity() > android::base::DEBUG) {
diff --git a/init/util.cpp b/init/util.cpp
index a19a6f3..d80cb1e 100644
--- a/init/util.cpp
+++ b/init/util.cpp
@@ -178,9 +178,26 @@
     return content;
 }
 
+static int OpenFile(const std::string& path, int flags, mode_t mode) {
+    std::string secontext;
+    if (SelabelLookupFileContext(path, mode, &secontext) && !secontext.empty()) {
+        setfscreatecon(secontext.c_str());
+    }
+
+    int rc = open(path.c_str(), flags, mode);
+
+    if (!secontext.empty()) {
+        int save_errno = errno;
+        setfscreatecon(nullptr);
+        errno = save_errno;
+    }
+
+    return rc;
+}
+
 Result<Success> WriteFile(const std::string& path, const std::string& content) {
     android::base::unique_fd fd(TEMP_FAILURE_RETRY(
-        open(path.c_str(), O_WRONLY | O_CREAT | O_NOFOLLOW | O_TRUNC | O_CLOEXEC, 0600)));
+        OpenFile(path, O_WRONLY | O_CREAT | O_NOFOLLOW | O_TRUNC | O_CLOEXEC, 0600)));
     if (fd == -1) {
         return ErrnoError() << "open() failed";
     }