1 /*
2  * Copyright (C) 2018 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 <dirent.h>
18 #include <errno.h>
19 #include <fcntl.h>
20 #include <linux/fs.h>
21 #include <selinux/selinux.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <sys/mount.h>
26 #include <sys/param.h>
27 #include <sys/stat.h>
28 #include <sys/statvfs.h>
29 #include <sys/types.h>
30 #include <sys/utsname.h>
31 #include <sys/vfs.h>
32 #include <unistd.h>
33 
34 #include <algorithm>
35 #include <memory>
36 #include <string>
37 #include <vector>
38 
39 #include <android-base/file.h>
40 #include <android-base/macros.h>
41 #include <android-base/properties.h>
42 #include <android-base/strings.h>
43 #include <android-base/unique_fd.h>
44 #include <ext4_utils/ext4_utils.h>
45 #include <fs_mgr.h>
46 #include <fs_mgr/file_wait.h>
47 #include <fs_mgr_dm_linear.h>
48 #include <fs_mgr_overlayfs.h>
49 #include <fstab/fstab.h>
50 #include <libdm/dm.h>
51 #include <libfiemap/image_manager.h>
52 #include <libgsi/libgsi.h>
53 #include <liblp/builder.h>
54 #include <liblp/liblp.h>
55 #include <storage_literals/storage_literals.h>
56 
57 #include "fs_mgr_priv.h"
58 #include "libfiemap/utility.h"
59 
60 using namespace std::literals;
61 using namespace android::dm;
62 using namespace android::fs_mgr;
63 using namespace android::storage_literals;
64 using android::fiemap::FilesystemHasReliablePinning;
65 using android::fiemap::IImageManager;
66 
67 namespace {
68 
fs_mgr_access(const std::string & path)69 bool fs_mgr_access(const std::string& path) {
70     auto save_errno = errno;
71     auto ret = access(path.c_str(), F_OK) == 0;
72     errno = save_errno;
73     return ret;
74 }
75 
76 // determine if a filesystem is available
fs_mgr_overlayfs_filesystem_available(const std::string & filesystem)77 bool fs_mgr_overlayfs_filesystem_available(const std::string& filesystem) {
78     std::string filesystems;
79     if (!android::base::ReadFileToString("/proc/filesystems", &filesystems)) return false;
80     return filesystems.find("\t" + filesystem + "\n") != std::string::npos;
81 }
82 
83 }  // namespace
84 
85 #if ALLOW_ADBD_DISABLE_VERITY == 0  // If we are a user build, provide stubs
86 
fs_mgr_overlayfs_candidate_list(const Fstab &)87 Fstab fs_mgr_overlayfs_candidate_list(const Fstab&) {
88     return {};
89 }
90 
fs_mgr_overlayfs_mount_all(Fstab *)91 bool fs_mgr_overlayfs_mount_all(Fstab*) {
92     return false;
93 }
94 
fs_mgr_overlayfs_setup(const char *,const char *,bool * change,bool)95 bool fs_mgr_overlayfs_setup(const char*, const char*, bool* change, bool) {
96     if (change) *change = false;
97     return false;
98 }
99 
fs_mgr_overlayfs_teardown(const char *,bool * change)100 bool fs_mgr_overlayfs_teardown(const char*, bool* change) {
101     if (change) *change = false;
102     return false;
103 }
104 
fs_mgr_overlayfs_is_setup()105 bool fs_mgr_overlayfs_is_setup() {
106     return false;
107 }
108 
109 namespace android {
110 namespace fs_mgr {
111 
MapScratchPartitionIfNeeded(Fstab *,const std::function<bool (const std::set<std::string> &)> &)112 void MapScratchPartitionIfNeeded(Fstab*, const std::function<bool(const std::set<std::string>&)>&) {
113 }
114 
CleanupOldScratchFiles()115 void CleanupOldScratchFiles() {}
116 
TeardownAllOverlayForMountPoint(const std::string &)117 void TeardownAllOverlayForMountPoint(const std::string&) {}
118 
119 }  // namespace fs_mgr
120 }  // namespace android
121 
122 #else  // ALLOW_ADBD_DISABLE_VERITY == 0
123 
124 namespace {
125 
fs_mgr_in_recovery()126 bool fs_mgr_in_recovery() {
127     // Check the existence of recovery binary instead of using the compile time
128     // macro, because first-stage-init is compiled with __ANDROID_RECOVERY__
129     // defined, albeit not in recovery. More details: system/core/init/README.md
130     return fs_mgr_access("/system/bin/recovery");
131 }
132 
fs_mgr_is_dsu_running()133 bool fs_mgr_is_dsu_running() {
134     // Since android::gsi::CanBootIntoGsi() or android::gsi::MarkSystemAsGsi() is
135     // never called in recovery, the return value of android::gsi::IsGsiRunning()
136     // is not well-defined. In this case, just return false as being in recovery
137     // implies not running a DSU system.
138     if (fs_mgr_in_recovery()) return false;
139     auto saved_errno = errno;
140     auto ret = android::gsi::IsGsiRunning();
141     errno = saved_errno;
142     return ret;
143 }
144 
145 // list of acceptable overlayfs backing storage
146 const auto kScratchMountPoint = "/mnt/scratch"s;
147 const auto kCacheMountPoint = "/cache"s;
148 
OverlayMountPoints()149 std::vector<const std::string> OverlayMountPoints() {
150     // Never fallback to legacy cache mount point if within a DSU system,
151     // because running a DSU system implies the device supports dynamic
152     // partitions, which means legacy cache mustn't be used.
153     if (fs_mgr_is_dsu_running()) {
154         return {kScratchMountPoint};
155     }
156     return {kScratchMountPoint, kCacheMountPoint};
157 }
158 
159 // Return true if everything is mounted, but before adb is started.  Right
160 // after 'trigger load_persist_props_action' is done.
fs_mgr_boot_completed()161 bool fs_mgr_boot_completed() {
162     return android::base::GetBoolProperty("ro.persistent_properties.ready", false);
163 }
164 
fs_mgr_is_dir(const std::string & path)165 bool fs_mgr_is_dir(const std::string& path) {
166     struct stat st;
167     return !stat(path.c_str(), &st) && S_ISDIR(st.st_mode);
168 }
169 
170 // Similar test as overlayfs workdir= validation in the kernel for read-write
171 // validation, except we use fs_mgr_work.  Covers space and storage issues.
fs_mgr_dir_is_writable(const std::string & path)172 bool fs_mgr_dir_is_writable(const std::string& path) {
173     auto test_directory = path + "/fs_mgr_work";
174     rmdir(test_directory.c_str());
175     auto ret = !mkdir(test_directory.c_str(), 0700);
176     return ret | !rmdir(test_directory.c_str());
177 }
178 
179 // At less than 1% or 8MB of free space return value of false,
180 // means we will try to wrap with overlayfs.
fs_mgr_filesystem_has_space(const std::string & mount_point)181 bool fs_mgr_filesystem_has_space(const std::string& mount_point) {
182     // If we have access issues to find out space remaining, return true
183     // to prevent us trying to override with overlayfs.
184     struct statvfs vst;
185     auto save_errno = errno;
186     if (statvfs(mount_point.c_str(), &vst)) {
187         errno = save_errno;
188         return true;
189     }
190 
191     static constexpr int kPercentThreshold = 1;                       // 1%
192     static constexpr unsigned long kSizeThreshold = 8 * 1024 * 1024;  // 8MB
193 
194     return (vst.f_bfree >= (vst.f_blocks * kPercentThreshold / 100)) &&
195            (static_cast<uint64_t>(vst.f_bfree) * vst.f_frsize) >= kSizeThreshold;
196 }
197 
198 const auto kPhysicalDevice = "/dev/block/by-name/"s;
199 constexpr char kScratchImageMetadata[] = "/metadata/gsi/remount/lp_metadata";
200 
201 // Note: this is meant only for recovery/first-stage init.
ScratchIsOnData()202 bool ScratchIsOnData() {
203     // The scratch partition of DSU is managed by gsid.
204     if (fs_mgr_is_dsu_running()) {
205         return false;
206     }
207     return fs_mgr_access(kScratchImageMetadata);
208 }
209 
fs_mgr_update_blk_device(FstabEntry * entry)210 bool fs_mgr_update_blk_device(FstabEntry* entry) {
211     if (entry->fs_mgr_flags.logical) {
212         fs_mgr_update_logical_partition(entry);
213     }
214     if (fs_mgr_access(entry->blk_device)) {
215         return true;
216     }
217     if (entry->blk_device != "/dev/root") {
218         return false;
219     }
220 
221     // special case for system-as-root (taimen and others)
222     auto blk_device = kPhysicalDevice + "system";
223     if (!fs_mgr_access(blk_device)) {
224         blk_device += fs_mgr_get_slot_suffix();
225         if (!fs_mgr_access(blk_device)) {
226             return false;
227         }
228     }
229     entry->blk_device = blk_device;
230     return true;
231 }
232 
fs_mgr_overlayfs_enabled(FstabEntry * entry)233 bool fs_mgr_overlayfs_enabled(FstabEntry* entry) {
234     // readonly filesystem, can not be mount -o remount,rw
235     // for squashfs, erofs or if free space is (near) zero making such a remount
236     // virtually useless, or if there are shared blocks that prevent remount,rw
237     if (!fs_mgr_filesystem_has_space(entry->mount_point)) {
238         return true;
239     }
240 
241     // blk_device needs to be setup so we can check superblock.
242     // If we fail here, because during init first stage and have doubts.
243     if (!fs_mgr_update_blk_device(entry)) {
244         return true;
245     }
246 
247     // check if ext4 de-dupe
248     auto save_errno = errno;
249     auto has_shared_blocks = fs_mgr_has_shared_blocks(entry->mount_point, entry->blk_device);
250     if (!has_shared_blocks && (entry->mount_point == "/system")) {
251         has_shared_blocks = fs_mgr_has_shared_blocks("/", entry->blk_device);
252     }
253     errno = save_errno;
254     return has_shared_blocks;
255 }
256 
fs_mgr_rm_all(const std::string & path,bool * change=nullptr,int level=0)257 bool fs_mgr_rm_all(const std::string& path, bool* change = nullptr, int level = 0) {
258     auto save_errno = errno;
259     std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(path.c_str()), closedir);
260     if (!dir) {
261         if (errno == ENOENT) {
262             errno = save_errno;
263             return true;
264         }
265         PERROR << "opendir " << path << " depth=" << level;
266         if ((errno == EPERM) && (level != 0)) {
267             errno = save_errno;
268             return true;
269         }
270         return false;
271     }
272     dirent* entry;
273     auto ret = true;
274     while ((entry = readdir(dir.get()))) {
275         if (("."s == entry->d_name) || (".."s == entry->d_name)) continue;
276         auto file = path + "/" + entry->d_name;
277         if (entry->d_type == DT_UNKNOWN) {
278             struct stat st;
279             save_errno = errno;
280             if (!lstat(file.c_str(), &st) && (st.st_mode & S_IFDIR)) entry->d_type = DT_DIR;
281             errno = save_errno;
282         }
283         if (entry->d_type == DT_DIR) {
284             ret &= fs_mgr_rm_all(file, change, level + 1);
285             if (!rmdir(file.c_str())) {
286                 if (change) *change = true;
287             } else {
288                 if (errno != ENOENT) ret = false;
289                 PERROR << "rmdir " << file << " depth=" << level;
290             }
291             continue;
292         }
293         if (!unlink(file.c_str())) {
294             if (change) *change = true;
295         } else {
296             if (errno != ENOENT) ret = false;
297             PERROR << "rm " << file << " depth=" << level;
298         }
299     }
300     return ret;
301 }
302 
303 const auto kUpperName = "upper"s;
304 const auto kWorkName = "work"s;
305 const auto kOverlayTopDir = "/overlay"s;
306 
fs_mgr_get_overlayfs_candidate(const std::string & mount_point)307 std::string fs_mgr_get_overlayfs_candidate(const std::string& mount_point) {
308     if (!fs_mgr_is_dir(mount_point)) return "";
309     const auto base = android::base::Basename(mount_point) + "/";
310     for (const auto& overlay_mount_point : OverlayMountPoints()) {
311         auto dir = overlay_mount_point + kOverlayTopDir + "/" + base;
312         auto upper = dir + kUpperName;
313         if (!fs_mgr_is_dir(upper)) continue;
314         auto work = dir + kWorkName;
315         if (!fs_mgr_is_dir(work)) continue;
316         if (!fs_mgr_dir_is_writable(work)) continue;
317         return dir;
318     }
319     return "";
320 }
321 
322 const auto kLowerdirOption = "lowerdir="s;
323 const auto kUpperdirOption = "upperdir="s;
324 
325 // default options for mount_point, returns empty string for none available.
fs_mgr_get_overlayfs_options(const std::string & mount_point)326 std::string fs_mgr_get_overlayfs_options(const std::string& mount_point) {
327     auto candidate = fs_mgr_get_overlayfs_candidate(mount_point);
328     if (candidate.empty()) return "";
329     auto ret = kLowerdirOption + mount_point + "," + kUpperdirOption + candidate + kUpperName +
330                ",workdir=" + candidate + kWorkName;
331     if (fs_mgr_overlayfs_valid() == OverlayfsValidResult::kOverrideCredsRequired) {
332         ret += ",override_creds=off";
333     }
334     return ret;
335 }
336 
fs_mgr_mount_point(const std::string & mount_point)337 const std::string fs_mgr_mount_point(const std::string& mount_point) {
338     if ("/"s != mount_point) return mount_point;
339     return "/system";
340 }
341 
fs_mgr_rw_access(const std::string & path)342 bool fs_mgr_rw_access(const std::string& path) {
343     if (path.empty()) return false;
344     auto save_errno = errno;
345     auto ret = access(path.c_str(), R_OK | W_OK) == 0;
346     errno = save_errno;
347     return ret;
348 }
349 
fs_mgr_overlayfs_already_mounted(const std::string & mount_point,bool overlay_only=true)350 bool fs_mgr_overlayfs_already_mounted(const std::string& mount_point, bool overlay_only = true) {
351     Fstab fstab;
352     auto save_errno = errno;
353     if (!ReadFstabFromFile("/proc/mounts", &fstab)) {
354         return false;
355     }
356     errno = save_errno;
357     const auto lowerdir = kLowerdirOption + mount_point;
358     for (const auto& entry : fstab) {
359         if (overlay_only && "overlay" != entry.fs_type && "overlayfs" != entry.fs_type) continue;
360         if (mount_point != entry.mount_point) continue;
361         if (!overlay_only) return true;
362         const auto options = android::base::Split(entry.fs_options, ",");
363         for (const auto& opt : options) {
364             if (opt == lowerdir) {
365                 return true;
366             }
367         }
368     }
369     return false;
370 }
371 
fs_mgr_wants_overlayfs(FstabEntry * entry)372 bool fs_mgr_wants_overlayfs(FstabEntry* entry) {
373     // Don't check entries that are managed by vold.
374     if (entry->fs_mgr_flags.vold_managed || entry->fs_mgr_flags.recovery_only) return false;
375 
376     // *_other doesn't want overlayfs.
377     if (entry->fs_mgr_flags.slot_select_other) return false;
378 
379     // Only concerned with readonly partitions.
380     if (!(entry->flags & MS_RDONLY)) return false;
381 
382     // If unbindable, do not allow overlayfs as this could expose us to
383     // security issues.  On Android, this could also be used to turn off
384     // the ability to overlay an otherwise acceptable filesystem since
385     // /system and /vendor are never bound(sic) to.
386     if (entry->flags & MS_UNBINDABLE) return false;
387 
388     if (!fs_mgr_overlayfs_enabled(entry)) return false;
389 
390     return true;
391 }
392 constexpr char kOverlayfsFileContext[] = "u:object_r:overlayfs_file:s0";
393 
fs_mgr_overlayfs_setup_dir(const std::string & dir,std::string * overlay,bool * change)394 bool fs_mgr_overlayfs_setup_dir(const std::string& dir, std::string* overlay, bool* change) {
395     auto ret = true;
396     auto top = dir + kOverlayTopDir;
397     if (setfscreatecon(kOverlayfsFileContext)) {
398         ret = false;
399         PERROR << "setfscreatecon " << kOverlayfsFileContext;
400     }
401     auto save_errno = errno;
402     if (!mkdir(top.c_str(), 0755)) {
403         if (change) *change = true;
404     } else if (errno != EEXIST) {
405         ret = false;
406         PERROR << "mkdir " << top;
407     } else {
408         errno = save_errno;
409     }
410     setfscreatecon(nullptr);
411 
412     if (overlay) *overlay = std::move(top);
413     return ret;
414 }
415 
fs_mgr_overlayfs_setup_one(const std::string & overlay,const std::string & mount_point,bool * change)416 bool fs_mgr_overlayfs_setup_one(const std::string& overlay, const std::string& mount_point,
417                                 bool* change) {
418     auto ret = true;
419     if (fs_mgr_overlayfs_already_mounted(mount_point)) return ret;
420     auto fsrec_mount_point = overlay + "/" + android::base::Basename(mount_point) + "/";
421 
422     if (setfscreatecon(kOverlayfsFileContext)) {
423         ret = false;
424         PERROR << "setfscreatecon " << kOverlayfsFileContext;
425     }
426     auto save_errno = errno;
427     if (!mkdir(fsrec_mount_point.c_str(), 0755)) {
428         if (change) *change = true;
429     } else if (errno != EEXIST) {
430         ret = false;
431         PERROR << "mkdir " << fsrec_mount_point;
432     } else {
433         errno = save_errno;
434     }
435 
436     save_errno = errno;
437     if (!mkdir((fsrec_mount_point + kWorkName).c_str(), 0755)) {
438         if (change) *change = true;
439     } else if (errno != EEXIST) {
440         ret = false;
441         PERROR << "mkdir " << fsrec_mount_point << kWorkName;
442     } else {
443         errno = save_errno;
444     }
445     setfscreatecon(nullptr);
446 
447     auto new_context = fs_mgr_get_context(mount_point);
448     if (!new_context.empty() && setfscreatecon(new_context.c_str())) {
449         ret = false;
450         PERROR << "setfscreatecon " << new_context;
451     }
452     auto upper = fsrec_mount_point + kUpperName;
453     save_errno = errno;
454     if (!mkdir(upper.c_str(), 0755)) {
455         if (change) *change = true;
456     } else if (errno != EEXIST) {
457         ret = false;
458         PERROR << "mkdir " << upper;
459     } else {
460         errno = save_errno;
461     }
462     if (!new_context.empty()) setfscreatecon(nullptr);
463 
464     return ret;
465 }
466 
fs_mgr_overlayfs_slot_number()467 uint32_t fs_mgr_overlayfs_slot_number() {
468     return SlotNumberForSlotSuffix(fs_mgr_get_slot_suffix());
469 }
470 
fs_mgr_overlayfs_super_device(uint32_t slot_number)471 std::string fs_mgr_overlayfs_super_device(uint32_t slot_number) {
472     return kPhysicalDevice + fs_mgr_get_super_partition_name(slot_number);
473 }
474 
fs_mgr_overlayfs_has_logical(const Fstab & fstab)475 bool fs_mgr_overlayfs_has_logical(const Fstab& fstab) {
476     for (const auto& entry : fstab) {
477         if (entry.fs_mgr_flags.logical) {
478             return true;
479         }
480     }
481     return false;
482 }
483 
fs_mgr_overlayfs_umount_scratch()484 void fs_mgr_overlayfs_umount_scratch() {
485     // Lazy umount will allow us to move on and possibly later
486     // establish a new fresh mount without requiring a reboot should
487     // the developer wish to restart.  Old references should melt
488     // away or have no data.  Main goal is to shut the door on the
489     // current overrides with an expectation of a subsequent reboot,
490     // thus any errors here are ignored.
491     umount2(kScratchMountPoint.c_str(), MNT_DETACH);
492     LINFO << "umount(" << kScratchMountPoint << ")";
493     rmdir(kScratchMountPoint.c_str());
494 }
495 
fs_mgr_overlayfs_teardown_scratch(const std::string & overlay,bool * change)496 bool fs_mgr_overlayfs_teardown_scratch(const std::string& overlay, bool* change) {
497     // umount and delete kScratchMountPoint storage if we have logical partitions
498     if (overlay != kScratchMountPoint) return true;
499 
500     // Validation check.
501     if (fs_mgr_is_dsu_running()) {
502         LERROR << "Destroying DSU scratch is not allowed.";
503         return false;
504     }
505 
506     auto save_errno = errno;
507     if (fs_mgr_overlayfs_already_mounted(kScratchMountPoint, false)) {
508         fs_mgr_overlayfs_umount_scratch();
509     }
510 
511     const auto partition_name = android::base::Basename(kScratchMountPoint);
512 
513     auto images = IImageManager::Open("remount", 10s);
514     if (images && images->BackingImageExists(partition_name)) {
515 #if defined __ANDROID_RECOVERY__
516         if (!images->DisableImage(partition_name)) {
517             return false;
518         }
519 #else
520         if (!images->UnmapImageIfExists(partition_name) ||
521             !images->DeleteBackingImage(partition_name)) {
522             return false;
523         }
524 #endif
525     }
526 
527     auto slot_number = fs_mgr_overlayfs_slot_number();
528     auto super_device = fs_mgr_overlayfs_super_device(slot_number);
529     if (!fs_mgr_rw_access(super_device)) return true;
530 
531     auto builder = MetadataBuilder::New(super_device, slot_number);
532     if (!builder) {
533         errno = save_errno;
534         return true;
535     }
536     if (builder->FindPartition(partition_name) == nullptr) {
537         errno = save_errno;
538         return true;
539     }
540     builder->RemovePartition(partition_name);
541     auto metadata = builder->Export();
542     if (metadata && UpdatePartitionTable(super_device, *metadata.get(), slot_number)) {
543         if (change) *change = true;
544         if (!DestroyLogicalPartition(partition_name)) return false;
545     } else {
546         LERROR << "delete partition " << overlay;
547         return false;
548     }
549     errno = save_errno;
550     return true;
551 }
552 
fs_mgr_overlayfs_teardown_one(const std::string & overlay,const std::string & mount_point,bool * change,bool * should_destroy_scratch=nullptr)553 bool fs_mgr_overlayfs_teardown_one(const std::string& overlay, const std::string& mount_point,
554                                    bool* change, bool* should_destroy_scratch = nullptr) {
555     const auto top = overlay + kOverlayTopDir;
556 
557     if (!fs_mgr_access(top)) {
558         if (should_destroy_scratch) *should_destroy_scratch = true;
559         return true;
560     }
561 
562     auto cleanup_all = mount_point.empty();
563     const auto partition_name = android::base::Basename(mount_point);
564     const auto oldpath = top + (cleanup_all ? "" : ("/" + partition_name));
565     const auto newpath = cleanup_all ? overlay + "/." + kOverlayTopDir.substr(1) + ".teardown"
566                                      : top + "/." + partition_name + ".teardown";
567     auto ret = fs_mgr_rm_all(newpath);
568     auto save_errno = errno;
569     if (!rename(oldpath.c_str(), newpath.c_str())) {
570         if (change) *change = true;
571     } else if (errno != ENOENT) {
572         ret = false;
573         PERROR << "mv " << oldpath << " " << newpath;
574     } else {
575         errno = save_errno;
576     }
577     ret &= fs_mgr_rm_all(newpath, change);
578     save_errno = errno;
579     if (!rmdir(newpath.c_str())) {
580         if (change) *change = true;
581     } else if (errno != ENOENT) {
582         ret = false;
583         PERROR << "rmdir " << newpath;
584     } else {
585         errno = save_errno;
586     }
587     if (!cleanup_all) {
588         save_errno = errno;
589         if (!rmdir(top.c_str())) {
590             if (change) *change = true;
591             cleanup_all = true;
592         } else if (errno == ENOTEMPTY) {
593             cleanup_all = true;
594             // cleanup all if the content is all hidden (leading .)
595             std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(top.c_str()), closedir);
596             if (!dir) {
597                 PERROR << "opendir " << top;
598             } else {
599                 dirent* entry;
600                 while ((entry = readdir(dir.get()))) {
601                     if (entry->d_name[0] != '.') {
602                         cleanup_all = false;
603                         break;
604                     }
605                 }
606             }
607             errno = save_errno;
608         } else if (errno == ENOENT) {
609             cleanup_all = true;
610             errno = save_errno;
611         } else {
612             ret = false;
613             PERROR << "rmdir " << top;
614         }
615     }
616     if (should_destroy_scratch) *should_destroy_scratch = cleanup_all;
617     return ret;
618 }
619 
fs_mgr_overlayfs_set_shared_mount(const std::string & mount_point,bool shared_flag)620 bool fs_mgr_overlayfs_set_shared_mount(const std::string& mount_point, bool shared_flag) {
621     auto ret = mount(nullptr, mount_point.c_str(), nullptr, shared_flag ? MS_SHARED : MS_PRIVATE,
622                      nullptr);
623     if (ret) {
624         PERROR << "__mount(target=" << mount_point
625                << ",flag=" << (shared_flag ? "MS_SHARED" : "MS_PRIVATE") << ")=" << ret;
626         return false;
627     }
628     return true;
629 }
630 
fs_mgr_overlayfs_move_mount(const std::string & source,const std::string & target)631 bool fs_mgr_overlayfs_move_mount(const std::string& source, const std::string& target) {
632     auto ret = mount(source.c_str(), target.c_str(), nullptr, MS_MOVE, nullptr);
633     if (ret) {
634         PERROR << "__mount(source=" << source << ",target=" << target << ",flag=MS_MOVE)=" << ret;
635         return false;
636     }
637     return true;
638 }
639 
640 struct mount_info {
641     std::string mount_point;
642     bool shared_flag;
643 };
644 
ReadMountinfoFromFile(const std::string & path)645 std::vector<mount_info> ReadMountinfoFromFile(const std::string& path) {
646     std::vector<mount_info> info;
647 
648     auto file = std::unique_ptr<FILE, decltype(&fclose)>{fopen(path.c_str(), "re"), fclose};
649     if (!file) {
650         PERROR << __FUNCTION__ << "(): cannot open file: '" << path << "'";
651         return info;
652     }
653 
654     ssize_t len;
655     size_t alloc_len = 0;
656     char* line = nullptr;
657     while ((len = getline(&line, &alloc_len, file.get())) != -1) {
658         /* if the last character is a newline, shorten the string by 1 byte */
659         if (line[len - 1] == '\n') {
660             line[len - 1] = '\0';
661         }
662 
663         static constexpr char delim[] = " \t";
664         char* save_ptr;
665         if (!strtok_r(line, delim, &save_ptr)) {
666             LERROR << "Error parsing mount ID";
667             break;
668         }
669         if (!strtok_r(nullptr, delim, &save_ptr)) {
670             LERROR << "Error parsing parent ID";
671             break;
672         }
673         if (!strtok_r(nullptr, delim, &save_ptr)) {
674             LERROR << "Error parsing mount source";
675             break;
676         }
677         if (!strtok_r(nullptr, delim, &save_ptr)) {
678             LERROR << "Error parsing root";
679             break;
680         }
681 
682         char* p;
683         if (!(p = strtok_r(nullptr, delim, &save_ptr))) {
684             LERROR << "Error parsing mount_point";
685             break;
686         }
687         mount_info entry = {p, false};
688 
689         if (!strtok_r(nullptr, delim, &save_ptr)) {
690             LERROR << "Error parsing mount_flags";
691             break;
692         }
693 
694         while ((p = strtok_r(nullptr, delim, &save_ptr))) {
695             if ((p[0] == '-') && (p[1] == '\0')) break;
696             if (android::base::StartsWith(p, "shared:")) entry.shared_flag = true;
697         }
698         if (!p) {
699             LERROR << "Error parsing fields";
700             break;
701         }
702         info.emplace_back(std::move(entry));
703     }
704 
705     free(line);
706     if (info.empty()) {
707         LERROR << __FUNCTION__ << "(): failed to load mountinfo from : '" << path << "'";
708     }
709     return info;
710 }
711 
fs_mgr_overlayfs_mount(const std::string & mount_point)712 bool fs_mgr_overlayfs_mount(const std::string& mount_point) {
713     auto options = fs_mgr_get_overlayfs_options(mount_point);
714     if (options.empty()) return false;
715 
716     auto retval = true;
717     auto save_errno = errno;
718 
719     struct move_entry {
720         std::string mount_point;
721         std::string dir;
722         bool shared_flag;
723     };
724     std::vector<move_entry> move;
725     auto parent_private = false;
726     auto parent_made_private = false;
727     auto dev_private = false;
728     auto dev_made_private = false;
729     for (auto& entry : ReadMountinfoFromFile("/proc/self/mountinfo")) {
730         if ((entry.mount_point == mount_point) && !entry.shared_flag) {
731             parent_private = true;
732         }
733         if ((entry.mount_point == "/dev") && !entry.shared_flag) {
734             dev_private = true;
735         }
736 
737         if (!android::base::StartsWith(entry.mount_point, mount_point + "/")) {
738             continue;
739         }
740         if (std::find_if(move.begin(), move.end(), [&entry](const auto& it) {
741                 return android::base::StartsWith(entry.mount_point, it.mount_point + "/");
742             }) != move.end()) {
743             continue;
744         }
745 
746         // use as the bound directory in /dev.
747         auto new_context = fs_mgr_get_context(entry.mount_point);
748         if (!new_context.empty() && setfscreatecon(new_context.c_str())) {
749             PERROR << "setfscreatecon " << new_context;
750         }
751         move_entry new_entry = {std::move(entry.mount_point), "/dev/TemporaryDir-XXXXXX",
752                                 entry.shared_flag};
753         const auto target = mkdtemp(new_entry.dir.data());
754         if (!target) {
755             retval = false;
756             save_errno = errno;
757             PERROR << "temporary directory for MS_BIND";
758             setfscreatecon(nullptr);
759             continue;
760         }
761         setfscreatecon(nullptr);
762 
763         if (!parent_private && !parent_made_private) {
764             parent_made_private = fs_mgr_overlayfs_set_shared_mount(mount_point, false);
765         }
766         if (new_entry.shared_flag) {
767             new_entry.shared_flag = fs_mgr_overlayfs_set_shared_mount(new_entry.mount_point, false);
768         }
769         if (!fs_mgr_overlayfs_move_mount(new_entry.mount_point, new_entry.dir)) {
770             retval = false;
771             save_errno = errno;
772             if (new_entry.shared_flag) {
773                 fs_mgr_overlayfs_set_shared_mount(new_entry.mount_point, true);
774             }
775             continue;
776         }
777         move.emplace_back(std::move(new_entry));
778     }
779 
780     // hijack __mount() report format to help triage
781     auto report = "__mount(source=overlay,target="s + mount_point + ",type=overlay";
782     const auto opt_list = android::base::Split(options, ",");
783     for (const auto& opt : opt_list) {
784         if (android::base::StartsWith(opt, kUpperdirOption)) {
785             report = report + "," + opt;
786             break;
787         }
788     }
789     report = report + ")=";
790 
791     auto ret = mount("overlay", mount_point.c_str(), "overlay", MS_RDONLY | MS_NOATIME,
792                      options.c_str());
793     if (ret) {
794         retval = false;
795         save_errno = errno;
796         PERROR << report << ret;
797     } else {
798         LINFO << report << ret;
799     }
800 
801     // Move submounts back.
802     for (const auto& entry : move) {
803         if (!dev_private && !dev_made_private) {
804             dev_made_private = fs_mgr_overlayfs_set_shared_mount("/dev", false);
805         }
806 
807         if (!fs_mgr_overlayfs_move_mount(entry.dir, entry.mount_point)) {
808             retval = false;
809             save_errno = errno;
810         } else if (entry.shared_flag &&
811                    !fs_mgr_overlayfs_set_shared_mount(entry.mount_point, true)) {
812             retval = false;
813             save_errno = errno;
814         }
815         rmdir(entry.dir.c_str());
816     }
817     if (dev_made_private) {
818         fs_mgr_overlayfs_set_shared_mount("/dev", true);
819     }
820     if (parent_made_private) {
821         fs_mgr_overlayfs_set_shared_mount(mount_point, true);
822     }
823 
824     errno = save_errno;
825     return retval;
826 }
827 
828 // Mount kScratchMountPoint
fs_mgr_overlayfs_mount_scratch(const std::string & device_path,const std::string mnt_type,bool readonly=false)829 bool fs_mgr_overlayfs_mount_scratch(const std::string& device_path, const std::string mnt_type,
830                                     bool readonly = false) {
831     if (readonly) {
832         if (!fs_mgr_access(device_path)) return false;
833     } else {
834         if (!fs_mgr_rw_access(device_path)) return false;
835     }
836 
837     auto f2fs = fs_mgr_is_f2fs(device_path);
838     auto ext4 = fs_mgr_is_ext4(device_path);
839     if (!f2fs && !ext4) return false;
840 
841     if (setfscreatecon(kOverlayfsFileContext)) {
842         PERROR << "setfscreatecon " << kOverlayfsFileContext;
843     }
844     if (mkdir(kScratchMountPoint.c_str(), 0755) && (errno != EEXIST)) {
845         PERROR << "create " << kScratchMountPoint;
846     }
847 
848     FstabEntry entry;
849     entry.blk_device = device_path;
850     entry.mount_point = kScratchMountPoint;
851     entry.fs_type = mnt_type;
852     if ((mnt_type == "f2fs") && !f2fs) entry.fs_type = "ext4";
853     if ((mnt_type == "ext4") && !ext4) entry.fs_type = "f2fs";
854     entry.flags = MS_NOATIME | MS_RDONLY;
855     auto mounted = true;
856     if (!readonly) {
857         if (entry.fs_type == "ext4") {
858             // check if ext4 de-dupe
859             entry.flags |= MS_RDONLY;
860             auto save_errno = errno;
861             mounted = fs_mgr_do_mount_one(entry) == 0;
862             if (mounted) {
863                 mounted = !fs_mgr_has_shared_blocks(entry.mount_point, entry.blk_device);
864                 fs_mgr_overlayfs_umount_scratch();
865             }
866             errno = save_errno;
867         }
868         entry.flags &= ~MS_RDONLY;
869         fs_mgr_set_blk_ro(device_path, false);
870     }
871     entry.fs_mgr_flags.check = true;
872     auto save_errno = errno;
873     if (mounted) mounted = fs_mgr_do_mount_one(entry) == 0;
874     if (!mounted) {
875         if ((entry.fs_type == "f2fs") && ext4) {
876             entry.fs_type = "ext4";
877             mounted = fs_mgr_do_mount_one(entry) == 0;
878         } else if ((entry.fs_type == "ext4") && f2fs) {
879             entry.fs_type = "f2fs";
880             mounted = fs_mgr_do_mount_one(entry) == 0;
881         }
882         if (!mounted) save_errno = errno;
883     }
884     setfscreatecon(nullptr);
885     if (!mounted) rmdir(kScratchMountPoint.c_str());
886     errno = save_errno;
887     return mounted;
888 }
889 
890 const std::string kMkF2fs("/system/bin/make_f2fs");
891 const std::string kMkExt4("/system/bin/mke2fs");
892 
893 // Only a suggestion for _first_ try during mounting
fs_mgr_overlayfs_scratch_mount_type()894 std::string fs_mgr_overlayfs_scratch_mount_type() {
895     if (!access(kMkF2fs.c_str(), X_OK) && fs_mgr_overlayfs_filesystem_available("f2fs")) {
896         return "f2fs";
897     }
898     if (!access(kMkExt4.c_str(), X_OK) && fs_mgr_overlayfs_filesystem_available("ext4")) {
899         return "ext4";
900     }
901     return "auto";
902 }
903 
904 // Note: we do not check access() here except for the super partition, since
905 // in first-stage init we wouldn't have registed by-name symlinks for "other"
906 // partitions that won't be mounted.
GetPhysicalScratchDevice()907 static std::string GetPhysicalScratchDevice() {
908     auto slot_number = fs_mgr_overlayfs_slot_number();
909     auto super_device = fs_mgr_overlayfs_super_device(slot_number);
910     auto path = fs_mgr_overlayfs_super_device(slot_number == 0);
911     if (super_device != path) {
912         return path;
913     }
914     if (fs_mgr_access(super_device)) {
915         // Do not try to use system_other on a DAP device.
916         return "";
917     }
918 
919     auto other_slot = fs_mgr_get_other_slot_suffix();
920     if (!other_slot.empty()) {
921         return kPhysicalDevice + "system" + other_slot;
922     }
923     return "";
924 }
925 
926 // Note: The scratch partition of DSU is managed by gsid, and should be initialized during
927 // first-stage-mount. Just check if the DM device for DSU scratch partition is created or not.
GetDsuScratchDevice()928 static std::string GetDsuScratchDevice() {
929     auto& dm = DeviceMapper::Instance();
930     std::string device;
931     if (dm.GetState(android::gsi::kDsuScratch) != DmDeviceState::INVALID &&
932         dm.GetDmDevicePathByName(android::gsi::kDsuScratch, &device)) {
933         return device;
934     }
935     return "";
936 }
937 
938 // This returns the scratch device that was detected during early boot (first-
939 // stage init). If the device was created later, for example during setup for
940 // the adb remount command, it can return an empty string since it does not
941 // query ImageManager. (Note that ImageManager in first-stage init will always
942 // use device-mapper, since /data is not available to use loop devices.)
GetBootScratchDevice()943 static std::string GetBootScratchDevice() {
944     // Note: fs_mgr_is_dsu_running() always returns false in recovery or fastbootd.
945     if (fs_mgr_is_dsu_running()) {
946         return GetDsuScratchDevice();
947     }
948 
949     auto& dm = DeviceMapper::Instance();
950 
951     // If there is a scratch partition allocated in /data or on super, we
952     // automatically prioritize that over super_other or system_other.
953     // Some devices, for example, have a write-protected eMMC and the
954     // super partition cannot be used even if it exists.
955     std::string device;
956     auto partition_name = android::base::Basename(kScratchMountPoint);
957     if (dm.GetState(partition_name) != DmDeviceState::INVALID &&
958         dm.GetDmDevicePathByName(partition_name, &device)) {
959         return device;
960     }
961 
962     // There is no dynamic scratch, so try and find a physical one.
963     return GetPhysicalScratchDevice();
964 }
965 
fs_mgr_overlayfs_make_scratch(const std::string & scratch_device,const std::string & mnt_type)966 bool fs_mgr_overlayfs_make_scratch(const std::string& scratch_device, const std::string& mnt_type) {
967     // Force mkfs by design for overlay support of adb remount, simplify and
968     // thus do not rely on fsck to correct problems that could creep in.
969     auto command = ""s;
970     if (mnt_type == "f2fs") {
971         command = kMkF2fs + " -w 4096 -f -d1 -l" + android::base::Basename(kScratchMountPoint);
972     } else if (mnt_type == "ext4") {
973         command = kMkExt4 + " -F -b 4096 -t ext4 -m 0 -O has_journal -M " + kScratchMountPoint;
974     } else {
975         errno = ESRCH;
976         LERROR << mnt_type << " has no mkfs cookbook";
977         return false;
978     }
979     command += " " + scratch_device + " >/dev/null 2>/dev/null </dev/null";
980     fs_mgr_set_blk_ro(scratch_device, false);
981     auto ret = system(command.c_str());
982     if (ret) {
983         LERROR << "make " << mnt_type << " filesystem on " << scratch_device << " return=" << ret;
984         return false;
985     }
986     return true;
987 }
988 
TruncatePartitionsWithSuffix(MetadataBuilder * builder,const std::string & suffix)989 static void TruncatePartitionsWithSuffix(MetadataBuilder* builder, const std::string& suffix) {
990     auto& dm = DeviceMapper::Instance();
991 
992     // Remove <other> partitions
993     for (const auto& group : builder->ListGroups()) {
994         for (const auto& part : builder->ListPartitionsInGroup(group)) {
995             const auto& name = part->name();
996             if (!android::base::EndsWith(name, suffix)) {
997                 continue;
998             }
999             if (dm.GetState(name) != DmDeviceState::INVALID && !DestroyLogicalPartition(name)) {
1000                 continue;
1001             }
1002             builder->ResizePartition(builder->FindPartition(name), 0);
1003         }
1004     }
1005 }
1006 
1007 // Create or update a scratch partition within super.
CreateDynamicScratch(std::string * scratch_device,bool * partition_exists,bool * change)1008 static bool CreateDynamicScratch(std::string* scratch_device, bool* partition_exists,
1009                                  bool* change) {
1010     const auto partition_name = android::base::Basename(kScratchMountPoint);
1011 
1012     auto& dm = DeviceMapper::Instance();
1013     *partition_exists = dm.GetState(partition_name) != DmDeviceState::INVALID;
1014 
1015     auto partition_create = !*partition_exists;
1016     auto slot_number = fs_mgr_overlayfs_slot_number();
1017     auto super_device = fs_mgr_overlayfs_super_device(slot_number);
1018     auto builder = MetadataBuilder::New(super_device, slot_number);
1019     if (!builder) {
1020         LERROR << "open " << super_device << " metadata";
1021         return false;
1022     }
1023     auto partition = builder->FindPartition(partition_name);
1024     *partition_exists = partition != nullptr;
1025     auto changed = false;
1026     if (!*partition_exists) {
1027         partition = builder->AddPartition(partition_name, LP_PARTITION_ATTR_NONE);
1028         if (!partition) {
1029             LERROR << "create " << partition_name;
1030             return false;
1031         }
1032         changed = true;
1033     }
1034     // Take half of free space, minimum 512MB or maximum free - margin.
1035     static constexpr auto kMinimumSize = uint64_t(512 * 1024 * 1024);
1036     if (partition->size() < kMinimumSize) {
1037         auto partition_size =
1038                 builder->AllocatableSpace() - builder->UsedSpace() + partition->size();
1039         if ((partition_size > kMinimumSize) || !partition->size()) {
1040             // Leave some space for free space jitter of a few erase
1041             // blocks, in case they are needed for any individual updates
1042             // to any other partition that needs to be flashed while
1043             // overlayfs is in force.  Of course if margin_size is not
1044             // enough could normally get a flash failure, so
1045             // ResizePartition() will delete the scratch partition in
1046             // order to fulfill.  Deleting scratch will destroy all of
1047             // the adb remount overrides :-( .
1048             auto margin_size = uint64_t(3 * 256 * 1024);
1049             BlockDeviceInfo info;
1050             if (builder->GetBlockDeviceInfo(fs_mgr_get_super_partition_name(slot_number), &info)) {
1051                 margin_size = 3 * info.logical_block_size;
1052             }
1053             partition_size = std::max(std::min(kMinimumSize, partition_size - margin_size),
1054                                       partition_size / 2);
1055             if (partition_size > partition->size()) {
1056                 if (!builder->ResizePartition(partition, partition_size)) {
1057                     // Try to free up space by deallocating partitions in the other slot.
1058                     TruncatePartitionsWithSuffix(builder.get(), fs_mgr_get_other_slot_suffix());
1059 
1060                     partition_size =
1061                             builder->AllocatableSpace() - builder->UsedSpace() + partition->size();
1062                     partition_size = std::max(std::min(kMinimumSize, partition_size - margin_size),
1063                                               partition_size / 2);
1064                     if (!builder->ResizePartition(partition, partition_size)) {
1065                         LERROR << "resize " << partition_name;
1066                         return false;
1067                     }
1068                 }
1069                 if (!partition_create) DestroyLogicalPartition(partition_name);
1070                 changed = true;
1071                 *partition_exists = false;
1072             }
1073         }
1074     }
1075     // land the update back on to the partition
1076     if (changed) {
1077         auto metadata = builder->Export();
1078         if (!metadata || !UpdatePartitionTable(super_device, *metadata.get(), slot_number)) {
1079             LERROR << "add partition " << partition_name;
1080             return false;
1081         }
1082 
1083         if (change) *change = true;
1084     }
1085 
1086     if (changed || partition_create) {
1087         CreateLogicalPartitionParams params = {
1088                 .block_device = super_device,
1089                 .metadata_slot = slot_number,
1090                 .partition_name = partition_name,
1091                 .force_writable = true,
1092                 .timeout_ms = 10s,
1093         };
1094         if (!CreateLogicalPartition(params, scratch_device)) {
1095             return false;
1096         }
1097 
1098         if (change) *change = true;
1099     } else if (scratch_device->empty()) {
1100         *scratch_device = GetBootScratchDevice();
1101     }
1102     return true;
1103 }
1104 
CreateScratchOnData(std::string * scratch_device,bool * partition_exists,bool * change)1105 static bool CreateScratchOnData(std::string* scratch_device, bool* partition_exists, bool* change) {
1106     *partition_exists = false;
1107     if (change) *change = false;
1108 
1109     auto images = IImageManager::Open("remount", 10s);
1110     if (!images) {
1111         return false;
1112     }
1113 
1114     auto partition_name = android::base::Basename(kScratchMountPoint);
1115     if (images->GetMappedImageDevice(partition_name, scratch_device)) {
1116         *partition_exists = true;
1117         return true;
1118     }
1119 
1120     BlockDeviceInfo info;
1121     PartitionOpener opener;
1122     if (!opener.GetInfo(fs_mgr_get_super_partition_name(), &info)) {
1123         LERROR << "could not get block device info for super";
1124         return false;
1125     }
1126 
1127     if (change) *change = true;
1128 
1129     // Note: calling RemoveDisabledImages here ensures that we do not race with
1130     // clean_scratch_files and accidentally try to map an image that will be
1131     // deleted.
1132     if (!images->RemoveDisabledImages()) {
1133         return false;
1134     }
1135     if (!images->BackingImageExists(partition_name)) {
1136         static constexpr uint64_t kMinimumSize = 16_MiB;
1137         static constexpr uint64_t kMaximumSize = 2_GiB;
1138 
1139         uint64_t size = std::clamp(info.size / 2, kMinimumSize, kMaximumSize);
1140         auto flags = IImageManager::CREATE_IMAGE_DEFAULT;
1141 
1142         if (!images->CreateBackingImage(partition_name, size, flags)) {
1143             LERROR << "could not create scratch image of " << size << " bytes";
1144             return false;
1145         }
1146     }
1147     if (!images->MapImageDevice(partition_name, 10s, scratch_device)) {
1148         LERROR << "could not map scratch image";
1149         return false;
1150     }
1151     return true;
1152 }
1153 
CanUseSuperPartition(const Fstab & fstab,bool * is_virtual_ab)1154 static bool CanUseSuperPartition(const Fstab& fstab, bool* is_virtual_ab) {
1155     auto slot_number = fs_mgr_overlayfs_slot_number();
1156     auto super_device = fs_mgr_overlayfs_super_device(slot_number);
1157     if (!fs_mgr_rw_access(super_device) || !fs_mgr_overlayfs_has_logical(fstab)) {
1158         return false;
1159     }
1160     auto metadata = ReadMetadata(super_device, slot_number);
1161     if (!metadata) {
1162         return false;
1163     }
1164     *is_virtual_ab = !!(metadata->header.flags & LP_HEADER_FLAG_VIRTUAL_AB_DEVICE);
1165     return true;
1166 }
1167 
fs_mgr_overlayfs_create_scratch(const Fstab & fstab,std::string * scratch_device,bool * partition_exists,bool * change)1168 bool fs_mgr_overlayfs_create_scratch(const Fstab& fstab, std::string* scratch_device,
1169                                      bool* partition_exists, bool* change) {
1170     // Use the DSU scratch device managed by gsid if within a DSU system.
1171     if (fs_mgr_is_dsu_running()) {
1172         *scratch_device = GetDsuScratchDevice();
1173         *partition_exists = !scratch_device->empty();
1174         *change = false;
1175         return *partition_exists;
1176     }
1177 
1178     // Try a physical partition first.
1179     *scratch_device = GetPhysicalScratchDevice();
1180     if (!scratch_device->empty() && fs_mgr_rw_access(*scratch_device)) {
1181         *partition_exists = true;
1182         return true;
1183     }
1184 
1185     // If that fails, see if we can land on super.
1186     bool is_virtual_ab;
1187     if (CanUseSuperPartition(fstab, &is_virtual_ab)) {
1188         bool can_use_data = false;
1189         if (is_virtual_ab && FilesystemHasReliablePinning("/data", &can_use_data) && can_use_data) {
1190             return CreateScratchOnData(scratch_device, partition_exists, change);
1191         }
1192         return CreateDynamicScratch(scratch_device, partition_exists, change);
1193     }
1194 
1195     errno = ENXIO;
1196     return false;
1197 }
1198 
1199 // Create and mount kScratchMountPoint storage if we have logical partitions
fs_mgr_overlayfs_setup_scratch(const Fstab & fstab,bool * change)1200 bool fs_mgr_overlayfs_setup_scratch(const Fstab& fstab, bool* change) {
1201     if (fs_mgr_overlayfs_already_mounted(kScratchMountPoint, false)) return true;
1202 
1203     std::string scratch_device;
1204     bool partition_exists;
1205     if (!fs_mgr_overlayfs_create_scratch(fstab, &scratch_device, &partition_exists, change)) {
1206         return false;
1207     }
1208 
1209     // If the partition exists, assume first that it can be mounted.
1210     auto mnt_type = fs_mgr_overlayfs_scratch_mount_type();
1211     if (partition_exists) {
1212         if (fs_mgr_overlayfs_mount_scratch(scratch_device, mnt_type)) {
1213             if (!fs_mgr_access(kScratchMountPoint + kOverlayTopDir) &&
1214                 !fs_mgr_filesystem_has_space(kScratchMountPoint)) {
1215                 // declare it useless, no overrides and no free space
1216                 fs_mgr_overlayfs_umount_scratch();
1217             } else {
1218                 if (change) *change = true;
1219                 return true;
1220             }
1221         }
1222         // partition existed, but was not initialized; fall through to make it.
1223         errno = 0;
1224     }
1225 
1226     if (!fs_mgr_overlayfs_make_scratch(scratch_device, mnt_type)) return false;
1227 
1228     if (change) *change = true;
1229 
1230     return fs_mgr_overlayfs_mount_scratch(scratch_device, mnt_type);
1231 }
1232 
fs_mgr_overlayfs_invalid()1233 bool fs_mgr_overlayfs_invalid() {
1234     if (fs_mgr_overlayfs_valid() == OverlayfsValidResult::kNotSupported) return true;
1235 
1236     // in recovery or fastbootd, not allowed!
1237     return fs_mgr_in_recovery();
1238 }
1239 
1240 }  // namespace
1241 
fs_mgr_overlayfs_candidate_list(const Fstab & fstab)1242 Fstab fs_mgr_overlayfs_candidate_list(const Fstab& fstab) {
1243     Fstab candidates;
1244     for (const auto& entry : fstab) {
1245         FstabEntry new_entry = entry;
1246         if (!fs_mgr_overlayfs_already_mounted(entry.mount_point) &&
1247             !fs_mgr_wants_overlayfs(&new_entry)) {
1248             continue;
1249         }
1250         auto new_mount_point = fs_mgr_mount_point(entry.mount_point);
1251         auto duplicate_or_more_specific = false;
1252         for (auto it = candidates.begin(); it != candidates.end();) {
1253             auto it_mount_point = fs_mgr_mount_point(it->mount_point);
1254             if ((it_mount_point == new_mount_point) ||
1255                 (android::base::StartsWith(new_mount_point, it_mount_point + "/"))) {
1256                 duplicate_or_more_specific = true;
1257                 break;
1258             }
1259             if (android::base::StartsWith(it_mount_point, new_mount_point + "/")) {
1260                 it = candidates.erase(it);
1261             } else {
1262                 ++it;
1263             }
1264         }
1265         if (!duplicate_or_more_specific) candidates.emplace_back(std::move(new_entry));
1266     }
1267     return candidates;
1268 }
1269 
TryMountScratch()1270 static void TryMountScratch() {
1271     // Note we get the boot scratch device here, which means if scratch was
1272     // just created through ImageManager, this could fail. In practice this
1273     // should not happen because "remount" detects this scenario (by checking
1274     // if verity is still disabled, i.e. no reboot occurred), and skips calling
1275     // fs_mgr_overlayfs_mount_all().
1276     auto scratch_device = GetBootScratchDevice();
1277     if (!fs_mgr_rw_access(scratch_device)) {
1278         return;
1279     }
1280     if (!WaitForFile(scratch_device, 10s)) {
1281         return;
1282     }
1283     const auto mount_type = fs_mgr_overlayfs_scratch_mount_type();
1284     if (!fs_mgr_overlayfs_mount_scratch(scratch_device, mount_type, true /* readonly */)) {
1285         return;
1286     }
1287     auto has_overlayfs_dir = fs_mgr_access(kScratchMountPoint + kOverlayTopDir);
1288     fs_mgr_overlayfs_umount_scratch();
1289     if (has_overlayfs_dir) {
1290         fs_mgr_overlayfs_mount_scratch(scratch_device, mount_type);
1291     }
1292 }
1293 
fs_mgr_overlayfs_mount_all(Fstab * fstab)1294 bool fs_mgr_overlayfs_mount_all(Fstab* fstab) {
1295     auto ret = false;
1296     if (fs_mgr_overlayfs_invalid()) return ret;
1297 
1298     auto scratch_can_be_mounted = true;
1299     for (const auto& entry : fs_mgr_overlayfs_candidate_list(*fstab)) {
1300         if (fs_mgr_is_verity_enabled(entry)) continue;
1301         auto mount_point = fs_mgr_mount_point(entry.mount_point);
1302         if (fs_mgr_overlayfs_already_mounted(mount_point)) {
1303             ret = true;
1304             continue;
1305         }
1306         if (scratch_can_be_mounted) {
1307             scratch_can_be_mounted = false;
1308             TryMountScratch();
1309         }
1310         if (fs_mgr_overlayfs_mount(mount_point)) ret = true;
1311     }
1312     return ret;
1313 }
1314 
1315 // Returns false if setup not permitted, errno set to last error.
1316 // If something is altered, set *change.
fs_mgr_overlayfs_setup(const char * backing,const char * mount_point,bool * change,bool force)1317 bool fs_mgr_overlayfs_setup(const char* backing, const char* mount_point, bool* change,
1318                             bool force) {
1319     if (change) *change = false;
1320     auto ret = false;
1321     if (fs_mgr_overlayfs_valid() == OverlayfsValidResult::kNotSupported) return ret;
1322     if (!fs_mgr_boot_completed()) {
1323         errno = EBUSY;
1324         PERROR << "setup";
1325         return ret;
1326     }
1327 
1328     auto save_errno = errno;
1329     Fstab fstab;
1330     if (!ReadDefaultFstab(&fstab)) {
1331         return false;
1332     }
1333     errno = save_errno;
1334     auto candidates = fs_mgr_overlayfs_candidate_list(fstab);
1335     for (auto it = candidates.begin(); it != candidates.end();) {
1336         if (mount_point &&
1337             (fs_mgr_mount_point(it->mount_point) != fs_mgr_mount_point(mount_point))) {
1338             it = candidates.erase(it);
1339             continue;
1340         }
1341         save_errno = errno;
1342         auto verity_enabled = !force && fs_mgr_is_verity_enabled(*it);
1343         if (errno == ENOENT || errno == ENXIO) errno = save_errno;
1344         if (verity_enabled) {
1345             it = candidates.erase(it);
1346             continue;
1347         }
1348         ++it;
1349     }
1350 
1351     if (candidates.empty()) return ret;
1352 
1353     std::string dir;
1354     for (const auto& overlay_mount_point : OverlayMountPoints()) {
1355         if (backing && backing[0] && (overlay_mount_point != backing)) continue;
1356         if (overlay_mount_point == kScratchMountPoint) {
1357             if (!fs_mgr_overlayfs_setup_scratch(fstab, change)) continue;
1358         } else {
1359             if (GetEntryForMountPoint(&fstab, overlay_mount_point) == nullptr) {
1360                 continue;
1361             }
1362         }
1363         dir = overlay_mount_point;
1364         break;
1365     }
1366     if (dir.empty()) {
1367         if (change && *change) errno = ESRCH;
1368         if (errno == EPERM) errno = save_errno;
1369         return ret;
1370     }
1371 
1372     std::string overlay;
1373     ret |= fs_mgr_overlayfs_setup_dir(dir, &overlay, change);
1374     for (const auto& entry : candidates) {
1375         ret |= fs_mgr_overlayfs_setup_one(overlay, fs_mgr_mount_point(entry.mount_point), change);
1376     }
1377     return ret;
1378 }
1379 
1380 // Note: This function never returns the DSU scratch device in recovery or fastbootd,
1381 // because the DSU scratch is created in the first-stage-mount, which is not run in recovery.
EnsureScratchMapped(std::string * device,bool * mapped)1382 static bool EnsureScratchMapped(std::string* device, bool* mapped) {
1383     *mapped = false;
1384     *device = GetBootScratchDevice();
1385     if (!device->empty()) {
1386         return true;
1387     }
1388 
1389     if (!fs_mgr_in_recovery()) {
1390         errno = EINVAL;
1391         return false;
1392     }
1393 
1394     auto partition_name = android::base::Basename(kScratchMountPoint);
1395 
1396     // Check for scratch on /data first, before looking for a modified super
1397     // partition. We should only reach this code in recovery, because scratch
1398     // would otherwise always be mapped.
1399     auto images = IImageManager::Open("remount", 10s);
1400     if (images && images->BackingImageExists(partition_name)) {
1401         if (!images->MapImageDevice(partition_name, 10s, device)) {
1402             return false;
1403         }
1404         *mapped = true;
1405         return true;
1406     }
1407 
1408     // Avoid uart spam by first checking for a scratch partition.
1409     auto metadata_slot = fs_mgr_overlayfs_slot_number();
1410     auto super_device = fs_mgr_overlayfs_super_device(metadata_slot);
1411     auto metadata = ReadCurrentMetadata(super_device);
1412     if (!metadata) {
1413         return false;
1414     }
1415 
1416     auto partition = FindPartition(*metadata.get(), partition_name);
1417     if (!partition) {
1418         return false;
1419     }
1420 
1421     CreateLogicalPartitionParams params = {
1422             .block_device = super_device,
1423             .metadata = metadata.get(),
1424             .partition = partition,
1425             .force_writable = true,
1426             .timeout_ms = 10s,
1427     };
1428     if (!CreateLogicalPartition(params, device)) {
1429         return false;
1430     }
1431     *mapped = true;
1432     return true;
1433 }
1434 
1435 // This should only be reachable in recovery, where DSU scratch is not
1436 // automatically mapped.
MapDsuScratchDevice(std::string * device)1437 static bool MapDsuScratchDevice(std::string* device) {
1438     std::string dsu_slot;
1439     if (!android::gsi::IsGsiInstalled() || !android::gsi::GetActiveDsu(&dsu_slot) ||
1440         dsu_slot.empty()) {
1441         // Nothing to do if no DSU installation present.
1442         return false;
1443     }
1444 
1445     auto images = IImageManager::Open("dsu/" + dsu_slot, 10s);
1446     if (!images || !images->BackingImageExists(android::gsi::kDsuScratch)) {
1447         // Nothing to do if DSU scratch device doesn't exist.
1448         return false;
1449     }
1450 
1451     images->UnmapImageDevice(android::gsi::kDsuScratch);
1452     if (!images->MapImageDevice(android::gsi::kDsuScratch, 10s, device)) {
1453         return false;
1454     }
1455     return true;
1456 }
1457 
1458 // Returns false if teardown not permitted, errno set to last error.
1459 // If something is altered, set *change.
fs_mgr_overlayfs_teardown(const char * mount_point,bool * change)1460 bool fs_mgr_overlayfs_teardown(const char* mount_point, bool* change) {
1461     if (change) *change = false;
1462     auto ret = true;
1463 
1464     // If scratch exists, but is not mounted, lets gain access to clean
1465     // specific override entries.
1466     auto mount_scratch = false;
1467     if ((mount_point != nullptr) && !fs_mgr_overlayfs_already_mounted(kScratchMountPoint, false)) {
1468         std::string scratch_device = GetBootScratchDevice();
1469         if (!scratch_device.empty()) {
1470             mount_scratch = fs_mgr_overlayfs_mount_scratch(scratch_device,
1471                                                            fs_mgr_overlayfs_scratch_mount_type());
1472         }
1473     }
1474     bool should_destroy_scratch = false;
1475     for (const auto& overlay_mount_point : OverlayMountPoints()) {
1476         ret &= fs_mgr_overlayfs_teardown_one(
1477                 overlay_mount_point, mount_point ? fs_mgr_mount_point(mount_point) : "", change,
1478                 overlay_mount_point == kScratchMountPoint ? &should_destroy_scratch : nullptr);
1479     }
1480     // Do not attempt to destroy DSU scratch if within a DSU system,
1481     // because DSU scratch partition is managed by gsid.
1482     if (should_destroy_scratch && !fs_mgr_is_dsu_running()) {
1483         ret &= fs_mgr_overlayfs_teardown_scratch(kScratchMountPoint, change);
1484     }
1485     if (fs_mgr_overlayfs_valid() == OverlayfsValidResult::kNotSupported) {
1486         // After obligatory teardown to make sure everything is clean, but if
1487         // we didn't want overlayfs in the first place, we do not want to
1488         // waste time on a reboot (or reboot request message).
1489         if (change) *change = false;
1490     }
1491     // And now that we did what we could, lets inform
1492     // caller that there may still be more to do.
1493     if (!fs_mgr_boot_completed()) {
1494         errno = EBUSY;
1495         PERROR << "teardown";
1496         ret = false;
1497     }
1498     if (mount_scratch) {
1499         fs_mgr_overlayfs_umount_scratch();
1500     }
1501     return ret;
1502 }
1503 
fs_mgr_overlayfs_is_setup()1504 bool fs_mgr_overlayfs_is_setup() {
1505     if (fs_mgr_overlayfs_already_mounted(kScratchMountPoint, false)) return true;
1506     Fstab fstab;
1507     if (!ReadDefaultFstab(&fstab)) {
1508         return false;
1509     }
1510     if (fs_mgr_overlayfs_invalid()) return false;
1511     for (const auto& entry : fs_mgr_overlayfs_candidate_list(fstab)) {
1512         if (fs_mgr_is_verity_enabled(entry)) continue;
1513         if (fs_mgr_overlayfs_already_mounted(fs_mgr_mount_point(entry.mount_point))) return true;
1514     }
1515     return false;
1516 }
1517 
1518 namespace android {
1519 namespace fs_mgr {
1520 
MapScratchPartitionIfNeeded(Fstab * fstab,const std::function<bool (const std::set<std::string> &)> & init)1521 void MapScratchPartitionIfNeeded(Fstab* fstab,
1522                                  const std::function<bool(const std::set<std::string>&)>& init) {
1523     if (fs_mgr_overlayfs_invalid()) {
1524         return;
1525     }
1526     if (GetEntryForMountPoint(fstab, kScratchMountPoint) != nullptr) {
1527         return;
1528     }
1529 
1530     bool want_scratch = false;
1531     for (const auto& entry : fs_mgr_overlayfs_candidate_list(*fstab)) {
1532         if (fs_mgr_is_verity_enabled(entry)) {
1533             continue;
1534         }
1535         if (fs_mgr_overlayfs_already_mounted(fs_mgr_mount_point(entry.mount_point))) {
1536             continue;
1537         }
1538         want_scratch = true;
1539         break;
1540     }
1541     if (!want_scratch) {
1542         return;
1543     }
1544 
1545     if (ScratchIsOnData()) {
1546         if (auto images = IImageManager::Open("remount", 0ms)) {
1547             images->MapAllImages(init);
1548         }
1549     }
1550 
1551     // Physical or logical partitions will have already been mapped here,
1552     // so just ensure /dev/block symlinks exist.
1553     auto device = GetBootScratchDevice();
1554     if (!device.empty()) {
1555         init({android::base::Basename(device)});
1556     }
1557 }
1558 
CleanupOldScratchFiles()1559 void CleanupOldScratchFiles() {
1560     if (!ScratchIsOnData()) {
1561         return;
1562     }
1563     if (auto images = IImageManager::Open("remount", 0ms)) {
1564         images->RemoveDisabledImages();
1565     }
1566 }
1567 
TeardownAllOverlayForMountPoint(const std::string & mount_point)1568 void TeardownAllOverlayForMountPoint(const std::string& mount_point) {
1569     if (!fs_mgr_in_recovery()) {
1570         LERROR << __FUNCTION__ << "(): must be called within recovery.";
1571         return;
1572     }
1573 
1574     // Empty string means teardown everything.
1575     const std::string teardown_dir = mount_point.empty() ? "" : fs_mgr_mount_point(mount_point);
1576     constexpr bool* ignore_change = nullptr;
1577 
1578     // Teardown legacy overlay mount points that's not backed by a scratch device.
1579     for (const auto& overlay_mount_point : OverlayMountPoints()) {
1580         if (overlay_mount_point == kScratchMountPoint) {
1581             continue;
1582         }
1583         fs_mgr_overlayfs_teardown_one(overlay_mount_point, teardown_dir, ignore_change);
1584     }
1585 
1586     // Map scratch device, mount kScratchMountPoint and teardown kScratchMountPoint.
1587     bool mapped = false;
1588     std::string scratch_device;
1589     if (EnsureScratchMapped(&scratch_device, &mapped)) {
1590         fs_mgr_overlayfs_umount_scratch();
1591         if (fs_mgr_overlayfs_mount_scratch(scratch_device, fs_mgr_overlayfs_scratch_mount_type())) {
1592             bool should_destroy_scratch = false;
1593             fs_mgr_overlayfs_teardown_one(kScratchMountPoint, teardown_dir, ignore_change,
1594                                           &should_destroy_scratch);
1595             if (should_destroy_scratch) {
1596                 fs_mgr_overlayfs_teardown_scratch(kScratchMountPoint, nullptr);
1597             }
1598             fs_mgr_overlayfs_umount_scratch();
1599         }
1600         if (mapped) {
1601             DestroyLogicalPartition(android::base::Basename(kScratchMountPoint));
1602         }
1603     }
1604 
1605     // Teardown DSU overlay if present.
1606     if (MapDsuScratchDevice(&scratch_device)) {
1607         fs_mgr_overlayfs_umount_scratch();
1608         if (fs_mgr_overlayfs_mount_scratch(scratch_device, fs_mgr_overlayfs_scratch_mount_type())) {
1609             fs_mgr_overlayfs_teardown_one(kScratchMountPoint, teardown_dir, ignore_change);
1610             fs_mgr_overlayfs_umount_scratch();
1611         }
1612         DestroyLogicalPartition(android::gsi::kDsuScratch);
1613     }
1614 }
1615 
1616 }  // namespace fs_mgr
1617 }  // namespace android
1618 
1619 #endif  // ALLOW_ADBD_DISABLE_VERITY != 0
1620 
fs_mgr_has_shared_blocks(const std::string & mount_point,const std::string & dev)1621 bool fs_mgr_has_shared_blocks(const std::string& mount_point, const std::string& dev) {
1622     struct statfs fs;
1623     if ((statfs((mount_point + "/lost+found").c_str(), &fs) == -1) ||
1624         (fs.f_type != EXT4_SUPER_MAGIC)) {
1625         return false;
1626     }
1627 
1628     android::base::unique_fd fd(open(dev.c_str(), O_RDONLY | O_CLOEXEC));
1629     if (fd < 0) return false;
1630 
1631     struct ext4_super_block sb;
1632     if ((TEMP_FAILURE_RETRY(lseek64(fd, 1024, SEEK_SET)) < 0) ||
1633         (TEMP_FAILURE_RETRY(read(fd, &sb, sizeof(sb))) < 0)) {
1634         return false;
1635     }
1636 
1637     struct fs_info info;
1638     if (ext4_parse_sb(&sb, &info) < 0) return false;
1639 
1640     return (info.feat_ro_compat & EXT4_FEATURE_RO_COMPAT_SHARED_BLOCKS) != 0;
1641 }
1642 
fs_mgr_get_context(const std::string & mount_point)1643 std::string fs_mgr_get_context(const std::string& mount_point) {
1644     char* ctx = nullptr;
1645     if (getfilecon(mount_point.c_str(), &ctx) == -1) {
1646         return "";
1647     }
1648 
1649     std::string context(ctx);
1650     free(ctx);
1651     return context;
1652 }
1653 
fs_mgr_overlayfs_valid()1654 OverlayfsValidResult fs_mgr_overlayfs_valid() {
1655     // Overlayfs available in the kernel, and patched for override_creds?
1656     if (fs_mgr_access("/sys/module/overlay/parameters/override_creds")) {
1657         return OverlayfsValidResult::kOverrideCredsRequired;
1658     }
1659     if (!fs_mgr_overlayfs_filesystem_available("overlay")) {
1660         return OverlayfsValidResult::kNotSupported;
1661     }
1662     struct utsname uts;
1663     if (uname(&uts) == -1) {
1664         return OverlayfsValidResult::kNotSupported;
1665     }
1666     int major, minor;
1667     if (sscanf(uts.release, "%d.%d", &major, &minor) != 2) {
1668         return OverlayfsValidResult::kNotSupported;
1669     }
1670     if (major < 4) {
1671         return OverlayfsValidResult::kOk;
1672     }
1673     if (major > 4) {
1674         return OverlayfsValidResult::kNotSupported;
1675     }
1676     if (minor > 3) {
1677         return OverlayfsValidResult::kNotSupported;
1678     }
1679     return OverlayfsValidResult::kOk;
1680 }
1681