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