xref: /aosp_15_r20/system/vold/Utils.cpp (revision f40fafd4c6c2594924d919feffc1a1fd6e3b30f3)
1*f40fafd4SAndroid Build Coastguard Worker /*
2*f40fafd4SAndroid Build Coastguard Worker  * Copyright (C) 2015 The Android Open Source Project
3*f40fafd4SAndroid Build Coastguard Worker  *
4*f40fafd4SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*f40fafd4SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*f40fafd4SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*f40fafd4SAndroid Build Coastguard Worker  *
8*f40fafd4SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*f40fafd4SAndroid Build Coastguard Worker  *
10*f40fafd4SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*f40fafd4SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*f40fafd4SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*f40fafd4SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*f40fafd4SAndroid Build Coastguard Worker  * limitations under the License.
15*f40fafd4SAndroid Build Coastguard Worker  */
16*f40fafd4SAndroid Build Coastguard Worker 
17*f40fafd4SAndroid Build Coastguard Worker #include "Utils.h"
18*f40fafd4SAndroid Build Coastguard Worker 
19*f40fafd4SAndroid Build Coastguard Worker #include "Process.h"
20*f40fafd4SAndroid Build Coastguard Worker #include "sehandle.h"
21*f40fafd4SAndroid Build Coastguard Worker 
22*f40fafd4SAndroid Build Coastguard Worker #include <android-base/chrono_utils.h>
23*f40fafd4SAndroid Build Coastguard Worker #include <android-base/file.h>
24*f40fafd4SAndroid Build Coastguard Worker #include <android-base/logging.h>
25*f40fafd4SAndroid Build Coastguard Worker #include <android-base/properties.h>
26*f40fafd4SAndroid Build Coastguard Worker #include <android-base/scopeguard.h>
27*f40fafd4SAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
28*f40fafd4SAndroid Build Coastguard Worker #include <android-base/strings.h>
29*f40fafd4SAndroid Build Coastguard Worker #include <android-base/unique_fd.h>
30*f40fafd4SAndroid Build Coastguard Worker #include <cutils/fs.h>
31*f40fafd4SAndroid Build Coastguard Worker #include <logwrap/logwrap.h>
32*f40fafd4SAndroid Build Coastguard Worker #include <private/android_filesystem_config.h>
33*f40fafd4SAndroid Build Coastguard Worker #include <private/android_projectid_config.h>
34*f40fafd4SAndroid Build Coastguard Worker 
35*f40fafd4SAndroid Build Coastguard Worker #include <dirent.h>
36*f40fafd4SAndroid Build Coastguard Worker #include <fcntl.h>
37*f40fafd4SAndroid Build Coastguard Worker #include <linux/fs.h>
38*f40fafd4SAndroid Build Coastguard Worker #include <linux/posix_acl.h>
39*f40fafd4SAndroid Build Coastguard Worker #include <linux/posix_acl_xattr.h>
40*f40fafd4SAndroid Build Coastguard Worker #include <mntent.h>
41*f40fafd4SAndroid Build Coastguard Worker #include <stdio.h>
42*f40fafd4SAndroid Build Coastguard Worker #include <stdlib.h>
43*f40fafd4SAndroid Build Coastguard Worker #include <sys/mount.h>
44*f40fafd4SAndroid Build Coastguard Worker #include <sys/stat.h>
45*f40fafd4SAndroid Build Coastguard Worker #include <sys/statvfs.h>
46*f40fafd4SAndroid Build Coastguard Worker #include <sys/sysmacros.h>
47*f40fafd4SAndroid Build Coastguard Worker #include <sys/types.h>
48*f40fafd4SAndroid Build Coastguard Worker #include <sys/wait.h>
49*f40fafd4SAndroid Build Coastguard Worker #include <sys/xattr.h>
50*f40fafd4SAndroid Build Coastguard Worker #include <unistd.h>
51*f40fafd4SAndroid Build Coastguard Worker 
52*f40fafd4SAndroid Build Coastguard Worker #include <filesystem>
53*f40fafd4SAndroid Build Coastguard Worker #include <list>
54*f40fafd4SAndroid Build Coastguard Worker #include <mutex>
55*f40fafd4SAndroid Build Coastguard Worker #include <regex>
56*f40fafd4SAndroid Build Coastguard Worker #include <thread>
57*f40fafd4SAndroid Build Coastguard Worker 
58*f40fafd4SAndroid Build Coastguard Worker #ifndef UMOUNT_NOFOLLOW
59*f40fafd4SAndroid Build Coastguard Worker #define UMOUNT_NOFOLLOW 0x00000008 /* Don't follow symlink on umount */
60*f40fafd4SAndroid Build Coastguard Worker #endif
61*f40fafd4SAndroid Build Coastguard Worker 
62*f40fafd4SAndroid Build Coastguard Worker using namespace std::chrono_literals;
63*f40fafd4SAndroid Build Coastguard Worker using android::base::EndsWith;
64*f40fafd4SAndroid Build Coastguard Worker using android::base::ReadFileToString;
65*f40fafd4SAndroid Build Coastguard Worker using android::base::StartsWith;
66*f40fafd4SAndroid Build Coastguard Worker using android::base::StringPrintf;
67*f40fafd4SAndroid Build Coastguard Worker using android::base::unique_fd;
68*f40fafd4SAndroid Build Coastguard Worker 
69*f40fafd4SAndroid Build Coastguard Worker namespace android {
70*f40fafd4SAndroid Build Coastguard Worker namespace vold {
71*f40fafd4SAndroid Build Coastguard Worker 
72*f40fafd4SAndroid Build Coastguard Worker char* sBlkidContext = nullptr;
73*f40fafd4SAndroid Build Coastguard Worker char* sBlkidUntrustedContext = nullptr;
74*f40fafd4SAndroid Build Coastguard Worker char* sFsckContext = nullptr;
75*f40fafd4SAndroid Build Coastguard Worker char* sFsckUntrustedContext = nullptr;
76*f40fafd4SAndroid Build Coastguard Worker 
77*f40fafd4SAndroid Build Coastguard Worker bool sSleepOnUnmount = true;
78*f40fafd4SAndroid Build Coastguard Worker 
79*f40fafd4SAndroid Build Coastguard Worker static const char* kBlkidPath = "/system/bin/blkid";
80*f40fafd4SAndroid Build Coastguard Worker static const char* kKeyPath = "/data/misc/vold";
81*f40fafd4SAndroid Build Coastguard Worker 
82*f40fafd4SAndroid Build Coastguard Worker static const char* kProcDevices = "/proc/devices";
83*f40fafd4SAndroid Build Coastguard Worker static const char* kProcFilesystems = "/proc/filesystems";
84*f40fafd4SAndroid Build Coastguard Worker 
85*f40fafd4SAndroid Build Coastguard Worker static const char* kAndroidDir = "/Android/";
86*f40fafd4SAndroid Build Coastguard Worker static const char* kAppDataDir = "/Android/data/";
87*f40fafd4SAndroid Build Coastguard Worker static const char* kAppMediaDir = "/Android/media/";
88*f40fafd4SAndroid Build Coastguard Worker static const char* kAppObbDir = "/Android/obb/";
89*f40fafd4SAndroid Build Coastguard Worker 
90*f40fafd4SAndroid Build Coastguard Worker static const char* kMediaProviderCtx = "u:r:mediaprovider:";
91*f40fafd4SAndroid Build Coastguard Worker static const char* kMediaProviderAppCtx = "u:r:mediaprovider_app:";
92*f40fafd4SAndroid Build Coastguard Worker 
93*f40fafd4SAndroid Build Coastguard Worker // Lock used to protect process-level SELinux changes from racing with each
94*f40fafd4SAndroid Build Coastguard Worker // other between multiple threads.
95*f40fafd4SAndroid Build Coastguard Worker static std::mutex kSecurityLock;
96*f40fafd4SAndroid Build Coastguard Worker 
GetFuseMountPathForUser(userid_t user_id,const std::string & relative_upper_path)97*f40fafd4SAndroid Build Coastguard Worker std::string GetFuseMountPathForUser(userid_t user_id, const std::string& relative_upper_path) {
98*f40fafd4SAndroid Build Coastguard Worker     return StringPrintf("/mnt/user/%d/%s", user_id, relative_upper_path.c_str());
99*f40fafd4SAndroid Build Coastguard Worker }
100*f40fafd4SAndroid Build Coastguard Worker 
CreateDeviceNode(const std::string & path,dev_t dev)101*f40fafd4SAndroid Build Coastguard Worker status_t CreateDeviceNode(const std::string& path, dev_t dev) {
102*f40fafd4SAndroid Build Coastguard Worker     std::lock_guard<std::mutex> lock(kSecurityLock);
103*f40fafd4SAndroid Build Coastguard Worker     const char* cpath = path.c_str();
104*f40fafd4SAndroid Build Coastguard Worker     auto clearfscreatecon = android::base::make_scope_guard([] { setfscreatecon(nullptr); });
105*f40fafd4SAndroid Build Coastguard Worker     auto secontext = std::unique_ptr<char, void (*)(char*)>(nullptr, freecon);
106*f40fafd4SAndroid Build Coastguard Worker     char* tmp_secontext;
107*f40fafd4SAndroid Build Coastguard Worker 
108*f40fafd4SAndroid Build Coastguard Worker     if (selabel_lookup(sehandle, &tmp_secontext, cpath, S_IFBLK) == 0) {
109*f40fafd4SAndroid Build Coastguard Worker         secontext.reset(tmp_secontext);
110*f40fafd4SAndroid Build Coastguard Worker         if (setfscreatecon(secontext.get()) != 0) {
111*f40fafd4SAndroid Build Coastguard Worker             LOG(ERROR) << "Failed to setfscreatecon for device node " << path;
112*f40fafd4SAndroid Build Coastguard Worker             return -EINVAL;
113*f40fafd4SAndroid Build Coastguard Worker         }
114*f40fafd4SAndroid Build Coastguard Worker     } else if (errno == ENOENT) {
115*f40fafd4SAndroid Build Coastguard Worker         LOG(DEBUG) << "No selabel defined for device node " << path;
116*f40fafd4SAndroid Build Coastguard Worker     } else {
117*f40fafd4SAndroid Build Coastguard Worker         PLOG(ERROR) << "Failed to look up selabel for device node " << path;
118*f40fafd4SAndroid Build Coastguard Worker         return -errno;
119*f40fafd4SAndroid Build Coastguard Worker     }
120*f40fafd4SAndroid Build Coastguard Worker 
121*f40fafd4SAndroid Build Coastguard Worker     mode_t mode = 0660 | S_IFBLK;
122*f40fafd4SAndroid Build Coastguard Worker     if (mknod(cpath, mode, dev) < 0) {
123*f40fafd4SAndroid Build Coastguard Worker         if (errno != EEXIST) {
124*f40fafd4SAndroid Build Coastguard Worker             PLOG(ERROR) << "Failed to create device node for " << major(dev) << ":" << minor(dev)
125*f40fafd4SAndroid Build Coastguard Worker                         << " at " << path;
126*f40fafd4SAndroid Build Coastguard Worker             return -errno;
127*f40fafd4SAndroid Build Coastguard Worker         }
128*f40fafd4SAndroid Build Coastguard Worker     }
129*f40fafd4SAndroid Build Coastguard Worker     return OK;
130*f40fafd4SAndroid Build Coastguard Worker }
131*f40fafd4SAndroid Build Coastguard Worker 
DestroyDeviceNode(const std::string & path)132*f40fafd4SAndroid Build Coastguard Worker status_t DestroyDeviceNode(const std::string& path) {
133*f40fafd4SAndroid Build Coastguard Worker     const char* cpath = path.c_str();
134*f40fafd4SAndroid Build Coastguard Worker     if (TEMP_FAILURE_RETRY(unlink(cpath))) {
135*f40fafd4SAndroid Build Coastguard Worker         return -errno;
136*f40fafd4SAndroid Build Coastguard Worker     } else {
137*f40fafd4SAndroid Build Coastguard Worker         return OK;
138*f40fafd4SAndroid Build Coastguard Worker     }
139*f40fafd4SAndroid Build Coastguard Worker }
140*f40fafd4SAndroid Build Coastguard Worker 
141*f40fafd4SAndroid Build Coastguard Worker // Sets a default ACL on the directory.
SetDefaultAcl(const std::string & path,mode_t mode,uid_t uid,gid_t gid,std::vector<gid_t> additionalGids)142*f40fafd4SAndroid Build Coastguard Worker status_t SetDefaultAcl(const std::string& path, mode_t mode, uid_t uid, gid_t gid,
143*f40fafd4SAndroid Build Coastguard Worker                        std::vector<gid_t> additionalGids) {
144*f40fafd4SAndroid Build Coastguard Worker     if (IsSdcardfsUsed()) {
145*f40fafd4SAndroid Build Coastguard Worker         // sdcardfs magically takes care of this
146*f40fafd4SAndroid Build Coastguard Worker         return OK;
147*f40fafd4SAndroid Build Coastguard Worker     }
148*f40fafd4SAndroid Build Coastguard Worker 
149*f40fafd4SAndroid Build Coastguard Worker     size_t num_entries = 3 + (additionalGids.size() > 0 ? additionalGids.size() + 1 : 0);
150*f40fafd4SAndroid Build Coastguard Worker     size_t size = sizeof(posix_acl_xattr_header) + num_entries * sizeof(posix_acl_xattr_entry);
151*f40fafd4SAndroid Build Coastguard Worker     auto buf = std::make_unique<uint8_t[]>(size);
152*f40fafd4SAndroid Build Coastguard Worker 
153*f40fafd4SAndroid Build Coastguard Worker     posix_acl_xattr_header* acl_header = reinterpret_cast<posix_acl_xattr_header*>(buf.get());
154*f40fafd4SAndroid Build Coastguard Worker     acl_header->a_version = POSIX_ACL_XATTR_VERSION;
155*f40fafd4SAndroid Build Coastguard Worker 
156*f40fafd4SAndroid Build Coastguard Worker     posix_acl_xattr_entry* entry =
157*f40fafd4SAndroid Build Coastguard Worker             reinterpret_cast<posix_acl_xattr_entry*>(buf.get() + sizeof(posix_acl_xattr_header));
158*f40fafd4SAndroid Build Coastguard Worker 
159*f40fafd4SAndroid Build Coastguard Worker     int tag_index = 0;
160*f40fafd4SAndroid Build Coastguard Worker 
161*f40fafd4SAndroid Build Coastguard Worker     entry[tag_index].e_tag = ACL_USER_OBJ;
162*f40fafd4SAndroid Build Coastguard Worker     // The existing mode_t mask has the ACL in the lower 9 bits:
163*f40fafd4SAndroid Build Coastguard Worker     // the lowest 3 for "other", the next 3 the group, the next 3 for the owner
164*f40fafd4SAndroid Build Coastguard Worker     // Use the mode_t masks to get these bits out, and shift them to get the
165*f40fafd4SAndroid Build Coastguard Worker     // correct value per entity.
166*f40fafd4SAndroid Build Coastguard Worker     //
167*f40fafd4SAndroid Build Coastguard Worker     // Eg if mode_t = 0700, rwx for the owner, then & S_IRWXU >> 6 results in 7
168*f40fafd4SAndroid Build Coastguard Worker     entry[tag_index].e_perm = (mode & S_IRWXU) >> 6;
169*f40fafd4SAndroid Build Coastguard Worker     entry[tag_index].e_id = uid;
170*f40fafd4SAndroid Build Coastguard Worker     tag_index++;
171*f40fafd4SAndroid Build Coastguard Worker 
172*f40fafd4SAndroid Build Coastguard Worker     entry[tag_index].e_tag = ACL_GROUP_OBJ;
173*f40fafd4SAndroid Build Coastguard Worker     entry[tag_index].e_perm = (mode & S_IRWXG) >> 3;
174*f40fafd4SAndroid Build Coastguard Worker     entry[tag_index].e_id = gid;
175*f40fafd4SAndroid Build Coastguard Worker     tag_index++;
176*f40fafd4SAndroid Build Coastguard Worker 
177*f40fafd4SAndroid Build Coastguard Worker     if (additionalGids.size() > 0) {
178*f40fafd4SAndroid Build Coastguard Worker         for (gid_t additional_gid : additionalGids) {
179*f40fafd4SAndroid Build Coastguard Worker             entry[tag_index].e_tag = ACL_GROUP;
180*f40fafd4SAndroid Build Coastguard Worker             entry[tag_index].e_perm = (mode & S_IRWXG) >> 3;
181*f40fafd4SAndroid Build Coastguard Worker             entry[tag_index].e_id = additional_gid;
182*f40fafd4SAndroid Build Coastguard Worker             tag_index++;
183*f40fafd4SAndroid Build Coastguard Worker         }
184*f40fafd4SAndroid Build Coastguard Worker 
185*f40fafd4SAndroid Build Coastguard Worker         entry[tag_index].e_tag = ACL_MASK;
186*f40fafd4SAndroid Build Coastguard Worker         entry[tag_index].e_perm = (mode & S_IRWXG) >> 3;
187*f40fafd4SAndroid Build Coastguard Worker         entry[tag_index].e_id = 0;
188*f40fafd4SAndroid Build Coastguard Worker         tag_index++;
189*f40fafd4SAndroid Build Coastguard Worker     }
190*f40fafd4SAndroid Build Coastguard Worker 
191*f40fafd4SAndroid Build Coastguard Worker     entry[tag_index].e_tag = ACL_OTHER;
192*f40fafd4SAndroid Build Coastguard Worker     entry[tag_index].e_perm = mode & S_IRWXO;
193*f40fafd4SAndroid Build Coastguard Worker     entry[tag_index].e_id = 0;
194*f40fafd4SAndroid Build Coastguard Worker 
195*f40fafd4SAndroid Build Coastguard Worker     int ret = setxattr(path.c_str(), XATTR_NAME_POSIX_ACL_DEFAULT, acl_header, size, 0);
196*f40fafd4SAndroid Build Coastguard Worker 
197*f40fafd4SAndroid Build Coastguard Worker     if (ret != 0) {
198*f40fafd4SAndroid Build Coastguard Worker         PLOG(ERROR) << "Failed to set default ACL on " << path;
199*f40fafd4SAndroid Build Coastguard Worker     }
200*f40fafd4SAndroid Build Coastguard Worker 
201*f40fafd4SAndroid Build Coastguard Worker     return ret;
202*f40fafd4SAndroid Build Coastguard Worker }
203*f40fafd4SAndroid Build Coastguard Worker 
SetQuotaInherit(const std::string & path)204*f40fafd4SAndroid Build Coastguard Worker int SetQuotaInherit(const std::string& path) {
205*f40fafd4SAndroid Build Coastguard Worker     unsigned int flags;
206*f40fafd4SAndroid Build Coastguard Worker 
207*f40fafd4SAndroid Build Coastguard Worker     android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY | O_CLOEXEC)));
208*f40fafd4SAndroid Build Coastguard Worker     if (fd == -1) {
209*f40fafd4SAndroid Build Coastguard Worker         PLOG(ERROR) << "Failed to open " << path << " to set project id inheritance.";
210*f40fafd4SAndroid Build Coastguard Worker         return -1;
211*f40fafd4SAndroid Build Coastguard Worker     }
212*f40fafd4SAndroid Build Coastguard Worker 
213*f40fafd4SAndroid Build Coastguard Worker     int ret = ioctl(fd, FS_IOC_GETFLAGS, &flags);
214*f40fafd4SAndroid Build Coastguard Worker     if (ret == -1) {
215*f40fafd4SAndroid Build Coastguard Worker         PLOG(ERROR) << "Failed to get flags for " << path << " to set project id inheritance.";
216*f40fafd4SAndroid Build Coastguard Worker         return ret;
217*f40fafd4SAndroid Build Coastguard Worker     }
218*f40fafd4SAndroid Build Coastguard Worker 
219*f40fafd4SAndroid Build Coastguard Worker     flags |= FS_PROJINHERIT_FL;
220*f40fafd4SAndroid Build Coastguard Worker 
221*f40fafd4SAndroid Build Coastguard Worker     ret = ioctl(fd, FS_IOC_SETFLAGS, &flags);
222*f40fafd4SAndroid Build Coastguard Worker     if (ret == -1) {
223*f40fafd4SAndroid Build Coastguard Worker         PLOG(ERROR) << "Failed to set flags for " << path << " to set project id inheritance.";
224*f40fafd4SAndroid Build Coastguard Worker         return ret;
225*f40fafd4SAndroid Build Coastguard Worker     }
226*f40fafd4SAndroid Build Coastguard Worker 
227*f40fafd4SAndroid Build Coastguard Worker     return 0;
228*f40fafd4SAndroid Build Coastguard Worker }
229*f40fafd4SAndroid Build Coastguard Worker 
SetQuotaProjectId(const std::string & path,long projectId)230*f40fafd4SAndroid Build Coastguard Worker int SetQuotaProjectId(const std::string& path, long projectId) {
231*f40fafd4SAndroid Build Coastguard Worker     struct fsxattr fsx;
232*f40fafd4SAndroid Build Coastguard Worker 
233*f40fafd4SAndroid Build Coastguard Worker     android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY | O_CLOEXEC)));
234*f40fafd4SAndroid Build Coastguard Worker     if (fd == -1) {
235*f40fafd4SAndroid Build Coastguard Worker         PLOG(ERROR) << "Failed to open " << path << " to set project id.";
236*f40fafd4SAndroid Build Coastguard Worker         return -1;
237*f40fafd4SAndroid Build Coastguard Worker     }
238*f40fafd4SAndroid Build Coastguard Worker 
239*f40fafd4SAndroid Build Coastguard Worker     int ret = ioctl(fd, FS_IOC_FSGETXATTR, &fsx);
240*f40fafd4SAndroid Build Coastguard Worker     if (ret == -1) {
241*f40fafd4SAndroid Build Coastguard Worker         PLOG(ERROR) << "Failed to get extended attributes for " << path << " to get project id.";
242*f40fafd4SAndroid Build Coastguard Worker         return ret;
243*f40fafd4SAndroid Build Coastguard Worker     }
244*f40fafd4SAndroid Build Coastguard Worker 
245*f40fafd4SAndroid Build Coastguard Worker     fsx.fsx_projid = projectId;
246*f40fafd4SAndroid Build Coastguard Worker     ret = ioctl(fd, FS_IOC_FSSETXATTR, &fsx);
247*f40fafd4SAndroid Build Coastguard Worker     if (ret == -1) {
248*f40fafd4SAndroid Build Coastguard Worker         PLOG(ERROR) << "Failed to set project id on " << path;
249*f40fafd4SAndroid Build Coastguard Worker         return ret;
250*f40fafd4SAndroid Build Coastguard Worker     }
251*f40fafd4SAndroid Build Coastguard Worker     return 0;
252*f40fafd4SAndroid Build Coastguard Worker }
253*f40fafd4SAndroid Build Coastguard Worker 
PrepareDirWithProjectId(const std::string & path,mode_t mode,uid_t uid,gid_t gid,long projectId)254*f40fafd4SAndroid Build Coastguard Worker int PrepareDirWithProjectId(const std::string& path, mode_t mode, uid_t uid, gid_t gid,
255*f40fafd4SAndroid Build Coastguard Worker                             long projectId) {
256*f40fafd4SAndroid Build Coastguard Worker     int ret = fs_prepare_dir(path.c_str(), mode, uid, gid);
257*f40fafd4SAndroid Build Coastguard Worker 
258*f40fafd4SAndroid Build Coastguard Worker     if (ret != 0) {
259*f40fafd4SAndroid Build Coastguard Worker         return ret;
260*f40fafd4SAndroid Build Coastguard Worker     }
261*f40fafd4SAndroid Build Coastguard Worker 
262*f40fafd4SAndroid Build Coastguard Worker     if (!IsSdcardfsUsed()) {
263*f40fafd4SAndroid Build Coastguard Worker         ret = SetQuotaProjectId(path, projectId);
264*f40fafd4SAndroid Build Coastguard Worker     }
265*f40fafd4SAndroid Build Coastguard Worker 
266*f40fafd4SAndroid Build Coastguard Worker     return ret;
267*f40fafd4SAndroid Build Coastguard Worker }
268*f40fafd4SAndroid Build Coastguard Worker 
FixupAppDir(const std::string & path,mode_t mode,uid_t uid,gid_t gid,long projectId)269*f40fafd4SAndroid Build Coastguard Worker static int FixupAppDir(const std::string& path, mode_t mode, uid_t uid, gid_t gid, long projectId) {
270*f40fafd4SAndroid Build Coastguard Worker     namespace fs = std::filesystem;
271*f40fafd4SAndroid Build Coastguard Worker 
272*f40fafd4SAndroid Build Coastguard Worker     // Setup the directory itself correctly
273*f40fafd4SAndroid Build Coastguard Worker     int ret = PrepareDirWithProjectId(path, mode, uid, gid, projectId);
274*f40fafd4SAndroid Build Coastguard Worker     if (ret != OK) {
275*f40fafd4SAndroid Build Coastguard Worker         return ret;
276*f40fafd4SAndroid Build Coastguard Worker     }
277*f40fafd4SAndroid Build Coastguard Worker 
278*f40fafd4SAndroid Build Coastguard Worker     // Fixup all of its file entries
279*f40fafd4SAndroid Build Coastguard Worker     for (const auto& itEntry : fs::directory_iterator(path)) {
280*f40fafd4SAndroid Build Coastguard Worker         ret = lchown(itEntry.path().c_str(), uid, gid);
281*f40fafd4SAndroid Build Coastguard Worker         if (ret != 0) {
282*f40fafd4SAndroid Build Coastguard Worker             return ret;
283*f40fafd4SAndroid Build Coastguard Worker         }
284*f40fafd4SAndroid Build Coastguard Worker 
285*f40fafd4SAndroid Build Coastguard Worker         ret = chmod(itEntry.path().c_str(), mode);
286*f40fafd4SAndroid Build Coastguard Worker         if (ret != 0) {
287*f40fafd4SAndroid Build Coastguard Worker             return ret;
288*f40fafd4SAndroid Build Coastguard Worker         }
289*f40fafd4SAndroid Build Coastguard Worker 
290*f40fafd4SAndroid Build Coastguard Worker         if (!IsSdcardfsUsed()) {
291*f40fafd4SAndroid Build Coastguard Worker             ret = SetQuotaProjectId(itEntry.path(), projectId);
292*f40fafd4SAndroid Build Coastguard Worker             if (ret != 0) {
293*f40fafd4SAndroid Build Coastguard Worker                 return ret;
294*f40fafd4SAndroid Build Coastguard Worker             }
295*f40fafd4SAndroid Build Coastguard Worker         }
296*f40fafd4SAndroid Build Coastguard Worker     }
297*f40fafd4SAndroid Build Coastguard Worker 
298*f40fafd4SAndroid Build Coastguard Worker     return OK;
299*f40fafd4SAndroid Build Coastguard Worker }
300*f40fafd4SAndroid Build Coastguard Worker 
PrepareAppDirFromRoot(const std::string & path,const std::string & root,int appUid,bool fixupExisting)301*f40fafd4SAndroid Build Coastguard Worker int PrepareAppDirFromRoot(const std::string& path, const std::string& root, int appUid,
302*f40fafd4SAndroid Build Coastguard Worker                           bool fixupExisting) {
303*f40fafd4SAndroid Build Coastguard Worker     long projectId;
304*f40fafd4SAndroid Build Coastguard Worker     size_t pos;
305*f40fafd4SAndroid Build Coastguard Worker     int ret = 0;
306*f40fafd4SAndroid Build Coastguard Worker     bool sdcardfsSupport = IsSdcardfsUsed();
307*f40fafd4SAndroid Build Coastguard Worker 
308*f40fafd4SAndroid Build Coastguard Worker     // Make sure the Android/ directories exist and are setup correctly
309*f40fafd4SAndroid Build Coastguard Worker     ret = PrepareAndroidDirs(root);
310*f40fafd4SAndroid Build Coastguard Worker     if (ret != 0) {
311*f40fafd4SAndroid Build Coastguard Worker         LOG(ERROR) << "Failed to prepare Android/ directories.";
312*f40fafd4SAndroid Build Coastguard Worker         return ret;
313*f40fafd4SAndroid Build Coastguard Worker     }
314*f40fafd4SAndroid Build Coastguard Worker 
315*f40fafd4SAndroid Build Coastguard Worker     // Now create the application-specific subdir(s)
316*f40fafd4SAndroid Build Coastguard Worker     // path is something like /data/media/0/Android/data/com.foo/files
317*f40fafd4SAndroid Build Coastguard Worker     // First, chop off the volume root, eg /data/media/0
318*f40fafd4SAndroid Build Coastguard Worker     std::string pathFromRoot = path.substr(root.length());
319*f40fafd4SAndroid Build Coastguard Worker 
320*f40fafd4SAndroid Build Coastguard Worker     uid_t uid = appUid;
321*f40fafd4SAndroid Build Coastguard Worker     gid_t gid = AID_MEDIA_RW;
322*f40fafd4SAndroid Build Coastguard Worker     std::vector<gid_t> additionalGids;
323*f40fafd4SAndroid Build Coastguard Worker     std::string appDir;
324*f40fafd4SAndroid Build Coastguard Worker 
325*f40fafd4SAndroid Build Coastguard Worker     // Check that the next part matches one of the allowed Android/ dirs
326*f40fafd4SAndroid Build Coastguard Worker     if (StartsWith(pathFromRoot, kAppDataDir)) {
327*f40fafd4SAndroid Build Coastguard Worker         appDir = kAppDataDir;
328*f40fafd4SAndroid Build Coastguard Worker         if (!sdcardfsSupport) {
329*f40fafd4SAndroid Build Coastguard Worker             gid = AID_EXT_DATA_RW;
330*f40fafd4SAndroid Build Coastguard Worker             // Also add the app's own UID as a group; since apps belong to a group
331*f40fafd4SAndroid Build Coastguard Worker             // that matches their UID, this ensures that they will always have access to
332*f40fafd4SAndroid Build Coastguard Worker             // the files created in these dirs, even if they are created by other processes
333*f40fafd4SAndroid Build Coastguard Worker             additionalGids.push_back(uid);
334*f40fafd4SAndroid Build Coastguard Worker         }
335*f40fafd4SAndroid Build Coastguard Worker     } else if (StartsWith(pathFromRoot, kAppMediaDir)) {
336*f40fafd4SAndroid Build Coastguard Worker         appDir = kAppMediaDir;
337*f40fafd4SAndroid Build Coastguard Worker         if (!sdcardfsSupport) {
338*f40fafd4SAndroid Build Coastguard Worker             gid = AID_MEDIA_RW;
339*f40fafd4SAndroid Build Coastguard Worker         }
340*f40fafd4SAndroid Build Coastguard Worker     } else if (StartsWith(pathFromRoot, kAppObbDir)) {
341*f40fafd4SAndroid Build Coastguard Worker         appDir = kAppObbDir;
342*f40fafd4SAndroid Build Coastguard Worker         if (!sdcardfsSupport) {
343*f40fafd4SAndroid Build Coastguard Worker             gid = AID_EXT_OBB_RW;
344*f40fafd4SAndroid Build Coastguard Worker             // See comments for kAppDataDir above
345*f40fafd4SAndroid Build Coastguard Worker             additionalGids.push_back(uid);
346*f40fafd4SAndroid Build Coastguard Worker         }
347*f40fafd4SAndroid Build Coastguard Worker     } else {
348*f40fafd4SAndroid Build Coastguard Worker         LOG(ERROR) << "Invalid application directory: " << path;
349*f40fafd4SAndroid Build Coastguard Worker         return -EINVAL;
350*f40fafd4SAndroid Build Coastguard Worker     }
351*f40fafd4SAndroid Build Coastguard Worker 
352*f40fafd4SAndroid Build Coastguard Worker     // mode = 770, plus sticky bit on directory to inherit GID when apps
353*f40fafd4SAndroid Build Coastguard Worker     // create subdirs
354*f40fafd4SAndroid Build Coastguard Worker     mode_t mode = S_IRWXU | S_IRWXG | S_ISGID;
355*f40fafd4SAndroid Build Coastguard Worker     // the project ID for application-specific directories is directly
356*f40fafd4SAndroid Build Coastguard Worker     // derived from their uid
357*f40fafd4SAndroid Build Coastguard Worker 
358*f40fafd4SAndroid Build Coastguard Worker     // Chop off the generic application-specific part, eg /Android/data/
359*f40fafd4SAndroid Build Coastguard Worker     // this leaves us with something like com.foo/files/
360*f40fafd4SAndroid Build Coastguard Worker     std::string leftToCreate = pathFromRoot.substr(appDir.length());
361*f40fafd4SAndroid Build Coastguard Worker     if (!EndsWith(leftToCreate, "/")) {
362*f40fafd4SAndroid Build Coastguard Worker         leftToCreate += "/";
363*f40fafd4SAndroid Build Coastguard Worker     }
364*f40fafd4SAndroid Build Coastguard Worker     std::string pathToCreate = root + appDir;
365*f40fafd4SAndroid Build Coastguard Worker     int depth = 0;
366*f40fafd4SAndroid Build Coastguard Worker     // Derive initial project ID
367*f40fafd4SAndroid Build Coastguard Worker     if (appDir == kAppDataDir || appDir == kAppMediaDir) {
368*f40fafd4SAndroid Build Coastguard Worker         projectId = uid - AID_APP_START + PROJECT_ID_EXT_DATA_START;
369*f40fafd4SAndroid Build Coastguard Worker     } else if (appDir == kAppObbDir) {
370*f40fafd4SAndroid Build Coastguard Worker         projectId = uid - AID_APP_START + PROJECT_ID_EXT_OBB_START;
371*f40fafd4SAndroid Build Coastguard Worker     }
372*f40fafd4SAndroid Build Coastguard Worker 
373*f40fafd4SAndroid Build Coastguard Worker     while ((pos = leftToCreate.find('/')) != std::string::npos) {
374*f40fafd4SAndroid Build Coastguard Worker         std::string component = leftToCreate.substr(0, pos + 1);
375*f40fafd4SAndroid Build Coastguard Worker         leftToCreate = leftToCreate.erase(0, pos + 1);
376*f40fafd4SAndroid Build Coastguard Worker         pathToCreate = pathToCreate + component;
377*f40fafd4SAndroid Build Coastguard Worker 
378*f40fafd4SAndroid Build Coastguard Worker         if (appDir == kAppDataDir && depth == 1 && component == "cache/") {
379*f40fafd4SAndroid Build Coastguard Worker             // All dirs use the "app" project ID, except for the cache dirs in
380*f40fafd4SAndroid Build Coastguard Worker             // Android/data, eg Android/data/com.foo/cache
381*f40fafd4SAndroid Build Coastguard Worker             // Note that this "sticks" - eg subdirs of this dir need the same
382*f40fafd4SAndroid Build Coastguard Worker             // project ID.
383*f40fafd4SAndroid Build Coastguard Worker             projectId = uid - AID_APP_START + PROJECT_ID_EXT_CACHE_START;
384*f40fafd4SAndroid Build Coastguard Worker         }
385*f40fafd4SAndroid Build Coastguard Worker 
386*f40fafd4SAndroid Build Coastguard Worker         if (fixupExisting && access(pathToCreate.c_str(), F_OK) == 0) {
387*f40fafd4SAndroid Build Coastguard Worker             // Fixup all files in this existing directory with the correct UID/GID
388*f40fafd4SAndroid Build Coastguard Worker             // and project ID.
389*f40fafd4SAndroid Build Coastguard Worker             ret = FixupAppDir(pathToCreate, mode, uid, gid, projectId);
390*f40fafd4SAndroid Build Coastguard Worker         } else {
391*f40fafd4SAndroid Build Coastguard Worker             ret = PrepareDirWithProjectId(pathToCreate, mode, uid, gid, projectId);
392*f40fafd4SAndroid Build Coastguard Worker         }
393*f40fafd4SAndroid Build Coastguard Worker 
394*f40fafd4SAndroid Build Coastguard Worker         if (ret != 0) {
395*f40fafd4SAndroid Build Coastguard Worker             return ret;
396*f40fafd4SAndroid Build Coastguard Worker         }
397*f40fafd4SAndroid Build Coastguard Worker 
398*f40fafd4SAndroid Build Coastguard Worker         if (depth == 0) {
399*f40fafd4SAndroid Build Coastguard Worker             // Set the default ACL on the top-level application-specific directories,
400*f40fafd4SAndroid Build Coastguard Worker             // to ensure that even if applications run with a umask of 0077,
401*f40fafd4SAndroid Build Coastguard Worker             // new directories within these directories will allow the GID
402*f40fafd4SAndroid Build Coastguard Worker             // specified here to write; this is necessary for apps like
403*f40fafd4SAndroid Build Coastguard Worker             // installers and MTP, that require access here.
404*f40fafd4SAndroid Build Coastguard Worker             //
405*f40fafd4SAndroid Build Coastguard Worker             // See man (5) acl for more details.
406*f40fafd4SAndroid Build Coastguard Worker             ret = SetDefaultAcl(pathToCreate, mode, uid, gid, additionalGids);
407*f40fafd4SAndroid Build Coastguard Worker             if (ret != 0) {
408*f40fafd4SAndroid Build Coastguard Worker                 return ret;
409*f40fafd4SAndroid Build Coastguard Worker             }
410*f40fafd4SAndroid Build Coastguard Worker 
411*f40fafd4SAndroid Build Coastguard Worker             if (!sdcardfsSupport) {
412*f40fafd4SAndroid Build Coastguard Worker                 // Set project ID inheritance, so that future subdirectories inherit the
413*f40fafd4SAndroid Build Coastguard Worker                 // same project ID
414*f40fafd4SAndroid Build Coastguard Worker                 ret = SetQuotaInherit(pathToCreate);
415*f40fafd4SAndroid Build Coastguard Worker                 if (ret != 0) {
416*f40fafd4SAndroid Build Coastguard Worker                     return ret;
417*f40fafd4SAndroid Build Coastguard Worker                 }
418*f40fafd4SAndroid Build Coastguard Worker             }
419*f40fafd4SAndroid Build Coastguard Worker         }
420*f40fafd4SAndroid Build Coastguard Worker 
421*f40fafd4SAndroid Build Coastguard Worker         depth++;
422*f40fafd4SAndroid Build Coastguard Worker     }
423*f40fafd4SAndroid Build Coastguard Worker 
424*f40fafd4SAndroid Build Coastguard Worker     return OK;
425*f40fafd4SAndroid Build Coastguard Worker }
426*f40fafd4SAndroid Build Coastguard Worker 
SetAttrs(const std::string & path,unsigned int attrs)427*f40fafd4SAndroid Build Coastguard Worker int SetAttrs(const std::string& path, unsigned int attrs) {
428*f40fafd4SAndroid Build Coastguard Worker     unsigned int flags;
429*f40fafd4SAndroid Build Coastguard Worker     android::base::unique_fd fd(
430*f40fafd4SAndroid Build Coastguard Worker             TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
431*f40fafd4SAndroid Build Coastguard Worker 
432*f40fafd4SAndroid Build Coastguard Worker     if (fd == -1) {
433*f40fafd4SAndroid Build Coastguard Worker         PLOG(ERROR) << "Failed to open " << path;
434*f40fafd4SAndroid Build Coastguard Worker         return -1;
435*f40fafd4SAndroid Build Coastguard Worker     }
436*f40fafd4SAndroid Build Coastguard Worker 
437*f40fafd4SAndroid Build Coastguard Worker     if (ioctl(fd, FS_IOC_GETFLAGS, &flags)) {
438*f40fafd4SAndroid Build Coastguard Worker         PLOG(ERROR) << "Failed to get flags for " << path;
439*f40fafd4SAndroid Build Coastguard Worker         return -1;
440*f40fafd4SAndroid Build Coastguard Worker     }
441*f40fafd4SAndroid Build Coastguard Worker 
442*f40fafd4SAndroid Build Coastguard Worker     if ((flags & attrs) == attrs) return 0;
443*f40fafd4SAndroid Build Coastguard Worker     flags |= attrs;
444*f40fafd4SAndroid Build Coastguard Worker     if (ioctl(fd, FS_IOC_SETFLAGS, &flags)) {
445*f40fafd4SAndroid Build Coastguard Worker         PLOG(ERROR) << "Failed to set flags for " << path << "(0x" << std::hex << attrs << ")";
446*f40fafd4SAndroid Build Coastguard Worker         return -1;
447*f40fafd4SAndroid Build Coastguard Worker     }
448*f40fafd4SAndroid Build Coastguard Worker     return 0;
449*f40fafd4SAndroid Build Coastguard Worker }
450*f40fafd4SAndroid Build Coastguard Worker 
PrepareDir(const std::string & path,mode_t mode,uid_t uid,gid_t gid,unsigned int attrs)451*f40fafd4SAndroid Build Coastguard Worker status_t PrepareDir(const std::string& path, mode_t mode, uid_t uid, gid_t gid,
452*f40fafd4SAndroid Build Coastguard Worker                     unsigned int attrs) {
453*f40fafd4SAndroid Build Coastguard Worker     std::lock_guard<std::mutex> lock(kSecurityLock);
454*f40fafd4SAndroid Build Coastguard Worker     const char* cpath = path.c_str();
455*f40fafd4SAndroid Build Coastguard Worker     auto clearfscreatecon = android::base::make_scope_guard([] { setfscreatecon(nullptr); });
456*f40fafd4SAndroid Build Coastguard Worker     auto secontext = std::unique_ptr<char, void (*)(char*)>(nullptr, freecon);
457*f40fafd4SAndroid Build Coastguard Worker     char* tmp_secontext;
458*f40fafd4SAndroid Build Coastguard Worker 
459*f40fafd4SAndroid Build Coastguard Worker     if (selabel_lookup(sehandle, &tmp_secontext, cpath, S_IFDIR) == 0) {
460*f40fafd4SAndroid Build Coastguard Worker         secontext.reset(tmp_secontext);
461*f40fafd4SAndroid Build Coastguard Worker         if (setfscreatecon(secontext.get()) != 0) {
462*f40fafd4SAndroid Build Coastguard Worker             LOG(ERROR) << "Failed to setfscreatecon for directory " << path;
463*f40fafd4SAndroid Build Coastguard Worker             return -EINVAL;
464*f40fafd4SAndroid Build Coastguard Worker         }
465*f40fafd4SAndroid Build Coastguard Worker     } else if (errno == ENOENT) {
466*f40fafd4SAndroid Build Coastguard Worker         LOG(DEBUG) << "No selabel defined for directory " << path;
467*f40fafd4SAndroid Build Coastguard Worker     } else {
468*f40fafd4SAndroid Build Coastguard Worker         PLOG(ERROR) << "Failed to look up selabel for directory " << path;
469*f40fafd4SAndroid Build Coastguard Worker         return -errno;
470*f40fafd4SAndroid Build Coastguard Worker     }
471*f40fafd4SAndroid Build Coastguard Worker 
472*f40fafd4SAndroid Build Coastguard Worker     if (fs_prepare_dir(cpath, mode, uid, gid) != 0) return -errno;
473*f40fafd4SAndroid Build Coastguard Worker     if (attrs && SetAttrs(path, attrs) != 0) return -errno;
474*f40fafd4SAndroid Build Coastguard Worker     return OK;
475*f40fafd4SAndroid Build Coastguard Worker }
476*f40fafd4SAndroid Build Coastguard Worker 
ForceUnmount(const std::string & path)477*f40fafd4SAndroid Build Coastguard Worker status_t ForceUnmount(const std::string& path) {
478*f40fafd4SAndroid Build Coastguard Worker     const char* cpath = path.c_str();
479*f40fafd4SAndroid Build Coastguard Worker     if (!umount2(cpath, UMOUNT_NOFOLLOW) || errno == EINVAL || errno == ENOENT) {
480*f40fafd4SAndroid Build Coastguard Worker         return OK;
481*f40fafd4SAndroid Build Coastguard Worker     }
482*f40fafd4SAndroid Build Coastguard Worker     // Apps might still be handling eject request, so wait before
483*f40fafd4SAndroid Build Coastguard Worker     // we start sending signals
484*f40fafd4SAndroid Build Coastguard Worker     if (sSleepOnUnmount) sleep(5);
485*f40fafd4SAndroid Build Coastguard Worker 
486*f40fafd4SAndroid Build Coastguard Worker     KillProcessesWithOpenFiles(path, SIGINT);
487*f40fafd4SAndroid Build Coastguard Worker     if (sSleepOnUnmount) sleep(5);
488*f40fafd4SAndroid Build Coastguard Worker     if (!umount2(cpath, UMOUNT_NOFOLLOW) || errno == EINVAL || errno == ENOENT) {
489*f40fafd4SAndroid Build Coastguard Worker         return OK;
490*f40fafd4SAndroid Build Coastguard Worker     }
491*f40fafd4SAndroid Build Coastguard Worker 
492*f40fafd4SAndroid Build Coastguard Worker     KillProcessesWithOpenFiles(path, SIGTERM);
493*f40fafd4SAndroid Build Coastguard Worker     if (sSleepOnUnmount) sleep(5);
494*f40fafd4SAndroid Build Coastguard Worker     if (!umount2(cpath, UMOUNT_NOFOLLOW) || errno == EINVAL || errno == ENOENT) {
495*f40fafd4SAndroid Build Coastguard Worker         return OK;
496*f40fafd4SAndroid Build Coastguard Worker     }
497*f40fafd4SAndroid Build Coastguard Worker 
498*f40fafd4SAndroid Build Coastguard Worker     KillProcessesWithOpenFiles(path, SIGKILL);
499*f40fafd4SAndroid Build Coastguard Worker     if (sSleepOnUnmount) sleep(5);
500*f40fafd4SAndroid Build Coastguard Worker     if (!umount2(cpath, UMOUNT_NOFOLLOW) || errno == EINVAL || errno == ENOENT) {
501*f40fafd4SAndroid Build Coastguard Worker         return OK;
502*f40fafd4SAndroid Build Coastguard Worker     }
503*f40fafd4SAndroid Build Coastguard Worker     PLOG(INFO) << "ForceUnmount failed";
504*f40fafd4SAndroid Build Coastguard Worker     return -errno;
505*f40fafd4SAndroid Build Coastguard Worker }
506*f40fafd4SAndroid Build Coastguard Worker 
KillProcessesWithTmpfsMountPrefix(const std::string & path)507*f40fafd4SAndroid Build Coastguard Worker status_t KillProcessesWithTmpfsMountPrefix(const std::string& path) {
508*f40fafd4SAndroid Build Coastguard Worker     if (KillProcessesWithTmpfsMounts(path, SIGINT) == 0) {
509*f40fafd4SAndroid Build Coastguard Worker         return OK;
510*f40fafd4SAndroid Build Coastguard Worker     }
511*f40fafd4SAndroid Build Coastguard Worker     if (sSleepOnUnmount) sleep(5);
512*f40fafd4SAndroid Build Coastguard Worker 
513*f40fafd4SAndroid Build Coastguard Worker     if (KillProcessesWithTmpfsMounts(path, SIGTERM) == 0) {
514*f40fafd4SAndroid Build Coastguard Worker         return OK;
515*f40fafd4SAndroid Build Coastguard Worker     }
516*f40fafd4SAndroid Build Coastguard Worker     if (sSleepOnUnmount) sleep(5);
517*f40fafd4SAndroid Build Coastguard Worker 
518*f40fafd4SAndroid Build Coastguard Worker     if (KillProcessesWithTmpfsMounts(path, SIGKILL) == 0) {
519*f40fafd4SAndroid Build Coastguard Worker         return OK;
520*f40fafd4SAndroid Build Coastguard Worker     }
521*f40fafd4SAndroid Build Coastguard Worker     if (sSleepOnUnmount) sleep(5);
522*f40fafd4SAndroid Build Coastguard Worker 
523*f40fafd4SAndroid Build Coastguard Worker     // Send SIGKILL a second time to determine if we've
524*f40fafd4SAndroid Build Coastguard Worker     // actually killed everyone mount
525*f40fafd4SAndroid Build Coastguard Worker     if (KillProcessesWithTmpfsMounts(path, SIGKILL) == 0) {
526*f40fafd4SAndroid Build Coastguard Worker         return OK;
527*f40fafd4SAndroid Build Coastguard Worker     }
528*f40fafd4SAndroid Build Coastguard Worker     PLOG(ERROR) << "Failed to kill processes using " << path;
529*f40fafd4SAndroid Build Coastguard Worker     return -EBUSY;
530*f40fafd4SAndroid Build Coastguard Worker }
531*f40fafd4SAndroid Build Coastguard Worker 
KillProcessesUsingPath(const std::string & path)532*f40fafd4SAndroid Build Coastguard Worker status_t KillProcessesUsingPath(const std::string& path) {
533*f40fafd4SAndroid Build Coastguard Worker     if (KillProcessesWithOpenFiles(path, SIGINT, false /* killFuseDaemon */) == 0) {
534*f40fafd4SAndroid Build Coastguard Worker         return OK;
535*f40fafd4SAndroid Build Coastguard Worker     }
536*f40fafd4SAndroid Build Coastguard Worker     if (sSleepOnUnmount) sleep(5);
537*f40fafd4SAndroid Build Coastguard Worker 
538*f40fafd4SAndroid Build Coastguard Worker     if (KillProcessesWithOpenFiles(path, SIGTERM, false /* killFuseDaemon */) == 0) {
539*f40fafd4SAndroid Build Coastguard Worker         return OK;
540*f40fafd4SAndroid Build Coastguard Worker     }
541*f40fafd4SAndroid Build Coastguard Worker     if (sSleepOnUnmount) sleep(5);
542*f40fafd4SAndroid Build Coastguard Worker 
543*f40fafd4SAndroid Build Coastguard Worker     if (KillProcessesWithOpenFiles(path, SIGKILL, false /* killFuseDaemon */) == 0) {
544*f40fafd4SAndroid Build Coastguard Worker         return OK;
545*f40fafd4SAndroid Build Coastguard Worker     }
546*f40fafd4SAndroid Build Coastguard Worker     if (sSleepOnUnmount) sleep(5);
547*f40fafd4SAndroid Build Coastguard Worker 
548*f40fafd4SAndroid Build Coastguard Worker     // Send SIGKILL a second time to determine if we've
549*f40fafd4SAndroid Build Coastguard Worker     // actually killed everyone with open files
550*f40fafd4SAndroid Build Coastguard Worker     // This time, we also kill the FUSE daemon if found
551*f40fafd4SAndroid Build Coastguard Worker     if (KillProcessesWithOpenFiles(path, SIGKILL, true /* killFuseDaemon */) == 0) {
552*f40fafd4SAndroid Build Coastguard Worker         return OK;
553*f40fafd4SAndroid Build Coastguard Worker     }
554*f40fafd4SAndroid Build Coastguard Worker     PLOG(ERROR) << "Failed to kill processes using " << path;
555*f40fafd4SAndroid Build Coastguard Worker     return -EBUSY;
556*f40fafd4SAndroid Build Coastguard Worker }
557*f40fafd4SAndroid Build Coastguard Worker 
BindMount(const std::string & source,const std::string & target)558*f40fafd4SAndroid Build Coastguard Worker status_t BindMount(const std::string& source, const std::string& target) {
559*f40fafd4SAndroid Build Coastguard Worker     if (UnmountTree(target) < 0) {
560*f40fafd4SAndroid Build Coastguard Worker         return -errno;
561*f40fafd4SAndroid Build Coastguard Worker     }
562*f40fafd4SAndroid Build Coastguard Worker     if (TEMP_FAILURE_RETRY(mount(source.c_str(), target.c_str(), nullptr, MS_BIND, nullptr)) < 0) {
563*f40fafd4SAndroid Build Coastguard Worker         PLOG(ERROR) << "Failed to bind mount " << source << " to " << target;
564*f40fafd4SAndroid Build Coastguard Worker         return -errno;
565*f40fafd4SAndroid Build Coastguard Worker     }
566*f40fafd4SAndroid Build Coastguard Worker     return OK;
567*f40fafd4SAndroid Build Coastguard Worker }
568*f40fafd4SAndroid Build Coastguard Worker 
Symlink(const std::string & target,const std::string & linkpath)569*f40fafd4SAndroid Build Coastguard Worker status_t Symlink(const std::string& target, const std::string& linkpath) {
570*f40fafd4SAndroid Build Coastguard Worker     if (Unlink(linkpath) < 0) {
571*f40fafd4SAndroid Build Coastguard Worker         return -errno;
572*f40fafd4SAndroid Build Coastguard Worker     }
573*f40fafd4SAndroid Build Coastguard Worker     if (TEMP_FAILURE_RETRY(symlink(target.c_str(), linkpath.c_str())) < 0) {
574*f40fafd4SAndroid Build Coastguard Worker         PLOG(ERROR) << "Failed to create symlink " << linkpath << " to " << target;
575*f40fafd4SAndroid Build Coastguard Worker         return -errno;
576*f40fafd4SAndroid Build Coastguard Worker     }
577*f40fafd4SAndroid Build Coastguard Worker     return OK;
578*f40fafd4SAndroid Build Coastguard Worker }
579*f40fafd4SAndroid Build Coastguard Worker 
Unlink(const std::string & linkpath)580*f40fafd4SAndroid Build Coastguard Worker status_t Unlink(const std::string& linkpath) {
581*f40fafd4SAndroid Build Coastguard Worker     if (TEMP_FAILURE_RETRY(unlink(linkpath.c_str())) < 0 && errno != EINVAL && errno != ENOENT) {
582*f40fafd4SAndroid Build Coastguard Worker         PLOG(ERROR) << "Failed to unlink " << linkpath;
583*f40fafd4SAndroid Build Coastguard Worker         return -errno;
584*f40fafd4SAndroid Build Coastguard Worker     }
585*f40fafd4SAndroid Build Coastguard Worker     return OK;
586*f40fafd4SAndroid Build Coastguard Worker }
587*f40fafd4SAndroid Build Coastguard Worker 
CreateDir(const std::string & dir,mode_t mode)588*f40fafd4SAndroid Build Coastguard Worker status_t CreateDir(const std::string& dir, mode_t mode) {
589*f40fafd4SAndroid Build Coastguard Worker     struct stat sb;
590*f40fafd4SAndroid Build Coastguard Worker     if (TEMP_FAILURE_RETRY(stat(dir.c_str(), &sb)) == 0) {
591*f40fafd4SAndroid Build Coastguard Worker         if (S_ISDIR(sb.st_mode)) {
592*f40fafd4SAndroid Build Coastguard Worker             return OK;
593*f40fafd4SAndroid Build Coastguard Worker         } else if (TEMP_FAILURE_RETRY(unlink(dir.c_str())) == -1) {
594*f40fafd4SAndroid Build Coastguard Worker             PLOG(ERROR) << "Failed to unlink " << dir;
595*f40fafd4SAndroid Build Coastguard Worker             return -errno;
596*f40fafd4SAndroid Build Coastguard Worker         }
597*f40fafd4SAndroid Build Coastguard Worker     } else if (errno != ENOENT) {
598*f40fafd4SAndroid Build Coastguard Worker         PLOG(ERROR) << "Failed to stat " << dir;
599*f40fafd4SAndroid Build Coastguard Worker         return -errno;
600*f40fafd4SAndroid Build Coastguard Worker     }
601*f40fafd4SAndroid Build Coastguard Worker     if (TEMP_FAILURE_RETRY(mkdir(dir.c_str(), mode)) == -1 && errno != EEXIST) {
602*f40fafd4SAndroid Build Coastguard Worker         PLOG(ERROR) << "Failed to mkdir " << dir;
603*f40fafd4SAndroid Build Coastguard Worker         return -errno;
604*f40fafd4SAndroid Build Coastguard Worker     }
605*f40fafd4SAndroid Build Coastguard Worker     return OK;
606*f40fafd4SAndroid Build Coastguard Worker }
607*f40fafd4SAndroid Build Coastguard Worker 
FindValue(const std::string & raw,const std::string & key,std::string * value)608*f40fafd4SAndroid Build Coastguard Worker bool FindValue(const std::string& raw, const std::string& key, std::string* value) {
609*f40fafd4SAndroid Build Coastguard Worker     auto qual = key + "=\"";
610*f40fafd4SAndroid Build Coastguard Worker     size_t start = 0;
611*f40fafd4SAndroid Build Coastguard Worker     while (true) {
612*f40fafd4SAndroid Build Coastguard Worker         start = raw.find(qual, start);
613*f40fafd4SAndroid Build Coastguard Worker         if (start == std::string::npos) return false;
614*f40fafd4SAndroid Build Coastguard Worker         if (start == 0 || raw[start - 1] == ' ') {
615*f40fafd4SAndroid Build Coastguard Worker             break;
616*f40fafd4SAndroid Build Coastguard Worker         }
617*f40fafd4SAndroid Build Coastguard Worker         start += 1;
618*f40fafd4SAndroid Build Coastguard Worker     }
619*f40fafd4SAndroid Build Coastguard Worker     start += qual.length();
620*f40fafd4SAndroid Build Coastguard Worker 
621*f40fafd4SAndroid Build Coastguard Worker     auto end = raw.find("\"", start);
622*f40fafd4SAndroid Build Coastguard Worker     if (end == std::string::npos) return false;
623*f40fafd4SAndroid Build Coastguard Worker 
624*f40fafd4SAndroid Build Coastguard Worker     *value = raw.substr(start, end - start);
625*f40fafd4SAndroid Build Coastguard Worker     return true;
626*f40fafd4SAndroid Build Coastguard Worker }
627*f40fafd4SAndroid Build Coastguard Worker 
readMetadata(const std::string & path,std::string * fsType,std::string * fsUuid,std::string * fsLabel,bool untrusted)628*f40fafd4SAndroid Build Coastguard Worker static status_t readMetadata(const std::string& path, std::string* fsType, std::string* fsUuid,
629*f40fafd4SAndroid Build Coastguard Worker                              std::string* fsLabel, bool untrusted) {
630*f40fafd4SAndroid Build Coastguard Worker     fsType->clear();
631*f40fafd4SAndroid Build Coastguard Worker     fsUuid->clear();
632*f40fafd4SAndroid Build Coastguard Worker     fsLabel->clear();
633*f40fafd4SAndroid Build Coastguard Worker 
634*f40fafd4SAndroid Build Coastguard Worker     std::vector<std::string> cmd;
635*f40fafd4SAndroid Build Coastguard Worker     cmd.push_back(kBlkidPath);
636*f40fafd4SAndroid Build Coastguard Worker     cmd.push_back("-c");
637*f40fafd4SAndroid Build Coastguard Worker     cmd.push_back("/dev/null");
638*f40fafd4SAndroid Build Coastguard Worker     cmd.push_back("-s");
639*f40fafd4SAndroid Build Coastguard Worker     cmd.push_back("TYPE");
640*f40fafd4SAndroid Build Coastguard Worker     cmd.push_back("-s");
641*f40fafd4SAndroid Build Coastguard Worker     cmd.push_back("UUID");
642*f40fafd4SAndroid Build Coastguard Worker     cmd.push_back("-s");
643*f40fafd4SAndroid Build Coastguard Worker     cmd.push_back("LABEL");
644*f40fafd4SAndroid Build Coastguard Worker     cmd.push_back(path);
645*f40fafd4SAndroid Build Coastguard Worker 
646*f40fafd4SAndroid Build Coastguard Worker     std::vector<std::string> output;
647*f40fafd4SAndroid Build Coastguard Worker     status_t res = ForkExecvp(cmd, &output, untrusted ? sBlkidUntrustedContext : sBlkidContext);
648*f40fafd4SAndroid Build Coastguard Worker     if (res != OK) {
649*f40fafd4SAndroid Build Coastguard Worker         LOG(WARNING) << "blkid failed to identify " << path;
650*f40fafd4SAndroid Build Coastguard Worker         return res;
651*f40fafd4SAndroid Build Coastguard Worker     }
652*f40fafd4SAndroid Build Coastguard Worker 
653*f40fafd4SAndroid Build Coastguard Worker     for (const auto& line : output) {
654*f40fafd4SAndroid Build Coastguard Worker         // Extract values from blkid output, if defined
655*f40fafd4SAndroid Build Coastguard Worker         FindValue(line, "TYPE", fsType);
656*f40fafd4SAndroid Build Coastguard Worker         FindValue(line, "UUID", fsUuid);
657*f40fafd4SAndroid Build Coastguard Worker         FindValue(line, "LABEL", fsLabel);
658*f40fafd4SAndroid Build Coastguard Worker     }
659*f40fafd4SAndroid Build Coastguard Worker 
660*f40fafd4SAndroid Build Coastguard Worker     return OK;
661*f40fafd4SAndroid Build Coastguard Worker }
662*f40fafd4SAndroid Build Coastguard Worker 
ReadMetadata(const std::string & path,std::string * fsType,std::string * fsUuid,std::string * fsLabel)663*f40fafd4SAndroid Build Coastguard Worker status_t ReadMetadata(const std::string& path, std::string* fsType, std::string* fsUuid,
664*f40fafd4SAndroid Build Coastguard Worker                       std::string* fsLabel) {
665*f40fafd4SAndroid Build Coastguard Worker     return readMetadata(path, fsType, fsUuid, fsLabel, false);
666*f40fafd4SAndroid Build Coastguard Worker }
667*f40fafd4SAndroid Build Coastguard Worker 
ReadMetadataUntrusted(const std::string & path,std::string * fsType,std::string * fsUuid,std::string * fsLabel)668*f40fafd4SAndroid Build Coastguard Worker status_t ReadMetadataUntrusted(const std::string& path, std::string* fsType, std::string* fsUuid,
669*f40fafd4SAndroid Build Coastguard Worker                                std::string* fsLabel) {
670*f40fafd4SAndroid Build Coastguard Worker     return readMetadata(path, fsType, fsUuid, fsLabel, true);
671*f40fafd4SAndroid Build Coastguard Worker }
672*f40fafd4SAndroid Build Coastguard Worker 
ConvertToArgv(const std::vector<std::string> & args)673*f40fafd4SAndroid Build Coastguard Worker static std::vector<const char*> ConvertToArgv(const std::vector<std::string>& args) {
674*f40fafd4SAndroid Build Coastguard Worker     std::vector<const char*> argv;
675*f40fafd4SAndroid Build Coastguard Worker     argv.reserve(args.size() + 1);
676*f40fafd4SAndroid Build Coastguard Worker     for (const auto& arg : args) {
677*f40fafd4SAndroid Build Coastguard Worker         if (argv.empty()) {
678*f40fafd4SAndroid Build Coastguard Worker             LOG(DEBUG) << arg;
679*f40fafd4SAndroid Build Coastguard Worker         } else {
680*f40fafd4SAndroid Build Coastguard Worker             LOG(DEBUG) << "    " << arg;
681*f40fafd4SAndroid Build Coastguard Worker         }
682*f40fafd4SAndroid Build Coastguard Worker         argv.emplace_back(arg.data());
683*f40fafd4SAndroid Build Coastguard Worker     }
684*f40fafd4SAndroid Build Coastguard Worker     argv.emplace_back(nullptr);
685*f40fafd4SAndroid Build Coastguard Worker     return argv;
686*f40fafd4SAndroid Build Coastguard Worker }
687*f40fafd4SAndroid Build Coastguard Worker 
ReadLinesFromFdAndLog(std::vector<std::string> * output,android::base::unique_fd ufd)688*f40fafd4SAndroid Build Coastguard Worker static status_t ReadLinesFromFdAndLog(std::vector<std::string>* output,
689*f40fafd4SAndroid Build Coastguard Worker                                       android::base::unique_fd ufd) {
690*f40fafd4SAndroid Build Coastguard Worker     std::unique_ptr<FILE, int (*)(FILE*)> fp(android::base::Fdopen(std::move(ufd), "r"), fclose);
691*f40fafd4SAndroid Build Coastguard Worker     if (!fp) {
692*f40fafd4SAndroid Build Coastguard Worker         PLOG(ERROR) << "fdopen in ReadLinesFromFdAndLog";
693*f40fafd4SAndroid Build Coastguard Worker         return -errno;
694*f40fafd4SAndroid Build Coastguard Worker     }
695*f40fafd4SAndroid Build Coastguard Worker     if (output) output->clear();
696*f40fafd4SAndroid Build Coastguard Worker     char line[1024];
697*f40fafd4SAndroid Build Coastguard Worker     while (fgets(line, sizeof(line), fp.get()) != nullptr) {
698*f40fafd4SAndroid Build Coastguard Worker         LOG(DEBUG) << line;
699*f40fafd4SAndroid Build Coastguard Worker         if (output) output->emplace_back(line);
700*f40fafd4SAndroid Build Coastguard Worker     }
701*f40fafd4SAndroid Build Coastguard Worker     return OK;
702*f40fafd4SAndroid Build Coastguard Worker }
703*f40fafd4SAndroid Build Coastguard Worker 
ForkExecvp(const std::vector<std::string> & args,std::vector<std::string> * output,char * context)704*f40fafd4SAndroid Build Coastguard Worker status_t ForkExecvp(const std::vector<std::string>& args, std::vector<std::string>* output,
705*f40fafd4SAndroid Build Coastguard Worker                     char* context) {
706*f40fafd4SAndroid Build Coastguard Worker     auto argv = ConvertToArgv(args);
707*f40fafd4SAndroid Build Coastguard Worker 
708*f40fafd4SAndroid Build Coastguard Worker     android::base::unique_fd pipe_read, pipe_write;
709*f40fafd4SAndroid Build Coastguard Worker     if (!android::base::Pipe(&pipe_read, &pipe_write)) {
710*f40fafd4SAndroid Build Coastguard Worker         PLOG(ERROR) << "Pipe in ForkExecvp";
711*f40fafd4SAndroid Build Coastguard Worker         return -errno;
712*f40fafd4SAndroid Build Coastguard Worker     }
713*f40fafd4SAndroid Build Coastguard Worker 
714*f40fafd4SAndroid Build Coastguard Worker     pid_t pid = fork();
715*f40fafd4SAndroid Build Coastguard Worker     if (pid == 0) {
716*f40fafd4SAndroid Build Coastguard Worker         if (context) {
717*f40fafd4SAndroid Build Coastguard Worker             if (setexeccon(context)) {
718*f40fafd4SAndroid Build Coastguard Worker                 LOG(ERROR) << "Failed to setexeccon in ForkExecvp";
719*f40fafd4SAndroid Build Coastguard Worker                 abort();
720*f40fafd4SAndroid Build Coastguard Worker             }
721*f40fafd4SAndroid Build Coastguard Worker         }
722*f40fafd4SAndroid Build Coastguard Worker         pipe_read.reset();
723*f40fafd4SAndroid Build Coastguard Worker         if (dup2(pipe_write.get(), STDOUT_FILENO) == -1) {
724*f40fafd4SAndroid Build Coastguard Worker             PLOG(ERROR) << "dup2 in ForkExecvp";
725*f40fafd4SAndroid Build Coastguard Worker             _exit(EXIT_FAILURE);
726*f40fafd4SAndroid Build Coastguard Worker         }
727*f40fafd4SAndroid Build Coastguard Worker         pipe_write.reset();
728*f40fafd4SAndroid Build Coastguard Worker         execvp(argv[0], const_cast<char**>(argv.data()));
729*f40fafd4SAndroid Build Coastguard Worker         PLOG(ERROR) << "exec in ForkExecvp";
730*f40fafd4SAndroid Build Coastguard Worker         _exit(EXIT_FAILURE);
731*f40fafd4SAndroid Build Coastguard Worker     }
732*f40fafd4SAndroid Build Coastguard Worker     if (pid == -1) {
733*f40fafd4SAndroid Build Coastguard Worker         PLOG(ERROR) << "fork in ForkExecvp";
734*f40fafd4SAndroid Build Coastguard Worker         return -errno;
735*f40fafd4SAndroid Build Coastguard Worker     }
736*f40fafd4SAndroid Build Coastguard Worker 
737*f40fafd4SAndroid Build Coastguard Worker     pipe_write.reset();
738*f40fafd4SAndroid Build Coastguard Worker     auto st = ReadLinesFromFdAndLog(output, std::move(pipe_read));
739*f40fafd4SAndroid Build Coastguard Worker     if (st != 0) return st;
740*f40fafd4SAndroid Build Coastguard Worker 
741*f40fafd4SAndroid Build Coastguard Worker     int status;
742*f40fafd4SAndroid Build Coastguard Worker     if (waitpid(pid, &status, 0) == -1) {
743*f40fafd4SAndroid Build Coastguard Worker         PLOG(ERROR) << "waitpid in ForkExecvp";
744*f40fafd4SAndroid Build Coastguard Worker         return -errno;
745*f40fafd4SAndroid Build Coastguard Worker     }
746*f40fafd4SAndroid Build Coastguard Worker     if (!WIFEXITED(status)) {
747*f40fafd4SAndroid Build Coastguard Worker         LOG(ERROR) << "Process did not exit normally, status: " << status;
748*f40fafd4SAndroid Build Coastguard Worker         return -ECHILD;
749*f40fafd4SAndroid Build Coastguard Worker     }
750*f40fafd4SAndroid Build Coastguard Worker     if (WEXITSTATUS(status)) {
751*f40fafd4SAndroid Build Coastguard Worker         LOG(ERROR) << "Process exited with code: " << WEXITSTATUS(status);
752*f40fafd4SAndroid Build Coastguard Worker         return WEXITSTATUS(status);
753*f40fafd4SAndroid Build Coastguard Worker     }
754*f40fafd4SAndroid Build Coastguard Worker     return OK;
755*f40fafd4SAndroid Build Coastguard Worker }
756*f40fafd4SAndroid Build Coastguard Worker 
ForkTimeout(int (* func)(void *),void * args,std::chrono::seconds timeout)757*f40fafd4SAndroid Build Coastguard Worker status_t ForkTimeout(int (*func)(void*), void* args, std::chrono::seconds timeout) {
758*f40fafd4SAndroid Build Coastguard Worker     int status;
759*f40fafd4SAndroid Build Coastguard Worker 
760*f40fafd4SAndroid Build Coastguard Worker     // We're waiting on either the timeout or workload process to finish, so we're
761*f40fafd4SAndroid Build Coastguard Worker     // initially forking to get away from any other vold children
762*f40fafd4SAndroid Build Coastguard Worker     pid_t wait_timeout_pid = fork();
763*f40fafd4SAndroid Build Coastguard Worker     if (wait_timeout_pid == 0) {
764*f40fafd4SAndroid Build Coastguard Worker         pid_t pid = fork();
765*f40fafd4SAndroid Build Coastguard Worker         if (pid == 0) {
766*f40fafd4SAndroid Build Coastguard Worker             _exit(func(args));
767*f40fafd4SAndroid Build Coastguard Worker         }
768*f40fafd4SAndroid Build Coastguard Worker         if (pid == -1) {
769*f40fafd4SAndroid Build Coastguard Worker             _exit(EXIT_FAILURE);
770*f40fafd4SAndroid Build Coastguard Worker         }
771*f40fafd4SAndroid Build Coastguard Worker         pid_t timer_pid = fork();
772*f40fafd4SAndroid Build Coastguard Worker         if (timer_pid == 0) {
773*f40fafd4SAndroid Build Coastguard Worker             std::this_thread::sleep_for(timeout);
774*f40fafd4SAndroid Build Coastguard Worker             _exit(ETIMEDOUT);
775*f40fafd4SAndroid Build Coastguard Worker         }
776*f40fafd4SAndroid Build Coastguard Worker         if (timer_pid == -1) {
777*f40fafd4SAndroid Build Coastguard Worker             PLOG(ERROR) << "fork in ForkTimeout failed";
778*f40fafd4SAndroid Build Coastguard Worker             kill(pid, SIGTERM);
779*f40fafd4SAndroid Build Coastguard Worker             _exit(EXIT_FAILURE);
780*f40fafd4SAndroid Build Coastguard Worker         }
781*f40fafd4SAndroid Build Coastguard Worker         // Preserve the exit code of the first process to finish, and end the other
782*f40fafd4SAndroid Build Coastguard Worker         pid_t finished = wait(&status);
783*f40fafd4SAndroid Build Coastguard Worker         if (finished == pid) {
784*f40fafd4SAndroid Build Coastguard Worker             kill(timer_pid, SIGTERM);
785*f40fafd4SAndroid Build Coastguard Worker         } else {
786*f40fafd4SAndroid Build Coastguard Worker             kill(pid, SIGTERM);
787*f40fafd4SAndroid Build Coastguard Worker         }
788*f40fafd4SAndroid Build Coastguard Worker         if (!WIFEXITED(status)) {
789*f40fafd4SAndroid Build Coastguard Worker             _exit(ECHILD);
790*f40fafd4SAndroid Build Coastguard Worker         }
791*f40fafd4SAndroid Build Coastguard Worker         _exit(WEXITSTATUS(status));
792*f40fafd4SAndroid Build Coastguard Worker     }
793*f40fafd4SAndroid Build Coastguard Worker     if (waitpid(wait_timeout_pid, &status, 0) == -1) {
794*f40fafd4SAndroid Build Coastguard Worker         PLOG(ERROR) << "waitpid in ForkTimeout failed";
795*f40fafd4SAndroid Build Coastguard Worker         return -errno;
796*f40fafd4SAndroid Build Coastguard Worker     }
797*f40fafd4SAndroid Build Coastguard Worker     if (!WIFEXITED(status)) {
798*f40fafd4SAndroid Build Coastguard Worker         LOG(ERROR) << "Process did not exit normally, status: " << status;
799*f40fafd4SAndroid Build Coastguard Worker         return -ECHILD;
800*f40fafd4SAndroid Build Coastguard Worker     }
801*f40fafd4SAndroid Build Coastguard Worker     if (WEXITSTATUS(status)) {
802*f40fafd4SAndroid Build Coastguard Worker         LOG(ERROR) << "Process exited with code: " << WEXITSTATUS(status);
803*f40fafd4SAndroid Build Coastguard Worker         return WEXITSTATUS(status);
804*f40fafd4SAndroid Build Coastguard Worker     }
805*f40fafd4SAndroid Build Coastguard Worker     return OK;
806*f40fafd4SAndroid Build Coastguard Worker }
807*f40fafd4SAndroid Build Coastguard Worker 
ForkExecvpTimeout(const std::vector<std::string> & args,std::chrono::seconds timeout,char * context)808*f40fafd4SAndroid Build Coastguard Worker status_t ForkExecvpTimeout(const std::vector<std::string>& args, std::chrono::seconds timeout,
809*f40fafd4SAndroid Build Coastguard Worker                            char* context) {
810*f40fafd4SAndroid Build Coastguard Worker     int status;
811*f40fafd4SAndroid Build Coastguard Worker 
812*f40fafd4SAndroid Build Coastguard Worker     pid_t wait_timeout_pid = fork();
813*f40fafd4SAndroid Build Coastguard Worker     if (wait_timeout_pid == 0) {
814*f40fafd4SAndroid Build Coastguard Worker         pid_t pid = ForkExecvpAsync(args, context);
815*f40fafd4SAndroid Build Coastguard Worker         if (pid == -1) {
816*f40fafd4SAndroid Build Coastguard Worker             _exit(EXIT_FAILURE);
817*f40fafd4SAndroid Build Coastguard Worker         }
818*f40fafd4SAndroid Build Coastguard Worker         pid_t timer_pid = fork();
819*f40fafd4SAndroid Build Coastguard Worker         if (timer_pid == 0) {
820*f40fafd4SAndroid Build Coastguard Worker             std::this_thread::sleep_for(timeout);
821*f40fafd4SAndroid Build Coastguard Worker             _exit(ETIMEDOUT);
822*f40fafd4SAndroid Build Coastguard Worker         }
823*f40fafd4SAndroid Build Coastguard Worker         if (timer_pid == -1) {
824*f40fafd4SAndroid Build Coastguard Worker             PLOG(ERROR) << "fork in ForkExecvpAsync_timeout";
825*f40fafd4SAndroid Build Coastguard Worker             kill(pid, SIGTERM);
826*f40fafd4SAndroid Build Coastguard Worker             _exit(EXIT_FAILURE);
827*f40fafd4SAndroid Build Coastguard Worker         }
828*f40fafd4SAndroid Build Coastguard Worker         pid_t finished = wait(&status);
829*f40fafd4SAndroid Build Coastguard Worker         if (finished == pid) {
830*f40fafd4SAndroid Build Coastguard Worker             kill(timer_pid, SIGTERM);
831*f40fafd4SAndroid Build Coastguard Worker         } else {
832*f40fafd4SAndroid Build Coastguard Worker             kill(pid, SIGTERM);
833*f40fafd4SAndroid Build Coastguard Worker         }
834*f40fafd4SAndroid Build Coastguard Worker         if (!WIFEXITED(status)) {
835*f40fafd4SAndroid Build Coastguard Worker             _exit(ECHILD);
836*f40fafd4SAndroid Build Coastguard Worker         }
837*f40fafd4SAndroid Build Coastguard Worker         _exit(WEXITSTATUS(status));
838*f40fafd4SAndroid Build Coastguard Worker     }
839*f40fafd4SAndroid Build Coastguard Worker     if (waitpid(wait_timeout_pid, &status, 0) == -1) {
840*f40fafd4SAndroid Build Coastguard Worker         PLOG(ERROR) << "waitpid in ForkExecvpAsync_timeout";
841*f40fafd4SAndroid Build Coastguard Worker         return -errno;
842*f40fafd4SAndroid Build Coastguard Worker     }
843*f40fafd4SAndroid Build Coastguard Worker     if (!WIFEXITED(status)) {
844*f40fafd4SAndroid Build Coastguard Worker         LOG(ERROR) << "Process did not exit normally, status: " << status;
845*f40fafd4SAndroid Build Coastguard Worker         return -ECHILD;
846*f40fafd4SAndroid Build Coastguard Worker     }
847*f40fafd4SAndroid Build Coastguard Worker     if (WEXITSTATUS(status)) {
848*f40fafd4SAndroid Build Coastguard Worker         LOG(ERROR) << "Process exited with code: " << WEXITSTATUS(status);
849*f40fafd4SAndroid Build Coastguard Worker         return WEXITSTATUS(status);
850*f40fafd4SAndroid Build Coastguard Worker     }
851*f40fafd4SAndroid Build Coastguard Worker     return OK;
852*f40fafd4SAndroid Build Coastguard Worker }
853*f40fafd4SAndroid Build Coastguard Worker 
ForkExecvpAsync(const std::vector<std::string> & args,char * context)854*f40fafd4SAndroid Build Coastguard Worker pid_t ForkExecvpAsync(const std::vector<std::string>& args, char* context) {
855*f40fafd4SAndroid Build Coastguard Worker     auto argv = ConvertToArgv(args);
856*f40fafd4SAndroid Build Coastguard Worker 
857*f40fafd4SAndroid Build Coastguard Worker     pid_t pid = fork();
858*f40fafd4SAndroid Build Coastguard Worker     if (pid == 0) {
859*f40fafd4SAndroid Build Coastguard Worker         close(STDIN_FILENO);
860*f40fafd4SAndroid Build Coastguard Worker         close(STDOUT_FILENO);
861*f40fafd4SAndroid Build Coastguard Worker         close(STDERR_FILENO);
862*f40fafd4SAndroid Build Coastguard Worker         if (context) {
863*f40fafd4SAndroid Build Coastguard Worker             if (setexeccon(context)) {
864*f40fafd4SAndroid Build Coastguard Worker                 LOG(ERROR) << "Failed to setexeccon in ForkExecvpAsync";
865*f40fafd4SAndroid Build Coastguard Worker                 abort();
866*f40fafd4SAndroid Build Coastguard Worker             }
867*f40fafd4SAndroid Build Coastguard Worker         }
868*f40fafd4SAndroid Build Coastguard Worker 
869*f40fafd4SAndroid Build Coastguard Worker         execvp(argv[0], const_cast<char**>(argv.data()));
870*f40fafd4SAndroid Build Coastguard Worker         PLOG(ERROR) << "exec in ForkExecvpAsync";
871*f40fafd4SAndroid Build Coastguard Worker         _exit(EXIT_FAILURE);
872*f40fafd4SAndroid Build Coastguard Worker     }
873*f40fafd4SAndroid Build Coastguard Worker     if (pid == -1) {
874*f40fafd4SAndroid Build Coastguard Worker         PLOG(ERROR) << "fork in ForkExecvpAsync";
875*f40fafd4SAndroid Build Coastguard Worker         return -1;
876*f40fafd4SAndroid Build Coastguard Worker     }
877*f40fafd4SAndroid Build Coastguard Worker     return pid;
878*f40fafd4SAndroid Build Coastguard Worker }
879*f40fafd4SAndroid Build Coastguard Worker 
ReadRandomBytes(size_t bytes,std::string & out)880*f40fafd4SAndroid Build Coastguard Worker status_t ReadRandomBytes(size_t bytes, std::string& out) {
881*f40fafd4SAndroid Build Coastguard Worker     out.resize(bytes);
882*f40fafd4SAndroid Build Coastguard Worker     return ReadRandomBytes(bytes, &out[0]);
883*f40fafd4SAndroid Build Coastguard Worker }
884*f40fafd4SAndroid Build Coastguard Worker 
ReadRandomBytes(size_t bytes,char * buf)885*f40fafd4SAndroid Build Coastguard Worker status_t ReadRandomBytes(size_t bytes, char* buf) {
886*f40fafd4SAndroid Build Coastguard Worker     int fd = TEMP_FAILURE_RETRY(open("/dev/urandom", O_RDONLY | O_CLOEXEC | O_NOFOLLOW));
887*f40fafd4SAndroid Build Coastguard Worker     if (fd == -1) {
888*f40fafd4SAndroid Build Coastguard Worker         return -errno;
889*f40fafd4SAndroid Build Coastguard Worker     }
890*f40fafd4SAndroid Build Coastguard Worker 
891*f40fafd4SAndroid Build Coastguard Worker     ssize_t n;
892*f40fafd4SAndroid Build Coastguard Worker     while ((n = TEMP_FAILURE_RETRY(read(fd, &buf[0], bytes))) > 0) {
893*f40fafd4SAndroid Build Coastguard Worker         bytes -= n;
894*f40fafd4SAndroid Build Coastguard Worker         buf += n;
895*f40fafd4SAndroid Build Coastguard Worker     }
896*f40fafd4SAndroid Build Coastguard Worker     close(fd);
897*f40fafd4SAndroid Build Coastguard Worker 
898*f40fafd4SAndroid Build Coastguard Worker     if (bytes == 0) {
899*f40fafd4SAndroid Build Coastguard Worker         return OK;
900*f40fafd4SAndroid Build Coastguard Worker     } else {
901*f40fafd4SAndroid Build Coastguard Worker         return -EIO;
902*f40fafd4SAndroid Build Coastguard Worker     }
903*f40fafd4SAndroid Build Coastguard Worker }
904*f40fafd4SAndroid Build Coastguard Worker 
GenerateRandomUuid(std::string & out)905*f40fafd4SAndroid Build Coastguard Worker status_t GenerateRandomUuid(std::string& out) {
906*f40fafd4SAndroid Build Coastguard Worker     status_t res = ReadRandomBytes(16, out);
907*f40fafd4SAndroid Build Coastguard Worker     if (res == OK) {
908*f40fafd4SAndroid Build Coastguard Worker         out[6] &= 0x0f; /* clear version        */
909*f40fafd4SAndroid Build Coastguard Worker         out[6] |= 0x40; /* set to version 4     */
910*f40fafd4SAndroid Build Coastguard Worker         out[8] &= 0x3f; /* clear variant        */
911*f40fafd4SAndroid Build Coastguard Worker         out[8] |= 0x80; /* set to IETF variant  */
912*f40fafd4SAndroid Build Coastguard Worker     }
913*f40fafd4SAndroid Build Coastguard Worker     return res;
914*f40fafd4SAndroid Build Coastguard Worker }
915*f40fafd4SAndroid Build Coastguard Worker 
HexToStr(const std::string & hex,std::string & str)916*f40fafd4SAndroid Build Coastguard Worker status_t HexToStr(const std::string& hex, std::string& str) {
917*f40fafd4SAndroid Build Coastguard Worker     str.clear();
918*f40fafd4SAndroid Build Coastguard Worker     bool even = true;
919*f40fafd4SAndroid Build Coastguard Worker     char cur = 0;
920*f40fafd4SAndroid Build Coastguard Worker     for (size_t i = 0; i < hex.size(); i++) {
921*f40fafd4SAndroid Build Coastguard Worker         int val = 0;
922*f40fafd4SAndroid Build Coastguard Worker         switch (hex[i]) {
923*f40fafd4SAndroid Build Coastguard Worker             // clang-format off
924*f40fafd4SAndroid Build Coastguard Worker             case ' ': case '-': case ':': continue;
925*f40fafd4SAndroid Build Coastguard Worker             case 'f': case 'F': val = 15; break;
926*f40fafd4SAndroid Build Coastguard Worker             case 'e': case 'E': val = 14; break;
927*f40fafd4SAndroid Build Coastguard Worker             case 'd': case 'D': val = 13; break;
928*f40fafd4SAndroid Build Coastguard Worker             case 'c': case 'C': val = 12; break;
929*f40fafd4SAndroid Build Coastguard Worker             case 'b': case 'B': val = 11; break;
930*f40fafd4SAndroid Build Coastguard Worker             case 'a': case 'A': val = 10; break;
931*f40fafd4SAndroid Build Coastguard Worker             case '9': val = 9; break;
932*f40fafd4SAndroid Build Coastguard Worker             case '8': val = 8; break;
933*f40fafd4SAndroid Build Coastguard Worker             case '7': val = 7; break;
934*f40fafd4SAndroid Build Coastguard Worker             case '6': val = 6; break;
935*f40fafd4SAndroid Build Coastguard Worker             case '5': val = 5; break;
936*f40fafd4SAndroid Build Coastguard Worker             case '4': val = 4; break;
937*f40fafd4SAndroid Build Coastguard Worker             case '3': val = 3; break;
938*f40fafd4SAndroid Build Coastguard Worker             case '2': val = 2; break;
939*f40fafd4SAndroid Build Coastguard Worker             case '1': val = 1; break;
940*f40fafd4SAndroid Build Coastguard Worker             case '0': val = 0; break;
941*f40fafd4SAndroid Build Coastguard Worker             default: return -EINVAL;
942*f40fafd4SAndroid Build Coastguard Worker                 // clang-format on
943*f40fafd4SAndroid Build Coastguard Worker         }
944*f40fafd4SAndroid Build Coastguard Worker 
945*f40fafd4SAndroid Build Coastguard Worker         if (even) {
946*f40fafd4SAndroid Build Coastguard Worker             cur = val << 4;
947*f40fafd4SAndroid Build Coastguard Worker         } else {
948*f40fafd4SAndroid Build Coastguard Worker             cur += val;
949*f40fafd4SAndroid Build Coastguard Worker             str.push_back(cur);
950*f40fafd4SAndroid Build Coastguard Worker             cur = 0;
951*f40fafd4SAndroid Build Coastguard Worker         }
952*f40fafd4SAndroid Build Coastguard Worker         even = !even;
953*f40fafd4SAndroid Build Coastguard Worker     }
954*f40fafd4SAndroid Build Coastguard Worker     return even ? OK : -EINVAL;
955*f40fafd4SAndroid Build Coastguard Worker }
956*f40fafd4SAndroid Build Coastguard Worker 
957*f40fafd4SAndroid Build Coastguard Worker static const char* kLookup = "0123456789abcdef";
958*f40fafd4SAndroid Build Coastguard Worker 
StrToHex(const std::string & str,std::string & hex)959*f40fafd4SAndroid Build Coastguard Worker status_t StrToHex(const std::string& str, std::string& hex) {
960*f40fafd4SAndroid Build Coastguard Worker     hex.clear();
961*f40fafd4SAndroid Build Coastguard Worker     for (size_t i = 0; i < str.size(); i++) {
962*f40fafd4SAndroid Build Coastguard Worker         hex.push_back(kLookup[(str[i] & 0xF0) >> 4]);
963*f40fafd4SAndroid Build Coastguard Worker         hex.push_back(kLookup[str[i] & 0x0F]);
964*f40fafd4SAndroid Build Coastguard Worker     }
965*f40fafd4SAndroid Build Coastguard Worker     return OK;
966*f40fafd4SAndroid Build Coastguard Worker }
967*f40fafd4SAndroid Build Coastguard Worker 
StrToHex(const KeyBuffer & str,KeyBuffer & hex)968*f40fafd4SAndroid Build Coastguard Worker status_t StrToHex(const KeyBuffer& str, KeyBuffer& hex) {
969*f40fafd4SAndroid Build Coastguard Worker     hex.clear();
970*f40fafd4SAndroid Build Coastguard Worker     for (size_t i = 0; i < str.size(); i++) {
971*f40fafd4SAndroid Build Coastguard Worker         hex.push_back(kLookup[(str.data()[i] & 0xF0) >> 4]);
972*f40fafd4SAndroid Build Coastguard Worker         hex.push_back(kLookup[str.data()[i] & 0x0F]);
973*f40fafd4SAndroid Build Coastguard Worker     }
974*f40fafd4SAndroid Build Coastguard Worker     return OK;
975*f40fafd4SAndroid Build Coastguard Worker }
976*f40fafd4SAndroid Build Coastguard Worker 
NormalizeHex(const std::string & in,std::string & out)977*f40fafd4SAndroid Build Coastguard Worker status_t NormalizeHex(const std::string& in, std::string& out) {
978*f40fafd4SAndroid Build Coastguard Worker     std::string tmp;
979*f40fafd4SAndroid Build Coastguard Worker     if (HexToStr(in, tmp)) {
980*f40fafd4SAndroid Build Coastguard Worker         return -EINVAL;
981*f40fafd4SAndroid Build Coastguard Worker     }
982*f40fafd4SAndroid Build Coastguard Worker     return StrToHex(tmp, out);
983*f40fafd4SAndroid Build Coastguard Worker }
984*f40fafd4SAndroid Build Coastguard Worker 
GetBlockDevSize(int fd,uint64_t * size)985*f40fafd4SAndroid Build Coastguard Worker status_t GetBlockDevSize(int fd, uint64_t* size) {
986*f40fafd4SAndroid Build Coastguard Worker     if (ioctl(fd, BLKGETSIZE64, size)) {
987*f40fafd4SAndroid Build Coastguard Worker         return -errno;
988*f40fafd4SAndroid Build Coastguard Worker     }
989*f40fafd4SAndroid Build Coastguard Worker 
990*f40fafd4SAndroid Build Coastguard Worker     return OK;
991*f40fafd4SAndroid Build Coastguard Worker }
992*f40fafd4SAndroid Build Coastguard Worker 
GetBlockDevSize(const std::string & path,uint64_t * size)993*f40fafd4SAndroid Build Coastguard Worker status_t GetBlockDevSize(const std::string& path, uint64_t* size) {
994*f40fafd4SAndroid Build Coastguard Worker     int fd = open(path.c_str(), O_RDONLY | O_CLOEXEC);
995*f40fafd4SAndroid Build Coastguard Worker     status_t res = OK;
996*f40fafd4SAndroid Build Coastguard Worker 
997*f40fafd4SAndroid Build Coastguard Worker     if (fd < 0) {
998*f40fafd4SAndroid Build Coastguard Worker         return -errno;
999*f40fafd4SAndroid Build Coastguard Worker     }
1000*f40fafd4SAndroid Build Coastguard Worker 
1001*f40fafd4SAndroid Build Coastguard Worker     res = GetBlockDevSize(fd, size);
1002*f40fafd4SAndroid Build Coastguard Worker 
1003*f40fafd4SAndroid Build Coastguard Worker     close(fd);
1004*f40fafd4SAndroid Build Coastguard Worker 
1005*f40fafd4SAndroid Build Coastguard Worker     return res;
1006*f40fafd4SAndroid Build Coastguard Worker }
1007*f40fafd4SAndroid Build Coastguard Worker 
GetBlockDev512Sectors(const std::string & path,uint64_t * nr_sec)1008*f40fafd4SAndroid Build Coastguard Worker status_t GetBlockDev512Sectors(const std::string& path, uint64_t* nr_sec) {
1009*f40fafd4SAndroid Build Coastguard Worker     uint64_t size;
1010*f40fafd4SAndroid Build Coastguard Worker     status_t res = GetBlockDevSize(path, &size);
1011*f40fafd4SAndroid Build Coastguard Worker 
1012*f40fafd4SAndroid Build Coastguard Worker     if (res != OK) {
1013*f40fafd4SAndroid Build Coastguard Worker         return res;
1014*f40fafd4SAndroid Build Coastguard Worker     }
1015*f40fafd4SAndroid Build Coastguard Worker 
1016*f40fafd4SAndroid Build Coastguard Worker     *nr_sec = size / 512;
1017*f40fafd4SAndroid Build Coastguard Worker 
1018*f40fafd4SAndroid Build Coastguard Worker     return OK;
1019*f40fafd4SAndroid Build Coastguard Worker }
1020*f40fafd4SAndroid Build Coastguard Worker 
GetFreeBytes(const std::string & path)1021*f40fafd4SAndroid Build Coastguard Worker uint64_t GetFreeBytes(const std::string& path) {
1022*f40fafd4SAndroid Build Coastguard Worker     struct statvfs sb;
1023*f40fafd4SAndroid Build Coastguard Worker     if (statvfs(path.c_str(), &sb) == 0) {
1024*f40fafd4SAndroid Build Coastguard Worker         return (uint64_t)sb.f_bavail * sb.f_frsize;
1025*f40fafd4SAndroid Build Coastguard Worker     } else {
1026*f40fafd4SAndroid Build Coastguard Worker         return -1;
1027*f40fafd4SAndroid Build Coastguard Worker     }
1028*f40fafd4SAndroid Build Coastguard Worker }
1029*f40fafd4SAndroid Build Coastguard Worker 
1030*f40fafd4SAndroid Build Coastguard Worker // TODO: borrowed from frameworks/native/libs/diskusage/ which should
1031*f40fafd4SAndroid Build Coastguard Worker // eventually be migrated into system/
stat_size(struct stat * s)1032*f40fafd4SAndroid Build Coastguard Worker static int64_t stat_size(struct stat* s) {
1033*f40fafd4SAndroid Build Coastguard Worker     int64_t blksize = s->st_blksize;
1034*f40fafd4SAndroid Build Coastguard Worker     // count actual blocks used instead of nominal file size
1035*f40fafd4SAndroid Build Coastguard Worker     int64_t size = s->st_blocks * 512;
1036*f40fafd4SAndroid Build Coastguard Worker 
1037*f40fafd4SAndroid Build Coastguard Worker     if (blksize) {
1038*f40fafd4SAndroid Build Coastguard Worker         /* round up to filesystem block size */
1039*f40fafd4SAndroid Build Coastguard Worker         size = (size + blksize - 1) & (~(blksize - 1));
1040*f40fafd4SAndroid Build Coastguard Worker     }
1041*f40fafd4SAndroid Build Coastguard Worker 
1042*f40fafd4SAndroid Build Coastguard Worker     return size;
1043*f40fafd4SAndroid Build Coastguard Worker }
1044*f40fafd4SAndroid Build Coastguard Worker 
1045*f40fafd4SAndroid Build Coastguard Worker // TODO: borrowed from frameworks/native/libs/diskusage/ which should
1046*f40fafd4SAndroid Build Coastguard Worker // eventually be migrated into system/
calculate_dir_size(int dfd)1047*f40fafd4SAndroid Build Coastguard Worker int64_t calculate_dir_size(int dfd) {
1048*f40fafd4SAndroid Build Coastguard Worker     int64_t size = 0;
1049*f40fafd4SAndroid Build Coastguard Worker     struct stat s;
1050*f40fafd4SAndroid Build Coastguard Worker     DIR* d;
1051*f40fafd4SAndroid Build Coastguard Worker     struct dirent* de;
1052*f40fafd4SAndroid Build Coastguard Worker 
1053*f40fafd4SAndroid Build Coastguard Worker     d = fdopendir(dfd);
1054*f40fafd4SAndroid Build Coastguard Worker     if (d == NULL) {
1055*f40fafd4SAndroid Build Coastguard Worker         close(dfd);
1056*f40fafd4SAndroid Build Coastguard Worker         return 0;
1057*f40fafd4SAndroid Build Coastguard Worker     }
1058*f40fafd4SAndroid Build Coastguard Worker 
1059*f40fafd4SAndroid Build Coastguard Worker     while ((de = readdir(d))) {
1060*f40fafd4SAndroid Build Coastguard Worker         const char* name = de->d_name;
1061*f40fafd4SAndroid Build Coastguard Worker         if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
1062*f40fafd4SAndroid Build Coastguard Worker             size += stat_size(&s);
1063*f40fafd4SAndroid Build Coastguard Worker         }
1064*f40fafd4SAndroid Build Coastguard Worker         if (de->d_type == DT_DIR) {
1065*f40fafd4SAndroid Build Coastguard Worker             int subfd;
1066*f40fafd4SAndroid Build Coastguard Worker 
1067*f40fafd4SAndroid Build Coastguard Worker             /* always skip "." and ".." */
1068*f40fafd4SAndroid Build Coastguard Worker             if (IsDotOrDotDot(*de)) continue;
1069*f40fafd4SAndroid Build Coastguard Worker 
1070*f40fafd4SAndroid Build Coastguard Worker             subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY | O_CLOEXEC);
1071*f40fafd4SAndroid Build Coastguard Worker             if (subfd >= 0) {
1072*f40fafd4SAndroid Build Coastguard Worker                 size += calculate_dir_size(subfd);
1073*f40fafd4SAndroid Build Coastguard Worker             }
1074*f40fafd4SAndroid Build Coastguard Worker         }
1075*f40fafd4SAndroid Build Coastguard Worker     }
1076*f40fafd4SAndroid Build Coastguard Worker     closedir(d);
1077*f40fafd4SAndroid Build Coastguard Worker     return size;
1078*f40fafd4SAndroid Build Coastguard Worker }
1079*f40fafd4SAndroid Build Coastguard Worker 
GetTreeBytes(const std::string & path)1080*f40fafd4SAndroid Build Coastguard Worker uint64_t GetTreeBytes(const std::string& path) {
1081*f40fafd4SAndroid Build Coastguard Worker     int dirfd = open(path.c_str(), O_RDONLY | O_DIRECTORY | O_CLOEXEC);
1082*f40fafd4SAndroid Build Coastguard Worker     if (dirfd < 0) {
1083*f40fafd4SAndroid Build Coastguard Worker         PLOG(WARNING) << "Failed to open " << path;
1084*f40fafd4SAndroid Build Coastguard Worker         return -1;
1085*f40fafd4SAndroid Build Coastguard Worker     } else {
1086*f40fafd4SAndroid Build Coastguard Worker         return calculate_dir_size(dirfd);
1087*f40fafd4SAndroid Build Coastguard Worker     }
1088*f40fafd4SAndroid Build Coastguard Worker }
1089*f40fafd4SAndroid Build Coastguard Worker 
1090*f40fafd4SAndroid Build Coastguard Worker // TODO: Use a better way to determine if it's media provider app.
IsFuseDaemon(const pid_t pid)1091*f40fafd4SAndroid Build Coastguard Worker bool IsFuseDaemon(const pid_t pid) {
1092*f40fafd4SAndroid Build Coastguard Worker     auto path = StringPrintf("/proc/%d/mounts", pid);
1093*f40fafd4SAndroid Build Coastguard Worker     char* tmp;
1094*f40fafd4SAndroid Build Coastguard Worker     if (lgetfilecon(path.c_str(), &tmp) < 0) {
1095*f40fafd4SAndroid Build Coastguard Worker         return false;
1096*f40fafd4SAndroid Build Coastguard Worker     }
1097*f40fafd4SAndroid Build Coastguard Worker     bool result = android::base::StartsWith(tmp, kMediaProviderAppCtx)
1098*f40fafd4SAndroid Build Coastguard Worker             || android::base::StartsWith(tmp, kMediaProviderCtx);
1099*f40fafd4SAndroid Build Coastguard Worker     freecon(tmp);
1100*f40fafd4SAndroid Build Coastguard Worker     return result;
1101*f40fafd4SAndroid Build Coastguard Worker }
1102*f40fafd4SAndroid Build Coastguard Worker 
IsFilesystemSupported(const std::string & fsType)1103*f40fafd4SAndroid Build Coastguard Worker bool IsFilesystemSupported(const std::string& fsType) {
1104*f40fafd4SAndroid Build Coastguard Worker     std::string supported;
1105*f40fafd4SAndroid Build Coastguard Worker     if (!ReadFileToString(kProcFilesystems, &supported)) {
1106*f40fafd4SAndroid Build Coastguard Worker         PLOG(ERROR) << "Failed to read supported filesystems";
1107*f40fafd4SAndroid Build Coastguard Worker         return false;
1108*f40fafd4SAndroid Build Coastguard Worker     }
1109*f40fafd4SAndroid Build Coastguard Worker     return supported.find(fsType + "\n") != std::string::npos;
1110*f40fafd4SAndroid Build Coastguard Worker }
1111*f40fafd4SAndroid Build Coastguard Worker 
IsSdcardfsUsed()1112*f40fafd4SAndroid Build Coastguard Worker bool IsSdcardfsUsed() {
1113*f40fafd4SAndroid Build Coastguard Worker     return IsFilesystemSupported("sdcardfs") &&
1114*f40fafd4SAndroid Build Coastguard Worker            base::GetBoolProperty(kExternalStorageSdcardfs, true);
1115*f40fafd4SAndroid Build Coastguard Worker }
1116*f40fafd4SAndroid Build Coastguard Worker 
WipeBlockDevice(const std::string & path)1117*f40fafd4SAndroid Build Coastguard Worker status_t WipeBlockDevice(const std::string& path) {
1118*f40fafd4SAndroid Build Coastguard Worker     status_t res = -1;
1119*f40fafd4SAndroid Build Coastguard Worker     const char* c_path = path.c_str();
1120*f40fafd4SAndroid Build Coastguard Worker     uint64_t range[2] = {0, 0};
1121*f40fafd4SAndroid Build Coastguard Worker 
1122*f40fafd4SAndroid Build Coastguard Worker     int fd = TEMP_FAILURE_RETRY(open(c_path, O_RDWR | O_CLOEXEC));
1123*f40fafd4SAndroid Build Coastguard Worker     if (fd == -1) {
1124*f40fafd4SAndroid Build Coastguard Worker         PLOG(ERROR) << "Failed to open " << path;
1125*f40fafd4SAndroid Build Coastguard Worker         goto done;
1126*f40fafd4SAndroid Build Coastguard Worker     }
1127*f40fafd4SAndroid Build Coastguard Worker 
1128*f40fafd4SAndroid Build Coastguard Worker     if (GetBlockDevSize(fd, &range[1]) != OK) {
1129*f40fafd4SAndroid Build Coastguard Worker         PLOG(ERROR) << "Failed to determine size of " << path;
1130*f40fafd4SAndroid Build Coastguard Worker         goto done;
1131*f40fafd4SAndroid Build Coastguard Worker     }
1132*f40fafd4SAndroid Build Coastguard Worker 
1133*f40fafd4SAndroid Build Coastguard Worker     LOG(INFO) << "About to discard " << range[1] << " on " << path;
1134*f40fafd4SAndroid Build Coastguard Worker     if (ioctl(fd, BLKDISCARD, &range) == 0) {
1135*f40fafd4SAndroid Build Coastguard Worker         LOG(INFO) << "Discard success on " << path;
1136*f40fafd4SAndroid Build Coastguard Worker         res = 0;
1137*f40fafd4SAndroid Build Coastguard Worker     } else {
1138*f40fafd4SAndroid Build Coastguard Worker         PLOG(ERROR) << "Discard failure on " << path;
1139*f40fafd4SAndroid Build Coastguard Worker     }
1140*f40fafd4SAndroid Build Coastguard Worker 
1141*f40fafd4SAndroid Build Coastguard Worker done:
1142*f40fafd4SAndroid Build Coastguard Worker     close(fd);
1143*f40fafd4SAndroid Build Coastguard Worker     return res;
1144*f40fafd4SAndroid Build Coastguard Worker }
1145*f40fafd4SAndroid Build Coastguard Worker 
isValidFilename(const std::string & name)1146*f40fafd4SAndroid Build Coastguard Worker static bool isValidFilename(const std::string& name) {
1147*f40fafd4SAndroid Build Coastguard Worker     if (name.empty() || (name == ".") || (name == "..") || (name.find('/') != std::string::npos)) {
1148*f40fafd4SAndroid Build Coastguard Worker         return false;
1149*f40fafd4SAndroid Build Coastguard Worker     } else {
1150*f40fafd4SAndroid Build Coastguard Worker         return true;
1151*f40fafd4SAndroid Build Coastguard Worker     }
1152*f40fafd4SAndroid Build Coastguard Worker }
1153*f40fafd4SAndroid Build Coastguard Worker 
BuildKeyPath(const std::string & partGuid)1154*f40fafd4SAndroid Build Coastguard Worker std::string BuildKeyPath(const std::string& partGuid) {
1155*f40fafd4SAndroid Build Coastguard Worker     return StringPrintf("%s/expand_%s.key", kKeyPath, partGuid.c_str());
1156*f40fafd4SAndroid Build Coastguard Worker }
1157*f40fafd4SAndroid Build Coastguard Worker 
BuildDataSystemLegacyPath(userid_t userId)1158*f40fafd4SAndroid Build Coastguard Worker std::string BuildDataSystemLegacyPath(userid_t userId) {
1159*f40fafd4SAndroid Build Coastguard Worker     return StringPrintf("%s/system/users/%u", BuildDataPath("").c_str(), userId);
1160*f40fafd4SAndroid Build Coastguard Worker }
1161*f40fafd4SAndroid Build Coastguard Worker 
BuildDataSystemCePath(userid_t userId)1162*f40fafd4SAndroid Build Coastguard Worker std::string BuildDataSystemCePath(userid_t userId) {
1163*f40fafd4SAndroid Build Coastguard Worker     return StringPrintf("%s/system_ce/%u", BuildDataPath("").c_str(), userId);
1164*f40fafd4SAndroid Build Coastguard Worker }
1165*f40fafd4SAndroid Build Coastguard Worker 
BuildDataSystemDePath(userid_t userId)1166*f40fafd4SAndroid Build Coastguard Worker std::string BuildDataSystemDePath(userid_t userId) {
1167*f40fafd4SAndroid Build Coastguard Worker     return StringPrintf("%s/system_de/%u", BuildDataPath("").c_str(), userId);
1168*f40fafd4SAndroid Build Coastguard Worker }
1169*f40fafd4SAndroid Build Coastguard Worker 
1170*f40fafd4SAndroid Build Coastguard Worker // Keep in sync with installd (frameworks/native/cmds/installd/utils.h)
BuildDataProfilesDePath(userid_t userId)1171*f40fafd4SAndroid Build Coastguard Worker std::string BuildDataProfilesDePath(userid_t userId) {
1172*f40fafd4SAndroid Build Coastguard Worker     return StringPrintf("%s/misc/profiles/cur/%u", BuildDataPath("").c_str(), userId);
1173*f40fafd4SAndroid Build Coastguard Worker }
1174*f40fafd4SAndroid Build Coastguard Worker 
BuildDataVendorCePath(userid_t userId)1175*f40fafd4SAndroid Build Coastguard Worker std::string BuildDataVendorCePath(userid_t userId) {
1176*f40fafd4SAndroid Build Coastguard Worker     return StringPrintf("%s/vendor_ce/%u", BuildDataPath("").c_str(), userId);
1177*f40fafd4SAndroid Build Coastguard Worker }
1178*f40fafd4SAndroid Build Coastguard Worker 
BuildDataVendorDePath(userid_t userId)1179*f40fafd4SAndroid Build Coastguard Worker std::string BuildDataVendorDePath(userid_t userId) {
1180*f40fafd4SAndroid Build Coastguard Worker     return StringPrintf("%s/vendor_de/%u", BuildDataPath("").c_str(), userId);
1181*f40fafd4SAndroid Build Coastguard Worker }
1182*f40fafd4SAndroid Build Coastguard Worker 
BuildDataPath(const std::string & volumeUuid)1183*f40fafd4SAndroid Build Coastguard Worker std::string BuildDataPath(const std::string& volumeUuid) {
1184*f40fafd4SAndroid Build Coastguard Worker     // TODO: unify with installd path generation logic
1185*f40fafd4SAndroid Build Coastguard Worker     if (volumeUuid.empty()) {
1186*f40fafd4SAndroid Build Coastguard Worker         return "/data";
1187*f40fafd4SAndroid Build Coastguard Worker     } else {
1188*f40fafd4SAndroid Build Coastguard Worker         CHECK(isValidFilename(volumeUuid));
1189*f40fafd4SAndroid Build Coastguard Worker         return StringPrintf("/mnt/expand/%s", volumeUuid.c_str());
1190*f40fafd4SAndroid Build Coastguard Worker     }
1191*f40fafd4SAndroid Build Coastguard Worker }
1192*f40fafd4SAndroid Build Coastguard Worker 
BuildDataMediaCePath(const std::string & volumeUuid,userid_t userId)1193*f40fafd4SAndroid Build Coastguard Worker std::string BuildDataMediaCePath(const std::string& volumeUuid, userid_t userId) {
1194*f40fafd4SAndroid Build Coastguard Worker     // TODO: unify with installd path generation logic
1195*f40fafd4SAndroid Build Coastguard Worker     std::string data(BuildDataPath(volumeUuid));
1196*f40fafd4SAndroid Build Coastguard Worker     return StringPrintf("%s/media/%u", data.c_str(), userId);
1197*f40fafd4SAndroid Build Coastguard Worker }
1198*f40fafd4SAndroid Build Coastguard Worker 
BuildDataMiscCePath(const std::string & volumeUuid,userid_t userId)1199*f40fafd4SAndroid Build Coastguard Worker std::string BuildDataMiscCePath(const std::string& volumeUuid, userid_t userId) {
1200*f40fafd4SAndroid Build Coastguard Worker     return StringPrintf("%s/misc_ce/%u", BuildDataPath(volumeUuid).c_str(), userId);
1201*f40fafd4SAndroid Build Coastguard Worker }
1202*f40fafd4SAndroid Build Coastguard Worker 
BuildDataMiscDePath(const std::string & volumeUuid,userid_t userId)1203*f40fafd4SAndroid Build Coastguard Worker std::string BuildDataMiscDePath(const std::string& volumeUuid, userid_t userId) {
1204*f40fafd4SAndroid Build Coastguard Worker     return StringPrintf("%s/misc_de/%u", BuildDataPath(volumeUuid).c_str(), userId);
1205*f40fafd4SAndroid Build Coastguard Worker }
1206*f40fafd4SAndroid Build Coastguard Worker 
BuildDataUserCePath(const std::string & volumeUuid,userid_t userId)1207*f40fafd4SAndroid Build Coastguard Worker std::string BuildDataUserCePath(const std::string& volumeUuid, userid_t userId) {
1208*f40fafd4SAndroid Build Coastguard Worker     // TODO: unify with installd path generation logic
1209*f40fafd4SAndroid Build Coastguard Worker     std::string data(BuildDataPath(volumeUuid));
1210*f40fafd4SAndroid Build Coastguard Worker     return StringPrintf("%s/user/%u", data.c_str(), userId);
1211*f40fafd4SAndroid Build Coastguard Worker }
1212*f40fafd4SAndroid Build Coastguard Worker 
BuildDataUserDePath(const std::string & volumeUuid,userid_t userId)1213*f40fafd4SAndroid Build Coastguard Worker std::string BuildDataUserDePath(const std::string& volumeUuid, userid_t userId) {
1214*f40fafd4SAndroid Build Coastguard Worker     // TODO: unify with installd path generation logic
1215*f40fafd4SAndroid Build Coastguard Worker     std::string data(BuildDataPath(volumeUuid));
1216*f40fafd4SAndroid Build Coastguard Worker     return StringPrintf("%s/user_de/%u", data.c_str(), userId);
1217*f40fafd4SAndroid Build Coastguard Worker }
1218*f40fafd4SAndroid Build Coastguard Worker 
GetDevice(const std::string & path)1219*f40fafd4SAndroid Build Coastguard Worker dev_t GetDevice(const std::string& path) {
1220*f40fafd4SAndroid Build Coastguard Worker     struct stat sb;
1221*f40fafd4SAndroid Build Coastguard Worker     if (stat(path.c_str(), &sb)) {
1222*f40fafd4SAndroid Build Coastguard Worker         PLOG(WARNING) << "Failed to stat " << path;
1223*f40fafd4SAndroid Build Coastguard Worker         return 0;
1224*f40fafd4SAndroid Build Coastguard Worker     } else {
1225*f40fafd4SAndroid Build Coastguard Worker         return sb.st_dev;
1226*f40fafd4SAndroid Build Coastguard Worker     }
1227*f40fafd4SAndroid Build Coastguard Worker }
1228*f40fafd4SAndroid Build Coastguard Worker 
1229*f40fafd4SAndroid Build Coastguard Worker // Returns true if |path| exists and is a symlink.
IsSymlink(const std::string & path)1230*f40fafd4SAndroid Build Coastguard Worker bool IsSymlink(const std::string& path) {
1231*f40fafd4SAndroid Build Coastguard Worker     struct stat stbuf;
1232*f40fafd4SAndroid Build Coastguard Worker     return lstat(path.c_str(), &stbuf) == 0 && S_ISLNK(stbuf.st_mode);
1233*f40fafd4SAndroid Build Coastguard Worker }
1234*f40fafd4SAndroid Build Coastguard Worker 
1235*f40fafd4SAndroid Build Coastguard Worker // Returns true if |path1| names the same existing file or directory as |path2|.
IsSameFile(const std::string & path1,const std::string & path2)1236*f40fafd4SAndroid Build Coastguard Worker bool IsSameFile(const std::string& path1, const std::string& path2) {
1237*f40fafd4SAndroid Build Coastguard Worker     struct stat stbuf1, stbuf2;
1238*f40fafd4SAndroid Build Coastguard Worker     if (stat(path1.c_str(), &stbuf1) != 0 || stat(path2.c_str(), &stbuf2) != 0) return false;
1239*f40fafd4SAndroid Build Coastguard Worker     return stbuf1.st_ino == stbuf2.st_ino && stbuf1.st_dev == stbuf2.st_dev;
1240*f40fafd4SAndroid Build Coastguard Worker }
1241*f40fafd4SAndroid Build Coastguard Worker 
RestoreconRecursive(const std::string & path)1242*f40fafd4SAndroid Build Coastguard Worker status_t RestoreconRecursive(const std::string& path) {
1243*f40fafd4SAndroid Build Coastguard Worker     LOG(DEBUG) << "Starting restorecon of " << path;
1244*f40fafd4SAndroid Build Coastguard Worker 
1245*f40fafd4SAndroid Build Coastguard Worker     static constexpr const char* kRestoreconString = "selinux.restorecon_recursive";
1246*f40fafd4SAndroid Build Coastguard Worker 
1247*f40fafd4SAndroid Build Coastguard Worker     android::base::SetProperty(kRestoreconString, "");
1248*f40fafd4SAndroid Build Coastguard Worker     android::base::SetProperty(kRestoreconString, path);
1249*f40fafd4SAndroid Build Coastguard Worker 
1250*f40fafd4SAndroid Build Coastguard Worker     android::base::WaitForProperty(kRestoreconString, path);
1251*f40fafd4SAndroid Build Coastguard Worker 
1252*f40fafd4SAndroid Build Coastguard Worker     LOG(DEBUG) << "Finished restorecon of " << path;
1253*f40fafd4SAndroid Build Coastguard Worker     return OK;
1254*f40fafd4SAndroid Build Coastguard Worker }
1255*f40fafd4SAndroid Build Coastguard Worker 
Readlinkat(int dirfd,const std::string & path,std::string * result)1256*f40fafd4SAndroid Build Coastguard Worker bool Readlinkat(int dirfd, const std::string& path, std::string* result) {
1257*f40fafd4SAndroid Build Coastguard Worker     // Shamelessly borrowed from android::base::Readlink()
1258*f40fafd4SAndroid Build Coastguard Worker     result->clear();
1259*f40fafd4SAndroid Build Coastguard Worker 
1260*f40fafd4SAndroid Build Coastguard Worker     // Most Linux file systems (ext2 and ext4, say) limit symbolic links to
1261*f40fafd4SAndroid Build Coastguard Worker     // 4095 bytes. Since we'll copy out into the string anyway, it doesn't
1262*f40fafd4SAndroid Build Coastguard Worker     // waste memory to just start there. We add 1 so that we can recognize
1263*f40fafd4SAndroid Build Coastguard Worker     // whether it actually fit (rather than being truncated to 4095).
1264*f40fafd4SAndroid Build Coastguard Worker     std::vector<char> buf(4095 + 1);
1265*f40fafd4SAndroid Build Coastguard Worker     while (true) {
1266*f40fafd4SAndroid Build Coastguard Worker         ssize_t size = readlinkat(dirfd, path.c_str(), &buf[0], buf.size());
1267*f40fafd4SAndroid Build Coastguard Worker         // Unrecoverable error?
1268*f40fafd4SAndroid Build Coastguard Worker         if (size == -1) return false;
1269*f40fafd4SAndroid Build Coastguard Worker         // It fit! (If size == buf.size(), it may have been truncated.)
1270*f40fafd4SAndroid Build Coastguard Worker         if (static_cast<size_t>(size) < buf.size()) {
1271*f40fafd4SAndroid Build Coastguard Worker             result->assign(&buf[0], size);
1272*f40fafd4SAndroid Build Coastguard Worker             return true;
1273*f40fafd4SAndroid Build Coastguard Worker         }
1274*f40fafd4SAndroid Build Coastguard Worker         // Double our buffer and try again.
1275*f40fafd4SAndroid Build Coastguard Worker         buf.resize(buf.size() * 2);
1276*f40fafd4SAndroid Build Coastguard Worker     }
1277*f40fafd4SAndroid Build Coastguard Worker }
1278*f40fafd4SAndroid Build Coastguard Worker 
GetMajorBlockVirtioBlk()1279*f40fafd4SAndroid Build Coastguard Worker static unsigned int GetMajorBlockVirtioBlk() {
1280*f40fafd4SAndroid Build Coastguard Worker     std::string devices;
1281*f40fafd4SAndroid Build Coastguard Worker     if (!ReadFileToString(kProcDevices, &devices)) {
1282*f40fafd4SAndroid Build Coastguard Worker         PLOG(ERROR) << "Unable to open /proc/devices";
1283*f40fafd4SAndroid Build Coastguard Worker         return 0;
1284*f40fafd4SAndroid Build Coastguard Worker     }
1285*f40fafd4SAndroid Build Coastguard Worker 
1286*f40fafd4SAndroid Build Coastguard Worker     bool blockSection = false;
1287*f40fafd4SAndroid Build Coastguard Worker     for (auto line : android::base::Split(devices, "\n")) {
1288*f40fafd4SAndroid Build Coastguard Worker         if (line == "Block devices:") {
1289*f40fafd4SAndroid Build Coastguard Worker             blockSection = true;
1290*f40fafd4SAndroid Build Coastguard Worker         } else if (line == "Character devices:") {
1291*f40fafd4SAndroid Build Coastguard Worker             blockSection = false;
1292*f40fafd4SAndroid Build Coastguard Worker         } else if (blockSection) {
1293*f40fafd4SAndroid Build Coastguard Worker             auto tokens = android::base::Split(line, " ");
1294*f40fafd4SAndroid Build Coastguard Worker             if (tokens.size() == 2 && tokens[1] == "virtblk") {
1295*f40fafd4SAndroid Build Coastguard Worker                 return std::stoul(tokens[0]);
1296*f40fafd4SAndroid Build Coastguard Worker             }
1297*f40fafd4SAndroid Build Coastguard Worker         }
1298*f40fafd4SAndroid Build Coastguard Worker     }
1299*f40fafd4SAndroid Build Coastguard Worker 
1300*f40fafd4SAndroid Build Coastguard Worker     return 0;
1301*f40fafd4SAndroid Build Coastguard Worker }
1302*f40fafd4SAndroid Build Coastguard Worker 
IsVirtioBlkDevice(unsigned int major)1303*f40fafd4SAndroid Build Coastguard Worker bool IsVirtioBlkDevice(unsigned int major) {
1304*f40fafd4SAndroid Build Coastguard Worker     // Most virtualized platforms expose block devices with the virtio-blk
1305*f40fafd4SAndroid Build Coastguard Worker     // block device driver. Unfortunately, this driver does not use a fixed
1306*f40fafd4SAndroid Build Coastguard Worker     // major number, but relies on the kernel to assign one from a specific
1307*f40fafd4SAndroid Build Coastguard Worker     // range of block majors, which are allocated for "LOCAL/EXPERIMENAL USE"
1308*f40fafd4SAndroid Build Coastguard Worker     // per Documentation/devices.txt. This is true even for the latest Linux
1309*f40fafd4SAndroid Build Coastguard Worker     // kernel (4.4; see init() in drivers/block/virtio_blk.c).
1310*f40fafd4SAndroid Build Coastguard Worker     static unsigned int kMajorBlockVirtioBlk = GetMajorBlockVirtioBlk();
1311*f40fafd4SAndroid Build Coastguard Worker     return kMajorBlockVirtioBlk && major == kMajorBlockVirtioBlk;
1312*f40fafd4SAndroid Build Coastguard Worker }
1313*f40fafd4SAndroid Build Coastguard Worker 
UnmountTree(const std::string & mountPoint)1314*f40fafd4SAndroid Build Coastguard Worker status_t UnmountTree(const std::string& mountPoint) {
1315*f40fafd4SAndroid Build Coastguard Worker     if (TEMP_FAILURE_RETRY(umount2(mountPoint.c_str(), MNT_DETACH)) < 0 && errno != EINVAL &&
1316*f40fafd4SAndroid Build Coastguard Worker         errno != ENOENT) {
1317*f40fafd4SAndroid Build Coastguard Worker         PLOG(ERROR) << "Failed to unmount " << mountPoint;
1318*f40fafd4SAndroid Build Coastguard Worker         return -errno;
1319*f40fafd4SAndroid Build Coastguard Worker     }
1320*f40fafd4SAndroid Build Coastguard Worker     return OK;
1321*f40fafd4SAndroid Build Coastguard Worker }
1322*f40fafd4SAndroid Build Coastguard Worker 
IsDotOrDotDot(const struct dirent & ent)1323*f40fafd4SAndroid Build Coastguard Worker bool IsDotOrDotDot(const struct dirent& ent) {
1324*f40fafd4SAndroid Build Coastguard Worker     return strcmp(ent.d_name, ".") == 0 || strcmp(ent.d_name, "..") == 0;
1325*f40fafd4SAndroid Build Coastguard Worker }
1326*f40fafd4SAndroid Build Coastguard Worker 
delete_dir_contents(DIR * dir)1327*f40fafd4SAndroid Build Coastguard Worker static status_t delete_dir_contents(DIR* dir) {
1328*f40fafd4SAndroid Build Coastguard Worker     // Shamelessly borrowed from android::installd
1329*f40fafd4SAndroid Build Coastguard Worker     int dfd = dirfd(dir);
1330*f40fafd4SAndroid Build Coastguard Worker     if (dfd < 0) {
1331*f40fafd4SAndroid Build Coastguard Worker         return -errno;
1332*f40fafd4SAndroid Build Coastguard Worker     }
1333*f40fafd4SAndroid Build Coastguard Worker 
1334*f40fafd4SAndroid Build Coastguard Worker     status_t result = OK;
1335*f40fafd4SAndroid Build Coastguard Worker     struct dirent* de;
1336*f40fafd4SAndroid Build Coastguard Worker     while ((de = readdir(dir))) {
1337*f40fafd4SAndroid Build Coastguard Worker         const char* name = de->d_name;
1338*f40fafd4SAndroid Build Coastguard Worker         if (de->d_type == DT_DIR) {
1339*f40fafd4SAndroid Build Coastguard Worker             /* always skip "." and ".." */
1340*f40fafd4SAndroid Build Coastguard Worker             if (IsDotOrDotDot(*de)) continue;
1341*f40fafd4SAndroid Build Coastguard Worker 
1342*f40fafd4SAndroid Build Coastguard Worker             android::base::unique_fd subfd(
1343*f40fafd4SAndroid Build Coastguard Worker                 openat(dfd, name, O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC));
1344*f40fafd4SAndroid Build Coastguard Worker             if (subfd.get() == -1) {
1345*f40fafd4SAndroid Build Coastguard Worker                 PLOG(ERROR) << "Couldn't openat " << name;
1346*f40fafd4SAndroid Build Coastguard Worker                 result = -errno;
1347*f40fafd4SAndroid Build Coastguard Worker                 continue;
1348*f40fafd4SAndroid Build Coastguard Worker             }
1349*f40fafd4SAndroid Build Coastguard Worker             std::unique_ptr<DIR, decltype(&closedir)> subdirp(
1350*f40fafd4SAndroid Build Coastguard Worker                 android::base::Fdopendir(std::move(subfd)), closedir);
1351*f40fafd4SAndroid Build Coastguard Worker             if (!subdirp) {
1352*f40fafd4SAndroid Build Coastguard Worker                 PLOG(ERROR) << "Couldn't fdopendir " << name;
1353*f40fafd4SAndroid Build Coastguard Worker                 result = -errno;
1354*f40fafd4SAndroid Build Coastguard Worker                 continue;
1355*f40fafd4SAndroid Build Coastguard Worker             }
1356*f40fafd4SAndroid Build Coastguard Worker             result = delete_dir_contents(subdirp.get());
1357*f40fafd4SAndroid Build Coastguard Worker             if (unlinkat(dfd, name, AT_REMOVEDIR) < 0) {
1358*f40fafd4SAndroid Build Coastguard Worker                 PLOG(ERROR) << "Couldn't unlinkat " << name;
1359*f40fafd4SAndroid Build Coastguard Worker                 result = -errno;
1360*f40fafd4SAndroid Build Coastguard Worker             }
1361*f40fafd4SAndroid Build Coastguard Worker         } else {
1362*f40fafd4SAndroid Build Coastguard Worker             if (unlinkat(dfd, name, 0) < 0) {
1363*f40fafd4SAndroid Build Coastguard Worker                 PLOG(ERROR) << "Couldn't unlinkat " << name;
1364*f40fafd4SAndroid Build Coastguard Worker                 result = -errno;
1365*f40fafd4SAndroid Build Coastguard Worker             }
1366*f40fafd4SAndroid Build Coastguard Worker         }
1367*f40fafd4SAndroid Build Coastguard Worker     }
1368*f40fafd4SAndroid Build Coastguard Worker     return result;
1369*f40fafd4SAndroid Build Coastguard Worker }
1370*f40fafd4SAndroid Build Coastguard Worker 
DeleteDirContentsAndDir(const std::string & pathname)1371*f40fafd4SAndroid Build Coastguard Worker status_t DeleteDirContentsAndDir(const std::string& pathname) {
1372*f40fafd4SAndroid Build Coastguard Worker     status_t res = DeleteDirContents(pathname);
1373*f40fafd4SAndroid Build Coastguard Worker     if (res < 0) {
1374*f40fafd4SAndroid Build Coastguard Worker         return res;
1375*f40fafd4SAndroid Build Coastguard Worker     }
1376*f40fafd4SAndroid Build Coastguard Worker     if (TEMP_FAILURE_RETRY(rmdir(pathname.c_str())) < 0 && errno != ENOENT) {
1377*f40fafd4SAndroid Build Coastguard Worker         PLOG(ERROR) << "rmdir failed on " << pathname;
1378*f40fafd4SAndroid Build Coastguard Worker         return -errno;
1379*f40fafd4SAndroid Build Coastguard Worker     }
1380*f40fafd4SAndroid Build Coastguard Worker     LOG(VERBOSE) << "Success: rmdir on " << pathname;
1381*f40fafd4SAndroid Build Coastguard Worker     return OK;
1382*f40fafd4SAndroid Build Coastguard Worker }
1383*f40fafd4SAndroid Build Coastguard Worker 
DeleteDirContents(const std::string & pathname)1384*f40fafd4SAndroid Build Coastguard Worker status_t DeleteDirContents(const std::string& pathname) {
1385*f40fafd4SAndroid Build Coastguard Worker     // Shamelessly borrowed from android::installd
1386*f40fafd4SAndroid Build Coastguard Worker     std::unique_ptr<DIR, decltype(&closedir)> dirp(opendir(pathname.c_str()), closedir);
1387*f40fafd4SAndroid Build Coastguard Worker     if (!dirp) {
1388*f40fafd4SAndroid Build Coastguard Worker         if (errno == ENOENT) {
1389*f40fafd4SAndroid Build Coastguard Worker             return OK;
1390*f40fafd4SAndroid Build Coastguard Worker         }
1391*f40fafd4SAndroid Build Coastguard Worker         PLOG(ERROR) << "Failed to opendir " << pathname;
1392*f40fafd4SAndroid Build Coastguard Worker         return -errno;
1393*f40fafd4SAndroid Build Coastguard Worker     }
1394*f40fafd4SAndroid Build Coastguard Worker     return delete_dir_contents(dirp.get());
1395*f40fafd4SAndroid Build Coastguard Worker }
1396*f40fafd4SAndroid Build Coastguard Worker 
1397*f40fafd4SAndroid Build Coastguard Worker // TODO(118708649): fix duplication with init/util.h
WaitForFile(const char * filename,std::chrono::nanoseconds timeout)1398*f40fafd4SAndroid Build Coastguard Worker status_t WaitForFile(const char* filename, std::chrono::nanoseconds timeout) {
1399*f40fafd4SAndroid Build Coastguard Worker     android::base::Timer t;
1400*f40fafd4SAndroid Build Coastguard Worker     while (t.duration() < timeout) {
1401*f40fafd4SAndroid Build Coastguard Worker         struct stat sb;
1402*f40fafd4SAndroid Build Coastguard Worker         if (stat(filename, &sb) != -1) {
1403*f40fafd4SAndroid Build Coastguard Worker             LOG(INFO) << "wait for '" << filename << "' took " << t;
1404*f40fafd4SAndroid Build Coastguard Worker             return 0;
1405*f40fafd4SAndroid Build Coastguard Worker         }
1406*f40fafd4SAndroid Build Coastguard Worker         std::this_thread::sleep_for(10ms);
1407*f40fafd4SAndroid Build Coastguard Worker     }
1408*f40fafd4SAndroid Build Coastguard Worker     LOG(WARNING) << "wait for '" << filename << "' timed out and took " << t;
1409*f40fafd4SAndroid Build Coastguard Worker     return -1;
1410*f40fafd4SAndroid Build Coastguard Worker }
1411*f40fafd4SAndroid Build Coastguard Worker 
pathExists(const std::string & path)1412*f40fafd4SAndroid Build Coastguard Worker bool pathExists(const std::string& path) {
1413*f40fafd4SAndroid Build Coastguard Worker     return access(path.c_str(), F_OK) == 0;
1414*f40fafd4SAndroid Build Coastguard Worker }
1415*f40fafd4SAndroid Build Coastguard Worker 
FsyncDirectory(const std::string & dirname)1416*f40fafd4SAndroid Build Coastguard Worker bool FsyncDirectory(const std::string& dirname) {
1417*f40fafd4SAndroid Build Coastguard Worker     android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(dirname.c_str(), O_RDONLY | O_CLOEXEC)));
1418*f40fafd4SAndroid Build Coastguard Worker     if (fd == -1) {
1419*f40fafd4SAndroid Build Coastguard Worker         PLOG(ERROR) << "Failed to open " << dirname;
1420*f40fafd4SAndroid Build Coastguard Worker         return false;
1421*f40fafd4SAndroid Build Coastguard Worker     }
1422*f40fafd4SAndroid Build Coastguard Worker     if (fsync(fd) == -1) {
1423*f40fafd4SAndroid Build Coastguard Worker         if (errno == EROFS || errno == EINVAL) {
1424*f40fafd4SAndroid Build Coastguard Worker             PLOG(WARNING) << "Skip fsync " << dirname
1425*f40fafd4SAndroid Build Coastguard Worker                           << " on a file system does not support synchronization";
1426*f40fafd4SAndroid Build Coastguard Worker         } else {
1427*f40fafd4SAndroid Build Coastguard Worker             PLOG(ERROR) << "Failed to fsync " << dirname;
1428*f40fafd4SAndroid Build Coastguard Worker             return false;
1429*f40fafd4SAndroid Build Coastguard Worker         }
1430*f40fafd4SAndroid Build Coastguard Worker     }
1431*f40fafd4SAndroid Build Coastguard Worker     return true;
1432*f40fafd4SAndroid Build Coastguard Worker }
1433*f40fafd4SAndroid Build Coastguard Worker 
FsyncParentDirectory(const std::string & path)1434*f40fafd4SAndroid Build Coastguard Worker bool FsyncParentDirectory(const std::string& path) {
1435*f40fafd4SAndroid Build Coastguard Worker     return FsyncDirectory(android::base::Dirname(path));
1436*f40fafd4SAndroid Build Coastguard Worker }
1437*f40fafd4SAndroid Build Coastguard Worker 
1438*f40fafd4SAndroid Build Coastguard Worker // Creates all parent directories of |path| that don't already exist.  Assigns
1439*f40fafd4SAndroid Build Coastguard Worker // the specified |mode| to any new directories, and also fsync()s their parent
1440*f40fafd4SAndroid Build Coastguard Worker // directories so that the new directories get written to disk right away.
MkdirsSync(const std::string & path,mode_t mode)1441*f40fafd4SAndroid Build Coastguard Worker bool MkdirsSync(const std::string& path, mode_t mode) {
1442*f40fafd4SAndroid Build Coastguard Worker     if (path[0] != '/') {
1443*f40fafd4SAndroid Build Coastguard Worker         LOG(ERROR) << "MkdirsSync() needs an absolute path, but got " << path;
1444*f40fafd4SAndroid Build Coastguard Worker         return false;
1445*f40fafd4SAndroid Build Coastguard Worker     }
1446*f40fafd4SAndroid Build Coastguard Worker     std::vector<std::string> components = android::base::Split(android::base::Dirname(path), "/");
1447*f40fafd4SAndroid Build Coastguard Worker 
1448*f40fafd4SAndroid Build Coastguard Worker     std::string current_dir = "/";
1449*f40fafd4SAndroid Build Coastguard Worker     for (const std::string& component : components) {
1450*f40fafd4SAndroid Build Coastguard Worker         if (component.empty()) continue;
1451*f40fafd4SAndroid Build Coastguard Worker 
1452*f40fafd4SAndroid Build Coastguard Worker         std::string parent_dir = current_dir;
1453*f40fafd4SAndroid Build Coastguard Worker         if (current_dir != "/") current_dir += "/";
1454*f40fafd4SAndroid Build Coastguard Worker         current_dir += component;
1455*f40fafd4SAndroid Build Coastguard Worker 
1456*f40fafd4SAndroid Build Coastguard Worker         if (!pathExists(current_dir)) {
1457*f40fafd4SAndroid Build Coastguard Worker             if (mkdir(current_dir.c_str(), mode) != 0) {
1458*f40fafd4SAndroid Build Coastguard Worker                 PLOG(ERROR) << "Failed to create " << current_dir;
1459*f40fafd4SAndroid Build Coastguard Worker                 return false;
1460*f40fafd4SAndroid Build Coastguard Worker             }
1461*f40fafd4SAndroid Build Coastguard Worker             if (!FsyncDirectory(parent_dir)) return false;
1462*f40fafd4SAndroid Build Coastguard Worker             LOG(DEBUG) << "Created directory " << current_dir;
1463*f40fafd4SAndroid Build Coastguard Worker         }
1464*f40fafd4SAndroid Build Coastguard Worker     }
1465*f40fafd4SAndroid Build Coastguard Worker     return true;
1466*f40fafd4SAndroid Build Coastguard Worker }
1467*f40fafd4SAndroid Build Coastguard Worker 
writeStringToFile(const std::string & payload,const std::string & filename)1468*f40fafd4SAndroid Build Coastguard Worker bool writeStringToFile(const std::string& payload, const std::string& filename) {
1469*f40fafd4SAndroid Build Coastguard Worker     android::base::unique_fd fd(TEMP_FAILURE_RETRY(
1470*f40fafd4SAndroid Build Coastguard Worker         open(filename.c_str(), O_WRONLY | O_CREAT | O_NOFOLLOW | O_TRUNC | O_CLOEXEC, 0666)));
1471*f40fafd4SAndroid Build Coastguard Worker     if (fd == -1) {
1472*f40fafd4SAndroid Build Coastguard Worker         PLOG(ERROR) << "Failed to open " << filename;
1473*f40fafd4SAndroid Build Coastguard Worker         return false;
1474*f40fafd4SAndroid Build Coastguard Worker     }
1475*f40fafd4SAndroid Build Coastguard Worker     if (!android::base::WriteStringToFd(payload, fd)) {
1476*f40fafd4SAndroid Build Coastguard Worker         PLOG(ERROR) << "Failed to write to " << filename;
1477*f40fafd4SAndroid Build Coastguard Worker         unlink(filename.c_str());
1478*f40fafd4SAndroid Build Coastguard Worker         return false;
1479*f40fafd4SAndroid Build Coastguard Worker     }
1480*f40fafd4SAndroid Build Coastguard Worker     // fsync as close won't guarantee flush data
1481*f40fafd4SAndroid Build Coastguard Worker     // see close(2), fsync(2) and b/68901441
1482*f40fafd4SAndroid Build Coastguard Worker     if (fsync(fd) == -1) {
1483*f40fafd4SAndroid Build Coastguard Worker         if (errno == EROFS || errno == EINVAL) {
1484*f40fafd4SAndroid Build Coastguard Worker             PLOG(WARNING) << "Skip fsync " << filename
1485*f40fafd4SAndroid Build Coastguard Worker                           << " on a file system does not support synchronization";
1486*f40fafd4SAndroid Build Coastguard Worker         } else {
1487*f40fafd4SAndroid Build Coastguard Worker             PLOG(ERROR) << "Failed to fsync " << filename;
1488*f40fafd4SAndroid Build Coastguard Worker             unlink(filename.c_str());
1489*f40fafd4SAndroid Build Coastguard Worker             return false;
1490*f40fafd4SAndroid Build Coastguard Worker         }
1491*f40fafd4SAndroid Build Coastguard Worker     }
1492*f40fafd4SAndroid Build Coastguard Worker     return true;
1493*f40fafd4SAndroid Build Coastguard Worker }
1494*f40fafd4SAndroid Build Coastguard Worker 
AbortFuseConnections()1495*f40fafd4SAndroid Build Coastguard Worker status_t AbortFuseConnections() {
1496*f40fafd4SAndroid Build Coastguard Worker     namespace fs = std::filesystem;
1497*f40fafd4SAndroid Build Coastguard Worker 
1498*f40fafd4SAndroid Build Coastguard Worker     static constexpr const char* kFuseConnections = "/sys/fs/fuse/connections";
1499*f40fafd4SAndroid Build Coastguard Worker 
1500*f40fafd4SAndroid Build Coastguard Worker     std::error_code ec;
1501*f40fafd4SAndroid Build Coastguard Worker     for (const auto& itEntry : fs::directory_iterator(kFuseConnections, ec)) {
1502*f40fafd4SAndroid Build Coastguard Worker         std::string fsPath = itEntry.path().string() + "/filesystem";
1503*f40fafd4SAndroid Build Coastguard Worker         std::string fs;
1504*f40fafd4SAndroid Build Coastguard Worker 
1505*f40fafd4SAndroid Build Coastguard Worker         // Virtiofs is on top of fuse and there isn't any user space daemon.
1506*f40fafd4SAndroid Build Coastguard Worker         // Android user space doesn't manage it.
1507*f40fafd4SAndroid Build Coastguard Worker         if (android::base::ReadFileToString(fsPath, &fs, false) &&
1508*f40fafd4SAndroid Build Coastguard Worker             android::base::Trim(fs) == "virtiofs") {
1509*f40fafd4SAndroid Build Coastguard Worker             LOG(INFO) << "Ignore virtiofs connection entry " << itEntry.path().string();
1510*f40fafd4SAndroid Build Coastguard Worker             continue;
1511*f40fafd4SAndroid Build Coastguard Worker         }
1512*f40fafd4SAndroid Build Coastguard Worker 
1513*f40fafd4SAndroid Build Coastguard Worker         std::string abortPath = itEntry.path().string() + "/abort";
1514*f40fafd4SAndroid Build Coastguard Worker         LOG(DEBUG) << "Aborting fuse connection entry " << abortPath;
1515*f40fafd4SAndroid Build Coastguard Worker         bool ret = writeStringToFile("1", abortPath);
1516*f40fafd4SAndroid Build Coastguard Worker         if (!ret) {
1517*f40fafd4SAndroid Build Coastguard Worker             LOG(WARNING) << "Failed to write to " << abortPath;
1518*f40fafd4SAndroid Build Coastguard Worker         }
1519*f40fafd4SAndroid Build Coastguard Worker     }
1520*f40fafd4SAndroid Build Coastguard Worker 
1521*f40fafd4SAndroid Build Coastguard Worker     if (ec) {
1522*f40fafd4SAndroid Build Coastguard Worker         LOG(WARNING) << "Failed to iterate through " << kFuseConnections << ": "  << ec.message();
1523*f40fafd4SAndroid Build Coastguard Worker         return -ec.value();
1524*f40fafd4SAndroid Build Coastguard Worker     }
1525*f40fafd4SAndroid Build Coastguard Worker 
1526*f40fafd4SAndroid Build Coastguard Worker     return OK;
1527*f40fafd4SAndroid Build Coastguard Worker }
1528*f40fafd4SAndroid Build Coastguard Worker 
EnsureDirExists(const std::string & path,mode_t mode,uid_t uid,gid_t gid)1529*f40fafd4SAndroid Build Coastguard Worker status_t EnsureDirExists(const std::string& path, mode_t mode, uid_t uid, gid_t gid) {
1530*f40fafd4SAndroid Build Coastguard Worker     if (access(path.c_str(), F_OK) != 0) {
1531*f40fafd4SAndroid Build Coastguard Worker         PLOG(WARNING) << "Dir does not exist: " << path;
1532*f40fafd4SAndroid Build Coastguard Worker         if (fs_prepare_dir(path.c_str(), mode, uid, gid) != 0) {
1533*f40fafd4SAndroid Build Coastguard Worker             return -errno;
1534*f40fafd4SAndroid Build Coastguard Worker         }
1535*f40fafd4SAndroid Build Coastguard Worker     }
1536*f40fafd4SAndroid Build Coastguard Worker     return OK;
1537*f40fafd4SAndroid Build Coastguard Worker }
1538*f40fafd4SAndroid Build Coastguard Worker 
1539*f40fafd4SAndroid Build Coastguard Worker // Gets the sysfs path for parameters of the backing device info (bdi)
getBdiPathForMount(const std::string & mount)1540*f40fafd4SAndroid Build Coastguard Worker static std::string getBdiPathForMount(const std::string& mount) {
1541*f40fafd4SAndroid Build Coastguard Worker     // First figure out MAJOR:MINOR of mount. Simplest way is to stat the path.
1542*f40fafd4SAndroid Build Coastguard Worker     struct stat info;
1543*f40fafd4SAndroid Build Coastguard Worker     if (stat(mount.c_str(), &info) != 0) {
1544*f40fafd4SAndroid Build Coastguard Worker         PLOG(ERROR) << "Failed to stat " << mount;
1545*f40fafd4SAndroid Build Coastguard Worker         return "";
1546*f40fafd4SAndroid Build Coastguard Worker     }
1547*f40fafd4SAndroid Build Coastguard Worker     unsigned int maj = major(info.st_dev);
1548*f40fafd4SAndroid Build Coastguard Worker     unsigned int min = minor(info.st_dev);
1549*f40fafd4SAndroid Build Coastguard Worker 
1550*f40fafd4SAndroid Build Coastguard Worker     return StringPrintf("/sys/class/bdi/%u:%u", maj, min);
1551*f40fafd4SAndroid Build Coastguard Worker }
1552*f40fafd4SAndroid Build Coastguard Worker 
1553*f40fafd4SAndroid Build Coastguard Worker // Configures max_ratio for the FUSE filesystem.
ConfigureMaxDirtyRatioForFuse(const std::string & fuse_mount,unsigned int max_ratio)1554*f40fafd4SAndroid Build Coastguard Worker void ConfigureMaxDirtyRatioForFuse(const std::string& fuse_mount, unsigned int max_ratio) {
1555*f40fafd4SAndroid Build Coastguard Worker     LOG(INFO) << "Configuring max_ratio of " << fuse_mount << " fuse filesystem to " << max_ratio;
1556*f40fafd4SAndroid Build Coastguard Worker     if (max_ratio > 100) {
1557*f40fafd4SAndroid Build Coastguard Worker         LOG(ERROR) << "Invalid max_ratio: " << max_ratio;
1558*f40fafd4SAndroid Build Coastguard Worker         return;
1559*f40fafd4SAndroid Build Coastguard Worker     }
1560*f40fafd4SAndroid Build Coastguard Worker     std::string fuseBdiPath = getBdiPathForMount(fuse_mount);
1561*f40fafd4SAndroid Build Coastguard Worker     if (fuseBdiPath == "") {
1562*f40fafd4SAndroid Build Coastguard Worker         return;
1563*f40fafd4SAndroid Build Coastguard Worker     }
1564*f40fafd4SAndroid Build Coastguard Worker     std::string max_ratio_file = StringPrintf("%s/max_ratio", fuseBdiPath.c_str());
1565*f40fafd4SAndroid Build Coastguard Worker     unique_fd fd(TEMP_FAILURE_RETRY(open(max_ratio_file.c_str(), O_WRONLY | O_CLOEXEC)));
1566*f40fafd4SAndroid Build Coastguard Worker     if (fd.get() == -1) {
1567*f40fafd4SAndroid Build Coastguard Worker         PLOG(ERROR) << "Failed to open " << max_ratio_file;
1568*f40fafd4SAndroid Build Coastguard Worker         return;
1569*f40fafd4SAndroid Build Coastguard Worker     }
1570*f40fafd4SAndroid Build Coastguard Worker     LOG(INFO) << "Writing " << max_ratio << " to " << max_ratio_file;
1571*f40fafd4SAndroid Build Coastguard Worker     if (!WriteStringToFd(std::to_string(max_ratio), fd)) {
1572*f40fafd4SAndroid Build Coastguard Worker         PLOG(ERROR) << "Failed to write to " << max_ratio_file;
1573*f40fafd4SAndroid Build Coastguard Worker     }
1574*f40fafd4SAndroid Build Coastguard Worker }
1575*f40fafd4SAndroid Build Coastguard Worker 
1576*f40fafd4SAndroid Build Coastguard Worker // Configures read ahead property of the fuse filesystem with the mount point |fuse_mount| by
1577*f40fafd4SAndroid Build Coastguard Worker // writing |read_ahead_kb| to the /sys/class/bdi/MAJOR:MINOR/read_ahead_kb.
ConfigureReadAheadForFuse(const std::string & fuse_mount,size_t read_ahead_kb)1578*f40fafd4SAndroid Build Coastguard Worker void ConfigureReadAheadForFuse(const std::string& fuse_mount, size_t read_ahead_kb) {
1579*f40fafd4SAndroid Build Coastguard Worker     LOG(INFO) << "Configuring read_ahead of " << fuse_mount << " fuse filesystem to "
1580*f40fafd4SAndroid Build Coastguard Worker               << read_ahead_kb << "kb";
1581*f40fafd4SAndroid Build Coastguard Worker     std::string fuseBdiPath = getBdiPathForMount(fuse_mount);
1582*f40fafd4SAndroid Build Coastguard Worker     if (fuseBdiPath == "") {
1583*f40fafd4SAndroid Build Coastguard Worker         return;
1584*f40fafd4SAndroid Build Coastguard Worker     }
1585*f40fafd4SAndroid Build Coastguard Worker     // We found the bdi path for our filesystem, time to configure read ahead!
1586*f40fafd4SAndroid Build Coastguard Worker     std::string read_ahead_file = StringPrintf("%s/read_ahead_kb", fuseBdiPath.c_str());
1587*f40fafd4SAndroid Build Coastguard Worker     unique_fd fd(TEMP_FAILURE_RETRY(open(read_ahead_file.c_str(), O_WRONLY | O_CLOEXEC)));
1588*f40fafd4SAndroid Build Coastguard Worker     if (fd.get() == -1) {
1589*f40fafd4SAndroid Build Coastguard Worker         PLOG(ERROR) << "Failed to open " << read_ahead_file;
1590*f40fafd4SAndroid Build Coastguard Worker         return;
1591*f40fafd4SAndroid Build Coastguard Worker     }
1592*f40fafd4SAndroid Build Coastguard Worker     LOG(INFO) << "Writing " << read_ahead_kb << " to " << read_ahead_file;
1593*f40fafd4SAndroid Build Coastguard Worker     if (!WriteStringToFd(std::to_string(read_ahead_kb), fd)) {
1594*f40fafd4SAndroid Build Coastguard Worker         PLOG(ERROR) << "Failed to write to " << read_ahead_file;
1595*f40fafd4SAndroid Build Coastguard Worker     }
1596*f40fafd4SAndroid Build Coastguard Worker }
1597*f40fafd4SAndroid Build Coastguard Worker 
MountUserFuse(userid_t user_id,const std::string & absolute_lower_path,const std::string & relative_upper_path,android::base::unique_fd * fuse_fd)1598*f40fafd4SAndroid Build Coastguard Worker status_t MountUserFuse(userid_t user_id, const std::string& absolute_lower_path,
1599*f40fafd4SAndroid Build Coastguard Worker                        const std::string& relative_upper_path, android::base::unique_fd* fuse_fd) {
1600*f40fafd4SAndroid Build Coastguard Worker     std::string pre_fuse_path(StringPrintf("/mnt/user/%d", user_id));
1601*f40fafd4SAndroid Build Coastguard Worker     std::string fuse_path(
1602*f40fafd4SAndroid Build Coastguard Worker             StringPrintf("%s/%s", pre_fuse_path.c_str(), relative_upper_path.c_str()));
1603*f40fafd4SAndroid Build Coastguard Worker 
1604*f40fafd4SAndroid Build Coastguard Worker     std::string pre_pass_through_path(StringPrintf("/mnt/pass_through/%d", user_id));
1605*f40fafd4SAndroid Build Coastguard Worker     std::string pass_through_path(
1606*f40fafd4SAndroid Build Coastguard Worker             StringPrintf("%s/%s", pre_pass_through_path.c_str(), relative_upper_path.c_str()));
1607*f40fafd4SAndroid Build Coastguard Worker 
1608*f40fafd4SAndroid Build Coastguard Worker     // Ensure that /mnt/user is 0700. With FUSE, apps don't need access to /mnt/user paths directly.
1609*f40fafd4SAndroid Build Coastguard Worker     // Without FUSE however, apps need /mnt/user access so /mnt/user in init.rc is 0755 until here
1610*f40fafd4SAndroid Build Coastguard Worker     auto result = PrepareDir("/mnt/user", 0750, AID_ROOT, AID_MEDIA_RW);
1611*f40fafd4SAndroid Build Coastguard Worker     if (result != android::OK) {
1612*f40fafd4SAndroid Build Coastguard Worker         PLOG(ERROR) << "Failed to prepare directory /mnt/user";
1613*f40fafd4SAndroid Build Coastguard Worker         return -1;
1614*f40fafd4SAndroid Build Coastguard Worker     }
1615*f40fafd4SAndroid Build Coastguard Worker 
1616*f40fafd4SAndroid Build Coastguard Worker     result = PrepareMountDirForUser(user_id);
1617*f40fafd4SAndroid Build Coastguard Worker     if (result != android::OK) {
1618*f40fafd4SAndroid Build Coastguard Worker         PLOG(ERROR) << "Failed to create Mount Directory for user " << user_id;
1619*f40fafd4SAndroid Build Coastguard Worker         return -1;
1620*f40fafd4SAndroid Build Coastguard Worker     }
1621*f40fafd4SAndroid Build Coastguard Worker 
1622*f40fafd4SAndroid Build Coastguard Worker     result = PrepareDir(fuse_path, 0700, AID_ROOT, AID_ROOT);
1623*f40fafd4SAndroid Build Coastguard Worker     if (result != android::OK) {
1624*f40fafd4SAndroid Build Coastguard Worker         PLOG(ERROR) << "Failed to prepare directory " << fuse_path;
1625*f40fafd4SAndroid Build Coastguard Worker         return -1;
1626*f40fafd4SAndroid Build Coastguard Worker     }
1627*f40fafd4SAndroid Build Coastguard Worker 
1628*f40fafd4SAndroid Build Coastguard Worker     result = PrepareDir(pre_pass_through_path, 0710, AID_ROOT, AID_MEDIA_RW);
1629*f40fafd4SAndroid Build Coastguard Worker     if (result != android::OK) {
1630*f40fafd4SAndroid Build Coastguard Worker         PLOG(ERROR) << "Failed to prepare directory " << pre_pass_through_path;
1631*f40fafd4SAndroid Build Coastguard Worker         return -1;
1632*f40fafd4SAndroid Build Coastguard Worker     }
1633*f40fafd4SAndroid Build Coastguard Worker 
1634*f40fafd4SAndroid Build Coastguard Worker     result = PrepareDir(pass_through_path, 0710, AID_ROOT, AID_MEDIA_RW);
1635*f40fafd4SAndroid Build Coastguard Worker     if (result != android::OK) {
1636*f40fafd4SAndroid Build Coastguard Worker         PLOG(ERROR) << "Failed to prepare directory " << pass_through_path;
1637*f40fafd4SAndroid Build Coastguard Worker         return -1;
1638*f40fafd4SAndroid Build Coastguard Worker     }
1639*f40fafd4SAndroid Build Coastguard Worker 
1640*f40fafd4SAndroid Build Coastguard Worker     if (relative_upper_path == "emulated") {
1641*f40fafd4SAndroid Build Coastguard Worker         std::string linkpath(StringPrintf("/mnt/user/%d/self", user_id));
1642*f40fafd4SAndroid Build Coastguard Worker         result = PrepareDir(linkpath, 0755, AID_ROOT, AID_ROOT);
1643*f40fafd4SAndroid Build Coastguard Worker         if (result != android::OK) {
1644*f40fafd4SAndroid Build Coastguard Worker             PLOG(ERROR) << "Failed to prepare directory " << linkpath;
1645*f40fafd4SAndroid Build Coastguard Worker             return -1;
1646*f40fafd4SAndroid Build Coastguard Worker         }
1647*f40fafd4SAndroid Build Coastguard Worker         linkpath += "/primary";
1648*f40fafd4SAndroid Build Coastguard Worker         Symlink("/storage/emulated/" + std::to_string(user_id), linkpath);
1649*f40fafd4SAndroid Build Coastguard Worker 
1650*f40fafd4SAndroid Build Coastguard Worker         std::string pass_through_linkpath(StringPrintf("/mnt/pass_through/%d/self", user_id));
1651*f40fafd4SAndroid Build Coastguard Worker         result = PrepareDir(pass_through_linkpath, 0710, AID_ROOT, AID_MEDIA_RW);
1652*f40fafd4SAndroid Build Coastguard Worker         if (result != android::OK) {
1653*f40fafd4SAndroid Build Coastguard Worker             PLOG(ERROR) << "Failed to prepare directory " << pass_through_linkpath;
1654*f40fafd4SAndroid Build Coastguard Worker             return -1;
1655*f40fafd4SAndroid Build Coastguard Worker         }
1656*f40fafd4SAndroid Build Coastguard Worker         pass_through_linkpath += "/primary";
1657*f40fafd4SAndroid Build Coastguard Worker         Symlink("/storage/emulated/" + std::to_string(user_id), pass_through_linkpath);
1658*f40fafd4SAndroid Build Coastguard Worker     }
1659*f40fafd4SAndroid Build Coastguard Worker 
1660*f40fafd4SAndroid Build Coastguard Worker     // Open fuse fd.
1661*f40fafd4SAndroid Build Coastguard Worker     fuse_fd->reset(open("/dev/fuse", O_RDWR | O_CLOEXEC));
1662*f40fafd4SAndroid Build Coastguard Worker     if (fuse_fd->get() == -1) {
1663*f40fafd4SAndroid Build Coastguard Worker         PLOG(ERROR) << "Failed to open /dev/fuse";
1664*f40fafd4SAndroid Build Coastguard Worker         return -1;
1665*f40fafd4SAndroid Build Coastguard Worker     }
1666*f40fafd4SAndroid Build Coastguard Worker 
1667*f40fafd4SAndroid Build Coastguard Worker     // Note: leaving out default_permissions since we don't want kernel to do lower filesystem
1668*f40fafd4SAndroid Build Coastguard Worker     // permission checks before routing to FUSE daemon.
1669*f40fafd4SAndroid Build Coastguard Worker     const auto opts = StringPrintf(
1670*f40fafd4SAndroid Build Coastguard Worker         "fd=%i,"
1671*f40fafd4SAndroid Build Coastguard Worker         "rootmode=40000,"
1672*f40fafd4SAndroid Build Coastguard Worker         "allow_other,"
1673*f40fafd4SAndroid Build Coastguard Worker         "user_id=0,group_id=0,",
1674*f40fafd4SAndroid Build Coastguard Worker         fuse_fd->get());
1675*f40fafd4SAndroid Build Coastguard Worker 
1676*f40fafd4SAndroid Build Coastguard Worker     result = TEMP_FAILURE_RETRY(mount("/dev/fuse", fuse_path.c_str(), "fuse",
1677*f40fafd4SAndroid Build Coastguard Worker                                       MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_NOATIME | MS_LAZYTIME,
1678*f40fafd4SAndroid Build Coastguard Worker                                       opts.c_str()));
1679*f40fafd4SAndroid Build Coastguard Worker     if (result != 0) {
1680*f40fafd4SAndroid Build Coastguard Worker         PLOG(ERROR) << "Failed to mount " << fuse_path;
1681*f40fafd4SAndroid Build Coastguard Worker         return -errno;
1682*f40fafd4SAndroid Build Coastguard Worker     }
1683*f40fafd4SAndroid Build Coastguard Worker 
1684*f40fafd4SAndroid Build Coastguard Worker     if (IsSdcardfsUsed()) {
1685*f40fafd4SAndroid Build Coastguard Worker         std::string sdcardfs_path(
1686*f40fafd4SAndroid Build Coastguard Worker                 StringPrintf("/mnt/runtime/full/%s", relative_upper_path.c_str()));
1687*f40fafd4SAndroid Build Coastguard Worker 
1688*f40fafd4SAndroid Build Coastguard Worker         LOG(INFO) << "Bind mounting " << sdcardfs_path << " to " << pass_through_path;
1689*f40fafd4SAndroid Build Coastguard Worker         return BindMount(sdcardfs_path, pass_through_path);
1690*f40fafd4SAndroid Build Coastguard Worker     } else {
1691*f40fafd4SAndroid Build Coastguard Worker         LOG(INFO) << "Bind mounting " << absolute_lower_path << " to " << pass_through_path;
1692*f40fafd4SAndroid Build Coastguard Worker         return BindMount(absolute_lower_path, pass_through_path);
1693*f40fafd4SAndroid Build Coastguard Worker     }
1694*f40fafd4SAndroid Build Coastguard Worker }
1695*f40fafd4SAndroid Build Coastguard Worker 
UnmountUserFuse(userid_t user_id,const std::string & absolute_lower_path,const std::string & relative_upper_path)1696*f40fafd4SAndroid Build Coastguard Worker status_t UnmountUserFuse(userid_t user_id, const std::string& absolute_lower_path,
1697*f40fafd4SAndroid Build Coastguard Worker                          const std::string& relative_upper_path) {
1698*f40fafd4SAndroid Build Coastguard Worker     std::string fuse_path(StringPrintf("/mnt/user/%d/%s", user_id, relative_upper_path.c_str()));
1699*f40fafd4SAndroid Build Coastguard Worker     std::string pass_through_path(
1700*f40fafd4SAndroid Build Coastguard Worker             StringPrintf("/mnt/pass_through/%d/%s", user_id, relative_upper_path.c_str()));
1701*f40fafd4SAndroid Build Coastguard Worker 
1702*f40fafd4SAndroid Build Coastguard Worker     LOG(INFO) << "Unmounting fuse path " << fuse_path;
1703*f40fafd4SAndroid Build Coastguard Worker     android::status_t result = ForceUnmount(fuse_path);
1704*f40fafd4SAndroid Build Coastguard Worker     if (result != android::OK) {
1705*f40fafd4SAndroid Build Coastguard Worker         // TODO(b/135341433): MNT_DETACH is needed for fuse because umount2 can fail with EBUSY.
1706*f40fafd4SAndroid Build Coastguard Worker         // Figure out why we get EBUSY and remove this special casing if possible.
1707*f40fafd4SAndroid Build Coastguard Worker         PLOG(ERROR) << "Failed to unmount. Trying MNT_DETACH " << fuse_path << " ...";
1708*f40fafd4SAndroid Build Coastguard Worker         if (umount2(fuse_path.c_str(), UMOUNT_NOFOLLOW | MNT_DETACH) && errno != EINVAL &&
1709*f40fafd4SAndroid Build Coastguard Worker             errno != ENOENT) {
1710*f40fafd4SAndroid Build Coastguard Worker             PLOG(ERROR) << "Failed to unmount with MNT_DETACH " << fuse_path;
1711*f40fafd4SAndroid Build Coastguard Worker             return -errno;
1712*f40fafd4SAndroid Build Coastguard Worker         }
1713*f40fafd4SAndroid Build Coastguard Worker         result = android::OK;
1714*f40fafd4SAndroid Build Coastguard Worker     }
1715*f40fafd4SAndroid Build Coastguard Worker     rmdir(fuse_path.c_str());
1716*f40fafd4SAndroid Build Coastguard Worker 
1717*f40fafd4SAndroid Build Coastguard Worker     LOG(INFO) << "Unmounting pass_through_path " << pass_through_path;
1718*f40fafd4SAndroid Build Coastguard Worker     auto status = ForceUnmount(pass_through_path);
1719*f40fafd4SAndroid Build Coastguard Worker     if (status != android::OK) {
1720*f40fafd4SAndroid Build Coastguard Worker         LOG(ERROR) << "Failed to unmount " << pass_through_path;
1721*f40fafd4SAndroid Build Coastguard Worker     }
1722*f40fafd4SAndroid Build Coastguard Worker     rmdir(pass_through_path.c_str());
1723*f40fafd4SAndroid Build Coastguard Worker 
1724*f40fafd4SAndroid Build Coastguard Worker     return result;
1725*f40fafd4SAndroid Build Coastguard Worker }
1726*f40fafd4SAndroid Build Coastguard Worker 
PrepareAndroidDirs(const std::string & volumeRoot)1727*f40fafd4SAndroid Build Coastguard Worker status_t PrepareAndroidDirs(const std::string& volumeRoot) {
1728*f40fafd4SAndroid Build Coastguard Worker     std::string androidDir = volumeRoot + kAndroidDir;
1729*f40fafd4SAndroid Build Coastguard Worker     std::string androidDataDir = volumeRoot + kAppDataDir;
1730*f40fafd4SAndroid Build Coastguard Worker     std::string androidObbDir = volumeRoot + kAppObbDir;
1731*f40fafd4SAndroid Build Coastguard Worker     std::string androidMediaDir = volumeRoot + kAppMediaDir;
1732*f40fafd4SAndroid Build Coastguard Worker 
1733*f40fafd4SAndroid Build Coastguard Worker     bool useSdcardFs = IsSdcardfsUsed();
1734*f40fafd4SAndroid Build Coastguard Worker 
1735*f40fafd4SAndroid Build Coastguard Worker     // mode 0771 + sticky bit for inheriting GIDs
1736*f40fafd4SAndroid Build Coastguard Worker     mode_t mode = S_IRWXU | S_IRWXG | S_IXOTH | S_ISGID;
1737*f40fafd4SAndroid Build Coastguard Worker     if (fs_prepare_dir(androidDir.c_str(), mode, AID_MEDIA_RW, AID_MEDIA_RW) != 0) {
1738*f40fafd4SAndroid Build Coastguard Worker         PLOG(ERROR) << "Failed to create " << androidDir;
1739*f40fafd4SAndroid Build Coastguard Worker         return -errno;
1740*f40fafd4SAndroid Build Coastguard Worker     }
1741*f40fafd4SAndroid Build Coastguard Worker 
1742*f40fafd4SAndroid Build Coastguard Worker     gid_t dataGid = useSdcardFs ? AID_MEDIA_RW : AID_EXT_DATA_RW;
1743*f40fafd4SAndroid Build Coastguard Worker     if (fs_prepare_dir(androidDataDir.c_str(), mode, AID_MEDIA_RW, dataGid) != 0) {
1744*f40fafd4SAndroid Build Coastguard Worker         PLOG(ERROR) << "Failed to create " << androidDataDir;
1745*f40fafd4SAndroid Build Coastguard Worker         return -errno;
1746*f40fafd4SAndroid Build Coastguard Worker     }
1747*f40fafd4SAndroid Build Coastguard Worker 
1748*f40fafd4SAndroid Build Coastguard Worker     gid_t obbGid = useSdcardFs ? AID_MEDIA_RW : AID_EXT_OBB_RW;
1749*f40fafd4SAndroid Build Coastguard Worker     if (fs_prepare_dir(androidObbDir.c_str(), mode, AID_MEDIA_RW, obbGid) != 0) {
1750*f40fafd4SAndroid Build Coastguard Worker         PLOG(ERROR) << "Failed to create " << androidObbDir;
1751*f40fafd4SAndroid Build Coastguard Worker         return -errno;
1752*f40fafd4SAndroid Build Coastguard Worker     }
1753*f40fafd4SAndroid Build Coastguard Worker     // Some other apps, like installers, have write access to the OBB directory
1754*f40fafd4SAndroid Build Coastguard Worker     // to pre-download them. To make sure newly created folders in this directory
1755*f40fafd4SAndroid Build Coastguard Worker     // have the right permissions, set a default ACL.
1756*f40fafd4SAndroid Build Coastguard Worker     SetDefaultAcl(androidObbDir, mode, AID_MEDIA_RW, obbGid, {});
1757*f40fafd4SAndroid Build Coastguard Worker 
1758*f40fafd4SAndroid Build Coastguard Worker     if (fs_prepare_dir(androidMediaDir.c_str(), mode, AID_MEDIA_RW, AID_MEDIA_RW) != 0) {
1759*f40fafd4SAndroid Build Coastguard Worker         PLOG(ERROR) << "Failed to create " << androidMediaDir;
1760*f40fafd4SAndroid Build Coastguard Worker         return -errno;
1761*f40fafd4SAndroid Build Coastguard Worker     }
1762*f40fafd4SAndroid Build Coastguard Worker 
1763*f40fafd4SAndroid Build Coastguard Worker     return OK;
1764*f40fafd4SAndroid Build Coastguard Worker }
1765*f40fafd4SAndroid Build Coastguard Worker 
1766*f40fafd4SAndroid Build Coastguard Worker namespace ab = android::base;
1767*f40fafd4SAndroid Build Coastguard Worker 
openDirFd(int parentFd,const char * name)1768*f40fafd4SAndroid Build Coastguard Worker static ab::unique_fd openDirFd(int parentFd, const char* name) {
1769*f40fafd4SAndroid Build Coastguard Worker     return ab::unique_fd{::openat(parentFd, name, O_CLOEXEC | O_DIRECTORY | O_PATH | O_NOFOLLOW)};
1770*f40fafd4SAndroid Build Coastguard Worker }
1771*f40fafd4SAndroid Build Coastguard Worker 
openAbsolutePathFd(std::string_view path)1772*f40fafd4SAndroid Build Coastguard Worker static ab::unique_fd openAbsolutePathFd(std::string_view path) {
1773*f40fafd4SAndroid Build Coastguard Worker     if (path.empty() || path[0] != '/') {
1774*f40fafd4SAndroid Build Coastguard Worker         errno = EINVAL;
1775*f40fafd4SAndroid Build Coastguard Worker         return {};
1776*f40fafd4SAndroid Build Coastguard Worker     }
1777*f40fafd4SAndroid Build Coastguard Worker     if (path == "/") {
1778*f40fafd4SAndroid Build Coastguard Worker         return openDirFd(-1, "/");
1779*f40fafd4SAndroid Build Coastguard Worker     }
1780*f40fafd4SAndroid Build Coastguard Worker 
1781*f40fafd4SAndroid Build Coastguard Worker     // first component is special - it includes the leading slash
1782*f40fafd4SAndroid Build Coastguard Worker     auto next = path.find('/', 1);
1783*f40fafd4SAndroid Build Coastguard Worker     auto component = std::string(path.substr(0, next));
1784*f40fafd4SAndroid Build Coastguard Worker     if (component == "..") {
1785*f40fafd4SAndroid Build Coastguard Worker         errno = EINVAL;
1786*f40fafd4SAndroid Build Coastguard Worker         return {};
1787*f40fafd4SAndroid Build Coastguard Worker     }
1788*f40fafd4SAndroid Build Coastguard Worker     auto fd = openDirFd(-1, component.c_str());
1789*f40fafd4SAndroid Build Coastguard Worker     if (!fd.ok()) {
1790*f40fafd4SAndroid Build Coastguard Worker         return fd;
1791*f40fafd4SAndroid Build Coastguard Worker     }
1792*f40fafd4SAndroid Build Coastguard Worker     path.remove_prefix(std::min(next + 1, path.size()));
1793*f40fafd4SAndroid Build Coastguard Worker     while (next != path.npos && !path.empty()) {
1794*f40fafd4SAndroid Build Coastguard Worker         next = path.find('/');
1795*f40fafd4SAndroid Build Coastguard Worker         component.assign(path.substr(0, next));
1796*f40fafd4SAndroid Build Coastguard Worker         fd = openDirFd(fd, component.c_str());
1797*f40fafd4SAndroid Build Coastguard Worker         if (!fd.ok()) {
1798*f40fafd4SAndroid Build Coastguard Worker             return fd;
1799*f40fafd4SAndroid Build Coastguard Worker         }
1800*f40fafd4SAndroid Build Coastguard Worker         path.remove_prefix(std::min(next + 1, path.size()));
1801*f40fafd4SAndroid Build Coastguard Worker     }
1802*f40fafd4SAndroid Build Coastguard Worker     return fd;
1803*f40fafd4SAndroid Build Coastguard Worker }
1804*f40fafd4SAndroid Build Coastguard Worker 
OpenDirInProcfs(std::string_view path)1805*f40fafd4SAndroid Build Coastguard Worker std::pair<android::base::unique_fd, std::string> OpenDirInProcfs(std::string_view path) {
1806*f40fafd4SAndroid Build Coastguard Worker     auto fd = openAbsolutePathFd(path);
1807*f40fafd4SAndroid Build Coastguard Worker     if (!fd.ok()) {
1808*f40fafd4SAndroid Build Coastguard Worker         return {};
1809*f40fafd4SAndroid Build Coastguard Worker     }
1810*f40fafd4SAndroid Build Coastguard Worker 
1811*f40fafd4SAndroid Build Coastguard Worker     auto linkPath = std::string("/proc/self/fd/") += std::to_string(fd.get());
1812*f40fafd4SAndroid Build Coastguard Worker     return {std::move(fd), std::move(linkPath)};
1813*f40fafd4SAndroid Build Coastguard Worker }
1814*f40fafd4SAndroid Build Coastguard Worker 
IsPropertySet(const char * name,bool & value)1815*f40fafd4SAndroid Build Coastguard Worker static bool IsPropertySet(const char* name, bool& value) {
1816*f40fafd4SAndroid Build Coastguard Worker     if (base::GetProperty(name, "") == "") return false;
1817*f40fafd4SAndroid Build Coastguard Worker 
1818*f40fafd4SAndroid Build Coastguard Worker     value = base::GetBoolProperty(name, false);
1819*f40fafd4SAndroid Build Coastguard Worker     LOG(INFO) << "fuse-bpf is " << (value ? "enabled" : "disabled") << " because of property "
1820*f40fafd4SAndroid Build Coastguard Worker               << name;
1821*f40fafd4SAndroid Build Coastguard Worker     return true;
1822*f40fafd4SAndroid Build Coastguard Worker }
1823*f40fafd4SAndroid Build Coastguard Worker 
IsFuseBpfEnabled()1824*f40fafd4SAndroid Build Coastguard Worker bool IsFuseBpfEnabled() {
1825*f40fafd4SAndroid Build Coastguard Worker     // This logic is reproduced in packages/providers/MediaProvider/jni/FuseDaemon.cpp
1826*f40fafd4SAndroid Build Coastguard Worker     // so changes made here must be reflected there
1827*f40fafd4SAndroid Build Coastguard Worker     bool enabled = false;
1828*f40fafd4SAndroid Build Coastguard Worker 
1829*f40fafd4SAndroid Build Coastguard Worker     if (IsPropertySet("ro.fuse.bpf.is_running", enabled)) return enabled;
1830*f40fafd4SAndroid Build Coastguard Worker 
1831*f40fafd4SAndroid Build Coastguard Worker     if (!IsPropertySet("persist.sys.fuse.bpf.override", enabled) &&
1832*f40fafd4SAndroid Build Coastguard Worker         !IsPropertySet("ro.fuse.bpf.enabled", enabled)) {
1833*f40fafd4SAndroid Build Coastguard Worker         // If the kernel has fuse-bpf, /sys/fs/fuse/features/fuse_bpf will exist and have the
1834*f40fafd4SAndroid Build Coastguard Worker         // contents 'supported\n' - see fs/fuse/inode.c in the kernel source
1835*f40fafd4SAndroid Build Coastguard Worker         std::string contents;
1836*f40fafd4SAndroid Build Coastguard Worker         const char* filename = "/sys/fs/fuse/features/fuse_bpf";
1837*f40fafd4SAndroid Build Coastguard Worker         if (!base::ReadFileToString(filename, &contents)) {
1838*f40fafd4SAndroid Build Coastguard Worker             LOG(INFO) << "fuse-bpf is disabled because " << filename << " cannot be read";
1839*f40fafd4SAndroid Build Coastguard Worker             enabled = false;
1840*f40fafd4SAndroid Build Coastguard Worker         } else if (contents == "supported\n") {
1841*f40fafd4SAndroid Build Coastguard Worker             LOG(INFO) << "fuse-bpf is enabled because " << filename << " reads 'supported'";
1842*f40fafd4SAndroid Build Coastguard Worker             enabled = true;
1843*f40fafd4SAndroid Build Coastguard Worker         } else {
1844*f40fafd4SAndroid Build Coastguard Worker             LOG(INFO) << "fuse-bpf is disabled because " << filename
1845*f40fafd4SAndroid Build Coastguard Worker                       << " does not read 'supported'";
1846*f40fafd4SAndroid Build Coastguard Worker             enabled = false;
1847*f40fafd4SAndroid Build Coastguard Worker         }
1848*f40fafd4SAndroid Build Coastguard Worker     }
1849*f40fafd4SAndroid Build Coastguard Worker 
1850*f40fafd4SAndroid Build Coastguard Worker     std::string value = enabled ? "true" : "false";
1851*f40fafd4SAndroid Build Coastguard Worker     LOG(INFO) << "Setting ro.fuse.bpf.is_running to " << value;
1852*f40fafd4SAndroid Build Coastguard Worker     base::SetProperty("ro.fuse.bpf.is_running", value);
1853*f40fafd4SAndroid Build Coastguard Worker     return enabled;
1854*f40fafd4SAndroid Build Coastguard Worker }
1855*f40fafd4SAndroid Build Coastguard Worker 
PrepareMountDirForUser(userid_t user_id)1856*f40fafd4SAndroid Build Coastguard Worker status_t PrepareMountDirForUser(userid_t user_id) {
1857*f40fafd4SAndroid Build Coastguard Worker     std::string pre_fuse_path(StringPrintf("/mnt/user/%d", user_id));
1858*f40fafd4SAndroid Build Coastguard Worker     LOG(INFO) << "Creating mount directory " << pre_fuse_path;
1859*f40fafd4SAndroid Build Coastguard Worker     // Shell is neither AID_ROOT nor AID_EVERYBODY. Since it equally needs 'execute' access to
1860*f40fafd4SAndroid Build Coastguard Worker     // /mnt/user/0 to 'adb shell ls /sdcard' for instance, we set the uid bit of /mnt/user/0 to
1861*f40fafd4SAndroid Build Coastguard Worker     // AID_SHELL. This gives shell access along with apps running as group everybody (user 0 apps)
1862*f40fafd4SAndroid Build Coastguard Worker     // These bits should be consistent with what is set in zygote in
1863*f40fafd4SAndroid Build Coastguard Worker     // com_android_internal_os_Zygote#MountEmulatedStorage on volume bind mount during app fork
1864*f40fafd4SAndroid Build Coastguard Worker     auto result = PrepareDir(pre_fuse_path, 0710, user_id ? AID_ROOT : AID_SHELL,
1865*f40fafd4SAndroid Build Coastguard Worker                              multiuser_get_uid(user_id, AID_EVERYBODY));
1866*f40fafd4SAndroid Build Coastguard Worker     if (result != android::OK) {
1867*f40fafd4SAndroid Build Coastguard Worker         PLOG(ERROR) << "Failed to prepare directory " << pre_fuse_path;
1868*f40fafd4SAndroid Build Coastguard Worker         return -1;
1869*f40fafd4SAndroid Build Coastguard Worker     }
1870*f40fafd4SAndroid Build Coastguard Worker     return result;
1871*f40fafd4SAndroid Build Coastguard Worker }
1872*f40fafd4SAndroid Build Coastguard Worker 
1873*f40fafd4SAndroid Build Coastguard Worker }  // namespace vold
1874*f40fafd4SAndroid Build Coastguard Worker }  // namespace android
1875