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