Mark tm-qpr-dev-plus-aosp-without-vendor@9129937 as merged
Ignore-AOSP-First: empty marker merge
Change-Id: I9d8ad4253682dae129aaf8fa42ac3f8971ad4ae1
diff --git a/bootstat/boot_reason_test.sh b/bootstat/boot_reason_test.sh
index 299b5d4..845b303 100755
--- a/bootstat/boot_reason_test.sh
+++ b/bootstat/boot_reason_test.sh
@@ -367,8 +367,6 @@
adb logcat -b all ${timestamp} |
grep bootstat[^e] |
grep -v -F "bootstat: Service started: /system/bin/bootstat --record_boot_complete${match}
-bootstat: Failed to read /data/misc/bootstat/post_decrypt_time_elapsed: No such file or directory
-bootstat: Failed to parse boot time record: /data/misc/bootstat/post_decrypt_time_elapsed
bootstat: Service started: /system/bin/bootstat --record_boot_reason
bootstat: Service started: /system/bin/bootstat --set_system_boot_reason
bootstat: Service started: /system/bin/bootstat --record_time_since_factory_reset
@@ -388,7 +386,6 @@
init : processing action (sys.boot_completed=1 && sys.bootstat.first_boot_completed=0) from (/system/etc/init/bootstat.rc
(/system/bin/bootstat --record_boot_complete --record_boot_reason --record_time_since_factory_reset -l)'
(/system/bin/bootstat --set_system_boot_reason --record_boot_complete --record_boot_reason --record_time_since_factory_reset -l)'
- (/system/bin/bootstat -r post_decrypt_time_elapsed)'
init : Command 'exec - system log -- /system/bin/bootstat --record_boot_complete' action=sys.boot_completed=1 && sys.bootstat.first_boot_completed=0 (/system/etc/init/bootstat.rc:
init : Command 'exec - system log -- /system/bin/bootstat --record_boot_reason' action=sys.boot_completed=1 && sys.bootstat.first_boot_completed=0 (/system/etc/init/bootstat.rc:
init : Command 'exec - system log -- /system/bin/bootstat --record_time_since_factory_reset' action=sys.boot_completed=1 && sys.bootstat.first_boot_completed=0 (/system/etc/init/bootstat.rc:
diff --git a/bootstat/bootstat.cpp b/bootstat/bootstat.cpp
index 589b99a..844357c 100644
--- a/bootstat/bootstat.cpp
+++ b/bootstat/bootstat.cpp
@@ -67,15 +67,9 @@
{"boot_complete",
{android::util::BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED,
android::util::BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__BOOT_COMPLETE}},
- {"boot_decryption_complete",
- {android::util::BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED,
- android::util::BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__BOOT_COMPLETE_ENCRYPTION}},
{"boot_complete_no_encryption",
{android::util::BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED,
android::util::BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__BOOT_COMPLETE_NO_ENCRYPTION}},
- {"boot_complete_post_decrypt",
- {android::util::BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED,
- android::util::BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__BOOT_COMPLETE_POST_DECRYPT}},
{"factory_reset_boot_complete",
{android::util::BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED,
android::util::BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__FACTORY_RESET_BOOT_COMPLETE}},
@@ -83,22 +77,12 @@
{android::util::BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED,
android::util::
BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__FACTORY_RESET_BOOT_COMPLETE_NO_ENCRYPTION}},
- {"factory_reset_boot_complete_post_decrypt",
- {android::util::BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED,
- android::util::
- BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__FACTORY_RESET_BOOT_COMPLETE_POST_DECRYPT}},
{"ota_boot_complete",
{android::util::BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED,
android::util::BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__OTA_BOOT_COMPLETE}},
{"ota_boot_complete_no_encryption",
{android::util::BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED,
android::util::BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__OTA_BOOT_COMPLETE_NO_ENCRYPTION}},
- {"ota_boot_complete_post_decrypt",
- {android::util::BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED,
- android::util::BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__OTA_BOOT_COMPLETE_POST_DECRYPT}},
- {"post_decrypt_time_elapsed",
- {android::util::BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED,
- android::util::BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__POST_DECRYPT}},
// DURATION
{"absolute_boot_time",
{android::util::BOOT_TIME_EVENT_DURATION_REPORTED,
@@ -1313,8 +1297,7 @@
return android::base::boot_clock::now().time_since_epoch() - GetBootTimeOffset();
}
-// Records several metrics related to the time it takes to boot the device,
-// including disambiguating boot time on encrypted or non-encrypted devices.
+// Records several metrics related to the time it takes to boot the device.
void RecordBootComplete() {
BootEventRecordStore boot_event_store;
BootEventRecordStore::BootEventRecord record;
@@ -1341,25 +1324,15 @@
return;
}
- // post_decrypt_time_elapsed is only logged on encrypted devices.
- if (boot_event_store.GetBootEvent("post_decrypt_time_elapsed", &record)) {
- // Log the amount of time elapsed until the device is decrypted, which
- // includes the variable amount of time the user takes to enter the
- // decryption password.
- boot_event_store.AddBootEventWithValue("boot_decryption_complete", uptime_s.count());
+ // The *_no_encryption events are emitted unconditionally, since they are left
+ // over from a time when encryption meant "full-disk encryption". But Android
+ // now always uses file-based encryption instead of full-disk encryption. At
+ // some point, these misleading and redundant events should be removed.
+ boot_event_store.AddBootEventWithValue(boot_complete_prefix + "_no_encryption",
+ uptime_s.count());
- // Subtract the decryption time to normalize the boot cycle timing.
- std::chrono::seconds boot_complete = std::chrono::seconds(uptime_s.count() - record.second);
- boot_event_store.AddBootEventWithValue(boot_complete_prefix + "_post_decrypt",
- boot_complete.count());
- } else {
- boot_event_store.AddBootEventWithValue(boot_complete_prefix + "_no_encryption",
- uptime_s.count());
- }
-
- // Record the total time from device startup to boot complete, regardless of
- // encryption state.
- // Note: we are recording seconds here even though the field in statsd atom specifies
+ // Record the total time from device startup to boot complete. Note: we are
+ // recording seconds here even though the field in statsd atom specifies
// milliseconds.
boot_event_store.AddBootEventWithValue(boot_complete_prefix, uptime_s.count());
diff --git a/bootstat/bootstat.rc b/bootstat/bootstat.rc
index a350fe7..23f01d1 100644
--- a/bootstat/bootstat.rc
+++ b/bootstat/bootstat.rc
@@ -33,7 +33,6 @@
chown system log /data/misc/bootstat/last_boot_time_utc
chown system log /data/misc/bootstat/ota_boot_complete
chown system log /data/misc/bootstat/ota_boot_complete_no_encryption
- chown system log /data/misc/bootstat/post_decrypt_time_elapsed
chown system log /data/misc/bootstat/ro.boottime.init
chown system log /data/misc/bootstat/ro.boottime.init.cold_boot_wait
chown system log /data/misc/bootstat/ro.boottime.init.selinux
diff --git a/debuggerd/handler/debuggerd_handler.cpp b/debuggerd/handler/debuggerd_handler.cpp
index 55770f1..c64de0e 100644
--- a/debuggerd/handler/debuggerd_handler.cpp
+++ b/debuggerd/handler/debuggerd_handler.cpp
@@ -103,9 +103,15 @@
static bool is_permissive_mte() {
// Environment variable for testing or local use from shell.
char* permissive_env = getenv("MTE_PERMISSIVE");
+ char process_sysprop_name[512];
+ async_safe_format_buffer(process_sysprop_name, sizeof(process_sysprop_name),
+ "persist.device_config.memory_safety_native.permissive.process.%s",
+ getprogname());
// DO NOT REPLACE this with GetBoolProperty. That uses std::string which allocates, so it is
// not async-safe (and this functiong gets used in a signal handler).
return property_parse_bool("persist.sys.mte.permissive") ||
+ property_parse_bool("persist.device_config.memory_safety_native.permissive.default") ||
+ property_parse_bool(process_sysprop_name) ||
(permissive_env && ParseBool(permissive_env) == ParseBoolResult::kTrue);
}
diff --git a/fastboot/device/commands.cpp b/fastboot/device/commands.cpp
index 823783e..3799d1f 100644
--- a/fastboot/device/commands.cpp
+++ b/fastboot/device/commands.cpp
@@ -40,6 +40,8 @@
#include <storage_literals/storage_literals.h>
#include <uuid/uuid.h>
+#include <bootloader_message/bootloader_message.h>
+
#include "BootControlClient.h"
#include "constants.h"
#include "fastboot_device.h"
@@ -154,6 +156,14 @@
return true;
}
+static void PostWipeData() {
+ std::string err;
+ // Reset mte state of device.
+ if (!WriteMiscMemtagMessage({}, &err)) {
+ LOG(ERROR) << "Failed to reset MTE state: " << err;
+ }
+}
+
const std::unordered_map<std::string, std::function<bool(FastbootDevice*)>> kSpecialVars = {
{"all", GetVarAll},
{"dmesg", GetDmesg},
@@ -232,6 +242,7 @@
//Perform oem PostWipeData if Android userdata partition has been erased
bool support_oem_postwipedata = false;
if (partition_name == "userdata") {
+ PostWipeData();
support_oem_postwipedata = OemPostWipeData(device);
}
@@ -610,6 +621,10 @@
if (ret < 0) {
return device->WriteStatus(FastbootResult::FAIL, strerror(-ret));
}
+ if (partition_name == "userdata") {
+ PostWipeData();
+ }
+
return device->WriteStatus(FastbootResult::OKAY, "Flashing succeeded");
}
diff --git a/fs_mgr/Android.bp b/fs_mgr/Android.bp
index 49761ac..45cd3c0 100644
--- a/fs_mgr/Android.bp
+++ b/fs_mgr/Android.bp
@@ -254,3 +254,39 @@
"clean_scratch_files",
],
}
+
+cc_binary {
+ name: "set-verity-state",
+ srcs: ["set-verity-state.cpp"],
+ shared_libs: [
+ "libbase",
+ "libbinder",
+ "libcrypto",
+ "libcrypto_utils",
+ "libfs_mgr_binder",
+ "libutils",
+ ],
+ static_libs: [
+ "libavb_user",
+ ],
+ header_libs: [
+ "libcutils_headers",
+ ],
+
+ cflags: ["-Werror"],
+ cppflags: [
+ "-DALLOW_DISABLE_VERITY=0",
+ ],
+ product_variables: {
+ debuggable: {
+ cppflags: [
+ "-UALLOW_DISABLE_VERITY",
+ "-DALLOW_DISABLE_VERITY=1",
+ ],
+ },
+ },
+ symlinks: [
+ "enable-verity",
+ "disable-verity",
+ ],
+}
diff --git a/fs_mgr/OWNERS b/fs_mgr/OWNERS
index c6f9054..6f1059b 100644
--- a/fs_mgr/OWNERS
+++ b/fs_mgr/OWNERS
@@ -2,3 +2,4 @@
bowgotsai@google.com
dvander@google.com
elsk@google.com
+yochiang@google.com
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index 9fe8e18..27137a2 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -22,6 +22,7 @@
#include <fcntl.h>
#include <inttypes.h>
#include <libgen.h>
+#include <selinux/selinux.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -30,6 +31,7 @@
#include <sys/stat.h>
#include <sys/swap.h>
#include <sys/types.h>
+#include <sys/utsname.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>
@@ -2359,3 +2361,49 @@
return true;
}
+
+bool fs_mgr_filesystem_available(const std::string& filesystem) {
+ std::string filesystems;
+ if (!android::base::ReadFileToString("/proc/filesystems", &filesystems)) return false;
+ return filesystems.find("\t" + filesystem + "\n") != std::string::npos;
+}
+
+std::string fs_mgr_get_context(const std::string& mount_point) {
+ char* ctx = nullptr;
+ if (getfilecon(mount_point.c_str(), &ctx) == -1) {
+ PERROR << "getfilecon " << mount_point;
+ return "";
+ }
+
+ std::string context(ctx);
+ free(ctx);
+ return context;
+}
+
+OverlayfsValidResult fs_mgr_overlayfs_valid() {
+ // Overlayfs available in the kernel, and patched for override_creds?
+ if (access("/sys/module/overlay/parameters/override_creds", F_OK) == 0) {
+ return OverlayfsValidResult::kOverrideCredsRequired;
+ }
+ if (!fs_mgr_filesystem_available("overlay")) {
+ return OverlayfsValidResult::kNotSupported;
+ }
+ struct utsname uts;
+ if (uname(&uts) == -1) {
+ return OverlayfsValidResult::kNotSupported;
+ }
+ int major, minor;
+ if (sscanf(uts.release, "%d.%d", &major, &minor) != 2) {
+ return OverlayfsValidResult::kNotSupported;
+ }
+ if (major < 4) {
+ return OverlayfsValidResult::kOk;
+ }
+ if (major > 4) {
+ return OverlayfsValidResult::kNotSupported;
+ }
+ if (minor > 3) {
+ return OverlayfsValidResult::kNotSupported;
+ }
+ return OverlayfsValidResult::kOk;
+}
diff --git a/fs_mgr/fs_mgr_overlayfs.cpp b/fs_mgr/fs_mgr_overlayfs.cpp
index 1d5a04b..cc09d09 100644
--- a/fs_mgr/fs_mgr_overlayfs.cpp
+++ b/fs_mgr/fs_mgr_overlayfs.cpp
@@ -56,6 +56,7 @@
#include <storage_literals/storage_literals.h>
#include "fs_mgr_priv.h"
+#include "fs_mgr_priv_overlayfs.h"
#include "libfiemap/utility.h"
using namespace std::literals;
@@ -71,62 +72,9 @@
return access(path.c_str(), F_OK) == 0;
}
-// determine if a filesystem is available
-bool fs_mgr_overlayfs_filesystem_available(const std::string& filesystem) {
- std::string filesystems;
- if (!android::base::ReadFileToString("/proc/filesystems", &filesystems)) return false;
- return filesystems.find("\t" + filesystem + "\n") != std::string::npos;
-}
-
const auto kLowerdirOption = "lowerdir="s;
const auto kUpperdirOption = "upperdir="s;
-} // namespace
-
-#if ALLOW_ADBD_DISABLE_VERITY == 0 // If we are a user build, provide stubs
-
-bool fs_mgr_wants_overlayfs(FstabEntry*) {
- return false;
-}
-
-Fstab fs_mgr_overlayfs_candidate_list(const Fstab&) {
- return {};
-}
-
-bool fs_mgr_overlayfs_mount_all(Fstab*) {
- return false;
-}
-
-bool fs_mgr_overlayfs_setup(const char*, bool*, bool) {
- LOG(ERROR) << "Overlayfs remounts can only be used in debuggable builds";
- return false;
-}
-
-OverlayfsTeardownResult fs_mgr_overlayfs_teardown(const char*, bool*) {
- return OverlayfsTeardownResult::Ok;
-}
-
-bool fs_mgr_overlayfs_is_setup() {
- return false;
-}
-
-namespace android {
-namespace fs_mgr {
-
-void MapScratchPartitionIfNeeded(Fstab*, const std::function<bool(const std::set<std::string>&)>&) {
-}
-
-void CleanupOldScratchFiles() {}
-
-void TeardownAllOverlayForMountPoint(const std::string&) {}
-
-} // namespace fs_mgr
-} // namespace android
-
-#else // ALLOW_ADBD_DISABLE_VERITY == 0
-
-namespace {
-
bool fs_mgr_in_recovery() {
// Check the existence of recovery binary instead of using the compile time
// __ANDROID_RECOVERY__ macro.
@@ -234,6 +182,28 @@
return true;
}
+bool fs_mgr_has_shared_blocks(const std::string& mount_point, const std::string& dev) {
+ struct statfs fs;
+ if ((statfs((mount_point + "/lost+found").c_str(), &fs) == -1) ||
+ (fs.f_type != EXT4_SUPER_MAGIC)) {
+ return false;
+ }
+
+ android::base::unique_fd fd(open(dev.c_str(), O_RDONLY | O_CLOEXEC));
+ if (fd < 0) return false;
+
+ struct ext4_super_block sb;
+ if ((TEMP_FAILURE_RETRY(lseek64(fd, 1024, SEEK_SET)) < 0) ||
+ (TEMP_FAILURE_RETRY(read(fd, &sb, sizeof(sb))) < 0)) {
+ return false;
+ }
+
+ struct fs_info info;
+ if (ext4_parse_sb(&sb, &info) < 0) return false;
+
+ return (info.feat_ro_compat & EXT4_FEATURE_RO_COMPAT_SHARED_BLOCKS) != 0;
+}
+
bool fs_mgr_overlayfs_enabled(FstabEntry* entry) {
// readonly filesystem, can not be mount -o remount,rw
// for squashfs, erofs or if free space is (near) zero making such a remount
@@ -815,8 +785,7 @@
}
// Mount kScratchMountPoint
-bool fs_mgr_overlayfs_mount_scratch(const std::string& device_path, const std::string mnt_type,
- bool readonly = false) {
+bool MountScratch(const std::string& device_path, bool readonly = false) {
if (readonly) {
if (!fs_mgr_access(device_path)) {
LOG(ERROR) << "Path does not exist: " << device_path;
@@ -827,9 +796,12 @@
return false;
}
- auto f2fs = fs_mgr_is_f2fs(device_path);
- auto ext4 = fs_mgr_is_ext4(device_path);
- if (!f2fs && !ext4) {
+ std::vector<const char*> filesystem_candidates;
+ if (fs_mgr_is_f2fs(device_path)) {
+ filesystem_candidates = {"f2fs", "ext4"};
+ } else if (fs_mgr_is_ext4(device_path)) {
+ filesystem_candidates = {"ext4", "f2fs"};
+ } else {
LOG(ERROR) << "Scratch partition is not f2fs or ext4";
return false;
}
@@ -846,11 +818,7 @@
FstabEntry entry;
entry.blk_device = device_path;
entry.mount_point = kScratchMountPoint;
- entry.fs_type = mnt_type;
- if ((mnt_type == "f2fs") && !f2fs) entry.fs_type = "ext4";
- if ((mnt_type == "ext4") && !ext4) entry.fs_type = "f2fs";
entry.flags = MS_NOATIME | MS_RDONLY;
- auto mounted = true;
if (!readonly) {
entry.flags &= ~MS_RDONLY;
entry.flags |= MS_SYNCHRONOUS;
@@ -861,14 +829,12 @@
if (fs_mgr_overlayfs_already_mounted("/data", false)) {
entry.fs_mgr_flags.check = true;
}
- if (mounted) mounted = fs_mgr_do_mount_one(entry) == 0;
- if (!mounted) {
- if ((entry.fs_type == "f2fs") && ext4) {
- entry.fs_type = "ext4";
- mounted = fs_mgr_do_mount_one(entry) == 0;
- } else if ((entry.fs_type == "ext4") && f2fs) {
- entry.fs_type = "f2fs";
- mounted = fs_mgr_do_mount_one(entry) == 0;
+ bool mounted = false;
+ for (auto fs_type : filesystem_candidates) {
+ entry.fs_type = fs_type;
+ if (fs_mgr_do_mount_one(entry) == 0) {
+ mounted = true;
+ break;
}
}
if (!createcon.Restore()) {
@@ -884,39 +850,6 @@
const std::string kMkF2fs("/system/bin/make_f2fs");
const std::string kMkExt4("/system/bin/mke2fs");
-// Only a suggestion for _first_ try during mounting
-std::string fs_mgr_overlayfs_scratch_mount_type() {
- if (!access(kMkF2fs.c_str(), X_OK) && fs_mgr_overlayfs_filesystem_available("f2fs")) {
- return "f2fs";
- }
- if (!access(kMkExt4.c_str(), X_OK) && fs_mgr_overlayfs_filesystem_available("ext4")) {
- return "ext4";
- }
- return "auto";
-}
-
-// Note: we do not check access() here except for the super partition, since
-// in first-stage init we wouldn't have registed by-name symlinks for "other"
-// partitions that won't be mounted.
-static std::string GetPhysicalScratchDevice() {
- auto slot_number = fs_mgr_overlayfs_slot_number();
- auto super_device = fs_mgr_overlayfs_super_device(slot_number);
- auto path = fs_mgr_overlayfs_super_device(slot_number == 0);
- if (super_device != path) {
- return path;
- }
- if (fs_mgr_access(super_device)) {
- // Do not try to use system_other on a DAP device.
- return "";
- }
-
- auto other_slot = fs_mgr_get_other_slot_suffix();
- if (!other_slot.empty()) {
- return kPhysicalDevice + "system" + other_slot;
- }
- return "";
-}
-
// Note: The scratch partition of DSU is managed by gsid, and should be initialized during
// first-stage-mount. Just check if the DM device for DSU scratch partition is created or not.
static std::string GetDsuScratchDevice() {
@@ -953,27 +886,30 @@
return device;
}
- // There is no dynamic scratch, so try and find a physical one.
- return GetPhysicalScratchDevice();
+ return "";
}
-bool fs_mgr_overlayfs_make_scratch(const std::string& scratch_device, const std::string& mnt_type) {
+bool MakeScratchFilesystem(const std::string& scratch_device) {
// Force mkfs by design for overlay support of adb remount, simplify and
// thus do not rely on fsck to correct problems that could creep in.
+ auto fs_type = ""s;
auto command = ""s;
- if (mnt_type == "f2fs") {
+ if (!access(kMkF2fs.c_str(), X_OK) && fs_mgr_filesystem_available("f2fs")) {
+ fs_type = "f2fs";
command = kMkF2fs + " -w 4096 -f -d1 -l" + android::base::Basename(kScratchMountPoint);
- } else if (mnt_type == "ext4") {
+ } else if (!access(kMkExt4.c_str(), X_OK) && fs_mgr_filesystem_available("ext4")) {
+ fs_type = "ext4";
command = kMkExt4 + " -F -b 4096 -t ext4 -m 0 -O has_journal -M " + kScratchMountPoint;
} else {
- LERROR << mnt_type << " has no mkfs cookbook";
+ LERROR << "No supported mkfs command or filesystem driver available, supported filesystems "
+ "are: f2fs, ext4";
return false;
}
command += " " + scratch_device + " >/dev/null 2>/dev/null </dev/null";
fs_mgr_set_blk_ro(scratch_device, false);
auto ret = system(command.c_str());
if (ret) {
- LERROR << "make " << mnt_type << " filesystem on " << scratch_device << " return=" << ret;
+ LERROR << "make " << fs_type << " filesystem on " << scratch_device << " return=" << ret;
return false;
}
return true;
@@ -1153,7 +1089,7 @@
return true;
}
-static bool CanUseSuperPartition(const Fstab& fstab, bool* is_virtual_ab) {
+static bool CanUseSuperPartition(const Fstab& fstab) {
auto slot_number = fs_mgr_overlayfs_slot_number();
auto super_device = fs_mgr_overlayfs_super_device(slot_number);
if (!fs_mgr_rw_access(super_device) || !fs_mgr_overlayfs_has_logical(fstab)) {
@@ -1163,7 +1099,6 @@
if (!metadata) {
return false;
}
- *is_virtual_ab = !!(metadata->header.flags & LP_HEADER_FLAG_VIRTUAL_AB_DEVICE);
return true;
}
@@ -1176,23 +1111,15 @@
return *partition_exists;
}
- // Try a physical partition first.
- *scratch_device = GetPhysicalScratchDevice();
- if (!scratch_device->empty() && fs_mgr_rw_access(*scratch_device)) {
- *partition_exists = true;
- return true;
+ // Try ImageManager on /data first.
+ bool can_use_data = false;
+ if (FilesystemHasReliablePinning("/data", &can_use_data) && can_use_data) {
+ return CreateScratchOnData(scratch_device, partition_exists);
}
-
// If that fails, see if we can land on super.
- bool is_virtual_ab;
- if (CanUseSuperPartition(fstab, &is_virtual_ab)) {
- bool can_use_data = false;
- if (is_virtual_ab && FilesystemHasReliablePinning("/data", &can_use_data) && can_use_data) {
- return CreateScratchOnData(scratch_device, partition_exists);
- }
+ if (CanUseSuperPartition(fstab)) {
return CreateDynamicScratch(scratch_device, partition_exists);
}
-
return false;
}
@@ -1210,9 +1137,8 @@
}
// If the partition exists, assume first that it can be mounted.
- auto mnt_type = fs_mgr_overlayfs_scratch_mount_type();
if (partition_exists) {
- if (fs_mgr_overlayfs_mount_scratch(scratch_device, mnt_type)) {
+ if (MountScratch(scratch_device)) {
if (fs_mgr_access(kScratchMountPoint + kOverlayTopDir) ||
fs_mgr_filesystem_has_space(kScratchMountPoint)) {
return true;
@@ -1225,19 +1151,49 @@
}
}
- if (!fs_mgr_overlayfs_make_scratch(scratch_device, mnt_type)) {
+ if (!MakeScratchFilesystem(scratch_device)) {
LOG(ERROR) << "Failed to format scratch partition";
return false;
}
- return fs_mgr_overlayfs_mount_scratch(scratch_device, mnt_type);
+ return MountScratch(scratch_device);
}
-bool fs_mgr_overlayfs_invalid() {
- if (fs_mgr_overlayfs_valid() == OverlayfsValidResult::kNotSupported) return true;
+#if ALLOW_ADBD_DISABLE_VERITY
+constexpr bool kAllowOverlayfs = true;
+#else
+constexpr bool kAllowOverlayfs = false;
+#endif
+// NOTE: OverlayfsSetupAllowed() must be "stricter" than OverlayfsTeardownAllowed().
+// Setup is allowed only if teardown is also allowed.
+bool OverlayfsSetupAllowed(bool verbose = false) {
+ if (!kAllowOverlayfs) {
+ if (verbose) {
+ LOG(ERROR) << "Overlayfs remounts can only be used in debuggable builds";
+ }
+ return false;
+ }
+ // Check mandatory kernel patches.
+ if (fs_mgr_overlayfs_valid() == OverlayfsValidResult::kNotSupported) {
+ if (verbose) {
+ LOG(ERROR) << "Kernel does not support overlayfs";
+ }
+ return false;
+ }
// in recovery or fastbootd, not allowed!
- return fs_mgr_in_recovery();
+ if (fs_mgr_in_recovery()) {
+ if (verbose) {
+ LOG(ERROR) << "Unsupported overlayfs setup from recovery";
+ }
+ return false;
+ }
+ return true;
+}
+
+constexpr bool OverlayfsTeardownAllowed() {
+ // Never allow on non-debuggable build.
+ return kAllowOverlayfs;
}
} // namespace
@@ -1319,41 +1275,39 @@
if (!WaitForFile(scratch_device, 10s)) {
return;
}
- const auto mount_type = fs_mgr_overlayfs_scratch_mount_type();
- if (!fs_mgr_overlayfs_mount_scratch(scratch_device, mount_type, true /* readonly */)) {
+ if (!MountScratch(scratch_device, true /* readonly */)) {
return;
}
auto has_overlayfs_dir = fs_mgr_access(kScratchMountPoint + kOverlayTopDir);
fs_mgr_overlayfs_umount_scratch();
if (has_overlayfs_dir) {
- fs_mgr_overlayfs_mount_scratch(scratch_device, mount_type);
+ MountScratch(scratch_device);
}
}
bool fs_mgr_overlayfs_mount_all(Fstab* fstab) {
- auto ret = false;
- if (fs_mgr_overlayfs_invalid()) return ret;
-
+ if (!OverlayfsSetupAllowed()) {
+ return false;
+ }
+ auto ret = true;
auto scratch_can_be_mounted = true;
for (const auto& entry : fs_mgr_overlayfs_candidate_list(*fstab)) {
if (fs_mgr_is_verity_enabled(entry)) continue;
auto mount_point = fs_mgr_mount_point(entry.mount_point);
if (fs_mgr_overlayfs_already_mounted(mount_point)) {
- ret = true;
continue;
}
if (scratch_can_be_mounted) {
scratch_can_be_mounted = false;
TryMountScratch();
}
- if (fs_mgr_overlayfs_mount(mount_point)) ret = true;
+ ret &= fs_mgr_overlayfs_mount(mount_point);
}
return ret;
}
bool fs_mgr_overlayfs_setup(const char* mount_point, bool* want_reboot, bool just_disabled_verity) {
- if (fs_mgr_overlayfs_valid() == OverlayfsValidResult::kNotSupported) {
- LOG(ERROR) << "Overlayfs is not supported";
+ if (!OverlayfsSetupAllowed(/*verbose=*/true)) {
return false;
}
@@ -1523,7 +1477,8 @@
return true;
}
-OverlayfsTeardownResult TeardownMountsAndScratch(const char* mount_point, bool* want_reboot) {
+static OverlayfsTeardownResult TeardownMountsAndScratch(const char* mount_point,
+ bool* want_reboot) {
bool should_destroy_scratch = false;
auto rv = OverlayfsTeardownResult::Ok;
for (const auto& overlay_mount_point : OverlayMountPoints()) {
@@ -1555,14 +1510,17 @@
// Returns false if teardown not permitted. If something is altered, set *want_reboot.
OverlayfsTeardownResult fs_mgr_overlayfs_teardown(const char* mount_point, bool* want_reboot) {
+ if (!OverlayfsTeardownAllowed()) {
+ // Nothing to teardown.
+ return OverlayfsTeardownResult::Ok;
+ }
// If scratch exists, but is not mounted, lets gain access to clean
// specific override entries.
auto mount_scratch = false;
if ((mount_point != nullptr) && !fs_mgr_overlayfs_already_mounted(kScratchMountPoint, false)) {
std::string scratch_device = GetBootScratchDevice();
if (!scratch_device.empty()) {
- mount_scratch = fs_mgr_overlayfs_mount_scratch(scratch_device,
- fs_mgr_overlayfs_scratch_mount_type());
+ mount_scratch = MountScratch(scratch_device);
}
}
@@ -1577,12 +1535,14 @@
}
bool fs_mgr_overlayfs_is_setup() {
+ if (!OverlayfsSetupAllowed()) {
+ return false;
+ }
if (fs_mgr_overlayfs_already_mounted(kScratchMountPoint, false)) return true;
Fstab fstab;
if (!ReadDefaultFstab(&fstab)) {
return false;
}
- if (fs_mgr_overlayfs_invalid()) return false;
for (const auto& entry : fs_mgr_overlayfs_candidate_list(fstab)) {
if (fs_mgr_is_verity_enabled(entry)) continue;
if (fs_mgr_overlayfs_already_mounted(fs_mgr_mount_point(entry.mount_point))) return true;
@@ -1595,7 +1555,7 @@
void MapScratchPartitionIfNeeded(Fstab* fstab,
const std::function<bool(const std::set<std::string>&)>& init) {
- if (fs_mgr_overlayfs_invalid()) {
+ if (!OverlayfsSetupAllowed()) {
return;
}
if (GetEntryForMountPoint(fstab, kScratchMountPoint) != nullptr) {
@@ -1632,6 +1592,9 @@
}
void CleanupOldScratchFiles() {
+ if (!OverlayfsTeardownAllowed()) {
+ return;
+ }
if (!ScratchIsOnData()) {
return;
}
@@ -1641,6 +1604,9 @@
}
void TeardownAllOverlayForMountPoint(const std::string& mount_point) {
+ if (!OverlayfsTeardownAllowed()) {
+ return;
+ }
if (!fs_mgr_in_recovery()) {
LERROR << __FUNCTION__ << "(): must be called within recovery.";
return;
@@ -1675,7 +1641,7 @@
if (auto info = EnsureScratchMapped(); info.has_value()) {
// Map scratch device, mount kScratchMountPoint and teardown kScratchMountPoint.
fs_mgr_overlayfs_umount_scratch();
- if (fs_mgr_overlayfs_mount_scratch(info->device, fs_mgr_overlayfs_scratch_mount_type())) {
+ if (MountScratch(info->device)) {
bool should_destroy_scratch = false;
fs_mgr_overlayfs_teardown_one(kScratchMountPoint, teardown_dir, ignore_change,
&should_destroy_scratch);
@@ -1690,7 +1656,7 @@
std::string scratch_device;
if (MapDsuScratchDevice(&scratch_device)) {
fs_mgr_overlayfs_umount_scratch();
- if (fs_mgr_overlayfs_mount_scratch(scratch_device, fs_mgr_overlayfs_scratch_mount_type())) {
+ if (MountScratch(scratch_device)) {
fs_mgr_overlayfs_teardown_one(kScratchMountPoint, teardown_dir, ignore_change);
fs_mgr_overlayfs_umount_scratch();
}
@@ -1701,8 +1667,6 @@
} // namespace fs_mgr
} // namespace android
-#endif // ALLOW_ADBD_DISABLE_VERITY != 0
-
bool fs_mgr_overlayfs_already_mounted(const std::string& mount_point, bool overlay_only) {
Fstab fstab;
if (!ReadFstabFromFile("/proc/mounts", &fstab)) {
@@ -1722,65 +1686,3 @@
}
return false;
}
-
-bool fs_mgr_has_shared_blocks(const std::string& mount_point, const std::string& dev) {
- struct statfs fs;
- if ((statfs((mount_point + "/lost+found").c_str(), &fs) == -1) ||
- (fs.f_type != EXT4_SUPER_MAGIC)) {
- return false;
- }
-
- android::base::unique_fd fd(open(dev.c_str(), O_RDONLY | O_CLOEXEC));
- if (fd < 0) return false;
-
- struct ext4_super_block sb;
- if ((TEMP_FAILURE_RETRY(lseek64(fd, 1024, SEEK_SET)) < 0) ||
- (TEMP_FAILURE_RETRY(read(fd, &sb, sizeof(sb))) < 0)) {
- return false;
- }
-
- struct fs_info info;
- if (ext4_parse_sb(&sb, &info) < 0) return false;
-
- return (info.feat_ro_compat & EXT4_FEATURE_RO_COMPAT_SHARED_BLOCKS) != 0;
-}
-
-std::string fs_mgr_get_context(const std::string& mount_point) {
- char* ctx = nullptr;
- if (getfilecon(mount_point.c_str(), &ctx) == -1) {
- PLOG(ERROR) << "getfilecon " << mount_point;
- return "";
- }
-
- std::string context(ctx);
- free(ctx);
- return context;
-}
-
-OverlayfsValidResult fs_mgr_overlayfs_valid() {
- // Overlayfs available in the kernel, and patched for override_creds?
- if (fs_mgr_access("/sys/module/overlay/parameters/override_creds")) {
- return OverlayfsValidResult::kOverrideCredsRequired;
- }
- if (!fs_mgr_overlayfs_filesystem_available("overlay")) {
- return OverlayfsValidResult::kNotSupported;
- }
- struct utsname uts;
- if (uname(&uts) == -1) {
- return OverlayfsValidResult::kNotSupported;
- }
- int major, minor;
- if (sscanf(uts.release, "%d.%d", &major, &minor) != 2) {
- return OverlayfsValidResult::kNotSupported;
- }
- if (major < 4) {
- return OverlayfsValidResult::kOk;
- }
- if (major > 4) {
- return OverlayfsValidResult::kNotSupported;
- }
- if (minor > 3) {
- return OverlayfsValidResult::kNotSupported;
- }
- return OverlayfsValidResult::kOk;
-}
diff --git a/fs_mgr/fs_mgr_priv.h b/fs_mgr/fs_mgr_priv.h
index c5e477c..46f54cc 100644
--- a/fs_mgr/fs_mgr_priv.h
+++ b/fs_mgr/fs_mgr_priv.h
@@ -99,6 +99,16 @@
bool fs_mgr_teardown_verity(android::fs_mgr::FstabEntry* fstab);
+bool fs_mgr_filesystem_available(const std::string& filesystem);
+std::string fs_mgr_get_context(const std::string& mount_point);
+
+enum class OverlayfsValidResult {
+ kNotSupported = 0,
+ kOk,
+ kOverrideCredsRequired,
+};
+OverlayfsValidResult fs_mgr_overlayfs_valid();
+
namespace android {
namespace fs_mgr {
bool UnmapDevice(const std::string& name);
diff --git a/fs_mgr/fs_mgr_priv_overlayfs.h b/fs_mgr/fs_mgr_priv_overlayfs.h
new file mode 100644
index 0000000..45b954d
--- /dev/null
+++ b/fs_mgr/fs_mgr_priv_overlayfs.h
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <string>
+
+#include <fstab/fstab.h>
+
+bool fs_mgr_overlayfs_already_mounted(const std::string& mount_point, bool overlay_only = true);
+bool fs_mgr_wants_overlayfs(android::fs_mgr::FstabEntry* entry);
+android::fs_mgr::Fstab fs_mgr_overlayfs_candidate_list(const android::fs_mgr::Fstab& fstab);
+
+// If "mount_point" is non-null, set up exactly one overlay.
+// If "mount_point" is null, setup any overlays.
+//
+// If |want_reboot| is non-null, and a reboot is needed to apply overlays, then
+// it will be true on return. The caller is responsible for initializing it.
+bool fs_mgr_overlayfs_setup(const char* mount_point = nullptr, bool* want_reboot = nullptr,
+ bool just_disabled_verity = true);
+
+enum class OverlayfsTeardownResult {
+ Ok,
+ Busy, // Indicates that overlays are still in use.
+ Error
+};
+OverlayfsTeardownResult fs_mgr_overlayfs_teardown(const char* mount_point = nullptr,
+ bool* want_reboot = nullptr);
+
+namespace android {
+namespace fs_mgr {
+
+void CleanupOldScratchFiles();
+
+} // namespace fs_mgr
+} // namespace android
diff --git a/fs_mgr/fs_mgr_remount.cpp b/fs_mgr/fs_mgr_remount.cpp
index 2202fda..54c1c2c 100644
--- a/fs_mgr/fs_mgr_remount.cpp
+++ b/fs_mgr/fs_mgr_remount.cpp
@@ -42,6 +42,8 @@
#include <libavb_user/libavb_user.h>
#include <libgsi/libgsid.h>
+#include "fs_mgr_priv_overlayfs.h"
+
using namespace std::literals;
using android::fs_mgr::Fstab;
using android::fs_mgr::FstabEntry;
@@ -451,10 +453,9 @@
}
// Mount overlayfs.
- errno = 0;
- if (!fs_mgr_overlayfs_mount_all(&partitions) && errno) {
- PLOG(ERROR) << "Can not mount overlayfs for partitions";
- return BAD_OVERLAY;
+ if (!fs_mgr_overlayfs_mount_all(&partitions)) {
+ LOG(WARNING) << "Cannot mount overlayfs for some partitions";
+ // Continue regardless to handle raw remount case.
}
// Get actual mounts _after_ overlayfs has been added.
diff --git a/fs_mgr/fs_mgr_vendor_overlay.cpp b/fs_mgr/fs_mgr_vendor_overlay.cpp
index 1372511..6b32b4d 100644
--- a/fs_mgr/fs_mgr_vendor_overlay.cpp
+++ b/fs_mgr/fs_mgr_vendor_overlay.cpp
@@ -25,7 +25,6 @@
#include <android-base/logging.h>
#include <android-base/properties.h>
-#include <fs_mgr_overlayfs.h>
#include <fs_mgr_vendor_overlay.h>
#include <fstab/fstab.h>
diff --git a/fs_mgr/include/fs_mgr_overlayfs.h b/fs_mgr/include/fs_mgr_overlayfs.h
index 4d9b13f..bdaabbf 100644
--- a/fs_mgr/include/fs_mgr_overlayfs.h
+++ b/fs_mgr/include/fs_mgr_overlayfs.h
@@ -17,51 +17,21 @@
#pragma once
#include <functional>
+#include <set>
+#include <string>
#include <fstab/fstab.h>
-#include <set>
-#include <string>
-#include <vector>
+// Keep the list short and only add interfaces that must be exported public.
-android::fs_mgr::Fstab fs_mgr_overlayfs_candidate_list(const android::fs_mgr::Fstab& fstab);
-
-bool fs_mgr_wants_overlayfs(android::fs_mgr::FstabEntry* entry);
bool fs_mgr_overlayfs_mount_all(android::fs_mgr::Fstab* fstab);
bool fs_mgr_overlayfs_is_setup();
-bool fs_mgr_has_shared_blocks(const std::string& mount_point, const std::string& dev);
-bool fs_mgr_overlayfs_already_mounted(const std::string& mount_point, bool overlay_only = true);
-std::string fs_mgr_get_context(const std::string& mount_point);
-
-// If "mount_point" is non-null, set up exactly one overlay.
-// If "mount_point" is null, setup any overlays.
-//
-// If |want_reboot| is non-null, and a reboot is needed to apply overlays, then
-// it will be true on return. The caller is responsible for initializing it.
-bool fs_mgr_overlayfs_setup(const char* mount_point = nullptr, bool* want_reboot = nullptr,
- bool just_disabled_verity = true);
-
-enum class OverlayfsTeardownResult {
- Ok,
- Busy, // Indicates that overlays are still in use.
- Error
-};
-OverlayfsTeardownResult fs_mgr_overlayfs_teardown(const char* mount_point = nullptr,
- bool* want_reboot = nullptr);
-
-enum class OverlayfsValidResult {
- kNotSupported = 0,
- kOk,
- kOverrideCredsRequired,
-};
-OverlayfsValidResult fs_mgr_overlayfs_valid();
namespace android {
namespace fs_mgr {
void MapScratchPartitionIfNeeded(Fstab* fstab,
const std::function<bool(const std::set<std::string>&)>& init);
-void CleanupOldScratchFiles();
// Teardown overlays of all sources (cache dir, scratch device, DSU) for |mount_point|.
// Teardown all overlays if |mount_point| is empty.
diff --git a/fs_mgr/set-verity-state.cpp b/fs_mgr/set-verity-state.cpp
new file mode 100644
index 0000000..84ee01f
--- /dev/null
+++ b/fs_mgr/set-verity-state.cpp
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <getopt.h>
+#include <stdio.h>
+
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/properties.h>
+#include <binder/ProcessState.h>
+#include <cutils/android_reboot.h>
+#include <fs_mgr_overlayfs.h>
+#include <libavb_user/libavb_user.h>
+
+#include "fs_mgr_priv_overlayfs.h"
+
+using namespace std::string_literals;
+
+namespace {
+
+void print_usage() {
+ printf("Usage:\n"
+ "\tdisable-verity\n"
+ "\tenable-verity\n"
+ "\tset-verity-state [0|1]\n"
+ "Options:\n"
+ "\t-h --help\tthis help\n"
+ "\t-R --reboot\tautomatic reboot if needed for new settings to take effect\n"
+ "\t-v --verbose\tbe noisy\n");
+}
+
+#ifdef ALLOW_DISABLE_VERITY
+const bool kAllowDisableVerity = true;
+#else
+const bool kAllowDisableVerity = false;
+#endif
+
+static bool SetupOrTeardownOverlayfs(bool enable) {
+ bool want_reboot = false;
+ if (enable) {
+ if (!fs_mgr_overlayfs_setup(nullptr, &want_reboot)) {
+ LOG(ERROR) << "Overlayfs setup failed.";
+ return want_reboot;
+ }
+ if (want_reboot) {
+ printf("enabling overlayfs\n");
+ }
+ } else {
+ auto rv = fs_mgr_overlayfs_teardown(nullptr, &want_reboot);
+ if (rv == OverlayfsTeardownResult::Error) {
+ LOG(ERROR) << "Overlayfs teardown failed.";
+ return want_reboot;
+ }
+ if (rv == OverlayfsTeardownResult::Busy) {
+ LOG(ERROR) << "Overlayfs is still active until reboot.";
+ return true;
+ }
+ if (want_reboot) {
+ printf("disabling overlayfs\n");
+ }
+ }
+ return want_reboot;
+}
+
+/* Helper function to get A/B suffix, if any. If the device isn't
+ * using A/B the empty string is returned. Otherwise either "_a",
+ * "_b", ... is returned.
+ */
+std::string get_ab_suffix() {
+ return android::base::GetProperty("ro.boot.slot_suffix", "");
+}
+
+bool is_avb_device_locked() {
+ return android::base::GetProperty("ro.boot.vbmeta.device_state", "") == "locked";
+}
+
+bool is_debuggable() {
+ return android::base::GetBoolProperty("ro.debuggable", false);
+}
+
+bool is_using_avb() {
+ // Figure out if we're using VB1.0 or VB2.0 (aka AVB) - by
+ // contract, androidboot.vbmeta.digest is set by the bootloader
+ // when using AVB).
+ return !android::base::GetProperty("ro.boot.vbmeta.digest", "").empty();
+}
+
+[[noreturn]] void reboot(const std::string& name) {
+ LOG(INFO) << "Rebooting device for new settings to take effect";
+ ::sync();
+ android::base::SetProperty(ANDROID_RB_PROPERTY, "reboot," + name);
+ ::sleep(60);
+ LOG(ERROR) << "Failed to reboot";
+ ::exit(1);
+}
+
+struct SetVerityStateResult {
+ bool success = false;
+ bool want_reboot = false;
+};
+
+/* Use AVB to turn verity on/off */
+SetVerityStateResult SetVerityState(bool enable_verity) {
+ std::string ab_suffix = get_ab_suffix();
+ bool verity_enabled = false;
+
+ if (is_avb_device_locked()) {
+ LOG(ERROR) << "Device must be bootloader unlocked to change verity state";
+ return {};
+ }
+
+ std::unique_ptr<AvbOps, decltype(&avb_ops_user_free)> ops(avb_ops_user_new(),
+ &avb_ops_user_free);
+ if (!ops) {
+ LOG(ERROR) << "Error getting AVB ops";
+ return {};
+ }
+
+ if (!avb_user_verity_get(ops.get(), ab_suffix.c_str(), &verity_enabled)) {
+ LOG(ERROR) << "Error getting verity state";
+ return {};
+ }
+
+ if ((verity_enabled && enable_verity) || (!verity_enabled && !enable_verity)) {
+ LOG(INFO) << "Verity is already " << (verity_enabled ? "enabled" : "disabled");
+ return {.success = true, .want_reboot = false};
+ }
+
+ if (!avb_user_verity_set(ops.get(), ab_suffix.c_str(), enable_verity)) {
+ LOG(ERROR) << "Error setting verity state";
+ return {};
+ }
+
+ LOG(INFO) << "Successfully " << (enable_verity ? "enabled" : "disabled") << " verity";
+ return {.success = true, .want_reboot = true};
+}
+
+class MyLogger {
+ public:
+ explicit MyLogger(bool verbose) : verbose_(verbose) {}
+
+ void operator()(android::base::LogId id, android::base::LogSeverity severity, const char* tag,
+ const char* file, unsigned int line, const char* message) {
+ // Hide log starting with '[fs_mgr]' unless it's an error.
+ if (verbose_ || severity >= android::base::ERROR || message[0] != '[') {
+ fprintf(stderr, "%s\n", message);
+ }
+ logd_(id, severity, tag, file, line, message);
+ }
+
+ private:
+ android::base::LogdLogger logd_;
+ bool verbose_;
+};
+
+} // namespace
+
+int main(int argc, char* argv[]) {
+ bool auto_reboot = false;
+ bool verbose = false;
+
+ struct option longopts[] = {
+ {"help", no_argument, nullptr, 'h'},
+ {"reboot", no_argument, nullptr, 'R'},
+ {"verbose", no_argument, nullptr, 'v'},
+ {0, 0, nullptr, 0},
+ };
+ for (int opt; (opt = ::getopt_long(argc, argv, "hRv", longopts, nullptr)) != -1;) {
+ switch (opt) {
+ case 'h':
+ print_usage();
+ return 0;
+ case 'R':
+ auto_reboot = true;
+ break;
+ case 'v':
+ verbose = true;
+ break;
+ default:
+ print_usage();
+ return 1;
+ }
+ }
+
+ android::base::InitLogging(argv, MyLogger(verbose));
+
+ bool enable_verity = false;
+ const std::string progname = getprogname();
+ if (progname == "enable-verity") {
+ enable_verity = true;
+ } else if (progname == "disable-verity") {
+ enable_verity = false;
+ } else if (optind < argc && (argv[optind] == "1"s || argv[optind] == "0"s)) {
+ // progname "set-verity-state"
+ enable_verity = (argv[optind] == "1"s);
+ } else {
+ print_usage();
+ return 1;
+ }
+
+ if (!kAllowDisableVerity || !is_debuggable()) {
+ errno = EPERM;
+ PLOG(ERROR) << "Cannot disable/enable verity on user build";
+ return 1;
+ }
+
+ if (getuid() != 0) {
+ errno = EACCES;
+ PLOG(ERROR) << "Must be running as root (adb root)";
+ return 1;
+ }
+
+ if (!is_using_avb()) {
+ LOG(ERROR) << "Expected AVB device, VB1.0 is no longer supported";
+ return 1;
+ }
+
+ int exit_code = 0;
+ bool want_reboot = false;
+
+ auto ret = SetVerityState(enable_verity);
+ if (ret.success) {
+ want_reboot |= ret.want_reboot;
+ } else {
+ exit_code = 1;
+ }
+
+ // Disable any overlayfs unconditionally if we want verity enabled.
+ // Enable overlayfs only if verity is successfully disabled or is already disabled.
+ if (enable_verity || ret.success) {
+ // Start a threadpool to service waitForService() callbacks as
+ // fs_mgr_overlayfs_* might call waitForService() to get the image service.
+ android::ProcessState::self()->startThreadPool();
+ want_reboot |= SetupOrTeardownOverlayfs(!enable_verity);
+ }
+
+ if (want_reboot) {
+ if (auto_reboot) {
+ reboot(progname);
+ }
+ printf("Reboot the device for new settings to take effect\n");
+ }
+
+ return exit_code;
+}
diff --git a/fs_mgr/tests/adb-remount-test.sh b/fs_mgr/tests/adb-remount-test.sh
index a6bdd6c..eba4f6e 100755
--- a/fs_mgr/tests/adb-remount-test.sh
+++ b/fs_mgr/tests/adb-remount-test.sh
@@ -1241,40 +1241,45 @@
adb_sh grep -q " /vendor [^ ]* rw," /proc/mounts </dev/null ||
die -t "${T}" "/vendor is not RW"
+scratch_on_super=false
if ${overlayfs_needed}; then
- is_overlayfs_mounted || die -t "${T}" "expected overlay takeover"
-else
- is_overlayfs_mounted && die -t "${T}" "unexpected overlay takeover"
-fi
+ is_overlayfs_mounted /system ||
+ die -t "${T}" "expected overlay to takeover /system after remount"
-# If scratch_partition && uses_dynamic_scratch, then scratch is on super.
-# If scratch_partition && !uses_dynamic_scratch, then scratch is super_other, system_other.
-# If !scratch_partition, then scratch is on /data via image_manager.
-uses_dynamic_scratch=false
-scratch_partition=
-virtual_ab=$(get_property ro.virtual_ab.enabled)
-if ${overlayfs_needed}; then
+ # Collect information about the scratch device if we have one
M=$(adb_sh cat /proc/mounts </dev/null |
awk '$2 == "/mnt/scratch" { print $1, $3; exit }')
- [ -z "${M}" ] && die "cannot find any scratch device mounted on /mnt/scratch"
+ if [ -n "${M}" ]; then
+ scratch_device=$(echo "${M}" | awk '{ print $1 }')
+ scratch_filesystem=$(echo "${M}" | awk '{ print $2 }')
+ scratch_size=$(adb_sh df -k "${scratch_device}" </dev/null |
+ tail +2 | head -1 | awk '{ print $2 }')
+ [ -z "${scratch_size}" ] && die "cannot get size of scratch device (${scratch_device})"
- scratch_device=$(echo "${M}" | awk '{ print $1 }')
- scratch_filesystem=$(echo "${M}" | awk '{ print $2 }')
- scratch_size=$(adb_sh df -k "${scratch_device}" </dev/null |
- tail +2 | head -1 | awk '{ print $2 }')
- [ -z "${scratch_size}" ] && die "cannot get size of scratch device (${scratch_device})"
+ # Detect scratch partition backed by super?
+ for b in "/dev/block/by-name/super"{,_${ACTIVE_SLOT}}; do
+ if adb_test -e "${b}"; then
+ device=$(adb_su realpath "${b}")
+ D=$(adb_su stat -c '0x%t 0x%T' "${device}")
+ major=$(echo "${D}" | awk '{ print $1 }')
+ minor=$(echo "${D}" | awk '{ print $2 }')
+ super_devt=$(( major )):$(( minor ))
+ if adb_su dmctl table scratch | tail +2 | grep -q -w "${super_devt}"; then
+ scratch_on_super=true
+ fi
+ break
+ fi
+ done
- if [ -n "${virtual_ab}" ]; then
- LOG INFO "using dynamic scratch partition on /data (VAB device)"
- elif [[ "${scratch_device}" == /dev/block/by-name/* ]]; then
- scratch_partition="${scratch_device##/dev/block/by-name/}"
- LOG INFO "using physical scratch partition ${scratch_partition}"
+ if ${scratch_on_super}; then
+ LOG INFO "using dynamic scratch partition on super"
+ else
+ LOG INFO "using dynamic scratch partition on /data (VAB device)"
+ fi
+ LOG INFO "scratch device ${scratch_device} filesystem ${scratch_filesystem} size ${scratch_size}KiB"
else
- uses_dynamic_scratch=true
- scratch_partition=scratch
- LOG INFO "using dynamic scratch partition on super"
+ LOG INFO "cannot find any scratch device mounted on /mnt/scratch, using scratch on /cache"
fi
- LOG INFO "scratch device ${scratch_device} filesystem ${scratch_filesystem} size ${scratch_size}KiB"
for d in ${OVERLAYFS_BACKING}; do
if adb_test -d /${d}/overlay/system/upper; then
@@ -1283,8 +1288,6 @@
done
data_device=$(adb_sh awk '$2 == "/data" { print $1; exit }' /proc/mounts)
- is_overlayfs_mounted /system 2>/dev/null ||
- die -t "${T}" "expected overlay to takeover /system after remount"
# KISS (we do not support sub-mounts for system partitions currently)
adb_sh grep "^overlay " /proc/mounts </dev/null |
grep -vE "^overlay.* /(apex|system|vendor)/[^ ]" |
@@ -1312,6 +1315,8 @@
die "remount overlayfs missed a spot (rw)"
fi
done
+else
+ is_overlayfs_mounted && die -t "${T}" "unexpected overlay takeover"
fi
LOG OK "adb remount RW"
@@ -1455,31 +1460,18 @@
fastboot_getvar is-userspace yes &&
is_userspace_fastboot=true
- # check ${scratch_partition} via fastboot
- if [ -n "${scratch_partition}" ]; then
- fastboot_getvar partition-type:${scratch_partition} raw ||
- ( fastboot reboot && false) ||
- die "fastboot can not see ${scratch_partition} parameters"
- if ${uses_dynamic_scratch}; then
- fastboot_getvar has-slot:${scratch_partition} no &&
- fastboot_getvar is-logical:${scratch_partition} yes ||
- ( fastboot reboot && false) ||
- die "fastboot can not see ${scratch_partition} parameters"
- LOG INFO "expect fastboot erase ${scratch_partition} to fail"
- fastboot erase ${scratch_partition} &&
- ( fastboot reboot || true) &&
- die "fastboot can erase ${scratch_partition}"
- else
- fastboot_getvar is-logical:${scratch_partition} no ||
- ( fastboot reboot && false) ||
- die "fastboot can not see ${scratch_partition} parameters"
- fastboot reboot-bootloader ||
- die "fastboot reboot bootloader"
- fi
- LOG INFO "expect fastboot format ${scratch_partition} to fail"
- fastboot format ${scratch_partition} &&
- ( fastboot reboot || true) &&
- die "fastboot can format ${scratch_partition}"
+
+ if ${scratch_on_super}; then
+ fastboot_getvar partition-type:scratch raw ||
+ die "fastboot cannot see parameter partition-type:scratch"
+ fastboot_getvar has-slot:scratch no ||
+ die "fastboot cannot see parameter has-slot:scratch"
+ fastboot_getvar is-logical:scratch yes ||
+ die "fastboot cannot see parameter is-logical:scratch"
+ LOG INFO "expect fastboot erase scratch to fail"
+ fastboot erase scratch && die "fastboot can erase scratch"
+ LOG INFO "expect fastboot format scratch to fail"
+ fastboot format scratch && die "fastboot can format scratch"
fi
fastboot reboot || die "cannot reboot out of fastboot"
@@ -1539,9 +1531,9 @@
done
################################################################################
-if ${is_bootloader_fastboot} && [ -n "${scratch_partition}" ]; then
+if ${is_bootloader_fastboot} && ${scratch_on_super}; then
- LOG RUN "test fastboot flash to ${scratch_partition} recovery"
+ LOG RUN "test fastboot flash to scratch recovery"
avc_check
adb reboot fastboot </dev/null ||
@@ -1550,15 +1542,15 @@
dd if=/dev/zero of=${img} bs=4096 count=16 2>/dev/null &&
fastboot_wait ${FASTBOOT_WAIT} ||
die "reboot into fastboot to flash scratch `usb_status`"
- fastboot flash --force ${scratch_partition} ${img}
+ fastboot flash --force scratch ${img}
err=${?}
fastboot reboot ||
die "can not reboot out of fastboot"
[ 0 -eq ${err} ] ||
- die "fastboot flash ${scratch_partition}"
+ die "fastboot flash scratch"
adb_wait ${ADB_WAIT} &&
adb_root ||
- die "did not reboot after flashing empty ${scratch_partition} `usb_status`"
+ die "did not reboot after flashing empty scratch $(usb_status)"
T=`adb_date`
D=`adb disable-verity 2>&1`
err=${?}
@@ -1578,7 +1570,7 @@
[ ${err} = 0 ] &&
[ X"${D}" = X"${D##*setup failed}" ] &&
[ X"${D}" != X"${D##*[Uu]sing overlayfs}" ] &&
- LOG OK "${scratch_partition} recreated" ||
+ LOG OK "recreated scratch" ||
die -t ${T} "setup for overlayfs"
adb remount >&2 ||
die -t ${T} "remount failed"
diff --git a/init/Android.bp b/init/Android.bp
index 6255305..f0e362c 100644
--- a/init/Android.bp
+++ b/init/Android.bp
@@ -161,6 +161,7 @@
},
static_libs: [
"libavb",
+ "libbootloader_message",
"libc++fs",
"libcgrouprc_format",
"libfsverity_init",
@@ -181,7 +182,6 @@
],
shared_libs: [
"libbase",
- "libbootloader_message",
"libcrypto",
"libcutils",
"libdl",
diff --git a/init/fuzzer/Android.bp b/init/fuzzer/Android.bp
new file mode 100644
index 0000000..acbb746
--- /dev/null
+++ b/init/fuzzer/Android.bp
@@ -0,0 +1,72 @@
+/*
+ * 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.
+ */
+cc_defaults {
+ name: "libinit_defaults",
+ static_libs: [
+ "libc++fs",
+ "liblmkd_utils",
+ "libmodprobe",
+ "libprotobuf-cpp-lite",
+ "libpropertyinfoparser",
+ "libsnapshot_init",
+ "libinit",
+ ],
+ shared_libs: [
+ "libbase",
+ "libfs_mgr",
+ "libhidl-gen-utils",
+ "libkeyutils",
+ "liblog",
+ "libprocessgroup",
+ "libselinux",
+ ],
+ header_libs: ["libinit_headers"],
+ fuzz_config: {
+ cc: [
+ "android-media-fuzzing-reports@google.com",
+ ],
+ componentid: 155276,
+ },
+}
+
+cc_fuzz {
+ name: "init_parser_fuzzer",
+ srcs: [
+ "init_parser_fuzzer.cpp",
+ ],
+ shared_libs: ["libhidlmetadata",],
+ defaults: [
+ "libinit_defaults",
+ ],
+}
+
+cc_fuzz {
+ name: "init_property_fuzzer",
+ srcs: [
+ "init_property_fuzzer.cpp",
+ ],
+ defaults: ["libinit_defaults"],
+}
+
+cc_fuzz {
+ name: "init_ueventHandler_fuzzer",
+ srcs: [
+ "init_ueventHandler_fuzzer.cpp",
+ ],
+ defaults: [
+ "libinit_defaults",
+ ],
+}
diff --git a/init/fuzzer/README.md b/init/fuzzer/README.md
new file mode 100644
index 0000000..fc9a6a6
--- /dev/null
+++ b/init/fuzzer/README.md
@@ -0,0 +1,98 @@
+# Fuzzers for libinit
+
+## Table of contents
++ [init_parser_fuzzer](#InitParser)
++ [init_property_fuzzer](#InitProperty)
++ [init_ueventHandler_fuzzer](#InitUeventHandler)
+
+# <a name="InitParser"></a> Fuzzer for InitParser
+
+InitParser supports the following parameters:
+1. ValidPathNames (parameter name: "kValidPaths")
+2. ValidParseInputs (parameter name: "kValidInputs")
+
+| Parameter| Valid Values| Configured Value|
+|------------- |-------------| ----- |
+|`kValidPaths`| 0.`/system/etc/init/hw/init.rc`,<br/> 1.`/system/etc/init` |Value obtained from FuzzedDataProvider|
+|`kValidInputs`| 0.`{"","cpu", "10", "10"}`,<br/> 1.`{"","RLIM_CPU", "10", "10"}`,<br/> 2.`{"","12", "unlimited", "10"}`,<br/> 3.`{"","13", "-1", "10"}`,<br/> 4.`{"","14", "10", "unlimited"}`,<br/> 5.`{"","15", "10", "-1"}` |Value obtained from FuzzedDataProvider|
+
+#### Steps to run
+1. Build the fuzzer
+```
+ $ mm -j$(nproc) init_parser_fuzzer
+```
+2. Run on device
+```
+ $ adb sync data
+ $ adb shell /data/fuzz/arm64/init_parser_fuzzer/init_parser_fuzzer
+```
+
+# <a name="InitProperty"></a> Fuzzer for InitProperty
+
+InitProperty supports the following parameters:
+ PropertyType (parameter name: "PropertyType")
+
+| Parameter| Valid Values |Configured Value|
+|-------------|----------|----- |
+|`PropertyType`| 0.`STRING`,<br/> 1.`BOOL`,<br/> 2.`INT`,<br/> 3.`UINT`,<br/> 4.`DOUBLE`,<br/> 5.`SIZE`,<br/>6.`ENUM`,<br/>7.`RANDOM`|Value obtained from FuzzedDataProvider|
+
+#### Steps to run
+1. Build the fuzzer
+```
+ $ mm -j$(nproc) init_property_fuzzer
+```
+2. Run on device
+```
+ $ adb sync data
+ $ adb shell /data/fuzz/arm64/init_property_fuzzer/init_property_fuzzer
+```
+
+# <a name="InitUeventHandler"></a> Fuzzer for InitUeventHandler
+
+##### Maximize code coverage
+The configuration parameters are not hardcoded, but instead selected based on
+incoming data. This ensures more code paths are reached by the fuzzer.
+
+InitUeventHandler supports the following parameters:
+1. Major (parameter name: `major`)
+2. Minor (parameter name: `minor`)
+3. PartitionNum (parameter name: `partition_num`)
+4. Uid (parameter name: `uid`)
+5. Gid (parameter name: `gid`)
+6. Action (parameter name: `action`)
+7. Path (parameter name: `path`)
+8. Subsystem (parameter name: `subsystem`)
+9. PartitionName (parameter name: `partition_name`)
+10. DeviceName (parameter name: `device_name`)
+11. Modalias (parameter name: `modalias`)
+12. DevPath (parameter name: `devPath`)
+13. HandlerPath (parameter name: `handlerPath`)
+
+| Parameter| Valid Values| Configured Value|
+|------------- |-------------| ----- |
+| `major` | `UINT32_MIN` to `UINT32_MAX` | Value obtained from FuzzedDataProvider|
+| `minor` | `UINT32_MIN` to `UINT32_MAX` | Value obtained from FuzzedDataProvider|
+| `partition_num ` | `UINT32_MIN` to `UINT32_MAX` | Value obtained from FuzzedDataProvider|
+| `uid` | `UINT32_MIN` to `UINT32_MAX` | Value obtained from FuzzedDataProvider|
+| `gid` | `UINT32_MIN` to `UINT32_MAX` | Value obtained from FuzzedDataProvider|
+| `action` | `String` | Value obtained from FuzzedDataProvider|
+| `path` | `String` | Value obtained from FuzzedDataProvider|
+| `subsystem` | `String` | Value obtained from FuzzedDataProvider|
+| `partition_name` | `String` | Value obtained from FuzzedDataProvider|
+| `device_name` | `String` | Value obtained from FuzzedDataProvider|
+| `modalias` | `String` | Value obtained from FuzzedDataProvider|
+| `devPath` | `String` | Value obtained from FuzzedDataProvider|
+| `handlerPath` | `String` | Value obtained from FuzzedDataProvider|
+
+This also ensures that the plugin is always deterministic for any given input.
+
+#### Steps to run
+1. Build the fuzzer
+```
+$ mm -j$(nproc) init_ueventHandler_fuzzer
+```
+2. Run on device
+```
+$ adb sync data
+$ adb shell /data/fuzz/arm64/init_ueventHandler_fuzzer/init_ueventHandler_fuzzer
+```
diff --git a/init/fuzzer/init_parser_fuzzer.cpp b/init/fuzzer/init_parser_fuzzer.cpp
new file mode 100644
index 0000000..e6a78a2
--- /dev/null
+++ b/init/fuzzer/init_parser_fuzzer.cpp
@@ -0,0 +1,146 @@
+/*
+ * 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.
+ */
+
+#include <fuzzer/FuzzedDataProvider.h>
+#include <hidl/metadata.h>
+#include <import_parser.h>
+#include <interface_utils.h>
+#include <rlimit_parser.h>
+
+using namespace android;
+using namespace android::init;
+
+const std::vector<std::string> kValidInputs[] = {
+ {"", "cpu", "10", "10"}, {"", "RLIM_CPU", "10", "10"}, {"", "12", "unlimited", "10"},
+ {"", "13", "-1", "10"}, {"", "14", "10", "unlimited"}, {"", "15", "10", "-1"},
+};
+
+const std::string kValidPaths[] = {
+ "/system/etc/init/hw/init.rc",
+ "/system/etc/init",
+};
+
+const int32_t kMaxBytes = 256;
+const std::string kValidInterfaces = "android.frameworks.vr.composer@2.0::IVrComposerClient";
+
+class InitParserFuzzer {
+ public:
+ InitParserFuzzer(const uint8_t* data, size_t size) : fdp_(data, size){};
+ void Process();
+
+ private:
+ void InvokeParser();
+ void InvokeLimitParser();
+ void InvokeInterfaceUtils();
+ InterfaceInheritanceHierarchyMap GenerateHierarchyMap();
+ std::vector<HidlInterfaceMetadata> GenerateInterfaceMetadata();
+
+ FuzzedDataProvider fdp_;
+};
+
+void InitParserFuzzer::InvokeLimitParser() {
+ if (fdp_.ConsumeBool()) {
+ std::vector<std::string> input;
+ input.push_back("");
+ input.push_back(fdp_.ConsumeRandomLengthString(kMaxBytes));
+ input.push_back(fdp_.ConsumeRandomLengthString(kMaxBytes));
+ input.push_back(fdp_.ConsumeRandomLengthString(kMaxBytes));
+ ParseRlimit(input);
+ } else {
+ ParseRlimit(fdp_.PickValueInArray(kValidInputs));
+ }
+}
+
+std::vector<HidlInterfaceMetadata> InitParserFuzzer::GenerateInterfaceMetadata() {
+ std::vector<HidlInterfaceMetadata> random_interface;
+ for (size_t idx = 0; idx < fdp_.ConsumeIntegral<size_t>(); ++idx) {
+ HidlInterfaceMetadata metadata;
+ metadata.name = fdp_.ConsumeRandomLengthString(kMaxBytes);
+ for (size_t idx1 = 0; idx1 < fdp_.ConsumeIntegral<size_t>(); ++idx1) {
+ metadata.inherited.push_back(fdp_.ConsumeRandomLengthString(kMaxBytes));
+ }
+ random_interface.push_back(metadata);
+ }
+ return random_interface;
+}
+
+InterfaceInheritanceHierarchyMap InitParserFuzzer::GenerateHierarchyMap() {
+ InterfaceInheritanceHierarchyMap result;
+ std::vector<HidlInterfaceMetadata> random_interface;
+ if (fdp_.ConsumeBool()) {
+ random_interface = GenerateInterfaceMetadata();
+ } else {
+ random_interface = HidlInterfaceMetadata::all();
+ }
+
+ for (const HidlInterfaceMetadata& iface : random_interface) {
+ std::set<FQName> inherited_interfaces;
+ for (const std::string& intf : iface.inherited) {
+ FQName fqname;
+ (void)fqname.setTo(intf);
+ inherited_interfaces.insert(fqname);
+ }
+ FQName fqname;
+ (void)fqname.setTo(iface.name);
+ result[fqname] = inherited_interfaces;
+ }
+ return result;
+}
+
+void InitParserFuzzer::InvokeInterfaceUtils() {
+ InterfaceInheritanceHierarchyMap hierarchy_map = GenerateHierarchyMap();
+ SetKnownInterfaces(hierarchy_map);
+ IsKnownInterface(fdp_.ConsumeRandomLengthString(kMaxBytes));
+ std::set<std::string> interface_set;
+ for (size_t idx = 0; idx < fdp_.ConsumeIntegral<size_t>(); ++idx) {
+ auto set_interface_values = fdp_.PickValueInArray<const std::function<void()>>({
+ [&]() {
+ interface_set.insert(("aidl/" + fdp_.ConsumeRandomLengthString(kMaxBytes)));
+ },
+ [&]() { interface_set.insert(fdp_.ConsumeRandomLengthString(kMaxBytes)); },
+ [&]() { interface_set.insert(kValidInterfaces); },
+ });
+ set_interface_values();
+ }
+ CheckInterfaceInheritanceHierarchy(interface_set, hierarchy_map);
+}
+
+void InitParserFuzzer::InvokeParser() {
+ Parser parser;
+ std::string name = fdp_.ConsumeBool() ? fdp_.ConsumeRandomLengthString(kMaxBytes) : "import";
+ parser.AddSectionParser(name, std::make_unique<ImportParser>(&parser));
+ std::string path = fdp_.ConsumeBool() ? fdp_.PickValueInArray(kValidPaths)
+ : fdp_.ConsumeRandomLengthString(kMaxBytes);
+ parser.ParseConfig(path);
+ parser.ParseConfigFileInsecure(path);
+}
+
+void InitParserFuzzer::Process() {
+ while (fdp_.remaining_bytes()) {
+ auto invoke_parser_fuzzer = fdp_.PickValueInArray<const std::function<void()>>({
+ [&]() { InvokeParser(); },
+ [&]() { InvokeInterfaceUtils(); },
+ [&]() { InvokeLimitParser(); },
+ });
+ invoke_parser_fuzzer();
+ }
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ InitParserFuzzer init_parser_fuzzer(data, size);
+ init_parser_fuzzer.Process();
+ return 0;
+}
diff --git a/init/fuzzer/init_property_fuzzer.cpp b/init/fuzzer/init_property_fuzzer.cpp
new file mode 100644
index 0000000..22df375
--- /dev/null
+++ b/init/fuzzer/init_property_fuzzer.cpp
@@ -0,0 +1,140 @@
+/*
+ * 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.
+ */
+#include <persistent_properties.h>
+#include <property_type.h>
+#include <sys/stat.h>
+#include <fstream>
+#include "fuzzer/FuzzedDataProvider.h"
+
+using namespace android;
+using namespace android::init;
+using android::init::persistent_property_filename;
+
+const std::string kTempDir = "/data/local/tmp/";
+const std::string kFuzzerPropertyFile = kTempDir + "persistent_properties";
+constexpr int32_t kMaxPropertyLength = 10;
+const std::string kPrefix = "persist.";
+const std::string kPropertyName = kPrefix + "sys.timezone";
+const std::string kPropertyValue = "America/Los_Angeles";
+const std::string kLegacyPropertyFile = "/data/property/persist.properties";
+const std::string kSizeSuffix[3] = {"g", "k", "m"};
+constexpr int32_t kMinNumStrings = 1;
+constexpr int32_t kMaxNumStrings = 10;
+
+enum PropertyType { STRING, BOOL, INT, UINT, DOUBLE, SIZE, ENUM, RANDOM, kMaxValue = RANDOM };
+
+class InitPropertyFuzzer {
+ public:
+ InitPropertyFuzzer(const uint8_t* data, size_t size) : fdp_(data, size){};
+ void process();
+
+ private:
+ void InvokeCheckType();
+ void InvokeWritePersistentProperty();
+ void RemoveFiles();
+ void CreateFuzzerPropertyFile(const std::string property_file);
+ FuzzedDataProvider fdp_;
+};
+
+void InitPropertyFuzzer::InvokeCheckType() {
+ std::string property_type;
+ std::string value;
+ int type = fdp_.ConsumeEnum<PropertyType>();
+ switch (type) {
+ case STRING:
+ value = fdp_.ConsumeRandomLengthString(kMaxPropertyLength);
+ property_type = "string";
+ break;
+ case BOOL:
+ value = fdp_.ConsumeBool();
+ property_type = "bool";
+ break;
+ case INT:
+ value = fdp_.ConsumeIntegral<int>();
+ property_type = "int";
+ break;
+ case UINT:
+ value = fdp_.ConsumeIntegral<uint_t>();
+ property_type = "uint";
+ break;
+ case DOUBLE:
+ value = fdp_.ConsumeFloatingPoint<double>();
+ property_type = "double";
+ break;
+ case SIZE:
+ value = fdp_.ConsumeIntegral<uint_t>();
+ value = value.append(fdp_.PickValueInArray(kSizeSuffix));
+ property_type = "size";
+ break;
+ case ENUM:
+ value = fdp_.ConsumeIntegral<uint_t>();
+ property_type = "enum";
+ break;
+ case RANDOM:
+ value = fdp_.ConsumeRandomLengthString(kMaxPropertyLength);
+ property_type = fdp_.ConsumeRandomLengthString(kMaxPropertyLength);
+ break;
+ }
+
+ CheckType(property_type, value);
+}
+
+void InitPropertyFuzzer::InvokeWritePersistentProperty() {
+ if (fdp_.ConsumeBool()) {
+ WritePersistentProperty(kPropertyName, kPropertyValue);
+ } else {
+ WritePersistentProperty((kPrefix + fdp_.ConsumeRandomLengthString(kMaxPropertyLength)),
+ fdp_.ConsumeRandomLengthString(kMaxPropertyLength));
+ }
+}
+
+void InitPropertyFuzzer::RemoveFiles() {
+ remove(kFuzzerPropertyFile.c_str());
+ remove(kLegacyPropertyFile.c_str());
+}
+
+void InitPropertyFuzzer::CreateFuzzerPropertyFile(const std::string property_file) {
+ std::ofstream out;
+ out.open(property_file, std::ios::binary | std::ofstream::trunc);
+ chmod(property_file.c_str(), S_IRWXU);
+ const int32_t numStrings = fdp_.ConsumeIntegralInRange(kMinNumStrings, kMaxNumStrings);
+ for (int32_t i = 0; i < numStrings; ++i) {
+ out << fdp_.ConsumeRandomLengthString(kMaxPropertyLength) << "\n";
+ }
+ out.close();
+}
+
+void InitPropertyFuzzer::process() {
+ persistent_property_filename = kFuzzerPropertyFile;
+ /* Property and legacy files are created using createFuzzerPropertyFile() and */
+ /* are used in the below APIs. Hence createFuzzerPropertyFile() is not a part */
+ /* of the lambda construct. */
+ CreateFuzzerPropertyFile(kFuzzerPropertyFile);
+ CreateFuzzerPropertyFile(kLegacyPropertyFile);
+ auto property_type = fdp_.PickValueInArray<const std::function<void()>>({
+ [&]() { InvokeCheckType(); },
+ [&]() { InvokeWritePersistentProperty(); },
+ [&]() { LoadPersistentProperties(); },
+ });
+ property_type();
+ RemoveFiles();
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ InitPropertyFuzzer initPropertyFuzzer(data, size);
+ initPropertyFuzzer.process();
+ return 0;
+}
diff --git a/init/fuzzer/init_ueventHandler_fuzzer.cpp b/init/fuzzer/init_ueventHandler_fuzzer.cpp
new file mode 100644
index 0000000..b6d5f8a
--- /dev/null
+++ b/init/fuzzer/init_ueventHandler_fuzzer.cpp
@@ -0,0 +1,123 @@
+/*
+ * 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.
+ */
+
+#include <devices.h>
+#include <firmware_handler.h>
+#include <fuzzer/FuzzedDataProvider.h>
+#include <modalias_handler.h>
+#include <sys/stat.h>
+#include <util.h>
+#include <fstream>
+
+using namespace android;
+using namespace android::init;
+constexpr int32_t kMaxBytes = 100;
+constexpr int32_t kMaxSize = 1000;
+constexpr int32_t kMinSize = 1;
+
+/*'HandleUevent' prefixes the path with '/sys' and hence this is required to point
+ * to'/data/local/tmp' dir.*/
+const std::string kPath = "/../data/local/tmp/";
+const std::string kPathPrefix = "/..";
+
+void MakeFile(FuzzedDataProvider* fdp, std::string s) {
+ std::ofstream out;
+ out.open(s, std::ios::binary | std::ofstream::trunc);
+ for (int32_t idx = 0; idx < fdp->ConsumeIntegralInRange(kMinSize, kMaxSize); ++idx) {
+ out << fdp->ConsumeRandomLengthString(kMaxBytes) << "\n";
+ }
+ out.close();
+}
+
+void CreateDir(std::string Directory, FuzzedDataProvider* fdp) {
+ std::string tmp = Directory.substr(kPathPrefix.length());
+ mkdir_recursive(android::base::Dirname(tmp.c_str()),
+ S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
+ MakeFile(fdp, tmp + "/data");
+ MakeFile(fdp, tmp + "/loading");
+}
+
+std::string SelectRandomString(FuzzedDataProvider* fdp, std::string s) {
+ if (fdp->ConsumeBool()) {
+ if (fdp->ConsumeBool()) {
+ return fdp->ConsumeRandomLengthString(kMaxBytes);
+ } else {
+ return s;
+ }
+ }
+ return "";
+}
+
+Uevent CreateUevent(FuzzedDataProvider* fdp) {
+ Uevent uevent;
+ uevent.action = SelectRandomString(fdp, "add");
+ uevent.subsystem = SelectRandomString(fdp, "firmware");
+ uevent.path = SelectRandomString(fdp, kPath + fdp->ConsumeRandomLengthString(kMaxBytes));
+ uevent.firmware = fdp->ConsumeBool() ? fdp->ConsumeRandomLengthString(kMaxBytes) : "";
+ uevent.partition_name = fdp->ConsumeBool() ? fdp->ConsumeRandomLengthString(kMaxBytes) : "";
+ uevent.device_name = fdp->ConsumeBool() ? fdp->ConsumeRandomLengthString(kMaxBytes) : "";
+ uevent.modalias = fdp->ConsumeBool() ? fdp->ConsumeRandomLengthString(kMaxBytes) : "";
+ uevent.partition_num = fdp->ConsumeIntegral<int32_t>();
+ uevent.major = fdp->ConsumeIntegral<int32_t>();
+ uevent.minor = fdp->ConsumeIntegral<int32_t>();
+ return uevent;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ FuzzedDataProvider fdp(data, size);
+ while (fdp.remaining_bytes()) {
+ auto invoke_uevent_handler_fuzzer = fdp.PickValueInArray<const std::function<void()>>({
+ [&]() {
+ std::vector<std::string> modalias_vector;
+ for (size_t idx = 0;
+ idx < fdp.ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize); ++idx) {
+ modalias_vector.push_back(fdp.ConsumeRandomLengthString(kMaxBytes));
+ }
+ ModaliasHandler modalias_handler = ModaliasHandler(modalias_vector);
+ modalias_handler.HandleUevent(CreateUevent(&fdp));
+ },
+ [&]() {
+ std::vector<ExternalFirmwareHandler> external_handlers;
+ std::vector<std::string> firmware_directories;
+ for (size_t idx = 0;
+ idx < fdp.ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize); ++idx) {
+ std::string devPath = fdp.ConsumeRandomLengthString(kMaxBytes);
+ uid_t uid = fdp.ConsumeIntegral<uid_t>();
+ gid_t gid = fdp.ConsumeIntegral<gid_t>();
+ std::string handlerPath = fdp.ConsumeRandomLengthString(kMaxBytes);
+ ExternalFirmwareHandler externalFirmwareHandler =
+ ExternalFirmwareHandler(devPath, uid, gid, handlerPath);
+ external_handlers.push_back(externalFirmwareHandler);
+ firmware_directories.push_back(fdp.ConsumeRandomLengthString(kMaxBytes));
+ }
+ FirmwareHandler firmware_handler =
+ FirmwareHandler(firmware_directories, external_handlers);
+ Uevent uevent = CreateUevent(&fdp);
+ if (fdp.ConsumeBool() && uevent.path.size() != 0 &&
+ uevent.path.find(kPath) == 0) {
+ CreateDir(uevent.path, &fdp);
+ firmware_handler.HandleUevent(uevent);
+ std::string s = uevent.path.substr(kPathPrefix.length());
+ remove(s.c_str());
+ } else {
+ firmware_handler.HandleUevent(uevent);
+ }
+ },
+ });
+ invoke_uevent_handler_fuzzer();
+ }
+ return 0;
+}
diff --git a/init/service.cpp b/init/service.cpp
index 8334732..a633048 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -340,9 +340,18 @@
siginfo.si_status == BIONIC_SIGNAL_ART_PROFILER && !upgraded_mte_;
if (should_upgrade_mte) {
- LOG(INFO) << "Upgrading service " << name_ << " to sync MTE";
- once_environment_vars_.emplace_back("BIONIC_MEMTAG_UPGRADE_SECS", "60");
- upgraded_mte_ = true;
+ constexpr int kDefaultUpgradeSecs = 60;
+ int secs = GetIntProperty("persist.device_config.memory_safety_native.upgrade_secs.default",
+ kDefaultUpgradeSecs);
+ secs = GetIntProperty(
+ "persist.device_config.memory_safety_native.upgrade_secs.service." + name_, secs);
+ if (secs > 0) {
+ LOG(INFO) << "Upgrading service " << name_ << " to sync MTE for " << secs << " seconds";
+ once_environment_vars_.emplace_back("BIONIC_MEMTAG_UPGRADE_SECS", std::to_string(secs));
+ upgraded_mte_ = true;
+ } else {
+ LOG(INFO) << "Not upgrading service " << name_ << " to sync MTE due to device config";
+ }
}
#endif
diff --git a/libsparse/simg_dump.py b/libsparse/simg_dump.py
index 8811a52..47537ca 100755
--- a/libsparse/simg_dump.py
+++ b/libsparse/simg_dump.py
@@ -158,7 +158,7 @@
curtype = format("Fill with 0x%08X" % (fill))
if showhash:
h = hashlib.sha1()
- data = fill_bin * (blk_sz / 4);
+ data = fill_bin * (blk_sz // 4);
for block in range(chunk_sz):
h.update(data)
curhash = h.hexdigest()
diff --git a/libstats/pull_rust/Android.bp b/libstats/pull_rust/Android.bp
index a3ef131..85a38f8 100644
--- a/libstats/pull_rust/Android.bp
+++ b/libstats/pull_rust/Android.bp
@@ -51,6 +51,7 @@
min_sdk_version: "apex_inherit",
apex_available: [
"//apex_available:platform",
+ "com.android.resolv",
"com.android.virt",
],
}
diff --git a/set-verity-state/.clang-format b/set-verity-state/.clang-format
deleted file mode 120000
index fd0645f..0000000
--- a/set-verity-state/.clang-format
+++ /dev/null
@@ -1 +0,0 @@
-../.clang-format-2
\ No newline at end of file
diff --git a/set-verity-state/Android.bp b/set-verity-state/Android.bp
deleted file mode 100644
index f40118b..0000000
--- a/set-verity-state/Android.bp
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2019 The Android Open Source Project
-
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-cc_binary {
- name: "set-verity-state",
- srcs: ["set-verity-state.cpp"],
- shared_libs: [
- "libbase",
- "libbinder",
- "libcrypto",
- "libcrypto_utils",
- "libfs_mgr_binder",
- "libutils",
- ],
- static_libs: [
- "libavb_user",
- ],
- header_libs: [
- "libcutils_headers",
- ],
-
- cflags: ["-Werror"],
- cppflags: [
- "-DALLOW_DISABLE_VERITY=0",
- ],
- product_variables: {
- debuggable: {
- cppflags: [
- "-UALLOW_DISABLE_VERITY",
- "-DALLOW_DISABLE_VERITY=1",
- ],
- },
- },
- symlinks: [
- "enable-verity",
- "disable-verity",
- ],
-}
diff --git a/set-verity-state/OWNERS b/set-verity-state/OWNERS
deleted file mode 100644
index e849450..0000000
--- a/set-verity-state/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-dvander@google.com
-yochiang@google.com
-bowgotsai@google.com
diff --git a/set-verity-state/set-verity-state.cpp b/set-verity-state/set-verity-state.cpp
deleted file mode 100644
index 2b9c0ca..0000000
--- a/set-verity-state/set-verity-state.cpp
+++ /dev/null
@@ -1,256 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <getopt.h>
-#include <stdio.h>
-
-#include <android-base/file.h>
-#include <android-base/logging.h>
-#include <android-base/properties.h>
-#include <binder/ProcessState.h>
-#include <cutils/android_reboot.h>
-#include <fs_mgr_overlayfs.h>
-#include <libavb_user/libavb_user.h>
-
-using namespace std::string_literals;
-
-namespace {
-
-void print_usage() {
- printf(
- "Usage:\n"
- "\tdisable-verity\n"
- "\tenable-verity\n"
- "\tset-verity-state [0|1]\n"
- "Options:\n"
- "\t-h --help\tthis help\n"
- "\t-R --reboot\tautomatic reboot if needed for new settings to take effect\n"
- "\t-v --verbose\tbe noisy\n");
-}
-
-#ifdef ALLOW_DISABLE_VERITY
-const bool kAllowDisableVerity = true;
-#else
-const bool kAllowDisableVerity = false;
-#endif
-
-static bool SetupOrTeardownOverlayfs(bool enable) {
- bool want_reboot = false;
- if (enable) {
- if (!fs_mgr_overlayfs_setup(nullptr, &want_reboot)) {
- LOG(ERROR) << "Overlayfs setup failed.";
- return want_reboot;
- }
- if (want_reboot) {
- printf("enabling overlayfs\n");
- }
- } else {
- auto rv = fs_mgr_overlayfs_teardown(nullptr, &want_reboot);
- if (rv == OverlayfsTeardownResult::Error) {
- LOG(ERROR) << "Overlayfs teardown failed.";
- return want_reboot;
- }
- if (rv == OverlayfsTeardownResult::Busy) {
- LOG(ERROR) << "Overlayfs is still active until reboot.";
- return true;
- }
- if (want_reboot) {
- printf("disabling overlayfs\n");
- }
- }
- return want_reboot;
-}
-
-/* Helper function to get A/B suffix, if any. If the device isn't
- * using A/B the empty string is returned. Otherwise either "_a",
- * "_b", ... is returned.
- */
-std::string get_ab_suffix() {
- return android::base::GetProperty("ro.boot.slot_suffix", "");
-}
-
-bool is_avb_device_locked() {
- return android::base::GetProperty("ro.boot.vbmeta.device_state", "") == "locked";
-}
-
-bool is_debuggable() {
- return android::base::GetBoolProperty("ro.debuggable", false);
-}
-
-bool is_using_avb() {
- // Figure out if we're using VB1.0 or VB2.0 (aka AVB) - by
- // contract, androidboot.vbmeta.digest is set by the bootloader
- // when using AVB).
- return !android::base::GetProperty("ro.boot.vbmeta.digest", "").empty();
-}
-
-[[noreturn]] void reboot(const std::string& name) {
- LOG(INFO) << "Rebooting device for new settings to take effect";
- ::sync();
- android::base::SetProperty(ANDROID_RB_PROPERTY, "reboot," + name);
- ::sleep(60);
- LOG(ERROR) << "Failed to reboot";
- ::exit(1);
-}
-
-struct SetVerityStateResult {
- bool success = false;
- bool want_reboot = false;
-};
-
-/* Use AVB to turn verity on/off */
-SetVerityStateResult SetVerityState(bool enable_verity) {
- std::string ab_suffix = get_ab_suffix();
- bool verity_enabled = false;
-
- if (is_avb_device_locked()) {
- LOG(ERROR) << "Device must be bootloader unlocked to change verity state";
- return {};
- }
-
- std::unique_ptr<AvbOps, decltype(&avb_ops_user_free)> ops(avb_ops_user_new(), &avb_ops_user_free);
- if (!ops) {
- LOG(ERROR) << "Error getting AVB ops";
- return {};
- }
-
- if (!avb_user_verity_get(ops.get(), ab_suffix.c_str(), &verity_enabled)) {
- LOG(ERROR) << "Error getting verity state";
- return {};
- }
-
- if ((verity_enabled && enable_verity) || (!verity_enabled && !enable_verity)) {
- LOG(INFO) << "Verity is already " << (verity_enabled ? "enabled" : "disabled");
- return {.success = true, .want_reboot = false};
- }
-
- if (!avb_user_verity_set(ops.get(), ab_suffix.c_str(), enable_verity)) {
- LOG(ERROR) << "Error setting verity state";
- return {};
- }
-
- LOG(INFO) << "Successfully " << (enable_verity ? "enabled" : "disabled") << " verity";
- return {.success = true, .want_reboot = true};
-}
-
-class MyLogger {
- public:
- explicit MyLogger(bool verbose) : verbose_(verbose) {}
-
- void operator()(android::base::LogId id, android::base::LogSeverity severity, const char* tag,
- const char* file, unsigned int line, const char* message) {
- // Hide log starting with '[fs_mgr]' unless it's an error.
- if (verbose_ || severity >= android::base::ERROR || message[0] != '[') {
- fprintf(stderr, "%s\n", message);
- }
- logd_(id, severity, tag, file, line, message);
- }
-
- private:
- android::base::LogdLogger logd_;
- bool verbose_;
-};
-
-} // namespace
-
-int main(int argc, char* argv[]) {
- bool auto_reboot = false;
- bool verbose = false;
-
- struct option longopts[] = {
- {"help", no_argument, nullptr, 'h'},
- {"reboot", no_argument, nullptr, 'R'},
- {"verbose", no_argument, nullptr, 'v'},
- {0, 0, nullptr, 0},
- };
- for (int opt; (opt = ::getopt_long(argc, argv, "hRv", longopts, nullptr)) != -1;) {
- switch (opt) {
- case 'h':
- print_usage();
- return 0;
- case 'R':
- auto_reboot = true;
- break;
- case 'v':
- verbose = true;
- break;
- default:
- print_usage();
- return 1;
- }
- }
-
- android::base::InitLogging(argv, MyLogger(verbose));
-
- bool enable_verity = false;
- const std::string progname = getprogname();
- if (progname == "enable-verity") {
- enable_verity = true;
- } else if (progname == "disable-verity") {
- enable_verity = false;
- } else if (optind < argc && (argv[optind] == "1"s || argv[optind] == "0"s)) {
- // progname "set-verity-state"
- enable_verity = (argv[optind] == "1"s);
- } else {
- print_usage();
- return 1;
- }
-
- if (!kAllowDisableVerity || !is_debuggable()) {
- errno = EPERM;
- PLOG(ERROR) << "Cannot disable/enable verity on user build";
- return 1;
- }
-
- if (getuid() != 0) {
- errno = EACCES;
- PLOG(ERROR) << "Must be running as root (adb root)";
- return 1;
- }
-
- if (!is_using_avb()) {
- LOG(ERROR) << "Expected AVB device, VB1.0 is no longer supported";
- return 1;
- }
-
- int exit_code = 0;
- bool want_reboot = false;
-
- auto ret = SetVerityState(enable_verity);
- if (ret.success) {
- want_reboot |= ret.want_reboot;
- } else {
- exit_code = 1;
- }
-
- // Disable any overlayfs unconditionally if we want verity enabled.
- // Enable overlayfs only if verity is successfully disabled or is already disabled.
- if (enable_verity || ret.success) {
- // Start a threadpool to service waitForService() callbacks as
- // fs_mgr_overlayfs_* might call waitForService() to get the image service.
- android::ProcessState::self()->startThreadPool();
- want_reboot |= SetupOrTeardownOverlayfs(!enable_verity);
- }
-
- if (want_reboot) {
- if (auto_reboot) {
- reboot(progname);
- }
- printf("Reboot the device for new settings to take effect\n");
- }
-
- return exit_code;
-}