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