Merge changes I732e5b8a,I4271909e
* changes:
libutils: RefBase DEBUG_REF love
libutils: DEBUG_* modes compile forever
diff --git a/fastboot/Android.bp b/fastboot/Android.bp
index b478e6e..eed49fa 100644
--- a/fastboot/Android.bp
+++ b/fastboot/Android.bp
@@ -342,6 +342,8 @@
targets: [
"dist_files",
"sdk",
+ "sdk-repo-platform-tools",
+ "sdk_repo",
"win_sdk",
],
},
diff --git a/fs_mgr/Android.bp b/fs_mgr/Android.bp
index 45cd3c0..bebf19e 100644
--- a/fs_mgr/Android.bp
+++ b/fs_mgr/Android.bp
@@ -223,7 +223,6 @@
"libcutils",
"libcrypto",
"libext4_utils",
- "libfec",
"libfs_mgr_binder",
"liblog",
"liblp",
diff --git a/fs_mgr/fs_mgr_overlayfs.cpp b/fs_mgr/fs_mgr_overlayfs.cpp
index df26d85..cc09d09 100644
--- a/fs_mgr/fs_mgr_overlayfs.cpp
+++ b/fs_mgr/fs_mgr_overlayfs.cpp
@@ -785,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;
@@ -797,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;
}
@@ -816,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;
@@ -831,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()) {
@@ -854,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_filesystem_available("f2fs")) {
- return "f2fs";
- }
- if (!access(kMkExt4.c_str(), X_OK) && fs_mgr_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() {
@@ -923,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;
@@ -1123,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)) {
@@ -1133,7 +1099,6 @@
if (!metadata) {
return false;
}
- *is_virtual_ab = !!(metadata->header.flags & LP_HEADER_FLAG_VIRTUAL_AB_DEVICE);
return true;
}
@@ -1146,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;
}
@@ -1180,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;
@@ -1195,12 +1151,12 @@
}
}
- 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);
}
#if ALLOW_ADBD_DISABLE_VERITY
@@ -1319,14 +1275,13 @@
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);
}
}
@@ -1565,8 +1520,7 @@
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);
}
}
@@ -1687,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);
@@ -1702,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();
}
diff --git a/fs_mgr/fs_mgr_remount.cpp b/fs_mgr/fs_mgr_remount.cpp
index 54c1c2c..2edaaad 100644
--- a/fs_mgr/fs_mgr_remount.cpp
+++ b/fs_mgr/fs_mgr_remount.cpp
@@ -35,7 +35,6 @@
#include <binder/IServiceManager.h>
#include <bootloader_message/bootloader_message.h>
#include <cutils/android_reboot.h>
-#include <fec/io.h>
#include <fs_mgr_overlayfs.h>
#include <fs_mgr_priv.h>
#include <fstab/fstab.h>
@@ -50,7 +49,7 @@
namespace {
-[[noreturn]] void usage(int exit_status) {
+void usage() {
LOG(INFO) << getprogname()
<< " [-h] [-R] [-T fstab_file] [partition]...\n"
"\t-h --help\tthis help\n"
@@ -62,8 +61,6 @@
"-R notwithstanding, verity must be disabled on partition(s).\n"
"-R within a DSU guest system reboots into the DSU instead of the host system,\n"
"this command would enable DSU (one-shot) if not already enabled.";
-
- ::exit(exit_status);
}
const std::string system_mount_point(const android::fs_mgr::FstabEntry& entry) {
@@ -116,15 +113,9 @@
} // namespace
-using namespace std::chrono_literals;
-
enum RemountStatus {
REMOUNT_SUCCESS = 0,
- NOT_USERDEBUG,
- BADARG,
- NOT_ROOT,
- NO_FSTAB,
- UNKNOWN_PARTITION,
+ UNKNOWN_PARTITION = 5,
INVALID_PARTITION,
VERITY_PARTITION,
BAD_OVERLAY,
@@ -281,23 +272,13 @@
if (!fs_mgr_is_verity_enabled(entry)) {
return REMOUNT_SUCCESS;
}
- if (android::base::GetProperty("ro.boot.vbmeta.device_state", "") == "locked") {
- return VERITY_PARTITION;
- }
-
- bool ok = false;
std::unique_ptr<AvbOps, decltype(&::avb_ops_user_free)> ops(avb_ops_user_new(),
&::avb_ops_user_free);
- if (ops) {
- auto suffix = android::base::GetProperty("ro.boot.slot_suffix", "");
- ok = avb_user_verity_set(ops.get(), suffix.c_str(), false);
+ if (!ops) {
+ return VERITY_PARTITION;
}
- if (!ok && fs_mgr_set_blk_ro(entry.blk_device, false)) {
- fec::io fh(entry.blk_device.c_str(), O_RDWR);
- ok = fh && fh.set_verity_status(false);
- }
- if (!ok) {
+ if (!avb_user_verity_set(ops.get(), fs_mgr_get_slot_suffix().c_str(), false)) {
return VERITY_PARTITION;
}
result->disabled_verity = true;
@@ -489,15 +470,20 @@
// Make sure we are root.
if (::getuid() != 0) {
LOG(ERROR) << "Not running as root. Try \"adb root\" first.";
- return NOT_ROOT;
+ return 1;
}
// If somehow this executable is delivered on a "user" build, it can
// not function, so providing a clear message to the caller rather than
// letting if fall through and provide a lot of confusing failure messages.
- if (!ALLOW_ADBD_DISABLE_VERITY || (android::base::GetProperty("ro.debuggable", "0") != "1")) {
- LOG(ERROR) << "only functions on userdebug or eng builds";
- return NOT_USERDEBUG;
+ if (!ALLOW_ADBD_DISABLE_VERITY || !android::base::GetBoolProperty("ro.debuggable", false)) {
+ LOG(ERROR) << "Device must be userdebug build";
+ return 1;
+ }
+
+ if (android::base::GetProperty("ro.boot.vbmeta.device_state", "") == "locked") {
+ LOG(ERROR) << "Device must be bootloader unlocked";
+ return 1;
}
const char* fstab_file = nullptr;
@@ -514,15 +500,16 @@
for (int opt; (opt = ::getopt_long(argc, argv, "hRT:v", longopts, nullptr)) != -1;) {
switch (opt) {
case 'h':
- usage(SUCCESS);
- break;
+ usage();
+ return 0;
case 'R':
auto_reboot = true;
break;
case 'T':
if (fstab_file) {
LOG(ERROR) << "Cannot supply two fstabs: -T " << fstab_file << " -T" << optarg;
- usage(BADARG);
+ usage();
+ return 1;
}
fstab_file = optarg;
break;
@@ -531,8 +518,8 @@
break;
default:
LOG(ERROR) << "Bad Argument -" << char(opt);
- usage(BADARG);
- break;
+ usage();
+ return 1;
}
}
@@ -549,7 +536,7 @@
Fstab fstab;
if (!ReadFstab(fstab_file, &fstab) || fstab.empty()) {
PLOG(ERROR) << "Failed to read fstab";
- return NO_FSTAB;
+ return 1;
}
RemountCheckResult check_result;
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/fuzzer/Android.bp b/init/fuzzer/Android.bp
new file mode 100644
index 0000000..c21a196
--- /dev/null
+++ b/init/fuzzer/Android.bp
@@ -0,0 +1,76 @@
+/*
+ * 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.
+ */
+package {
+ default_applicable_licenses: ["system_core_init_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/reboot.cpp b/init/reboot.cpp
index 880674c..4c27a56 100644
--- a/init/reboot.cpp
+++ b/init/reboot.cpp
@@ -608,7 +608,7 @@
if (sem_init(&reboot_semaphore, false, 0) == -1) {
// These should never fail, but if they do, skip the graceful reboot and reboot immediately.
LOG(ERROR) << "sem_init() fail and RebootSystem() return!";
- RebootSystem(cmd, reboot_target);
+ RebootSystem(cmd, reboot_target, reason);
}
// Start a thread to monitor init shutdown process
@@ -636,7 +636,7 @@
// worry about unmounting it.
if (!IsDataMounted("*")) {
sync();
- RebootSystem(cmd, reboot_target);
+ RebootSystem(cmd, reboot_target, reason);
abort();
}
@@ -769,7 +769,7 @@
LOG(INFO) << "Shutdown /data";
}
}
- RebootSystem(cmd, reboot_target);
+ RebootSystem(cmd, reboot_target, reason);
abort();
}
diff --git a/init/reboot_utils.cpp b/init/reboot_utils.cpp
index f8e1de0..e6b868e 100644
--- a/init/reboot_utils.cpp
+++ b/init/reboot_utils.cpp
@@ -106,7 +106,8 @@
return value == CAP_SET;
}
-void __attribute__((noreturn)) RebootSystem(unsigned int cmd, const std::string& rebootTarget) {
+void __attribute__((noreturn))
+RebootSystem(unsigned int cmd, const std::string& rebootTarget, const std::string& reboot_reason) {
LOG(INFO) << "Reboot ending, jumping to kernel";
if (!IsRebootCapable()) {
@@ -127,10 +128,12 @@
case ANDROID_RB_THERMOFF:
if (android::base::GetBoolProperty("ro.thermal_warmreset", false)) {
+ std::string reason = "shutdown,thermal";
+ if (!reboot_reason.empty()) reason = reboot_reason;
+
LOG(INFO) << "Try to trigger a warm reset for thermal shutdown";
- static constexpr const char kThermalShutdownTarget[] = "shutdown,thermal";
syscall(__NR_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
- LINUX_REBOOT_CMD_RESTART2, kThermalShutdownTarget);
+ LINUX_REBOOT_CMD_RESTART2, reason.c_str());
} else {
reboot(RB_POWER_OFF);
}
diff --git a/init/reboot_utils.h b/init/reboot_utils.h
index a0023b9..09e87ef 100644
--- a/init/reboot_utils.h
+++ b/init/reboot_utils.h
@@ -29,7 +29,8 @@
// so if any of the attempts to determine this fail, it will still return true.
bool IsRebootCapable();
// This is a wrapper around the actual reboot calls.
-void __attribute__((noreturn)) RebootSystem(unsigned int cmd, const std::string& reboot_target);
+void __attribute__((noreturn)) RebootSystem(unsigned int cmd, const std::string& reboot_target,
+ const std::string& reboot_reason = "");
void __attribute__((noreturn)) InitFatalReboot(int signal_number);
void InstallRebootSignalHandlers();
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",
],
}