fs_mgr: remount: add -R argument
The -R flag tells remount it can reboot to disable verity or to run fsck on an ext4 deduped filesystem, or both. Testing may include a manual component because adb-remount-test.sh needs to run from a device in an enable-verity state to test this. Only recognizes chained avb. Test: adb-remount-test.sh Bug: 122602260 Change-Id: I6ce4372532d9b933dcca9e2bec544d525b76c4d9
This commit is contained in:
parent
8c07db6a6b
commit
1188ce4e1d
3 changed files with 94 additions and 15 deletions
|
@ -115,10 +115,17 @@ cc_library_static {
|
|||
cc_binary {
|
||||
name: "remount",
|
||||
defaults: ["fs_mgr_defaults"],
|
||||
static_libs: [
|
||||
"libavb_user",
|
||||
],
|
||||
shared_libs: [
|
||||
"libbootloader_message",
|
||||
"libbase",
|
||||
"libfs_mgr",
|
||||
],
|
||||
header_libs: [
|
||||
"libcutils_headers",
|
||||
],
|
||||
srcs: [
|
||||
"fs_mgr_remount.cpp",
|
||||
],
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include <errno.h>
|
||||
#include <getopt.h>
|
||||
#include <libavb_user/libavb_user.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/types.h>
|
||||
|
@ -30,6 +31,8 @@
|
|||
#include <android-base/logging.h>
|
||||
#include <android-base/properties.h>
|
||||
#include <android-base/strings.h>
|
||||
#include <bootloader_message/bootloader_message.h>
|
||||
#include <cutils/android_reboot.h>
|
||||
#include <fs_mgr_overlayfs.h>
|
||||
#include <fs_mgr_priv.h>
|
||||
#include <fstab/fstab.h>
|
||||
|
@ -38,12 +41,13 @@ namespace {
|
|||
|
||||
[[noreturn]] void usage(int exit_status) {
|
||||
LOG(INFO) << getprogname()
|
||||
<< " [-h] [-T fstab_file]\n"
|
||||
<< " [-h] [-R] [-T fstab_file]\n"
|
||||
"\t-h --help\tthis help\n"
|
||||
"\t-R --reboot\tdisable verity & reboot to facilitate remount\n"
|
||||
"\t-T --fstab\tcustom fstab file location\n"
|
||||
"\n"
|
||||
"Remount all partitions read-write.\n"
|
||||
"Verity must be disabled.";
|
||||
"-R notwithstanding, verity must be disabled.";
|
||||
|
||||
::exit(exit_status);
|
||||
}
|
||||
|
@ -110,6 +114,18 @@ void MyLogger(android::base::LogId id, android::base::LogSeverity severity, cons
|
|||
logd(id, severity, tag, file, line, message);
|
||||
}
|
||||
|
||||
[[noreturn]] void reboot(bool dedupe) {
|
||||
if (dedupe) {
|
||||
LOG(INFO) << "The device will now reboot to recovery and attempt un-deduplication.";
|
||||
} else {
|
||||
LOG(INFO) << "Successfully disabled verity\nrebooting device";
|
||||
}
|
||||
::sync();
|
||||
android::base::SetProperty(ANDROID_RB_PROPERTY, dedupe ? "reboot,recovery" : "reboot,remount");
|
||||
::sleep(60);
|
||||
::exit(0); // SUCCESS
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
|
@ -136,14 +152,19 @@ int main(int argc, char* argv[]) {
|
|||
}
|
||||
|
||||
const char* fstab_file = nullptr;
|
||||
auto can_reboot = false;
|
||||
|
||||
struct option longopts[] = {
|
||||
{"fstab", required_argument, nullptr, 'T'},
|
||||
{"help", no_argument, nullptr, 'h'},
|
||||
{"reboot", no_argument, nullptr, 'R'},
|
||||
{0, 0, nullptr, 0},
|
||||
};
|
||||
for (int opt; (opt = ::getopt_long(argc, argv, "hT:", longopts, nullptr)) != -1;) {
|
||||
for (int opt; (opt = ::getopt_long(argc, argv, "hRT:", longopts, nullptr)) != -1;) {
|
||||
switch (opt) {
|
||||
case 'R':
|
||||
can_reboot = true;
|
||||
break;
|
||||
case 'T':
|
||||
if (fstab_file) {
|
||||
LOG(ERROR) << "Cannot supply two fstabs: -T " << fstab_file << " -T" << optarg;
|
||||
|
@ -200,11 +221,32 @@ int main(int argc, char* argv[]) {
|
|||
}
|
||||
|
||||
// Check verity and optionally setup overlayfs backing.
|
||||
auto reboot_later = false;
|
||||
for (auto it = partitions.begin(); it != partitions.end();) {
|
||||
auto& entry = *it;
|
||||
auto& mount_point = entry.mount_point;
|
||||
if (fs_mgr_is_verity_enabled(entry)) {
|
||||
LOG(ERROR) << "Verity enabled on " << mount_point << ", skipping";
|
||||
LOG(WARNING) << "Verity enabled on " << mount_point;
|
||||
if (can_reboot &&
|
||||
(android::base::GetProperty("ro.boot.vbmeta.devices_state", "") != "locked")) {
|
||||
if (AvbOps* ops = avb_ops_user_new()) {
|
||||
auto ret = avb_user_verity_set(
|
||||
ops, android::base::GetProperty("ro.boot.slot_suffix", "").c_str(),
|
||||
false);
|
||||
avb_ops_user_free(ops);
|
||||
if (ret) {
|
||||
if (fs_mgr_overlayfs_valid() == OverlayfsValidResult::kNotSupported) {
|
||||
retval = VERITY_PARTITION;
|
||||
// w/o overlayfs available, also check for dedupe
|
||||
reboot_later = true;
|
||||
++it;
|
||||
continue;
|
||||
}
|
||||
reboot(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
LOG(ERROR) << "Skipping " << mount_point;
|
||||
retval = VERITY_PARTITION;
|
||||
it = partitions.erase(it);
|
||||
continue;
|
||||
|
@ -278,23 +320,23 @@ int main(int argc, char* argv[]) {
|
|||
continue;
|
||||
}
|
||||
}
|
||||
PLOG(WARNING) << "failed to remount partition dev:" << blk_device << " mnt:" << mount_point;
|
||||
// If errno = EROFS at this point, we are dealing with r/o
|
||||
// filesystem types like squashfs, erofs or ext4 dedupe. We will
|
||||
// consider such a device that does not have CONFIG_OVERLAY_FS
|
||||
// in the kernel as a misconfigured and take no action.
|
||||
//
|
||||
// ext4 dedupe _can_ be worked around by performing a reboot into
|
||||
// recovery and fsck'ing. However the current decision is to not
|
||||
// reboot to reserve only one shell command to do so (reboot). In
|
||||
// the future, if this is a problem, a -R flag could be introduced
|
||||
// to give permission to do so and as a convenience also implement
|
||||
// verity disable operations. We will require this functionality
|
||||
// in order for adb remount to call this executable instead of its
|
||||
// current internal code that recognizes the -R flag and logistics.
|
||||
PLOG(ERROR) << "failed to remount partition dev:" << blk_device << " mnt:" << mount_point;
|
||||
// in the kernel as a misconfigured; except for ext4 dedupe.
|
||||
if ((errno == EROFS) && can_reboot) {
|
||||
const std::vector<std::string> msg = {"--fsck_unshare_blocks"};
|
||||
std::string err;
|
||||
if (write_bootloader_message(msg, &err)) reboot(true);
|
||||
LOG(ERROR) << "Failed to set bootloader message: " << err;
|
||||
errno = EROFS;
|
||||
}
|
||||
retval = REMOUNT_FAILED;
|
||||
}
|
||||
|
||||
if (reboot_later) reboot(false);
|
||||
|
||||
try_unmount_bionic(&mounts);
|
||||
|
||||
return retval;
|
||||
|
|
|
@ -617,6 +617,19 @@ if [ "orange" = "`get_property ro.boot.verifiedbootstate`" -a \
|
|||
adb_reboot &&
|
||||
adb_wait 2m
|
||||
}
|
||||
|
||||
echo "${GREEN}[ RUN ]${NORMAL} Testing adb shell su root remount -R command" >&2
|
||||
|
||||
adb_su remount -R </dev/null || true
|
||||
sleep 2
|
||||
adb_wait 2m ||
|
||||
die "waiting for device after remount -R `usb_status`"
|
||||
if [ "orange" != "`get_property ro.boot.verifiedbootstate`" -o \
|
||||
"2" = "`get_property partition.system.verified`" ]; then
|
||||
die "remount -R command failed"
|
||||
fi
|
||||
|
||||
echo "${GREEN}[ OK ]${NORMAL} adb shell su root remount -R command" >&2
|
||||
fi
|
||||
|
||||
echo "${GREEN}[ RUN ]${NORMAL} Testing kernel support for overlayfs" >&2
|
||||
|
@ -1173,6 +1186,23 @@ echo "${GREEN}[ OK ]${NORMAL} remount command works from scratch" >&2
|
|||
restore
|
||||
err=${?}
|
||||
|
||||
if [ ${err} = 0 ] && ${overlayfs_supported}; then
|
||||
echo "${GREEN}[ RUN ]${NORMAL} test 'adb remount -R'" >&2
|
||||
adb_root &&
|
||||
adb remount -R &&
|
||||
adb_wait 2m ||
|
||||
die "adb remount -R"
|
||||
if [ "orange" != "`get_property ro.boot.verifiedbootstate`" -o \
|
||||
"2" = "`get_property partition.system.verified`" ]; then
|
||||
die "remount -R command failed to disable verity"
|
||||
fi
|
||||
|
||||
echo "${GREEN}[ OK ]${NORMAL} 'adb remount -R' command" >&2
|
||||
|
||||
restore
|
||||
err=${?}
|
||||
fi
|
||||
|
||||
restore() {
|
||||
true
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue