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