blob: 82b5275a3da6a38bdbb0215c482ee7b04e82f2f6 [file] [log] [blame]
Mark Salyzynb28389f2018-06-06 13:10:40 -07001/*
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>
Mark Salyzyn3ff87d82018-07-02 10:45:25 -070019#include <fcntl.h>
Mark Salyzynb28389f2018-06-06 13:10:40 -070020#include <linux/fs.h>
21#include <selinux/selinux.h>
22#include <stdio.h>
Mark Salyzyn2fde1ec2018-11-01 15:05:44 -070023#include <stdlib.h>
Mark Salyzynb28389f2018-06-06 13:10:40 -070024#include <string.h>
25#include <sys/mount.h>
26#include <sys/param.h>
27#include <sys/stat.h>
Mark Salyzyn53c96da2018-06-13 09:33:28 -070028#include <sys/statvfs.h>
Mark Salyzynb28389f2018-06-06 13:10:40 -070029#include <sys/types.h>
Mark Salyzyn6a116942018-11-05 08:53:30 -080030#include <sys/utsname.h>
Mark Salyzyn3ff87d82018-07-02 10:45:25 -070031#include <sys/vfs.h>
Mark Salyzynb28389f2018-06-06 13:10:40 -070032#include <unistd.h>
33
Mark Salyzyn54e47902018-08-29 10:44:33 -070034#include <algorithm>
Mark Salyzynb28389f2018-06-06 13:10:40 -070035#include <memory>
David Anderson982c3412022-02-08 22:06:44 -080036#include <optional>
Mark Salyzynb28389f2018-06-06 13:10:40 -070037#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>
Mark Salyzyn3ff87d82018-07-02 10:45:25 -070044#include <android-base/unique_fd.h>
45#include <ext4_utils/ext4_utils.h>
Mark Salyzyn1b066c32018-10-25 09:02:08 -070046#include <fs_mgr.h>
David Anderson5c475c72019-06-11 17:40:49 -070047#include <fs_mgr/file_wait.h>
Mark Salyzyn69ebd442018-06-06 13:10:40 -070048#include <fs_mgr_dm_linear.h>
Mark Salyzynb28389f2018-06-06 13:10:40 -070049#include <fs_mgr_overlayfs.h>
50#include <fstab/fstab.h>
Mark Salyzyn54e47902018-08-29 10:44:33 -070051#include <libdm/dm.h>
David Andersonc13586f2019-12-17 21:06:15 -080052#include <libfiemap/image_manager.h>
David Anderson0e330f12019-01-03 18:16:56 -080053#include <libgsi/libgsi.h>
Mark Salyzyn69ebd442018-06-06 13:10:40 -070054#include <liblp/builder.h>
55#include <liblp/liblp.h>
David Andersonc13586f2019-12-17 21:06:15 -080056#include <storage_literals/storage_literals.h>
Mark Salyzynb28389f2018-06-06 13:10:40 -070057
58#include "fs_mgr_priv.h"
David Andersonc13586f2019-12-17 21:06:15 -080059#include "libfiemap/utility.h"
Mark Salyzynb28389f2018-06-06 13:10:40 -070060
61using namespace std::literals;
Mark Salyzyn54e47902018-08-29 10:44:33 -070062using namespace android::dm;
Mark Salyzyn69ebd442018-06-06 13:10:40 -070063using namespace android::fs_mgr;
David Andersonc13586f2019-12-17 21:06:15 -080064using namespace android::storage_literals;
65using android::fiemap::FilesystemHasReliablePinning;
66using android::fiemap::IImageManager;
Mark Salyzynb28389f2018-06-06 13:10:40 -070067
Mark Salyzyn6a116942018-11-05 08:53:30 -080068namespace {
69
70bool fs_mgr_access(const std::string& path) {
Justin Yun818ff632018-11-01 17:25:39 +090071 auto save_errno = errno;
72 auto ret = access(path.c_str(), F_OK) == 0;
73 errno = save_errno;
74 return ret;
75}
76
Mark Salyzyn6d109ec2019-01-30 10:19:15 -080077// determine if a filesystem is available
78bool fs_mgr_overlayfs_filesystem_available(const std::string& filesystem) {
79 std::string filesystems;
80 if (!android::base::ReadFileToString("/proc/filesystems", &filesystems)) return false;
81 return filesystems.find("\t" + filesystem + "\n") != std::string::npos;
82}
83
Mark Salyzyn6a116942018-11-05 08:53:30 -080084} // namespace
85
Mark Salyzynb28389f2018-06-06 13:10:40 -070086#if ALLOW_ADBD_DISABLE_VERITY == 0 // If we are a user build, provide stubs
87
Mark Salyzyndffdb432019-01-24 11:08:10 -080088Fstab fs_mgr_overlayfs_candidate_list(const Fstab&) {
89 return {};
90}
91
Tom Cherry23319eb2018-11-30 16:16:05 -080092bool fs_mgr_overlayfs_mount_all(Fstab*) {
Mark Salyzynb28389f2018-06-06 13:10:40 -070093 return false;
94}
95
Mark Salyzyne0c581f2019-05-29 14:01:56 -070096bool fs_mgr_overlayfs_setup(const char*, const char*, bool* change, bool) {
Greg Kaiserb4bf8c62018-08-10 05:24:25 -070097 if (change) *change = false;
Mark Salyzynb28389f2018-06-06 13:10:40 -070098 return false;
99}
100
101bool fs_mgr_overlayfs_teardown(const char*, bool* change) {
Greg Kaiserb4bf8c62018-08-10 05:24:25 -0700102 if (change) *change = false;
Mark Salyzynb28389f2018-06-06 13:10:40 -0700103 return false;
104}
105
Mark Salyzyndd748aa2018-12-03 13:42:22 -0800106bool fs_mgr_overlayfs_is_setup() {
107 return false;
108}
109
David Andersonc13586f2019-12-17 21:06:15 -0800110namespace android {
111namespace fs_mgr {
112
Yo Chiang66d0d962020-10-27 19:07:37 +0800113void MapScratchPartitionIfNeeded(Fstab*, const std::function<bool(const std::set<std::string>&)>&) {
114}
115
Jintao Zhu84822c82021-04-21 14:31:22 +0800116void CleanupOldScratchFiles() {}
117
Yo Chiang66d0d962020-10-27 19:07:37 +0800118void TeardownAllOverlayForMountPoint(const std::string&) {}
119
David Andersonc13586f2019-12-17 21:06:15 -0800120} // namespace fs_mgr
121} // namespace android
122
Mark Salyzynb28389f2018-06-06 13:10:40 -0700123#else // ALLOW_ADBD_DISABLE_VERITY == 0
124
125namespace {
126
Yi-Yo Chiangd1ff1bc2021-02-11 22:59:11 +0800127bool fs_mgr_in_recovery() {
128 // Check the existence of recovery binary instead of using the compile time
Yi-Yo Chiang8f73f02e2022-02-23 16:20:09 +0800129 // __ANDROID_RECOVERY__ macro.
130 // If BOARD_USES_RECOVERY_AS_BOOT is true, both normal and recovery boot
131 // mode would use the same init binary, which would mean during normal boot
132 // the '/init' binary is actually a symlink pointing to
133 // init_second_stage.recovery, which would be compiled with
134 // __ANDROID_RECOVERY__ defined.
Yi-Yo Chiangd1ff1bc2021-02-11 22:59:11 +0800135 return fs_mgr_access("/system/bin/recovery");
136}
137
138bool fs_mgr_is_dsu_running() {
139 // Since android::gsi::CanBootIntoGsi() or android::gsi::MarkSystemAsGsi() is
140 // never called in recovery, the return value of android::gsi::IsGsiRunning()
141 // is not well-defined. In this case, just return false as being in recovery
142 // implies not running a DSU system.
143 if (fs_mgr_in_recovery()) return false;
144 auto saved_errno = errno;
145 auto ret = android::gsi::IsGsiRunning();
146 errno = saved_errno;
147 return ret;
148}
149
Mark Salyzyn69ebd442018-06-06 13:10:40 -0700150// list of acceptable overlayfs backing storage
151const auto kScratchMountPoint = "/mnt/scratch"s;
152const auto kCacheMountPoint = "/cache"s;
Yi-Yo Chiangd1ff1bc2021-02-11 22:59:11 +0800153
154std::vector<const std::string> OverlayMountPoints() {
155 // Never fallback to legacy cache mount point if within a DSU system,
156 // because running a DSU system implies the device supports dynamic
157 // partitions, which means legacy cache mustn't be used.
158 if (fs_mgr_is_dsu_running()) {
159 return {kScratchMountPoint};
160 }
161 return {kScratchMountPoint, kCacheMountPoint};
162}
Mark Salyzynb28389f2018-06-06 13:10:40 -0700163
Mark Salyzyn5f6b0692018-06-13 09:33:28 -0700164// Return true if everything is mounted, but before adb is started. Right
165// after 'trigger load_persist_props_action' is done.
Mark Salyzynb28389f2018-06-06 13:10:40 -0700166bool fs_mgr_boot_completed() {
Mark Salyzyn5f6b0692018-06-13 09:33:28 -0700167 return android::base::GetBoolProperty("ro.persistent_properties.ready", false);
Mark Salyzynb28389f2018-06-06 13:10:40 -0700168}
169
170bool fs_mgr_is_dir(const std::string& path) {
171 struct stat st;
172 return !stat(path.c_str(), &st) && S_ISDIR(st.st_mode);
173}
174
175// Similar test as overlayfs workdir= validation in the kernel for read-write
176// validation, except we use fs_mgr_work. Covers space and storage issues.
177bool fs_mgr_dir_is_writable(const std::string& path) {
178 auto test_directory = path + "/fs_mgr_work";
179 rmdir(test_directory.c_str());
180 auto ret = !mkdir(test_directory.c_str(), 0700);
181 return ret | !rmdir(test_directory.c_str());
182}
183
Mark Salyzyn18085412019-08-15 08:34:27 -0700184// At less than 1% or 8MB of free space return value of false,
Mark Salyzyn53c96da2018-06-13 09:33:28 -0700185// means we will try to wrap with overlayfs.
Tom Cherry23319eb2018-11-30 16:16:05 -0800186bool fs_mgr_filesystem_has_space(const std::string& mount_point) {
Mark Salyzyn53c96da2018-06-13 09:33:28 -0700187 // If we have access issues to find out space remaining, return true
188 // to prevent us trying to override with overlayfs.
189 struct statvfs vst;
Mark Salyzyn98a01282019-05-13 09:14:55 -0700190 auto save_errno = errno;
191 if (statvfs(mount_point.c_str(), &vst)) {
192 errno = save_errno;
193 return true;
194 }
Mark Salyzyn53c96da2018-06-13 09:33:28 -0700195
Mark Salyzyn18085412019-08-15 08:34:27 -0700196 static constexpr int kPercentThreshold = 1; // 1%
197 static constexpr unsigned long kSizeThreshold = 8 * 1024 * 1024; // 8MB
Mark Salyzyn53c96da2018-06-13 09:33:28 -0700198
Mark Salyzyn18085412019-08-15 08:34:27 -0700199 return (vst.f_bfree >= (vst.f_blocks * kPercentThreshold / 100)) &&
Yi-Yo Chiang67e3bbc2021-02-12 15:55:50 +0800200 (static_cast<uint64_t>(vst.f_bfree) * vst.f_frsize) >= kSizeThreshold;
Mark Salyzyn53c96da2018-06-13 09:33:28 -0700201}
202
Mark Salyzyn31c14e12019-07-31 08:33:53 -0700203const auto kPhysicalDevice = "/dev/block/by-name/"s;
David Andersonc13586f2019-12-17 21:06:15 -0800204constexpr char kScratchImageMetadata[] = "/metadata/gsi/remount/lp_metadata";
205
206// Note: this is meant only for recovery/first-stage init.
207bool ScratchIsOnData() {
Yo Chiang0267bf02020-10-21 22:25:21 +0800208 // The scratch partition of DSU is managed by gsid.
209 if (fs_mgr_is_dsu_running()) {
210 return false;
211 }
David Andersonc13586f2019-12-17 21:06:15 -0800212 return fs_mgr_access(kScratchImageMetadata);
213}
Mark Salyzyn31c14e12019-07-31 08:33:53 -0700214
215bool fs_mgr_update_blk_device(FstabEntry* entry) {
216 if (entry->fs_mgr_flags.logical) {
217 fs_mgr_update_logical_partition(entry);
218 }
219 if (fs_mgr_access(entry->blk_device)) {
220 return true;
221 }
222 if (entry->blk_device != "/dev/root") {
223 return false;
224 }
225
226 // special case for system-as-root (taimen and others)
227 auto blk_device = kPhysicalDevice + "system";
228 if (!fs_mgr_access(blk_device)) {
229 blk_device += fs_mgr_get_slot_suffix();
230 if (!fs_mgr_access(blk_device)) {
231 return false;
232 }
233 }
234 entry->blk_device = blk_device;
235 return true;
236}
237
Tom Cherry23319eb2018-11-30 16:16:05 -0800238bool fs_mgr_overlayfs_enabled(FstabEntry* entry) {
Mark Salyzynb28389f2018-06-06 13:10:40 -0700239 // readonly filesystem, can not be mount -o remount,rw
Mark Salyzync11f8e52019-01-22 08:54:56 -0800240 // for squashfs, erofs or if free space is (near) zero making such a remount
Mark Salyzyn3ff87d82018-07-02 10:45:25 -0700241 // virtually useless, or if there are shared blocks that prevent remount,rw
Mark Salyzync11f8e52019-01-22 08:54:56 -0800242 if (!fs_mgr_filesystem_has_space(entry->mount_point)) {
Mark Salyzyn1b066c32018-10-25 09:02:08 -0700243 return true;
244 }
Mark Salyzyn31c14e12019-07-31 08:33:53 -0700245
246 // blk_device needs to be setup so we can check superblock.
247 // If we fail here, because during init first stage and have doubts.
248 if (!fs_mgr_update_blk_device(entry)) {
249 return true;
Mark Salyzyn1b066c32018-10-25 09:02:08 -0700250 }
Mark Salyzyn31c14e12019-07-31 08:33:53 -0700251
252 // check if ext4 de-dupe
Mark Salyzynd202c552018-12-12 10:36:32 -0800253 auto save_errno = errno;
254 auto has_shared_blocks = fs_mgr_has_shared_blocks(entry->mount_point, entry->blk_device);
Mark Salyzynd6ef9d22019-04-11 12:58:19 -0700255 if (!has_shared_blocks && (entry->mount_point == "/system")) {
256 has_shared_blocks = fs_mgr_has_shared_blocks("/", entry->blk_device);
257 }
Mark Salyzynd202c552018-12-12 10:36:32 -0800258 errno = save_errno;
259 return has_shared_blocks;
Mark Salyzyn1b066c32018-10-25 09:02:08 -0700260}
261
262bool fs_mgr_rm_all(const std::string& path, bool* change = nullptr, int level = 0) {
263 auto save_errno = errno;
264 std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(path.c_str()), closedir);
265 if (!dir) {
266 if (errno == ENOENT) {
267 errno = save_errno;
268 return true;
269 }
270 PERROR << "opendir " << path << " depth=" << level;
271 if ((errno == EPERM) && (level != 0)) {
272 errno = save_errno;
273 return true;
274 }
275 return false;
276 }
277 dirent* entry;
278 auto ret = true;
279 while ((entry = readdir(dir.get()))) {
280 if (("."s == entry->d_name) || (".."s == entry->d_name)) continue;
281 auto file = path + "/" + entry->d_name;
282 if (entry->d_type == DT_UNKNOWN) {
283 struct stat st;
284 save_errno = errno;
285 if (!lstat(file.c_str(), &st) && (st.st_mode & S_IFDIR)) entry->d_type = DT_DIR;
286 errno = save_errno;
287 }
288 if (entry->d_type == DT_DIR) {
289 ret &= fs_mgr_rm_all(file, change, level + 1);
290 if (!rmdir(file.c_str())) {
291 if (change) *change = true;
292 } else {
293 if (errno != ENOENT) ret = false;
294 PERROR << "rmdir " << file << " depth=" << level;
295 }
296 continue;
297 }
298 if (!unlink(file.c_str())) {
299 if (change) *change = true;
300 } else {
301 if (errno != ENOENT) ret = false;
302 PERROR << "rm " << file << " depth=" << level;
303 }
304 }
305 return ret;
Mark Salyzynb28389f2018-06-06 13:10:40 -0700306}
307
Mark Salyzyne5ecbb52018-06-06 13:10:40 -0700308const auto kUpperName = "upper"s;
309const auto kWorkName = "work"s;
310const auto kOverlayTopDir = "/overlay"s;
Mark Salyzynb28389f2018-06-06 13:10:40 -0700311
312std::string fs_mgr_get_overlayfs_candidate(const std::string& mount_point) {
313 if (!fs_mgr_is_dir(mount_point)) return "";
Mark Salyzyn69ebd442018-06-06 13:10:40 -0700314 const auto base = android::base::Basename(mount_point) + "/";
Yi-Yo Chiangd1ff1bc2021-02-11 22:59:11 +0800315 for (const auto& overlay_mount_point : OverlayMountPoints()) {
Mark Salyzyn69ebd442018-06-06 13:10:40 -0700316 auto dir = overlay_mount_point + kOverlayTopDir + "/" + base;
317 auto upper = dir + kUpperName;
318 if (!fs_mgr_is_dir(upper)) continue;
319 auto work = dir + kWorkName;
320 if (!fs_mgr_is_dir(work)) continue;
321 if (!fs_mgr_dir_is_writable(work)) continue;
322 return dir;
323 }
324 return "";
Mark Salyzynb28389f2018-06-06 13:10:40 -0700325}
326
Mark Salyzyne5ecbb52018-06-06 13:10:40 -0700327const auto kLowerdirOption = "lowerdir="s;
328const auto kUpperdirOption = "upperdir="s;
Mark Salyzynb28389f2018-06-06 13:10:40 -0700329
David Anderson70d05742021-11-19 16:00:27 -0800330static inline bool KernelSupportsUserXattrs() {
331 struct utsname uts;
332 uname(&uts);
333
334 int major, minor;
335 if (sscanf(uts.release, "%d.%d", &major, &minor) != 2) {
336 return false;
337 }
338 return major > 5 || (major == 5 && minor >= 15);
339}
340
Mark Salyzynb28389f2018-06-06 13:10:40 -0700341// default options for mount_point, returns empty string for none available.
Mark Salyzynd3dc3c82018-06-13 09:33:28 -0700342std::string fs_mgr_get_overlayfs_options(const std::string& mount_point) {
343 auto candidate = fs_mgr_get_overlayfs_candidate(mount_point);
Mark Salyzynb28389f2018-06-06 13:10:40 -0700344 if (candidate.empty()) return "";
Mark Salyzyn6a116942018-11-05 08:53:30 -0800345 auto ret = kLowerdirOption + mount_point + "," + kUpperdirOption + candidate + kUpperName +
346 ",workdir=" + candidate + kWorkName;
347 if (fs_mgr_overlayfs_valid() == OverlayfsValidResult::kOverrideCredsRequired) {
348 ret += ",override_creds=off";
349 }
David Anderson70d05742021-11-19 16:00:27 -0800350 if (KernelSupportsUserXattrs()) {
351 ret += ",userxattr";
352 }
Mark Salyzyn6a116942018-11-05 08:53:30 -0800353 return ret;
Mark Salyzynb28389f2018-06-06 13:10:40 -0700354}
355
Mark Salyzyndffdb432019-01-24 11:08:10 -0800356const std::string fs_mgr_mount_point(const std::string& mount_point) {
Mark Salyzynd3dc3c82018-06-13 09:33:28 -0700357 if ("/"s != mount_point) return mount_point;
Mark Salyzynd3dc3c82018-06-13 09:33:28 -0700358 return "/system";
Mark Salyzynb28389f2018-06-06 13:10:40 -0700359}
360
Mark Salyzyn69ebd442018-06-06 13:10:40 -0700361bool fs_mgr_rw_access(const std::string& path) {
362 if (path.empty()) return false;
363 auto save_errno = errno;
364 auto ret = access(path.c_str(), R_OK | W_OK) == 0;
365 errno = save_errno;
366 return ret;
367}
368
Mark Salyzyn69ebd442018-06-06 13:10:40 -0700369bool fs_mgr_overlayfs_already_mounted(const std::string& mount_point, bool overlay_only = true) {
Tom Cherry23319eb2018-11-30 16:16:05 -0800370 Fstab fstab;
Mark Salyzyn98a01282019-05-13 09:14:55 -0700371 auto save_errno = errno;
Tom Cherry23319eb2018-11-30 16:16:05 -0800372 if (!ReadFstabFromFile("/proc/mounts", &fstab)) {
373 return false;
374 }
Mark Salyzyn98a01282019-05-13 09:14:55 -0700375 errno = save_errno;
Mark Salyzyna526bbe2018-09-20 15:23:00 -0700376 const auto lowerdir = kLowerdirOption + mount_point;
Tom Cherry23319eb2018-11-30 16:16:05 -0800377 for (const auto& entry : fstab) {
378 if (overlay_only && "overlay" != entry.fs_type && "overlayfs" != entry.fs_type) continue;
379 if (mount_point != entry.mount_point) continue;
Mark Salyzyn69ebd442018-06-06 13:10:40 -0700380 if (!overlay_only) return true;
Tom Cherry23319eb2018-11-30 16:16:05 -0800381 const auto options = android::base::Split(entry.fs_options, ",");
Mark Salyzyna526bbe2018-09-20 15:23:00 -0700382 for (const auto& opt : options) {
383 if (opt == lowerdir) {
384 return true;
385 }
386 }
387 }
388 return false;
389}
390
Tom Cherry23319eb2018-11-30 16:16:05 -0800391bool fs_mgr_wants_overlayfs(FstabEntry* entry) {
Mark Salyzynb28389f2018-06-06 13:10:40 -0700392 // Don't check entries that are managed by vold.
Tom Cherry23319eb2018-11-30 16:16:05 -0800393 if (entry->fs_mgr_flags.vold_managed || entry->fs_mgr_flags.recovery_only) return false;
Mark Salyzynb28389f2018-06-06 13:10:40 -0700394
Yifan Hongacf859a2019-01-09 11:13:09 -0800395 // *_other doesn't want overlayfs.
396 if (entry->fs_mgr_flags.slot_select_other) return false;
397
Mark Salyzynb28389f2018-06-06 13:10:40 -0700398 // Only concerned with readonly partitions.
Tom Cherry23319eb2018-11-30 16:16:05 -0800399 if (!(entry->flags & MS_RDONLY)) return false;
Mark Salyzynb28389f2018-06-06 13:10:40 -0700400
401 // If unbindable, do not allow overlayfs as this could expose us to
402 // security issues. On Android, this could also be used to turn off
403 // the ability to overlay an otherwise acceptable filesystem since
404 // /system and /vendor are never bound(sic) to.
Tom Cherry23319eb2018-11-30 16:16:05 -0800405 if (entry->flags & MS_UNBINDABLE) return false;
Mark Salyzynb28389f2018-06-06 13:10:40 -0700406
Tom Cherry23319eb2018-11-30 16:16:05 -0800407 if (!fs_mgr_overlayfs_enabled(entry)) return false;
Mark Salyzynb28389f2018-06-06 13:10:40 -0700408
Mark Salyzyn54e47902018-08-29 10:44:33 -0700409 return true;
Mark Salyzynb28389f2018-06-06 13:10:40 -0700410}
Mark Salyzyne5ecbb52018-06-06 13:10:40 -0700411constexpr char kOverlayfsFileContext[] = "u:object_r:overlayfs_file:s0";
Mark Salyzyn40b45b82018-08-27 12:41:50 -0700412
Mark Salyzyn780db022018-06-06 13:10:40 -0700413bool fs_mgr_overlayfs_setup_dir(const std::string& dir, std::string* overlay, bool* change) {
414 auto ret = true;
415 auto top = dir + kOverlayTopDir;
416 if (setfscreatecon(kOverlayfsFileContext)) {
417 ret = false;
418 PERROR << "setfscreatecon " << kOverlayfsFileContext;
419 }
420 auto save_errno = errno;
421 if (!mkdir(top.c_str(), 0755)) {
422 if (change) *change = true;
423 } else if (errno != EEXIST) {
424 ret = false;
425 PERROR << "mkdir " << top;
426 } else {
427 errno = save_errno;
428 }
429 setfscreatecon(nullptr);
430
431 if (overlay) *overlay = std::move(top);
432 return ret;
433}
434
Mark Salyzynb28389f2018-06-06 13:10:40 -0700435bool fs_mgr_overlayfs_setup_one(const std::string& overlay, const std::string& mount_point,
436 bool* change) {
437 auto ret = true;
Mark Salyzynfab9f082019-02-04 14:59:16 -0800438 if (fs_mgr_overlayfs_already_mounted(mount_point)) return ret;
Mark Salyzyne5ecbb52018-06-06 13:10:40 -0700439 auto fsrec_mount_point = overlay + "/" + android::base::Basename(mount_point) + "/";
Mark Salyzyn40b45b82018-08-27 12:41:50 -0700440
Mark Salyzyne5ecbb52018-06-06 13:10:40 -0700441 if (setfscreatecon(kOverlayfsFileContext)) {
Mark Salyzyn40b45b82018-08-27 12:41:50 -0700442 ret = false;
Mark Salyzyn03df4232018-08-29 10:44:33 -0700443 PERROR << "setfscreatecon " << kOverlayfsFileContext;
Mark Salyzyn40b45b82018-08-27 12:41:50 -0700444 }
Mark Salyzynb28389f2018-06-06 13:10:40 -0700445 auto save_errno = errno;
446 if (!mkdir(fsrec_mount_point.c_str(), 0755)) {
447 if (change) *change = true;
448 } else if (errno != EEXIST) {
449 ret = false;
Mark Salyzyn03df4232018-08-29 10:44:33 -0700450 PERROR << "mkdir " << fsrec_mount_point;
Mark Salyzynb28389f2018-06-06 13:10:40 -0700451 } else {
452 errno = save_errno;
453 }
454
455 save_errno = errno;
Mark Salyzyne5ecbb52018-06-06 13:10:40 -0700456 if (!mkdir((fsrec_mount_point + kWorkName).c_str(), 0755)) {
Mark Salyzynb28389f2018-06-06 13:10:40 -0700457 if (change) *change = true;
458 } else if (errno != EEXIST) {
459 ret = false;
Mark Salyzyn03df4232018-08-29 10:44:33 -0700460 PERROR << "mkdir " << fsrec_mount_point << kWorkName;
Mark Salyzynb28389f2018-06-06 13:10:40 -0700461 } else {
462 errno = save_errno;
463 }
Mark Salyzyn40b45b82018-08-27 12:41:50 -0700464 setfscreatecon(nullptr);
Mark Salyzynb28389f2018-06-06 13:10:40 -0700465
466 auto new_context = fs_mgr_get_context(mount_point);
467 if (!new_context.empty() && setfscreatecon(new_context.c_str())) {
468 ret = false;
Mark Salyzyn03df4232018-08-29 10:44:33 -0700469 PERROR << "setfscreatecon " << new_context;
Mark Salyzynb28389f2018-06-06 13:10:40 -0700470 }
Mark Salyzyne5ecbb52018-06-06 13:10:40 -0700471 auto upper = fsrec_mount_point + kUpperName;
Mark Salyzynb28389f2018-06-06 13:10:40 -0700472 save_errno = errno;
473 if (!mkdir(upper.c_str(), 0755)) {
474 if (change) *change = true;
475 } else if (errno != EEXIST) {
476 ret = false;
Mark Salyzyn03df4232018-08-29 10:44:33 -0700477 PERROR << "mkdir " << upper;
Mark Salyzynb28389f2018-06-06 13:10:40 -0700478 } else {
479 errno = save_errno;
480 }
481 if (!new_context.empty()) setfscreatecon(nullptr);
482
483 return ret;
484}
485
Mark Salyzyn69ebd442018-06-06 13:10:40 -0700486uint32_t fs_mgr_overlayfs_slot_number() {
487 return SlotNumberForSlotSuffix(fs_mgr_get_slot_suffix());
488}
489
490std::string fs_mgr_overlayfs_super_device(uint32_t slot_number) {
Mark Salyzynf2693122018-11-26 09:57:17 -0800491 return kPhysicalDevice + fs_mgr_get_super_partition_name(slot_number);
Mark Salyzyn69ebd442018-06-06 13:10:40 -0700492}
493
Tom Cherry23319eb2018-11-30 16:16:05 -0800494bool fs_mgr_overlayfs_has_logical(const Fstab& fstab) {
495 for (const auto& entry : fstab) {
496 if (entry.fs_mgr_flags.logical) {
497 return true;
498 }
Mark Salyzyn69ebd442018-06-06 13:10:40 -0700499 }
500 return false;
501}
502
Mark Salyzync0966c92018-11-26 09:57:17 -0800503void fs_mgr_overlayfs_umount_scratch() {
504 // Lazy umount will allow us to move on and possibly later
505 // establish a new fresh mount without requiring a reboot should
506 // the developer wish to restart. Old references should melt
507 // away or have no data. Main goal is to shut the door on the
508 // current overrides with an expectation of a subsequent reboot,
509 // thus any errors here are ignored.
510 umount2(kScratchMountPoint.c_str(), MNT_DETACH);
511 LINFO << "umount(" << kScratchMountPoint << ")";
512 rmdir(kScratchMountPoint.c_str());
513}
514
Mark Salyzyn69ebd442018-06-06 13:10:40 -0700515bool fs_mgr_overlayfs_teardown_scratch(const std::string& overlay, bool* change) {
516 // umount and delete kScratchMountPoint storage if we have logical partitions
517 if (overlay != kScratchMountPoint) return true;
Mark Salyzyn69ebd442018-06-06 13:10:40 -0700518
Yo Chiang0267bf02020-10-21 22:25:21 +0800519 // Validation check.
520 if (fs_mgr_is_dsu_running()) {
521 LERROR << "Destroying DSU scratch is not allowed.";
522 return false;
523 }
524
Mark Salyzyn69ebd442018-06-06 13:10:40 -0700525 auto save_errno = errno;
526 if (fs_mgr_overlayfs_already_mounted(kScratchMountPoint, false)) {
Mark Salyzync0966c92018-11-26 09:57:17 -0800527 fs_mgr_overlayfs_umount_scratch();
Mark Salyzyn69ebd442018-06-06 13:10:40 -0700528 }
David Andersonc13586f2019-12-17 21:06:15 -0800529
530 const auto partition_name = android::base::Basename(kScratchMountPoint);
531
532 auto images = IImageManager::Open("remount", 10s);
533 if (images && images->BackingImageExists(partition_name)) {
534#if defined __ANDROID_RECOVERY__
535 if (!images->DisableImage(partition_name)) {
536 return false;
537 }
538#else
539 if (!images->UnmapImageIfExists(partition_name) ||
540 !images->DeleteBackingImage(partition_name)) {
541 return false;
542 }
543#endif
544 }
545
546 auto slot_number = fs_mgr_overlayfs_slot_number();
547 auto super_device = fs_mgr_overlayfs_super_device(slot_number);
548 if (!fs_mgr_rw_access(super_device)) return true;
549
Mark Salyzyn69ebd442018-06-06 13:10:40 -0700550 auto builder = MetadataBuilder::New(super_device, slot_number);
551 if (!builder) {
552 errno = save_errno;
553 return true;
554 }
Mark Salyzyn69ebd442018-06-06 13:10:40 -0700555 if (builder->FindPartition(partition_name) == nullptr) {
556 errno = save_errno;
557 return true;
558 }
559 builder->RemovePartition(partition_name);
560 auto metadata = builder->Export();
561 if (metadata && UpdatePartitionTable(super_device, *metadata.get(), slot_number)) {
562 if (change) *change = true;
David Anderson470fe2b2019-07-10 18:09:50 -0700563 if (!DestroyLogicalPartition(partition_name)) return false;
Mark Salyzyn69ebd442018-06-06 13:10:40 -0700564 } else {
Mark Salyzyncb2f6b62018-11-20 12:59:21 -0800565 LERROR << "delete partition " << overlay;
Mark Salyzyn69ebd442018-06-06 13:10:40 -0700566 return false;
567 }
568 errno = save_errno;
569 return true;
570}
571
Mark Salyzyn336f7592018-06-06 13:10:40 -0700572bool fs_mgr_overlayfs_teardown_one(const std::string& overlay, const std::string& mount_point,
Yo Chiang0267bf02020-10-21 22:25:21 +0800573 bool* change, bool* should_destroy_scratch = nullptr) {
Mark Salyzyn336f7592018-06-06 13:10:40 -0700574 const auto top = overlay + kOverlayTopDir;
Mark Salyzyn336f7592018-06-06 13:10:40 -0700575
Yo Chiang0267bf02020-10-21 22:25:21 +0800576 if (!fs_mgr_access(top)) {
577 if (should_destroy_scratch) *should_destroy_scratch = true;
578 return true;
579 }
Mark Salyzynaace4862018-03-16 11:00:26 -0700580
581 auto cleanup_all = mount_point.empty();
Mark Salyzyn9b44e802018-08-29 10:44:33 -0700582 const auto partition_name = android::base::Basename(mount_point);
583 const auto oldpath = top + (cleanup_all ? "" : ("/" + partition_name));
584 const auto newpath = cleanup_all ? overlay + "/." + kOverlayTopDir.substr(1) + ".teardown"
585 : top + "/." + partition_name + ".teardown";
Mark Salyzyn336f7592018-06-06 13:10:40 -0700586 auto ret = fs_mgr_rm_all(newpath);
Mark Salyzynaace4862018-03-16 11:00:26 -0700587 auto save_errno = errno;
Mark Salyzyn336f7592018-06-06 13:10:40 -0700588 if (!rename(oldpath.c_str(), newpath.c_str())) {
589 if (change) *change = true;
590 } else if (errno != ENOENT) {
591 ret = false;
592 PERROR << "mv " << oldpath << " " << newpath;
593 } else {
594 errno = save_errno;
595 }
596 ret &= fs_mgr_rm_all(newpath, change);
597 save_errno = errno;
598 if (!rmdir(newpath.c_str())) {
599 if (change) *change = true;
600 } else if (errno != ENOENT) {
601 ret = false;
602 PERROR << "rmdir " << newpath;
603 } else {
604 errno = save_errno;
605 }
Mark Salyzynaace4862018-03-16 11:00:26 -0700606 if (!cleanup_all) {
Mark Salyzyn336f7592018-06-06 13:10:40 -0700607 save_errno = errno;
608 if (!rmdir(top.c_str())) {
609 if (change) *change = true;
Mark Salyzyn69ebd442018-06-06 13:10:40 -0700610 cleanup_all = true;
Mark Salyzyn9b44e802018-08-29 10:44:33 -0700611 } else if (errno == ENOTEMPTY) {
612 cleanup_all = true;
613 // cleanup all if the content is all hidden (leading .)
614 std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(top.c_str()), closedir);
615 if (!dir) {
616 PERROR << "opendir " << top;
617 } else {
618 dirent* entry;
619 while ((entry = readdir(dir.get()))) {
620 if (entry->d_name[0] != '.') {
621 cleanup_all = false;
622 break;
623 }
624 }
625 }
626 errno = save_errno;
627 } else if (errno == ENOENT) {
628 cleanup_all = true;
629 errno = save_errno;
630 } else {
Mark Salyzyn336f7592018-06-06 13:10:40 -0700631 ret = false;
632 PERROR << "rmdir " << top;
Mark Salyzyn336f7592018-06-06 13:10:40 -0700633 }
634 }
Yo Chiang0267bf02020-10-21 22:25:21 +0800635 if (should_destroy_scratch) *should_destroy_scratch = cleanup_all;
Mark Salyzyn336f7592018-06-06 13:10:40 -0700636 return ret;
637}
638
Mark Salyzyn8cf21032019-05-29 08:49:11 -0700639bool fs_mgr_overlayfs_set_shared_mount(const std::string& mount_point, bool shared_flag) {
640 auto ret = mount(nullptr, mount_point.c_str(), nullptr, shared_flag ? MS_SHARED : MS_PRIVATE,
641 nullptr);
642 if (ret) {
643 PERROR << "__mount(target=" << mount_point
644 << ",flag=" << (shared_flag ? "MS_SHARED" : "MS_PRIVATE") << ")=" << ret;
645 return false;
646 }
647 return true;
648}
649
650bool fs_mgr_overlayfs_move_mount(const std::string& source, const std::string& target) {
651 auto ret = mount(source.c_str(), target.c_str(), nullptr, MS_MOVE, nullptr);
652 if (ret) {
653 PERROR << "__mount(source=" << source << ",target=" << target << ",flag=MS_MOVE)=" << ret;
654 return false;
655 }
656 return true;
657}
658
659struct mount_info {
660 std::string mount_point;
661 bool shared_flag;
662};
663
664std::vector<mount_info> ReadMountinfoFromFile(const std::string& path) {
665 std::vector<mount_info> info;
666
667 auto file = std::unique_ptr<FILE, decltype(&fclose)>{fopen(path.c_str(), "re"), fclose};
668 if (!file) {
669 PERROR << __FUNCTION__ << "(): cannot open file: '" << path << "'";
670 return info;
671 }
672
673 ssize_t len;
674 size_t alloc_len = 0;
675 char* line = nullptr;
676 while ((len = getline(&line, &alloc_len, file.get())) != -1) {
677 /* if the last character is a newline, shorten the string by 1 byte */
678 if (line[len - 1] == '\n') {
679 line[len - 1] = '\0';
680 }
681
682 static constexpr char delim[] = " \t";
683 char* save_ptr;
684 if (!strtok_r(line, delim, &save_ptr)) {
685 LERROR << "Error parsing mount ID";
686 break;
687 }
688 if (!strtok_r(nullptr, delim, &save_ptr)) {
689 LERROR << "Error parsing parent ID";
690 break;
691 }
692 if (!strtok_r(nullptr, delim, &save_ptr)) {
693 LERROR << "Error parsing mount source";
694 break;
695 }
696 if (!strtok_r(nullptr, delim, &save_ptr)) {
697 LERROR << "Error parsing root";
698 break;
699 }
700
701 char* p;
702 if (!(p = strtok_r(nullptr, delim, &save_ptr))) {
703 LERROR << "Error parsing mount_point";
704 break;
705 }
706 mount_info entry = {p, false};
707
708 if (!strtok_r(nullptr, delim, &save_ptr)) {
709 LERROR << "Error parsing mount_flags";
710 break;
711 }
712
713 while ((p = strtok_r(nullptr, delim, &save_ptr))) {
714 if ((p[0] == '-') && (p[1] == '\0')) break;
715 if (android::base::StartsWith(p, "shared:")) entry.shared_flag = true;
716 }
717 if (!p) {
718 LERROR << "Error parsing fields";
719 break;
720 }
721 info.emplace_back(std::move(entry));
722 }
723
724 free(line);
725 if (info.empty()) {
726 LERROR << __FUNCTION__ << "(): failed to load mountinfo from : '" << path << "'";
727 }
728 return info;
729}
730
Mark Salyzynd3dc3c82018-06-13 09:33:28 -0700731bool fs_mgr_overlayfs_mount(const std::string& mount_point) {
732 auto options = fs_mgr_get_overlayfs_options(mount_point);
Mark Salyzynb28389f2018-06-06 13:10:40 -0700733 if (options.empty()) return false;
734
Mark Salyzyn8cf21032019-05-29 08:49:11 -0700735 auto retval = true;
736 auto save_errno = errno;
737
738 struct move_entry {
739 std::string mount_point;
740 std::string dir;
741 bool shared_flag;
742 };
743 std::vector<move_entry> move;
744 auto parent_private = false;
745 auto parent_made_private = false;
746 auto dev_private = false;
747 auto dev_made_private = false;
748 for (auto& entry : ReadMountinfoFromFile("/proc/self/mountinfo")) {
749 if ((entry.mount_point == mount_point) && !entry.shared_flag) {
750 parent_private = true;
751 }
752 if ((entry.mount_point == "/dev") && !entry.shared_flag) {
753 dev_private = true;
754 }
755
756 if (!android::base::StartsWith(entry.mount_point, mount_point + "/")) {
757 continue;
758 }
759 if (std::find_if(move.begin(), move.end(), [&entry](const auto& it) {
760 return android::base::StartsWith(entry.mount_point, it.mount_point + "/");
761 }) != move.end()) {
762 continue;
763 }
764
765 // use as the bound directory in /dev.
766 auto new_context = fs_mgr_get_context(entry.mount_point);
767 if (!new_context.empty() && setfscreatecon(new_context.c_str())) {
768 PERROR << "setfscreatecon " << new_context;
769 }
770 move_entry new_entry = {std::move(entry.mount_point), "/dev/TemporaryDir-XXXXXX",
771 entry.shared_flag};
772 const auto target = mkdtemp(new_entry.dir.data());
773 if (!target) {
774 retval = false;
775 save_errno = errno;
776 PERROR << "temporary directory for MS_BIND";
777 setfscreatecon(nullptr);
778 continue;
779 }
780 setfscreatecon(nullptr);
781
782 if (!parent_private && !parent_made_private) {
783 parent_made_private = fs_mgr_overlayfs_set_shared_mount(mount_point, false);
784 }
785 if (new_entry.shared_flag) {
786 new_entry.shared_flag = fs_mgr_overlayfs_set_shared_mount(new_entry.mount_point, false);
787 }
788 if (!fs_mgr_overlayfs_move_mount(new_entry.mount_point, new_entry.dir)) {
789 retval = false;
790 save_errno = errno;
791 if (new_entry.shared_flag) {
792 fs_mgr_overlayfs_set_shared_mount(new_entry.mount_point, true);
793 }
794 continue;
795 }
796 move.emplace_back(std::move(new_entry));
797 }
798
Mark Salyzynb28389f2018-06-06 13:10:40 -0700799 // hijack __mount() report format to help triage
Mark Salyzynd3dc3c82018-06-13 09:33:28 -0700800 auto report = "__mount(source=overlay,target="s + mount_point + ",type=overlay";
Mark Salyzynb28389f2018-06-06 13:10:40 -0700801 const auto opt_list = android::base::Split(options, ",");
Chih-Hung Hsieh1b7b7972018-12-11 10:34:33 -0800802 for (const auto& opt : opt_list) {
Mark Salyzyne5ecbb52018-06-06 13:10:40 -0700803 if (android::base::StartsWith(opt, kUpperdirOption)) {
Mark Salyzynb28389f2018-06-06 13:10:40 -0700804 report = report + "," + opt;
805 break;
806 }
807 }
808 report = report + ")=";
809
Mark Salyzyn808763e2019-08-28 12:53:26 -0700810 auto ret = mount("overlay", mount_point.c_str(), "overlay", MS_RDONLY | MS_NOATIME,
Mark Salyzynb28389f2018-06-06 13:10:40 -0700811 options.c_str());
812 if (ret) {
Mark Salyzyn8cf21032019-05-29 08:49:11 -0700813 retval = false;
814 save_errno = errno;
Mark Salyzynb28389f2018-06-06 13:10:40 -0700815 PERROR << report << ret;
Mark Salyzynb28389f2018-06-06 13:10:40 -0700816 } else {
817 LINFO << report << ret;
Mark Salyzynb28389f2018-06-06 13:10:40 -0700818 }
Mark Salyzyn8cf21032019-05-29 08:49:11 -0700819
820 // Move submounts back.
821 for (const auto& entry : move) {
822 if (!dev_private && !dev_made_private) {
823 dev_made_private = fs_mgr_overlayfs_set_shared_mount("/dev", false);
824 }
825
826 if (!fs_mgr_overlayfs_move_mount(entry.dir, entry.mount_point)) {
827 retval = false;
828 save_errno = errno;
829 } else if (entry.shared_flag &&
830 !fs_mgr_overlayfs_set_shared_mount(entry.mount_point, true)) {
831 retval = false;
832 save_errno = errno;
833 }
834 rmdir(entry.dir.c_str());
835 }
836 if (dev_made_private) {
837 fs_mgr_overlayfs_set_shared_mount("/dev", true);
838 }
839 if (parent_made_private) {
840 fs_mgr_overlayfs_set_shared_mount(mount_point, true);
841 }
842
843 errno = save_errno;
844 return retval;
Mark Salyzynb28389f2018-06-06 13:10:40 -0700845}
846
Mark Salyzyn69ebd442018-06-06 13:10:40 -0700847// Mount kScratchMountPoint
Yifan Hong3be2c7a2019-01-08 13:33:52 -0800848bool fs_mgr_overlayfs_mount_scratch(const std::string& device_path, const std::string mnt_type,
849 bool readonly = false) {
850 if (readonly) {
851 if (!fs_mgr_access(device_path)) return false;
852 } else {
853 if (!fs_mgr_rw_access(device_path)) return false;
854 }
855
Mark Salyzyn60a76f32019-03-14 15:34:35 -0700856 auto f2fs = fs_mgr_is_f2fs(device_path);
857 auto ext4 = fs_mgr_is_ext4(device_path);
858 if (!f2fs && !ext4) return false;
859
Mark Salyzyn69ebd442018-06-06 13:10:40 -0700860 if (setfscreatecon(kOverlayfsFileContext)) {
861 PERROR << "setfscreatecon " << kOverlayfsFileContext;
862 }
863 if (mkdir(kScratchMountPoint.c_str(), 0755) && (errno != EEXIST)) {
864 PERROR << "create " << kScratchMountPoint;
865 }
866
Tom Cherry23319eb2018-11-30 16:16:05 -0800867 FstabEntry entry;
868 entry.blk_device = device_path;
869 entry.mount_point = kScratchMountPoint;
870 entry.fs_type = mnt_type;
Mark Salyzyn60a76f32019-03-14 15:34:35 -0700871 if ((mnt_type == "f2fs") && !f2fs) entry.fs_type = "ext4";
872 if ((mnt_type == "ext4") && !ext4) entry.fs_type = "f2fs";
Mark Salyzyn93ce58d2020-02-12 11:43:13 -0800873 entry.flags = MS_NOATIME | MS_RDONLY;
874 auto mounted = true;
875 if (!readonly) {
876 if (entry.fs_type == "ext4") {
877 // check if ext4 de-dupe
878 entry.flags |= MS_RDONLY;
879 auto save_errno = errno;
880 mounted = fs_mgr_do_mount_one(entry) == 0;
881 if (mounted) {
882 mounted = !fs_mgr_has_shared_blocks(entry.mount_point, entry.blk_device);
883 fs_mgr_overlayfs_umount_scratch();
884 }
885 errno = save_errno;
886 }
887 entry.flags &= ~MS_RDONLY;
Jaegeuk Kimbbad87a2021-12-29 13:17:15 -0800888 entry.flags |= MS_SYNCHRONOUS;
889 entry.fs_options = "nodiscard";
Yifan Hongccdba572019-01-08 13:33:52 -0800890 fs_mgr_set_blk_ro(device_path, false);
891 }
Jaegeuk Kim06db8032022-01-06 17:28:41 -0800892 // check_fs requires apex runtime library
893 if (fs_mgr_overlayfs_already_mounted("/data", false)) {
894 entry.fs_mgr_flags.check = true;
895 }
Mark Salyzyn69ebd442018-06-06 13:10:40 -0700896 auto save_errno = errno;
Mark Salyzyn93ce58d2020-02-12 11:43:13 -0800897 if (mounted) mounted = fs_mgr_do_mount_one(entry) == 0;
Mark Salyzyn6b313de2018-08-29 10:44:33 -0700898 if (!mounted) {
Mark Salyzyn60a76f32019-03-14 15:34:35 -0700899 if ((entry.fs_type == "f2fs") && ext4) {
Tom Cherry23319eb2018-11-30 16:16:05 -0800900 entry.fs_type = "ext4";
Mark Salyzyn60a76f32019-03-14 15:34:35 -0700901 mounted = fs_mgr_do_mount_one(entry) == 0;
902 } else if ((entry.fs_type == "ext4") && f2fs) {
Tom Cherry23319eb2018-11-30 16:16:05 -0800903 entry.fs_type = "f2fs";
Mark Salyzyn60a76f32019-03-14 15:34:35 -0700904 mounted = fs_mgr_do_mount_one(entry) == 0;
Mark Salyzyn6b313de2018-08-29 10:44:33 -0700905 }
Mark Salyzyn6b313de2018-08-29 10:44:33 -0700906 if (!mounted) save_errno = errno;
907 }
Mark Salyzyn69ebd442018-06-06 13:10:40 -0700908 setfscreatecon(nullptr);
909 if (!mounted) rmdir(kScratchMountPoint.c_str());
910 errno = save_errno;
911 return mounted;
912}
913
914const std::string kMkF2fs("/system/bin/make_f2fs");
915const std::string kMkExt4("/system/bin/mke2fs");
916
Mark Salyzyn6b313de2018-08-29 10:44:33 -0700917// Only a suggestion for _first_ try during mounting
Mark Salyzyn69ebd442018-06-06 13:10:40 -0700918std::string fs_mgr_overlayfs_scratch_mount_type() {
Mark Salyzyn6d109ec2019-01-30 10:19:15 -0800919 if (!access(kMkF2fs.c_str(), X_OK) && fs_mgr_overlayfs_filesystem_available("f2fs")) {
920 return "f2fs";
921 }
922 if (!access(kMkExt4.c_str(), X_OK) && fs_mgr_overlayfs_filesystem_available("ext4")) {
923 return "ext4";
924 }
Mark Salyzyn69ebd442018-06-06 13:10:40 -0700925 return "auto";
926}
927
David Anderson69def122019-12-15 22:51:33 -0800928// Note: we do not check access() here except for the super partition, since
929// in first-stage init we wouldn't have registed by-name symlinks for "other"
930// partitions that won't be mounted.
931static std::string GetPhysicalScratchDevice() {
Mark Salyzynf2693122018-11-26 09:57:17 -0800932 auto slot_number = fs_mgr_overlayfs_slot_number();
933 auto super_device = fs_mgr_overlayfs_super_device(slot_number);
934 auto path = fs_mgr_overlayfs_super_device(slot_number == 0);
David Anderson864021f2019-12-10 21:07:51 -0800935 if (super_device != path) {
David Anderson69def122019-12-15 22:51:33 -0800936 return path;
David Anderson864021f2019-12-10 21:07:51 -0800937 }
938 if (fs_mgr_access(super_device)) {
David Anderson69def122019-12-15 22:51:33 -0800939 // Do not try to use system_other on a DAP device.
940 return "";
David Anderson864021f2019-12-10 21:07:51 -0800941 }
942
943 auto other_slot = fs_mgr_get_other_slot_suffix();
944 if (!other_slot.empty()) {
David Anderson69def122019-12-15 22:51:33 -0800945 return kPhysicalDevice + "system" + other_slot;
Mark Salyzynf2693122018-11-26 09:57:17 -0800946 }
David Anderson69def122019-12-15 22:51:33 -0800947 return "";
David Anderson864021f2019-12-10 21:07:51 -0800948}
949
Yo Chiang0267bf02020-10-21 22:25:21 +0800950// Note: The scratch partition of DSU is managed by gsid, and should be initialized during
951// first-stage-mount. Just check if the DM device for DSU scratch partition is created or not.
952static std::string GetDsuScratchDevice() {
953 auto& dm = DeviceMapper::Instance();
954 std::string device;
955 if (dm.GetState(android::gsi::kDsuScratch) != DmDeviceState::INVALID &&
956 dm.GetDmDevicePathByName(android::gsi::kDsuScratch, &device)) {
957 return device;
958 }
959 return "";
960}
961
David Anderson69def122019-12-15 22:51:33 -0800962// This returns the scratch device that was detected during early boot (first-
963// stage init). If the device was created later, for example during setup for
964// the adb remount command, it can return an empty string since it does not
David Andersonc13586f2019-12-17 21:06:15 -0800965// query ImageManager. (Note that ImageManager in first-stage init will always
966// use device-mapper, since /data is not available to use loop devices.)
David Anderson69def122019-12-15 22:51:33 -0800967static std::string GetBootScratchDevice() {
Yo Chiang0267bf02020-10-21 22:25:21 +0800968 // Note: fs_mgr_is_dsu_running() always returns false in recovery or fastbootd.
969 if (fs_mgr_is_dsu_running()) {
970 return GetDsuScratchDevice();
971 }
972
David Anderson69def122019-12-15 22:51:33 -0800973 auto& dm = DeviceMapper::Instance();
David Anderson864021f2019-12-10 21:07:51 -0800974
David Anderson69def122019-12-15 22:51:33 -0800975 // If there is a scratch partition allocated in /data or on super, we
976 // automatically prioritize that over super_other or system_other.
977 // Some devices, for example, have a write-protected eMMC and the
978 // super partition cannot be used even if it exists.
979 std::string device;
980 auto partition_name = android::base::Basename(kScratchMountPoint);
981 if (dm.GetState(partition_name) != DmDeviceState::INVALID &&
982 dm.GetDmDevicePathByName(partition_name, &device)) {
983 return device;
David Anderson864021f2019-12-10 21:07:51 -0800984 }
David Anderson69def122019-12-15 22:51:33 -0800985
986 // There is no dynamic scratch, so try and find a physical one.
987 return GetPhysicalScratchDevice();
David Anderson864021f2019-12-10 21:07:51 -0800988}
989
Mark Salyzynd14eb572018-12-05 10:19:48 -0800990bool fs_mgr_overlayfs_make_scratch(const std::string& scratch_device, const std::string& mnt_type) {
991 // Force mkfs by design for overlay support of adb remount, simplify and
992 // thus do not rely on fsck to correct problems that could creep in.
993 auto command = ""s;
994 if (mnt_type == "f2fs") {
995 command = kMkF2fs + " -w 4096 -f -d1 -l" + android::base::Basename(kScratchMountPoint);
996 } else if (mnt_type == "ext4") {
Mark Salyzyn6d109ec2019-01-30 10:19:15 -0800997 command = kMkExt4 + " -F -b 4096 -t ext4 -m 0 -O has_journal -M " + kScratchMountPoint;
Mark Salyzynd14eb572018-12-05 10:19:48 -0800998 } else {
999 errno = ESRCH;
1000 LERROR << mnt_type << " has no mkfs cookbook";
1001 return false;
1002 }
Mark Salyzyn45607142019-04-17 11:21:12 -07001003 command += " " + scratch_device + " >/dev/null 2>/dev/null </dev/null";
Yifan Hongccdba572019-01-08 13:33:52 -08001004 fs_mgr_set_blk_ro(scratch_device, false);
Mark Salyzynd14eb572018-12-05 10:19:48 -08001005 auto ret = system(command.c_str());
1006 if (ret) {
1007 LERROR << "make " << mnt_type << " filesystem on " << scratch_device << " return=" << ret;
1008 return false;
1009 }
1010 return true;
1011}
1012
Mark Salyzync3fc2aa2019-04-30 13:21:04 -07001013static void TruncatePartitionsWithSuffix(MetadataBuilder* builder, const std::string& suffix) {
1014 auto& dm = DeviceMapper::Instance();
1015
1016 // Remove <other> partitions
1017 for (const auto& group : builder->ListGroups()) {
1018 for (const auto& part : builder->ListPartitionsInGroup(group)) {
1019 const auto& name = part->name();
1020 if (!android::base::EndsWith(name, suffix)) {
1021 continue;
1022 }
David Anderson470fe2b2019-07-10 18:09:50 -07001023 if (dm.GetState(name) != DmDeviceState::INVALID && !DestroyLogicalPartition(name)) {
Mark Salyzync3fc2aa2019-04-30 13:21:04 -07001024 continue;
1025 }
1026 builder->ResizePartition(builder->FindPartition(name), 0);
1027 }
1028 }
1029}
1030
David Andersona3bf8472019-12-10 20:43:40 -08001031// Create or update a scratch partition within super.
David Anderson69def122019-12-15 22:51:33 -08001032static bool CreateDynamicScratch(std::string* scratch_device, bool* partition_exists,
1033 bool* change) {
David Andersona3bf8472019-12-10 20:43:40 -08001034 const auto partition_name = android::base::Basename(kScratchMountPoint);
1035
1036 auto& dm = DeviceMapper::Instance();
1037 *partition_exists = dm.GetState(partition_name) != DmDeviceState::INVALID;
1038
Mark Salyzyn13a66052018-12-05 10:45:06 -08001039 auto partition_create = !*partition_exists;
Mark Salyzyncb2f6b62018-11-20 12:59:21 -08001040 auto slot_number = fs_mgr_overlayfs_slot_number();
1041 auto super_device = fs_mgr_overlayfs_super_device(slot_number);
Mark Salyzyncb2f6b62018-11-20 12:59:21 -08001042 auto builder = MetadataBuilder::New(super_device, slot_number);
1043 if (!builder) {
1044 LERROR << "open " << super_device << " metadata";
1045 return false;
1046 }
Mark Salyzyncb2f6b62018-11-20 12:59:21 -08001047 auto partition = builder->FindPartition(partition_name);
Mark Salyzyn13a66052018-12-05 10:45:06 -08001048 *partition_exists = partition != nullptr;
Mark Salyzyncb2f6b62018-11-20 12:59:21 -08001049 auto changed = false;
Mark Salyzyn13a66052018-12-05 10:45:06 -08001050 if (!*partition_exists) {
Mark Salyzyncb2f6b62018-11-20 12:59:21 -08001051 partition = builder->AddPartition(partition_name, LP_PARTITION_ATTR_NONE);
1052 if (!partition) {
1053 LERROR << "create " << partition_name;
Mark Salyzyn69ebd442018-06-06 13:10:40 -07001054 return false;
1055 }
Mark Salyzyncb2f6b62018-11-20 12:59:21 -08001056 changed = true;
1057 }
Mark Salyzyn756eebe2018-11-27 16:14:35 -08001058 // Take half of free space, minimum 512MB or maximum free - margin.
Mark Salyzyncb2f6b62018-11-20 12:59:21 -08001059 static constexpr auto kMinimumSize = uint64_t(512 * 1024 * 1024);
Mark Salyzyncb2f6b62018-11-20 12:59:21 -08001060 if (partition->size() < kMinimumSize) {
1061 auto partition_size =
1062 builder->AllocatableSpace() - builder->UsedSpace() + partition->size();
1063 if ((partition_size > kMinimumSize) || !partition->size()) {
Mark Salyzyn756eebe2018-11-27 16:14:35 -08001064 // Leave some space for free space jitter of a few erase
1065 // blocks, in case they are needed for any individual updates
1066 // to any other partition that needs to be flashed while
1067 // overlayfs is in force. Of course if margin_size is not
1068 // enough could normally get a flash failure, so
1069 // ResizePartition() will delete the scratch partition in
1070 // order to fulfill. Deleting scratch will destroy all of
1071 // the adb remount overrides :-( .
1072 auto margin_size = uint64_t(3 * 256 * 1024);
1073 BlockDeviceInfo info;
Mark Salyzync3fc2aa2019-04-30 13:21:04 -07001074 if (builder->GetBlockDeviceInfo(fs_mgr_get_super_partition_name(slot_number), &info)) {
Mark Salyzyn756eebe2018-11-27 16:14:35 -08001075 margin_size = 3 * info.logical_block_size;
1076 }
1077 partition_size = std::max(std::min(kMinimumSize, partition_size - margin_size),
Mark Salyzyncb2f6b62018-11-20 12:59:21 -08001078 partition_size / 2);
1079 if (partition_size > partition->size()) {
1080 if (!builder->ResizePartition(partition, partition_size)) {
Mark Salyzync3fc2aa2019-04-30 13:21:04 -07001081 // Try to free up space by deallocating partitions in the other slot.
1082 TruncatePartitionsWithSuffix(builder.get(), fs_mgr_get_other_slot_suffix());
1083
1084 partition_size =
1085 builder->AllocatableSpace() - builder->UsedSpace() + partition->size();
1086 partition_size = std::max(std::min(kMinimumSize, partition_size - margin_size),
1087 partition_size / 2);
1088 if (!builder->ResizePartition(partition, partition_size)) {
1089 LERROR << "resize " << partition_name;
1090 return false;
1091 }
Mark Salyzyncb2f6b62018-11-20 12:59:21 -08001092 }
David Anderson470fe2b2019-07-10 18:09:50 -07001093 if (!partition_create) DestroyLogicalPartition(partition_name);
Mark Salyzyncb2f6b62018-11-20 12:59:21 -08001094 changed = true;
Mark Salyzyn13a66052018-12-05 10:45:06 -08001095 *partition_exists = false;
Mark Salyzyn69ebd442018-06-06 13:10:40 -07001096 }
Mark Salyzyncb2f6b62018-11-20 12:59:21 -08001097 }
1098 }
1099 // land the update back on to the partition
1100 if (changed) {
1101 auto metadata = builder->Export();
1102 if (!metadata || !UpdatePartitionTable(super_device, *metadata.get(), slot_number)) {
1103 LERROR << "add partition " << partition_name;
1104 return false;
Mark Salyzyn69ebd442018-06-06 13:10:40 -07001105 }
1106
Mark Salyzyncb2f6b62018-11-20 12:59:21 -08001107 if (change) *change = true;
1108 }
1109
1110 if (changed || partition_create) {
David Anderson15aa9542019-08-12 17:07:50 -07001111 CreateLogicalPartitionParams params = {
1112 .block_device = super_device,
1113 .metadata_slot = slot_number,
1114 .partition_name = partition_name,
1115 .force_writable = true,
1116 .timeout_ms = 10s,
1117 };
1118 if (!CreateLogicalPartition(params, scratch_device)) {
Mark Salyzyn69ebd442018-06-06 13:10:40 -07001119 return false;
David Anderson15aa9542019-08-12 17:07:50 -07001120 }
Mark Salyzyncb2f6b62018-11-20 12:59:21 -08001121
1122 if (change) *change = true;
Mark Salyzyn5ced7602020-02-11 07:52:18 -08001123 } else if (scratch_device->empty()) {
1124 *scratch_device = GetBootScratchDevice();
Mark Salyzyn69ebd442018-06-06 13:10:40 -07001125 }
Mark Salyzyn13a66052018-12-05 10:45:06 -08001126 return true;
1127}
Mark Salyzyn69ebd442018-06-06 13:10:40 -07001128
David Andersonc1c05da2022-02-16 18:57:41 -08001129static inline uint64_t GetIdealDataScratchSize() {
1130 BlockDeviceInfo super_info;
1131 PartitionOpener opener;
1132 if (!opener.GetInfo(fs_mgr_get_super_partition_name(), &super_info)) {
1133 LERROR << "could not get block device info for super";
1134 return 0;
1135 }
1136
1137 struct statvfs s;
1138 if (statvfs("/data", &s) < 0) {
1139 PERROR << "could not statfs /data";
1140 return 0;
1141 }
1142
1143 return std::min(super_info.size, (uint64_t(s.f_frsize) * s.f_bfree) / 2);
1144}
1145
David Andersonc13586f2019-12-17 21:06:15 -08001146static bool CreateScratchOnData(std::string* scratch_device, bool* partition_exists, bool* change) {
1147 *partition_exists = false;
George Burgess IV1c8d8142020-11-09 22:15:16 -08001148 if (change) *change = false;
David Andersonc13586f2019-12-17 21:06:15 -08001149
1150 auto images = IImageManager::Open("remount", 10s);
1151 if (!images) {
1152 return false;
1153 }
1154
1155 auto partition_name = android::base::Basename(kScratchMountPoint);
1156 if (images->GetMappedImageDevice(partition_name, scratch_device)) {
1157 *partition_exists = true;
1158 return true;
1159 }
1160
George Burgess IV1c8d8142020-11-09 22:15:16 -08001161 if (change) *change = true;
David Andersonc13586f2019-12-17 21:06:15 -08001162
1163 // Note: calling RemoveDisabledImages here ensures that we do not race with
1164 // clean_scratch_files and accidentally try to map an image that will be
1165 // deleted.
1166 if (!images->RemoveDisabledImages()) {
1167 return false;
1168 }
1169 if (!images->BackingImageExists(partition_name)) {
David Andersonc1c05da2022-02-16 18:57:41 -08001170 uint64_t size = GetIdealDataScratchSize();
1171 if (!size) {
1172 size = 2_GiB;
1173 }
David Andersonc13586f2019-12-17 21:06:15 -08001174
David Andersonc13586f2019-12-17 21:06:15 -08001175 auto flags = IImageManager::CREATE_IMAGE_DEFAULT;
1176
1177 if (!images->CreateBackingImage(partition_name, size, flags)) {
1178 LERROR << "could not create scratch image of " << size << " bytes";
1179 return false;
1180 }
1181 }
1182 if (!images->MapImageDevice(partition_name, 10s, scratch_device)) {
1183 LERROR << "could not map scratch image";
1184 return false;
1185 }
1186 return true;
1187}
1188
1189static bool CanUseSuperPartition(const Fstab& fstab, bool* is_virtual_ab) {
David Anderson69def122019-12-15 22:51:33 -08001190 auto slot_number = fs_mgr_overlayfs_slot_number();
1191 auto super_device = fs_mgr_overlayfs_super_device(slot_number);
1192 if (!fs_mgr_rw_access(super_device) || !fs_mgr_overlayfs_has_logical(fstab)) {
David Andersona3bf8472019-12-10 20:43:40 -08001193 return false;
1194 }
David Andersonc13586f2019-12-17 21:06:15 -08001195 auto metadata = ReadMetadata(super_device, slot_number);
1196 if (!metadata) {
1197 return false;
1198 }
1199 *is_virtual_ab = !!(metadata->header.flags & LP_HEADER_FLAG_VIRTUAL_AB_DEVICE);
David Andersona3bf8472019-12-10 20:43:40 -08001200 return true;
1201}
1202
David Anderson69def122019-12-15 22:51:33 -08001203bool fs_mgr_overlayfs_create_scratch(const Fstab& fstab, std::string* scratch_device,
1204 bool* partition_exists, bool* change) {
Yo Chiang0267bf02020-10-21 22:25:21 +08001205 // Use the DSU scratch device managed by gsid if within a DSU system.
1206 if (fs_mgr_is_dsu_running()) {
1207 *scratch_device = GetDsuScratchDevice();
1208 *partition_exists = !scratch_device->empty();
1209 *change = false;
1210 return *partition_exists;
1211 }
1212
David Anderson69def122019-12-15 22:51:33 -08001213 // Try a physical partition first.
1214 *scratch_device = GetPhysicalScratchDevice();
1215 if (!scratch_device->empty() && fs_mgr_rw_access(*scratch_device)) {
1216 *partition_exists = true;
1217 return true;
1218 }
1219
1220 // If that fails, see if we can land on super.
David Andersonc13586f2019-12-17 21:06:15 -08001221 bool is_virtual_ab;
1222 if (CanUseSuperPartition(fstab, &is_virtual_ab)) {
1223 bool can_use_data = false;
1224 if (is_virtual_ab && FilesystemHasReliablePinning("/data", &can_use_data) && can_use_data) {
1225 return CreateScratchOnData(scratch_device, partition_exists, change);
1226 }
David Anderson69def122019-12-15 22:51:33 -08001227 return CreateDynamicScratch(scratch_device, partition_exists, change);
1228 }
1229
1230 errno = ENXIO;
1231 return false;
1232}
1233
Mark Salyzyn13a66052018-12-05 10:45:06 -08001234// Create and mount kScratchMountPoint storage if we have logical partitions
Tom Cherry23319eb2018-11-30 16:16:05 -08001235bool fs_mgr_overlayfs_setup_scratch(const Fstab& fstab, bool* change) {
Mark Salyzyn13a66052018-12-05 10:45:06 -08001236 if (fs_mgr_overlayfs_already_mounted(kScratchMountPoint, false)) return true;
1237
1238 std::string scratch_device;
1239 bool partition_exists;
1240 if (!fs_mgr_overlayfs_create_scratch(fstab, &scratch_device, &partition_exists, change)) {
1241 return false;
1242 }
Mark Salyzyn69ebd442018-06-06 13:10:40 -07001243
Mark Salyzynd14eb572018-12-05 10:19:48 -08001244 // If the partition exists, assume first that it can be mounted.
1245 auto mnt_type = fs_mgr_overlayfs_scratch_mount_type();
Mark Salyzyn69ebd442018-06-06 13:10:40 -07001246 if (partition_exists) {
1247 if (fs_mgr_overlayfs_mount_scratch(scratch_device, mnt_type)) {
Mark Salyzyndf8cf182019-01-04 14:43:27 -08001248 if (!fs_mgr_access(kScratchMountPoint + kOverlayTopDir) &&
1249 !fs_mgr_filesystem_has_space(kScratchMountPoint)) {
1250 // declare it useless, no overrides and no free space
1251 fs_mgr_overlayfs_umount_scratch();
1252 } else {
1253 if (change) *change = true;
1254 return true;
1255 }
Mark Salyzyn69ebd442018-06-06 13:10:40 -07001256 }
Mark Salyzynd14eb572018-12-05 10:19:48 -08001257 // partition existed, but was not initialized; fall through to make it.
Mark Salyzyn69ebd442018-06-06 13:10:40 -07001258 errno = 0;
1259 }
1260
Mark Salyzynd14eb572018-12-05 10:19:48 -08001261 if (!fs_mgr_overlayfs_make_scratch(scratch_device, mnt_type)) return false;
Mark Salyzyn69ebd442018-06-06 13:10:40 -07001262
1263 if (change) *change = true;
1264
1265 return fs_mgr_overlayfs_mount_scratch(scratch_device, mnt_type);
1266}
1267
Tom Cherry23319eb2018-11-30 16:16:05 -08001268bool fs_mgr_overlayfs_invalid() {
Mark Salyzyn9040aa52018-11-26 09:57:17 -08001269 if (fs_mgr_overlayfs_valid() == OverlayfsValidResult::kNotSupported) return true;
1270
Yo Chiang0267bf02020-10-21 22:25:21 +08001271 // in recovery or fastbootd, not allowed!
1272 return fs_mgr_in_recovery();
Mark Salyzyn9040aa52018-11-26 09:57:17 -08001273}
1274
Mark Salyzynb28389f2018-06-06 13:10:40 -07001275} // namespace
1276
Mark Salyzyndffdb432019-01-24 11:08:10 -08001277Fstab fs_mgr_overlayfs_candidate_list(const Fstab& fstab) {
1278 Fstab candidates;
1279 for (const auto& entry : fstab) {
1280 FstabEntry new_entry = entry;
Ryan Savitski814cbfa2019-07-30 12:01:46 +00001281 if (!fs_mgr_overlayfs_already_mounted(entry.mount_point) &&
Mark Salyzyndffdb432019-01-24 11:08:10 -08001282 !fs_mgr_wants_overlayfs(&new_entry)) {
1283 continue;
1284 }
1285 auto new_mount_point = fs_mgr_mount_point(entry.mount_point);
1286 auto duplicate_or_more_specific = false;
1287 for (auto it = candidates.begin(); it != candidates.end();) {
1288 auto it_mount_point = fs_mgr_mount_point(it->mount_point);
1289 if ((it_mount_point == new_mount_point) ||
1290 (android::base::StartsWith(new_mount_point, it_mount_point + "/"))) {
1291 duplicate_or_more_specific = true;
1292 break;
1293 }
1294 if (android::base::StartsWith(it_mount_point, new_mount_point + "/")) {
1295 it = candidates.erase(it);
1296 } else {
1297 ++it;
1298 }
1299 }
1300 if (!duplicate_or_more_specific) candidates.emplace_back(std::move(new_entry));
1301 }
1302 return candidates;
1303}
1304
David Andersoncd720dc2019-12-10 21:08:08 -08001305static void TryMountScratch() {
David Anderson69def122019-12-15 22:51:33 -08001306 // Note we get the boot scratch device here, which means if scratch was
1307 // just created through ImageManager, this could fail. In practice this
1308 // should not happen because "remount" detects this scenario (by checking
1309 // if verity is still disabled, i.e. no reboot occurred), and skips calling
1310 // fs_mgr_overlayfs_mount_all().
1311 auto scratch_device = GetBootScratchDevice();
David Andersonc13586f2019-12-17 21:06:15 -08001312 if (!fs_mgr_rw_access(scratch_device)) {
David Andersoncd720dc2019-12-10 21:08:08 -08001313 return;
1314 }
1315 if (!WaitForFile(scratch_device, 10s)) {
1316 return;
1317 }
1318 const auto mount_type = fs_mgr_overlayfs_scratch_mount_type();
1319 if (!fs_mgr_overlayfs_mount_scratch(scratch_device, mount_type, true /* readonly */)) {
1320 return;
1321 }
1322 auto has_overlayfs_dir = fs_mgr_access(kScratchMountPoint + kOverlayTopDir);
1323 fs_mgr_overlayfs_umount_scratch();
1324 if (has_overlayfs_dir) {
1325 fs_mgr_overlayfs_mount_scratch(scratch_device, mount_type);
1326 }
1327}
1328
Tom Cherry23319eb2018-11-30 16:16:05 -08001329bool fs_mgr_overlayfs_mount_all(Fstab* fstab) {
Mark Salyzynb28389f2018-06-06 13:10:40 -07001330 auto ret = false;
Tom Cherry23319eb2018-11-30 16:16:05 -08001331 if (fs_mgr_overlayfs_invalid()) return ret;
Mark Salyzynb28389f2018-06-06 13:10:40 -07001332
Mark Salyzyn69ebd442018-06-06 13:10:40 -07001333 auto scratch_can_be_mounted = true;
Mark Salyzyndffdb432019-01-24 11:08:10 -08001334 for (const auto& entry : fs_mgr_overlayfs_candidate_list(*fstab)) {
1335 if (fs_mgr_is_verity_enabled(entry)) continue;
1336 auto mount_point = fs_mgr_mount_point(entry.mount_point);
Mark Salyzynfab9f082019-02-04 14:59:16 -08001337 if (fs_mgr_overlayfs_already_mounted(mount_point)) {
1338 ret = true;
1339 continue;
1340 }
Mark Salyzyn69ebd442018-06-06 13:10:40 -07001341 if (scratch_can_be_mounted) {
1342 scratch_can_be_mounted = false;
David Andersoncd720dc2019-12-10 21:08:08 -08001343 TryMountScratch();
Mark Salyzyn69ebd442018-06-06 13:10:40 -07001344 }
Mark Salyzynd3dc3c82018-06-13 09:33:28 -07001345 if (fs_mgr_overlayfs_mount(mount_point)) ret = true;
Mark Salyzynb28389f2018-06-06 13:10:40 -07001346 }
1347 return ret;
1348}
1349
1350// Returns false if setup not permitted, errno set to last error.
1351// If something is altered, set *change.
Ed Chen19814012019-12-17 08:53:13 +00001352bool fs_mgr_overlayfs_setup(const char* backing, const char* mount_point, bool* change,
1353 bool force) {
Mark Salyzynb28389f2018-06-06 13:10:40 -07001354 if (change) *change = false;
1355 auto ret = false;
Mark Salyzyn6a116942018-11-05 08:53:30 -08001356 if (fs_mgr_overlayfs_valid() == OverlayfsValidResult::kNotSupported) return ret;
Mark Salyzynb28389f2018-06-06 13:10:40 -07001357 if (!fs_mgr_boot_completed()) {
1358 errno = EBUSY;
Mark Salyzyn03df4232018-08-29 10:44:33 -07001359 PERROR << "setup";
Mark Salyzynb28389f2018-06-06 13:10:40 -07001360 return ret;
1361 }
1362
Mark Salyzynd202c552018-12-12 10:36:32 -08001363 auto save_errno = errno;
Tom Cherry23319eb2018-11-30 16:16:05 -08001364 Fstab fstab;
1365 if (!ReadDefaultFstab(&fstab)) {
1366 return false;
1367 }
Mark Salyzynd202c552018-12-12 10:36:32 -08001368 errno = save_errno;
Mark Salyzyndffdb432019-01-24 11:08:10 -08001369 auto candidates = fs_mgr_overlayfs_candidate_list(fstab);
1370 for (auto it = candidates.begin(); it != candidates.end();) {
1371 if (mount_point &&
1372 (fs_mgr_mount_point(it->mount_point) != fs_mgr_mount_point(mount_point))) {
1373 it = candidates.erase(it);
1374 continue;
1375 }
1376 save_errno = errno;
Mark Salyzyne0c581f2019-05-29 14:01:56 -07001377 auto verity_enabled = !force && fs_mgr_is_verity_enabled(*it);
Mark Salyzyndffdb432019-01-24 11:08:10 -08001378 if (errno == ENOENT || errno == ENXIO) errno = save_errno;
1379 if (verity_enabled) {
1380 it = candidates.erase(it);
1381 continue;
1382 }
1383 ++it;
1384 }
1385
1386 if (candidates.empty()) return ret;
Mark Salyzyn69ebd442018-06-06 13:10:40 -07001387
1388 std::string dir;
Yi-Yo Chiangd1ff1bc2021-02-11 22:59:11 +08001389 for (const auto& overlay_mount_point : OverlayMountPoints()) {
Ed Chen19814012019-12-17 08:53:13 +00001390 if (backing && backing[0] && (overlay_mount_point != backing)) continue;
Mark Salyzyn69ebd442018-06-06 13:10:40 -07001391 if (overlay_mount_point == kScratchMountPoint) {
Tom Cherry23319eb2018-11-30 16:16:05 -08001392 if (!fs_mgr_overlayfs_setup_scratch(fstab, change)) continue;
Mark Salyzyn69ebd442018-06-06 13:10:40 -07001393 } else {
Tom Cherry2e545f82019-01-29 08:49:57 -08001394 if (GetEntryForMountPoint(&fstab, overlay_mount_point) == nullptr) {
Tom Cherry23319eb2018-11-30 16:16:05 -08001395 continue;
1396 }
Mark Salyzyn69ebd442018-06-06 13:10:40 -07001397 }
1398 dir = overlay_mount_point;
1399 break;
1400 }
1401 if (dir.empty()) {
Mark Salyzynd202c552018-12-12 10:36:32 -08001402 if (change && *change) errno = ESRCH;
1403 if (errno == EPERM) errno = save_errno;
Mark Salyzyn69ebd442018-06-06 13:10:40 -07001404 return ret;
1405 }
Mark Salyzynb28389f2018-06-06 13:10:40 -07001406
Mark Salyzyn780db022018-06-06 13:10:40 -07001407 std::string overlay;
Mark Salyzyn69ebd442018-06-06 13:10:40 -07001408 ret |= fs_mgr_overlayfs_setup_dir(dir, &overlay, change);
Mark Salyzyndffdb432019-01-24 11:08:10 -08001409 for (const auto& entry : candidates) {
1410 ret |= fs_mgr_overlayfs_setup_one(overlay, fs_mgr_mount_point(entry.mount_point), change);
Mark Salyzynb28389f2018-06-06 13:10:40 -07001411 }
1412 return ret;
1413}
1414
David Anderson982c3412022-02-08 22:06:44 -08001415struct MapInfo {
1416 // If set, partition is owned by ImageManager.
1417 std::unique_ptr<IImageManager> images;
1418 // If set, and images is null, this is a DAP partition.
1419 std::string name;
1420 // If set, and images and name are empty, this is a non-dynamic partition.
1421 std::string device;
1422
1423 MapInfo() = default;
1424 MapInfo(MapInfo&&) = default;
1425 ~MapInfo() {
1426 if (images) {
1427 images->UnmapImageDevice(name);
1428 } else if (!name.empty()) {
1429 DestroyLogicalPartition(name);
1430 }
1431 }
1432};
1433
Yo Chiang0267bf02020-10-21 22:25:21 +08001434// Note: This function never returns the DSU scratch device in recovery or fastbootd,
1435// because the DSU scratch is created in the first-stage-mount, which is not run in recovery.
David Anderson982c3412022-02-08 22:06:44 -08001436static std::optional<MapInfo> EnsureScratchMapped() {
1437 MapInfo info;
1438 info.device = GetBootScratchDevice();
1439 if (!info.device.empty()) {
1440 return {std::move(info)};
David Anderson43d9f182019-12-10 21:18:28 -08001441 }
Yo Chiang66d0d962020-10-27 19:07:37 +08001442 if (!fs_mgr_in_recovery()) {
David Anderson982c3412022-02-08 22:06:44 -08001443 return {};
Yo Chiang66d0d962020-10-27 19:07:37 +08001444 }
1445
David Andersonc13586f2019-12-17 21:06:15 -08001446 auto partition_name = android::base::Basename(kScratchMountPoint);
1447
1448 // Check for scratch on /data first, before looking for a modified super
1449 // partition. We should only reach this code in recovery, because scratch
1450 // would otherwise always be mapped.
1451 auto images = IImageManager::Open("remount", 10s);
1452 if (images && images->BackingImageExists(partition_name)) {
David Anderson982c3412022-02-08 22:06:44 -08001453 if (images->IsImageDisabled(partition_name)) {
1454 return {};
David Andersonc13586f2019-12-17 21:06:15 -08001455 }
David Anderson982c3412022-02-08 22:06:44 -08001456 if (!images->MapImageDevice(partition_name, 10s, &info.device)) {
1457 return {};
1458 }
1459 info.name = partition_name;
1460 info.images = std::move(images);
1461 return {std::move(info)};
David Andersonc13586f2019-12-17 21:06:15 -08001462 }
1463
David Anderson69def122019-12-15 22:51:33 -08001464 // Avoid uart spam by first checking for a scratch partition.
1465 auto metadata_slot = fs_mgr_overlayfs_slot_number();
1466 auto super_device = fs_mgr_overlayfs_super_device(metadata_slot);
1467 auto metadata = ReadCurrentMetadata(super_device);
1468 if (!metadata) {
David Anderson982c3412022-02-08 22:06:44 -08001469 return {};
David Anderson43d9f182019-12-10 21:18:28 -08001470 }
David Anderson69def122019-12-15 22:51:33 -08001471
David Anderson69def122019-12-15 22:51:33 -08001472 auto partition = FindPartition(*metadata.get(), partition_name);
1473 if (!partition) {
David Anderson982c3412022-02-08 22:06:44 -08001474 return {};
David Anderson69def122019-12-15 22:51:33 -08001475 }
1476
1477 CreateLogicalPartitionParams params = {
1478 .block_device = super_device,
1479 .metadata = metadata.get(),
1480 .partition = partition,
1481 .force_writable = true,
1482 .timeout_ms = 10s,
1483 };
David Anderson982c3412022-02-08 22:06:44 -08001484 if (!CreateLogicalPartition(params, &info.device)) {
1485 return {};
David Anderson69def122019-12-15 22:51:33 -08001486 }
David Anderson982c3412022-02-08 22:06:44 -08001487 info.name = partition_name;
1488 return {std::move(info)};
David Anderson43d9f182019-12-10 21:18:28 -08001489}
1490
Yo Chiang66d0d962020-10-27 19:07:37 +08001491// This should only be reachable in recovery, where DSU scratch is not
1492// automatically mapped.
1493static bool MapDsuScratchDevice(std::string* device) {
Yo Chiang0267bf02020-10-21 22:25:21 +08001494 std::string dsu_slot;
1495 if (!android::gsi::IsGsiInstalled() || !android::gsi::GetActiveDsu(&dsu_slot) ||
1496 dsu_slot.empty()) {
1497 // Nothing to do if no DSU installation present.
Yo Chiang66d0d962020-10-27 19:07:37 +08001498 return false;
Yo Chiang0267bf02020-10-21 22:25:21 +08001499 }
1500
1501 auto images = IImageManager::Open("dsu/" + dsu_slot, 10s);
1502 if (!images || !images->BackingImageExists(android::gsi::kDsuScratch)) {
1503 // Nothing to do if DSU scratch device doesn't exist.
Yo Chiang66d0d962020-10-27 19:07:37 +08001504 return false;
Yo Chiang0267bf02020-10-21 22:25:21 +08001505 }
1506
1507 images->UnmapImageDevice(android::gsi::kDsuScratch);
Yo Chiang66d0d962020-10-27 19:07:37 +08001508 if (!images->MapImageDevice(android::gsi::kDsuScratch, 10s, device)) {
1509 return false;
1510 }
1511 return true;
Yo Chiang0267bf02020-10-21 22:25:21 +08001512}
Yo Chiang0267bf02020-10-21 22:25:21 +08001513
Mark Salyzynb28389f2018-06-06 13:10:40 -07001514// Returns false if teardown not permitted, errno set to last error.
1515// If something is altered, set *change.
1516bool fs_mgr_overlayfs_teardown(const char* mount_point, bool* change) {
1517 if (change) *change = false;
Mark Salyzyn69ebd442018-06-06 13:10:40 -07001518 auto ret = true;
David Anderson69def122019-12-15 22:51:33 -08001519
Mark Salyzyn7f47e4b2018-08-29 10:44:33 -07001520 // If scratch exists, but is not mounted, lets gain access to clean
1521 // specific override entries.
Mark Salyzync0966c92018-11-26 09:57:17 -08001522 auto mount_scratch = false;
Mark Salyzyn7f47e4b2018-08-29 10:44:33 -07001523 if ((mount_point != nullptr) && !fs_mgr_overlayfs_already_mounted(kScratchMountPoint, false)) {
Yo Chiang66d0d962020-10-27 19:07:37 +08001524 std::string scratch_device = GetBootScratchDevice();
1525 if (!scratch_device.empty()) {
David Anderson43d9f182019-12-10 21:18:28 -08001526 mount_scratch = fs_mgr_overlayfs_mount_scratch(scratch_device,
1527 fs_mgr_overlayfs_scratch_mount_type());
Mark Salyzyn7f47e4b2018-08-29 10:44:33 -07001528 }
Mark Salyzyn7f47e4b2018-08-29 10:44:33 -07001529 }
Yo Chiang0267bf02020-10-21 22:25:21 +08001530 bool should_destroy_scratch = false;
Yi-Yo Chiangd1ff1bc2021-02-11 22:59:11 +08001531 for (const auto& overlay_mount_point : OverlayMountPoints()) {
Mark Salyzyndffdb432019-01-24 11:08:10 -08001532 ret &= fs_mgr_overlayfs_teardown_one(
Yo Chiang0267bf02020-10-21 22:25:21 +08001533 overlay_mount_point, mount_point ? fs_mgr_mount_point(mount_point) : "", change,
1534 overlay_mount_point == kScratchMountPoint ? &should_destroy_scratch : nullptr);
1535 }
1536 // Do not attempt to destroy DSU scratch if within a DSU system,
1537 // because DSU scratch partition is managed by gsid.
1538 if (should_destroy_scratch && !fs_mgr_is_dsu_running()) {
Yo Chiang0267bf02020-10-21 22:25:21 +08001539 ret &= fs_mgr_overlayfs_teardown_scratch(kScratchMountPoint, change);
Mark Salyzyn69ebd442018-06-06 13:10:40 -07001540 }
Mark Salyzyn6a116942018-11-05 08:53:30 -08001541 if (fs_mgr_overlayfs_valid() == OverlayfsValidResult::kNotSupported) {
Mark Salyzynb28389f2018-06-06 13:10:40 -07001542 // After obligatory teardown to make sure everything is clean, but if
Yo Chiang66d0d962020-10-27 19:07:37 +08001543 // we didn't want overlayfs in the first place, we do not want to
Mark Salyzynb28389f2018-06-06 13:10:40 -07001544 // waste time on a reboot (or reboot request message).
1545 if (change) *change = false;
1546 }
1547 // And now that we did what we could, lets inform
1548 // caller that there may still be more to do.
1549 if (!fs_mgr_boot_completed()) {
1550 errno = EBUSY;
Mark Salyzyn03df4232018-08-29 10:44:33 -07001551 PERROR << "teardown";
Mark Salyzynb28389f2018-06-06 13:10:40 -07001552 ret = false;
1553 }
David Anderson69def122019-12-15 22:51:33 -08001554 if (mount_scratch) {
1555 fs_mgr_overlayfs_umount_scratch();
1556 }
Mark Salyzynb28389f2018-06-06 13:10:40 -07001557 return ret;
1558}
1559
Mark Salyzyndd748aa2018-12-03 13:42:22 -08001560bool fs_mgr_overlayfs_is_setup() {
1561 if (fs_mgr_overlayfs_already_mounted(kScratchMountPoint, false)) return true;
Tom Cherry23319eb2018-11-30 16:16:05 -08001562 Fstab fstab;
1563 if (!ReadDefaultFstab(&fstab)) {
1564 return false;
1565 }
1566 if (fs_mgr_overlayfs_invalid()) return false;
Mark Salyzyndffdb432019-01-24 11:08:10 -08001567 for (const auto& entry : fs_mgr_overlayfs_candidate_list(fstab)) {
1568 if (fs_mgr_is_verity_enabled(entry)) continue;
1569 if (fs_mgr_overlayfs_already_mounted(fs_mgr_mount_point(entry.mount_point))) return true;
Mark Salyzyndd748aa2018-12-03 13:42:22 -08001570 }
1571 return false;
1572}
1573
David Andersonc13586f2019-12-17 21:06:15 -08001574namespace android {
1575namespace fs_mgr {
1576
1577void MapScratchPartitionIfNeeded(Fstab* fstab,
1578 const std::function<bool(const std::set<std::string>&)>& init) {
1579 if (fs_mgr_overlayfs_invalid()) {
1580 return;
1581 }
1582 if (GetEntryForMountPoint(fstab, kScratchMountPoint) != nullptr) {
1583 return;
1584 }
1585
1586 bool want_scratch = false;
1587 for (const auto& entry : fs_mgr_overlayfs_candidate_list(*fstab)) {
1588 if (fs_mgr_is_verity_enabled(entry)) {
1589 continue;
1590 }
1591 if (fs_mgr_overlayfs_already_mounted(fs_mgr_mount_point(entry.mount_point))) {
1592 continue;
1593 }
1594 want_scratch = true;
1595 break;
1596 }
1597 if (!want_scratch) {
1598 return;
1599 }
1600
1601 if (ScratchIsOnData()) {
1602 if (auto images = IImageManager::Open("remount", 0ms)) {
1603 images->MapAllImages(init);
1604 }
1605 }
1606
1607 // Physical or logical partitions will have already been mapped here,
1608 // so just ensure /dev/block symlinks exist.
1609 auto device = GetBootScratchDevice();
1610 if (!device.empty()) {
1611 init({android::base::Basename(device)});
1612 }
1613}
1614
1615void CleanupOldScratchFiles() {
1616 if (!ScratchIsOnData()) {
1617 return;
1618 }
1619 if (auto images = IImageManager::Open("remount", 0ms)) {
1620 images->RemoveDisabledImages();
1621 }
1622}
1623
Yo Chiang66d0d962020-10-27 19:07:37 +08001624void TeardownAllOverlayForMountPoint(const std::string& mount_point) {
1625 if (!fs_mgr_in_recovery()) {
1626 LERROR << __FUNCTION__ << "(): must be called within recovery.";
1627 return;
1628 }
1629
1630 // Empty string means teardown everything.
1631 const std::string teardown_dir = mount_point.empty() ? "" : fs_mgr_mount_point(mount_point);
1632 constexpr bool* ignore_change = nullptr;
1633
1634 // Teardown legacy overlay mount points that's not backed by a scratch device.
Yi-Yo Chiangd1ff1bc2021-02-11 22:59:11 +08001635 for (const auto& overlay_mount_point : OverlayMountPoints()) {
Yo Chiang66d0d962020-10-27 19:07:37 +08001636 if (overlay_mount_point == kScratchMountPoint) {
1637 continue;
1638 }
1639 fs_mgr_overlayfs_teardown_one(overlay_mount_point, teardown_dir, ignore_change);
1640 }
1641
David Anderson982c3412022-02-08 22:06:44 -08001642 if (mount_point.empty()) {
1643 // Throw away the entire partition.
1644 auto partition_name = android::base::Basename(kScratchMountPoint);
1645 auto images = IImageManager::Open("remount", 10s);
1646 if (images && images->BackingImageExists(partition_name)) {
1647 if (images->DisableImage(partition_name)) {
1648 LOG(INFO) << "Disabled scratch partition for: " << kScratchMountPoint;
1649 } else {
1650 LOG(ERROR) << "Unable to disable scratch partition for " << kScratchMountPoint;
1651 }
1652 }
1653 }
1654
1655 if (auto info = EnsureScratchMapped(); info.has_value()) {
1656 // Map scratch device, mount kScratchMountPoint and teardown kScratchMountPoint.
Yo Chiang66d0d962020-10-27 19:07:37 +08001657 fs_mgr_overlayfs_umount_scratch();
David Anderson982c3412022-02-08 22:06:44 -08001658 if (fs_mgr_overlayfs_mount_scratch(info->device, fs_mgr_overlayfs_scratch_mount_type())) {
Yo Chiang66d0d962020-10-27 19:07:37 +08001659 bool should_destroy_scratch = false;
1660 fs_mgr_overlayfs_teardown_one(kScratchMountPoint, teardown_dir, ignore_change,
1661 &should_destroy_scratch);
David Anderson982c3412022-02-08 22:06:44 -08001662 fs_mgr_overlayfs_umount_scratch();
Yo Chiang66d0d962020-10-27 19:07:37 +08001663 if (should_destroy_scratch) {
1664 fs_mgr_overlayfs_teardown_scratch(kScratchMountPoint, nullptr);
1665 }
Yo Chiang66d0d962020-10-27 19:07:37 +08001666 }
1667 }
1668
1669 // Teardown DSU overlay if present.
David Anderson982c3412022-02-08 22:06:44 -08001670 std::string scratch_device;
Yo Chiang66d0d962020-10-27 19:07:37 +08001671 if (MapDsuScratchDevice(&scratch_device)) {
1672 fs_mgr_overlayfs_umount_scratch();
1673 if (fs_mgr_overlayfs_mount_scratch(scratch_device, fs_mgr_overlayfs_scratch_mount_type())) {
1674 fs_mgr_overlayfs_teardown_one(kScratchMountPoint, teardown_dir, ignore_change);
1675 fs_mgr_overlayfs_umount_scratch();
1676 }
1677 DestroyLogicalPartition(android::gsi::kDsuScratch);
1678 }
1679}
1680
David Andersonc13586f2019-12-17 21:06:15 -08001681} // namespace fs_mgr
1682} // namespace android
1683
Mark Salyzynb28389f2018-06-06 13:10:40 -07001684#endif // ALLOW_ADBD_DISABLE_VERITY != 0
Mark Salyzyn3ff87d82018-07-02 10:45:25 -07001685
1686bool fs_mgr_has_shared_blocks(const std::string& mount_point, const std::string& dev) {
1687 struct statfs fs;
1688 if ((statfs((mount_point + "/lost+found").c_str(), &fs) == -1) ||
1689 (fs.f_type != EXT4_SUPER_MAGIC)) {
1690 return false;
1691 }
1692
1693 android::base::unique_fd fd(open(dev.c_str(), O_RDONLY | O_CLOEXEC));
1694 if (fd < 0) return false;
1695
1696 struct ext4_super_block sb;
1697 if ((TEMP_FAILURE_RETRY(lseek64(fd, 1024, SEEK_SET)) < 0) ||
1698 (TEMP_FAILURE_RETRY(read(fd, &sb, sizeof(sb))) < 0)) {
1699 return false;
1700 }
1701
1702 struct fs_info info;
1703 if (ext4_parse_sb(&sb, &info) < 0) return false;
1704
1705 return (info.feat_ro_compat & EXT4_FEATURE_RO_COMPAT_SHARED_BLOCKS) != 0;
1706}
Justin Yun6bab0a92018-10-29 18:31:48 +09001707
1708std::string fs_mgr_get_context(const std::string& mount_point) {
1709 char* ctx = nullptr;
1710 if (getfilecon(mount_point.c_str(), &ctx) == -1) {
1711 return "";
1712 }
1713
1714 std::string context(ctx);
1715 free(ctx);
1716 return context;
1717}
1718
Mark Salyzyn6a116942018-11-05 08:53:30 -08001719OverlayfsValidResult fs_mgr_overlayfs_valid() {
Justin Yun6bab0a92018-10-29 18:31:48 +09001720 // Overlayfs available in the kernel, and patched for override_creds?
Mark Salyzyn6a116942018-11-05 08:53:30 -08001721 if (fs_mgr_access("/sys/module/overlay/parameters/override_creds")) {
1722 return OverlayfsValidResult::kOverrideCredsRequired;
1723 }
Mark Salyzyn6d109ec2019-01-30 10:19:15 -08001724 if (!fs_mgr_overlayfs_filesystem_available("overlay")) {
Mark Salyzyn6a116942018-11-05 08:53:30 -08001725 return OverlayfsValidResult::kNotSupported;
1726 }
1727 struct utsname uts;
1728 if (uname(&uts) == -1) {
1729 return OverlayfsValidResult::kNotSupported;
1730 }
1731 int major, minor;
1732 if (sscanf(uts.release, "%d.%d", &major, &minor) != 2) {
1733 return OverlayfsValidResult::kNotSupported;
1734 }
1735 if (major < 4) {
1736 return OverlayfsValidResult::kOk;
1737 }
1738 if (major > 4) {
1739 return OverlayfsValidResult::kNotSupported;
1740 }
Mark Salyzyna9451a52019-02-26 08:39:40 -08001741 if (minor > 3) {
Mark Salyzyn6a116942018-11-05 08:53:30 -08001742 return OverlayfsValidResult::kNotSupported;
1743 }
1744 return OverlayfsValidResult::kOk;
Justin Yun6bab0a92018-10-29 18:31:48 +09001745}