Merge "Create misc_ce and misc_de mirror storage"
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/debuggerd/crasher/Android.bp b/debuggerd/crasher/Android.bp
index 3af806b..fe1689c 100644
--- a/debuggerd/crasher/Android.bp
+++ b/debuggerd/crasher/Android.bp
@@ -15,6 +15,7 @@
"-fstack-protector-all",
"-Wno-date-time",
],
+ tidy: false, // crasher.cpp tests many memory access errors
srcs: ["crasher.cpp"],
arch: {
arm: {
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 f8befd3..e929f42 100644
--- a/fastboot/device/commands.cpp
+++ b/fastboot/device/commands.cpp
@@ -131,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}},
diff --git a/fastboot/device/variables.cpp b/fastboot/device/variables.cpp
index 5f99656..d2a7947 100644
--- a/fastboot/device/variables.cpp
+++ b/fastboot/device/variables.cpp
@@ -379,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/fastboot.cpp b/fastboot/fastboot.cpp
index 46190f2..f1b82e9 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -129,23 +129,23 @@
};
struct Image {
- const char* nickname;
- const char* img_name;
- const char* sig_name;
- const char* part_name;
+ std::string nickname;
+ std::string img_name;
+ std::string sig_name;
+ std::string part_name;
bool optional_if_no_image;
ImageType type;
- bool IsSecondary() const { return nickname == nullptr; }
+ bool IsSecondary() const { return nickname.empty(); }
};
-static Image images[] = {
+static std::vector<Image> images = {
// clang-format off
{ "boot", "boot.img", "boot.sig", "boot", false, ImageType::BootCritical },
{ "init_boot",
"init_boot.img", "init_boot.sig",
"init_boot",
true, ImageType::BootCritical },
- { nullptr, "boot_other.img", "boot.sig", "boot", true, ImageType::Normal },
+ { "", "boot_other.img", "boot.sig", "boot", true, ImageType::Normal },
{ "cache", "cache.img", "cache.sig", "cache", true, ImageType::Extra },
{ "dtbo", "dtbo.img", "dtbo.sig", "dtbo", true, ImageType::BootCritical },
{ "dts", "dt.img", "dt.sig", "dts", true, ImageType::BootCritical },
@@ -164,7 +164,7 @@
"system_ext.img", "system_ext.sig",
"system_ext",
true, ImageType::Normal },
- { nullptr, "system_other.img", "system.sig", "system", true, ImageType::Normal },
+ { "", "system_other.img", "system.sig", "system", true, ImageType::Normal },
{ "userdata", "userdata.img", "userdata.sig", "userdata", true, ImageType::Extra },
{ "vbmeta", "vbmeta.img", "vbmeta.sig", "vbmeta", true, ImageType::BootCritical },
{ "vbmeta_system",
@@ -191,7 +191,7 @@
"vendor_kernel_boot.sig",
"vendor_kernel_boot",
true, ImageType::BootCritical },
- { nullptr, "vendor_other.img", "vendor.sig", "vendor", true, ImageType::Normal },
+ { "", "vendor_other.img", "vendor.sig", "vendor", true, ImageType::Normal },
// clang-format on
};
@@ -212,8 +212,8 @@
}
static std::string find_item(const std::string& item) {
- for (size_t i = 0; i < arraysize(images); ++i) {
- if (images[i].nickname && item == images[i].nickname) {
+ for (size_t i = 0; i < images.size(); ++i) {
+ if (!images[i].nickname.empty() && item == images[i].nickname) {
return find_item_given_name(images[i].img_name);
}
}
@@ -274,7 +274,8 @@
// require matching serial number or device path if requested
// at the command line with the -s option.
if (local_serial && (strcmp(local_serial, info->serial_number) != 0 &&
- strcmp(local_serial, info->device_path) != 0)) return -1;
+ strcmp(local_serial, info->device_path) != 0))
+ return -1;
return 0;
}
@@ -532,15 +533,15 @@
std::vector<char> dtb_data;
if (!g_dtb_path.empty()) {
if (g_boot_img_hdr.header_version != 2) {
- die("Argument dtb not supported for boot image header version %d\n",
- g_boot_img_hdr.header_version);
+ die("Argument dtb not supported for boot image header version %d\n",
+ g_boot_img_hdr.header_version);
}
if (!ReadFileToVector(g_dtb_path, &dtb_data)) {
die("cannot load '%s': %s", g_dtb_path.c_str(), strerror(errno));
}
}
- fprintf(stderr,"creating boot image...\n");
+ fprintf(stderr, "creating boot image...\n");
std::vector<char> out;
mkbootimg(kernel_data, ramdisk_data, second_stage_data, dtb_data, g_base_addr, g_boot_img_hdr,
@@ -562,15 +563,15 @@
}
if (zip_entry.uncompressed_length > std::numeric_limits<size_t>::max()) {
- die("entry '%s' is too large: %" PRIu64, entry_name.c_str(), zip_entry.uncompressed_length);
+ die("entry '%s' is too large: %" PRIu64, entry_name.c_str(), zip_entry.uncompressed_length);
}
out->resize(zip_entry.uncompressed_length);
fprintf(stderr, "extracting %s (%zu MB) to RAM...\n", entry_name.c_str(),
out->size() / 1024 / 1024);
- int error = ExtractToMemory(zip, &zip_entry, reinterpret_cast<uint8_t*>(out->data()),
- out->size());
+ int error =
+ ExtractToMemory(zip, &zip_entry, reinterpret_cast<uint8_t*>(out->data()), out->size());
if (error != 0) die("failed to extract '%s': %s", entry_name.c_str(), ErrorCodeString(error));
return true;
@@ -618,8 +619,8 @@
std::string path_template(make_temporary_template());
int fd = mkstemp(&path_template[0]);
if (fd == -1) {
- die("failed to create temporary file for %s with template %s: %s\n",
- path_template.c_str(), what, strerror(errno));
+ die("failed to create temporary file for %s with template %s: %s\n", path_template.c_str(),
+ what, strerror(errno));
}
unlink(path_template.c_str());
return fd;
@@ -673,16 +674,15 @@
std::string var_value;
if (fb->GetVar(var, &var_value) != fastboot::SUCCESS) {
fprintf(stderr, "FAILED\n\n");
- fprintf(stderr, "Could not getvar for '%s' (%s)\n\n", var.c_str(),
- fb->Error().c_str());
+ fprintf(stderr, "Could not getvar for '%s' (%s)\n\n", var.c_str(), fb->Error().c_str());
return false;
}
bool match = false;
for (const auto& option : options) {
- if (option == var_value || (option.back() == '*' &&
- !var_value.compare(0, option.length() - 1, option, 0,
- option.length() - 1))) {
+ if (option == var_value ||
+ (option.back() == '*' &&
+ !var_value.compare(0, option.length() - 1, option, 0, option.length() - 1))) {
match = true;
break;
}
@@ -757,8 +757,8 @@
die("device doesn't have required partition %s!", partition_name.c_str());
}
bool known_partition = false;
- for (size_t i = 0; i < arraysize(images); ++i) {
- if (images[i].nickname && images[i].nickname == partition_name) {
+ for (size_t i = 0; i < images.size(); ++i) {
+ if (!images[i].nickname.empty() && images[i].nickname == partition_name) {
images[i].optional_if_no_image = false;
known_partition = true;
}
@@ -796,9 +796,9 @@
bool met = CheckRequirement(cur_product, name, product, invert, options);
if (!met) {
if (!force_flash) {
- die("requirements not met!");
+ die("requirements not met!");
} else {
- fprintf(stderr, "requirements not met! but proceeding due to --force\n");
+ fprintf(stderr, "requirements not met! but proceeding due to --force\n");
}
}
}
@@ -822,7 +822,6 @@
DisplayVarOrError("Baseband Version.....", "version-baseband");
DisplayVarOrError("Serial Number........", "serialno");
fprintf(stderr, "--------------------------------------------\n");
-
}
static struct sparse_file** load_sparse_files(int fd, int64_t max_size) {
@@ -830,13 +829,14 @@
if (!s) die("cannot sparse read file");
if (max_size <= 0 || max_size > std::numeric_limits<uint32_t>::max()) {
- die("invalid max size %" PRId64, max_size);
+ die("invalid max size %" PRId64, max_size);
}
int files = sparse_file_resparse(s, max_size, nullptr, 0);
if (files < 0) die("Failed to resparse");
- sparse_file** out_s = reinterpret_cast<sparse_file**>(calloc(sizeof(struct sparse_file *), files + 1));
+ sparse_file** out_s =
+ reinterpret_cast<sparse_file**>(calloc(sizeof(struct sparse_file*), files + 1));
if (!out_s) die("Failed to allocate sparse file array");
files = sparse_file_resparse(s, max_size, out_s, files);
@@ -1078,8 +1078,7 @@
lseek(buf->fd.get(), 0, SEEK_SET);
}
-static void flash_buf(const std::string& partition, struct fastboot_buffer *buf)
-{
+static void flash_buf(const std::string& partition, struct fastboot_buffer* buf) {
sparse_file** s;
if (partition == "boot" || partition == "boot_a" || partition == "boot_b" ||
@@ -1097,7 +1096,7 @@
rewrite_vbmeta_buffer(buf, false /* vbmeta_in_boot */);
} else if (!has_vbmeta_partition() &&
(partition == "boot" || partition == "boot_a" || partition == "boot_b")) {
- rewrite_vbmeta_buffer(buf, true /* vbmeta_in_boot */ );
+ rewrite_vbmeta_buffer(buf, true /* vbmeta_in_boot */);
}
}
@@ -1143,14 +1142,14 @@
}
static bool supports_AB() {
- return get_slot_count() >= 2;
+ return get_slot_count() >= 2;
}
// Given a current slot, this returns what the 'other' slot is.
static std::string get_other_slot(const std::string& current_slot, int count) {
if (count == 0) return "";
- char next = (current_slot[0] - 'a' + 1)%count + 'a';
+ char next = (current_slot[0] - 'a' + 1) % count + 'a';
return std::string(1, next);
}
@@ -1185,17 +1184,17 @@
if (count == 0) die("Device does not support slots");
if (slot == "other") {
- std::string other = get_other_slot( count);
+ std::string other = get_other_slot(count);
if (other == "") {
- die("No known slots");
+ die("No known slots");
}
return other;
}
- if (slot.size() == 1 && (slot[0]-'a' >= 0 && slot[0]-'a' < count)) return slot;
+ if (slot.size() == 1 && (slot[0] - 'a' >= 0 && slot[0] - 'a' < count)) return slot;
fprintf(stderr, "Slot %s does not exist. supported slots are:\n", slot.c_str());
- for (int i=0; i<count; i++) {
+ for (int i = 0; i < count; i++) {
fprintf(stderr, "%c\n", (char)(i + 'a'));
}
@@ -1203,7 +1202,7 @@
}
static std::string verify_slot(const std::string& slot) {
- return verify_slot(slot, true);
+ return verify_slot(slot, true);
}
static void do_for_partition(const std::string& part, const std::string& slot,
@@ -1243,7 +1242,8 @@
* partition does not support slots.
*/
static void do_for_partitions(const std::string& part, const std::string& slot,
- const std::function<void(const std::string&)>& func, bool force_slot) {
+ const std::function<void(const std::string&)>& func,
+ bool force_slot) {
std::string has_slot;
// |part| can be vendor_boot:default. Query has-slot on the first token only.
auto part_tokens = android::base::Split(part, ":");
@@ -1254,7 +1254,7 @@
slot.c_str());
}
if (has_slot == "yes") {
- for (int i=0; i < get_slot_count(); i++) {
+ for (int i = 0; i < get_slot_count(); i++) {
do_for_partition(part, std::string(1, (char)(i + 'a')), func, force_slot);
}
} else {
@@ -1403,7 +1403,7 @@
class ImageSource {
public:
- virtual ~ImageSource() {};
+ virtual ~ImageSource(){};
virtual bool ReadFile(const std::string& name, std::vector<char>* out) const = 0;
virtual unique_fd OpenFile(const std::string& name) const = 0;
};
@@ -1435,13 +1435,11 @@
FlashAllTool::FlashAllTool(const ImageSource& source, const std::string& slot_override,
bool skip_secondary, bool wipe, bool force_flash)
- : source_(source),
- slot_override_(slot_override),
- skip_secondary_(skip_secondary),
- wipe_(wipe),
- force_flash_(force_flash)
-{
-}
+ : source_(source),
+ slot_override_(slot_override),
+ skip_secondary_(skip_secondary),
+ wipe_(wipe),
+ force_flash_(force_flash) {}
void FlashAllTool::Flash() {
DumpInfo();
@@ -1508,7 +1506,7 @@
}
void FlashAllTool::CollectImages() {
- for (size_t i = 0; i < arraysize(images); ++i) {
+ for (size_t i = 0; i < images.size(); ++i) {
std::string slot = slot_override_;
if (images[i].IsSecondary()) {
if (skip_secondary_) {
@@ -1532,7 +1530,7 @@
if (image->optional_if_no_image) {
continue;
}
- die("could not load '%s': %s", image->img_name, strerror(errno));
+ die("could not load '%s': %s", image->img_name.c_str(), strerror(errno));
}
FlashImage(*image, slot, &buf);
}
@@ -1734,8 +1732,7 @@
fprintf(stderr, "File system type %s not supported.\n", partition_type.c_str());
return;
}
- die("Formatting is not supported for file system with type '%s'.",
- partition_type.c_str());
+ die("Formatting is not supported for file system with type '%s'.", partition_type.c_str());
}
int64_t size;
@@ -1892,32 +1889,30 @@
g_boot_img_hdr.page_size = 2048;
g_boot_img_hdr.dtb_addr = 0x01100000;
- const struct option longopts[] = {
- {"base", required_argument, 0, 0},
- {"cmdline", required_argument, 0, 0},
- {"disable-verification", no_argument, 0, 0},
- {"disable-verity", no_argument, 0, 0},
- {"force", no_argument, 0, 0},
- {"fs-options", required_argument, 0, 0},
- {"header-version", required_argument, 0, 0},
- {"help", no_argument, 0, 'h'},
- {"kernel-offset", required_argument, 0, 0},
- {"os-patch-level", required_argument, 0, 0},
- {"os-version", required_argument, 0, 0},
- {"page-size", required_argument, 0, 0},
- {"ramdisk-offset", required_argument, 0, 0},
- {"set-active", optional_argument, 0, 'a'},
- {"skip-reboot", no_argument, 0, 0},
- {"skip-secondary", no_argument, 0, 0},
- {"slot", required_argument, 0, 0},
- {"tags-offset", required_argument, 0, 0},
- {"dtb", required_argument, 0, 0},
- {"dtb-offset", required_argument, 0, 0},
- {"unbuffered", no_argument, 0, 0},
- {"verbose", no_argument, 0, 'v'},
- {"version", no_argument, 0, 0},
- {0, 0, 0, 0}
- };
+ const struct option longopts[] = {{"base", required_argument, 0, 0},
+ {"cmdline", required_argument, 0, 0},
+ {"disable-verification", no_argument, 0, 0},
+ {"disable-verity", no_argument, 0, 0},
+ {"force", no_argument, 0, 0},
+ {"fs-options", required_argument, 0, 0},
+ {"header-version", required_argument, 0, 0},
+ {"help", no_argument, 0, 'h'},
+ {"kernel-offset", required_argument, 0, 0},
+ {"os-patch-level", required_argument, 0, 0},
+ {"os-version", required_argument, 0, 0},
+ {"page-size", required_argument, 0, 0},
+ {"ramdisk-offset", required_argument, 0, 0},
+ {"set-active", optional_argument, 0, 'a'},
+ {"skip-reboot", no_argument, 0, 0},
+ {"skip-secondary", no_argument, 0, 0},
+ {"slot", required_argument, 0, 0},
+ {"tags-offset", required_argument, 0, 0},
+ {"dtb", required_argument, 0, 0},
+ {"dtb-offset", required_argument, 0, 0},
+ {"unbuffered", no_argument, 0, 0},
+ {"verbose", no_argument, 0, 'v'},
+ {"version", no_argument, 0, 0},
+ {0, 0, 0, 0}};
serial = getenv("ANDROID_SERIAL");
@@ -1966,7 +1961,8 @@
setvbuf(stdout, nullptr, _IONBF, 0);
setvbuf(stderr, nullptr, _IONBF, 0);
} else if (name == "version") {
- fprintf(stdout, "fastboot version %s-%s\n", PLATFORM_TOOLS_VERSION, android::build::GetBuildNumber().c_str());
+ fprintf(stdout, "fastboot version %s-%s\n", PLATFORM_TOOLS_VERSION,
+ android::build::GetBuildNumber().c_str());
fprintf(stdout, "Installed as %s\n", android::base::GetExecutablePath().c_str());
return 0;
} else {
@@ -2024,9 +2020,9 @@
return 1;
}
fastboot::DriverCallbacks driver_callbacks = {
- .prolog = Status,
- .epilog = Epilog,
- .info = InfoMessage,
+ .prolog = Status,
+ .epilog = Epilog,
+ .info = InfoMessage,
};
fastboot::FastBootDriver fastboot_driver(transport, driver_callbacks, false);
fb = &fastboot_driver;
@@ -2063,7 +2059,8 @@
std::string partition = next_arg(&args);
auto erase = [&](const std::string& partition) {
std::string partition_type;
- if (fb->GetVar("partition-type:" + partition, &partition_type) == fastboot::SUCCESS &&
+ if (fb->GetVar("partition-type:" + partition, &partition_type) ==
+ fastboot::SUCCESS &&
fs_get_generator(partition_type) != nullptr) {
fprintf(stderr, "******** Did you mean to fastboot format this %s partition?\n",
partition_type.c_str());
@@ -2118,7 +2115,6 @@
} else {
syntax_error("unknown reboot target %s", what.c_str());
}
-
}
if (!args.empty()) syntax_error("junk after reboot command");
} else if (command == FB_CMD_REBOOT_BOOTLOADER) {
@@ -2149,7 +2145,7 @@
}
if (fname.empty()) die("cannot determine image filename for '%s'", pname.c_str());
- auto flash = [&](const std::string &partition) {
+ auto flash = [&](const std::string& partition) {
if (should_flash_in_userspace(partition) && !is_userspace_fastboot() &&
!force_flash) {
die("The partition you are trying to flash is dynamic, and "
@@ -2178,7 +2174,8 @@
do_for_partitions(partition, slot_override, flashraw, true);
} else if (command == "flashall") {
if (slot_override == "all") {
- fprintf(stderr, "Warning: slot set to 'all'. Secondary slots will not be flashed.\n");
+ fprintf(stderr,
+ "Warning: slot set to 'all'. Secondary slots will not be flashed.\n");
do_flashall(slot_override, true, wants_wipe, force_flash);
} else {
do_flashall(slot_override, skip_secondary, wants_wipe, force_flash);
@@ -2187,7 +2184,8 @@
} else if (command == "update") {
bool slot_all = (slot_override == "all");
if (slot_all) {
- fprintf(stderr, "Warning: slot set to 'all'. Secondary slots will not be flashed.\n");
+ fprintf(stderr,
+ "Warning: slot set to 'all'. Secondary slots will not be flashed.\n");
}
std::string filename = "update.zip";
if (!args.empty()) {
@@ -2214,10 +2212,9 @@
} else if (command == "flashing") {
if (args.empty()) {
syntax_error("missing 'flashing' command");
- } else if (args.size() == 1 && (args[0] == "unlock" || args[0] == "lock" ||
- args[0] == "unlock_critical" ||
- args[0] == "lock_critical" ||
- args[0] == "get_unlock_ability")) {
+ } else if (args.size() == 1 &&
+ (args[0] == "unlock" || args[0] == "lock" || args[0] == "unlock_critical" ||
+ args[0] == "lock_critical" || args[0] == "get_unlock_ability")) {
do_oem_command("flashing", &args);
} else {
syntax_error("unknown 'flashing' command %s", args[0].c_str());
@@ -2272,7 +2269,7 @@
if (force_flash) {
CancelSnapshotIfNeeded();
}
- std::vector<std::string> partitions = { "userdata", "cache", "metadata" };
+ std::vector<std::string> partitions = {"userdata", "cache", "metadata"};
for (const auto& partition : partitions) {
std::string partition_type;
if (fb->GetVar("partition-type:" + partition, &partition_type) != fastboot::SUCCESS) {
@@ -2334,8 +2331,7 @@
unsigned fsOptions = 0;
std::vector<std::string> options = android::base::Split(arg, ",");
- if (options.size() < 1)
- syntax_error("bad options: %s", arg);
+ if (options.size() < 1) syntax_error("bad options: %s", arg);
for (size_t i = 0; i < options.size(); ++i) {
if (options[i] == "casefold")
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/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_remount.cpp b/fs_mgr/fs_mgr_remount.cpp
index eac3ff2..23bc8e8 100644
--- a/fs_mgr/fs_mgr_remount.cpp
+++ b/fs_mgr/fs_mgr_remount.cpp
@@ -139,19 +139,6 @@
}
}
-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);
@@ -172,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
@@ -184,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) {
@@ -247,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) {
@@ -260,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;
@@ -275,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;
@@ -283,7 +269,7 @@
partitions->emplace_back(*entry);
}
- return REMOUNT_SUCCESS;
+ return true;
}
struct RemountCheckResult {
@@ -294,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;
}
@@ -342,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);
@@ -407,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);
@@ -422,20 +386,19 @@
}
// 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;
}
struct SetVerityStateResult {
@@ -445,30 +408,33 @@
SetVerityStateResult SetVerityState(bool enable_verity) {
const auto ab_suffix = android::base::GetProperty("ro.boot.slot_suffix", "");
- bool verity_enabled = false;
-
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 {};
}
-
+ 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};
}
@@ -500,25 +466,48 @@
return want_reboot;
}
-static int do_remount(Fstab& fstab, const std::vector<std::string>& partition_args,
- RemountCheckResult* check_result) {
+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.
@@ -531,18 +520,18 @@
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
@@ -552,7 +541,7 @@
// 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(false /* verbose */));
@@ -573,7 +562,7 @@
switch (opt) {
case 'h':
usage();
- return 0;
+ return EXIT_SUCCESS;
case 'R':
auto_reboot = true;
break;
@@ -581,7 +570,7 @@
if (fstab_file) {
LOG(ERROR) << "Cannot supply two fstabs: -T " << fstab_file << " -T " << optarg;
usage();
- return 1;
+ return EXIT_FAILURE;
}
fstab_file = optarg;
break;
@@ -591,7 +580,7 @@
default:
LOG(ERROR) << "Bad argument -" << char(opt);
usage();
- return 1;
+ return EXIT_FAILURE;
}
}
@@ -611,7 +600,7 @@
enable_verity = (argv[optind] == "1"s);
} else {
usage();
- return 1;
+ return EXIT_FAILURE;
}
} else {
remount = true;
@@ -623,7 +612,7 @@
// Make sure we are root.
if (::getuid() != 0) {
LOG(ERROR) << "Not running as root. Try \"adb root\" first.";
- return 1;
+ return EXIT_FAILURE;
}
// If somehow this executable is delivered on a "user" build, it can
@@ -631,12 +620,12 @@
// 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;
+ return EXIT_FAILURE;
}
- if (android::base::GetProperty("ro.boot.vbmeta.device_state", "") == "locked") {
+ if (android::base::GetProperty("ro.boot.verifiedbootstate", "") != "orange") {
LOG(ERROR) << "Device must be bootloader unlocked";
- return 1;
+ return EXIT_FAILURE;
}
// Start a threadpool to service waitForService() callbacks as
@@ -644,14 +633,6 @@
android::ProcessState::self()->startThreadPool();
if (!remount) {
- // 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).
- if (android::base::GetProperty("ro.boot.vbmeta.digest", "").empty()) {
- LOG(ERROR) << "Expected AVB device, VB1.0 is no longer supported";
- return 1;
- }
-
auto ret = SetVerityState(enable_verity);
// Disable any overlayfs unconditionally if we want verity enabled.
@@ -666,23 +647,23 @@
}
std::cout << "Reboot the device for new settings to take effect" << std::endl;
}
- return ret.success ? 0 : 1;
+ 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.";
@@ -691,10 +672,10 @@
} else if (check_result.setup_overlayfs) {
LOG(INFO) << "Overlayfs enabled.";
}
- if (result == REMOUNT_SUCCESS) {
- LOG(INFO) << "remount succeeded";
- } else {
- LOG(ERROR) << "remount failed";
+ 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) {
@@ -702,15 +683,15 @@
// 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("remount");
} else {
LOG(INFO) << "Now reboot your device for settings to take effect";
}
- return REMOUNT_SUCCESS;
+ return EXIT_SUCCESS;
}
- 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/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/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/fs_mgr/tools/dmuserd.cpp b/fs_mgr/tools/dmuserd.cpp
index 6b68b28..da7156c 100644
--- a/fs_mgr/tools/dmuserd.cpp
+++ b/fs_mgr/tools/dmuserd.cpp
@@ -13,6 +13,7 @@
#include <sys/prctl.h>
#include <unistd.h>
#include <iostream>
+#include <string>
#define SECTOR_SIZE ((__u64)512)
#define BUFFER_BYTES 4096
@@ -133,16 +134,16 @@
return 0;
}
-int simple_daemon(char* control_path, char* backing_path) {
- int control_fd = open(control_path, O_RDWR);
+static int simple_daemon(const std::string& control_path, const std::string& backing_path) {
+ int control_fd = open(control_path.c_str(), O_RDWR);
if (control_fd < 0) {
- fprintf(stderr, "Unable to open control device %s\n", control_path);
+ fprintf(stderr, "Unable to open control device %s\n", control_path.c_str());
return -1;
}
- int backing_fd = open(backing_path, O_RDWR);
+ int backing_fd = open(backing_path.c_str(), O_RDWR);
if (backing_fd < 0) {
- fprintf(stderr, "Unable to open backing device %s\n", backing_path);
+ fprintf(stderr, "Unable to open backing device %s\n", backing_path.c_str());
return -1;
}
@@ -286,8 +287,8 @@
}
int main(int argc, char* argv[]) {
- char* control_path = NULL;
- char* backing_path = NULL;
+ std::string control_path;
+ std::string backing_path;
char* store;
int c;
@@ -299,10 +300,10 @@
usage(basename(argv[0]));
exit(0);
case 'c':
- control_path = strdup(optarg);
+ control_path = optarg;
break;
case 'b':
- backing_path = strdup(optarg);
+ backing_path = optarg;
break;
case 'v':
verbose = true;
diff --git a/init/Android.bp b/init/Android.bp
index 06f696e..c7e7de8 100644
--- a/init/Android.bp
+++ b/init/Android.bp
@@ -109,21 +109,22 @@
misc_undefined: ["signed-integer-overflow"],
},
cflags: [
- "-DLOG_UEVENTS=0",
- "-Wall",
- "-Wextra",
- "-Wno-unused-parameter",
- "-Werror",
- "-Wthread-safety",
"-DALLOW_FIRST_STAGE_CONSOLE=0",
"-DALLOW_LOCAL_PROP_OVERRIDE=0",
"-DALLOW_PERMISSIVE_SELINUX=0",
- "-DREBOOT_BOOTLOADER_ON_PANIC=0",
- "-DWORLD_WRITABLE_KMSG=0",
+ "-DANDROID_BASE_UNIQUE_FD_DISABLE_IMPLICIT_CONVERSION",
"-DDUMP_ON_UMOUNT_FAILURE=0",
- "-DSHUTDOWN_ZERO_TIMEOUT=0",
"-DINIT_FULL_SOURCES",
"-DINSTALL_DEBUG_POLICY_TO_SYSTEM_EXT=0",
+ "-DLOG_UEVENTS=0",
+ "-DREBOOT_BOOTLOADER_ON_PANIC=0",
+ "-DSHUTDOWN_ZERO_TIMEOUT=0",
+ "-DWORLD_WRITABLE_KMSG=0",
+ "-Wall",
+ "-Werror",
+ "-Wextra",
+ "-Wno-unused-parameter",
+ "-Wthread-safety",
],
product_variables: {
debuggable: {
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 7cb8b11..a89813e 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -331,13 +331,13 @@
unique_fd s(TEMP_FAILURE_RETRY(socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0)));
if (s < 0) return ErrnoError() << "opening socket failed";
- if (ioctl(s, SIOCGIFFLAGS, &ifr) < 0) {
+ if (ioctl(s.get(), SIOCGIFFLAGS, &ifr) < 0) {
return ErrnoError() << "ioctl(..., SIOCGIFFLAGS, ...) failed";
}
ifr.ifr_flags |= IFF_UP;
- if (ioctl(s, SIOCSIFFLAGS, &ifr) < 0) {
+ if (ioctl(s.get(), SIOCSIFFLAGS, &ifr) < 0) {
return ErrnoError() << "ioctl(..., SIOCSIFFLAGS, ...) failed";
}
@@ -516,11 +516,11 @@
loop_info info;
/* if it is a blank loop device */
- if (ioctl(loop, LOOP_GET_STATUS, &info) < 0 && errno == ENXIO) {
+ if (ioctl(loop.get(), LOOP_GET_STATUS, &info) < 0 && errno == ENXIO) {
/* if it becomes our loop device */
- if (ioctl(loop, LOOP_SET_FD, fd.get()) >= 0) {
+ if (ioctl(loop.get(), LOOP_SET_FD, fd.get()) >= 0) {
if (mount(tmp.c_str(), target, system, flags, options) < 0) {
- ioctl(loop, LOOP_CLR_FD, 0);
+ ioctl(loop.get(), LOOP_CLR_FD, 0);
return ErrnoError() << "mount() failed";
}
return {};
@@ -901,16 +901,16 @@
if (fd == -1) {
return ErrnoError() << "Error opening file";
}
- if (posix_fadvise(fd, 0, 0, POSIX_FADV_WILLNEED)) {
+ if (posix_fadvise(fd.get(), 0, 0, POSIX_FADV_WILLNEED)) {
return ErrnoError() << "Error posix_fadvise file";
}
- if (readahead(fd, 0, std::numeric_limits<size_t>::max())) {
+ if (readahead(fd.get(), 0, std::numeric_limits<size_t>::max())) {
return ErrnoError() << "Error readahead file";
}
if (fully) {
char buf[BUFSIZ];
ssize_t n;
- while ((n = TEMP_FAILURE_RETRY(read(fd, &buf[0], sizeof(buf)))) > 0) {
+ while ((n = TEMP_FAILURE_RETRY(read(fd.get(), &buf[0], sizeof(buf)))) > 0) {
}
if (n != 0) {
return ErrnoError() << "Error reading file";
diff --git a/init/epoll.cpp b/init/epoll.cpp
index fd1af4f..cd73a0c 100644
--- a/init/epoll.cpp
+++ b/init/epoll.cpp
@@ -57,7 +57,7 @@
.events = events,
.data.fd = fd,
};
- if (epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, fd, &ev) == -1) {
+ if (epoll_ctl(epoll_fd_.get(), EPOLL_CTL_ADD, fd, &ev) == -1) {
Result<void> result = ErrnoError() << "epoll_ctl failed to add fd";
epoll_handlers_.erase(fd);
return result;
@@ -66,7 +66,7 @@
}
Result<void> Epoll::UnregisterHandler(int fd) {
- if (epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, fd, nullptr) == -1) {
+ if (epoll_ctl(epoll_fd_.get(), EPOLL_CTL_DEL, fd, nullptr) == -1) {
return ErrnoError() << "epoll_ctl failed to remove fd";
}
auto it = epoll_handlers_.find(fd);
@@ -88,7 +88,7 @@
}
const auto max_events = epoll_handlers_.size();
epoll_event ev[max_events];
- auto num_events = TEMP_FAILURE_RETRY(epoll_wait(epoll_fd_, ev, max_events, timeout_ms));
+ auto num_events = TEMP_FAILURE_RETRY(epoll_wait(epoll_fd_.get(), ev, max_events, timeout_ms));
if (num_events == -1) {
return ErrnoError() << "epoll_wait failed";
}
diff --git a/init/firmware_handler.cpp b/init/firmware_handler.cpp
index 30e808d..b9fa58c 100644
--- a/init/firmware_handler.cpp
+++ b/init/firmware_handler.cpp
@@ -257,12 +257,12 @@
return false;
}
struct stat sb;
- if (fstat(fw_fd, &sb) == -1) {
+ if (fstat(fw_fd.get(), &sb) == -1) {
attempted_paths_and_errors.emplace_back("firmware: attempted " + file +
", fstat failed: " + strerror(errno));
return false;
}
- LoadFirmware(firmware, root, fw_fd, sb.st_size, loading_fd, data_fd);
+ LoadFirmware(firmware, root, fw_fd.get(), sb.st_size, loading_fd.get(), data_fd.get());
return true;
};
@@ -287,7 +287,7 @@
}
// Write "-1" as our response to the kernel's firmware request, since we have nothing for it.
- write(loading_fd, "-1", 2);
+ write(loading_fd.get(), "-1", 2);
}
bool FirmwareHandler::ForEachFirmwareDirectory(
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/persistent_properties.cpp b/init/persistent_properties.cpp
index d33a6b8..8db7267 100644
--- a/init/persistent_properties.cpp
+++ b/init/persistent_properties.cpp
@@ -77,7 +77,7 @@
}
struct stat sb;
- if (fstat(fd, &sb) == -1) {
+ if (fstat(fd.get(), &sb) == -1) {
PLOG(ERROR) << "fstat on property file \"" << entry->d_name << "\" failed";
continue;
}
@@ -198,7 +198,7 @@
if (!WriteStringToFd(serialized_string, fd)) {
return ErrnoError() << "Unable to write file contents";
}
- fsync(fd);
+ fsync(fd.get());
fd.reset();
if (rename(temp_filename.c_str(), persistent_property_filename.c_str())) {
@@ -216,7 +216,7 @@
if (dir_fd < 0) {
return ErrnoError() << "Unable to open persistent properties directory for fsync()";
}
- fsync(dir_fd);
+ fsync(dir_fd.get());
return {};
}
diff --git a/init/property_service.cpp b/init/property_service.cpp
index f3550a1..9df9828 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -300,13 +300,13 @@
if (!socket_.ok()) {
return true;
}
- int result = TEMP_FAILURE_RETRY(send(socket_, &value, sizeof(value), 0));
+ int result = TEMP_FAILURE_RETRY(send(socket_.get(), &value, sizeof(value), 0));
return result == sizeof(value);
}
bool GetSourceContext(std::string* source_context) const {
char* c_source_context = nullptr;
- if (getpeercon(socket_, &c_source_context) != 0) {
+ if (getpeercon(socket_.get(), &c_source_context) != 0) {
return false;
}
*source_context = c_source_context;
@@ -320,13 +320,13 @@
private:
bool PollIn(uint32_t* timeout_ms) {
- struct pollfd ufds[1];
- ufds[0].fd = socket_;
- ufds[0].events = POLLIN;
- ufds[0].revents = 0;
+ struct pollfd ufd = {
+ .fd = socket_.get(),
+ .events = POLLIN,
+ };
while (*timeout_ms > 0) {
auto start_time = std::chrono::steady_clock::now();
- int nr = poll(ufds, 1, *timeout_ms);
+ int nr = poll(&ufd, 1, *timeout_ms);
auto now = std::chrono::steady_clock::now();
auto time_elapsed =
std::chrono::duration_cast<std::chrono::milliseconds>(now - start_time);
@@ -368,7 +368,7 @@
return false;
}
- int result = TEMP_FAILURE_RETRY(recv(socket_, data, bytes_left, MSG_DONTWAIT));
+ int result = TEMP_FAILURE_RETRY(recv(socket_.get(), data, bytes_left, MSG_DONTWAIT));
if (result <= 0) {
PLOG(ERROR) << "sys_prop: recv error";
return false;
diff --git a/init/reboot.cpp b/init/reboot.cpp
index 1f4186d..a3fc534 100644
--- a/init/reboot.cpp
+++ b/init/reboot.cpp
@@ -767,7 +767,7 @@
if (IsDataMounted("f2fs")) {
uint32_t flag = F2FS_GOING_DOWN_FULLSYNC;
unique_fd fd(TEMP_FAILURE_RETRY(open("/data", O_RDONLY)));
- int ret = ioctl(fd, F2FS_IOC_SHUTDOWN, &flag);
+ int ret = ioctl(fd.get(), F2FS_IOC_SHUTDOWN, &flag);
if (ret) {
PLOG(ERROR) << "Shutdown /data: ";
} else {
diff --git a/init/security.cpp b/init/security.cpp
index 2ecf687..6e616be 100644
--- a/init/security.cpp
+++ b/init/security.cpp
@@ -216,7 +216,7 @@
return {};
}
- int ioctl_ret = ioctl(fd, PERF_EVENT_IOC_RESET);
+ int ioctl_ret = ioctl(fd.get(), PERF_EVENT_IOC_RESET);
if (ioctl_ret != -1) {
// Success implies that the kernel doesn't have the hooks.
return {};
diff --git a/init/selinux.cpp b/init/selinux.cpp
index ab5b0a0..ea308aa 100644
--- a/init/selinux.cpp
+++ b/init/selinux.cpp
@@ -567,7 +567,7 @@
return ErrnoError() << "Failed to open " << dstPath;
}
- ret = ExtractEntryToFile(archive, &entry, fd);
+ ret = ExtractEntryToFile(archive, &entry, fd.get());
if (ret != 0) {
return Error() << "Failed to extract entry \"" << fileName << "\" ("
<< entry.uncompressed_length << " bytes) to \"" << dstPath
@@ -785,7 +785,7 @@
return;
}
- TEMP_FAILURE_RETRY(send(fd, &request, sizeof(request), 0));
+ TEMP_FAILURE_RETRY(send(fd.get(), &request, sizeof(request), 0));
}
} // namespace
diff --git a/init/service.cpp b/init/service.cpp
index 85ac2fc..2ce81a0 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -136,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)
@@ -227,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
@@ -242,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();
}
@@ -292,7 +290,8 @@
}
if ((siginfo.si_code != CLD_EXITED || siginfo.si_status != 0) && on_failure_reboot_target_) {
- LOG(ERROR) << "Service with 'reboot_on_failure' option failed, shutting down system.";
+ LOG(ERROR) << "Service " << name_
+ << " has 'reboot_on_failure' option and failed, shutting down system.";
trigger_shutdown(*on_failure_reboot_target_);
}
@@ -433,8 +432,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,8 @@
}
// Enters namespaces, sets environment variables, writes PID files and runs the service executable.
-void Service::RunService(const std::vector<Descriptor>& descriptors, InterprocessFifo fifo) {
+void Service::RunService(const std::vector<Descriptor>& descriptors,
+ 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();
}
@@ -529,11 +527,12 @@
// Wait until the cgroups have been created and until the cgroup controllers have been
// activated.
- Result<uint8_t> byte = fifo.Read();
+ Result<uint8_t> byte = cgroups_activated.Read();
if (!byte.ok()) {
LOG(ERROR) << name_ << ": failed to read from notification channel: " << byte.error();
}
- if (!*byte) {
+ cgroups_activated.Close();
+ if (*byte != kCgroupsActivated) {
LOG(FATAL) << "Service '" << name_ << "' failed to start due to a fatal error";
_exit(EXIT_FAILURE);
}
@@ -554,13 +553,7 @@
// As requested, set our gid, supplemental gids, uid, context, and
// priority. Aborts on failure.
- SetProcessAttributesAndCaps();
-
- // If SetProcessAttributes() called setsid(), report this to the parent.
- if (RequiresConsole(proc_attr_)) {
- fifo.Write(2);
- }
- fifo.Close();
+ SetProcessAttributesAndCaps(std::move(setsid_finished));
if (!ExpandArgsAndExecv(args_, sigstop_)) {
PLOG(ERROR) << "cannot execv('" << args_[0]
@@ -603,8 +596,14 @@
return {};
}
- InterprocessFifo fifo;
- OR_RETURN(fifo.Initialize());
+ // 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;
@@ -662,8 +661,13 @@
if (pid == 0) {
umask(077);
- RunService(descriptors, std::move(fifo));
+ cgroups_activated.CloseWriteFd();
+ 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) {
@@ -692,7 +696,7 @@
limit_percent_ != -1 || !limit_property_.empty();
errno = -createProcessGroup(proc_attr_.uid, pid_, use_memcg);
if (errno != 0) {
- Result<void> result = fifo.Write(0);
+ Result<void> result = cgroups_activated.Write(kActivatingCgroupsFailed);
if (!result.ok()) {
return Error() << "Sending notification failed: " << result.error();
}
@@ -716,17 +720,19 @@
LmkdRegister(name_, proc_attr_.uid, pid_, oom_score_adjust_);
}
- if (Result<void> result = fifo.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 (proc_attr_.console.empty()) {
+ if (!RequiresConsole(proc_attr_)) {
if (setpgid(pid, pid) < 0) {
switch (errno) {
- case EACCES: // Child has already performed execve().
- case ESRCH: // Child process no longer exists.
+ 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";
@@ -734,16 +740,18 @@
}
} else {
// The Read() call below will return an error if the child is killed.
- if (Result<uint8_t> result = fifo.Read(); !result.ok() || *result != 2) {
+ 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: " << *result << " <> 2";
+ return Error() << "Waiting for setsid() failed: " << static_cast<uint32_t>(*result)
+ << " <> " << static_cast<uint32_t>(kSetSidFinished);
}
}
}
- fifo.Close();
+ setsid_finished.Close();
NotifyStateChange("running");
reboot_on_failure.Disable();
diff --git a/init/service.h b/init/service.h
index 2c2778d..f9749d2 100644
--- a/init/service.h
+++ b/init/service.h
@@ -73,6 +73,8 @@
const std::vector<gid_t>& supp_gids, int namespace_flags, const std::string& seclabel,
Subcontext* subcontext_for_restart_commands, const std::string& filename,
const std::vector<std::string>& args);
+ Service(const Service&) = delete;
+ void operator=(const Service&) = delete;
static Result<std::unique_ptr<Service>> MakeTemporaryOneshotService(
const std::vector<std::string>& args);
@@ -104,10 +106,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 +141,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 +149,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 fifo);
+ 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 +183,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 +217,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_list.cpp b/init/service_list.cpp
index 3047821..937d82e 100644
--- a/init/service_list.cpp
+++ b/init/service_list.cpp
@@ -24,8 +24,8 @@
ServiceList::ServiceList() {}
ServiceList& ServiceList::GetInstance() {
- static ServiceList instance;
- return instance;
+ static ServiceList* instance = new ServiceList;
+ return *instance;
}
size_t ServiceList::CheckAllCommands() {
diff --git a/init/service_utils.cpp b/init/service_utils.cpp
index 9585d05..7004d8d 100644
--- a/init/service_utils.cpp
+++ b/init/service_utils.cpp
@@ -52,7 +52,7 @@
if (fd == -1) {
return ErrnoError() << "Could not open namespace at " << path;
}
- if (setns(fd, nstype) == -1) {
+ if (setns(fd.get(), nstype) == -1) {
return ErrnoError() << "Could not setns() namespace at " << path;
}
return {};
@@ -127,22 +127,22 @@
void SetupStdio(bool stdio_to_kmsg) {
auto fd = unique_fd{open("/dev/null", O_RDWR | O_CLOEXEC)};
- dup2(fd, STDIN_FILENO);
+ dup2(fd.get(), STDIN_FILENO);
if (stdio_to_kmsg) {
fd.reset(open("/dev/kmsg_debug", O_WRONLY | O_CLOEXEC));
if (fd == -1) fd.reset(open("/dev/null", O_WRONLY | O_CLOEXEC));
}
- dup2(fd, STDOUT_FILENO);
- dup2(fd, STDERR_FILENO);
+ dup2(fd.get(), STDOUT_FILENO);
+ dup2(fd.get(), STDERR_FILENO);
}
void OpenConsole(const std::string& console) {
auto fd = unique_fd{open(console.c_str(), O_RDWR | O_CLOEXEC)};
if (fd == -1) fd.reset(open("/dev/null", O_RDWR | O_CLOEXEC));
- ioctl(fd, TIOCSCTTY, 0);
- dup2(fd, 0);
- dup2(fd, 1);
- dup2(fd, 2);
+ ioctl(fd.get(), TIOCSCTTY, 0);
+ dup2(fd.get(), 0);
+ dup2(fd.get(), 1);
+ dup2(fd.get(), 2);
}
} // namespace
@@ -190,7 +190,7 @@
}
// Fixup as we set O_NONBLOCK for open, the intent for fd is to block reads.
- fcntl(fd, F_SETFL, flags);
+ fcntl(fd.get(), F_SETFL, flags);
return Descriptor(ANDROID_FILE_ENV_PREFIX + name, std::move(fd));
}
@@ -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
@@ -242,6 +242,8 @@
if (RequiresConsole(attr)) {
setsid();
+ setsid_finished.Write(kSetSidFinished);
+ setsid_finished.Close();
OpenConsole(attr.console);
} else {
// Without PID namespaces, this call duplicates the setpgid() call from
diff --git a/init/service_utils.h b/init/service_utils.h
index c66f2b4..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)
@@ -94,7 +102,7 @@
return !attr.console.empty();
}
-Result<void> SetProcessAttributes(const ProcessAttributes& attr);
+Result<void> SetProcessAttributes(const ProcessAttributes& attr, InterprocessFifo setsid_finished);
Result<void> WritePidToFiles(std::vector<std::string>* files);
diff --git a/init/subcontext.cpp b/init/subcontext.cpp
index 961e006..6a095fb 100644
--- a/init/subcontext.cpp
+++ b/init/subcontext.cpp
@@ -207,7 +207,7 @@
// We explicitly do not use O_CLOEXEC here, such that we can reference this FD by number
// in the subcontext process after we exec.
- int child_fd = dup(subcontext_socket); // NOLINT(android-cloexec-dup)
+ int child_fd = dup(subcontext_socket.get()); // NOLINT(android-cloexec-dup)
if (child_fd < 0) {
PLOG(FATAL) << "Could not dup child_fd";
}
@@ -268,12 +268,12 @@
}
Result<SubcontextReply> Subcontext::TransmitMessage(const SubcontextCommand& subcontext_command) {
- if (auto result = SendMessage(socket_, subcontext_command); !result.ok()) {
+ if (auto result = SendMessage(socket_.get(), subcontext_command); !result.ok()) {
Restart();
return ErrnoError() << "Failed to send message to subcontext";
}
- auto subcontext_message = ReadMessage(socket_);
+ auto subcontext_message = ReadMessage(socket_.get());
if (!subcontext_message.ok()) {
Restart();
return Error() << "Failed to receive result from subcontext: " << subcontext_message.error();
diff --git a/init/test_upgrade_mte/mte_upgrade_test_helper.cpp b/init/test_upgrade_mte/mte_upgrade_test_helper.cpp
index 10af06b..3188337 100644
--- a/init/test_upgrade_mte/mte_upgrade_test_helper.cpp
+++ b/init/test_upgrade_mte/mte_upgrade_test_helper.cpp
@@ -22,6 +22,7 @@
#include <sys/prctl.h>
#include <time.h>
#include <unistd.h>
+#include <memory>
int MaybeDowngrade() {
int res = prctl(PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0);
@@ -58,7 +59,7 @@
// Disallow automatic upgrade from ASYNC mode.
if (prctl(PR_SET_TAGGED_ADDR_CTRL, res & ~PR_MTE_TCF_SYNC, 0, 0, 0) == -1) abort();
}
- volatile char* f = (char*)malloc(1);
+ std::unique_ptr<volatile char[]> f(new char[1]);
f[17] = 'x';
char buf[1];
read(1, buf, 1);
diff --git a/init/uevent_listener.cpp b/init/uevent_listener.cpp
index 7cd396a..5da6777 100644
--- a/init/uevent_listener.cpp
+++ b/init/uevent_listener.cpp
@@ -92,12 +92,12 @@
LOG(FATAL) << "Could not open uevent socket";
}
- fcntl(device_fd_, F_SETFL, O_NONBLOCK);
+ fcntl(device_fd_.get(), F_SETFL, O_NONBLOCK);
}
ReadUeventResult UeventListener::ReadUevent(Uevent* uevent) const {
char msg[UEVENT_MSG_LEN + 2];
- int n = uevent_kernel_multicast_recv(device_fd_, msg, UEVENT_MSG_LEN);
+ int n = uevent_kernel_multicast_recv(device_fd_.get(), msg, UEVENT_MSG_LEN);
if (n <= 0) {
if (errno != EAGAIN && errno != EWOULDBLOCK) {
PLOG(ERROR) << "Error reading from Uevent Fd";
@@ -184,9 +184,10 @@
const std::optional<std::chrono::milliseconds> relative_timeout) const {
using namespace std::chrono;
- pollfd ufd;
- ufd.events = POLLIN;
- ufd.fd = device_fd_;
+ pollfd ufd = {
+ .events = POLLIN,
+ .fd = device_fd_.get(),
+ };
auto start_time = steady_clock::now();
diff --git a/init/util.cpp b/init/util.cpp
index 3d42855..bc8ea6e 100644
--- a/init/util.cpp
+++ b/init/util.cpp
@@ -120,12 +120,12 @@
if (passcred) {
int on = 1;
- if (setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on))) {
+ if (setsockopt(fd.get(), SOL_SOCKET, SO_PASSCRED, &on, sizeof(on))) {
return ErrnoError() << "Failed to set SO_PASSCRED '" << name << "'";
}
}
- int ret = bind(fd, (struct sockaddr *) &addr, sizeof (addr));
+ int ret = bind(fd.get(), (struct sockaddr*)&addr, sizeof(addr));
int savederrno = errno;
if (!secontext.empty()) {
@@ -145,7 +145,7 @@
if (fchmodat(AT_FDCWD, addr.sun_path, perm, AT_SYMLINK_NOFOLLOW)) {
return ErrnoError() << "Failed to fchmodat socket '" << addr.sun_path << "'";
}
- if (should_listen && listen(fd, /* use OS maximum */ 1 << 30)) {
+ if (should_listen && listen(fd.get(), /* use OS maximum */ 1 << 30)) {
return ErrnoError() << "Failed to listen on socket '" << addr.sun_path << "'";
}
@@ -168,7 +168,7 @@
// For security reasons, disallow world-writable
// or group-writable files.
struct stat sb;
- if (fstat(fd, &sb) == -1) {
+ if (fstat(fd.get(), &sb) == -1) {
return ErrnoError() << "fstat failed()";
}
if ((sb.st_mode & (S_IWGRP | S_IWOTH)) != 0) {
diff --git a/janitors/OWNERS b/janitors/OWNERS
index e132f0b..d871201 100644
--- a/janitors/OWNERS
+++ b/janitors/OWNERS
@@ -1,6 +1,7 @@
# OWNERS file for projects that don't really have owners so much as volunteer janitors.
ccross@google.com
+cferris@google.com
dwillemsen@google.com
enh@google.com
narayan@google.com
-sadafebrahimi@google.com
\ No newline at end of file
+sadafebrahimi@google.com
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/libsystem/include/system/graphics-base-v1.2.h b/libsystem/include/system/graphics-base-v1.2.h
index 2194f5e..624912c 100644
--- a/libsystem/include/system/graphics-base-v1.2.h
+++ b/libsystem/include/system/graphics-base-v1.2.h
@@ -14,13 +14,17 @@
} android_hdr_v1_2_t;
typedef enum {
- HAL_DATASPACE_DISPLAY_BT2020 = 142999552 /* ((STANDARD_BT2020 | TRANSFER_SRGB) | RANGE_FULL) */,
+ HAL_DATASPACE_DISPLAY_BT2020 = 142999552 /* STANDARD_BT2020 | TRANSFER_SRGB | RANGE_FULL */,
HAL_DATASPACE_DYNAMIC_DEPTH = 4098 /* 0x1002 */,
HAL_DATASPACE_JPEG_APP_SEGMENTS = 4099 /* 0x1003 */,
HAL_DATASPACE_HEIF = 4100 /* 0x1004 */,
} android_dataspace_v1_2_t;
typedef enum {
+ HAL_COLOR_MODE_DISPLAY_BT2020 = 13,
+} android_color_mode_v1_2_t;
+
+typedef enum {
HAL_PIXEL_FORMAT_HSV_888 = 55 /* 0x37 */,
} android_pixel_format_v1_2_t;
diff --git a/libutils/Unicode_test.cpp b/libutils/Unicode_test.cpp
index 8b994d9..7969525 100644
--- a/libutils/Unicode_test.cpp
+++ b/libutils/Unicode_test.cpp
@@ -35,86 +35,208 @@
}
char16_t const * const kSearchString = u"I am a leaf on the wind.";
+
+ constexpr static size_t BUFSIZE = 64; // large enough for all tests
+
+ void TestUTF8toUTF16(std::initializer_list<uint8_t> input,
+ std::initializer_list<char16_t> expect,
+ const char* err_msg_length = "",
+ ssize_t expected_length = 0) {
+ uint8_t empty_str[] = {};
+ char16_t output[BUFSIZE];
+
+ const size_t inlen = input.size(), outlen = expect.size();
+ ASSERT_LT(outlen, BUFSIZE);
+
+ const uint8_t *input_data = inlen ? std::data(input) : empty_str;
+ ssize_t measured = utf8_to_utf16_length(input_data, inlen);
+ EXPECT_EQ(expected_length ? : (ssize_t)outlen, measured) << err_msg_length;
+
+ utf8_to_utf16(input_data, inlen, output, outlen + 1);
+ for (size_t i = 0; i < outlen; i++) {
+ EXPECT_EQ(std::data(expect)[i], output[i]);
+ }
+ EXPECT_EQ(0, output[outlen]) << "should be null terminated";
+ }
+
+ void TestUTF16toUTF8(std::initializer_list<char16_t> input,
+ std::initializer_list<char> expect,
+ const char* err_msg_length = "",
+ ssize_t expected_length = 0) {
+ char16_t empty_str[] = {};
+ char output[BUFSIZE];
+
+ const size_t inlen = input.size(), outlen = expect.size();
+ ASSERT_LT(outlen, BUFSIZE);
+
+ const char16_t *input_data = inlen ? std::data(input) : empty_str;
+ ssize_t measured = utf16_to_utf8_length(input_data, inlen);
+ EXPECT_EQ(expected_length ? : (ssize_t)outlen, measured) << err_msg_length;
+
+ utf16_to_utf8(input_data, inlen, output, outlen + 1);
+ for (size_t i = 0; i < outlen; i++) {
+ EXPECT_EQ(std::data(expect)[i], output[i]);
+ }
+ EXPECT_EQ(0, output[outlen]) << "should be null terminated";
+ }
};
TEST_F(UnicodeTest, UTF8toUTF16ZeroLength) {
- ssize_t measured;
-
- const uint8_t str[] = { };
-
- measured = utf8_to_utf16_length(str, 0);
- EXPECT_EQ(0, measured)
- << "Zero length input should return zero length output.";
+ TestUTF8toUTF16({}, {},
+ "Zero length input should return zero length output.");
}
-TEST_F(UnicodeTest, UTF8toUTF16ASCIILength) {
- ssize_t measured;
-
- // U+0030 or ASCII '0'
- const uint8_t str[] = { 0x30 };
-
- measured = utf8_to_utf16_length(str, sizeof(str));
- EXPECT_EQ(1, measured)
- << "ASCII glyphs should have a length of 1 char16_t";
+TEST_F(UnicodeTest, UTF8toUTF16ASCII) {
+ TestUTF8toUTF16(
+ { 0x30 }, // U+0030 or ASCII '0'
+ { 0x0030 },
+ "ASCII codepoints should have a length of 1 char16_t");
}
-TEST_F(UnicodeTest, UTF8toUTF16Plane1Length) {
- ssize_t measured;
-
- // U+2323 SMILE
- const uint8_t str[] = { 0xE2, 0x8C, 0xA3 };
-
- measured = utf8_to_utf16_length(str, sizeof(str));
- EXPECT_EQ(1, measured)
- << "Plane 1 glyphs should have a length of 1 char16_t";
+TEST_F(UnicodeTest, UTF8toUTF16Plane1) {
+ TestUTF8toUTF16(
+ { 0xE2, 0x8C, 0xA3 }, // U+2323 SMILE
+ { 0x2323 },
+ "Plane 1 codepoints should have a length of 1 char16_t");
}
-TEST_F(UnicodeTest, UTF8toUTF16SurrogateLength) {
- ssize_t measured;
-
- // U+10000
- const uint8_t str[] = { 0xF0, 0x90, 0x80, 0x80 };
-
- measured = utf8_to_utf16_length(str, sizeof(str));
- EXPECT_EQ(2, measured)
- << "Surrogate pairs should have a length of 2 char16_t";
+TEST_F(UnicodeTest, UTF8toUTF16Surrogate) {
+ TestUTF8toUTF16(
+ { 0xF0, 0x90, 0x80, 0x80 }, // U+10000
+ { 0xD800, 0xDC00 },
+ "Surrogate pairs should have a length of 2 char16_t");
}
TEST_F(UnicodeTest, UTF8toUTF16TruncatedUTF8) {
- ssize_t measured;
-
- // Truncated U+2323 SMILE
- // U+2323 SMILE
- const uint8_t str[] = { 0xE2, 0x8C };
-
- measured = utf8_to_utf16_length(str, sizeof(str));
- EXPECT_EQ(-1, measured)
- << "Truncated UTF-8 should return -1 to indicate invalid";
+ TestUTF8toUTF16(
+ { 0xE2, 0x8C }, // Truncated U+2323 SMILE
+ { }, // Conversion should still work but produce nothing
+ "Truncated UTF-8 should return -1 to indicate invalid",
+ -1);
}
TEST_F(UnicodeTest, UTF8toUTF16Normal) {
- const uint8_t str[] = {
- 0x30, // U+0030, 1 UTF-16 character
- 0xC4, 0x80, // U+0100, 1 UTF-16 character
- 0xE2, 0x8C, 0xA3, // U+2323, 1 UTF-16 character
+ TestUTF8toUTF16({
+ 0x30, // U+0030, 1 UTF-16 character
+ 0xC4, 0x80, // U+0100, 1 UTF-16 character
+ 0xE2, 0x8C, 0xA3, // U+2323, 1 UTF-16 character
0xF0, 0x90, 0x80, 0x80, // U+10000, 2 UTF-16 character
- };
+ }, {
+ 0x0030,
+ 0x0100,
+ 0x2323,
+ 0xD800, 0xDC00
+ });
+}
- char16_t output[1 + 1 + 1 + 2 + 1]; // Room for null
+TEST_F(UnicodeTest, UTF8toUTF16Invalid) {
+ // TODO: The current behavior of utf8_to_utf16 is to treat invalid
+ // leading byte (>= 0xf8) as a 4-byte UTF8 sequence, and to treat
+ // invalid trailing byte(s) (i.e. bytes not having MSB set) as if
+ // they are valid and do the normal conversion. However, a better
+ // handling would be to treat invalid sequences as errors, such
+ // cases need to be reported and invalid characters (e.g. U+FFFD)
+ // could be produced at the place of error. Until a fix is ready
+ // and compatibility is not an issue, we will keep testing the
+ // current behavior
+ TestUTF8toUTF16({
+ 0xf8, // invalid leading byte
+ 0xc4, 0x00, // U+0100 with invalid trailing byte
+ 0xe2, 0x0c, 0xa3, // U+2323 with invalid trailing bytes
+ 0xf0, 0x10, 0x00, 0x00, // U+10000 with invalid trailing bytes
+ }, {
+ 0x4022, // invalid leading byte (>=0xfc) is treated
+ // as valid for 4-byte UTF8 sequence
+ 0x000C,
+ 0x00A3, // invalid leadnig byte (b'10xxxxxx) is
+ // treated as valid single UTF-8 byte
+ 0xD800, // invalid trailing bytes are treated
+ 0xDC00, // as valid bytes and follow normal
+ });
+}
- utf8_to_utf16(str, sizeof(str), output, sizeof(output) / sizeof(output[0]));
+TEST_F(UnicodeTest, UTF16toUTF8ZeroLength) {
+ // TODO: The current behavior of utf16_to_utf8_length() is that
+ // it returns -1 if the input is a zero length UTF16 string.
+ // This is inconsistent with utf8_to_utf16_length() where a zero
+ // length string returns 0. However, to fix the current behavior,
+ // we could have compatibility issue. Until then, we will keep
+ // testing the current behavior
+ TestUTF16toUTF8({}, {},
+ "Zero length UTF16 input should return length of -1.", -1);
+}
- EXPECT_EQ(0x0030, output[0])
- << "should be U+0030";
- EXPECT_EQ(0x0100, output[1])
- << "should be U+0100";
- EXPECT_EQ(0x2323, output[2])
- << "should be U+2323";
- EXPECT_EQ(0xD800, output[3])
- << "should be first half of surrogate U+10000";
- EXPECT_EQ(0xDC00, output[4])
- << "should be second half of surrogate U+10000";
- EXPECT_EQ(0, output[5]) << "should be null terminated";
+TEST_F(UnicodeTest, UTF16toUTF8ASCII) {
+ TestUTF16toUTF8(
+ { 0x0030 }, // U+0030 or ASCII '0'
+ { '\x30' },
+ "ASCII codepoints in UTF16 should give a length of 1 in UTF8");
+}
+
+TEST_F(UnicodeTest, UTF16toUTF8Plane1) {
+ TestUTF16toUTF8(
+ { 0x2323 }, // U+2323 SMILE
+ { '\xE2', '\x8C', '\xA3' },
+ "Plane 1 codepoints should have a length of 3 char in UTF-8");
+}
+
+TEST_F(UnicodeTest, UTF16toUTF8Surrogate) {
+ TestUTF16toUTF8(
+ { 0xD800, 0xDC00 }, // U+10000
+ { '\xF0', '\x90', '\x80', '\x80' },
+ "Surrogate pairs should have a length of 4 chars");
+}
+
+TEST_F(UnicodeTest, UTF16toUTF8UnpairedSurrogate) {
+ TestUTF16toUTF8(
+ { 0xD800 }, // U+10000 with high surrogate pair only
+ { }, // Unpaired surrogate should be ignored
+ "A single unpaired high surrogate should have a length of 0 chars");
+
+ TestUTF16toUTF8(
+ { 0xDC00 }, // U+10000 with low surrogate pair only
+ { }, // Unpaired surrogate should be ignored
+ "A single unpaired low surrogate should have a length of 0 chars");
+
+ TestUTF16toUTF8(
+ // U+0030, U+0100, U+10000 with high surrogate pair only, U+2323
+ { 0x0030, 0x0100, 0xDC00, 0x2323 },
+ { '\x30', '\xC4', '\x80', '\xE2', '\x8C', '\xA3' },
+ "Unpaired high surrogate should be skipped in the middle");
+
+ TestUTF16toUTF8(
+ // U+0030, U+0100, U+10000 with high surrogate pair only, U+2323
+ { 0x0030, 0x0100, 0xDC00, 0x2323 },
+ { '\x30', '\xC4', '\x80', '\xE2', '\x8C', '\xA3' },
+ "Unpaired low surrogate should be skipped in the middle");
+}
+
+TEST_F(UnicodeTest, UTF16toUTF8CorrectInvalidSurrogate) {
+ // http://b/29250543
+ // d841d8 is an invalid start for a surrogate pair. Make sure this is handled by ignoring the
+ // first character in the pair and handling the rest correctly.
+ TestUTF16toUTF8(
+ { 0xD841, 0xD841, 0xDC41 }, // U+20441
+ { '\xF0', '\xA0', '\x91', '\x81' },
+ "Invalid start for a surrogate pair should be ignored");
+}
+
+TEST_F(UnicodeTest, UTF16toUTF8Normal) {
+ TestUTF16toUTF8({
+ 0x0024, // U+0024 ($) --> 0x24, 1 UTF-8 byte
+ 0x00A3, // U+00A3 (£) --> 0xC2 0xA3, 2 UTF-8 bytes
+ 0x0939, // U+0939 (ह) --> 0xE0 0xA4 0xB9, 3 UTF-8 bytes
+ 0x20AC, // U+20AC (€) --> 0xE2 0x82 0xAC, 3 UTF-8 bytes
+ 0xD55C, // U+D55C (한)--> 0xED 0x95 0x9C, 3 UTF-8 bytes
+ 0xD801, 0xDC37, // U+10437 (𐐷) --> 0xF0 0x90 0x90 0xB7, 4 UTF-8 bytes
+ }, {
+ '\x24',
+ '\xC2', '\xA3',
+ '\xE0', '\xA4', '\xB9',
+ '\xE2', '\x82', '\xAC',
+ '\xED', '\x95', '\x9C',
+ '\xF0', '\x90', '\x90', '\xB7',
+ });
}
TEST_F(UnicodeTest, strstr16EmptyTarget) {
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 3a98fdb..47f77b1 100644
--- a/rootdir/etc/linker.config.json
+++ b/rootdir/etc/linker.config.json
@@ -22,17 +22,16 @@
"libnetd_resolv.so",
// netd
"libnetd_updatable.so",
- // nn
- "libneuralnetworks.so",
// statsd
"libstatspull.so",
"libstatssocket.so",
- // tethering LLNDK
- "libcom.android.tethering.connectivity_native.so",
// adbd
"libadb_pairing_auth.so",
"libadb_pairing_connection.so",
"libadb_pairing_server.so"
+
+ // LLNDK libraries in APEXes will be added automatically from the build,
+ // using build variable LLNDK_MOVED_TO_APEX_LIBRARIES.
],
"provideLibs": [
"libaptX_encoder.so",
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 3700f00..d8e6b55 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
@@ -1118,6 +1114,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
@@ -1321,7 +1318,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/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/TrustyKeyMintDevice.cpp b/trusty/keymaster/keymint/TrustyKeyMintDevice.cpp
index 7d58162..b696ff9 100644
--- a/trusty/keymaster/keymint/TrustyKeyMintDevice.cpp
+++ b/trusty/keymaster/keymint/TrustyKeyMintDevice.cpp
@@ -91,7 +91,7 @@
} // namespace
ScopedAStatus TrustyKeyMintDevice::getHardwareInfo(KeyMintHardwareInfo* info) {
- info->versionNumber = 2;
+ info->versionNumber = 3;
info->securityLevel = kSecurityLevel;
info->keyMintName = "TrustyKeyMintDevice";
info->keyMintAuthorName = "Google";
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/keymaster/keymint/service.cpp b/trusty/keymaster/keymint/service.cpp
index 3447b27..14549d2 100644
--- a/trusty/keymaster/keymint/service.cpp
+++ b/trusty/keymaster/keymint/service.cpp
@@ -41,7 +41,7 @@
int main() {
auto trustyKeymaster = std::make_shared<keymaster::TrustyKeymaster>();
- int err = trustyKeymaster->Initialize(keymaster::KmVersion::KEYMINT_2);
+ int err = trustyKeymaster->Initialize(keymaster::KmVersion::KEYMINT_3);
if (err != 0) {
LOG(FATAL) << "Could not initialize TrustyKeymaster for KeyMint (" << err << ")";
return -1;
diff --git a/trusty/keymint/Android.bp b/trusty/keymint/Android.bp
new file mode 100644
index 0000000..54aadaa
--- /dev/null
+++ b/trusty/keymint/Android.bp
@@ -0,0 +1,37 @@
+//
+// Copyright (C) 2022 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.
+
+rust_binary {
+ name: "android.hardware.security.keymint-service.rust.trusty",
+ relative_install_path: "hw",
+ vendor: true,
+ init_rc: ["android.hardware.security.keymint-service.rust.trusty.rc"],
+ vintf_fragments: ["android.hardware.security.keymint-service.rust.trusty.xml"],
+ srcs: [
+ "src/keymint_hal_main.rs"
+ ],
+ rustlibs: [
+ "libandroid_logger",
+ "libbinder_rs",
+ "libkmr_wire",
+ "libkmr_hal",
+ "libtrusty-rs",
+ "liblibc",
+ "liblog_rust",
+ ],
+ required: [
+ "android.hardware.hardware_keystore.xml",
+ ],
+}
diff --git a/trusty/keymint/android.hardware.hardware_keystore.rust.trusty-keymint.xml b/trusty/keymint/android.hardware.hardware_keystore.rust.trusty-keymint.xml
new file mode 100644
index 0000000..cd656b2
--- /dev/null
+++ b/trusty/keymint/android.hardware.hardware_keystore.rust.trusty-keymint.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2021 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.
+-->
+<permissions>
+ <feature name="android.hardware.hardware_keystore" version="300" />
+</permissions>
diff --git a/trusty/keymint/android.hardware.security.keymint-service.rust.trusty.rc b/trusty/keymint/android.hardware.security.keymint-service.rust.trusty.rc
new file mode 100644
index 0000000..e3d94c6
--- /dev/null
+++ b/trusty/keymint/android.hardware.security.keymint-service.rust.trusty.rc
@@ -0,0 +1,7 @@
+service vendor.keymint.rust-trusty /vendor/bin/hw/android.hardware.security.keymint-service.rust.trusty
+ class early_hal
+ user nobody
+ group drmrpc
+ # The keymint service is not allowed to restart.
+ # If it crashes, a device restart is required.
+ oneshot
\ No newline at end of file
diff --git a/trusty/keymint/android.hardware.security.keymint-service.rust.trusty.xml b/trusty/keymint/android.hardware.security.keymint-service.rust.trusty.xml
new file mode 100644
index 0000000..3dc9c88
--- /dev/null
+++ b/trusty/keymint/android.hardware.security.keymint-service.rust.trusty.xml
@@ -0,0 +1,20 @@
+<manifest version="1.0" type="device">
+ <hal format="aidl">
+ <name>android.hardware.security.keymint</name>
+ <version>3</version>
+ <fqname>IKeyMintDevice/default</fqname>
+ </hal>
+ <hal format="aidl">
+ <name>android.hardware.security.secureclock</name>
+ <fqname>ISecureClock/default</fqname>
+ </hal>
+ <hal format="aidl">
+ <name>android.hardware.security.sharedsecret</name>
+ <fqname>ISharedSecret/default</fqname>
+ </hal>
+ <hal format="aidl">
+ <name>android.hardware.security.keymint</name>
+ <version>3</version>
+ <fqname>IRemotelyProvisionedComponent/default</fqname>
+ </hal>
+</manifest>
diff --git a/trusty/keymint/src/keymint_hal_main.rs b/trusty/keymint/src/keymint_hal_main.rs
new file mode 100644
index 0000000..d2d5f27
--- /dev/null
+++ b/trusty/keymint/src/keymint_hal_main.rs
@@ -0,0 +1,155 @@
+//
+// Copyright (C) 2022 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.
+
+//! This module implements the HAL service for Keymint (Rust) in Trusty.
+use kmr_hal::{keymint, rpc, secureclock, send_hal_info, sharedsecret, SerializedChannel};
+use log::{error, info};
+use std::{
+ ffi::CString,
+ ops::DerefMut,
+ panic,
+ sync::{Arc, Mutex},
+};
+use trusty::DEFAULT_DEVICE;
+
+const TRUSTY_KEYMINT_RUST_SERVICE_NAME: &str = "com.android.trusty.keymint";
+
+static SERVICE_INSTANCE: &str = "default";
+
+static KM_SERVICE_NAME: &str = "android.hardware.security.keymint.IKeyMintDevice";
+static RPC_SERVICE_NAME: &str = "android.hardware.security.keymint.IRemotelyProvisionedComponent";
+static SECURE_CLOCK_SERVICE_NAME: &str = "android.hardware.security.secureclock.ISecureClock";
+static SHARED_SECRET_SERVICE_NAME: &str = "android.hardware.security.sharedsecret.ISharedSecret";
+
+/// Local error type for failures in the HAL service.
+#[derive(Debug, Clone)]
+struct HalServiceError(String);
+
+#[derive(Debug)]
+struct TipcChannel(trusty::TipcChannel);
+
+impl SerializedChannel for TipcChannel {
+ fn execute(&mut self, serialized_req: &[u8]) -> binder::Result<Vec<u8>> {
+ self.0.send(serialized_req).map_err(|e| {
+ binder::Status::new_exception(
+ binder::ExceptionCode::TRANSACTION_FAILED,
+ Some(
+ &CString::new(format!(
+ "Failed to send the request via tipc channel because of {:?}",
+ e
+ ))
+ .unwrap(),
+ ),
+ )
+ })?;
+ let mut recv_buf = Vec::new();
+ // TODO(b/253501976): cope with fragmentation of responses
+ self.0.recv(&mut recv_buf).map_err(|e| {
+ binder::Status::new_exception(
+ binder::ExceptionCode::TRANSACTION_FAILED,
+ Some(
+ &CString::new(format!(
+ "Failed to receive the response via tipc channel because of {:?}",
+ e
+ ))
+ .unwrap(),
+ ),
+ )
+ })?;
+ Ok(recv_buf)
+ }
+}
+
+fn main() {
+ if let Err(e) = inner_main() {
+ panic!("HAL service failed: {:?}", e);
+ }
+}
+
+fn inner_main() -> Result<(), HalServiceError> {
+ // Initialize Android logging.
+ android_logger::init_once(
+ android_logger::Config::default()
+ .with_tag("keymint-hal-trusty")
+ .with_min_level(log::Level::Info)
+ .with_log_id(android_logger::LogId::System),
+ );
+ // Redirect panic messages to logcat.
+ panic::set_hook(Box::new(|panic_info| {
+ error!("{}", panic_info);
+ }));
+
+ info!("Trusty KM HAL service is starting.");
+
+ info!("Starting thread pool now.");
+ binder::ProcessState::start_thread_pool();
+
+ // Create connection to the TA
+ let connection = trusty::TipcChannel::connect(DEFAULT_DEVICE, TRUSTY_KEYMINT_RUST_SERVICE_NAME)
+ .map_err(|e| {
+ HalServiceError(format!("Failed to connect to Trusty Keymint TA because of {:?}.", e))
+ })?;
+ let tipc_channel = Arc::new(Mutex::new(TipcChannel(connection)));
+
+ // Register the Keymint service
+ let km_service = keymint::Device::new_as_binder(tipc_channel.clone());
+ let km_service_name = format!("{}/{}", KM_SERVICE_NAME, SERVICE_INSTANCE);
+ binder::add_service(&km_service_name, km_service.as_binder()).map_err(|e| {
+ HalServiceError(format!(
+ "Failed to register service {} because of {:?}.",
+ km_service_name, e
+ ))
+ })?;
+
+ // Register the Remotely Provisioned Component service
+ let rpc_service = rpc::Device::new_as_binder(tipc_channel.clone());
+ let rpc_service_name = format!("{}/{}", RPC_SERVICE_NAME, SERVICE_INSTANCE);
+ binder::add_service(&rpc_service_name, rpc_service.as_binder()).map_err(|e| {
+ HalServiceError(format!(
+ "Failed to register service {} because of {:?}.",
+ rpc_service_name, e
+ ))
+ })?;
+
+ // Register the Secure Clock service
+ let sclock_service = secureclock::Device::new_as_binder(tipc_channel.clone());
+ let sclock_service_name = format!("{}/{}", SECURE_CLOCK_SERVICE_NAME, SERVICE_INSTANCE);
+ binder::add_service(&sclock_service_name, sclock_service.as_binder()).map_err(|e| {
+ HalServiceError(format!(
+ "Failed to register service {} because of {:?}.",
+ sclock_service_name, e
+ ))
+ })?;
+
+ // Register the Shared Secret service
+ let ssecret_service = sharedsecret::Device::new_as_binder(tipc_channel.clone());
+ let ssecret_service_name = format!("{}/{}", SHARED_SECRET_SERVICE_NAME, SERVICE_INSTANCE);
+ binder::add_service(&ssecret_service_name, ssecret_service.as_binder()).map_err(|e| {
+ HalServiceError(format!(
+ "Failed to register service {} because of {:?}.",
+ ssecret_service_name, e
+ ))
+ })?;
+
+ // Send the HAL service information to the TA
+ send_hal_info(tipc_channel.lock().unwrap().deref_mut())
+ .map_err(|e| HalServiceError(format!("Failed to populate HAL info: {:?}", e)))?;
+
+ info!("Successfully registered KeyMint HAL services.");
+ info!("Joining thread pool now.");
+ binder::ProcessState::join_thread_pool();
+ info!("KeyMint HAL service is terminating."); // should not reach here
+ 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:
diff --git a/trusty/test/binder/aidl/ByteEnum.aidl b/trusty/test/binder/aidl/com/android/trusty/binder/test/ByteEnum.aidl
similarity index 94%
rename from trusty/test/binder/aidl/ByteEnum.aidl
rename to trusty/test/binder/aidl/com/android/trusty/binder/test/ByteEnum.aidl
index d3a13ac..9c712c0 100644
--- a/trusty/test/binder/aidl/ByteEnum.aidl
+++ b/trusty/test/binder/aidl/com/android/trusty/binder/test/ByteEnum.aidl
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+package com.android.trusty.binder.test;
+
/*
* Hello, world!
*/
diff --git a/trusty/test/binder/aidl/ITestService.aidl b/trusty/test/binder/aidl/com/android/trusty/binder/test/ITestService.aidl
similarity index 93%
rename from trusty/test/binder/aidl/ITestService.aidl
rename to trusty/test/binder/aidl/com/android/trusty/binder/test/ITestService.aidl
index c6a99c8..cfbb246 100644
--- a/trusty/test/binder/aidl/ITestService.aidl
+++ b/trusty/test/binder/aidl/com/android/trusty/binder/test/ITestService.aidl
@@ -14,10 +14,11 @@
* limitations under the License.
*/
+package com.android.trusty.binder.test;
-import ByteEnum;
-import IntEnum;
-import LongEnum;
+import com.android.trusty.binder.test.ByteEnum;
+import com.android.trusty.binder.test.IntEnum;
+import com.android.trusty.binder.test.LongEnum;
interface ITestService {
const @utf8InCpp String PORT = "com.android.trusty.binder.test.service";
diff --git a/trusty/test/binder/aidl/IntEnum.aidl b/trusty/test/binder/aidl/com/android/trusty/binder/test/IntEnum.aidl
similarity index 94%
rename from trusty/test/binder/aidl/IntEnum.aidl
rename to trusty/test/binder/aidl/com/android/trusty/binder/test/IntEnum.aidl
index 120e44f..4055b25 100644
--- a/trusty/test/binder/aidl/IntEnum.aidl
+++ b/trusty/test/binder/aidl/com/android/trusty/binder/test/IntEnum.aidl
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+package com.android.trusty.binder.test;
+
@JavaDerive(toString=true)
@Backing(type="int")
enum IntEnum {
diff --git a/trusty/test/binder/aidl/LongEnum.aidl b/trusty/test/binder/aidl/com/android/trusty/binder/test/LongEnum.aidl
similarity index 94%
rename from trusty/test/binder/aidl/LongEnum.aidl
rename to trusty/test/binder/aidl/com/android/trusty/binder/test/LongEnum.aidl
index 0e9e933..20c64af 100644
--- a/trusty/test/binder/aidl/LongEnum.aidl
+++ b/trusty/test/binder/aidl/com/android/trusty/binder/test/LongEnum.aidl
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+package com.android.trusty.binder.test;
+
@Backing(type="long")
enum LongEnum {
FOO = 100000000000,
diff --git a/trusty/test/binder/aidl/rules.mk b/trusty/test/binder/aidl/rules.mk
index 6154abb..546a370 100644
--- a/trusty/test/binder/aidl/rules.mk
+++ b/trusty/test/binder/aidl/rules.mk
@@ -17,10 +17,12 @@
MODULE := $(LOCAL_DIR)
+MODULE_AIDL_PACKAGE := com/android/trusty/binder/test
+
MODULE_AIDLS := \
- $(LOCAL_DIR)/ByteEnum.aidl \
- $(LOCAL_DIR)/IntEnum.aidl \
- $(LOCAL_DIR)/ITestService.aidl \
- $(LOCAL_DIR)/LongEnum.aidl \
+ $(LOCAL_DIR)/$(MODULE_AIDL_PACKAGE)/ByteEnum.aidl \
+ $(LOCAL_DIR)/$(MODULE_AIDL_PACKAGE)/IntEnum.aidl \
+ $(LOCAL_DIR)/$(MODULE_AIDL_PACKAGE)/ITestService.aidl \
+ $(LOCAL_DIR)/$(MODULE_AIDL_PACKAGE)/LongEnum.aidl \
include make/aidl.mk