Merge "Add myself to janitor owners."
diff --git a/debuggerd/Android.bp b/debuggerd/Android.bp
index 7afbbe7..15b5813 100644
--- a/debuggerd/Android.bp
+++ b/debuggerd/Android.bp
@@ -467,28 +467,36 @@
arch: {
arm: {
src: "seccomp_policy/crash_dump.arm.policy",
+ required: [
+ "crash_dump.policy_other",
+ ],
},
arm64: {
src: "seccomp_policy/crash_dump.arm64.policy",
+ required: [
+ "crash_dump.policy_other",
+ ],
},
riscv64: {
src: "seccomp_policy/crash_dump.riscv64.policy",
},
x86: {
src: "seccomp_policy/crash_dump.x86.policy",
+ required: [
+ "crash_dump.policy_other",
+ ],
},
x86_64: {
src: "seccomp_policy/crash_dump.x86_64.policy",
+ required: [
+ "crash_dump.policy_other",
+ ],
},
},
- required: [
- "crash_dump.policy_other",
- ],
}
-// NB -- this installs "the other" architecture. (puts 32 bit config in on 64 bit device)
-// or at least that is the intention so that we get both of them populated
+// This installs the "other" architecture (so 32-bit on 64-bit device).
prebuilt_etc {
name: "crash_dump.policy_other",
sub_dir: "seccomp_policy",
diff --git a/fastboot/Android.bp b/fastboot/Android.bp
index eed49fa..765174b 100644
--- a/fastboot/Android.bp
+++ b/fastboot/Android.bp
@@ -168,6 +168,7 @@
"android.hardware.boot-V1-ndk",
"libboot_control_client",
"android.hardware.fastboot@1.1",
+ "android.hardware.fastboot-V1-ndk",
"android.hardware.health@2.0",
"android.hardware.health-V1-ndk",
"libasyncio",
@@ -192,6 +193,7 @@
"libc++fs",
"libhealthhalutils",
"libhealthshim",
+ "libfastbootshim",
"libsnapshot_cow",
"liblz4",
"libsnapshot_nobinder",
diff --git a/fastboot/constants.h b/fastboot/constants.h
index f6fc74e..ad169d1 100644
--- a/fastboot/constants.h
+++ b/fastboot/constants.h
@@ -64,6 +64,7 @@
#define FB_VAR_SLOT_UNBOOTABLE "slot-unbootable"
#define FB_VAR_IS_LOGICAL "is-logical"
#define FB_VAR_IS_USERSPACE "is-userspace"
+#define FB_VAR_IS_FORCE_DEBUGGABLE "is-force-debuggable"
#define FB_VAR_HW_REVISION "hw-revision"
#define FB_VAR_VARIANT "variant"
#define FB_VAR_OFF_MODE_CHARGE_STATE "off-mode-charge"
diff --git a/fastboot/device/commands.cpp b/fastboot/device/commands.cpp
index 3799d1f..e929f42 100644
--- a/fastboot/device/commands.cpp
+++ b/fastboot/device/commands.cpp
@@ -57,8 +57,6 @@
using android::fs_mgr::MetadataBuilder;
using android::hal::CommandResult;
using ::android::hardware::hidl_string;
-using ::android::hardware::fastboot::V1_0::Result;
-using ::android::hardware::fastboot::V1_0::Status;
using android::snapshot::SnapshotManager;
using MergeStatus = android::hal::BootControlClient::MergeStatus;
@@ -133,6 +131,7 @@
{FB_VAR_PARTITION_TYPE, {GetPartitionType, GetAllPartitionArgsWithSlot}},
{FB_VAR_IS_LOGICAL, {GetPartitionIsLogical, GetAllPartitionArgsWithSlot}},
{FB_VAR_IS_USERSPACE, {GetIsUserspace, nullptr}},
+ {FB_VAR_IS_FORCE_DEBUGGABLE, {GetIsForceDebuggable, nullptr}},
{FB_VAR_OFF_MODE_CHARGE_STATE, {GetOffModeChargeState, nullptr}},
{FB_VAR_BATTERY_VOLTAGE, {GetBatteryVoltage, nullptr}},
{FB_VAR_BATTERY_SOC_OK, {GetBatterySoCOk, nullptr}},
@@ -203,20 +202,21 @@
return false;
}
- Result ret;
- auto ret_val = fastboot_hal->doOemSpecificErase([&](Result result) { ret = result; });
- if (!ret_val.isOk()) {
- return false;
- }
- if (ret.status == Status::NOT_SUPPORTED) {
- return false;
- } else if (ret.status != Status::SUCCESS) {
- device->WriteStatus(FastbootResult::FAIL, ret.message);
- } else {
+ auto status = fastboot_hal->doOemSpecificErase();
+ if (status.isOk()) {
device->WriteStatus(FastbootResult::OKAY, "Erasing succeeded");
+ return true;
}
-
- return true;
+ switch (status.getExceptionCode()) {
+ case EX_UNSUPPORTED_OPERATION:
+ return false;
+ case EX_SERVICE_SPECIFIC:
+ device->WriteStatus(FastbootResult::FAIL, status.getDescription());
+ return false;
+ default:
+ LOG(ERROR) << "Erase operation failed" << status.getDescription();
+ return false;
+ }
}
bool EraseHandler(FastbootDevice* device, const std::vector<std::string>& args) {
@@ -266,18 +266,16 @@
if (args[0] == "oem postwipedata userdata") {
return device->WriteStatus(FastbootResult::FAIL, "Unable to do oem postwipedata userdata");
}
-
- Result ret;
- auto ret_val = fastboot_hal->doOemCommand(args[0], [&](Result result) { ret = result; });
- if (!ret_val.isOk()) {
- return device->WriteStatus(FastbootResult::FAIL, "Unable to do OEM command");
- }
- if (ret.status != Status::SUCCESS) {
- return device->WriteStatus(FastbootResult::FAIL, ret.message);
+ std::string message;
+ auto status = fastboot_hal->doOemCommand(args[0], &message);
+ if (!status.isOk()) {
+ LOG(ERROR) << "Unable to do OEM command " << args[0].c_str() << status.getDescription();
+ return device->WriteStatus(FastbootResult::FAIL,
+ "Unable to do OEM command " + status.getDescription());
}
- device->WriteInfo(ret.message);
- return device->WriteStatus(FastbootResult::OKAY, ret.message);
+ device->WriteInfo(message);
+ return device->WriteStatus(FastbootResult::OKAY, message);
}
bool DownloadHandler(FastbootDevice* device, const std::vector<std::string>& args) {
diff --git a/fastboot/device/fastboot_device.cpp b/fastboot/device/fastboot_device.cpp
index 4932e5c..5afeb4f 100644
--- a/fastboot/device/fastboot_device.cpp
+++ b/fastboot/device/fastboot_device.cpp
@@ -25,6 +25,7 @@
#include <android/binder_manager.h>
#include <android/hardware/boot/1.0/IBootControl.h>
#include <android/hardware/fastboot/1.1/IFastboot.h>
+#include <fastbootshim.h>
#include <fs_mgr.h>
#include <fs_mgr/roots.h>
#include <health-shim/shim.h>
@@ -64,6 +65,27 @@
return nullptr;
}
+std::shared_ptr<aidl::android::hardware::fastboot::IFastboot> get_fastboot_service() {
+ using aidl::android::hardware::fastboot::IFastboot;
+ using HidlFastboot = android::hardware::fastboot::V1_1::IFastboot;
+ using aidl::android::hardware::fastboot::FastbootShim;
+ auto service_name = IFastboot::descriptor + "/default"s;
+ ndk::SpAIBinder binder(AServiceManager_getService(service_name.c_str()));
+ std::shared_ptr<IFastboot> fastboot = IFastboot::fromBinder(binder);
+ if (fastboot != nullptr) {
+ LOG(INFO) << "Using AIDL fastboot service";
+ return fastboot;
+ }
+ LOG(INFO) << "Unable to get AIDL fastboot service, trying HIDL...";
+ android::sp<HidlFastboot> hidl_fastboot = HidlFastboot::getService();
+ if (hidl_fastboot != nullptr) {
+ LOG(INFO) << "Found and now using fastboot HIDL implementation";
+ return ndk::SharedRefBase::make<FastbootShim>(hidl_fastboot);
+ }
+ LOG(WARNING) << "No fastboot implementation is found.";
+ return nullptr;
+}
+
FastbootDevice::FastbootDevice()
: kCommandMap({
{FB_CMD_SET_ACTIVE, SetActiveHandler},
@@ -87,7 +109,7 @@
}),
boot_control_hal_(BootControlClient::WaitForService()),
health_hal_(get_health_service()),
- fastboot_hal_(IFastboot::getService()),
+ fastboot_hal_(get_fastboot_service()),
active_slot_("") {
if (android::base::GetProperty("fastbootd.protocol", "usb") == "tcp") {
transport_ = std::make_unique<ClientTcpTransport>();
diff --git a/fastboot/device/fastboot_device.h b/fastboot/device/fastboot_device.h
index 9df8fa5..fcaf249 100644
--- a/fastboot/device/fastboot_device.h
+++ b/fastboot/device/fastboot_device.h
@@ -23,8 +23,8 @@
#include <vector>
#include <BootControlClient.h>
+#include <aidl/android/hardware/fastboot/IFastboot.h>
#include <aidl/android/hardware/health/IHealth.h>
-#include <android/hardware/fastboot/1.1/IFastboot.h>
#include "commands.h"
#include "transport.h"
@@ -52,7 +52,7 @@
Transport* get_transport() { return transport_.get(); }
BootControlClient* boot_control_hal() const { return boot_control_hal_.get(); }
BootControlClient* boot1_1() const;
- android::sp<android::hardware::fastboot::V1_1::IFastboot> fastboot_hal() {
+ std::shared_ptr<aidl::android::hardware::fastboot::IFastboot> fastboot_hal() {
return fastboot_hal_;
}
std::shared_ptr<aidl::android::hardware::health::IHealth> health_hal() { return health_hal_; }
@@ -65,7 +65,7 @@
std::unique_ptr<Transport> transport_;
std::unique_ptr<BootControlClient> boot_control_hal_;
std::shared_ptr<aidl::android::hardware::health::IHealth> health_hal_;
- android::sp<android::hardware::fastboot::V1_1::IFastboot> fastboot_hal_;
+ std::shared_ptr<aidl::android::hardware::fastboot::IFastboot> fastboot_hal_;
std::vector<char> download_data_;
std::string active_slot_;
};
diff --git a/fastboot/device/variables.cpp b/fastboot/device/variables.cpp
index b6eb2cd..d2a7947 100644
--- a/fastboot/device/variables.cpp
+++ b/fastboot/device/variables.cpp
@@ -41,9 +41,7 @@
#endif
using MergeStatus = android::hal::BootControlClient::MergeStatus;
-using ::android::hardware::fastboot::V1_0::FileSystemType;
-using ::android::hardware::fastboot::V1_0::Result;
-using ::android::hardware::fastboot::V1_0::Status;
+using aidl::android::hardware::fastboot::FileSystemType;
using namespace android::fs_mgr;
using namespace std::string_literals;
@@ -104,17 +102,16 @@
*message = "Fastboot HAL not found";
return false;
}
+ std::string device_variant = "";
+ auto status = fastboot_hal->getVariant(&device_variant);
- Result ret;
- auto ret_val = fastboot_hal->getVariant([&](std::string device_variant, Result result) {
- *message = device_variant;
- ret = result;
- });
- if (!ret_val.isOk() || ret.status != Status::SUCCESS) {
+ if (!status.isOk()) {
*message = "Unable to get device variant";
+ LOG(ERROR) << message->c_str() << status.getDescription();
return false;
}
+ *message = device_variant;
return true;
}
@@ -147,17 +144,14 @@
return false;
}
- Result ret;
- auto ret_val = fastboot_hal->getBatteryVoltageFlashingThreshold(
- [&](int32_t voltage_threshold, Result result) {
- *message = battery_voltage >= voltage_threshold ? "yes" : "no";
- ret = result;
- });
-
- if (!ret_val.isOk() || ret.status != Status::SUCCESS) {
+ auto voltage_threshold = 0;
+ auto status = fastboot_hal->getBatteryVoltageFlashingThreshold(&voltage_threshold);
+ if (!status.isOk()) {
*message = "Unable to get battery voltage flashing threshold";
+ LOG(ERROR) << message->c_str() << status.getDescription();
return false;
}
+ *message = battery_voltage >= voltage_threshold ? "yes" : "no";
return true;
}
@@ -169,18 +163,14 @@
*message = "Fastboot HAL not found";
return false;
}
-
- Result ret;
- auto ret_val =
- fastboot_hal->getOffModeChargeState([&](bool off_mode_charging_state, Result result) {
- *message = off_mode_charging_state ? "1" : "0";
- ret = result;
- });
- if (!ret_val.isOk() || (ret.status != Status::SUCCESS)) {
+ bool off_mode_charging_state = false;
+ auto status = fastboot_hal->getOffModeChargeState(&off_mode_charging_state);
+ if (!status.isOk()) {
*message = "Unable to get off mode charge state";
+ LOG(ERROR) << message->c_str() << status.getDescription();
return false;
}
-
+ *message = off_mode_charging_state ? "1" : "0";
return true;
}
@@ -337,14 +327,11 @@
}
FileSystemType type;
- Result ret;
- auto ret_val =
- fastboot_hal->getPartitionType(args[0], [&](FileSystemType fs_type, Result result) {
- type = fs_type;
- ret = result;
- });
- if (!ret_val.isOk() || (ret.status != Status::SUCCESS)) {
+ auto status = fastboot_hal->getPartitionType(args[0], &type);
+
+ if (!status.isOk()) {
*message = "Unable to retrieve partition type";
+ LOG(ERROR) << message->c_str() << status.getDescription();
} else {
switch (type) {
case FileSystemType::RAW:
@@ -392,6 +379,12 @@
return true;
}
+bool GetIsForceDebuggable(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
+ std::string* message) {
+ *message = android::base::GetBoolProperty("ro.force.debuggable", false) ? "yes" : "no";
+ return true;
+}
+
std::vector<std::vector<std::string>> GetAllPartitionArgsWithSlot(FastbootDevice* device) {
std::vector<std::vector<std::string>> args;
auto partitions = ListPartitions(device);
diff --git a/fastboot/device/variables.h b/fastboot/device/variables.h
index aa4d9fc..3b2d484 100644
--- a/fastboot/device/variables.h
+++ b/fastboot/device/variables.h
@@ -54,6 +54,8 @@
std::string* message);
bool GetIsUserspace(FastbootDevice* device, const std::vector<std::string>& args,
std::string* message);
+bool GetIsForceDebuggable(FastbootDevice* device, const std::vector<std::string>& args,
+ std::string* message);
bool GetHardwareRevision(FastbootDevice* device, const std::vector<std::string>& args,
std::string* message);
bool GetVariant(FastbootDevice* device, const std::vector<std::string>& args, std::string* message);
diff --git a/fastboot/socket_test.cpp b/fastboot/socket_test.cpp
index 373abc3..74ff377 100644
--- a/fastboot/socket_test.cpp
+++ b/fastboot/socket_test.cpp
@@ -293,23 +293,23 @@
}
TEST(SocketMockTest, TestSendFailure) {
- SocketMock* mock = new SocketMock;
+ std::unique_ptr<SocketMock> mock(new SocketMock);
mock->ExpectSendFailure("foo");
- EXPECT_FALSE(SendString(mock, "foo"));
+ EXPECT_FALSE(SendString(mock.get(), "foo"));
- EXPECT_NONFATAL_FAILURE(SendString(mock, "foo"), "no message was expected");
+ EXPECT_NONFATAL_FAILURE(SendString(mock.get(), "foo"), "no message was expected");
mock->ExpectSend("foo");
- EXPECT_NONFATAL_FAILURE(SendString(mock, "bar"), "expected foo, but got bar");
- EXPECT_TRUE(SendString(mock, "foo"));
+ EXPECT_NONFATAL_FAILURE(SendString(mock.get(), "bar"), "expected foo, but got bar");
+ EXPECT_TRUE(SendString(mock.get(), "foo"));
mock->AddReceive("foo");
- EXPECT_NONFATAL_FAILURE(SendString(mock, "foo"), "called out-of-order");
- EXPECT_TRUE(ReceiveString(mock, "foo"));
+ EXPECT_NONFATAL_FAILURE(SendString(mock.get(), "foo"), "called out-of-order");
+ EXPECT_TRUE(ReceiveString(mock.get(), "foo"));
mock->ExpectSend("foo");
- EXPECT_NONFATAL_FAILURE(delete mock, "1 event(s) were not handled");
+ EXPECT_NONFATAL_FAILURE(mock.reset(), "1 event(s) were not handled");
}
TEST(SocketMockTest, TestReceiveSuccess) {
@@ -331,33 +331,33 @@
}
TEST(SocketMockTest, TestReceiveFailure) {
- SocketMock* mock = new SocketMock;
+ std::unique_ptr<SocketMock> mock(new SocketMock);
mock->AddReceiveFailure();
- EXPECT_FALSE(ReceiveString(mock, "foo"));
+ EXPECT_FALSE(ReceiveString(mock.get(), "foo"));
EXPECT_FALSE(mock->ReceiveTimedOut());
mock->AddReceiveTimeout();
- EXPECT_FALSE(ReceiveString(mock, "foo"));
+ EXPECT_FALSE(ReceiveString(mock.get(), "foo"));
EXPECT_TRUE(mock->ReceiveTimedOut());
mock->AddReceive("foo");
mock->AddReceiveFailure();
- EXPECT_FALSE(ReceiveString(mock, "foobar"));
+ EXPECT_FALSE(ReceiveString(mock.get(), "foobar"));
- EXPECT_NONFATAL_FAILURE(ReceiveString(mock, "foo"), "no message was ready");
+ EXPECT_NONFATAL_FAILURE(ReceiveString(mock.get(), "foo"), "no message was ready");
mock->ExpectSend("foo");
- EXPECT_NONFATAL_FAILURE(ReceiveString(mock, "foo"), "called out-of-order");
- EXPECT_TRUE(SendString(mock, "foo"));
+ EXPECT_NONFATAL_FAILURE(ReceiveString(mock.get(), "foo"), "called out-of-order");
+ EXPECT_TRUE(SendString(mock.get(), "foo"));
char c;
mock->AddReceive("foo");
EXPECT_NONFATAL_FAILURE(mock->Receive(&c, 1, 0), "not enough bytes (1) for foo");
- EXPECT_TRUE(ReceiveString(mock, "foo"));
+ EXPECT_TRUE(ReceiveString(mock.get(), "foo"));
mock->AddReceive("foo");
- EXPECT_NONFATAL_FAILURE(delete mock, "1 event(s) were not handled");
+ EXPECT_NONFATAL_FAILURE(mock.reset(), "1 event(s) were not handled");
}
TEST(SocketMockTest, TestAcceptSuccess) {
@@ -372,14 +372,14 @@
}
TEST(SocketMockTest, TestAcceptFailure) {
- SocketMock* mock = new SocketMock;
+ std::unique_ptr<SocketMock> mock(new SocketMock);
EXPECT_NONFATAL_FAILURE(mock->Accept(), "no socket was ready");
mock->ExpectSend("foo");
EXPECT_NONFATAL_FAILURE(mock->Accept(), "called out-of-order");
- EXPECT_TRUE(SendString(mock, "foo"));
+ EXPECT_TRUE(SendString(mock.get(), "foo"));
mock->AddAccept(nullptr);
- EXPECT_NONFATAL_FAILURE(delete mock, "1 event(s) were not handled");
+ EXPECT_NONFATAL_FAILURE(mock.reset(), "1 event(s) were not handled");
}
diff --git a/fs_mgr/Android.bp b/fs_mgr/Android.bp
index bebf19e..dd61272 100644
--- a/fs_mgr/Android.bp
+++ b/fs_mgr/Android.bp
@@ -251,41 +251,8 @@
},
symlinks: [
"clean_scratch_files",
- ],
-}
-
-cc_binary {
- name: "set-verity-state",
- srcs: ["set-verity-state.cpp"],
- shared_libs: [
- "libbase",
- "libbinder",
- "libcrypto",
- "libcrypto_utils",
- "libfs_mgr_binder",
- "libutils",
- ],
- static_libs: [
- "libavb_user",
- ],
- header_libs: [
- "libcutils_headers",
- ],
-
- cflags: ["-Werror"],
- cppflags: [
- "-DALLOW_DISABLE_VERITY=0",
- ],
- product_variables: {
- debuggable: {
- cppflags: [
- "-UALLOW_DISABLE_VERITY",
- "-DALLOW_DISABLE_VERITY=1",
- ],
- },
- },
- symlinks: [
- "enable-verity",
"disable-verity",
+ "enable-verity",
+ "set-verity-state",
],
}
diff --git a/fs_mgr/OWNERS b/fs_mgr/OWNERS
index 6f1059b..bd46489 100644
--- a/fs_mgr/OWNERS
+++ b/fs_mgr/OWNERS
@@ -1,4 +1,4 @@
-# Bug component: 30545
+# Bug component: 325626
bowgotsai@google.com
dvander@google.com
elsk@google.com
diff --git a/fs_mgr/fs_mgr_overlayfs.cpp b/fs_mgr/fs_mgr_overlayfs.cpp
index 5468fb8..bb24abf 100644
--- a/fs_mgr/fs_mgr_overlayfs.cpp
+++ b/fs_mgr/fs_mgr_overlayfs.cpp
@@ -69,6 +69,7 @@
namespace {
constexpr char kDataScratchSizeMbProp[] = "fs_mgr.overlayfs.data_scratch_size_mb";
+constexpr char kPreferCacheBackingStorageProp[] = "fs_mgr.overlayfs.prefer_cache_backing_storage";
bool fs_mgr_access(const std::string& path) {
return access(path.c_str(), F_OK) == 0;
@@ -101,6 +102,10 @@
const auto kScratchMountPoint = "/mnt/scratch"s;
const auto kCacheMountPoint = "/cache"s;
+bool IsABDevice() {
+ return !android::base::GetProperty("ro.boot.slot_suffix", "").empty();
+}
+
std::vector<const std::string> OverlayMountPoints() {
// Never fallback to legacy cache mount point if within a DSU system,
// because running a DSU system implies the device supports dynamic
@@ -108,6 +113,15 @@
if (fs_mgr_is_dsu_running()) {
return {kScratchMountPoint};
}
+
+ // For non-A/B devices prefer cache backing storage if
+ // kPreferCacheBackingStorageProp property set.
+ if (!IsABDevice() &&
+ android::base::GetBoolProperty(kPreferCacheBackingStorageProp, false) &&
+ android::base::GetIntProperty("ro.vendor.api_level", -1) < __ANDROID_API_T__) {
+ return {kCacheMountPoint, kScratchMountPoint};
+ }
+
return {kScratchMountPoint, kCacheMountPoint};
}
diff --git a/fs_mgr/fs_mgr_remount.cpp b/fs_mgr/fs_mgr_remount.cpp
index 2edaaad..23bc8e8 100644
--- a/fs_mgr/fs_mgr_remount.cpp
+++ b/fs_mgr/fs_mgr_remount.cpp
@@ -22,6 +22,7 @@
#include <sys/vfs.h>
#include <unistd.h>
+#include <iostream>
#include <string>
#include <thread>
#include <utility>
@@ -33,6 +34,7 @@
#include <android-base/strings.h>
#include <android/os/IVold.h>
#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
#include <bootloader_message/bootloader_message.h>
#include <cutils/android_reboot.h>
#include <fs_mgr_overlayfs.h>
@@ -50,17 +52,34 @@
namespace {
void usage() {
- LOG(INFO) << getprogname()
- << " [-h] [-R] [-T fstab_file] [partition]...\n"
- "\t-h --help\tthis help\n"
- "\t-R --reboot\tdisable verity & reboot to facilitate remount\n"
- "\t-T --fstab\tcustom fstab file location\n"
- "\tpartition\tspecific partition(s) (empty does all)\n"
- "\n"
- "Remount specified partition(s) read-write, by name or mount point.\n"
- "-R notwithstanding, verity must be disabled on partition(s).\n"
- "-R within a DSU guest system reboots into the DSU instead of the host system,\n"
- "this command would enable DSU (one-shot) if not already enabled.";
+ const std::string progname = getprogname();
+ if (progname == "disable-verity" || progname == "enable-verity" ||
+ progname == "set-verity-state") {
+ std::cout << "Usage: disable-verity\n"
+ << " enable-verity\n"
+ << " set-verity-state [0|1]\n"
+ << R"(
+Options:
+ -h --help this help
+ -R --reboot automatic reboot if needed for new settings to take effect
+ -v --verbose be noisy)"
+ << std::endl;
+ } else {
+ std::cout << "Usage: " << progname << " [-h] [-R] [-T fstab_file] [partition]...\n"
+ << R"(
+Options:
+ -h --help this help
+ -R --reboot disable verity & reboot to facilitate remount
+ -v --verbose be noisy
+ -T --fstab custom fstab file location
+ partition specific partition(s) (empty does all)
+
+Remount specified partition(s) read-write, by name or mount point.
+-R notwithstanding, verity must be disabled on partition(s).
+-R within a DSU guest system reboots into the DSU instead of the host system,
+this command would enable DSU (one-shot) if not already enabled.)"
+ << std::endl;
+ }
}
const std::string system_mount_point(const android::fs_mgr::FstabEntry& entry) {
@@ -79,23 +98,32 @@
return &(*it);
}
-auto verbose = false;
+class MyLogger {
+ public:
+ explicit MyLogger(bool verbose) : verbose_(verbose) {}
-void MyLogger(android::base::LogId id, android::base::LogSeverity severity, const char* tag,
- const char* file, unsigned int line, const char* message) {
- if (verbose || severity == android::base::ERROR || message[0] != '[') {
- fprintf(stderr, "%s\n", message);
+ void operator()(android::base::LogId id, android::base::LogSeverity severity, const char* tag,
+ const char* file, unsigned int line, const char* message) {
+ // By default, print ERROR logs and logs of this program (does not start with '[')
+ // Print [libfs_mgr] INFO logs only if -v is given.
+ if (verbose_ || severity >= android::base::ERROR || message[0] != '[') {
+ fprintf(stderr, "%s\n", message);
+ }
+ logd_(id, severity, tag, file, line, message);
}
- static auto logd = android::base::LogdLogger();
- logd(id, severity, tag, file, line, message);
-}
-[[noreturn]] void reboot() {
+ private:
+ android::base::LogdLogger logd_;
+ bool verbose_;
+};
+
+[[noreturn]] void reboot(const std::string& name) {
LOG(INFO) << "Rebooting device for new settings to take effect";
::sync();
- android::base::SetProperty(ANDROID_RB_PROPERTY, "reboot,remount");
+ android::base::SetProperty(ANDROID_RB_PROPERTY, "reboot," + name);
::sleep(60);
- ::exit(0); // SUCCESS
+ LOG(ERROR) << "Failed to reboot";
+ ::exit(1);
}
static android::sp<android::os::IVold> GetVold() {
@@ -111,21 +139,6 @@
}
}
-} // namespace
-
-enum RemountStatus {
- REMOUNT_SUCCESS = 0,
- UNKNOWN_PARTITION = 5,
- INVALID_PARTITION,
- VERITY_PARTITION,
- BAD_OVERLAY,
- NO_MOUNTS,
- REMOUNT_FAILED,
- BINDER_ERROR,
- CHECKPOINTING,
- GSID_ERROR,
-};
-
static bool ReadFstab(const char* fstab_file, android::fs_mgr::Fstab* fstab) {
if (fstab_file) {
return android::fs_mgr::ReadFstabFromFile(fstab_file, fstab);
@@ -146,10 +159,10 @@
return true;
}
-static RemountStatus VerifyCheckpointing() {
+bool VerifyCheckpointing() {
if (!android::base::GetBoolProperty("ro.virtual_ab.enabled", false) &&
!android::base::GetBoolProperty("ro.virtual_ab.retrofit", false)) {
- return REMOUNT_SUCCESS;
+ return true;
}
// Virtual A/B devices can use /data as backing storage; make sure we're
@@ -158,13 +171,13 @@
bool checkpointing = false;
if (!vold->isCheckpointing(&checkpointing).isOk()) {
LOG(ERROR) << "Could not determine checkpointing status.";
- return BINDER_ERROR;
+ return false;
}
if (checkpointing) {
LOG(ERROR) << "Cannot use remount when a checkpoint is in progress.";
- return CHECKPOINTING;
+ return false;
}
- return REMOUNT_SUCCESS;
+ return true;
}
static bool IsRemountable(Fstab& candidates, const FstabEntry& entry) {
@@ -221,8 +234,7 @@
return partitions;
}
-static RemountStatus GetRemountList(const Fstab& fstab, const std::vector<std::string>& argv,
- Fstab* partitions) {
+bool GetRemountList(const Fstab& fstab, const std::vector<std::string>& argv, Fstab* partitions) {
auto candidates = fs_mgr_overlayfs_candidate_list(fstab);
for (const auto& arg : argv) {
@@ -234,7 +246,7 @@
auto it = FindPartition(fstab, partition);
if (it == fstab.end()) {
LOG(ERROR) << "Unknown partition " << arg;
- return UNKNOWN_PARTITION;
+ return false;
}
const FstabEntry* entry = &*it;
@@ -249,7 +261,7 @@
if (!fs_mgr_overlayfs_already_mounted(entry->mount_point) &&
!IsRemountable(candidates, *entry)) {
LOG(ERROR) << "Invalid partition " << arg;
- return INVALID_PARTITION;
+ return false;
}
if (GetEntryForMountPoint(partitions, entry->mount_point) != nullptr) {
continue;
@@ -257,7 +269,7 @@
partitions->emplace_back(*entry);
}
- return REMOUNT_SUCCESS;
+ return true;
}
struct RemountCheckResult {
@@ -268,43 +280,18 @@
bool remounted_anything = false;
};
-static RemountStatus CheckVerity(const FstabEntry& entry, RemountCheckResult* result) {
- if (!fs_mgr_is_verity_enabled(entry)) {
- return REMOUNT_SUCCESS;
- }
-
- std::unique_ptr<AvbOps, decltype(&::avb_ops_user_free)> ops(avb_ops_user_new(),
- &::avb_ops_user_free);
- if (!ops) {
- return VERITY_PARTITION;
- }
- if (!avb_user_verity_set(ops.get(), fs_mgr_get_slot_suffix().c_str(), false)) {
- return VERITY_PARTITION;
- }
- result->disabled_verity = true;
- result->reboot_later = true;
- return REMOUNT_SUCCESS;
-}
-
-static RemountStatus CheckVerityAndOverlayfs(Fstab* partitions, RemountCheckResult* result) {
- RemountStatus status = REMOUNT_SUCCESS;
+bool CheckOverlayfs(Fstab* partitions, RemountCheckResult* result) {
+ bool ok = true;
for (auto it = partitions->begin(); it != partitions->end();) {
auto& entry = *it;
const auto& mount_point = entry.mount_point;
- if (auto rv = CheckVerity(entry, result); rv != REMOUNT_SUCCESS) {
- LOG(ERROR) << "Skipping verified partition " << mount_point << " for remount";
- status = rv;
- it = partitions->erase(it);
- continue;
- }
-
if (fs_mgr_wants_overlayfs(&entry)) {
bool want_reboot = false;
bool force = result->disabled_verity;
if (!fs_mgr_overlayfs_setup(mount_point.c_str(), &want_reboot, force)) {
LOG(ERROR) << "Overlayfs setup for " << mount_point << " failed, skipping";
- status = BAD_OVERLAY;
+ ok = false;
it = partitions->erase(it);
continue;
}
@@ -316,45 +303,48 @@
}
it++;
}
- return status;
+ return ok;
}
-static RemountStatus EnableDsuIfNeeded() {
+bool EnableDsuIfNeeded() {
auto gsid = android::gsi::GetGsiService();
if (!gsid) {
- return REMOUNT_SUCCESS;
+ return true;
}
auto dsu_running = false;
if (auto status = gsid->isGsiRunning(&dsu_running); !status.isOk()) {
LOG(ERROR) << "Failed to get DSU running state: " << status;
- return BINDER_ERROR;
+ return false;
}
auto dsu_enabled = false;
if (auto status = gsid->isGsiEnabled(&dsu_enabled); !status.isOk()) {
LOG(ERROR) << "Failed to get DSU enabled state: " << status;
- return BINDER_ERROR;
+ return false;
}
if (dsu_running && !dsu_enabled) {
std::string dsu_slot;
if (auto status = gsid->getActiveDsuSlot(&dsu_slot); !status.isOk()) {
LOG(ERROR) << "Failed to get active DSU slot: " << status;
- return BINDER_ERROR;
+ return false;
}
LOG(INFO) << "DSU is running but disabled, enable DSU so that we stay within the "
"DSU guest system after reboot";
int error = 0;
- if (auto status = gsid->enableGsi(/* oneShot = */ true, dsu_slot, &error);
- !status.isOk() || error != android::gsi::IGsiService::INSTALL_OK) {
- LOG(ERROR) << "Failed to enable DSU: " << status << ", error code: " << error;
- return !status.isOk() ? BINDER_ERROR : GSID_ERROR;
+ if (auto status = gsid->enableGsi(/* oneShot = */ true, dsu_slot, &error); !status.isOk()) {
+ LOG(ERROR) << "Failed to enable DSU: " << status;
+ return false;
+ }
+ if (error != android::gsi::IGsiService::INSTALL_OK) {
+ LOG(ERROR) << "Failed to enable DSU, error code: " << error;
+ return false;
}
LOG(INFO) << "Successfully enabled DSU (one-shot mode)";
}
- return REMOUNT_SUCCESS;
+ return true;
}
-static RemountStatus RemountPartition(Fstab& fstab, Fstab& mounts, FstabEntry& entry) {
+bool RemountPartition(Fstab& fstab, Fstab& mounts, FstabEntry& entry) {
// unlock the r/o key for the mount point device
if (entry.fs_mgr_flags.logical) {
fs_mgr_update_logical_partition(&entry);
@@ -381,7 +371,7 @@
}
if (!found) {
PLOG(INFO) << "skip unmounted partition dev:" << blk_device << " mnt:" << mount_point;
- return REMOUNT_SUCCESS;
+ return true;
}
if (blk_device == "/dev/root") {
auto from_fstab = GetEntryForMountPoint(&fstab, mount_point);
@@ -396,41 +386,128 @@
}
// Now remount!
- if (::mount(blk_device.c_str(), mount_point.c_str(), entry.fs_type.c_str(), MS_REMOUNT,
- nullptr) == 0) {
- return REMOUNT_SUCCESS;
- }
- if ((errno == EINVAL) && (mount_point != entry.mount_point)) {
- mount_point = entry.mount_point;
- if (::mount(blk_device.c_str(), mount_point.c_str(), entry.fs_type.c_str(), MS_REMOUNT,
+ for (const auto& mnt_point : {mount_point, entry.mount_point}) {
+ if (::mount(blk_device.c_str(), mnt_point.c_str(), entry.fs_type.c_str(), MS_REMOUNT,
nullptr) == 0) {
- return REMOUNT_SUCCESS;
+ LOG(INFO) << "Remounted " << mnt_point << " as RW";
+ return true;
+ }
+ if (errno != EINVAL || mount_point == entry.mount_point) {
+ break;
}
}
PLOG(ERROR) << "failed to remount partition dev:" << blk_device << " mnt:" << mount_point;
- return REMOUNT_FAILED;
+ return false;
}
-static int do_remount(Fstab& fstab, const std::vector<std::string>& partition_args,
- RemountCheckResult* check_result) {
+struct SetVerityStateResult {
+ bool success = false;
+ bool want_reboot = false;
+};
+
+SetVerityStateResult SetVerityState(bool enable_verity) {
+ const auto ab_suffix = android::base::GetProperty("ro.boot.slot_suffix", "");
+ std::unique_ptr<AvbOps, decltype(&avb_ops_user_free)> ops(avb_ops_user_new(),
+ &avb_ops_user_free);
+ if (!ops) {
+ LOG(ERROR) << "Error getting AVB ops";
+ return {};
+ }
+ if (!avb_user_verity_set(ops.get(), ab_suffix.c_str(), enable_verity)) {
+ LOG(ERROR) << "Error setting verity state";
+ return {};
+ }
+ bool verification_enabled = false;
+ if (!avb_user_verification_get(ops.get(), ab_suffix.c_str(), &verification_enabled)) {
+ LOG(ERROR) << "Error getting verification state";
+ return {};
+ }
+ if (!verification_enabled) {
+ LOG(WARNING) << "AVB verification is disabled, "
+ << (enable_verity ? "enabling" : "disabling")
+ << " verity state may have no effect";
+ return {.success = true, .want_reboot = false};
+ }
+ const auto verity_mode = android::base::GetProperty("ro.boot.veritymode", "");
+ const bool was_enabled = (verity_mode != "disabled");
+ if ((was_enabled && enable_verity) || (!was_enabled && !enable_verity)) {
+ LOG(INFO) << "Verity is already " << (enable_verity ? "enabled" : "disabled");
+ return {.success = true, .want_reboot = false};
+ }
+ LOG(INFO) << "Successfully " << (enable_verity ? "enabled" : "disabled") << " verity";
+ return {.success = true, .want_reboot = true};
+}
+
+bool SetupOrTeardownOverlayfs(bool enable) {
+ bool want_reboot = false;
+ if (enable) {
+ if (!fs_mgr_overlayfs_setup(nullptr, &want_reboot)) {
+ LOG(ERROR) << "Overlayfs setup failed.";
+ return want_reboot;
+ }
+ if (want_reboot) {
+ printf("enabling overlayfs\n");
+ }
+ } else {
+ auto rv = fs_mgr_overlayfs_teardown(nullptr, &want_reboot);
+ if (rv == OverlayfsTeardownResult::Error) {
+ LOG(ERROR) << "Overlayfs teardown failed.";
+ return want_reboot;
+ }
+ if (rv == OverlayfsTeardownResult::Busy) {
+ LOG(ERROR) << "Overlayfs is still active until reboot.";
+ return true;
+ }
+ if (want_reboot) {
+ printf("disabling overlayfs\n");
+ }
+ }
+ return want_reboot;
+}
+
+bool do_remount(Fstab& fstab, const std::vector<std::string>& partition_args,
+ RemountCheckResult* check_result) {
Fstab partitions;
if (partition_args.empty()) {
partitions = GetAllRemountablePartitions(fstab);
} else {
- if (auto rv = GetRemountList(fstab, partition_args, &partitions); rv != REMOUNT_SUCCESS) {
- return rv;
+ if (!GetRemountList(fstab, partition_args, &partitions)) {
+ return false;
}
}
- // Check verity and optionally setup overlayfs backing.
- auto retval = CheckVerityAndOverlayfs(&partitions, check_result);
+ // Disable verity.
+ auto verity_result = SetVerityState(false /* enable_verity */);
+
+ // Treat error as fatal and suggest reboot only if verity is enabled.
+ // TODO(b/260041315): We check the device mapper for any "<partition>-verity" device present
+ // instead of checking ro.boot.veritymode because emulator has incorrect property value.
+ bool must_disable_verity = false;
+ for (const auto& partition : partitions) {
+ if (fs_mgr_is_verity_enabled(partition)) {
+ must_disable_verity = true;
+ break;
+ }
+ }
+ if (must_disable_verity) {
+ if (!verity_result.success) {
+ return false;
+ }
+ if (verity_result.want_reboot) {
+ check_result->reboot_later = true;
+ check_result->disabled_verity = true;
+ }
+ }
+
+ // Optionally setup overlayfs backing.
+ bool ok = CheckOverlayfs(&partitions, check_result);
if (partitions.empty() || check_result->disabled_verity) {
if (partitions.empty()) {
LOG(WARNING) << "No remountable partitions were found.";
}
- return retval;
+ return ok;
}
// Mount overlayfs.
@@ -443,51 +520,35 @@
android::fs_mgr::Fstab mounts;
if (!android::fs_mgr::ReadFstabFromFile("/proc/mounts", &mounts) || mounts.empty()) {
PLOG(ERROR) << "Failed to read /proc/mounts";
- return NO_MOUNTS;
+ return false;
}
// Remount selected partitions.
for (auto& entry : partitions) {
- if (auto rv = RemountPartition(fstab, mounts, entry); rv != REMOUNT_SUCCESS) {
- retval = rv;
- } else {
+ if (RemountPartition(fstab, mounts, entry)) {
check_result->remounted_anything = true;
+ } else {
+ ok = false;
}
}
- return retval;
+ return ok;
}
+} // namespace
+
int main(int argc, char* argv[]) {
// Do not use MyLogger() when running as clean_scratch_files, as stdout/stderr of daemon process
// are discarded.
if (argc > 0 && android::base::Basename(argv[0]) == "clean_scratch_files"s) {
android::fs_mgr::CleanupOldScratchFiles();
- return 0;
+ return EXIT_SUCCESS;
}
- android::base::InitLogging(argv, MyLogger);
-
- // Make sure we are root.
- if (::getuid() != 0) {
- LOG(ERROR) << "Not running as root. Try \"adb root\" first.";
- return 1;
- }
-
- // If somehow this executable is delivered on a "user" build, it can
- // not function, so providing a clear message to the caller rather than
- // letting if fall through and provide a lot of confusing failure messages.
- if (!ALLOW_ADBD_DISABLE_VERITY || !android::base::GetBoolProperty("ro.debuggable", false)) {
- LOG(ERROR) << "Device must be userdebug build";
- return 1;
- }
-
- if (android::base::GetProperty("ro.boot.vbmeta.device_state", "") == "locked") {
- LOG(ERROR) << "Device must be bootloader unlocked";
- return 1;
- }
+ android::base::InitLogging(argv, MyLogger(false /* verbose */));
const char* fstab_file = nullptr;
- auto auto_reboot = false;
+ bool auto_reboot = false;
+ bool verbose = false;
std::vector<std::string> partition_args;
struct option longopts[] = {
@@ -501,15 +562,15 @@
switch (opt) {
case 'h':
usage();
- return 0;
+ return EXIT_SUCCESS;
case 'R':
auto_reboot = true;
break;
case 'T':
if (fstab_file) {
- LOG(ERROR) << "Cannot supply two fstabs: -T " << fstab_file << " -T" << optarg;
+ LOG(ERROR) << "Cannot supply two fstabs: -T " << fstab_file << " -T " << optarg;
usage();
- return 1;
+ return EXIT_FAILURE;
}
fstab_file = optarg;
break;
@@ -517,30 +578,92 @@
verbose = true;
break;
default:
- LOG(ERROR) << "Bad Argument -" << char(opt);
+ LOG(ERROR) << "Bad argument -" << char(opt);
usage();
- return 1;
+ return EXIT_FAILURE;
}
}
- for (; argc > optind; ++optind) {
- partition_args.emplace_back(argv[optind]);
+ if (verbose) {
+ android::base::SetLogger(MyLogger(verbose));
+ }
+
+ bool remount = false;
+ bool enable_verity = false;
+ const std::string progname = getprogname();
+ if (progname == "enable-verity") {
+ enable_verity = true;
+ } else if (progname == "disable-verity") {
+ enable_verity = false;
+ } else if (progname == "set-verity-state") {
+ if (optind < argc && (argv[optind] == "1"s || argv[optind] == "0"s)) {
+ enable_verity = (argv[optind] == "1"s);
+ } else {
+ usage();
+ return EXIT_FAILURE;
+ }
+ } else {
+ remount = true;
+ for (; optind < argc; ++optind) {
+ partition_args.emplace_back(argv[optind]);
+ }
+ }
+
+ // Make sure we are root.
+ if (::getuid() != 0) {
+ LOG(ERROR) << "Not running as root. Try \"adb root\" first.";
+ return EXIT_FAILURE;
+ }
+
+ // If somehow this executable is delivered on a "user" build, it can
+ // not function, so providing a clear message to the caller rather than
+ // letting if fall through and provide a lot of confusing failure messages.
+ if (!ALLOW_ADBD_DISABLE_VERITY || !android::base::GetBoolProperty("ro.debuggable", false)) {
+ LOG(ERROR) << "Device must be userdebug build";
+ return EXIT_FAILURE;
+ }
+
+ if (android::base::GetProperty("ro.boot.verifiedbootstate", "") != "orange") {
+ LOG(ERROR) << "Device must be bootloader unlocked";
+ return EXIT_FAILURE;
+ }
+
+ // Start a threadpool to service waitForService() callbacks as
+ // fs_mgr_overlayfs_* might call waitForService() to get the image service.
+ android::ProcessState::self()->startThreadPool();
+
+ if (!remount) {
+ auto ret = SetVerityState(enable_verity);
+
+ // Disable any overlayfs unconditionally if we want verity enabled.
+ // Enable overlayfs only if verity is successfully disabled or is already disabled.
+ if (enable_verity || ret.success) {
+ ret.want_reboot |= SetupOrTeardownOverlayfs(!enable_verity);
+ }
+
+ if (ret.want_reboot) {
+ if (auto_reboot) {
+ reboot(progname);
+ }
+ std::cout << "Reboot the device for new settings to take effect" << std::endl;
+ }
+ return ret.success ? EXIT_SUCCESS : EXIT_FAILURE;
}
// Make sure checkpointing is disabled if necessary.
- if (auto rv = VerifyCheckpointing(); rv != REMOUNT_SUCCESS) {
- return rv;
+ if (!VerifyCheckpointing()) {
+ return EXIT_FAILURE;
}
// Read the selected fstab.
Fstab fstab;
if (!ReadFstab(fstab_file, &fstab) || fstab.empty()) {
PLOG(ERROR) << "Failed to read fstab";
- return 1;
+ return EXIT_FAILURE;
}
RemountCheckResult check_result;
- int result = do_remount(fstab, partition_args, &check_result);
+ bool remount_success = do_remount(fstab, partition_args, &check_result);
if (check_result.disabled_verity && check_result.setup_overlayfs) {
LOG(INFO) << "Verity disabled; overlayfs enabled.";
@@ -549,27 +672,26 @@
} else if (check_result.setup_overlayfs) {
LOG(INFO) << "Overlayfs enabled.";
}
-
+ if (remount_success && check_result.remounted_anything) {
+ LOG(INFO) << "Remount succeeded";
+ } else if (!remount_success) {
+ LOG(ERROR) << "Remount failed";
+ }
if (check_result.reboot_later) {
if (auto_reboot) {
// If (1) remount requires a reboot to take effect, (2) system is currently
// running a DSU guest and (3) DSU is disabled, then enable DSU so that the
// next reboot would not take us back to the host system but stay within
// the guest system.
- if (auto rv = EnableDsuIfNeeded(); rv != REMOUNT_SUCCESS) {
+ if (!EnableDsuIfNeeded()) {
LOG(ERROR) << "Unable to automatically enable DSU";
- return rv;
+ return EXIT_FAILURE;
}
- reboot();
+ reboot("remount");
} else {
LOG(INFO) << "Now reboot your device for settings to take effect";
}
- return REMOUNT_SUCCESS;
+ return EXIT_SUCCESS;
}
- if (result == REMOUNT_SUCCESS) {
- printf("remount succeeded\n");
- } else {
- printf("remount failed\n");
- }
- return result;
+ return remount_success ? EXIT_SUCCESS : EXIT_FAILURE;
}
diff --git a/fs_mgr/libsnapshot/Android.bp b/fs_mgr/libsnapshot/Android.bp
index 8e4b556..2165961 100644
--- a/fs_mgr/libsnapshot/Android.bp
+++ b/fs_mgr/libsnapshot/Android.bp
@@ -261,6 +261,7 @@
},
auto_gen_config: true,
require_root: true,
+ compile_multilib: "first",
}
cc_test {
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/cow_writer.h b/fs_mgr/libsnapshot/include/libsnapshot/cow_writer.h
index b93fd32..a9682a1 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/cow_writer.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/cow_writer.h
@@ -16,6 +16,7 @@
#include <stdint.h>
+#include <cstdint>
#include <memory>
#include <optional>
#include <string>
@@ -150,6 +151,7 @@
bool SetFd(android::base::borrowed_fd fd);
bool Sync();
bool Truncate(off_t length);
+ bool EnsureSpaceAvailable(const uint64_t bytes_needed) const;
private:
android::base::unique_fd owned_fd_;
@@ -165,6 +167,7 @@
bool is_dev_null_ = false;
bool merge_in_progress_ = false;
bool is_block_device_ = false;
+ uint64_t cow_image_size_ = INT64_MAX;
};
} // namespace snapshot
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/cow_compress.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/cow_compress.cpp
index e58f45a..0eb231b 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/cow_compress.cpp
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/cow_compress.cpp
@@ -84,7 +84,13 @@
<< ", compression bound: " << bound << ", ret: " << compressed_size;
return {};
}
- buffer.resize(compressed_size);
+ // Don't run compression if the compressed output is larger
+ if (compressed_size >= length) {
+ buffer.resize(length);
+ memcpy(buffer.data(), data, length);
+ } else {
+ buffer.resize(compressed_size);
+ }
return buffer;
}
default:
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/cow_decompress.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/cow_decompress.cpp
index a4d2277..139a29f 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/cow_decompress.cpp
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/cow_decompress.cpp
@@ -273,6 +273,18 @@
<< actual_buffer_size << " bytes";
return false;
}
+ // If input size is same as output size, then input is uncompressed.
+ if (stream_->Size() == output_size) {
+ size_t bytes_read = 0;
+ stream_->Read(output_buffer, output_size, &bytes_read);
+ if (bytes_read != output_size) {
+ LOG(ERROR) << "Failed to read all input at once. Expected: " << output_size
+ << " actual: " << bytes_read;
+ return false;
+ }
+ sink_->ReturnData(output_buffer, output_size);
+ return true;
+ }
std::string input_buffer;
input_buffer.resize(stream_->Size());
size_t bytes_read = 0;
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/cow_writer.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/cow_writer.cpp
index 5f5d1fb..43c17a6 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/cow_writer.cpp
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/cow_writer.cpp
@@ -30,9 +30,29 @@
#include <lz4.h>
#include <zlib.h>
+#include <fcntl.h>
+#include <linux/fs.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+
namespace android {
namespace snapshot {
+namespace {
+std::string GetFdPath(int fd) {
+ const auto fd_path = "/proc/self/fd/" + std::to_string(fd);
+ std::string file_path(512, '\0');
+ const auto err = readlink(fd_path.c_str(), file_path.data(), file_path.size());
+ if (err <= 0) {
+ PLOG(ERROR) << "Failed to determine path for fd " << fd;
+ file_path.clear();
+ } else {
+ file_path.resize(err);
+ }
+ return file_path;
+}
+} // namespace
+
static_assert(sizeof(off_t) == sizeof(uint64_t));
using android::base::borrowed_fd;
@@ -163,12 +183,25 @@
} else {
fd_ = fd;
- struct stat stat;
+ struct stat stat {};
if (fstat(fd.get(), &stat) < 0) {
PLOG(ERROR) << "fstat failed";
return false;
}
+ const auto file_path = GetFdPath(fd.get());
is_block_device_ = S_ISBLK(stat.st_mode);
+ if (is_block_device_) {
+ uint64_t size_in_bytes = 0;
+ if (ioctl(fd.get(), BLKGETSIZE64, &size_in_bytes)) {
+ PLOG(ERROR) << "Failed to get total size for: " << fd.get();
+ return false;
+ }
+ cow_image_size_ = size_in_bytes;
+ LOG(INFO) << "COW image " << file_path << " has size " << size_in_bytes;
+ } else {
+ LOG(INFO) << "COW image " << file_path
+ << " is not a block device, assuming unlimited space.";
+ }
}
return true;
}
@@ -343,7 +376,8 @@
op.data_length = static_cast<uint16_t>(data.size());
if (!WriteOperation(op, data.data(), data.size())) {
- PLOG(ERROR) << "AddRawBlocks: write failed";
+ PLOG(ERROR) << "AddRawBlocks: write failed, bytes requested: " << size
+ << ", bytes written: " << i * header_.block_size;
return false;
}
} else {
@@ -512,12 +546,26 @@
return true;
}
-bool CowWriter::WriteOperation(const CowOperation& op, const void* data, size_t size) {
- if (lseek(fd_.get(), next_op_pos_, SEEK_SET) < 0) {
- PLOG(ERROR) << "lseek failed for writing operation.";
+bool CowWriter::EnsureSpaceAvailable(const uint64_t bytes_needed) const {
+ if (bytes_needed > cow_image_size_) {
+ LOG(ERROR) << "No space left on COW device. Required: " << bytes_needed
+ << ", available: " << cow_image_size_;
+ errno = ENOSPC;
return false;
}
- if (!android::base::WriteFully(fd_, reinterpret_cast<const uint8_t*>(&op), sizeof(op))) {
+ return true;
+}
+
+bool CowWriter::WriteOperation(const CowOperation& op, const void* data, size_t size) {
+ if (!EnsureSpaceAvailable(next_op_pos_ + sizeof(op))) {
+ return false;
+ }
+ if (!EnsureSpaceAvailable(next_data_pos_ + size)) {
+ return false;
+ }
+
+ if (!android::base::WriteFullyAtOffset(fd_, reinterpret_cast<const uint8_t*>(&op), sizeof(op),
+ next_op_pos_)) {
return false;
}
if (data != nullptr && size > 0) {
@@ -542,13 +590,8 @@
next_op_pos_ += sizeof(CowOperation) + GetNextOpOffset(op, header_.cluster_ops);
}
-bool CowWriter::WriteRawData(const void* data, size_t size) {
- if (lseek(fd_.get(), next_data_pos_, SEEK_SET) < 0) {
- PLOG(ERROR) << "lseek failed for writing data.";
- return false;
- }
-
- if (!android::base::WriteFully(fd_, data, size)) {
+bool CowWriter::WriteRawData(const void* data, const size_t size) {
+ if (!android::base::WriteFullyAtOffset(fd_, data, size, next_data_pos_)) {
return false;
}
return true;
diff --git a/fs_mgr/libsnapshot/snapshot_writer.cpp b/fs_mgr/libsnapshot/snapshot_writer.cpp
index 6aad3d1..82a7fd7 100644
--- a/fs_mgr/libsnapshot/snapshot_writer.cpp
+++ b/fs_mgr/libsnapshot/snapshot_writer.cpp
@@ -93,6 +93,9 @@
std::unique_ptr<FileDescriptor> CompressedSnapshotWriter::OpenReader() {
auto cow = OpenCowReader();
+ if (cow == nullptr) {
+ return nullptr;
+ }
auto reader = std::make_unique<CompressedSnapshotReader>();
if (!reader->SetCow(std::move(cow))) {
diff --git a/fs_mgr/libsnapshot/utility.cpp b/fs_mgr/libsnapshot/utility.cpp
index cadd24d..a98bf0e 100644
--- a/fs_mgr/libsnapshot/utility.cpp
+++ b/fs_mgr/libsnapshot/utility.cpp
@@ -17,6 +17,7 @@
#include <errno.h>
#include <time.h>
+#include <filesystem>
#include <iomanip>
#include <sstream>
@@ -152,6 +153,24 @@
}
}
+bool FsyncDirectory(const char* dirname) {
+ android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(dirname, O_RDONLY | O_CLOEXEC)));
+ if (fd == -1) {
+ PLOG(ERROR) << "Failed to open " << dirname;
+ return false;
+ }
+ if (fsync(fd) == -1) {
+ if (errno == EROFS || errno == EINVAL) {
+ PLOG(WARNING) << "Skip fsync " << dirname
+ << " on a file system does not support synchronization";
+ } else {
+ PLOG(ERROR) << "Failed to fsync " << dirname;
+ return false;
+ }
+ }
+ return true;
+}
+
bool WriteStringToFileAtomic(const std::string& content, const std::string& path) {
const std::string tmp_path = path + ".tmp";
{
@@ -175,11 +194,11 @@
PLOG(ERROR) << "rename failed from " << tmp_path << " to " << path;
return false;
}
- return true;
+ return FsyncDirectory(std::filesystem::path(path).parent_path().c_str());
}
std::ostream& operator<<(std::ostream& os, const Now&) {
- struct tm now;
+ struct tm now {};
time_t t = time(nullptr);
localtime_r(&t, &now);
return os << std::put_time(&now, "%Y%m%d-%H%M%S");
diff --git a/fs_mgr/libsnapshot/utility.h b/fs_mgr/libsnapshot/utility.h
index eff6f10..8c4c7c6 100644
--- a/fs_mgr/libsnapshot/utility.h
+++ b/fs_mgr/libsnapshot/utility.h
@@ -117,6 +117,7 @@
// Note that rename() is an atomic operation. This function may not work properly if there
// is an open fd to |path|, because that fd has an old view of the file.
bool WriteStringToFileAtomic(const std::string& content, const std::string& path);
+bool FsyncDirectory(const char* dirname);
// Writes current time to a given stream.
struct Now {};
diff --git a/fs_mgr/set-verity-state.cpp b/fs_mgr/set-verity-state.cpp
deleted file mode 100644
index 84ee01f..0000000
--- a/fs_mgr/set-verity-state.cpp
+++ /dev/null
@@ -1,258 +0,0 @@
-/*
- * Copyright (C) 2019 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 <getopt.h>
-#include <stdio.h>
-
-#include <android-base/file.h>
-#include <android-base/logging.h>
-#include <android-base/properties.h>
-#include <binder/ProcessState.h>
-#include <cutils/android_reboot.h>
-#include <fs_mgr_overlayfs.h>
-#include <libavb_user/libavb_user.h>
-
-#include "fs_mgr_priv_overlayfs.h"
-
-using namespace std::string_literals;
-
-namespace {
-
-void print_usage() {
- printf("Usage:\n"
- "\tdisable-verity\n"
- "\tenable-verity\n"
- "\tset-verity-state [0|1]\n"
- "Options:\n"
- "\t-h --help\tthis help\n"
- "\t-R --reboot\tautomatic reboot if needed for new settings to take effect\n"
- "\t-v --verbose\tbe noisy\n");
-}
-
-#ifdef ALLOW_DISABLE_VERITY
-const bool kAllowDisableVerity = true;
-#else
-const bool kAllowDisableVerity = false;
-#endif
-
-static bool SetupOrTeardownOverlayfs(bool enable) {
- bool want_reboot = false;
- if (enable) {
- if (!fs_mgr_overlayfs_setup(nullptr, &want_reboot)) {
- LOG(ERROR) << "Overlayfs setup failed.";
- return want_reboot;
- }
- if (want_reboot) {
- printf("enabling overlayfs\n");
- }
- } else {
- auto rv = fs_mgr_overlayfs_teardown(nullptr, &want_reboot);
- if (rv == OverlayfsTeardownResult::Error) {
- LOG(ERROR) << "Overlayfs teardown failed.";
- return want_reboot;
- }
- if (rv == OverlayfsTeardownResult::Busy) {
- LOG(ERROR) << "Overlayfs is still active until reboot.";
- return true;
- }
- if (want_reboot) {
- printf("disabling overlayfs\n");
- }
- }
- return want_reboot;
-}
-
-/* Helper function to get A/B suffix, if any. If the device isn't
- * using A/B the empty string is returned. Otherwise either "_a",
- * "_b", ... is returned.
- */
-std::string get_ab_suffix() {
- return android::base::GetProperty("ro.boot.slot_suffix", "");
-}
-
-bool is_avb_device_locked() {
- return android::base::GetProperty("ro.boot.vbmeta.device_state", "") == "locked";
-}
-
-bool is_debuggable() {
- return android::base::GetBoolProperty("ro.debuggable", false);
-}
-
-bool is_using_avb() {
- // Figure out if we're using VB1.0 or VB2.0 (aka AVB) - by
- // contract, androidboot.vbmeta.digest is set by the bootloader
- // when using AVB).
- return !android::base::GetProperty("ro.boot.vbmeta.digest", "").empty();
-}
-
-[[noreturn]] void reboot(const std::string& name) {
- LOG(INFO) << "Rebooting device for new settings to take effect";
- ::sync();
- android::base::SetProperty(ANDROID_RB_PROPERTY, "reboot," + name);
- ::sleep(60);
- LOG(ERROR) << "Failed to reboot";
- ::exit(1);
-}
-
-struct SetVerityStateResult {
- bool success = false;
- bool want_reboot = false;
-};
-
-/* Use AVB to turn verity on/off */
-SetVerityStateResult SetVerityState(bool enable_verity) {
- std::string ab_suffix = get_ab_suffix();
- bool verity_enabled = false;
-
- if (is_avb_device_locked()) {
- LOG(ERROR) << "Device must be bootloader unlocked to change verity state";
- return {};
- }
-
- std::unique_ptr<AvbOps, decltype(&avb_ops_user_free)> ops(avb_ops_user_new(),
- &avb_ops_user_free);
- if (!ops) {
- LOG(ERROR) << "Error getting AVB ops";
- return {};
- }
-
- if (!avb_user_verity_get(ops.get(), ab_suffix.c_str(), &verity_enabled)) {
- LOG(ERROR) << "Error getting verity state";
- return {};
- }
-
- if ((verity_enabled && enable_verity) || (!verity_enabled && !enable_verity)) {
- LOG(INFO) << "Verity is already " << (verity_enabled ? "enabled" : "disabled");
- return {.success = true, .want_reboot = false};
- }
-
- if (!avb_user_verity_set(ops.get(), ab_suffix.c_str(), enable_verity)) {
- LOG(ERROR) << "Error setting verity state";
- return {};
- }
-
- LOG(INFO) << "Successfully " << (enable_verity ? "enabled" : "disabled") << " verity";
- return {.success = true, .want_reboot = true};
-}
-
-class MyLogger {
- public:
- explicit MyLogger(bool verbose) : verbose_(verbose) {}
-
- void operator()(android::base::LogId id, android::base::LogSeverity severity, const char* tag,
- const char* file, unsigned int line, const char* message) {
- // Hide log starting with '[fs_mgr]' unless it's an error.
- if (verbose_ || severity >= android::base::ERROR || message[0] != '[') {
- fprintf(stderr, "%s\n", message);
- }
- logd_(id, severity, tag, file, line, message);
- }
-
- private:
- android::base::LogdLogger logd_;
- bool verbose_;
-};
-
-} // namespace
-
-int main(int argc, char* argv[]) {
- bool auto_reboot = false;
- bool verbose = false;
-
- struct option longopts[] = {
- {"help", no_argument, nullptr, 'h'},
- {"reboot", no_argument, nullptr, 'R'},
- {"verbose", no_argument, nullptr, 'v'},
- {0, 0, nullptr, 0},
- };
- for (int opt; (opt = ::getopt_long(argc, argv, "hRv", longopts, nullptr)) != -1;) {
- switch (opt) {
- case 'h':
- print_usage();
- return 0;
- case 'R':
- auto_reboot = true;
- break;
- case 'v':
- verbose = true;
- break;
- default:
- print_usage();
- return 1;
- }
- }
-
- android::base::InitLogging(argv, MyLogger(verbose));
-
- bool enable_verity = false;
- const std::string progname = getprogname();
- if (progname == "enable-verity") {
- enable_verity = true;
- } else if (progname == "disable-verity") {
- enable_verity = false;
- } else if (optind < argc && (argv[optind] == "1"s || argv[optind] == "0"s)) {
- // progname "set-verity-state"
- enable_verity = (argv[optind] == "1"s);
- } else {
- print_usage();
- return 1;
- }
-
- if (!kAllowDisableVerity || !is_debuggable()) {
- errno = EPERM;
- PLOG(ERROR) << "Cannot disable/enable verity on user build";
- return 1;
- }
-
- if (getuid() != 0) {
- errno = EACCES;
- PLOG(ERROR) << "Must be running as root (adb root)";
- return 1;
- }
-
- if (!is_using_avb()) {
- LOG(ERROR) << "Expected AVB device, VB1.0 is no longer supported";
- return 1;
- }
-
- int exit_code = 0;
- bool want_reboot = false;
-
- auto ret = SetVerityState(enable_verity);
- if (ret.success) {
- want_reboot |= ret.want_reboot;
- } else {
- exit_code = 1;
- }
-
- // Disable any overlayfs unconditionally if we want verity enabled.
- // Enable overlayfs only if verity is successfully disabled or is already disabled.
- if (enable_verity || ret.success) {
- // Start a threadpool to service waitForService() callbacks as
- // fs_mgr_overlayfs_* might call waitForService() to get the image service.
- android::ProcessState::self()->startThreadPool();
- want_reboot |= SetupOrTeardownOverlayfs(!enable_verity);
- }
-
- if (want_reboot) {
- if (auto_reboot) {
- reboot(progname);
- }
- printf("Reboot the device for new settings to take effect\n");
- }
-
- return exit_code;
-}
diff --git a/fs_mgr/tests/adb-remount-test.sh b/fs_mgr/tests/adb-remount-test.sh
index 68f8152..c87e564 100755
--- a/fs_mgr/tests/adb-remount-test.sh
+++ b/fs_mgr/tests/adb-remount-test.sh
@@ -1422,9 +1422,12 @@
LOG RUN "flash vendor, and confirm vendor override disappears"
is_bootloader_fastboot=true
-# cuttlefish?
-[[ "$(get_property ro.product.vendor.device)" == vsoc_* ]] &&
- is_bootloader_fastboot=false
+# virtual device?
+case "$(get_property ro.product.vendor.device)" in
+ vsoc_* | emulator_* | emulator64_*)
+ is_bootloader_fastboot=false
+ ;;
+esac
is_userspace_fastboot=false
if ! ${is_bootloader_fastboot}; then
diff --git a/init/init.cpp b/init/init.cpp
index 540e2ca..4262191 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -739,33 +739,13 @@
HandlePowerctlMessage("shutdown,container");
}
-static constexpr std::chrono::milliseconds kDiagnosticTimeout = 10s;
-
-static void HandleSignalFd(bool one_off) {
+static void HandleSignalFd() {
signalfd_siginfo siginfo;
- auto started = std::chrono::steady_clock::now();
- do {
- ssize_t bytes_read = TEMP_FAILURE_RETRY(read(signal_fd, &siginfo, sizeof(siginfo)));
- if (bytes_read < 0 && errno == EAGAIN) {
- if (one_off) {
- return;
- }
- auto now = std::chrono::steady_clock::now();
- std::chrono::duration<double> waited = now - started;
- if (waited >= kDiagnosticTimeout) {
- LOG(ERROR) << "epoll() woke us up, but we waited with no SIGCHLD!";
- started = now;
- }
-
- std::this_thread::sleep_for(100ms);
- continue;
- }
- if (bytes_read != sizeof(siginfo)) {
- PLOG(ERROR) << "Failed to read siginfo from signal_fd";
- return;
- }
- break;
- } while (!one_off);
+ ssize_t bytes_read = TEMP_FAILURE_RETRY(read(signal_fd, &siginfo, sizeof(siginfo)));
+ if (bytes_read != sizeof(siginfo)) {
+ PLOG(ERROR) << "Failed to read siginfo from signal_fd";
+ return;
+ }
switch (siginfo.ssi_signo) {
case SIGCHLD:
@@ -820,14 +800,13 @@
LOG(FATAL) << "Failed to register a fork handler: " << strerror(result);
}
- signal_fd = signalfd(-1, &mask, SFD_CLOEXEC | SFD_NONBLOCK);
+ signal_fd = signalfd(-1, &mask, SFD_CLOEXEC);
if (signal_fd == -1) {
PLOG(FATAL) << "failed to create signalfd";
}
constexpr int flags = EPOLLIN | EPOLLPRI;
- auto handler = std::bind(HandleSignalFd, false);
- if (auto result = epoll->RegisterHandler(signal_fd, handler, flags); !result.ok()) {
+ if (auto result = epoll->RegisterHandler(signal_fd, HandleSignalFd, flags); !result.ok()) {
LOG(FATAL) << result.error();
}
}
@@ -956,32 +935,6 @@
return {};
}
-static void DumpPidFds(const std::string& prefix, pid_t pid) {
- std::error_code ec;
- std::string proc_dir = "/proc/" + std::to_string(pid) + "/fd";
- for (const auto& entry : std::filesystem::directory_iterator(proc_dir)) {
- std::string target;
- if (android::base::Readlink(entry.path(), &target)) {
- LOG(ERROR) << prefix << target;
- } else {
- LOG(ERROR) << prefix << entry.path();
- }
- }
-}
-
-static void DumpFile(const std::string& prefix, const std::string& file) {
- std::ifstream fp(file);
- if (!fp) {
- LOG(ERROR) << "Could not open " << file;
- return;
- }
-
- std::string line;
- while (std::getline(fp, line)) {
- LOG(ERROR) << prefix << line;
- }
-}
-
int SecondStageMain(int argc, char** argv) {
if (REBOOT_BOOTLOADER_ON_PANIC) {
InstallRebootSignalHandlers();
@@ -1155,7 +1108,7 @@
setpriority(PRIO_PROCESS, 0, 0);
while (true) {
// By default, sleep until something happens.
- std::chrono::milliseconds epoll_timeout{kDiagnosticTimeout};
+ std::optional<std::chrono::milliseconds> epoll_timeout;
auto shutdown_command = shutdown_state.CheckShutdown();
if (shutdown_command) {
@@ -1187,25 +1140,6 @@
auto epoll_result = epoll.Wait(epoll_timeout);
if (!epoll_result.ok()) {
LOG(ERROR) << epoll_result.error();
- } else if (*epoll_result <= 0 && Service::is_exec_service_running()) {
- static bool dumped_diagnostics = false;
- std::chrono::duration<double> waited =
- std::chrono::steady_clock::now() - Service::exec_service_started();
- if (waited >= kDiagnosticTimeout) {
- LOG(ERROR) << "Exec service is hung? Waited " << waited.count()
- << " without SIGCHLD";
- if (!dumped_diagnostics) {
- DumpPidFds("exec service opened: ", Service::exec_service_pid());
-
- std::string status_file =
- "/proc/" + std::to_string(Service::exec_service_pid()) + "/status";
- DumpFile("exec service: ", status_file);
- dumped_diagnostics = true;
-
- LOG(INFO) << "Attempting to handle any stuck SIGCHLDs...";
- HandleSignalFd(true);
- }
- }
}
if (!IsShuttingDown()) {
HandleControlMessages();
diff --git a/init/init_test.cpp b/init/init_test.cpp
index 5c1e9ef..aea1cb3 100644
--- a/init/init_test.cpp
+++ b/init/init_test.cpp
@@ -193,6 +193,35 @@
EXPECT_TRUE(service->is_override());
}
+TEST(init, StartConsole) {
+ if (access("/dev/console", F_OK) < 0) {
+ GTEST_SKIP() << "/dev/console not found";
+ }
+ std::string init_script = R"init(
+service console /system/bin/sh
+ class core
+ console console
+ disabled
+ user root
+ group root shell log readproc
+ seclabel u:r:shell:s0
+ setenv HOSTNAME console
+)init";
+
+ ActionManager action_manager;
+ ServiceList service_list;
+ TestInitText(init_script, BuiltinFunctionMap(), {}, &action_manager, &service_list);
+ ASSERT_EQ(std::distance(service_list.begin(), service_list.end()), 1);
+
+ auto service = service_list.begin()->get();
+ ASSERT_NE(service, nullptr);
+ ASSERT_RESULT_OK(service->Start());
+ const pid_t pid = service->pid();
+ ASSERT_GT(pid, 0);
+ EXPECT_NE(getsid(pid), 0);
+ service->Stop();
+}
+
static std::string GetSecurityContext() {
char* ctx;
if (getcon(&ctx) == -1) {
diff --git a/init/reboot.cpp b/init/reboot.cpp
index 4c27a56..1f4186d 100644
--- a/init/reboot.cpp
+++ b/init/reboot.cpp
@@ -567,6 +567,11 @@
}
static Result<void> UnmountAllApexes() {
+ // don't need to unmount because apexd doesn't use /data in Microdroid
+ if (IsMicrodroid()) {
+ return {};
+ }
+
const char* args[] = {"/system/bin/apexd", "--unmount-all"};
int status;
if (logwrap_fork_execvp(arraysize(args), args, &status, false, LOG_KLOG, true, nullptr) != 0) {
diff --git a/init/service.cpp b/init/service.cpp
index 331cd88..8db2b05 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -16,6 +16,7 @@
#include "service.h"
+#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <linux/securebits.h>
@@ -135,8 +136,6 @@
unsigned long Service::next_start_order_ = 1;
bool Service::is_exec_service_running_ = false;
-pid_t Service::exec_service_pid_ = -1;
-std::chrono::time_point<std::chrono::steady_clock> Service::exec_service_started_;
Service::Service(const std::string& name, Subcontext* subcontext_for_restart_commands,
const std::string& filename, const std::vector<std::string>& args)
@@ -226,7 +225,7 @@
}
}
-void Service::SetProcessAttributesAndCaps() {
+void Service::SetProcessAttributesAndCaps(InterprocessFifo setsid_finished) {
// Keep capabilites on uid change.
if (capabilities_ && proc_attr_.uid) {
// If Android is running in a container, some securebits might already
@@ -241,7 +240,7 @@
}
}
- if (auto result = SetProcessAttributes(proc_attr_); !result.ok()) {
+ if (auto result = SetProcessAttributes(proc_attr_, std::move(setsid_finished)); !result.ok()) {
LOG(FATAL) << "cannot set attribute for " << name_ << ": " << result.error();
}
@@ -432,8 +431,6 @@
flags_ |= SVC_EXEC;
is_exec_service_running_ = true;
- exec_service_pid_ = pid_;
- exec_service_started_ = std::chrono::steady_clock::now();
LOG(INFO) << "SVC_EXEC service '" << name_ << "' pid " << pid_ << " (uid " << proc_attr_.uid
<< " gid " << proc_attr_.gid << "+" << proc_attr_.supp_gids.size() << " context "
@@ -507,7 +504,7 @@
// Enters namespaces, sets environment variables, writes PID files and runs the service executable.
void Service::RunService(const std::vector<Descriptor>& descriptors,
- InterprocessFifo cgroups_activated) {
+ InterprocessFifo cgroups_activated, InterprocessFifo setsid_finished) {
if (auto result = EnterNamespaces(namespaces_, name_, mount_namespace_); !result.ok()) {
LOG(FATAL) << "Service '" << name_ << "' failed to set up namespaces: " << result.error();
}
@@ -534,7 +531,7 @@
LOG(ERROR) << name_ << ": failed to read from notification channel: " << byte.error();
}
cgroups_activated.Close();
- if (!*byte) {
+ if (*byte != kCgroupsActivated) {
LOG(FATAL) << "Service '" << name_ << "' failed to start due to a fatal error";
_exit(EXIT_FAILURE);
}
@@ -555,7 +552,7 @@
// As requested, set our gid, supplemental gids, uid, context, and
// priority. Aborts on failure.
- SetProcessAttributesAndCaps();
+ SetProcessAttributesAndCaps(std::move(setsid_finished));
if (!ExpandArgsAndExecv(args_, sigstop_)) {
PLOG(ERROR) << "cannot execv('" << args_[0]
@@ -598,11 +595,14 @@
return {};
}
- InterprocessFifo cgroups_activated;
-
- if (Result<void> result = cgroups_activated.Initialize(); !result.ok()) {
- return result;
- }
+ // cgroups_activated is used for communication from the parent to the child
+ // while setsid_finished is used for communication from the child process to
+ // the parent process. These two communication channels are separate because
+ // combining these into a single communication channel would introduce a
+ // race between the Write() calls by the parent and by the child.
+ InterprocessFifo cgroups_activated, setsid_finished;
+ OR_RETURN(cgroups_activated.Initialize());
+ OR_RETURN(setsid_finished.Initialize());
if (Result<void> result = CheckConsole(); !result.ok()) {
return result;
@@ -661,10 +661,12 @@
if (pid == 0) {
umask(077);
cgroups_activated.CloseWriteFd();
- RunService(descriptors, std::move(cgroups_activated));
+ setsid_finished.CloseReadFd();
+ RunService(descriptors, std::move(cgroups_activated), std::move(setsid_finished));
_exit(127);
} else {
cgroups_activated.CloseReadFd();
+ setsid_finished.CloseWriteFd();
}
if (pid < 0) {
@@ -693,7 +695,7 @@
limit_percent_ != -1 || !limit_property_.empty();
errno = -createProcessGroup(proc_attr_.uid, pid_, use_memcg);
if (errno != 0) {
- Result<void> result = cgroups_activated.Write(0);
+ Result<void> result = cgroups_activated.Write(kActivatingCgroupsFailed);
if (!result.ok()) {
return Error() << "Sending notification failed: " << result.error();
}
@@ -717,10 +719,39 @@
LmkdRegister(name_, proc_attr_.uid, pid_, oom_score_adjust_);
}
- if (Result<void> result = cgroups_activated.Write(1); !result.ok()) {
+ if (Result<void> result = cgroups_activated.Write(kCgroupsActivated); !result.ok()) {
return Error() << "Sending cgroups activated notification failed: " << result.error();
}
+ cgroups_activated.Close();
+
+ // Call setpgid() from the parent process to make sure that this call has
+ // finished before the parent process calls kill(-pgid, ...).
+ if (!RequiresConsole(proc_attr_)) {
+ if (setpgid(pid, pid) < 0) {
+ switch (errno) {
+ case EACCES: // Child has already performed setpgid() followed by execve().
+ case ESRCH: // Child process no longer exists.
+ break;
+ default:
+ PLOG(ERROR) << "setpgid() from parent failed";
+ }
+ }
+ } else {
+ // The Read() call below will return an error if the child is killed.
+ if (Result<uint8_t> result = setsid_finished.Read();
+ !result.ok() || *result != kSetSidFinished) {
+ if (!result.ok()) {
+ return Error() << "Waiting for setsid() failed: " << result.error();
+ } else {
+ return Error() << "Waiting for setsid() failed: " << static_cast<uint32_t>(*result)
+ << " <> " << static_cast<uint32_t>(kSetSidFinished);
+ }
+ }
+ }
+
+ setsid_finished.Close();
+
NotifyStateChange("running");
reboot_on_failure.Disable();
return {};
diff --git a/init/service.h b/init/service.h
index b2c9909..6fb2804 100644
--- a/init/service.h
+++ b/init/service.h
@@ -104,10 +104,6 @@
size_t CheckAllCommands() const { return onrestart_.CheckAllCommands(); }
static bool is_exec_service_running() { return is_exec_service_running_; }
- static pid_t exec_service_pid() { return exec_service_pid_; }
- static std::chrono::time_point<std::chrono::steady_clock> exec_service_started() {
- return exec_service_started_;
- }
const std::string& name() const { return name_; }
const std::set<std::string>& classnames() const { return classnames_; }
@@ -143,7 +139,7 @@
flags_ &= ~SVC_ONESHOT;
}
}
- Subcontext* subcontext() const { return subcontext_; }
+ const Subcontext* subcontext() const { return subcontext_; }
const std::string& filename() const { return filename_; }
void set_filename(const std::string& name) { filename_ = name; }
@@ -151,18 +147,17 @@
void NotifyStateChange(const std::string& new_state) const;
void StopOrReset(int how);
void KillProcessGroup(int signal, bool report_oneshot = false);
- void SetProcessAttributesAndCaps();
+ void SetProcessAttributesAndCaps(InterprocessFifo setsid_finished);
void ResetFlagsForStart();
Result<void> CheckConsole();
void ConfigureMemcg();
- void RunService(const std::vector<Descriptor>& descriptors, InterprocessFifo cgroups_activated);
+ void RunService(const std::vector<Descriptor>& descriptors, InterprocessFifo cgroups_activated,
+ InterprocessFifo setsid_finished);
void SetMountNamespace();
static unsigned long next_start_order_;
static bool is_exec_service_running_;
- static std::chrono::time_point<std::chrono::steady_clock> exec_service_started_;
- static pid_t exec_service_pid_;
- std::string name_;
+ const std::string name_;
std::set<std::string> classnames_;
unsigned flags_;
@@ -186,7 +181,7 @@
// Environment variables that only get applied to the next run.
std::vector<std::pair<std::string, std::string>> once_environment_vars_;
- Subcontext* subcontext_;
+ const Subcontext* const subcontext_;
Action onrestart_; // Commands to execute on restart.
std::vector<std::string> writepid_files_;
@@ -220,7 +215,7 @@
bool updatable_ = false;
- std::vector<std::string> args_;
+ const std::vector<std::string> args_;
std::vector<std::function<void(const siginfo_t& siginfo)>> reap_callbacks_;
diff --git a/init/service_utils.cpp b/init/service_utils.cpp
index a14969e..15bf963 100644
--- a/init/service_utils.cpp
+++ b/init/service_utils.cpp
@@ -232,7 +232,7 @@
return {};
}
-Result<void> SetProcessAttributes(const ProcessAttributes& attr) {
+Result<void> SetProcessAttributes(const ProcessAttributes& attr, InterprocessFifo setsid_finished) {
if (attr.ioprio_class != IoSchedClass_NONE) {
if (android_set_ioprio(getpid(), attr.ioprio_class, attr.ioprio_pri)) {
PLOG(ERROR) << "failed to set pid " << getpid() << " ioprio=" << attr.ioprio_class
@@ -240,11 +240,17 @@
}
}
- if (!attr.console.empty()) {
+ if (RequiresConsole(attr)) {
setsid();
+ setsid_finished.Write(kSetSidFinished);
+ setsid_finished.Close();
OpenConsole(attr.console);
} else {
- if (setpgid(0, getpid()) == -1) {
+ // Without PID namespaces, this call duplicates the setpgid() call from
+ // the parent process. With PID namespaces, this setpgid() call sets the
+ // process group ID for a child of the init process in the PID
+ // namespace.
+ if (setpgid(0, 0) == -1) {
return ErrnoError() << "setpgid failed";
}
SetupStdio(attr.stdio_to_kmsg);
diff --git a/init/service_utils.h b/init/service_utils.h
index 65a2012..d4143aa 100644
--- a/init/service_utils.h
+++ b/init/service_utils.h
@@ -26,12 +26,20 @@
#include <android-base/unique_fd.h>
#include <cutils/iosched_policy.h>
+#include "interprocess_fifo.h"
#include "mount_namespace.h"
#include "result.h"
namespace android {
namespace init {
+// Constants used by Service::Start() for communication between parent and child.
+enum ServiceCode : uint8_t {
+ kActivatingCgroupsFailed,
+ kCgroupsActivated,
+ kSetSidFinished,
+};
+
class Descriptor {
public:
Descriptor(const std::string& name, android::base::unique_fd fd)
@@ -89,7 +97,12 @@
int priority;
bool stdio_to_kmsg;
};
-Result<void> SetProcessAttributes(const ProcessAttributes& attr);
+
+inline bool RequiresConsole(const ProcessAttributes& attr) {
+ return !attr.console.empty();
+}
+
+Result<void> SetProcessAttributes(const ProcessAttributes& attr, InterprocessFifo setsid_finished);
Result<void> WritePidToFiles(std::vector<std::string>* files);
diff --git a/libsparse/append2simg.cpp b/libsparse/append2simg.cpp
index 99f4339..d3a43a8 100644
--- a/libsparse/append2simg.cpp
+++ b/libsparse/append2simg.cpp
@@ -64,60 +64,60 @@
input_path = argv[2];
} else {
usage();
- exit(-1);
+ exit(EXIT_FAILURE);
}
ret = asprintf(&tmp_path, "%s.append2simg", output_path);
if (ret < 0) {
fprintf(stderr, "Couldn't allocate filename\n");
- exit(-1);
+ exit(EXIT_FAILURE);
}
output = open(output_path, O_RDWR | O_BINARY);
if (output < 0) {
fprintf(stderr, "Couldn't open output file (%s)\n", strerror(errno));
- exit(-1);
+ exit(EXIT_FAILURE);
}
sparse_output = sparse_file_import_auto(output, false, true);
if (!sparse_output) {
fprintf(stderr, "Couldn't import output file\n");
- exit(-1);
+ exit(EXIT_FAILURE);
}
input = open(input_path, O_RDONLY | O_BINARY);
if (input < 0) {
fprintf(stderr, "Couldn't open input file (%s)\n", strerror(errno));
- exit(-1);
+ exit(EXIT_FAILURE);
}
input_len = lseek64(input, 0, SEEK_END);
if (input_len < 0) {
fprintf(stderr, "Couldn't get input file length (%s)\n", strerror(errno));
- exit(-1);
+ exit(EXIT_FAILURE);
} else if (input_len % sparse_output->block_size) {
fprintf(stderr, "Input file is not a multiple of the output file's block size");
- exit(-1);
+ exit(EXIT_FAILURE);
}
lseek64(input, 0, SEEK_SET);
output_block = sparse_output->len / sparse_output->block_size;
if (sparse_file_add_fd(sparse_output, input, 0, input_len, output_block) < 0) {
fprintf(stderr, "Couldn't add input file\n");
- exit(-1);
+ exit(EXIT_FAILURE);
}
sparse_output->len += input_len;
tmp_fd = open(tmp_path, O_WRONLY | O_CREAT | O_BINARY, 0664);
if (tmp_fd < 0) {
fprintf(stderr, "Couldn't open temporary file (%s)\n", strerror(errno));
- exit(-1);
+ exit(EXIT_FAILURE);
}
lseek64(output, 0, SEEK_SET);
if (sparse_file_write(sparse_output, tmp_fd, false, true, false) < 0) {
fprintf(stderr, "Failed to write sparse file\n");
- exit(-1);
+ exit(EXIT_FAILURE);
}
sparse_file_destroy(sparse_output);
@@ -128,10 +128,10 @@
ret = rename(tmp_path, output_path);
if (ret < 0) {
fprintf(stderr, "Failed to rename temporary file (%s)\n", strerror(errno));
- exit(-1);
+ exit(EXIT_FAILURE);
}
free(tmp_path);
- exit(0);
+ exit(EXIT_SUCCESS);
}
diff --git a/libsparse/img2simg.cpp b/libsparse/img2simg.cpp
index 51580f7..c390506 100644
--- a/libsparse/img2simg.cpp
+++ b/libsparse/img2simg.cpp
@@ -61,14 +61,14 @@
break;
default:
usage();
- exit(-1);
+ exit(EXIT_FAILURE);
}
}
extra = argc - optind;
if (extra < 2 || extra > 3) {
usage();
- exit(-1);
+ exit(EXIT_FAILURE);
}
if (extra == 3) {
@@ -77,7 +77,7 @@
if (block_size < 1024 || block_size % 4 != 0) {
usage();
- exit(-1);
+ exit(EXIT_FAILURE);
}
arg_in = argv[optind];
@@ -87,7 +87,7 @@
in = open(arg_in, O_RDONLY | O_BINARY);
if (in < 0) {
fprintf(stderr, "Cannot open input file %s\n", arg_in);
- exit(-1);
+ exit(EXIT_FAILURE);
}
}
@@ -98,7 +98,7 @@
out = open(arg_out, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0664);
if (out < 0) {
fprintf(stderr, "Cannot open output file %s\n", arg_out);
- exit(-1);
+ exit(EXIT_FAILURE);
}
}
@@ -108,24 +108,24 @@
s = sparse_file_new(block_size, len);
if (!s) {
fprintf(stderr, "Failed to create sparse file\n");
- exit(-1);
+ exit(EXIT_FAILURE);
}
sparse_file_verbose(s);
ret = sparse_file_read(s, in, mode, false);
if (ret) {
fprintf(stderr, "Failed to read file\n");
- exit(-1);
+ exit(EXIT_FAILURE);
}
ret = sparse_file_write(s, out, false, true, false);
if (ret) {
fprintf(stderr, "Failed to write sparse file\n");
- exit(-1);
+ exit(EXIT_FAILURE);
}
close(in);
close(out);
- exit(0);
+ exit(EXIT_SUCCESS);
}
diff --git a/libsparse/simg2img.cpp b/libsparse/simg2img.cpp
index 8ba5f69..2301a83 100644
--- a/libsparse/simg2img.cpp
+++ b/libsparse/simg2img.cpp
@@ -41,13 +41,13 @@
if (argc < 3) {
usage();
- exit(-1);
+ exit(EXIT_FAILURE);
}
out = open(argv[argc - 1], O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0664);
if (out < 0) {
fprintf(stderr, "Cannot open output file %s\n", argv[argc - 1]);
- exit(-1);
+ exit(EXIT_FAILURE);
}
for (i = 1; i < argc - 1; i++) {
@@ -57,14 +57,14 @@
in = open(argv[i], O_RDONLY | O_BINARY);
if (in < 0) {
fprintf(stderr, "Cannot open input file %s\n", argv[i]);
- exit(-1);
+ exit(EXIT_FAILURE);
}
}
s = sparse_file_import(in, true, false);
if (!s) {
fprintf(stderr, "Failed to read sparse file\n");
- exit(-1);
+ exit(EXIT_FAILURE);
}
if (lseek(out, 0, SEEK_SET) == -1) {
@@ -74,7 +74,7 @@
if (sparse_file_write(s, out, false, false, false) < 0) {
fprintf(stderr, "Cannot write output file\n");
- exit(-1);
+ exit(EXIT_FAILURE);
}
sparse_file_destroy(s);
close(in);
@@ -82,5 +82,5 @@
close(out);
- exit(0);
+ exit(EXIT_SUCCESS);
}
diff --git a/libsparse/simg2simg.cpp b/libsparse/simg2simg.cpp
deleted file mode 100644
index a2c296e..0000000
--- a/libsparse/simg2simg.cpp
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (C) 2012 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.
- */
-
-#define _FILE_OFFSET_BITS 64
-#define _LARGEFILE64_SOURCE 1
-
-#include <fcntl.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <sparse/sparse.h>
-
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
-
-void usage() {
- fprintf(stderr, "Usage: simg2simg <sparse image file> <sparse_image_file> <max_size>\n");
-}
-
-int main(int argc, char* argv[]) {
- int in;
- int out;
- int i;
- int ret;
- struct sparse_file* s;
- int64_t max_size;
- struct sparse_file** out_s;
- int files;
- char filename[4096];
-
- if (argc != 4) {
- usage();
- exit(-1);
- }
-
- max_size = atoll(argv[3]);
-
- in = open(argv[1], O_RDONLY | O_BINARY);
- if (in < 0) {
- fprintf(stderr, "Cannot open input file %s\n", argv[1]);
- exit(-1);
- }
-
- s = sparse_file_import(in, true, false);
- if (!s) {
- fprintf(stderr, "Failed to import sparse file\n");
- exit(-1);
- }
-
- files = sparse_file_resparse(s, max_size, nullptr, 0);
- if (files < 0) {
- fprintf(stderr, "Failed to resparse\n");
- exit(-1);
- }
-
- out_s = calloc(sizeof(struct sparse_file*), files);
- if (!out_s) {
- fprintf(stderr, "Failed to allocate sparse file array\n");
- exit(-1);
- }
-
- files = sparse_file_resparse(s, max_size, out_s, files);
- if (files < 0) {
- fprintf(stderr, "Failed to resparse\n");
- exit(-1);
- }
-
- for (i = 0; i < files; i++) {
- ret = snprintf(filename, sizeof(filename), "%s.%d", argv[2], i);
- if (ret >= (int)sizeof(filename)) {
- fprintf(stderr, "Filename too long\n");
- exit(-1);
- }
-
- out = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0664);
- if (out < 0) {
- fprintf(stderr, "Cannot open output file %s\n", argv[2]);
- exit(-1);
- }
-
- ret = sparse_file_write(out_s[i], out, false, true, false);
- if (ret) {
- fprintf(stderr, "Failed to write sparse file\n");
- exit(-1);
- }
- close(out);
- }
-
- close(in);
-
- exit(0);
-}
diff --git a/libutils/include/utils/RefBase.h b/libutils/include/utils/RefBase.h
index f3acd6f..5e3fa7d 100644
--- a/libutils/include/utils/RefBase.h
+++ b/libutils/include/utils/RefBase.h
@@ -210,6 +210,7 @@
#include <atomic>
#include <functional>
+#include <memory>
#include <type_traits> // for common_type.
#include <stdint.h>
diff --git a/property_service/libpropertyinfoserializer/property_info_serializer_test.cpp b/property_service/libpropertyinfoserializer/property_info_serializer_test.cpp
index 77cbdd4..a484441 100644
--- a/property_service/libpropertyinfoserializer/property_info_serializer_test.cpp
+++ b/property_service/libpropertyinfoserializer/property_info_serializer_test.cpp
@@ -399,7 +399,6 @@
{"dalvik.vm.lockprof.threshold", "u:object_r:dalvik_prop:s0"},
{"dalvik.vm.stack-trace-file", "u:object_r:dalvik_prop:s0"},
{"dalvik.vm.usejit", "u:object_r:dalvik_prop:s0"},
- {"dalvik.vm.usejitprofiles", "u:object_r:dalvik_prop:s0"},
{"debug.atrace.tags.enableflags", "u:object_r:debug_prop:s0"},
{"debug.force_rtl", "u:object_r:debug_prop:s0"},
{"dev.bootcomplete", "u:object_r:system_prop:s0"},
diff --git a/rootdir/etc/linker.config.json b/rootdir/etc/linker.config.json
index c88c7ff..3a98fdb 100644
--- a/rootdir/etc/linker.config.json
+++ b/rootdir/etc/linker.config.json
@@ -27,6 +27,8 @@
// statsd
"libstatspull.so",
"libstatssocket.so",
+ // tethering LLNDK
+ "libcom.android.tethering.connectivity_native.so",
// adbd
"libadb_pairing_auth.so",
"libadb_pairing_connection.so",
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 1eec061..1131f3f 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -535,10 +535,6 @@
# /data, which in turn can only be loaded when system properties are present.
trigger post-fs-data
- # APEXes are ready to use. apex-ready is a public trigger similar to apexd.status=ready which
- # is a system-private property.
- trigger apex-ready
-
# Should be before netd, but after apex, properties and logging is available.
trigger load_bpf_programs
@@ -1112,6 +1108,7 @@
# are not aware of using fsync()/sync() to prepare sudden power-cut.
write /dev/sys/fs/by-name/userdata/cp_interval 200
write /dev/sys/fs/by-name/userdata/gc_urgent_sleep_time 50
+ write /dev/sys/fs/by-name/userdata/iostat_period_ms 1000
write /dev/sys/fs/by-name/userdata/iostat_enable 1
# set readahead multiplier for POSIX_FADV_SEQUENTIAL files
@@ -1315,7 +1312,6 @@
on userspace-reboot-resume
trigger userspace-reboot-fs-remount
trigger post-fs-data
- trigger apex-ready
trigger zygote-start
trigger early-boot
trigger boot
diff --git a/trusty/gatekeeper/TEST_MAPPING b/trusty/gatekeeper/TEST_MAPPING
new file mode 100644
index 0000000..da6c769
--- /dev/null
+++ b/trusty/gatekeeper/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "presubmit": [
+ {
+ "name": "VtsHalGatekeeperTargetTest"
+ }
+ ]
+}
diff --git a/trusty/keymaster/Android.bp b/trusty/keymaster/Android.bp
index adc9fdf..31f0a72 100644
--- a/trusty/keymaster/Android.bp
+++ b/trusty/keymaster/Android.bp
@@ -109,6 +109,7 @@
"keymint_use_latest_hal_aidl_ndk_shared",
],
shared_libs: [
+ "android.hardware.security.rkp-V3-ndk",
"android.hardware.security.secureclock-V1-ndk",
"android.hardware.security.sharedsecret-V1-ndk",
"lib_android_keymaster_keymint_utils",
diff --git a/trusty/keymaster/TEST_MAPPING b/trusty/keymaster/TEST_MAPPING
new file mode 100644
index 0000000..ae48327
--- /dev/null
+++ b/trusty/keymaster/TEST_MAPPING
@@ -0,0 +1,13 @@
+{
+ "presubmit": [
+ {
+ "name": "RemoteProvisionerUnitTests"
+ },
+ {
+ "name": "VtsAidlKeyMintTargetTest"
+ },
+ {
+ "name": "VtsHalRemotelyProvisionedComponentTargetTest"
+ }
+ ]
+}
diff --git a/trusty/keymaster/keymint/TrustyRemotelyProvisionedComponentDevice.cpp b/trusty/keymaster/keymint/TrustyRemotelyProvisionedComponentDevice.cpp
index c6800cd..710be3e 100644
--- a/trusty/keymaster/keymint/TrustyRemotelyProvisionedComponentDevice.cpp
+++ b/trusty/keymaster/keymint/TrustyRemotelyProvisionedComponentDevice.cpp
@@ -85,6 +85,7 @@
info->rpcAuthorName = std::move(response.rpcAuthorName);
info->supportedEekCurve = response.supportedEekCurve;
info->uniqueId = std::move(response.uniqueId);
+ info->supportedNumKeysInCsr = response.supportedNumKeysInCsr;
return ScopedAStatus::ok();
}
diff --git a/trusty/storage/proxy/Android.bp b/trusty/storage/proxy/Android.bp
index 94f26d8..e952ee0 100644
--- a/trusty/storage/proxy/Android.bp
+++ b/trusty/storage/proxy/Android.bp
@@ -32,11 +32,11 @@
shared_libs: [
"libbase",
+ "libcutils",
"liblog",
"libhardware_legacy",
],
header_libs: [
- "libcutils_headers",
"libgsi_headers",
],
diff --git a/trusty/storage/proxy/storage.c b/trusty/storage/proxy/storage.c
index c531cfd..033dc21 100644
--- a/trusty/storage/proxy/storage.c
+++ b/trusty/storage/proxy/storage.c
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+#include <cutils/properties.h>
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
@@ -43,6 +44,22 @@
static const char *ssdir_name;
+/*
+ * Property set to 1 after we have opened a file under ssdir_name. The backing
+ * files for both TD and TDP are currently located under /data/vendor/ss and can
+ * only be opened once userdata is mounted. This storageproxyd service is
+ * restarted when userdata is available, which causes the Trusty storage service
+ * to reconnect and attempt to open the backing files for TD and TDP. Once we
+ * set this property, other users can expect that the Trusty storage service
+ * ports will be available (although they may block if still being initialized),
+ * and connections will not be reset after this point (assuming the
+ * storageproxyd service stays running).
+ */
+#define FS_READY_PROPERTY "ro.vendor.trusty.storage.fs_ready"
+
+/* has FS_READY_PROPERTY been set? */
+static bool fs_ready_initialized = false;
+
static enum sync_state fs_state;
static enum sync_state fd_state[FD_TBL_SIZE];
@@ -336,6 +353,16 @@
ALOGV("%s: \"%s\": fd = %u: handle = %d\n",
__func__, path, rc, resp.handle);
+ /* a backing file has been opened, notify any waiting init steps */
+ if (!fs_ready_initialized) {
+ rc = property_set(FS_READY_PROPERTY, "1");
+ if (rc == 0) {
+ fs_ready_initialized = true;
+ } else {
+ ALOGE("Could not set property %s, rc: %d\n", FS_READY_PROPERTY, rc);
+ }
+ }
+
return ipc_respond(msg, &resp, sizeof(resp));
err_response: