diff options
Diffstat (limited to 'host')
11 files changed, 229 insertions, 32 deletions
diff --git a/host/commands/process_sandboxer/Android.bp b/host/commands/process_sandboxer/Android.bp index a685a7194..d56459ed2 100644 --- a/host/commands/process_sandboxer/Android.bp +++ b/host/commands/process_sandboxer/Android.bp @@ -26,8 +26,10 @@ cc_binary_host { srcs: [ "main.cpp", "policies.cpp", + "policies/baseline.cpp", "policies/kernel_log_monitor.cpp", "policies/logcat_receiver.cpp", + "policies/process_sandboxer_test_hello_world.cpp", ], shared_libs: ["sandboxed_api_sandbox2"], static_libs: [ @@ -43,3 +45,26 @@ cc_binary_host { }, }, } + +cc_test_host { + name: "process_sandboxer_test", + defaults: ["cuttlefish_buildhost_only"], + srcs: ["process_sandboxer_test.cpp"], + // When running `atest --host process_sandboxer_test`, these are only + // refreshed after running `m installclean`. + data_bins: [ + "process_sandboxer", + "process_sandboxer_test_hello_world", + ], + static_libs: [ + "libbase", + "libcuttlefish_fs", + "libcuttlefish_utils", + "liblog", + ], + team: "trendy_team_cloud_android", + // TODO(schuffelen): See if this is possible to enable on CI + test_options: { + unit_test: false, + }, +} diff --git a/host/commands/process_sandboxer/main.cpp b/host/commands/process_sandboxer/main.cpp index 2ddcfb5f3..78e68d8e0 100644 --- a/host/commands/process_sandboxer/main.cpp +++ b/host/commands/process_sandboxer/main.cpp @@ -17,7 +17,9 @@ #include <stdlib.h> #include <memory> +#include <optional> #include <string> +#include <string_view> #include <vector> #include "absl/flags/flag.h" @@ -46,13 +48,19 @@ using sapi::file::JoinPath; namespace cuttlefish { +static std::optional<std::string_view> FromEnv(const std::string& name) { + auto value = getenv(name.c_str()); + return value == NULL ? std::optional<std::string_view>() : value; +} + int ProcessSandboxerMain(int argc, char** argv) { absl::InitializeLog(); auto args = absl::ParseCommandLine(argc, argv); HostInfo host; host.artifacts_path = CleanPath(absl::GetFlag(FLAGS_host_artifacts_path)); - host.cuttlefish_config_path = CleanPath(getenv(kCuttlefishConfigEnvVarName)); + host.cuttlefish_config_path = + CleanPath(FromEnv(kCuttlefishConfigEnvVarName).value_or("")); host.log_dir = CleanPath(absl::GetFlag(FLAGS_log_dir)); setenv("LD_LIBRARY_PATH", JoinPath(host.artifacts_path, "lib64").c_str(), 1); diff --git a/host/commands/process_sandboxer/policies.cpp b/host/commands/process_sandboxer/policies.cpp index f9777e8c3..e2339967f 100644 --- a/host/commands/process_sandboxer/policies.cpp +++ b/host/commands/process_sandboxer/policies.cpp @@ -37,6 +37,11 @@ std::unique_ptr<sandbox2::Policy> PolicyForExecutable( builders[JoinPath(host.artifacts_path, "bin", "logcat_receiver")] = LogcatReceiverPolicy; + // TODO(schuffelen): Don't include test policies in the production impl + builders[JoinPath(host.artifacts_path, "testcases", "process_sandboxer_test", + "x86_64", "process_sandboxer_test_hello_world")] = + HelloWorldPolicy; + if (auto it = builders.find(executable); it != builders.end()) { return (it->second)(host).BuildOrDie(); } else { diff --git a/host/commands/process_sandboxer/policies.h b/host/commands/process_sandboxer/policies.h index 0f38b2a50..aa0ffc9dc 100644 --- a/host/commands/process_sandboxer/policies.h +++ b/host/commands/process_sandboxer/policies.h @@ -29,9 +29,14 @@ struct HostInfo { std::string log_dir; }; +sandbox2::PolicyBuilder BaselinePolicy(const HostInfo&, std::string_view exe); + sandbox2::PolicyBuilder KernelLogMonitorPolicy(const HostInfo&); sandbox2::PolicyBuilder LogcatReceiverPolicy(const HostInfo&); +// Testing policies +sandbox2::PolicyBuilder HelloWorldPolicy(const HostInfo&); + std::unique_ptr<sandbox2::Policy> PolicyForExecutable( const HostInfo& host_info, std::string_view executable_path); diff --git a/host/commands/process_sandboxer/policies/baseline.cpp b/host/commands/process_sandboxer/policies/baseline.cpp new file mode 100644 index 000000000..732fe3351 --- /dev/null +++ b/host/commands/process_sandboxer/policies/baseline.cpp @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2024 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 "host/commands/process_sandboxer/policies.h" + +#include "sandboxed_api/sandbox2/policybuilder.h" +#include "sandboxed_api/util/path.h" + +using sapi::file::JoinPath; + +namespace cuttlefish { + +sandbox2::PolicyBuilder BaselinePolicy(const HostInfo& host, + std::string_view exe) { + return sandbox2::PolicyBuilder() + .AddLibrariesForBinary(exe, JoinPath(host.artifacts_path, "lib64")) + // For dynamic linking and memory allocation + .AllowDynamicStartup() + .AllowExit() + .AllowGetPIDs() + .AllowGetRandom() + .AllowMmap() + .AllowReadlink() + .AllowRestartableSequences(sandbox2::PolicyBuilder::kAllowSlowFences) + .AllowWrite(); +} + +} // namespace cuttlefish diff --git a/host/commands/process_sandboxer/policies/kernel_log_monitor.cpp b/host/commands/process_sandboxer/policies/kernel_log_monitor.cpp index 97b1611d4..fe9ceddac 100644 --- a/host/commands/process_sandboxer/policies/kernel_log_monitor.cpp +++ b/host/commands/process_sandboxer/policies/kernel_log_monitor.cpp @@ -28,29 +28,15 @@ namespace cuttlefish { sandbox2::PolicyBuilder KernelLogMonitorPolicy(const HostInfo& host) { auto exe = JoinPath(host.artifacts_path, "bin", "kernel_log_monitor"); - auto lib64 = JoinPath(host.artifacts_path, "lib64"); - return sandbox2::PolicyBuilder() - .AddDirectory(lib64) + return BaselinePolicy(host, exe) .AddDirectory(host.log_dir, /* is_ro= */ false) .AddFile(host.cuttlefish_config_path) - .AddLibrariesForBinary(exe, lib64) - // For dynamic linking - .AddPolicyOnSyscall(__NR_prctl, - {ARG_32(0), JEQ32(PR_CAPBSET_READ, ALLOW)}) - .AllowDynamicStartup() - .AllowGetPIDs() - .AllowGetRandom() .AllowHandleSignals() - .AllowMmap() .AllowOpen() .AllowRead() - .AllowReadlink() - .AllowRestartableSequences(sandbox2::PolicyBuilder::kAllowSlowFences) .AllowSelect() .AllowSafeFcntl() - .AllowSyscall(__NR_tgkill) - .AllowTCGETS() - .AllowWrite(); + .AllowTCGETS(); } } // namespace cuttlefish diff --git a/host/commands/process_sandboxer/policies/logcat_receiver.cpp b/host/commands/process_sandboxer/policies/logcat_receiver.cpp index b761144eb..c03e4d6fa 100644 --- a/host/commands/process_sandboxer/policies/logcat_receiver.cpp +++ b/host/commands/process_sandboxer/policies/logcat_receiver.cpp @@ -28,27 +28,13 @@ namespace cuttlefish { sandbox2::PolicyBuilder LogcatReceiverPolicy(const HostInfo& host) { auto exe = JoinPath(host.artifacts_path, "bin", "logcat_receiver"); - auto lib64 = JoinPath(host.artifacts_path, "lib64"); - return sandbox2::PolicyBuilder() - .AddDirectory(lib64) + return BaselinePolicy(host, exe) .AddDirectory(host.log_dir, /* is_ro= */ false) .AddFile(host.cuttlefish_config_path) - .AddLibrariesForBinary(exe, lib64) - // For dynamic linking - .AddPolicyOnSyscall(__NR_prctl, - {ARG_32(0), JEQ32(PR_CAPBSET_READ, ALLOW)}) - .AllowDynamicStartup() - .AllowExit() - .AllowGetPIDs() - .AllowGetRandom() .AllowHandleSignals() - .AllowMmap() .AllowOpen() .AllowRead() - .AllowReadlink() - .AllowRestartableSequences(sandbox2::PolicyBuilder::kAllowSlowFences) .AllowSafeFcntl() - .AllowSyscall(__NR_tgkill) .AllowWrite(); } diff --git a/host/commands/process_sandboxer/policies/process_sandboxer_test_hello_world.cpp b/host/commands/process_sandboxer/policies/process_sandboxer_test_hello_world.cpp new file mode 100644 index 000000000..2a9fe70c3 --- /dev/null +++ b/host/commands/process_sandboxer/policies/process_sandboxer_test_hello_world.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2024 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 "host/commands/process_sandboxer/policies.h" + +#include "sandboxed_api/sandbox2/policybuilder.h" +#include "sandboxed_api/util/path.h" + +using sapi::file::JoinPath; + +namespace cuttlefish { + +sandbox2::PolicyBuilder HelloWorldPolicy(const HostInfo& host) { + auto exe = + JoinPath(host.artifacts_path, "testcases", "process_sandboxer_test", + "x86_64", "process_sandboxer_test_hello_world"); + return BaselinePolicy(host, exe); +} + +} // namespace cuttlefish diff --git a/host/commands/process_sandboxer/process_sandboxer_test.cpp b/host/commands/process_sandboxer/process_sandboxer_test.cpp new file mode 100644 index 000000000..0043a068e --- /dev/null +++ b/host/commands/process_sandboxer/process_sandboxer_test.cpp @@ -0,0 +1,70 @@ +// +// Copyright (C) 2024 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 <libgen.h> +#include <stdlib.h> + +#include <string> +#include <string_view> + +#include <fmt/format.h> +#include <gtest/gtest.h> + +#include "common/libs/utils/subprocess.h" + +namespace cuttlefish { + +static std::string ExecutableSelfPath() { + char exe_path[PATH_MAX + 1]; + auto path_size = readlink("/proc/self/exe", exe_path, PATH_MAX); + CHECK_GT(path_size, 0) << strerror(errno); + CHECK_LE(path_size, PATH_MAX); + exe_path[path_size + 1] = '\0'; // Readlink does not append a null terminator + char abs_path[PATH_MAX]; + char* real = realpath(exe_path, abs_path); + CHECK(real) << strerror(errno); + return real; +} + +static std::string HostArtifactsDir() { + auto path = ExecutableSelfPath(); + path = dirname(path.data()); // x86_64 + path = dirname(path.data()); // <test case> + path = dirname(path.data()); // testcases + path = dirname(path.data()); // linux-86 + return path; +} + +static std::string ExecutablePath(std::string_view exe) { + auto dir_path = ExecutableSelfPath(); + dir_path = dirname(dir_path.data()); + return fmt::format("{}/{}", dir_path, exe); +} + +TEST(SandboxExecutable, HelloWorld) { + Command executable(ExecutablePath("process_sandboxer_test_hello_world")); + auto opt = SubprocessOptions().SandboxArguments({ + ExecutablePath("process_sandboxer"), + "--host_artifacts_path=" + HostArtifactsDir(), + }); + + std::string in, out, err; + int code = RunWithManagedStdio(std::move(executable), &in, &out, &err, opt); + + EXPECT_EQ(code, 0) << err; + EXPECT_EQ(out, "Allocated vector with 100 members\n"); +} + +} // namespace cuttlefish diff --git a/host/commands/process_sandboxer/test_executables/Android.bp b/host/commands/process_sandboxer/test_executables/Android.bp new file mode 100644 index 000000000..c9feefb5e --- /dev/null +++ b/host/commands/process_sandboxer/test_executables/Android.bp @@ -0,0 +1,25 @@ +// Copyright (C) 2024 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. + +package { + default_applicable_licenses: ["Android-Apache-2.0"], +} + +// Executables intended to validate process_sandboxer itself + +cc_binary_host { + name: "process_sandboxer_test_hello_world", + defaults: ["cuttlefish_buildhost_only"], + srcs: ["process_sandboxer_test_hello_world.cpp"], +} diff --git a/host/commands/process_sandboxer/test_executables/process_sandboxer_test_hello_world.cpp b/host/commands/process_sandboxer/test_executables/process_sandboxer_test_hello_world.cpp new file mode 100644 index 000000000..b1cd1bf3b --- /dev/null +++ b/host/commands/process_sandboxer/test_executables/process_sandboxer_test_hello_world.cpp @@ -0,0 +1,13 @@ +#include <iostream> +#include <string> +#include <vector> + +int main() { + // Exercise dynamic memory allocation + std::vector<std::string> test_vec; + for (size_t i = 0; i < 100; i++) { + test_vec.emplace_back(std::to_string(i)); + } + // Exercise writing to stderr + std::cout << "Allocated vector with " << test_vec.size() << " members\n"; +} |