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