summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Android.bp3
-rw-r--r--Android.mk6
-rw-r--r--fastboot/fastboot.cpp1
-rw-r--r--install/include/install/install.h4
-rw-r--r--install/install.cpp47
-rw-r--r--minadbd/Android.bp12
-rw-r--r--minadbd/minadbd_services.cpp4
-rw-r--r--recovery.cpp6
-rw-r--r--recovery_main.cpp5
-rw-r--r--recovery_ui/Android.bp21
-rw-r--r--recovery_ui/ethernet_device.cpp136
-rw-r--r--recovery_ui/ethernet_ui.cpp32
-rw-r--r--recovery_ui/include/recovery_ui/device.h12
-rw-r--r--recovery_ui/include/recovery_ui/ethernet_ui.h34
-rw-r--r--recovery_ui/include/recovery_ui/ui.h4
-rw-r--r--recovery_ui/screen_ui.cpp21
-rw-r--r--recovery_utils/roots.cpp10
-rw-r--r--tests/Android.bp1
-rw-r--r--tests/unit/install_test.cpp28
-rw-r--r--uncrypt/uncrypt.cpp6
-rw-r--r--updater/updater_runtime.cpp60
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*>(&current_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 {