Allow media.codec and media.extractor to specify two policy files.

Bug: Bug: 34723744
Test: Unit tests.
Test: media.codec, media.extractor start, have Seccomp.
Test: cat /proc/`pgrep .codec`/status | grep Seccomp
      Seccomp:    2
Test: cat /proc/`pgrep .extractor`/status | grep Seccomp
      Seccomp:    2
Change-Id: If5c3dcc934f5d76bd32859b2f7b7ecb772a56303
diff --git a/services/minijail/Android.mk b/services/minijail/Android.mk
index 836fad3..3e63f97 100644
--- a/services/minijail/Android.mk
+++ b/services/minijail/Android.mk
@@ -7,3 +7,11 @@
 LOCAL_SHARED_LIBRARIES := libbase libminijail
 LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
 include $(BUILD_SHARED_LIBRARY)
+
+
+# Unit tests.
+include $(CLEAR_VARS)
+LOCAL_MODULE := libavservices_minijail_unittest
+LOCAL_SRC_FILES := minijail.cpp av_services_minijail_unittest.cpp
+LOCAL_SHARED_LIBRARIES := libbase libminijail
+include $(BUILD_NATIVE_TEST)
diff --git a/services/minijail/av_services_minijail_unittest.cpp b/services/minijail/av_services_minijail_unittest.cpp
new file mode 100644
index 0000000..31313f8
--- /dev/null
+++ b/services/minijail/av_services_minijail_unittest.cpp
@@ -0,0 +1,58 @@
+// Copyright (C) 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <string>
+
+#include <android-base/file.h>
+#include <android-base/unique_fd.h>
+
+#include <gtest/gtest.h>
+
+#include "minijail.h"
+
+class WritePolicyTest : public ::testing::Test
+{
+  protected:
+    const std::string base_policy_ =
+        "read: 1\n"
+        "write: 1\n"
+        "rt_sigreturn: 1\n"
+        "exit: 1\n";
+
+    const std::string additional_policy_ =
+        "mmap: 1\n"
+        "munmap: 1\n";
+
+    const std::string full_policy_ = base_policy_ + std::string("\n") + additional_policy_;
+};
+
+TEST_F(WritePolicyTest, OneFile)
+{
+    std::string final_string;
+    android::base::unique_fd fd(android::WritePolicyToPipe(base_policy_, std::string()));
+    EXPECT_LE(0, fd.get());
+    bool success = android::base::ReadFdToString(fd.get(), &final_string);
+    EXPECT_TRUE(success);
+    EXPECT_EQ(final_string, base_policy_);
+}
+
+TEST_F(WritePolicyTest, TwoFiles)
+{
+    std::string final_string;
+    android::base::unique_fd fd(android::WritePolicyToPipe(base_policy_, additional_policy_));
+    EXPECT_LE(0, fd.get());
+    bool success = android::base::ReadFdToString(fd.get(), &final_string);
+    EXPECT_TRUE(success);
+    EXPECT_EQ(final_string, full_policy_);
+}
diff --git a/services/minijail/minijail.cpp b/services/minijail/minijail.cpp
index 53ff858..7b61ae8 100644
--- a/services/minijail/minijail.cpp
+++ b/services/minijail/minijail.cpp
@@ -17,6 +17,7 @@
 #include <sys/types.h>
 #include <unistd.h>
 
+#include <android-base/file.h>
 #include <android-base/logging.h>
 #include <android-base/unique_fd.h>
 
@@ -27,30 +28,71 @@
 
 namespace android {
 
-int SetUpMinijail(const std::string& seccomp_policy_path)
+int WritePolicyToPipe(const std::string& base_policy_content,
+                      const std::string& additional_policy_content)
+{
+    int pipefd[2];
+    if (pipe(pipefd) == -1) {
+        PLOG(ERROR) << "pipe() failed";
+        return -1;
+    }
+
+    base::unique_fd write_end(pipefd[1]);
+    std::string content = base_policy_content;
+
+    if (additional_policy_content.length() > 0) {
+        content += "\n";
+        content += additional_policy_content;
+    }
+
+    if (!base::WriteStringToFd(content, write_end.get())) {
+        LOG(ERROR) << "Could not write policy to fd";
+        return -1;
+    }
+
+    return pipefd[0];
+}
+
+int SetUpMinijail(const std::string& base_policy_path, const std::string& additional_policy_path)
 {
     // No seccomp policy defined for this architecture.
-    if (access(seccomp_policy_path.c_str(), R_OK) == -1) {
+    if (access(base_policy_path.c_str(), R_OK) == -1) {
         LOG(WARNING) << "No seccomp policy defined for this architecture.";
         return 0;
     }
 
-    int policy_fd = TEMP_FAILURE_RETRY(open(seccomp_policy_path.c_str(), O_RDONLY | O_CLOEXEC));
-    if (policy_fd == -1) {
-        PLOG(FATAL) << "Failed to open seccomp policy file '" << seccomp_policy_path << "'";
+    std::string base_policy_content;
+    std::string additional_policy_content;
+    if (!base::ReadFileToString(base_policy_path, &base_policy_content,
+                                false /* follow_symlinks */)) {
+        LOG(ERROR) << "Could not read base policy file '" << base_policy_path << "'";
+        return -1;
+    }
+
+    if (additional_policy_path.length() > 0 &&
+        !base::ReadFileToString(additional_policy_path, &additional_policy_content,
+                                false /* follow_symlinks */)) {
+        LOG(WARNING) << "Could not read additional policy file '" << additional_policy_path << "'";
+        additional_policy_content = std::string();
+    }
+
+    base::unique_fd policy_fd(WritePolicyToPipe(base_policy_content, additional_policy_content));
+    if (policy_fd.get() == -1) {
+        LOG(ERROR) << "Could not write seccomp policy to fd";
+        return -1;
     }
 
     ScopedMinijail jail{minijail_new()};
     if (!jail) {
-        LOG(WARNING) << "Failed to create minijail.";
+        LOG(ERROR) << "Failed to create minijail.";
         return -1;
     }
 
     minijail_no_new_privs(jail.get());
     minijail_log_seccomp_filter_failures(jail.get());
     minijail_use_seccomp_filter(jail.get());
-    // This closes |policy_fd|.
-    minijail_parse_seccomp_filters_from_fd(jail.get(), policy_fd);
+    // Transfer ownership of |policy_fd|.
+    minijail_parse_seccomp_filters_from_fd(jail.get(), policy_fd.release());
     minijail_enter(jail.get());
     return 0;
 }
diff --git a/services/minijail/minijail.h b/services/minijail/minijail.h
index c7bd399..3d6db37 100644
--- a/services/minijail/minijail.h
+++ b/services/minijail/minijail.h
@@ -18,7 +18,10 @@
 #include <string>
 
 namespace android {
-int SetUpMinijail(const std::string& seccomp_policy_path);
+int WritePolicyToPipe(const std::string& base_policy_content,
+                      const std::string& additional_policy_content);
+int SetUpMinijail(const std::string& base_policy_path,
+                  const std::string& additional_policy_path);
 }
 
 #endif  // AV_SERVICES_MINIJAIL_MINIJAIL