xref: /aosp_15_r20/system/core/fs_mgr/fs_mgr_remount.cpp (revision 00c7fec1bb09f3284aad6a6f96d2f63dfc3650ad)
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. "
175                          "To forcibly end checkpointing, "
176                          "call 'vdc checkpoint commitChanges'. "
177                          "This can lead to data corruption if rolled back."
178                       << std::endl;
179             LOG(INFO) << "Waiting for checkpoint to complete before remounting...";
180         }
181         std::this_thread::sleep_for(4s);
182     }
183     return true;
184 }
185 
IsRemountable(Fstab & candidates,const FstabEntry & entry)186 static bool IsRemountable(Fstab& candidates, const FstabEntry& entry) {
187     if (entry.fs_mgr_flags.vold_managed || entry.fs_mgr_flags.recovery_only ||
188         entry.fs_mgr_flags.slot_select_other) {
189         return false;
190     }
191     if (!(entry.flags & MS_RDONLY)) {
192         return false;
193     }
194     if (entry.fs_type == "vfat") {
195         return false;
196     }
197     if (auto candidate_entry = GetEntryForMountPoint(&candidates, entry.mount_point)) {
198         return candidate_entry->fs_type == entry.fs_type;
199     }
200     return true;
201 }
202 
FindPartition(const Fstab & fstab,const std::string & partition)203 static Fstab::const_iterator FindPartition(const Fstab& fstab, const std::string& partition) {
204     Fstab mounts;
205     if (!android::fs_mgr::ReadFstabFromFile("/proc/mounts", &mounts)) {
206         LOG(ERROR) << "Failed to read /proc/mounts";
207         return fstab.end();
208     }
209 
210     for (auto iter = fstab.begin(); iter != fstab.end(); iter++) {
211         const auto mount_point = system_mount_point(*iter);
212         if (partition == mount_point || partition == android::base::Basename(mount_point)) {
213             // In case fstab has multiple entries, pick the one that matches the
214             // actual mounted filesystem type.
215             auto proc_mount_point = (iter->mount_point == "/system") ? "/" : iter->mount_point;
216             auto mounted = GetEntryForMountPoint(&mounts, proc_mount_point);
217             if (mounted && mounted->fs_type == iter->fs_type) {
218                 return iter;
219             }
220         }
221     }
222     return fstab.end();
223 }
224 
GetAllRemountablePartitions(Fstab & fstab)225 static Fstab GetAllRemountablePartitions(Fstab& fstab) {
226     auto candidates = fs_mgr_overlayfs_candidate_list(fstab);
227 
228     Fstab partitions;
229     for (const auto& entry : fstab) {
230         if (IsRemountable(candidates, entry)) {
231             partitions.emplace_back(entry);
232         }
233     }
234     return partitions;
235 }
236 
GetRemountList(const Fstab & fstab,const std::vector<std::string> & argv,Fstab * partitions)237 bool GetRemountList(const Fstab& fstab, const std::vector<std::string>& argv, Fstab* partitions) {
238     auto candidates = fs_mgr_overlayfs_candidate_list(fstab);
239 
240     for (const auto& arg : argv) {
241         std::string partition = arg;
242         if (partition == "/") {
243             partition = "/system";
244         }
245 
246         auto it = FindPartition(fstab, partition);
247         if (it == fstab.end()) {
248             LOG(ERROR) << "Unknown partition " << arg;
249             return false;
250         }
251 
252         const FstabEntry* entry = &*it;
253 
254         // If it's already remounted, include it so it gets gracefully skipped
255         // later on.
256         if (!fs_mgr_overlayfs_already_mounted(entry->mount_point) &&
257             !IsRemountable(candidates, *entry)) {
258             LOG(ERROR) << "Invalid partition " << arg;
259             return false;
260         }
261         if (GetEntryForMountPoint(partitions, entry->mount_point) != nullptr) {
262             continue;
263         }
264         partitions->emplace_back(*entry);
265     }
266 
267     return true;
268 }
269 
270 struct RemountCheckResult {
271     bool reboot_later = false;
272     bool setup_overlayfs = false;
273     bool disabled_verity = false;
274     bool verity_error = false;
275     bool remounted_anything = false;
276 };
277 
CheckOverlayfs(Fstab * partitions,RemountCheckResult * result)278 bool CheckOverlayfs(Fstab* partitions, RemountCheckResult* result) {
279     bool ok = true;
280     for (auto it = partitions->begin(); it != partitions->end();) {
281         auto& entry = *it;
282         const auto& mount_point = entry.mount_point;
283 
284         if (fs_mgr_wants_overlayfs(&entry)) {
285             bool want_reboot = false;
286             bool force = result->disabled_verity;
287             if (!fs_mgr_overlayfs_setup(*partitions, mount_point.c_str(), &want_reboot, force)) {
288                 LOG(ERROR) << "Overlayfs setup for " << mount_point << " failed, skipping";
289                 ok = false;
290                 it = partitions->erase(it);
291                 continue;
292             }
293             if (want_reboot) {
294                 LOG(INFO) << "Using overlayfs for " << mount_point;
295                 result->reboot_later = true;
296                 result->setup_overlayfs = true;
297             }
298         }
299         it++;
300     }
301     return ok;
302 }
303 
EnableDsuIfNeeded()304 bool EnableDsuIfNeeded() {
305     auto gsid = android::gsi::GetGsiService();
306     if (!gsid) {
307         return true;
308     }
309 
310     auto dsu_running = false;
311     if (auto status = gsid->isGsiRunning(&dsu_running); !status.isOk()) {
312         LOG(ERROR) << "Failed to get DSU running state: " << status;
313         return false;
314     }
315     auto dsu_enabled = false;
316     if (auto status = gsid->isGsiEnabled(&dsu_enabled); !status.isOk()) {
317         LOG(ERROR) << "Failed to get DSU enabled state: " << status;
318         return false;
319     }
320     if (dsu_running && !dsu_enabled) {
321         std::string dsu_slot;
322         if (auto status = gsid->getActiveDsuSlot(&dsu_slot); !status.isOk()) {
323             LOG(ERROR) << "Failed to get active DSU slot: " << status;
324             return false;
325         }
326         LOG(INFO) << "DSU is running but disabled, enable DSU so that we stay within the "
327                      "DSU guest system after reboot";
328         int error = 0;
329         if (auto status = gsid->enableGsi(/* oneShot = */ true, dsu_slot, &error); !status.isOk()) {
330             LOG(ERROR) << "Failed to enable DSU: " << status;
331             return false;
332         }
333         if (error != android::gsi::IGsiService::INSTALL_OK) {
334             LOG(ERROR) << "Failed to enable DSU, error code: " << error;
335             return false;
336         }
337         LOG(INFO) << "Successfully enabled DSU (one-shot mode)";
338     }
339     return true;
340 }
341 
RemountPartition(Fstab & fstab,Fstab & mounts,FstabEntry & entry)342 bool RemountPartition(Fstab& fstab, Fstab& mounts, FstabEntry& entry) {
343     // unlock the r/o key for the mount point device
344     if (entry.fs_mgr_flags.logical) {
345         fs_mgr_update_logical_partition(&entry);
346     }
347     auto blk_device = entry.blk_device;
348     auto mount_point = entry.mount_point;
349 
350     auto found = false;
351     for (auto it = mounts.rbegin(); it != mounts.rend(); ++it) {
352         auto& rentry = *it;
353         if (mount_point == rentry.mount_point) {
354             blk_device = rentry.blk_device;
355             found = true;
356             break;
357         }
358         // Find overlayfs mount point?
359         if ((mount_point == "/" && rentry.mount_point == "/system") ||
360             (mount_point == "/system" && rentry.mount_point == "/")) {
361             blk_device = rentry.blk_device;
362             mount_point = "/system";
363             found = true;
364             break;
365         }
366     }
367     if (!found) {
368         PLOG(INFO) << "skip unmounted partition dev:" << blk_device << " mnt:" << mount_point;
369         return true;
370     }
371     if (blk_device == "/dev/root") {
372         auto from_fstab = GetEntryForMountPoint(&fstab, mount_point);
373         if (from_fstab) blk_device = from_fstab->blk_device;
374     }
375     fs_mgr_set_blk_ro(blk_device, false);
376 
377     // Find system-as-root mount point?
378     if ((mount_point == "/system") && !GetEntryForMountPoint(&mounts, mount_point) &&
379         GetEntryForMountPoint(&mounts, "/")) {
380         mount_point = "/";
381     }
382 
383     // Now remount!
384     for (const auto& mnt_point : {mount_point, entry.mount_point}) {
385         if (::mount(blk_device.c_str(), mnt_point.c_str(), entry.fs_type.c_str(),
386                     MS_REMOUNT | MS_NOATIME, nullptr) == 0) {
387             LOG(INFO) << "Remounted " << mnt_point << " as RW";
388             return true;
389         }
390         if (errno != EINVAL || mount_point == entry.mount_point) {
391             break;
392         }
393     }
394 
395     PLOG(ERROR) << "failed to remount partition dev:" << blk_device << " mnt:" << mount_point;
396     return false;
397 }
398 
399 struct SetVerityStateResult {
400     bool success = false;
401     bool want_reboot = false;
402 };
403 
SetVerityState(bool enable_verity)404 SetVerityStateResult SetVerityState(bool enable_verity) {
405     const auto ab_suffix = android::base::GetProperty("ro.boot.slot_suffix", "");
406     std::unique_ptr<AvbOps, decltype(&avb_ops_user_free)> ops(avb_ops_user_new(),
407                                                               &avb_ops_user_free);
408     if (!ops) {
409         LOG(ERROR) << "Error getting AVB ops";
410         return {};
411     }
412     if (!avb_user_verity_set(ops.get(), ab_suffix.c_str(), enable_verity)) {
413         LOG(ERROR) << "Error setting verity state";
414         return {};
415     }
416     bool verification_enabled = false;
417     if (!avb_user_verification_get(ops.get(), ab_suffix.c_str(), &verification_enabled)) {
418         LOG(ERROR) << "Error getting verification state";
419         return {};
420     }
421     if (!verification_enabled) {
422         LOG(WARNING) << "AVB verification is disabled, "
423                      << (enable_verity ? "enabling" : "disabling")
424                      << " verity state may have no effect";
425         return {.success = true, .want_reboot = false};
426     }
427     const auto verity_mode = android::base::GetProperty("ro.boot.veritymode", "");
428     const bool was_enabled = (verity_mode != "disabled");
429     if ((was_enabled && enable_verity) || (!was_enabled && !enable_verity)) {
430         LOG(INFO) << "Verity is already " << (enable_verity ? "enabled" : "disabled");
431         return {.success = true, .want_reboot = false};
432     }
433     LOG(INFO) << "Successfully " << (enable_verity ? "enabled" : "disabled") << " verity";
434     return {.success = true, .want_reboot = true};
435 }
436 
SetupOrTeardownOverlayfs(bool enable)437 bool SetupOrTeardownOverlayfs(bool enable) {
438     bool want_reboot = false;
439     if (enable) {
440         Fstab fstab;
441         if (!ReadDefaultFstab(&fstab)) {
442             LOG(ERROR) << "Could not read fstab.";
443             return want_reboot;
444         }
445         if (!fs_mgr_overlayfs_setup(fstab, nullptr, &want_reboot)) {
446             LOG(ERROR) << "Overlayfs setup failed.";
447             return want_reboot;
448         }
449         if (want_reboot) {
450             printf("enabling overlayfs\n");
451         }
452     } else {
453         auto rv = fs_mgr_overlayfs_teardown(nullptr, &want_reboot);
454         if (rv == OverlayfsTeardownResult::Error) {
455             LOG(ERROR) << "Overlayfs teardown failed.";
456             return want_reboot;
457         }
458         if (rv == OverlayfsTeardownResult::Busy) {
459             LOG(ERROR) << "Overlayfs is still active until reboot.";
460             return true;
461         }
462         if (want_reboot) {
463             printf("disabling overlayfs\n");
464         }
465     }
466     return want_reboot;
467 }
468 
do_remount(Fstab & fstab,const std::vector<std::string> & partition_args,RemountCheckResult * check_result)469 bool do_remount(Fstab& fstab, const std::vector<std::string>& partition_args,
470                 RemountCheckResult* check_result) {
471     Fstab partitions;
472     if (partition_args.empty()) {
473         partitions = GetAllRemountablePartitions(fstab);
474     } else {
475         if (!GetRemountList(fstab, partition_args, &partitions)) {
476             return false;
477         }
478     }
479 
480     // Disable verity.
481     auto verity_result = SetVerityState(false /* enable_verity */);
482 
483     // Treat error as fatal and suggest reboot only if verity is enabled.
484     // TODO(b/260041315): We check the device mapper for any "<partition>-verity" device present
485     // instead of checking ro.boot.veritymode because emulator has incorrect property value.
486     bool must_disable_verity = false;
487     for (const auto& partition : partitions) {
488         if (fs_mgr_is_verity_enabled(partition)) {
489             must_disable_verity = true;
490             break;
491         }
492     }
493     if (must_disable_verity) {
494         if (!verity_result.success) {
495             return false;
496         }
497         if (verity_result.want_reboot) {
498             check_result->reboot_later = true;
499             check_result->disabled_verity = true;
500         }
501     }
502 
503     // Optionally setup overlayfs backing.
504     bool ok = CheckOverlayfs(&partitions, check_result);
505 
506     if (partitions.empty() || check_result->disabled_verity) {
507         if (partitions.empty()) {
508             LOG(WARNING) << "No remountable partitions were found.";
509         }
510         return ok;
511     }
512 
513     // Mount overlayfs.
514     if (!fs_mgr_overlayfs_mount_all(&partitions)) {
515         LOG(WARNING) << "Cannot mount overlayfs for some partitions";
516         // Continue regardless to handle raw remount case.
517     }
518 
519     // Get actual mounts _after_ overlayfs has been added.
520     android::fs_mgr::Fstab mounts;
521     if (!android::fs_mgr::ReadFstabFromFile("/proc/mounts", &mounts) || mounts.empty()) {
522         PLOG(ERROR) << "Failed to read /proc/mounts";
523         return false;
524     }
525 
526     // Remount selected partitions.
527     for (auto& entry : partitions) {
528         if (RemountPartition(fstab, mounts, entry)) {
529             check_result->remounted_anything = true;
530         } else {
531             ok = false;
532         }
533     }
534     return ok;
535 }
536 
537 }  // namespace
538 
main(int argc,char * argv[])539 int main(int argc, char* argv[]) {
540     // Do not use MyLogger() when running as clean_scratch_files, as stdout/stderr of daemon process
541     // are discarded.
542     if (argc > 0 && android::base::Basename(argv[0]) == "clean_scratch_files"s) {
543         android::fs_mgr::CleanupOldScratchFiles();
544         return EXIT_SUCCESS;
545     }
546 
547     android::base::InitLogging(argv, MyLogger(false /* verbose */));
548 
549     const char* fstab_file = nullptr;
550     bool auto_reboot = false;
551     bool verbose = false;
552     std::vector<std::string> partition_args;
553 
554     struct option longopts[] = {
555             {"fstab", required_argument, nullptr, 'T'},
556             {"help", no_argument, nullptr, 'h'},
557             {"reboot", no_argument, nullptr, 'R'},
558             {"verbose", no_argument, nullptr, 'v'},
559             {0, 0, nullptr, 0},
560     };
561     for (int opt; (opt = ::getopt_long(argc, argv, "hRT:v", longopts, nullptr)) != -1;) {
562         switch (opt) {
563             case 'h':
564                 usage();
565                 return EXIT_SUCCESS;
566             case 'R':
567                 auto_reboot = true;
568                 break;
569             case 'T':
570                 if (fstab_file) {
571                     LOG(ERROR) << "Cannot supply two fstabs: -T " << fstab_file << " -T " << optarg;
572                     usage();
573                     return EXIT_FAILURE;
574                 }
575                 fstab_file = optarg;
576                 break;
577             case 'v':
578                 verbose = true;
579                 break;
580             default:
581                 LOG(ERROR) << "Bad argument -" << char(opt);
582                 usage();
583                 return EXIT_FAILURE;
584         }
585     }
586 
587     if (verbose) {
588         android::base::SetLogger(MyLogger(verbose));
589     }
590 
591     bool remount = false;
592     bool enable_verity = false;
593     const std::string progname = getprogname();
594     if (progname == "enable-verity") {
595         enable_verity = true;
596     } else if (progname == "disable-verity") {
597         enable_verity = false;
598     } else if (progname == "set-verity-state") {
599         if (optind < argc && (argv[optind] == "1"s || argv[optind] == "0"s)) {
600             enable_verity = (argv[optind] == "1"s);
601         } else {
602             usage();
603             return EXIT_FAILURE;
604         }
605     } else {
606         remount = true;
607         for (; optind < argc; ++optind) {
608             partition_args.emplace_back(argv[optind]);
609         }
610     }
611 
612     // Make sure we are root.
613     if (const auto uid = ::getuid(); uid != AID_ROOT) {
614         // If requesting auto reboot, also try to auto gain root.
615         if (auto_reboot && uid == AID_SHELL && access("/system/xbin/su", F_OK) == 0) {
616             std::vector<char*> args{const_cast<char*>("/system/xbin/su"),
617                                     const_cast<char*>("root")};
618             for (int i = 0; i < argc; ++i) {
619                 args.push_back(argv[i]);
620             }
621             args.push_back(nullptr);
622             LOG(INFO) << "Attempting to gain root with \"su root\"";
623             execv(args[0], args.data());
624             PLOG(ERROR) << "Failed to execute \"su root\"";
625         }
626         LOG(ERROR) << "Not running as root. Try \"adb root\" first.";
627         return EXIT_FAILURE;
628     }
629 
630     // If somehow this executable is delivered on a "user" build, it can
631     // not function, so providing a clear message to the caller rather than
632     // letting if fall through and provide a lot of confusing failure messages.
633     if (!ALLOW_ADBD_DISABLE_VERITY || !android::base::GetBoolProperty("ro.debuggable", false)) {
634         LOG(ERROR) << "Device must be userdebug build";
635         return EXIT_FAILURE;
636     }
637 
638     if (android::base::GetProperty("ro.boot.verifiedbootstate", "") != "orange") {
639         LOG(ERROR) << "Device must be bootloader unlocked";
640         return EXIT_FAILURE;
641     }
642 
643     // Start a threadpool to service waitForService() callbacks as
644     // fs_mgr_overlayfs_* might call waitForService() to get the image service.
645     android::ProcessState::self()->startThreadPool();
646 
647     if (!remount) {
648         auto ret = SetVerityState(enable_verity);
649 
650         // Disable any overlayfs unconditionally if we want verity enabled.
651         // Enable overlayfs only if verity is successfully disabled or is already disabled.
652         if (enable_verity || ret.success) {
653             ret.want_reboot |= SetupOrTeardownOverlayfs(!enable_verity);
654         }
655 
656         if (ret.want_reboot) {
657             if (auto_reboot) {
658                 reboot(progname);
659             }
660             std::cout << "Reboot the device for new settings to take effect" << std::endl;
661         }
662         return ret.success ? EXIT_SUCCESS : EXIT_FAILURE;
663     }
664 
665     // Make sure checkpointing is disabled if necessary.
666     if (!VerifyCheckpointing()) {
667         return EXIT_FAILURE;
668     }
669 
670     // Read the selected fstab.
671     Fstab fstab;
672     if (!ReadFstab(fstab_file, &fstab) || fstab.empty()) {
673         PLOG(ERROR) << "Failed to read fstab";
674         return EXIT_FAILURE;
675     }
676 
677     RemountCheckResult check_result;
678     bool remount_success = do_remount(fstab, partition_args, &check_result);
679 
680     if (check_result.disabled_verity && check_result.setup_overlayfs) {
681         LOG(INFO) << "Verity disabled; overlayfs enabled.";
682     } else if (check_result.disabled_verity) {
683         LOG(INFO) << "Verity disabled.";
684     } else if (check_result.setup_overlayfs) {
685         LOG(INFO) << "Overlayfs enabled.";
686     }
687     if (remount_success && check_result.remounted_anything) {
688         LOG(INFO) << "Remount succeeded";
689     } else if (!remount_success) {
690         LOG(ERROR) << "Remount failed";
691     }
692     if (check_result.reboot_later) {
693         if (auto_reboot) {
694             // If (1) remount requires a reboot to take effect, (2) system is currently
695             // running a DSU guest and (3) DSU is disabled, then enable DSU so that the
696             // next reboot would not take us back to the host system but stay within
697             // the guest system.
698             if (!EnableDsuIfNeeded()) {
699                 LOG(ERROR) << "Unable to automatically enable DSU";
700                 return EXIT_FAILURE;
701             }
702             reboot("remount");
703         } else {
704             LOG(INFO) << "Now reboot your device for settings to take effect";
705         }
706         return EXIT_SUCCESS;
707     }
708     return remount_success ? EXIT_SUCCESS : EXIT_FAILURE;
709 }
710