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