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