diff options
-rw-r--r-- | Android.bp | 3 | ||||
-rw-r--r-- | Android.mk | 6 | ||||
-rw-r--r-- | fastboot/fastboot.cpp | 1 | ||||
-rw-r--r-- | install/include/install/install.h | 4 | ||||
-rw-r--r-- | install/install.cpp | 47 | ||||
-rw-r--r-- | minadbd/Android.bp | 12 | ||||
-rw-r--r-- | minadbd/minadbd_services.cpp | 4 | ||||
-rw-r--r-- | recovery.cpp | 6 | ||||
-rw-r--r-- | recovery_main.cpp | 5 | ||||
-rw-r--r-- | recovery_ui/Android.bp | 21 | ||||
-rw-r--r-- | recovery_ui/ethernet_device.cpp | 136 | ||||
-rw-r--r-- | recovery_ui/ethernet_ui.cpp | 32 | ||||
-rw-r--r-- | recovery_ui/include/recovery_ui/device.h | 12 | ||||
-rw-r--r-- | recovery_ui/include/recovery_ui/ethernet_ui.h | 34 | ||||
-rw-r--r-- | recovery_ui/include/recovery_ui/ui.h | 4 | ||||
-rw-r--r-- | recovery_ui/screen_ui.cpp | 21 | ||||
-rw-r--r-- | recovery_utils/roots.cpp | 10 | ||||
-rw-r--r-- | tests/Android.bp | 1 | ||||
-rw-r--r-- | tests/unit/install_test.cpp | 28 | ||||
-rw-r--r-- | uncrypt/uncrypt.cpp | 6 | ||||
-rw-r--r-- | updater/updater_runtime.cpp | 60 |
21 files changed, 436 insertions, 17 deletions
diff --git a/Android.bp b/Android.bp index 4032bcc19..c0c58ddbc 100644 --- a/Android.bp +++ b/Android.bp @@ -72,12 +72,14 @@ cc_defaults { ], static_libs: [ + "libc++fs", "libinstall", "librecovery_fastboot", "libminui", "librecovery_utils", "libotautil", "libsnapshot_nobinder", + "update_metadata-protos", ], } @@ -94,6 +96,7 @@ cc_library_static { ], shared_libs: [ + "libfusesideload", "librecovery_ui", ], } diff --git a/Android.mk b/Android.mk index d727ca2af..58167491a 100644 --- a/Android.mk +++ b/Android.mk @@ -18,9 +18,9 @@ LOCAL_PATH := $(call my-dir) RECOVERY_API_VERSION := 3 RECOVERY_FSTAB_VERSION := 2 -# TARGET_RECOVERY_UI_LIB should be one of librecovery_ui_{default,wear,vr} or a device-specific -# module that defines make_device() and the exact RecoveryUI class for the target. It defaults to -# librecovery_ui_default, which uses ScreenRecoveryUI. +# TARGET_RECOVERY_UI_LIB should be one of librecovery_ui_{default,wear,vr,ethernet} or a +# device-specific module that defines make_device() and the exact RecoveryUI class for the +# target. It defaults to librecovery_ui_default, which uses ScreenRecoveryUI. TARGET_RECOVERY_UI_LIB ?= librecovery_ui_default # librecovery_ui_ext (shared library) diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp index 202334997..a0930087c 100644 --- a/fastboot/fastboot.cpp +++ b/fastboot/fastboot.cpp @@ -52,6 +52,7 @@ Device::BuiltinAction StartFastboot(Device* device, const std::vector<std::strin ui->ResetKeyInterruptStatus(); ui->SetTitle(title_lines); ui->ShowText(true); + device->StartFastboot(); // Reset to normal system boot so recovery won't cycle indefinitely. // TODO(b/112277594) Clear only if 'recovery' field of BCB is empty. If not, diff --git a/install/include/install/install.h b/install/include/install/install.h index 87d43ab09..bef23e9ca 100644 --- a/install/include/install/install.h +++ b/install/include/install/install.h @@ -63,3 +63,7 @@ bool ReadMetadataFromPackage(ZipArchiveHandle zip, std::map<std::string, std::st // pre-device and serial number (if presents). A/B OTA specific checks: pre-build version, // fingerprint, timestamp. bool CheckPackageMetadata(const std::map<std::string, std::string>& metadata, OtaType ota_type); + +// Ensures the path to the update package is mounted. Also set the |should_use_fuse| to true if the +// package stays on a removable media. +bool SetupPackageMount(const std::string& package_path, bool* should_use_fuse); diff --git a/install/install.cpp b/install/install.cpp index 56c1e68de..d404997dc 100644 --- a/install/install.cpp +++ b/install/install.cpp @@ -30,6 +30,7 @@ #include <atomic> #include <chrono> #include <condition_variable> +#include <filesystem> #include <functional> #include <limits> #include <mutex> @@ -652,3 +653,49 @@ bool verify_package(Package* package, RecoveryUI* ui) { } return true; } + +bool SetupPackageMount(const std::string& package_path, bool* should_use_fuse) { + CHECK(should_use_fuse != nullptr); + + if (package_path.empty()) { + return false; + } + + *should_use_fuse = true; + if (package_path[0] == '@') { + auto block_map_path = package_path.substr(1); + if (ensure_path_mounted(block_map_path) != 0) { + LOG(ERROR) << "Failed to mount " << block_map_path; + return false; + } + // uncrypt only produces block map only if the package stays on /data. + *should_use_fuse = false; + return true; + } + + // Package is not a block map file. + if (ensure_path_mounted(package_path) != 0) { + LOG(ERROR) << "Failed to mount " << package_path; + return false; + } + + // Reject the package if the input path doesn't equal the canonicalized path. + // e.g. /cache/../sdcard/update_package. + std::error_code ec; + auto canonical_path = std::filesystem::canonical(package_path, ec); + if (ec) { + LOG(ERROR) << "Failed to get canonical of " << package_path << ", " << ec.message(); + return false; + } + if (canonical_path.string() != package_path) { + LOG(ERROR) << "Installation aborts. The canonical path " << canonical_path.string() + << " doesn't equal the original path " << package_path; + return false; + } + + constexpr const char* CACHE_ROOT = "/cache"; + if (android::base::StartsWith(package_path, CACHE_ROOT)) { + *should_use_fuse = false; + } + return true; +} diff --git a/minadbd/Android.bp b/minadbd/Android.bp index c39c73443..793680f33 100644 --- a/minadbd/Android.bp +++ b/minadbd/Android.bp @@ -34,7 +34,7 @@ cc_defaults { // `libminadbd_services` is analogous to the `libadbd_services` for regular `adbd`, but providing // the sideload service only. -cc_library { +cc_library_static { name: "libminadbd_services", recovery_available: true, @@ -79,6 +79,8 @@ cc_binary { defaults: [ "minadbd_defaults", + "libadbd_binary_dependencies", + "librecovery_utils_defaults", ], srcs: [ @@ -86,10 +88,14 @@ cc_binary { ], shared_libs: [ - "libadbd", "libbase", "libcrypto", + ], + + static_libs: [ "libminadbd_services", + "libfusesideload", + "librecovery_utils", ], required: [ @@ -104,6 +110,7 @@ cc_test { defaults: [ "minadbd_defaults", "librecovery_utils_defaults", + "libadbd_binary_dependencies", ], srcs: [ @@ -116,7 +123,6 @@ cc_test { "libfusesideload", "librecovery_utils", "libotautil", - "libadbd", ], shared_libs: [ diff --git a/minadbd/minadbd_services.cpp b/minadbd/minadbd_services.cpp index eb91fb3e4..ff91ba931 100644 --- a/minadbd/minadbd_services.cpp +++ b/minadbd/minadbd_services.cpp @@ -266,6 +266,10 @@ static void WipeDeviceService(unique_fd fd, const std::string& args) { } } +asocket* daemon_service_to_socket(std::string_view) { + return nullptr; +} + unique_fd daemon_service_to_fd(std::string_view name, atransport* /* transport */) { // Common services that are supported both in sideload and rescue modes. if (android::base::ConsumePrefix(&name, "reboot:")) { diff --git a/recovery.cpp b/recovery.cpp index b1f106b1c..b02202766 100644 --- a/recovery.cpp +++ b/recovery.cpp @@ -752,7 +752,11 @@ Device::BuiltinAction start_recovery(Device* device, const std::vector<std::stri ensure_path_mounted(update_package); } - if (install_with_fuse) { + bool should_use_fuse = false; + if (!SetupPackageMount(update_package, &should_use_fuse)) { + LOG(INFO) << "Failed to set up the package access, skipping installation"; + status = INSTALL_ERROR; + } else if (install_with_fuse || should_use_fuse) { LOG(INFO) << "Installing package " << update_package << " with fuse"; status = InstallWithFuseFromPath(update_package, ui); } else if (auto memory_package = Package::CreateMemoryPackage( diff --git a/recovery_main.cpp b/recovery_main.cpp index 30a1fc0a4..80cba61d3 100644 --- a/recovery_main.cpp +++ b/recovery_main.cpp @@ -471,6 +471,11 @@ int main(int argc, char** argv) { std::string usb_config = fastboot ? "fastboot" : IsRoDebuggable() || IsDeviceUnlocked() ? "adb" : "none"; std::string usb_state = android::base::GetProperty("sys.usb.state", "none"); + if (fastboot) { + device->PreFastboot(); + } else { + device->PreRecovery(); + } if (usb_config != usb_state) { if (!SetUsbConfig("none")) { LOG(ERROR) << "Failed to clear USB config"; diff --git a/recovery_ui/Android.bp b/recovery_ui/Android.bp index 149ef8acc..9dfee5fd5 100644 --- a/recovery_ui/Android.bp +++ b/recovery_ui/Android.bp @@ -22,6 +22,7 @@ cc_library { srcs: [ "device.cpp", + "ethernet_ui.cpp", "screen_ui.cpp", "stub_ui.cpp", "ui.cpp", @@ -90,3 +91,23 @@ cc_library_static { export_include_dirs: ["include"], } + +// The default device that uses EthernetRecoveryUI. +cc_library_static { + name: "librecovery_ui_ethernet", + recovery_available: true, + + defaults: [ + "recovery_defaults", + ], + + srcs: [ + "ethernet_device.cpp", + ], + + shared_libs: [ + "libbase", + ], + + export_include_dirs: ["include"], +} diff --git a/recovery_ui/ethernet_device.cpp b/recovery_ui/ethernet_device.cpp new file mode 100644 index 000000000..39ec65dc4 --- /dev/null +++ b/recovery_ui/ethernet_device.cpp @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2020 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 <android-base/logging.h> +#include <android-base/properties.h> +#include <android-base/strings.h> +#include <android-base/unique_fd.h> +#include <arpa/inet.h> +#include <ifaddrs.h> +#include <linux/if.h> +#include <string.h> +#include <sys/ioctl.h> +#include <sys/socket.h> +#include <sys/types.h> + +#include "recovery_ui/device.h" +#include "recovery_ui/ethernet_ui.h" + +class EthernetDevice : public Device { + public: + explicit EthernetDevice(EthernetRecoveryUI* ui); + + void PreRecovery() override; + void PreFastboot() override; + + private: + int SetInterfaceFlags(const unsigned set, const unsigned clr); + void SetTitleIPv6LinkLocalAddress(const bool interface_up); + + android::base::unique_fd ctl_sock_; + static const std::string interface; +}; + +const std::string EthernetDevice::interface = "eth0"; + +EthernetDevice::EthernetDevice(EthernetRecoveryUI* ui) + : Device(ui), ctl_sock_(socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0)) { + if (ctl_sock_ < 0) { + PLOG(ERROR) << "Failed to open socket"; + } +} + +void EthernetDevice::PreRecovery() { + SetInterfaceFlags(0, IFF_UP); + SetTitleIPv6LinkLocalAddress(false); +} + +void EthernetDevice::PreFastboot() { + android::base::SetProperty("fastbootd.protocol", "tcp"); + + if (SetInterfaceFlags(IFF_UP, 0) < 0) { + LOG(ERROR) << "Failed to bring up interface"; + return; + } + + SetTitleIPv6LinkLocalAddress(true); +} + +int EthernetDevice::SetInterfaceFlags(const unsigned set, const unsigned clr) { + struct ifreq ifr; + + if (ctl_sock_ < 0) { + return -1; + } + + memset(&ifr, 0, sizeof(struct ifreq)); + strncpy(ifr.ifr_name, interface.c_str(), IFNAMSIZ); + ifr.ifr_name[IFNAMSIZ - 1] = 0; + + if (ioctl(ctl_sock_, SIOCGIFFLAGS, &ifr) < 0) { + PLOG(ERROR) << "Failed to get interface active flags"; + return -1; + } + ifr.ifr_flags = (ifr.ifr_flags & (~clr)) | set; + + if (ioctl(ctl_sock_, SIOCSIFFLAGS, &ifr) < 0) { + PLOG(ERROR) << "Failed to set interface active flags"; + return -1; + } + + return 0; +} + +void EthernetDevice::SetTitleIPv6LinkLocalAddress(const bool interface_up) { + auto recovery_ui = reinterpret_cast<EthernetRecoveryUI*>(GetUI()); + if (!interface_up) { + recovery_ui->SetIPv6LinkLocalAddress(); + return; + } + + struct ifaddrs* ifaddr; + if (getifaddrs(&ifaddr) == -1) { + PLOG(ERROR) << "Failed to get interface addresses"; + recovery_ui->SetIPv6LinkLocalAddress(); + return; + } + + std::unique_ptr<struct ifaddrs, decltype(&freeifaddrs)> guard{ ifaddr, freeifaddrs }; + for (struct ifaddrs* ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) { + if (ifa->ifa_addr->sa_family != AF_INET6 || interface != ifa->ifa_name) { + continue; + } + + auto current_addr = reinterpret_cast<struct sockaddr_in6*>(ifa->ifa_addr); + if (!IN6_IS_ADDR_LINKLOCAL(&(current_addr->sin6_addr))) { + continue; + } + + char addrstr[INET6_ADDRSTRLEN]; + inet_ntop(AF_INET6, reinterpret_cast<const void*>(¤t_addr->sin6_addr), addrstr, + INET6_ADDRSTRLEN); + LOG(INFO) << "Our IPv6 link-local address is " << addrstr; + recovery_ui->SetIPv6LinkLocalAddress(addrstr); + return; + } + + recovery_ui->SetIPv6LinkLocalAddress(); +} + +// ----------------------------------------------------------------------------------------- +Device* make_device() { + return new EthernetDevice(new EthernetRecoveryUI); +} diff --git a/recovery_ui/ethernet_ui.cpp b/recovery_ui/ethernet_ui.cpp new file mode 100644 index 000000000..535d407f9 --- /dev/null +++ b/recovery_ui/ethernet_ui.cpp @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2020 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 "recovery_ui/ethernet_ui.h" + +#include <android-base/logging.h> + +void EthernetRecoveryUI::SetTitle(const std::vector<std::string>& lines) { + ScreenRecoveryUI::SetTitle(lines); + + // Append IP address, if any + if (!address_.empty()) { + title_lines_.push_back("IPv6 link-local address - " + address_); + } +} + +void EthernetRecoveryUI::SetIPv6LinkLocalAddress(const std::string& address) { + address_ = address; +} diff --git a/recovery_ui/include/recovery_ui/device.h b/recovery_ui/include/recovery_ui/device.h index f4f993638..76166f09d 100644 --- a/recovery_ui/include/recovery_ui/device.h +++ b/recovery_ui/include/recovery_ui/device.h @@ -79,10 +79,22 @@ class Device { ui_.reset(ui); } + // Called before recovery mode started up, to perform whatever device-specific recovery mode + // preparation as needed. + virtual void PreRecovery() {} + // Called when recovery starts up (after the UI has been obtained and initialized and after the // arguments have been parsed, but before anything else). virtual void StartRecovery() {} + // Called before fastboot mode is started up, to perform whatever device-specific fastboot mode + // preparation as needed. + virtual void PreFastboot() {} + + // Called when fastboot starts up (after the UI has been obtained and initialized and after the + // arguments have been parsed, but before anything else). + virtual void StartFastboot() {} + // Called from the main thread when recovery is at the main menu and waiting for input, and a key // is pressed. (Note that "at" the main menu does not necessarily mean the menu is visible; // recovery will be at the main menu with it invisible after an unsuccessful operation, such as diff --git a/recovery_ui/include/recovery_ui/ethernet_ui.h b/recovery_ui/include/recovery_ui/ethernet_ui.h new file mode 100644 index 000000000..f40c73f69 --- /dev/null +++ b/recovery_ui/include/recovery_ui/ethernet_ui.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2020 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 RECOVERY_ETHERNET_UI_H +#define RECOVERY_ETHERNET_UI_H + +#include "screen_ui.h" + +class EthernetRecoveryUI : public ScreenRecoveryUI { + public: + EthernetRecoveryUI() {} + void SetTitle(const std::vector<std::string>& lines) override; + + // For EthernetDevice + void SetIPv6LinkLocalAddress(const std::string& address = ""); + + private: + std::string address_; +}; + +#endif // RECOVERY_ETHERNET_UI_H diff --git a/recovery_ui/include/recovery_ui/ui.h b/recovery_ui/include/recovery_ui/ui.h index 08ec1d76a..512732f90 100644 --- a/recovery_ui/include/recovery_ui/ui.h +++ b/recovery_ui/include/recovery_ui/ui.h @@ -192,6 +192,8 @@ class RecoveryUI { return key_interrupted_; } + virtual bool IsUsbConnected(); + protected: void EnqueueKey(int key_code); @@ -226,8 +228,6 @@ class RecoveryUI { void ProcessKey(int key_code, int updown); void TimeKey(int key_code, int count); - bool IsUsbConnected(); - bool InitScreensaver(); void SetScreensaverState(ScreensaverState state); diff --git a/recovery_ui/screen_ui.cpp b/recovery_ui/screen_ui.cpp index 6dcb161fa..b2c828f34 100644 --- a/recovery_ui/screen_ui.cpp +++ b/recovery_ui/screen_ui.cpp @@ -37,6 +37,7 @@ #include <unordered_map> #include <vector> +#include <android-base/chrono_utils.h> #include <android-base/logging.h> #include <android-base/properties.h> #include <android-base/stringprintf.h> @@ -881,10 +882,28 @@ bool ScreenRecoveryUI::LoadWipeDataMenuText() { return true; } +static bool InitGraphics() { + // Timeout is same as init wait for file default of 5 seconds and is arbitrary + const unsigned timeout = 500; // 10ms increments + for (auto retry = timeout; retry > 0; --retry) { + if (gr_init() == 0) { + if (retry < timeout) { + // Log message like init wait for file completion log for consistency. + LOG(WARNING) << "wait for 'graphics' took " << ((timeout - retry) * 10) << "ms"; + } + return true; + } + std::this_thread::sleep_for(10ms); + } + // Log message like init wait for file timeout log for consistency. + LOG(ERROR) << "timeout wait for 'graphics' took " << (timeout * 10) << "ms"; + return false; +} + bool ScreenRecoveryUI::Init(const std::string& locale) { RecoveryUI::Init(locale); - if (gr_init() == -1) { + if (!InitGraphics()) { return false; } diff --git a/recovery_utils/roots.cpp b/recovery_utils/roots.cpp index 58a313973..19484478c 100644 --- a/recovery_utils/roots.cpp +++ b/recovery_utils/roots.cpp @@ -157,8 +157,8 @@ int format_volume(const std::string& volume, const std::string& directory) { bool needs_projid = false; if (volume == "/data") { - needs_casefold = android::base::GetBoolProperty("ro.emulated_storage.casefold", false); - needs_projid = android::base::GetBoolProperty("ro.emulated_storage.projid", false); + needs_casefold = android::base::GetBoolProperty("external_storage.casefold.enabled", false); + needs_projid = android::base::GetBoolProperty("external_storage.projid.enabled", false); } // If there's a key_loc that looks like a path, it should be a block device for storing encryption @@ -259,6 +259,12 @@ int format_volume(const std::string& volume, const std::string& directory) { make_f2fs_cmd.push_back("-C"); make_f2fs_cmd.push_back("utf8"); } + if (v->fs_mgr_flags.fs_compress) { + make_f2fs_cmd.push_back("-O"); + make_f2fs_cmd.push_back("compression"); + make_f2fs_cmd.push_back("-O"); + make_f2fs_cmd.push_back("extra_attr"); + } make_f2fs_cmd.push_back(v->blk_device); if (length >= kSectorSize) { make_f2fs_cmd.push_back(std::to_string(length / kSectorSize)); diff --git a/tests/Android.bp b/tests/Android.bp index 3d223907c..a9a088a32 100644 --- a/tests/Android.bp +++ b/tests/Android.bp @@ -92,6 +92,7 @@ librecovery_static_libs = [ "libhidlbase", "liblp", "libtinyxml2", + "libc++fs", ] // recovery image for unittests. diff --git a/tests/unit/install_test.cpp b/tests/unit/install_test.cpp index 370fbdcc5..ee753494c 100644 --- a/tests/unit/install_test.cpp +++ b/tests/unit/install_test.cpp @@ -35,6 +35,7 @@ #include "install/wipe_device.h" #include "otautil/paths.h" #include "private/setup_commands.h" +#include "recovery_utils/roots.h" static void BuildZipArchive(const std::map<std::string, std::string>& file_map, int fd, int compression_type) { @@ -513,3 +514,30 @@ TEST(InstallTest, CheckPackageMetadata_ab_post_timestamp) { "\n"); TestCheckPackageMetadata(metadata, OtaType::AB, true); } + +TEST(InstallTest, SetupPackageMount_package_path) { + load_volume_table(); + bool install_with_fuse; + + // Setup should fail if the input path doesn't exist. + ASSERT_FALSE(SetupPackageMount("/does_not_exist", &install_with_fuse)); + + // Package should be installed with fuse if it's not in /cache. + TemporaryDir temp_dir; + TemporaryFile update_package(temp_dir.path); + ASSERT_TRUE(SetupPackageMount(update_package.path, &install_with_fuse)); + ASSERT_TRUE(install_with_fuse); + + // Setup should fail if the input path isn't canonicalized. + std::string uncanonical_package_path = android::base::Join( + std::vector<std::string>{ + temp_dir.path, + "..", + android::base::Basename(temp_dir.path), + android::base::Basename(update_package.path), + }, + '/'); + + ASSERT_EQ(0, access(uncanonical_package_path.c_str(), R_OK)); + ASSERT_FALSE(SetupPackageMount(uncanonical_package_path, &install_with_fuse)); +} diff --git a/uncrypt/uncrypt.cpp b/uncrypt/uncrypt.cpp index f1f4f69f0..c798e31d6 100644 --- a/uncrypt/uncrypt.cpp +++ b/uncrypt/uncrypt.cpp @@ -477,9 +477,9 @@ static int Uncrypt(const std::string& input_path, const std::string& map_file, i return kUncryptRealpathFindError; } - bool encryptable; - bool encrypted; - bool f2fs_fs; + bool encryptable = false; + bool encrypted = false; + bool f2fs_fs = false; const std::string blk_dev = FindBlockDevice(path, &encryptable, &encrypted, &f2fs_fs); if (blk_dev.empty()) { LOG(ERROR) << "Failed to find block device for " << path; diff --git a/updater/updater_runtime.cpp b/updater/updater_runtime.cpp index c4222a56e..b1b8863fd 100644 --- a/updater/updater_runtime.cpp +++ b/updater/updater_runtime.cpp @@ -43,10 +43,62 @@ std::string UpdaterRuntime::FindBlockDeviceName(const std::string_view name) con return std::string(name); } +static struct { + const char* name; + unsigned flag; +} mount_flags_list[] = { + { "noatime", MS_NOATIME }, + { "noexec", MS_NOEXEC }, + { "nosuid", MS_NOSUID }, + { "nodev", MS_NODEV }, + { "nodiratime", MS_NODIRATIME }, + { "ro", MS_RDONLY }, + { "rw", 0 }, + { "remount", MS_REMOUNT }, + { "bind", MS_BIND }, + { "rec", MS_REC }, + { "unbindable", MS_UNBINDABLE }, + { "private", MS_PRIVATE }, + { "slave", MS_SLAVE }, + { "shared", MS_SHARED }, + { "defaults", 0 }, + { 0, 0 }, +}; + +static bool setMountFlag(const std::string& flag, unsigned* mount_flags) { + for (const auto& [name, value] : mount_flags_list) { + if (flag == name) { + *mount_flags |= value; + return true; + } + } + return false; +} + +static bool parseMountFlags(const std::string& flags, unsigned* mount_flags, + std::string* fs_options) { + bool is_flag_set = false; + std::vector<std::string> flag_list; + for (const auto& flag : android::base::Split(flags, ",")) { + if (!setMountFlag(flag, mount_flags)) { + // Unknown flag, so it must be a filesystem specific option. + flag_list.push_back(flag); + } else { + is_flag_set = true; + } + } + *fs_options = android::base::Join(flag_list, ','); + return is_flag_set; +} + int UpdaterRuntime::Mount(const std::string_view location, const std::string_view mount_point, const std::string_view fs_type, const std::string_view mount_options) { std::string mount_point_string(mount_point); + std::string mount_options_string(mount_options); char* secontext = nullptr; + unsigned mount_flags = 0; + std::string fs_options; + if (sehandle_) { selabel_lookup(sehandle_, &secontext, mount_point_string.c_str(), 0755); setfscreatecon(secontext); @@ -59,9 +111,13 @@ int UpdaterRuntime::Mount(const std::string_view location, const std::string_vie setfscreatecon(nullptr); } + if (!parseMountFlags(mount_options_string, &mount_flags, &fs_options)) { + // Fall back to default + mount_flags = MS_NOATIME | MS_NODEV | MS_NODIRATIME; + } + return mount(std::string(location).c_str(), mount_point_string.c_str(), - std::string(fs_type).c_str(), MS_NOATIME | MS_NODEV | MS_NODIRATIME, - std::string(mount_options).c_str()); + std::string(fs_type).c_str(), mount_flags, fs_options.c_str()); } bool UpdaterRuntime::IsMounted(const std::string_view mount_point) const { |