1 /*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <errno.h>
18 #include <getopt.h>
19 #include <stdio.h>
20 #include <sys/mount.h>
21 #include <sys/types.h>
22 #include <sys/vfs.h>
23 #include <unistd.h>
24
25 #include <iostream>
26 #include <string>
27 #include <thread>
28 #include <utility>
29 #include <vector>
30
31 #include <android-base/file.h>
32 #include <android-base/logging.h>
33 #include <android-base/properties.h>
34 #include <android-base/strings.h>
35 #include <android/os/IVold.h>
36 #include <binder/IServiceManager.h>
37 #include <binder/ProcessState.h>
38 #include <bootloader_message/bootloader_message.h>
39 #include <cutils/android_reboot.h>
40 #include <fs_mgr_overlayfs.h>
41 #include <fs_mgr_priv.h>
42 #include <fstab/fstab.h>
43 #include <libavb_user/libavb_user.h>
44 #include <libgsi/libgsid.h>
45
46 #include "fs_mgr_priv_overlayfs.h"
47
48 using namespace std::literals;
49 using android::fs_mgr::Fstab;
50 using android::fs_mgr::FstabEntry;
51
52 namespace {
53
usage()54 void usage() {
55 const std::string progname = getprogname();
56 if (progname == "disable-verity" || progname == "enable-verity" ||
57 progname == "set-verity-state") {
58 std::cout << "Usage: disable-verity\n"
59 << " enable-verity\n"
60 << " set-verity-state [0|1]\n"
61 << R"(
62 Options:
63 -h --help this help
64 -R --reboot automatic reboot if needed for new settings to take effect
65 -v --verbose be noisy)"
66 << std::endl;
67 } else {
68 std::cout << "Usage: " << progname << " [-h] [-R] [-T fstab_file] [partition]...\n"
69 << R"(
70 Options:
71 -h --help this help
72 -R --reboot disable verity & reboot to facilitate remount
73 -v --verbose be noisy
74 -T --fstab custom fstab file location
75 partition specific partition(s) (empty does all)
76
77 Remount specified partition(s) read-write, by name or mount point.
78 -R notwithstanding, verity must be disabled on partition(s).
79 -R within a DSU guest system reboots into the DSU instead of the host system,
80 this command would enable DSU (one-shot) if not already enabled.)"
81 << std::endl;
82 }
83 }
84
system_mount_point(const android::fs_mgr::FstabEntry & entry)85 const std::string system_mount_point(const android::fs_mgr::FstabEntry& entry) {
86 if (entry.mount_point == "/") return "/system";
87 return entry.mount_point;
88 }
89
GetWrappedEntry(const Fstab & overlayfs_candidates,const FstabEntry & entry)90 const FstabEntry* GetWrappedEntry(const Fstab& overlayfs_candidates, const FstabEntry& entry) {
91 auto mount_point = system_mount_point(entry);
92 auto it = std::find_if(overlayfs_candidates.begin(), overlayfs_candidates.end(),
93 [&mount_point](const auto& entry) {
94 return android::base::StartsWith(mount_point,
95 system_mount_point(entry) + "/");
96 });
97 if (it == overlayfs_candidates.end()) return nullptr;
98 return &(*it);
99 }
100
101 class MyLogger {
102 public:
MyLogger(bool verbose)103 explicit MyLogger(bool verbose) : verbose_(verbose) {}
104
operator ()(android::base::LogId id,android::base::LogSeverity severity,const char * tag,const char * file,unsigned int line,const char * message)105 void operator()(android::base::LogId id, android::base::LogSeverity severity, const char* tag,
106 const char* file, unsigned int line, const char* message) {
107 // By default, print ERROR logs and logs of this program (does not start with '[')
108 // Print [libfs_mgr] INFO logs only if -v is given.
109 if (verbose_ || severity >= android::base::ERROR || message[0] != '[') {
110 fprintf(stderr, "%s\n", message);
111 }
112 logd_(id, severity, tag, file, line, message);
113 }
114
115 private:
116 android::base::LogdLogger logd_;
117 bool verbose_;
118 };
119
reboot(const std::string & name)120 [[noreturn]] void reboot(const std::string& name) {
121 LOG(INFO) << "Rebooting device for new settings to take effect";
122 ::sync();
123 android::base::SetProperty(ANDROID_RB_PROPERTY, "reboot," + name);
124 ::sleep(60);
125 LOG(ERROR) << "Failed to reboot";
126 ::exit(1);
127 }
128
GetVold()129 static android::sp<android::os::IVold> GetVold() {
130 while (true) {
131 if (auto sm = android::defaultServiceManager()) {
132 if (auto binder = sm->getService(android::String16("vold"))) {
133 if (auto vold = android::interface_cast<android::os::IVold>(binder)) {
134 return vold;
135 }
136 }
137 }
138 std::this_thread::sleep_for(2s);
139 }
140 }
141
ReadFstab(const char * fstab_file,android::fs_mgr::Fstab * fstab)142 static bool ReadFstab(const char* fstab_file, android::fs_mgr::Fstab* fstab) {
143 if (fstab_file) {
144 return android::fs_mgr::ReadFstabFromFile(fstab_file, fstab);
145 }
146 if (!android::fs_mgr::ReadDefaultFstab(fstab)) {
147 return false;
148 }
149
150 // Manufacture a / entry from /proc/mounts if missing.
151 if (!GetEntryForMountPoint(fstab, "/system") && !GetEntryForMountPoint(fstab, "/")) {
152 android::fs_mgr::Fstab mounts;
153 if (android::fs_mgr::ReadFstabFromFile("/proc/mounts", &mounts)) {
154 if (auto entry = GetEntryForMountPoint(&mounts, "/")) {
155 if (entry->fs_type != "rootfs") fstab->emplace_back(*entry);
156 }
157 }
158 }
159 return true;
160 }
161
VerifyCheckpointing()162 bool VerifyCheckpointing() {
163 if (!android::base::GetBoolProperty("ro.virtual_ab.enabled", false) &&
164 !android::base::GetBoolProperty("ro.virtual_ab.retrofit", false)) {
165 return true;
166 }
167
168 // Virtual A/B devices can use /data as backing storage; make sure we're
169 // not checkpointing.
170 auto vold = GetVold();
171 bool checkpointing = false;
172 if (!vold->isCheckpointing(&checkpointing).isOk()) {
173 LOG(ERROR) << "Could not determine checkpointing status.";
174 return false;
175 }
176 if (checkpointing) {
177 LOG(ERROR) << "Cannot use remount when a checkpoint is in progress.";
178 LOG(ERROR) << "To force end checkpointing, call 'vdc checkpoint commitChanges'";
179 LOG(ERROR) << "Warning: this can lead to data corruption if rolled back.";
180 return false;
181 }
182 return true;
183 }
184
IsRemountable(Fstab & candidates,const FstabEntry & entry)185 static bool IsRemountable(Fstab& candidates, const FstabEntry& entry) {
186 if (entry.fs_mgr_flags.vold_managed || entry.fs_mgr_flags.recovery_only ||
187 entry.fs_mgr_flags.slot_select_other) {
188 return false;
189 }
190 if (!(entry.flags & MS_RDONLY)) {
191 return false;
192 }
193 if (entry.fs_type == "vfat") {
194 return false;
195 }
196 if (auto candidate_entry = GetEntryForMountPoint(&candidates, entry.mount_point)) {
197 return candidate_entry->fs_type == entry.fs_type;
198 }
199 if (GetWrappedEntry(candidates, entry)) {
200 return false;
201 }
202 return true;
203 }
204
FindPartition(const Fstab & fstab,const std::string & partition)205 static Fstab::const_iterator FindPartition(const Fstab& fstab, const std::string& partition) {
206 Fstab mounts;
207 if (!android::fs_mgr::ReadFstabFromFile("/proc/mounts", &mounts)) {
208 LOG(ERROR) << "Failed to read /proc/mounts";
209 return fstab.end();
210 }
211
212 for (auto iter = fstab.begin(); iter != fstab.end(); iter++) {
213 const auto mount_point = system_mount_point(*iter);
214 if (partition == mount_point || partition == android::base::Basename(mount_point)) {
215 // In case fstab has multiple entries, pick the one that matches the
216 // actual mounted filesystem type.
217 auto proc_mount_point = (iter->mount_point == "/system") ? "/" : iter->mount_point;
218 auto mounted = GetEntryForMountPoint(&mounts, proc_mount_point);
219 if (mounted && mounted->fs_type == iter->fs_type) {
220 return iter;
221 }
222 }
223 }
224 return fstab.end();
225 }
226
GetAllRemountablePartitions(Fstab & fstab)227 static Fstab GetAllRemountablePartitions(Fstab& fstab) {
228 auto candidates = fs_mgr_overlayfs_candidate_list(fstab);
229
230 Fstab partitions;
231 for (const auto& entry : fstab) {
232 if (IsRemountable(candidates, entry)) {
233 partitions.emplace_back(entry);
234 }
235 }
236 return partitions;
237 }
238
GetRemountList(const Fstab & fstab,const std::vector<std::string> & argv,Fstab * partitions)239 bool GetRemountList(const Fstab& fstab, const std::vector<std::string>& argv, Fstab* partitions) {
240 auto candidates = fs_mgr_overlayfs_candidate_list(fstab);
241
242 for (const auto& arg : argv) {
243 std::string partition = arg;
244 if (partition == "/") {
245 partition = "/system";
246 }
247
248 auto it = FindPartition(fstab, partition);
249 if (it == fstab.end()) {
250 LOG(ERROR) << "Unknown partition " << arg;
251 return false;
252 }
253
254 const FstabEntry* entry = &*it;
255 if (auto wrap = GetWrappedEntry(candidates, *entry); wrap != nullptr) {
256 LOG(INFO) << "partition " << arg << " covered by overlayfs for " << wrap->mount_point
257 << ", switching";
258 entry = wrap;
259 }
260
261 // If it's already remounted, include it so it gets gracefully skipped
262 // later on.
263 if (!fs_mgr_overlayfs_already_mounted(entry->mount_point) &&
264 !IsRemountable(candidates, *entry)) {
265 LOG(ERROR) << "Invalid partition " << arg;
266 return false;
267 }
268 if (GetEntryForMountPoint(partitions, entry->mount_point) != nullptr) {
269 continue;
270 }
271 partitions->emplace_back(*entry);
272 }
273
274 return true;
275 }
276
277 struct RemountCheckResult {
278 bool reboot_later = false;
279 bool setup_overlayfs = false;
280 bool disabled_verity = false;
281 bool verity_error = false;
282 bool remounted_anything = false;
283 };
284
CheckOverlayfs(Fstab * partitions,RemountCheckResult * result)285 bool CheckOverlayfs(Fstab* partitions, RemountCheckResult* result) {
286 bool ok = true;
287 for (auto it = partitions->begin(); it != partitions->end();) {
288 auto& entry = *it;
289 const auto& mount_point = entry.mount_point;
290
291 if (fs_mgr_wants_overlayfs(&entry)) {
292 bool want_reboot = false;
293 bool force = result->disabled_verity;
294 if (!fs_mgr_overlayfs_setup(*partitions, mount_point.c_str(), &want_reboot, force)) {
295 LOG(ERROR) << "Overlayfs setup for " << mount_point << " failed, skipping";
296 ok = false;
297 it = partitions->erase(it);
298 continue;
299 }
300 if (want_reboot) {
301 LOG(INFO) << "Using overlayfs for " << mount_point;
302 result->reboot_later = true;
303 result->setup_overlayfs = true;
304 }
305 }
306 it++;
307 }
308 return ok;
309 }
310
EnableDsuIfNeeded()311 bool EnableDsuIfNeeded() {
312 auto gsid = android::gsi::GetGsiService();
313 if (!gsid) {
314 return true;
315 }
316
317 auto dsu_running = false;
318 if (auto status = gsid->isGsiRunning(&dsu_running); !status.isOk()) {
319 LOG(ERROR) << "Failed to get DSU running state: " << status;
320 return false;
321 }
322 auto dsu_enabled = false;
323 if (auto status = gsid->isGsiEnabled(&dsu_enabled); !status.isOk()) {
324 LOG(ERROR) << "Failed to get DSU enabled state: " << status;
325 return false;
326 }
327 if (dsu_running && !dsu_enabled) {
328 std::string dsu_slot;
329 if (auto status = gsid->getActiveDsuSlot(&dsu_slot); !status.isOk()) {
330 LOG(ERROR) << "Failed to get active DSU slot: " << status;
331 return false;
332 }
333 LOG(INFO) << "DSU is running but disabled, enable DSU so that we stay within the "
334 "DSU guest system after reboot";
335 int error = 0;
336 if (auto status = gsid->enableGsi(/* oneShot = */ true, dsu_slot, &error); !status.isOk()) {
337 LOG(ERROR) << "Failed to enable DSU: " << status;
338 return false;
339 }
340 if (error != android::gsi::IGsiService::INSTALL_OK) {
341 LOG(ERROR) << "Failed to enable DSU, error code: " << error;
342 return false;
343 }
344 LOG(INFO) << "Successfully enabled DSU (one-shot mode)";
345 }
346 return true;
347 }
348
RemountPartition(Fstab & fstab,Fstab & mounts,FstabEntry & entry)349 bool RemountPartition(Fstab& fstab, Fstab& mounts, FstabEntry& entry) {
350 // unlock the r/o key for the mount point device
351 if (entry.fs_mgr_flags.logical) {
352 fs_mgr_update_logical_partition(&entry);
353 }
354 auto blk_device = entry.blk_device;
355 auto mount_point = entry.mount_point;
356
357 auto found = false;
358 for (auto it = mounts.rbegin(); it != mounts.rend(); ++it) {
359 auto& rentry = *it;
360 if (mount_point == rentry.mount_point) {
361 blk_device = rentry.blk_device;
362 found = true;
363 break;
364 }
365 // Find overlayfs mount point?
366 if ((mount_point == "/" && rentry.mount_point == "/system") ||
367 (mount_point == "/system" && rentry.mount_point == "/")) {
368 blk_device = rentry.blk_device;
369 mount_point = "/system";
370 found = true;
371 break;
372 }
373 }
374 if (!found) {
375 PLOG(INFO) << "skip unmounted partition dev:" << blk_device << " mnt:" << mount_point;
376 return true;
377 }
378 if (blk_device == "/dev/root") {
379 auto from_fstab = GetEntryForMountPoint(&fstab, mount_point);
380 if (from_fstab) blk_device = from_fstab->blk_device;
381 }
382 fs_mgr_set_blk_ro(blk_device, false);
383
384 // Find system-as-root mount point?
385 if ((mount_point == "/system") && !GetEntryForMountPoint(&mounts, mount_point) &&
386 GetEntryForMountPoint(&mounts, "/")) {
387 mount_point = "/";
388 }
389
390 // Now remount!
391 for (const auto& mnt_point : {mount_point, entry.mount_point}) {
392 if (::mount(blk_device.c_str(), mnt_point.c_str(), entry.fs_type.c_str(), MS_REMOUNT,
393 nullptr) == 0) {
394 LOG(INFO) << "Remounted " << mnt_point << " as RW";
395 return true;
396 }
397 if (errno != EINVAL || mount_point == entry.mount_point) {
398 break;
399 }
400 }
401
402 PLOG(ERROR) << "failed to remount partition dev:" << blk_device << " mnt:" << mount_point;
403 return false;
404 }
405
406 struct SetVerityStateResult {
407 bool success = false;
408 bool want_reboot = false;
409 };
410
SetVerityState(bool enable_verity)411 SetVerityStateResult SetVerityState(bool enable_verity) {
412 const auto ab_suffix = android::base::GetProperty("ro.boot.slot_suffix", "");
413 std::unique_ptr<AvbOps, decltype(&avb_ops_user_free)> ops(avb_ops_user_new(),
414 &avb_ops_user_free);
415 if (!ops) {
416 LOG(ERROR) << "Error getting AVB ops";
417 return {};
418 }
419 if (!avb_user_verity_set(ops.get(), ab_suffix.c_str(), enable_verity)) {
420 LOG(ERROR) << "Error setting verity state";
421 return {};
422 }
423 bool verification_enabled = false;
424 if (!avb_user_verification_get(ops.get(), ab_suffix.c_str(), &verification_enabled)) {
425 LOG(ERROR) << "Error getting verification state";
426 return {};
427 }
428 if (!verification_enabled) {
429 LOG(WARNING) << "AVB verification is disabled, "
430 << (enable_verity ? "enabling" : "disabling")
431 << " verity state may have no effect";
432 return {.success = true, .want_reboot = false};
433 }
434 const auto verity_mode = android::base::GetProperty("ro.boot.veritymode", "");
435 const bool was_enabled = (verity_mode != "disabled");
436 if ((was_enabled && enable_verity) || (!was_enabled && !enable_verity)) {
437 LOG(INFO) << "Verity is already " << (enable_verity ? "enabled" : "disabled");
438 return {.success = true, .want_reboot = false};
439 }
440 LOG(INFO) << "Successfully " << (enable_verity ? "enabled" : "disabled") << " verity";
441 return {.success = true, .want_reboot = true};
442 }
443
SetupOrTeardownOverlayfs(bool enable)444 bool SetupOrTeardownOverlayfs(bool enable) {
445 bool want_reboot = false;
446 if (enable) {
447 Fstab fstab;
448 if (!ReadDefaultFstab(&fstab)) {
449 LOG(ERROR) << "Could not read fstab.";
450 return want_reboot;
451 }
452 if (!fs_mgr_overlayfs_setup(fstab, nullptr, &want_reboot)) {
453 LOG(ERROR) << "Overlayfs setup failed.";
454 return want_reboot;
455 }
456 if (want_reboot) {
457 printf("enabling overlayfs\n");
458 }
459 } else {
460 auto rv = fs_mgr_overlayfs_teardown(nullptr, &want_reboot);
461 if (rv == OverlayfsTeardownResult::Error) {
462 LOG(ERROR) << "Overlayfs teardown failed.";
463 return want_reboot;
464 }
465 if (rv == OverlayfsTeardownResult::Busy) {
466 LOG(ERROR) << "Overlayfs is still active until reboot.";
467 return true;
468 }
469 if (want_reboot) {
470 printf("disabling overlayfs\n");
471 }
472 }
473 return want_reboot;
474 }
475
do_remount(Fstab & fstab,const std::vector<std::string> & partition_args,RemountCheckResult * check_result)476 bool do_remount(Fstab& fstab, const std::vector<std::string>& partition_args,
477 RemountCheckResult* check_result) {
478 Fstab partitions;
479 if (partition_args.empty()) {
480 partitions = GetAllRemountablePartitions(fstab);
481 } else {
482 if (!GetRemountList(fstab, partition_args, &partitions)) {
483 return false;
484 }
485 }
486
487 // Disable verity.
488 auto verity_result = SetVerityState(false /* enable_verity */);
489
490 // Treat error as fatal and suggest reboot only if verity is enabled.
491 // TODO(b/260041315): We check the device mapper for any "<partition>-verity" device present
492 // instead of checking ro.boot.veritymode because emulator has incorrect property value.
493 bool must_disable_verity = false;
494 for (const auto& partition : partitions) {
495 if (fs_mgr_is_verity_enabled(partition)) {
496 must_disable_verity = true;
497 break;
498 }
499 }
500 if (must_disable_verity) {
501 if (!verity_result.success) {
502 return false;
503 }
504 if (verity_result.want_reboot) {
505 check_result->reboot_later = true;
506 check_result->disabled_verity = true;
507 }
508 }
509
510 // Optionally setup overlayfs backing.
511 bool ok = CheckOverlayfs(&partitions, check_result);
512
513 if (partitions.empty() || check_result->disabled_verity) {
514 if (partitions.empty()) {
515 LOG(WARNING) << "No remountable partitions were found.";
516 }
517 return ok;
518 }
519
520 // Mount overlayfs.
521 if (!fs_mgr_overlayfs_mount_all(&partitions)) {
522 LOG(WARNING) << "Cannot mount overlayfs for some partitions";
523 // Continue regardless to handle raw remount case.
524 }
525
526 // Get actual mounts _after_ overlayfs has been added.
527 android::fs_mgr::Fstab mounts;
528 if (!android::fs_mgr::ReadFstabFromFile("/proc/mounts", &mounts) || mounts.empty()) {
529 PLOG(ERROR) << "Failed to read /proc/mounts";
530 return false;
531 }
532
533 // Remount selected partitions.
534 for (auto& entry : partitions) {
535 if (RemountPartition(fstab, mounts, entry)) {
536 check_result->remounted_anything = true;
537 } else {
538 ok = false;
539 }
540 }
541 return ok;
542 }
543
544 } // namespace
545
main(int argc,char * argv[])546 int main(int argc, char* argv[]) {
547 // Do not use MyLogger() when running as clean_scratch_files, as stdout/stderr of daemon process
548 // are discarded.
549 if (argc > 0 && android::base::Basename(argv[0]) == "clean_scratch_files"s) {
550 android::fs_mgr::CleanupOldScratchFiles();
551 return EXIT_SUCCESS;
552 }
553
554 android::base::InitLogging(argv, MyLogger(false /* verbose */));
555
556 const char* fstab_file = nullptr;
557 bool auto_reboot = false;
558 bool verbose = false;
559 std::vector<std::string> partition_args;
560
561 struct option longopts[] = {
562 {"fstab", required_argument, nullptr, 'T'},
563 {"help", no_argument, nullptr, 'h'},
564 {"reboot", no_argument, nullptr, 'R'},
565 {"verbose", no_argument, nullptr, 'v'},
566 {0, 0, nullptr, 0},
567 };
568 for (int opt; (opt = ::getopt_long(argc, argv, "hRT:v", longopts, nullptr)) != -1;) {
569 switch (opt) {
570 case 'h':
571 usage();
572 return EXIT_SUCCESS;
573 case 'R':
574 auto_reboot = true;
575 break;
576 case 'T':
577 if (fstab_file) {
578 LOG(ERROR) << "Cannot supply two fstabs: -T " << fstab_file << " -T " << optarg;
579 usage();
580 return EXIT_FAILURE;
581 }
582 fstab_file = optarg;
583 break;
584 case 'v':
585 verbose = true;
586 break;
587 default:
588 LOG(ERROR) << "Bad argument -" << char(opt);
589 usage();
590 return EXIT_FAILURE;
591 }
592 }
593
594 if (verbose) {
595 android::base::SetLogger(MyLogger(verbose));
596 }
597
598 bool remount = false;
599 bool enable_verity = false;
600 const std::string progname = getprogname();
601 if (progname == "enable-verity") {
602 enable_verity = true;
603 } else if (progname == "disable-verity") {
604 enable_verity = false;
605 } else if (progname == "set-verity-state") {
606 if (optind < argc && (argv[optind] == "1"s || argv[optind] == "0"s)) {
607 enable_verity = (argv[optind] == "1"s);
608 } else {
609 usage();
610 return EXIT_FAILURE;
611 }
612 } else {
613 remount = true;
614 for (; optind < argc; ++optind) {
615 partition_args.emplace_back(argv[optind]);
616 }
617 }
618
619 // Make sure we are root.
620 if (::getuid() != 0) {
621 LOG(ERROR) << "Not running as root. Try \"adb root\" first.";
622 return EXIT_FAILURE;
623 }
624
625 // If somehow this executable is delivered on a "user" build, it can
626 // not function, so providing a clear message to the caller rather than
627 // letting if fall through and provide a lot of confusing failure messages.
628 if (!ALLOW_ADBD_DISABLE_VERITY || !android::base::GetBoolProperty("ro.debuggable", false)) {
629 LOG(ERROR) << "Device must be userdebug build";
630 return EXIT_FAILURE;
631 }
632
633 if (android::base::GetProperty("ro.boot.verifiedbootstate", "") != "orange") {
634 LOG(ERROR) << "Device must be bootloader unlocked";
635 return EXIT_FAILURE;
636 }
637
638 // Start a threadpool to service waitForService() callbacks as
639 // fs_mgr_overlayfs_* might call waitForService() to get the image service.
640 android::ProcessState::self()->startThreadPool();
641
642 if (!remount) {
643 auto ret = SetVerityState(enable_verity);
644
645 // Disable any overlayfs unconditionally if we want verity enabled.
646 // Enable overlayfs only if verity is successfully disabled or is already disabled.
647 if (enable_verity || ret.success) {
648 ret.want_reboot |= SetupOrTeardownOverlayfs(!enable_verity);
649 }
650
651 if (ret.want_reboot) {
652 if (auto_reboot) {
653 reboot(progname);
654 }
655 std::cout << "Reboot the device for new settings to take effect" << std::endl;
656 }
657 return ret.success ? EXIT_SUCCESS : EXIT_FAILURE;
658 }
659
660 // Make sure checkpointing is disabled if necessary.
661 if (!VerifyCheckpointing()) {
662 return EXIT_FAILURE;
663 }
664
665 // Read the selected fstab.
666 Fstab fstab;
667 if (!ReadFstab(fstab_file, &fstab) || fstab.empty()) {
668 PLOG(ERROR) << "Failed to read fstab";
669 return EXIT_FAILURE;
670 }
671
672 RemountCheckResult check_result;
673 bool remount_success = do_remount(fstab, partition_args, &check_result);
674
675 if (check_result.disabled_verity && check_result.setup_overlayfs) {
676 LOG(INFO) << "Verity disabled; overlayfs enabled.";
677 } else if (check_result.disabled_verity) {
678 LOG(INFO) << "Verity disabled.";
679 } else if (check_result.setup_overlayfs) {
680 LOG(INFO) << "Overlayfs enabled.";
681 }
682 if (remount_success && check_result.remounted_anything) {
683 LOG(INFO) << "Remount succeeded";
684 } else if (!remount_success) {
685 LOG(ERROR) << "Remount failed";
686 }
687 if (check_result.reboot_later) {
688 if (auto_reboot) {
689 // If (1) remount requires a reboot to take effect, (2) system is currently
690 // running a DSU guest and (3) DSU is disabled, then enable DSU so that the
691 // next reboot would not take us back to the host system but stay within
692 // the guest system.
693 if (!EnableDsuIfNeeded()) {
694 LOG(ERROR) << "Unable to automatically enable DSU";
695 return EXIT_FAILURE;
696 }
697 reboot("remount");
698 } else {
699 LOG(INFO) << "Now reboot your device for settings to take effect";
700 }
701 return EXIT_SUCCESS;
702 }
703 return remount_success ? EXIT_SUCCESS : EXIT_FAILURE;
704 }
705