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