diff options
-rw-r--r-- | artd/Android.bp | 27 | ||||
-rw-r--r-- | artd/artd.cc | 5 | ||||
-rw-r--r-- | artd/artd.h | 13 | ||||
-rw-r--r-- | artd/artd_fuzzer.cc | 31 | ||||
-rw-r--r-- | artd/artd_main.cc | 31 | ||||
-rw-r--r-- | artd/artd_test.cc | 3 | ||||
-rw-r--r-- | build/Android.gtest.mk | 2 | ||||
-rw-r--r-- | build/apex/Android.bp | 2 | ||||
-rw-r--r-- | build/apex/art.rc | 27 | ||||
-rwxr-xr-x | build/apex/art_apex_test.py | 2 | ||||
-rw-r--r-- | dexopt_chroot_setup/Android.bp | 111 | ||||
-rw-r--r-- | dexopt_chroot_setup/README.md | 10 | ||||
-rw-r--r-- | dexopt_chroot_setup/binder/Android.bp | 56 | ||||
-rw-r--r-- | dexopt_chroot_setup/binder/com/android/server/art/IDexoptChrootSetup.aidl | 21 | ||||
-rw-r--r-- | dexopt_chroot_setup/dexopt_chroot_setup.cc | 52 | ||||
-rw-r--r-- | dexopt_chroot_setup/dexopt_chroot_setup.h | 35 | ||||
-rw-r--r-- | dexopt_chroot_setup/dexopt_chroot_setup_fuzzer.cc | 31 | ||||
-rw-r--r-- | dexopt_chroot_setup/dexopt_chroot_setup_main.cc | 43 | ||||
-rw-r--r-- | dexopt_chroot_setup/dexopt_chroot_setup_test.cc | 41 | ||||
-rw-r--r-- | libarttools/art_exec.cc | 11 | ||||
-rwxr-xr-x | test/utils/regen-test-files | 1 |
21 files changed, 547 insertions, 8 deletions
diff --git a/artd/Android.bp b/artd/Android.bp index 5449cd90a6..8b74981e2f 100644 --- a/artd/Android.bp +++ b/artd/Android.bp @@ -105,3 +105,30 @@ art_cc_test { ], test_config_template: "art_standalone_artd_tests.xml", } + +cc_fuzz { + name: "artd_fuzzer", + defaults: [ + "service_fuzzer_defaults", + "art_module_source_build_defaults", + "artd_defaults", + // Fuzzer is on a special variant, different from the APEX variant. When + // linking against "libdexfile" as a shared library, the build system + // incorrectly picks the platform variant, which only exposes system + // APIs. As a workaround, we link against "libdexfile" as a static + // library. + "libdexfile_static_defaults", + ], + host_supported: true, + srcs: ["artd_fuzzer.cc"], + shared_libs: [ + "libart", + "libartbase", + "liblog", + ], + fuzz_config: { + cc: [ + "art-module-team@google.com", + ], + }, +} diff --git a/artd/artd.cc b/artd/artd.cc index f1fc558306..c44013b740 100644 --- a/artd/artd.cc +++ b/artd/artd.cc @@ -123,6 +123,7 @@ using ::ndk::ScopedAStatus; using TmpProfilePath = ProfilePath::TmpProfilePath; constexpr const char* kServiceName = "artd"; +constexpr const char* kPreRebootServiceName = "artd_pre_reboot"; constexpr const char* kArtdCancellationSignalType = "ArtdCancellationSignal"; // Timeout for short operations, such as merging profiles. @@ -1336,8 +1337,8 @@ Result<void> Artd::Start() { OR_RETURN(SetLogVerbosity()); MemMap::Init(); - ScopedAStatus status = ScopedAStatus::fromStatus( - AServiceManager_registerLazyService(this->asBinder().get(), kServiceName)); + ScopedAStatus status = ScopedAStatus::fromStatus(AServiceManager_registerLazyService( + this->asBinder().get(), options_.is_pre_reboot ? kPreRebootServiceName : kServiceName)); if (!status.isOk()) { return Error() << status.getDescription(); } diff --git a/artd/artd.h b/artd/artd.h index fd1ce19e55..f1dc18a503 100644 --- a/artd/artd.h +++ b/artd/artd.h @@ -46,6 +46,12 @@ namespace art { namespace artd { +struct Options { + // If true, this artd instance is for Pre-reboot Dexopt. It runs in a chroot environment that is + // set up by dexopt_chroot_setup. + bool is_pre_reboot = false; +}; + class ArtdCancellationSignal : public aidl::com::android::server::art::BnArtdCancellationSignal { public: explicit ArtdCancellationSignal(std::function<int(pid_t, int)> kill_func) @@ -69,12 +75,14 @@ class ArtdCancellationSignal : public aidl::com::android::server::art::BnArtdCan class Artd : public aidl::com::android::server::art::BnArtd { public: - explicit Artd(std::unique_ptr<art::tools::SystemProperties> props = + explicit Artd(Options&& options, + std::unique_ptr<art::tools::SystemProperties> props = std::make_unique<art::tools::SystemProperties>(), std::unique_ptr<ExecUtils> exec_utils = std::make_unique<ExecUtils>(), std::function<int(pid_t, int)> kill_func = kill, std::function<int(int, struct stat*)> fstat_func = fstat) - : props_(std::move(props)), + : options_(std::move(options)), + props_(std::move(props)), exec_utils_(std::move(exec_utils)), kill_(std::move(kill_func)), fstat_(std::move(fstat_func)) {} @@ -256,6 +264,7 @@ class Artd : public aidl::com::android::server::art::BnArtd { std::mutex ofa_context_mu_; std::unique_ptr<OatFileAssistantContext> ofa_context_ GUARDED_BY(ofa_context_mu_); + const Options options_; const std::unique_ptr<art::tools::SystemProperties> props_; const std::unique_ptr<ExecUtils> exec_utils_; const std::function<int(pid_t, int)> kill_; diff --git a/artd/artd_fuzzer.cc b/artd/artd_fuzzer.cc new file mode 100644 index 0000000000..23d9a9013a --- /dev/null +++ b/artd/artd_fuzzer.cc @@ -0,0 +1,31 @@ +/* + * 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 "artd.h" +#include "fuzzbinder/libbinder_ndk_driver.h" +#include "fuzzer/FuzzedDataProvider.h" + +using ::android::fuzzService; +using ::art::artd::Artd; +using ::ndk::SharedRefBase; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + auto artd = SharedRefBase::make<Artd>(art::artd::Options()); + + fuzzService(artd->asBinder().get(), FuzzedDataProvider(data, size)); + + return 0; +} diff --git a/artd/artd_main.cc b/artd/artd_main.cc index 9fe5bd81b4..212e9c4046 100644 --- a/artd/artd_main.cc +++ b/artd/artd_main.cc @@ -22,10 +22,39 @@ #include "android/binder_process.h" #include "artd.h" +namespace art { +namespace artd { +namespace { + +constexpr int kErrorUsage = 100; + +[[noreturn]] void ParseError(const std::string& error_msg) { + LOG(ERROR) << error_msg; + std::cerr << error_msg << "\n"; + exit(kErrorUsage); +} + +Options ParseOptions(int argc, char** argv) { + Options options; + for (int i = 1; i < argc; i++) { + std::string_view arg = argv[i]; + if (arg == "--pre-reboot") { + options.is_pre_reboot = true; + } else { + ParseError("Unknown option " + std::string(arg)); + } + } + return options; +} + +} // namespace +} // namespace artd +} // namespace art + int main([[maybe_unused]] int argc, char* argv[]) { android::base::InitLogging(argv); - auto artd = ndk::SharedRefBase::make<art::artd::Artd>(); + auto artd = ndk::SharedRefBase::make<art::artd::Artd>(art::artd::ParseOptions(argc, argv)); LOG(INFO) << "Starting artd"; diff --git a/artd/artd_test.cc b/artd/artd_test.cc index fc7c0765ef..79fa7cd4e1 100644 --- a/artd/artd_test.cc +++ b/artd/artd_test.cc @@ -320,7 +320,8 @@ class ArtdTest : public CommonArtTest { EXPECT_CALL(*mock_props_, GetProperty).Times(AnyNumber()).WillRepeatedly(Return("")); auto mock_exec_utils = std::make_unique<MockExecUtils>(); mock_exec_utils_ = mock_exec_utils.get(); - artd_ = ndk::SharedRefBase::make<Artd>(std::move(mock_props), + artd_ = ndk::SharedRefBase::make<Artd>(Options(), + std::move(mock_props), std::move(mock_exec_utils), mock_kill_.AsStdFunction(), mock_fstat_.AsStdFunction()); diff --git a/build/Android.gtest.mk b/build/Android.gtest.mk index 434145d39c..750c62d9ea 100644 --- a/build/Android.gtest.mk +++ b/build/Android.gtest.mk @@ -136,6 +136,7 @@ endif ART_TEST_MODULES_TARGET := $(ART_TEST_MODULES_COMMON) \ art_artd_tests \ + art_dexopt_chroot_setup_tests \ art_odrefresh_tests \ ART_TEST_MODULES_HOST := $(ART_TEST_MODULES_COMMON) @@ -145,6 +146,7 @@ ifneq (,$(wildcard frameworks/native/libs/binder)) # can build the libbinder_ndk dependency. It is not available as a prebuilt on # master-art. ART_TEST_MODULES_HOST += art_artd_tests + ART_TEST_MODULES_HOST += art_dexopt_chroot_setup_tests endif ART_TARGET_GTEST_NAMES := $(foreach tm,$(ART_TEST_MODULES_TARGET),\ diff --git a/build/apex/Android.bp b/build/apex/Android.bp index c2a4153e70..fed90e4718 100644 --- a/build/apex/Android.bp +++ b/build/apex/Android.bp @@ -217,6 +217,7 @@ apex_defaults { "art_boot", "art_exec", "artd", + "dexopt_chroot_setup", ], multilib: { both: { @@ -341,6 +342,7 @@ art_gtests = [ "art_dexdump_tests", "art_dexlayout_tests", "art_dexlist_tests", + "art_dexopt_chroot_setup_tests", "art_disassembler_tests", "art_dexoptanalyzer_tests", "art_imgdiag_tests", diff --git a/build/apex/art.rc b/build/apex/art.rc index 6afa446282..b3eea29982 100644 --- a/build/apex/art.rc +++ b/build/apex/art.rc @@ -12,7 +12,8 @@ # See the License for the specific language governing permissions and # limitations under the License. -# A lazy service that is started and stopped dynamically as needed. +# A service that handles dexopt. See art/artd/README.md. It's a lazy service +# that is started and stopped dynamically as needed. service artd /apex/com.android.art/bin/artd interface aidl artd disabled # Prevents the service from automatically starting at boot. @@ -22,6 +23,30 @@ service artd /apex/com.android.art/bin/artd group artd capabilities DAC_OVERRIDE DAC_READ_SEARCH FOWNER CHOWN +# Same as above, but for Pre-reboot Dexopt. It runs in a chroot environment that +# is set up by dexopt_chroot_setup. It's a lazy service that is started and +# stopped dynamically as needed. +service artd_pre_reboot /apex/com.android.art/bin/art_exec --chroot=/mnt/pre_reboot_dexopt -- /apex/com.android.art/bin/artd --pre-reboot + interface aidl artd_pre_reboot + disabled # Prevents the service from automatically starting at boot. + oneshot # Prevents the service from automatically restarting each time it is stopped. + class core + user artd + group artd + capabilities DAC_OVERRIDE DAC_READ_SEARCH FOWNER CHOWN SYS_CHROOT + seclabel u:r:artd:s0 + +# A service that sets up the chroot environment for Pre-reboot Dexopt. See +# art/dexopt_chroot_setup/README.md. It's a lazy service that is started and +# stopped dynamically as needed. +service dexopt_chroot_setup /apex/com.android.art/bin/dexopt_chroot_setup + interface aidl dexopt_chroot_setup + disabled # Prevents the service from automatically starting at boot. + oneshot # Prevents the service from automatically restarting each time it is stopped. + class core + user artd + group artd + # Run at boot in Android U and later. service art_boot /apex/com.android.art/bin/art_boot disabled # Started explicitly from system/core/rootdir/init.rc diff --git a/build/apex/art_apex_test.py b/build/apex/art_apex_test.py index 7693c1a3c7..a12403118b 100755 --- a/build/apex/art_apex_test.py +++ b/build/apex/art_apex_test.py @@ -552,6 +552,7 @@ class ReleaseTargetChecker: self._checker.check_executable('art_boot') self._checker.check_executable('art_exec') self._checker.check_executable('artd') + self._checker.check_executable('dexopt_chroot_setup') self._checker.check_executable('oatdump') self._checker.check_executable("odrefresh") self._checker.check_symlinked_multilib_executable('dex2oat') @@ -681,6 +682,7 @@ class TestingTargetChecker: self._checker.check_art_test_executable('art_dexdump_tests') self._checker.check_art_test_executable('art_dexlayout_tests') self._checker.check_art_test_executable('art_dexlist_tests') + self._checker.check_art_test_executable('art_dexopt_chroot_setup_tests') self._checker.check_art_test_executable('art_dexoptanalyzer_tests') self._checker.check_art_test_executable('art_disassembler_tests') self._checker.check_art_test_executable('art_imgdiag_tests') diff --git a/dexopt_chroot_setup/Android.bp b/dexopt_chroot_setup/Android.bp new file mode 100644 index 0000000000..93e012a594 --- /dev/null +++ b/dexopt_chroot_setup/Android.bp @@ -0,0 +1,111 @@ +// +// 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 { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "art_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["art_license"], +} + +cc_defaults { + name: "dexopt_chroot_setup_defaults", + defaults: ["art_defaults"], + srcs: [ + "dexopt_chroot_setup.cc", + ], + shared_libs: [ + "libbase", + "libbinder_ndk", + ], + static_libs: [ + "dexopt_chroot_setup-aidl-ndk", + ], +} + +art_cc_binary { + name: "dexopt_chroot_setup", + defaults: ["dexopt_chroot_setup_defaults"], + srcs: [ + "dexopt_chroot_setup_main.cc", + ], + shared_libs: [ + "libart", + "libartbase", + ], + apex_available: [ + "com.android.art", + "com.android.art.debug", + ], +} + +art_cc_defaults { + name: "art_dexopt_chroot_setup_tests_defaults", + defaults: ["dexopt_chroot_setup_defaults"], + static_libs: [ + "libgmock", + ], + srcs: [ + "dexopt_chroot_setup_test.cc", + ], +} + +// Version of ART gtest `art_dexopt_chroot_setup_tests` bundled with the ART +// APEX on target. +// +// This test requires the full libbinder_ndk implementation on host, which is +// not available as a prebuilt on the thin master-art branch. Hence it won't +// work there, and there's a conditional in Android.gtest.mk to exclude it from +// test-art-host-gtest. +art_cc_test { + name: "art_dexopt_chroot_setup_tests", + defaults: [ + "art_gtest_defaults", + "art_dexopt_chroot_setup_tests_defaults", + ], +} + +// Standalone version of ART gtest `art_dexopt_chroot_setup_tests`, not bundled +// with the ART APEX on target. +art_cc_test { + name: "art_standalone_dexopt_chroot_setup_tests", + defaults: [ + "art_standalone_gtest_defaults", + "art_dexopt_chroot_setup_tests_defaults", + ], +} + +cc_fuzz { + name: "dexopt_chroot_setup_fuzzer", + defaults: [ + "service_fuzzer_defaults", + "art_module_source_build_defaults", + "dexopt_chroot_setup_defaults", + ], + host_supported: true, + srcs: ["dexopt_chroot_setup_fuzzer.cc"], + shared_libs: [ + "libart", + "libartbase", + "liblog", + ], + fuzz_config: { + cc: [ + "art-module-team@google.com", + ], + }, +} diff --git a/dexopt_chroot_setup/README.md b/dexopt_chroot_setup/README.md new file mode 100644 index 0000000000..71401248d6 --- /dev/null +++ b/dexopt_chroot_setup/README.md @@ -0,0 +1,10 @@ +## dexopt_chroot_setup + +dexopt_chroot_setup is a component of ART Service. It sets up the chroot +environment for Pre-reboot Dexopt, to dexopt apps on a best-effort basis before +the reboot after a Mainline update or an OTA update is downloaded, to support +seamless updates. + +It requires elevated permissions that are not available to system_server, such +as mounting filesystems. It publishes a binder interface that is internal to ART +Service's Java code. diff --git a/dexopt_chroot_setup/binder/Android.bp b/dexopt_chroot_setup/binder/Android.bp new file mode 100644 index 0000000000..629a783062 --- /dev/null +++ b/dexopt_chroot_setup/binder/Android.bp @@ -0,0 +1,56 @@ +// +// 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 { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "art_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["art_license"], +} + +aidl_interface { + name: "dexopt_chroot_setup-aidl", + srcs: [ + "com/android/server/art/*.aidl", + ], + host_supported: true, + backend: { + java: { + enabled: true, + apex_available: [ + "com.android.art", + "com.android.art.debug", + ], + }, + cpp: { + enabled: false, + }, + ndk: { + enabled: true, + apex_available: [ + "com.android.art", + "com.android.art.debug", + ], + }, + }, + unstable: true, + visibility: [ + "//system/tools/aidl/build", + "//art:__subpackages__", + ], + min_sdk_version: "31", +} diff --git a/dexopt_chroot_setup/binder/com/android/server/art/IDexoptChrootSetup.aidl b/dexopt_chroot_setup/binder/com/android/server/art/IDexoptChrootSetup.aidl new file mode 100644 index 0000000000..f38fceade8 --- /dev/null +++ b/dexopt_chroot_setup/binder/com/android/server/art/IDexoptChrootSetup.aidl @@ -0,0 +1,21 @@ +/* + * 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 com.android.server.art; + +/** @hide */ +interface IDexoptChrootSetup { +} diff --git a/dexopt_chroot_setup/dexopt_chroot_setup.cc b/dexopt_chroot_setup/dexopt_chroot_setup.cc new file mode 100644 index 0000000000..c9a1c735c2 --- /dev/null +++ b/dexopt_chroot_setup/dexopt_chroot_setup.cc @@ -0,0 +1,52 @@ +/* + * 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 "dexopt_chroot_setup.h" + +#include "aidl/com/android/server/art/BnDexoptChrootSetup.h" +#include "android-base/errors.h" +#include "android-base/result.h" +#include "android/binder_auto_utils.h" +#include "android/binder_manager.h" +#include "android/binder_process.h" + +namespace art { +namespace dexopt_chroot_setup { + +namespace { + +using ::android::base::Error; +using ::android::base::Result; +using ::ndk::ScopedAStatus; + +constexpr const char* kServiceName = "dexopt_chroot_setup"; + +} // namespace + +Result<void> DexoptChrootSetup::Start() { + ScopedAStatus status = ScopedAStatus::fromStatus( + AServiceManager_registerLazyService(this->asBinder().get(), kServiceName)); + if (!status.isOk()) { + return Error() << status.getDescription(); + } + + ABinderProcess_startThreadPool(); + + return {}; +} + +} // namespace dexopt_chroot_setup +} // namespace art diff --git a/dexopt_chroot_setup/dexopt_chroot_setup.h b/dexopt_chroot_setup/dexopt_chroot_setup.h new file mode 100644 index 0000000000..858c71711d --- /dev/null +++ b/dexopt_chroot_setup/dexopt_chroot_setup.h @@ -0,0 +1,35 @@ +/* + * 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. + */ + +#ifndef ART_DEXOPT_CHROOT_SETUP_DEXOPT_CHROOT_SETUP_H_ +#define ART_DEXOPT_CHROOT_SETUP_DEXOPT_CHROOT_SETUP_H_ + +#include "aidl/com/android/server/art/BnDexoptChrootSetup.h" +#include "android-base/result.h" + +namespace art { +namespace dexopt_chroot_setup { + +// A service that sets up the chroot environment for Pre-reboot Dexopt. +class DexoptChrootSetup : public aidl::com::android::server::art::BnDexoptChrootSetup { + public: + android::base::Result<void> Start(); +}; + +} // namespace dexopt_chroot_setup +} // namespace art + +#endif // ART_DEXOPT_CHROOT_SETUP_DEXOPT_CHROOT_SETUP_H_ diff --git a/dexopt_chroot_setup/dexopt_chroot_setup_fuzzer.cc b/dexopt_chroot_setup/dexopt_chroot_setup_fuzzer.cc new file mode 100644 index 0000000000..fe3663e38e --- /dev/null +++ b/dexopt_chroot_setup/dexopt_chroot_setup_fuzzer.cc @@ -0,0 +1,31 @@ +/* + * 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 "dexopt_chroot_setup.h" +#include "fuzzbinder/libbinder_ndk_driver.h" +#include "fuzzer/FuzzedDataProvider.h" + +using ::android::fuzzService; +using ::art::dexopt_chroot_setup::DexoptChrootSetup; +using ::ndk::SharedRefBase; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + auto dexopt_chroot_setup = SharedRefBase::make<DexoptChrootSetup>(); + + fuzzService(dexopt_chroot_setup->asBinder().get(), FuzzedDataProvider(data, size)); + + return 0; +} diff --git a/dexopt_chroot_setup/dexopt_chroot_setup_main.cc b/dexopt_chroot_setup/dexopt_chroot_setup_main.cc new file mode 100644 index 0000000000..5e74783619 --- /dev/null +++ b/dexopt_chroot_setup/dexopt_chroot_setup_main.cc @@ -0,0 +1,43 @@ +/* + * 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 <stdlib.h> + +#include "android-base/logging.h" +#include "android-base/macros.h" +#include "android/binder_interface_utils.h" +#include "android/binder_process.h" +#include "dexopt_chroot_setup.h" + +int main([[maybe_unused]] int argc, char* argv[]) { + android::base::InitLogging(argv); + + auto dexopt_chroot_setup = + ndk::SharedRefBase::make<art::dexopt_chroot_setup::DexoptChrootSetup>(); + + LOG(INFO) << "Starting dexopt_chroot_setup"; + + if (android::base::Result<void> ret = dexopt_chroot_setup->Start(); !ret.ok()) { + LOG(ERROR) << "Unable to start dexopt_chroot_setup: " << ret.error(); + exit(1); + } + + ABinderProcess_joinThreadPool(); + + LOG(INFO) << "dexopt_chroot_setup shutting down"; + + return 0; +} diff --git a/dexopt_chroot_setup/dexopt_chroot_setup_test.cc b/dexopt_chroot_setup/dexopt_chroot_setup_test.cc new file mode 100644 index 0000000000..ba42fc53ea --- /dev/null +++ b/dexopt_chroot_setup/dexopt_chroot_setup_test.cc @@ -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 "dexopt_chroot_setup.h" + +#include "base/common_art_test.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +namespace art { +namespace dexopt_chroot_setup { +namespace { + +class DexoptChrootSetupTest : public CommonArtTest { + protected: + void SetUp() override { + CommonArtTest::SetUp(); + dexopt_chroot_setup_ = ndk::SharedRefBase::make<DexoptChrootSetup>(); + } + + std::shared_ptr<DexoptChrootSetup> dexopt_chroot_setup_; +}; + +TEST_F(DexoptChrootSetupTest, HelloWorld) { EXPECT_NE(dexopt_chroot_setup_, nullptr); } + +} // namespace +} // namespace dexopt_chroot_setup +} // namespace art diff --git a/libarttools/art_exec.cc b/libarttools/art_exec.cc index 37a2a5fb70..a382342def 100644 --- a/libarttools/art_exec.cc +++ b/libarttools/art_exec.cc @@ -30,7 +30,6 @@ #include <unordered_set> #include <vector> -#include "android-base/format.h" #include "android-base/logging.h" #include "android-base/parseint.h" #include "android-base/result.h" @@ -80,6 +79,7 @@ struct Options { bool drop_capabilities = false; std::unordered_set<int> keep_fds{fileno(stdin), fileno(stdout), fileno(stderr)}; std::unordered_map<std::string, std::string> envs; + std::string chroot; }; [[noreturn]] void Usage(const std::string& error_msg) { @@ -123,6 +123,8 @@ Options ParseOptions(int argc, char** argv) { } options.envs[std::string(arg.substr(/*pos=*/0, /*n=*/pos))] = std::string(arg.substr(pos + 1)); + } else if (ConsumePrefix(&arg, "--chroot=")) { + options.chroot = arg; } else if (arg == "--") { if (i + 1 >= argc) { Usage("Missing command after '--'"); @@ -215,6 +217,13 @@ int main(int argc, char** argv) { setenv(key.c_str(), value.c_str(), /*overwrite=*/1); } + if (!options.chroot.empty()) { + if (chroot(options.chroot.c_str()) != 0) { + PLOG(ERROR) << ART_FORMAT("Failed to chroot to '{}'", options.chroot); + return kErrorOther; + } + } + execv(argv[options.command_pos], argv + options.command_pos); std::vector<const char*> command_args(argv + options.command_pos, argv + argc); diff --git a/test/utils/regen-test-files b/test/utils/regen-test-files index 71b857e50e..36ac9ef9b1 100755 --- a/test/utils/regen-test-files +++ b/test/utils/regen-test-files @@ -244,6 +244,7 @@ art_gtest_user_module_names = [ "art_standalone_dex2oat_tests", "art_standalone_dexdump_tests", "art_standalone_dexlist_tests", + "art_standalone_dexopt_chroot_setup_tests", "art_standalone_libartbase_tests", "art_standalone_libartpalette_tests", "art_standalone_libartservice_tests", |