101ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe/* 201ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe ** Copyright 2016, The Android Open Source Project 301ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe ** 401ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe ** Licensed under the Apache License, Version 2.0 (the "License"); 501ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe ** you may not use this file except in compliance with the License. 601ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe ** You may obtain a copy of the License at 701ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe ** 801ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe ** http://www.apache.org/licenses/LICENSE-2.0 901ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe ** 1001ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe ** Unless required by applicable law or agreed to in writing, software 1101ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe ** distributed under the License is distributed on an "AS IS" BASIS, 1201ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1301ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe ** See the License for the specific language governing permissions and 1401ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe ** limitations under the License. 1501ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe */ 1601ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe 170354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampe#include <fcntl.h> 1801ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe#include <linux/unistd.h> 1901ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe#include <sys/mount.h> 2001ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe#include <sys/wait.h> 2101ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe 220354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampe#include <sstream> 230354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampe 2401ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe#include <android-base/logging.h> 2501ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe#include <android-base/macros.h> 2601ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe#include <android-base/stringprintf.h> 2701ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe 280354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampe#include <commands.h> 290ba073ce81fbe544592e0a3cd526b274e83fdf9fAndreas Gampe#include <otapreopt_utils.h> 30aef445d1c659698612c0e5a8f3d5f2b9f8a2b778Andreas Gampe 3101ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe#ifndef LOG_TAG 3201ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe#define LOG_TAG "otapreopt" 3301ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe#endif 3401ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe 3501ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampeusing android::base::StringPrintf; 3601ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe 3701ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampenamespace android { 3801ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampenamespace installd { 3901ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe 400354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampestatic void CloseDescriptor(int fd) { 410354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampe if (fd >= 0) { 420354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampe int result = close(fd); 430354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampe UNUSED(result); // Ignore result. Printing to logcat will open a new descriptor 440354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampe // that we do *not* want. 450354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampe } 460354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampe} 470354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampe 480354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampestatic void CloseDescriptor(const char* descriptor_string) { 490354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampe int fd = -1; 500354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampe std::istringstream stream(descriptor_string); 510354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampe stream >> fd; 520354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampe if (!stream.fail()) { 530354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampe CloseDescriptor(fd); 540354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampe } 550354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampe} 560354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampe 570354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampe// Entry for otapreopt_chroot. Expected parameters are: 580354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampe// [cmd] [status-fd] [target-slot] "dexopt" [dexopt-params] 590354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampe// The file descriptor denoted by status-fd will be closed. The rest of the parameters will 600354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampe// be passed on to otapreopt in the chroot. 6101ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampestatic int otapreopt_chroot(const int argc, char **arg) { 620354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampe // Close all file descriptors. They are coming from the caller, we do not want to pass them 630354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampe // on across our fork/exec into a different domain. 640354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampe // 1) Default descriptors. 650354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampe CloseDescriptor(STDIN_FILENO); 660354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampe CloseDescriptor(STDOUT_FILENO); 670354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampe CloseDescriptor(STDERR_FILENO); 680354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampe // 2) The status channel. 690354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampe CloseDescriptor(arg[1]); 700354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampe 7101ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe // We need to run the otapreopt tool from the postinstall partition. As such, set up a 7201ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe // mount namespace and change root. 7301ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe 7401ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe // Create our own mount namespace. 7501ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe if (unshare(CLONE_NEWNS) != 0) { 7601ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe PLOG(ERROR) << "Failed to unshare() for otapreopt."; 7701ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe exit(200); 7801ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe } 7901ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe 8001ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe // Make postinstall private, so that our changes don't propagate. 8101ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe if (mount("", "/postinstall", nullptr, MS_PRIVATE, nullptr) != 0) { 8201ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe PLOG(ERROR) << "Failed to mount private."; 8301ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe exit(201); 8401ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe } 8501ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe 8601ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe // Bind mount necessary directories. 8701ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe constexpr const char* kBindMounts[] = { 8801ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe "/data", "/dev", "/proc", "/sys" 8901ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe }; 9001ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe for (size_t i = 0; i < arraysize(kBindMounts); ++i) { 9101ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe std::string trg = StringPrintf("/postinstall%s", kBindMounts[i]); 9201ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe if (mount(kBindMounts[i], trg.c_str(), nullptr, MS_BIND, nullptr) != 0) { 9301ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe PLOG(ERROR) << "Failed to bind-mount " << kBindMounts[i]; 9401ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe exit(202); 9501ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe } 9601ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe } 9701ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe 980ba073ce81fbe544592e0a3cd526b274e83fdf9fAndreas Gampe // Try to mount the vendor partition. update_engine doesn't do this for us, but we 990ba073ce81fbe544592e0a3cd526b274e83fdf9fAndreas Gampe // want it for vendor APKs. 1000ba073ce81fbe544592e0a3cd526b274e83fdf9fAndreas Gampe // Notes: 1010ba073ce81fbe544592e0a3cd526b274e83fdf9fAndreas Gampe // 1) We pretty much guess a name here and hope to find the partition by name. 1020ba073ce81fbe544592e0a3cd526b274e83fdf9fAndreas Gampe // It is just as complicated and brittle to scan /proc/mounts. But this requires 1030ba073ce81fbe544592e0a3cd526b274e83fdf9fAndreas Gampe // validating the target-slot so as not to try to mount some totally random path. 1040ba073ce81fbe544592e0a3cd526b274e83fdf9fAndreas Gampe // 2) We're in a mount namespace here, so when we die, this will be cleaned up. 1050ba073ce81fbe544592e0a3cd526b274e83fdf9fAndreas Gampe // 3) Ignore errors. Printing anything at this stage will open a file descriptor 1060ba073ce81fbe544592e0a3cd526b274e83fdf9fAndreas Gampe // for logging. 1070ba073ce81fbe544592e0a3cd526b274e83fdf9fAndreas Gampe if (!ValidateTargetSlotSuffix(arg[2])) { 1080ba073ce81fbe544592e0a3cd526b274e83fdf9fAndreas Gampe LOG(ERROR) << "Target slot suffix not legal: " << arg[2]; 1090ba073ce81fbe544592e0a3cd526b274e83fdf9fAndreas Gampe exit(207); 1100ba073ce81fbe544592e0a3cd526b274e83fdf9fAndreas Gampe } 1110ba073ce81fbe544592e0a3cd526b274e83fdf9fAndreas Gampe std::string vendor_partition = StringPrintf("/dev/block/bootdevice/by-name/vendor%s", 1120ba073ce81fbe544592e0a3cd526b274e83fdf9fAndreas Gampe arg[2]); 1130ba073ce81fbe544592e0a3cd526b274e83fdf9fAndreas Gampe int vendor_result = mount(vendor_partition.c_str(), 1140ba073ce81fbe544592e0a3cd526b274e83fdf9fAndreas Gampe "/postinstall/vendor", 1150ba073ce81fbe544592e0a3cd526b274e83fdf9fAndreas Gampe "ext4", 1160ba073ce81fbe544592e0a3cd526b274e83fdf9fAndreas Gampe MS_RDONLY, 1170ba073ce81fbe544592e0a3cd526b274e83fdf9fAndreas Gampe /* data */ nullptr); 1180ba073ce81fbe544592e0a3cd526b274e83fdf9fAndreas Gampe UNUSED(vendor_result); 1190ba073ce81fbe544592e0a3cd526b274e83fdf9fAndreas Gampe 12001ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe // Chdir into /postinstall. 12101ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe if (chdir("/postinstall") != 0) { 12201ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe PLOG(ERROR) << "Unable to chdir into /postinstall."; 12301ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe exit(203); 12401ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe } 12501ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe 12601ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe // Make /postinstall the root in our mount namespace. 12701ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe if (chroot(".") != 0) { 12801ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe PLOG(ERROR) << "Failed to chroot"; 12901ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe exit(204); 13001ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe } 13101ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe 13201ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe if (chdir("/") != 0) { 13301ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe PLOG(ERROR) << "Unable to chdir into /."; 13401ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe exit(205); 13501ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe } 13601ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe 13701ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe // Now go on and run otapreopt. 13801ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe 1390354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampe // Incoming: cmd + status-fd + target-slot + "dexopt" + dexopt-params + null 1400354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampe // Outgoing: cmd + target-slot + "dexopt" + dexopt-params + null 1410354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampe constexpr size_t kInArguments = 1 // Binary name. 1420354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampe + 1 // status file descriptor. 1430354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampe + 1 // target-slot. 1440354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampe + 1 // "dexopt." 1450354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampe + DEXOPT_PARAM_COUNT // dexopt parameters. 1460354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampe + 1; // null termination. 1470354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampe constexpr size_t kOutArguments = 1 // Binary name. 1480354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampe + 1 // target-slot. 1490354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampe + 1 // "dexopt." 1500354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampe + DEXOPT_PARAM_COUNT // dexopt parameters. 1510354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampe + 1; // null termination. 1520354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampe const char* argv[kOutArguments]; 1530354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampe if (static_cast<size_t>(argc) != kInArguments - 1 /* null termination */) { 1540354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampe LOG(ERROR) << "Unexpected argument size " 1550354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampe << argc 1560354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampe << " vs " 1570354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampe << (kInArguments - 1); 1580354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampe for (size_t i = 0; i < static_cast<size_t>(argc); ++i) { 1590354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampe if (arg[i] == nullptr) { 1600354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampe LOG(ERROR) << "(null)"; 1610354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampe } else { 1620354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampe LOG(ERROR) << "\"" << arg[i] << "\""; 1630354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampe } 1640354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampe } 1650354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampe exit(206); 1660354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampe } 16701ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe argv[0] = "/system/bin/otapreopt"; 1680354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampe 1690354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampe // The first parameter is the status file descriptor, skip. 1700354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampe 1710354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampe for (size_t i = 1; i <= kOutArguments - 2 /* cmd + null */; ++i) { 1720354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampe argv[i] = arg[i + 1]; 17301ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe } 1740354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampe argv[kOutArguments - 1] = nullptr; 17501ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe 17601ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe execv(argv[0], (char * const *)argv); 17701ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe PLOG(ERROR) << "execv(OTAPREOPT) failed."; 17801ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe exit(99); 17901ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe} 18001ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe 18101ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe} // namespace installd 18201ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe} // namespace android 18301ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe 18401ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampeint main(const int argc, char *argv[]) { 18501ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe return android::installd::otapreopt_chroot(argc, argv); 18601ad5984dd202311a7e301c8c771a5d4b7c76136Andreas Gampe} 187