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 <errno.h>
18 #include <fcntl.h>
19 #include <linux/fs.h>
20 #include <selinux/selinux.h>
21 #include <stdlib.h>
22 #include <sys/mount.h>
23 #include <sys/stat.h>
24 #include <sys/statvfs.h>
25 #include <sys/types.h>
26 #include <sys/vfs.h>
27 #include <unistd.h>
28 
29 #include <algorithm>
30 #include <memory>
31 #include <string>
32 #include <vector>
33 
34 #include <android-base/file.h>
35 #include <android-base/macros.h>
36 #include <android-base/properties.h>
37 #include <android-base/scopeguard.h>
38 #include <android-base/strings.h>
39 #include <android-base/unique_fd.h>
40 #include <ext4_utils/ext4_utils.h>
41 #include <fs_mgr.h>
42 #include <fs_mgr/file_wait.h>
43 #include <fs_mgr_overlayfs.h>
44 #include <fstab/fstab.h>
45 #include <libgsi/libgsi.h>
46 #include <storage_literals/storage_literals.h>
47 
48 #include "fs_mgr_overlayfs_control.h"
49 #include "fs_mgr_overlayfs_mount.h"
50 #include "fs_mgr_priv.h"
51 
52 using namespace std::literals;
53 using namespace android::fs_mgr;
54 using namespace android::storage_literals;
55 
56 constexpr char kPreferCacheBackingStorageProp[] = "fs_mgr.overlayfs.prefer_cache_backing_storage";
57 
58 constexpr char kCacheMountPoint[] = "/cache";
59 constexpr char kPhysicalDevice[] = "/dev/block/by-name/";
60 
61 // Mount tree to temporarily hold references to submounts.
62 constexpr char kMoveMountTempDir[] = "/dev/remount";
63 
64 constexpr char kLowerdirOption[] = "lowerdir=";
65 constexpr char kUpperdirOption[] = "upperdir=";
66 constexpr char kWorkdirOption[] = "workdir=";
67 
fs_mgr_is_dsu_running()68 bool fs_mgr_is_dsu_running() {
69     // Since android::gsi::CanBootIntoGsi() or android::gsi::MarkSystemAsGsi() is
70     // never called in recovery, the return value of android::gsi::IsGsiRunning()
71     // is not well-defined. In this case, just return false as being in recovery
72     // implies not running a DSU system.
73     if (InRecovery()) return false;
74     return android::gsi::IsGsiRunning();
75 }
76 
OverlayMountPoints()77 std::vector<const std::string> OverlayMountPoints() {
78     // Never fallback to legacy cache mount point if within a DSU system,
79     // because running a DSU system implies the device supports dynamic
80     // partitions, which means legacy cache mustn't be used.
81     if (fs_mgr_is_dsu_running()) {
82         return {kScratchMountPoint};
83     }
84 
85     // For non-A/B devices prefer cache backing storage if
86     // kPreferCacheBackingStorageProp property set.
87     if (fs_mgr_get_slot_suffix().empty() &&
88         android::base::GetBoolProperty(kPreferCacheBackingStorageProp, false) &&
89         android::base::GetIntProperty("ro.vendor.api_level", -1) < __ANDROID_API_T__) {
90         return {kCacheMountPoint, kScratchMountPoint};
91     }
92 
93     return {kScratchMountPoint, kCacheMountPoint};
94 }
95 
GetEncodedBaseDirForMountPoint(const std::string & mount_point)96 std::string GetEncodedBaseDirForMountPoint(const std::string& mount_point) {
97     std::string normalized_path;
98     if (mount_point.empty() || !android::base::Realpath(mount_point, &normalized_path)) {
99         return "";
100     }
101     std::string_view sv(normalized_path);
102     if (sv != "/") {
103         android::base::ConsumePrefix(&sv, "/");
104         android::base::ConsumeSuffix(&sv, "/");
105     }
106     return android::base::StringReplace(sv, "/", "@", true);
107 }
108 
fs_mgr_is_dir(const std::string & path)109 static bool fs_mgr_is_dir(const std::string& path) {
110     struct stat st;
111     return !stat(path.c_str(), &st) && S_ISDIR(st.st_mode);
112 }
113 
114 // At less than 1% or 8MB of free space return value of false,
115 // means we will try to wrap with overlayfs.
fs_mgr_filesystem_has_space(const std::string & mount_point)116 bool fs_mgr_filesystem_has_space(const std::string& mount_point) {
117     // If we have access issues to find out space remaining, return true
118     // to prevent us trying to override with overlayfs.
119     struct statvfs vst;
120     if (statvfs(mount_point.c_str(), &vst)) {
121         PLOG(ERROR) << "statvfs " << mount_point;
122         return true;
123     }
124 
125     static constexpr int kPercentThreshold = 1;                       // 1%
126     static constexpr unsigned long kSizeThreshold = 8 * 1024 * 1024;  // 8MB
127 
128     return (vst.f_bfree >= (vst.f_blocks * kPercentThreshold / 100)) &&
129            (static_cast<uint64_t>(vst.f_bfree) * vst.f_frsize) >= kSizeThreshold;
130 }
131 
fs_mgr_update_blk_device(FstabEntry * entry)132 static bool fs_mgr_update_blk_device(FstabEntry* entry) {
133     if (entry->fs_mgr_flags.logical) {
134         fs_mgr_update_logical_partition(entry);
135     }
136     if (access(entry->blk_device.c_str(), F_OK) == 0) {
137         return true;
138     }
139     if (entry->blk_device != "/dev/root") {
140         return false;
141     }
142 
143     // special case for system-as-root (taimen and others)
144     auto blk_device = kPhysicalDevice + "system"s;
145     if (access(blk_device.c_str(), F_OK)) {
146         blk_device += fs_mgr_get_slot_suffix();
147         if (access(blk_device.c_str(), F_OK)) {
148             return false;
149         }
150     }
151     entry->blk_device = blk_device;
152     return true;
153 }
154 
fs_mgr_has_shared_blocks(const std::string & mount_point,const std::string & dev)155 static bool fs_mgr_has_shared_blocks(const std::string& mount_point, const std::string& dev) {
156     struct statfs fs;
157     if ((statfs((mount_point + "/lost+found").c_str(), &fs) == -1) ||
158         (fs.f_type != EXT4_SUPER_MAGIC)) {
159         return false;
160     }
161 
162     android::base::unique_fd fd(open(dev.c_str(), O_RDONLY | O_CLOEXEC));
163     if (fd < 0) return false;
164 
165     struct ext4_super_block sb;
166     if ((TEMP_FAILURE_RETRY(lseek64(fd, 1024, SEEK_SET)) < 0) ||
167         (TEMP_FAILURE_RETRY(read(fd, &sb, sizeof(sb))) < 0)) {
168         return false;
169     }
170 
171     struct fs_info info;
172     if (ext4_parse_sb(&sb, &info) < 0) return false;
173 
174     return (info.feat_ro_compat & EXT4_FEATURE_RO_COMPAT_SHARED_BLOCKS) != 0;
175 }
176 
177 #define F2FS_SUPER_OFFSET 1024
178 #define F2FS_FEATURE_OFFSET 2180
179 #define F2FS_FEATURE_RO 0x4000
fs_mgr_is_read_only_f2fs(const std::string & dev)180 static bool fs_mgr_is_read_only_f2fs(const std::string& dev) {
181     if (!fs_mgr_is_f2fs(dev)) return false;
182 
183     android::base::unique_fd fd(open(dev.c_str(), O_RDONLY | O_CLOEXEC));
184     if (fd < 0) return false;
185 
186     __le32 feat;
187     if ((TEMP_FAILURE_RETRY(lseek64(fd, F2FS_SUPER_OFFSET + F2FS_FEATURE_OFFSET, SEEK_SET)) < 0) ||
188         (TEMP_FAILURE_RETRY(read(fd, &feat, sizeof(feat))) < 0)) {
189         return false;
190     }
191 
192     return (feat & cpu_to_le32(F2FS_FEATURE_RO)) != 0;
193 }
194 
fs_mgr_overlayfs_enabled(FstabEntry * entry)195 static bool fs_mgr_overlayfs_enabled(FstabEntry* entry) {
196     // readonly filesystem, can not be mount -o remount,rw
197     // for squashfs, erofs or if free space is (near) zero making such a remount
198     // virtually useless, or if there are shared blocks that prevent remount,rw
199     if (!fs_mgr_filesystem_has_space(entry->mount_point)) {
200         return true;
201     }
202 
203     // blk_device needs to be setup so we can check superblock.
204     // If we fail here, because during init first stage and have doubts.
205     if (!fs_mgr_update_blk_device(entry)) {
206         return true;
207     }
208 
209     // f2fs read-only mode doesn't support remount,rw
210     if (fs_mgr_is_read_only_f2fs(entry->blk_device)) {
211         return true;
212     }
213 
214     // check if ext4 de-dupe
215     auto has_shared_blocks = fs_mgr_has_shared_blocks(entry->mount_point, entry->blk_device);
216     if (!has_shared_blocks && (entry->mount_point == "/system")) {
217         has_shared_blocks = fs_mgr_has_shared_blocks("/", entry->blk_device);
218     }
219     return has_shared_blocks;
220 }
221 
fs_mgr_mount_point(const std::string & mount_point)222 const std::string fs_mgr_mount_point(const std::string& mount_point) {
223     if ("/"s != mount_point) return mount_point;
224     return "/system";
225 }
226 
227 // default options for mount_point, returns empty string for none available.
fs_mgr_get_overlayfs_options(const FstabEntry & entry)228 static std::string fs_mgr_get_overlayfs_options(const FstabEntry& entry) {
229     const auto mount_point = fs_mgr_mount_point(entry.mount_point);
230     if (!fs_mgr_is_dir(mount_point)) {
231         return "";
232     }
233     const auto base = GetEncodedBaseDirForMountPoint(mount_point);
234     if (base.empty()) {
235         return "";
236     }
237     for (const auto& overlay_mount_point : OverlayMountPoints()) {
238         const auto dir = overlay_mount_point + "/" + kOverlayTopDir + "/" + base + "/";
239         const auto upper = dir + kUpperName;
240         const auto work = dir + kWorkName;
241         if (!fs_mgr_is_dir(upper) || !fs_mgr_is_dir(work) || access(work.c_str(), R_OK | W_OK)) {
242             continue;
243         }
244         auto ret = kLowerdirOption + mount_point + "," + kUpperdirOption + upper + "," +
245                    kWorkdirOption + work + android::fs_mgr::CheckOverlayfs().mount_flags;
246         for (const auto& flag : android::base::Split(entry.fs_options, ",")) {
247             if (android::base::StartsWith(flag, "context=")) {
248                 ret += "," + flag;
249             }
250         }
251         return ret;
252     }
253     return "";
254 }
255 
Set(const std::string & context)256 bool AutoSetFsCreateCon::Set(const std::string& context) {
257     if (setfscreatecon(context.c_str())) {
258         PLOG(ERROR) << "setfscreatecon " << context;
259         return false;
260     }
261     ok_ = true;
262     return true;
263 }
264 
Restore()265 bool AutoSetFsCreateCon::Restore() {
266     if (restored_ || !ok_) {
267         return true;
268     }
269     if (setfscreatecon(nullptr)) {
270         PLOG(ERROR) << "setfscreatecon null";
271         return false;
272     }
273     restored_ = true;
274     return true;
275 }
276 
277 // Returns true if immediate unmount succeeded and the scratch mount point was
278 // removed.
fs_mgr_overlayfs_umount_scratch()279 bool fs_mgr_overlayfs_umount_scratch() {
280     if (umount(kScratchMountPoint) != 0) {
281         return false;
282     }
283     if (rmdir(kScratchMountPoint) != 0 && errno != ENOENT) {
284         PLOG(ERROR) << "rmdir " << kScratchMountPoint;
285     }
286     return true;
287 }
288 
fs_mgr_overlayfs_set_shared_mount(const std::string & mount_point,bool shared_flag)289 static bool fs_mgr_overlayfs_set_shared_mount(const std::string& mount_point, bool shared_flag) {
290     auto ret = mount(nullptr, mount_point.c_str(), nullptr, shared_flag ? MS_SHARED : MS_PRIVATE,
291                      nullptr);
292     if (ret) {
293         PERROR << "__mount(target=" << mount_point
294                << ",flag=" << (shared_flag ? "MS_SHARED" : "MS_PRIVATE") << ")=" << ret;
295         return false;
296     }
297     return true;
298 }
299 
fs_mgr_overlayfs_move_mount(const std::string & source,const std::string & target)300 static bool fs_mgr_overlayfs_move_mount(const std::string& source, const std::string& target) {
301     auto ret = mount(source.c_str(), target.c_str(), nullptr, MS_MOVE, nullptr);
302     if (ret) {
303         PERROR << "__mount(source=" << source << ",target=" << target << ",flag=MS_MOVE)=" << ret;
304         return false;
305     }
306     return true;
307 }
308 
fs_mgr_overlayfs_mount(const std::string & mount_point,const std::string & options)309 static bool fs_mgr_overlayfs_mount(const std::string& mount_point, const std::string& options) {
310     auto report = "__mount(source=overlay,target="s + mount_point + ",type=overlay";
311     for (const auto& opt : android::base::Split(options, ",")) {
312         if (android::base::StartsWith(opt, kUpperdirOption)) {
313             report = report + "," + opt;
314             break;
315         }
316     }
317     report = report + ")=";
318     auto ret = mount("overlay", mount_point.c_str(), "overlay", MS_RDONLY | MS_NOATIME,
319                      options.c_str());
320     if (ret) {
321         PERROR << report << ret;
322     } else {
323         LINFO << report << ret;
324     }
325     return !ret;
326 }
327 
328 struct mount_info {
329     std::string mount_point;
330     bool shared_flag;
331 };
332 
ReadMountinfoFromFile(const std::string & path)333 static std::vector<mount_info> ReadMountinfoFromFile(const std::string& path) {
334     std::vector<mount_info> info;
335 
336     auto file = std::unique_ptr<FILE, decltype(&fclose)>{fopen(path.c_str(), "re"), fclose};
337     if (!file) {
338         PERROR << __FUNCTION__ << "(): cannot open file: '" << path << "'";
339         return info;
340     }
341 
342     ssize_t len;
343     size_t alloc_len = 0;
344     char* line = nullptr;
345     while ((len = getline(&line, &alloc_len, file.get())) != -1) {
346         /* if the last character is a newline, shorten the string by 1 byte */
347         if (line[len - 1] == '\n') {
348             line[len - 1] = '\0';
349         }
350 
351         static constexpr char delim[] = " \t";
352         char* save_ptr;
353         if (!strtok_r(line, delim, &save_ptr)) {
354             LERROR << "Error parsing mount ID";
355             break;
356         }
357         if (!strtok_r(nullptr, delim, &save_ptr)) {
358             LERROR << "Error parsing parent ID";
359             break;
360         }
361         if (!strtok_r(nullptr, delim, &save_ptr)) {
362             LERROR << "Error parsing mount source";
363             break;
364         }
365         if (!strtok_r(nullptr, delim, &save_ptr)) {
366             LERROR << "Error parsing root";
367             break;
368         }
369 
370         char* p;
371         if (!(p = strtok_r(nullptr, delim, &save_ptr))) {
372             LERROR << "Error parsing mount_point";
373             break;
374         }
375         mount_info entry = {p, false};
376 
377         if (!strtok_r(nullptr, delim, &save_ptr)) {
378             LERROR << "Error parsing mount_flags";
379             break;
380         }
381 
382         while ((p = strtok_r(nullptr, delim, &save_ptr))) {
383             if ((p[0] == '-') && (p[1] == '\0')) break;
384             if (android::base::StartsWith(p, "shared:")) entry.shared_flag = true;
385         }
386         if (!p) {
387             LERROR << "Error parsing fields";
388             break;
389         }
390         info.emplace_back(std::move(entry));
391     }
392 
393     free(line);
394     if (info.empty()) {
395         LERROR << __FUNCTION__ << "(): failed to load mountinfo from : '" << path << "'";
396     }
397     return info;
398 }
399 
fs_mgr_overlayfs_mount_one(const FstabEntry & fstab_entry)400 static bool fs_mgr_overlayfs_mount_one(const FstabEntry& fstab_entry) {
401     const auto mount_point = fs_mgr_mount_point(fstab_entry.mount_point);
402     const auto options = fs_mgr_get_overlayfs_options(fstab_entry);
403     if (options.empty()) return false;
404 
405     struct MoveEntry {
406         std::string mount_point;
407         std::string dir;
408         bool shared_flag;
409     };
410     std::vector<MoveEntry> moved_mounts;
411 
412     bool retval = true;
413     bool move_dir_shared = true;
414     bool parent_shared = true;
415     bool root_shared = true;
416     bool root_made_private = false;
417 
418     // There could be multiple mount entries with the same mountpoint.
419     // Group these entries together with stable_sort, and keep only the last entry of a group.
420     // Only move mount the last entry in an over mount group, because the other entries are
421     // overshadowed and only the filesystem mounted with the last entry participates in file
422     // pathname resolution.
423     auto mountinfo = ReadMountinfoFromFile("/proc/self/mountinfo");
424     std::stable_sort(mountinfo.begin(), mountinfo.end(), [](const auto& lhs, const auto& rhs) {
425         return lhs.mount_point < rhs.mount_point;
426     });
427     std::reverse(mountinfo.begin(), mountinfo.end());
428     auto erase_from = std::unique(
429             mountinfo.begin(), mountinfo.end(),
430             [](const auto& lhs, const auto& rhs) { return lhs.mount_point == rhs.mount_point; });
431     mountinfo.erase(erase_from, mountinfo.end());
432     std::reverse(mountinfo.begin(), mountinfo.end());
433     // mountinfo is reversed twice, so still is in lexical sorted order.
434 
435     for (const auto& entry : mountinfo) {
436         if (entry.mount_point == kMoveMountTempDir) {
437             move_dir_shared = entry.shared_flag;
438         }
439         if (entry.mount_point == mount_point ||
440             (mount_point == "/system" && entry.mount_point == "/")) {
441             parent_shared = entry.shared_flag;
442         }
443         if (entry.mount_point == "/") {
444             root_shared = entry.shared_flag;
445         }
446     }
447 
448     // Precondition is that kMoveMountTempDir is MS_PRIVATE, otherwise don't try to move any
449     // submount in to or out of it.
450     if (move_dir_shared) {
451         mountinfo.clear();
452     }
453 
454     // Need to make the original mountpoint MS_PRIVATE, so that the overlayfs can be MS_MOVE.
455     // This could happen if its parent mount is remounted later.
456     if (!fs_mgr_overlayfs_set_shared_mount(mount_point, false)) {
457         // If failed to set "/system" mount type, it might be due to "/system" not being a valid
458         // mountpoint after switch root. Retry with "/" in this case.
459         if (errno == EINVAL && mount_point == "/system") {
460             root_made_private = fs_mgr_overlayfs_set_shared_mount("/", false);
461         }
462     }
463 
464     for (const auto& entry : mountinfo) {
465         // Find all immediate submounts.
466         if (!android::base::StartsWith(entry.mount_point, mount_point + "/")) {
467             continue;
468         }
469         // Exclude duplicated or more specific entries.
470         if (std::find_if(moved_mounts.begin(), moved_mounts.end(), [&entry](const auto& it) {
471                 return it.mount_point == entry.mount_point ||
472                        android::base::StartsWith(entry.mount_point, it.mount_point + "/");
473             }) != moved_mounts.end()) {
474             continue;
475         }
476         // mountinfo is in lexical order, so no need to worry about |entry| being a parent mount of
477         // entries of |moved_mounts|.
478 
479         MoveEntry new_entry{entry.mount_point, kMoveMountTempDir + "/TemporaryDir-XXXXXX"s,
480                             entry.shared_flag};
481         {
482             AutoSetFsCreateCon createcon;
483             auto new_context = fs_mgr_get_context(entry.mount_point);
484             if (new_context.empty() || !createcon.Set(new_context)) {
485                 continue;
486             }
487             const auto target = mkdtemp(new_entry.dir.data());
488             if (!target) {
489                 retval = false;
490                 PERROR << "temporary directory for MS_MOVE";
491                 continue;
492             }
493             if (!createcon.Restore()) {
494                 retval = false;
495                 rmdir(new_entry.dir.c_str());
496                 continue;
497             }
498         }
499 
500         if (new_entry.shared_flag) {
501             new_entry.shared_flag = fs_mgr_overlayfs_set_shared_mount(new_entry.mount_point, false);
502         }
503         if (!fs_mgr_overlayfs_move_mount(new_entry.mount_point, new_entry.dir)) {
504             retval = false;
505             if (new_entry.shared_flag) {
506                 fs_mgr_overlayfs_set_shared_mount(new_entry.mount_point, true);
507             }
508             rmdir(new_entry.dir.c_str());
509             continue;
510         }
511         moved_mounts.push_back(std::move(new_entry));
512     }
513 
514     retval &= fs_mgr_overlayfs_mount(mount_point, options);
515 
516     // Move submounts back.
517     for (const auto& entry : moved_mounts) {
518         if (!fs_mgr_overlayfs_move_mount(entry.dir, entry.mount_point)) {
519             retval = false;
520         } else if (entry.shared_flag &&
521                    !fs_mgr_overlayfs_set_shared_mount(entry.mount_point, true)) {
522             retval = false;
523         }
524         rmdir(entry.dir.c_str());
525     }
526     // If the original (overridden) mount was MS_SHARED, then set the overlayfs mount to MS_SHARED.
527     if (parent_shared) {
528         fs_mgr_overlayfs_set_shared_mount(mount_point, true);
529     }
530     if (root_shared && root_made_private) {
531         fs_mgr_overlayfs_set_shared_mount("/", true);
532     }
533 
534     return retval;
535 }
536 
537 // Mount kScratchMountPoint
MountScratch(const std::string & device_path,bool readonly)538 bool MountScratch(const std::string& device_path, bool readonly) {
539     if (readonly) {
540         if (access(device_path.c_str(), F_OK)) {
541             LOG(ERROR) << "Path does not exist: " << device_path;
542             return false;
543         }
544     } else if (access(device_path.c_str(), R_OK | W_OK)) {
545         LOG(ERROR) << "Path does not exist or is not readwrite: " << device_path;
546         return false;
547     }
548 
549     std::vector<const char*> filesystem_candidates;
550     if (fs_mgr_is_f2fs(device_path)) {
551         filesystem_candidates = {"f2fs", "ext4"};
552     } else if (fs_mgr_is_ext4(device_path)) {
553         filesystem_candidates = {"ext4", "f2fs"};
554     } else {
555         LOG(ERROR) << "Scratch partition is not f2fs or ext4";
556         return false;
557     }
558 
559     AutoSetFsCreateCon createcon(kOverlayfsFileContext);
560     if (!createcon.Ok()) {
561         return false;
562     }
563     if (mkdir(kScratchMountPoint, 0755) && (errno != EEXIST)) {
564         PERROR << "create " << kScratchMountPoint;
565         return false;
566     }
567 
568     FstabEntry entry;
569     entry.blk_device = device_path;
570     entry.mount_point = kScratchMountPoint;
571     entry.flags = MS_NOATIME | MS_RDONLY;
572     if (!readonly) {
573         entry.flags &= ~MS_RDONLY;
574         entry.flags |= MS_SYNCHRONOUS;
575         entry.fs_options = "nodiscard";
576         fs_mgr_set_blk_ro(device_path, false);
577     }
578     // check_fs requires apex runtime library
579     if (fs_mgr_overlayfs_already_mounted("/data", false)) {
580         entry.fs_mgr_flags.check = true;
581     }
582     bool mounted = false;
583     for (auto fs_type : filesystem_candidates) {
584         entry.fs_type = fs_type;
585         if (fs_mgr_do_mount_one(entry) == 0) {
586             mounted = true;
587             break;
588         }
589     }
590     if (!createcon.Restore()) {
591         return false;
592     }
593     if (!mounted) {
594         rmdir(kScratchMountPoint);
595         return false;
596     }
597     return true;
598 }
599 
600 // NOTE: OverlayfsSetupAllowed() must be "stricter" than OverlayfsTeardownAllowed().
601 // Setup is allowed only if teardown is also allowed.
OverlayfsSetupAllowed(bool verbose)602 bool OverlayfsSetupAllowed(bool verbose) {
603     if (!kAllowOverlayfs) {
604         if (verbose) {
605             LOG(ERROR) << "Overlayfs remounts can only be used in debuggable builds";
606         }
607         return false;
608     }
609     // Check mandatory kernel patches.
610     if (!android::fs_mgr::CheckOverlayfs().supported) {
611         if (verbose) {
612             LOG(ERROR) << "Kernel does not support overlayfs";
613         }
614         return false;
615     }
616     // in recovery or fastbootd, not allowed!
617     if (InRecovery()) {
618         if (verbose) {
619             LOG(ERROR) << "Unsupported overlayfs setup from recovery";
620         }
621         return false;
622     }
623     return true;
624 }
625 
fs_mgr_wants_overlayfs(FstabEntry * entry)626 bool fs_mgr_wants_overlayfs(FstabEntry* entry) {
627     // Don't check entries that are managed by vold.
628     if (entry->fs_mgr_flags.vold_managed || entry->fs_mgr_flags.recovery_only) return false;
629 
630     // *_other doesn't want overlayfs.
631     if (entry->fs_mgr_flags.slot_select_other) return false;
632 
633     // Only concerned with readonly partitions.
634     if (!(entry->flags & MS_RDONLY)) return false;
635 
636     // If unbindable, do not allow overlayfs as this could expose us to
637     // security issues.  On Android, this could also be used to turn off
638     // the ability to overlay an otherwise acceptable filesystem since
639     // /system and /vendor are never bound(sic) to.
640     if (entry->flags & MS_UNBINDABLE) return false;
641 
642     if (!fs_mgr_overlayfs_enabled(entry)) return false;
643 
644     return true;
645 }
646 
fs_mgr_overlayfs_candidate_list(const Fstab & fstab)647 Fstab fs_mgr_overlayfs_candidate_list(const Fstab& fstab) {
648     android::fs_mgr::Fstab mounts;
649     if (!android::fs_mgr::ReadFstabFromFile("/proc/mounts", &mounts)) {
650         PLOG(ERROR) << "Failed to read /proc/mounts";
651         return {};
652     }
653 
654     Fstab candidates;
655     for (const auto& entry : fstab) {
656         // Filter out partitions whose type doesn't match what's mounted.
657         // This avoids spammy behavior on devices which can mount different
658         // filesystems for each partition.
659         auto proc_mount_point = (entry.mount_point == "/system") ? "/" : entry.mount_point;
660         auto mounted = GetEntryForMountPoint(&mounts, proc_mount_point);
661         if (!mounted || mounted->fs_type != entry.fs_type) {
662             continue;
663         }
664 
665         FstabEntry new_entry = entry;
666         if (!fs_mgr_overlayfs_already_mounted(entry.mount_point) &&
667             !fs_mgr_wants_overlayfs(&new_entry)) {
668             continue;
669         }
670         const auto new_mount_point = fs_mgr_mount_point(new_entry.mount_point);
671         if (std::find_if(candidates.begin(), candidates.end(), [&](const auto& it) {
672                 return fs_mgr_mount_point(it.mount_point) == new_mount_point;
673             }) != candidates.end()) {
674             continue;
675         }
676         candidates.push_back(std::move(new_entry));
677     }
678     return candidates;
679 }
680 
TryMountScratch()681 static void TryMountScratch() {
682     // Note we get the boot scratch device here, which means if scratch was
683     // just created through ImageManager, this could fail. In practice this
684     // should not happen because "remount" detects this scenario (by checking
685     // if verity is still disabled, i.e. no reboot occurred), and skips calling
686     // fs_mgr_overlayfs_mount_all().
687     auto scratch_device = GetBootScratchDevice();
688     if (access(scratch_device.c_str(), R_OK | W_OK)) {
689         return;
690     }
691     if (!WaitForFile(scratch_device, 10s)) {
692         return;
693     }
694     if (!MountScratch(scratch_device, true /* readonly */)) {
695         return;
696     }
697     const auto top = kScratchMountPoint + "/"s + kOverlayTopDir;
698     const bool has_overlayfs_dir = access(top.c_str(), F_OK) == 0;
699     fs_mgr_overlayfs_umount_scratch();
700     if (has_overlayfs_dir) {
701         MountScratch(scratch_device);
702     }
703 }
704 
fs_mgr_overlayfs_mount_all(Fstab * fstab)705 bool fs_mgr_overlayfs_mount_all(Fstab* fstab) {
706     if (!OverlayfsSetupAllowed()) {
707         return false;
708     }
709 
710     // Ensure kMoveMountTempDir is standalone mount tree with 'private' propagation by bind mounting
711     // to itself and set to MS_PRIVATE.
712     // Otherwise mounts moved in to it would have their propagation type changed unintentionally.
713     // Section 5d, https://www.kernel.org/doc/Documentation/filesystems/sharedsubtree.txt
714     if (!fs_mgr_overlayfs_already_mounted(kMoveMountTempDir, false)) {
715         if (mkdir(kMoveMountTempDir, 0755) && errno != EEXIST) {
716             PERROR << "mkdir " << kMoveMountTempDir;
717         }
718         if (mount(kMoveMountTempDir, kMoveMountTempDir, nullptr, MS_BIND, nullptr)) {
719             PERROR << "bind mount " << kMoveMountTempDir;
720         }
721     }
722     fs_mgr_overlayfs_set_shared_mount(kMoveMountTempDir, false);
723     android::base::ScopeGuard umountDir([]() {
724         umount(kMoveMountTempDir);
725         rmdir(kMoveMountTempDir);
726     });
727 
728     auto ret = true;
729     auto scratch_can_be_mounted = !fs_mgr_overlayfs_already_mounted(kScratchMountPoint, false);
730     for (const auto& entry : fs_mgr_overlayfs_candidate_list(*fstab)) {
731         if (fs_mgr_is_verity_enabled(entry)) continue;
732         auto mount_point = fs_mgr_mount_point(entry.mount_point);
733         if (fs_mgr_overlayfs_already_mounted(mount_point)) {
734             continue;
735         }
736         if (scratch_can_be_mounted) {
737             scratch_can_be_mounted = false;
738             TryMountScratch();
739         }
740         ret &= fs_mgr_overlayfs_mount_one(entry);
741     }
742     return ret;
743 }
744 
fs_mgr_overlayfs_is_setup()745 bool fs_mgr_overlayfs_is_setup() {
746     if (!OverlayfsSetupAllowed()) {
747         return false;
748     }
749     if (fs_mgr_overlayfs_already_mounted(kScratchMountPoint, false)) return true;
750     Fstab fstab;
751     if (!ReadDefaultFstab(&fstab)) {
752         return false;
753     }
754     for (const auto& entry : fs_mgr_overlayfs_candidate_list(fstab)) {
755         if (fs_mgr_is_verity_enabled(entry)) continue;
756         if (fs_mgr_overlayfs_already_mounted(fs_mgr_mount_point(entry.mount_point))) return true;
757     }
758     return false;
759 }
760 
fs_mgr_overlayfs_already_mounted(const std::string & mount_point,bool overlay_only)761 bool fs_mgr_overlayfs_already_mounted(const std::string& mount_point, bool overlay_only) {
762     Fstab fstab;
763     if (!ReadFstabFromProcMounts(&fstab)) {
764         return false;
765     }
766     const auto lowerdir = kLowerdirOption + mount_point;
767     for (const auto& entry : GetEntriesForMountPoint(&fstab, mount_point)) {
768         if (!overlay_only) {
769             return true;
770         }
771         if (entry->fs_type != "overlay" && entry->fs_type != "overlayfs") {
772             continue;
773         }
774         const auto options = android::base::Split(entry->fs_options, ",");
775         for (const auto& opt : options) {
776             if (opt == lowerdir) {
777                 return true;
778             }
779         }
780     }
781     return false;
782 }
783 
784 namespace android {
785 namespace fs_mgr {
786 
MountOverlayfs(const FstabEntry & fstab_entry,bool * scratch_can_be_mounted)787 void MountOverlayfs(const FstabEntry& fstab_entry, bool* scratch_can_be_mounted) {
788     if (!OverlayfsSetupAllowed()) {
789         return;
790     }
791     const auto candidates = fs_mgr_overlayfs_candidate_list({fstab_entry});
792     if (candidates.empty()) {
793         return;
794     }
795     const auto& entry = candidates.front();
796     if (fs_mgr_is_verity_enabled(entry)) {
797         return;
798     }
799     const auto mount_point = fs_mgr_mount_point(entry.mount_point);
800     if (fs_mgr_overlayfs_already_mounted(mount_point)) {
801         return;
802     }
803     if (*scratch_can_be_mounted) {
804         *scratch_can_be_mounted = false;
805         if (!fs_mgr_overlayfs_already_mounted(kScratchMountPoint, false)) {
806             TryMountScratch();
807         }
808     }
809     const auto options = fs_mgr_get_overlayfs_options(entry);
810     if (options.empty()) {
811         return;
812     }
813     fs_mgr_overlayfs_mount(mount_point, options);
814 }
815 
816 }  // namespace fs_mgr
817 }  // namespace android
818