• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "PublicVolume.h"
18 
19 #include "AppFuseUtil.h"
20 #include "Utils.h"
21 #include "VolumeManager.h"
22 #include "fs/Exfat.h"
23 #include "fs/Vfat.h"
24 
25 #include <android-base/logging.h>
26 #include <android-base/properties.h>
27 #include <android-base/stringprintf.h>
28 #include <cutils/fs.h>
29 #include <private/android_filesystem_config.h>
30 #include <utils/Timers.h>
31 
32 #include <fcntl.h>
33 #include <stdlib.h>
34 #include <sys/mount.h>
35 #include <sys/stat.h>
36 #include <sys/sysmacros.h>
37 #include <sys/types.h>
38 #include <sys/wait.h>
39 #include <android_vold_flags.h>
40 
41 using android::base::GetBoolProperty;
42 using android::base::StringPrintf;
43 namespace flags = android::vold::flags;
44 
45 namespace android {
46 namespace vold {
47 
48 static const char* kSdcardFsPath = "/system/bin/sdcard";
49 
50 static const char* kAsecPath = "/mnt/secure/asec";
51 
PublicVolume(dev_t device)52 PublicVolume::PublicVolume(dev_t device) : VolumeBase(Type::kPublic), mDevice(device) {
53     setId(StringPrintf("public:%u,%u", major(device), minor(device)));
54     mDevPath = StringPrintf("/dev/block/vold/%s", getId().c_str());
55     mFuseMounted = false;
56     mUseSdcardFs = IsSdcardfsUsed();
57 }
58 
~PublicVolume()59 PublicVolume::~PublicVolume() {}
60 
readMetadata()61 status_t PublicVolume::readMetadata() {
62     status_t res = ReadMetadataUntrusted(mDevPath, &mFsType, &mFsUuid, &mFsLabel);
63 
64     auto listener = getListener();
65     if (listener) listener->onVolumeMetadataChanged(getId(), mFsType, mFsUuid, mFsLabel);
66 
67     return res;
68 }
69 
initAsecStage()70 status_t PublicVolume::initAsecStage() {
71     std::string legacyPath(mRawPath + "/android_secure");
72     std::string securePath(mRawPath + "/.android_secure");
73 
74     // Recover legacy secure path
75     if (!access(legacyPath.c_str(), R_OK | X_OK) && access(securePath.c_str(), R_OK | X_OK)) {
76         if (rename(legacyPath.c_str(), securePath.c_str())) {
77             PLOG(WARNING) << getId() << " failed to rename legacy ASEC dir";
78         }
79     }
80 
81     if (TEMP_FAILURE_RETRY(mkdir(securePath.c_str(), 0700))) {
82         if (errno != EEXIST) {
83             PLOG(WARNING) << getId() << " creating ASEC stage failed";
84             return -errno;
85         }
86     }
87 
88     BindMount(securePath, kAsecPath);
89 
90     return OK;
91 }
92 
getStableName()93 std::string PublicVolume::getStableName() {
94     // Use UUID as stable name, if available
95     std::string stableName = getId();
96     if (!mFsUuid.empty()) {
97         stableName = mFsUuid;
98     }
99     return stableName;
100 }
101 
doCreate()102 status_t PublicVolume::doCreate() {
103     return CreateDeviceNode(mDevPath, mDevice);
104 }
105 
doDestroy()106 status_t PublicVolume::doDestroy() {
107     return DestroyDeviceNode(mDevPath);
108 }
109 
doMount()110 status_t PublicVolume::doMount() {
111     bool isVisible = isVisibleForWrite();
112     readMetadata();
113 
114     if (mFsType == "vfat" && vfat::IsSupported()) {
115         if (vfat::Check(mDevPath)) {
116             LOG(ERROR) << getId() << " failed filesystem check";
117             return -EIO;
118         }
119     } else if (mFsType == "exfat" && exfat::IsSupported()) {
120         if (exfat::Check(mDevPath)) {
121             LOG(ERROR) << getId() << " failed filesystem check";
122             return -EIO;
123         }
124     } else {
125         LOG(ERROR) << getId() << " unsupported filesystem " << mFsType;
126         return -EIO;
127     }
128 
129     std::string stableName = getStableName();
130 
131     mRawPath = StringPrintf("/mnt/media_rw/%s", stableName.c_str());
132 
133     mSdcardFsDefault = StringPrintf("/mnt/runtime/default/%s", stableName.c_str());
134     mSdcardFsRead = StringPrintf("/mnt/runtime/read/%s", stableName.c_str());
135     mSdcardFsWrite = StringPrintf("/mnt/runtime/write/%s", stableName.c_str());
136     mSdcardFsFull = StringPrintf("/mnt/runtime/full/%s", stableName.c_str());
137 
138     setInternalPath(mRawPath);
139     if (isVisible) {
140         setPath(StringPrintf("/storage/%s", stableName.c_str()));
141     } else {
142         setPath(mRawPath);
143     }
144 
145     if (fs_prepare_dir(mRawPath.c_str(), 0700, AID_ROOT, AID_ROOT)) {
146         PLOG(ERROR) << getId() << " failed to create mount points";
147         return -errno;
148     }
149 
150     if (mFsType == "vfat") {
151         if (vfat::Mount(mDevPath, mRawPath, false, false, false, AID_ROOT,
152                         (isVisible ? AID_MEDIA_RW : AID_EXTERNAL_STORAGE), 0007, true)) {
153             PLOG(ERROR) << getId() << " failed to mount " << mDevPath;
154             return -EIO;
155         }
156     } else if (mFsType == "exfat") {
157         if (exfat::Mount(mDevPath, mRawPath, AID_ROOT,
158                          (isVisible ? AID_MEDIA_RW : AID_EXTERNAL_STORAGE), 0007)) {
159             PLOG(ERROR) << getId() << " failed to mount " << mDevPath;
160             return -EIO;
161         }
162     }
163 
164     if (getMountFlags() & MountFlags::kPrimary) {
165         initAsecStage();
166     }
167 
168     if (!isVisible) {
169         // Not visible to apps, so no need to spin up sdcardfs or FUSE
170         return OK;
171     }
172 
173     if (mUseSdcardFs) {
174         if (fs_prepare_dir(mSdcardFsDefault.c_str(), 0700, AID_ROOT, AID_ROOT) ||
175             fs_prepare_dir(mSdcardFsRead.c_str(), 0700, AID_ROOT, AID_ROOT) ||
176             fs_prepare_dir(mSdcardFsWrite.c_str(), 0700, AID_ROOT, AID_ROOT) ||
177             fs_prepare_dir(mSdcardFsFull.c_str(), 0700, AID_ROOT, AID_ROOT)) {
178             PLOG(ERROR) << getId() << " failed to create sdcardfs mount points";
179             return -errno;
180         }
181 
182         dev_t before = GetDevice(mSdcardFsFull);
183 
184         int sdcardFsPid;
185         if (!(sdcardFsPid = fork())) {
186             if (getMountFlags() & MountFlags::kPrimary) {
187                 // clang-format off
188                 if (execl(kSdcardFsPath, kSdcardFsPath,
189                         "-u", "1023", // AID_MEDIA_RW
190                         "-g", "1023", // AID_MEDIA_RW
191                         "-U", std::to_string(getMountUserId()).c_str(),
192                         "-w",
193                         mRawPath.c_str(),
194                         stableName.c_str(),
195                         NULL)) {
196                     // clang-format on
197                     PLOG(ERROR) << "Failed to exec";
198                 }
199             } else {
200                 // clang-format off
201                 if (execl(kSdcardFsPath, kSdcardFsPath,
202                         "-u", "1023", // AID_MEDIA_RW
203                         "-g", "1023", // AID_MEDIA_RW
204                         "-U", std::to_string(getMountUserId()).c_str(),
205                         mRawPath.c_str(),
206                         stableName.c_str(),
207                         NULL)) {
208                     // clang-format on
209                     PLOG(ERROR) << "Failed to exec";
210                 }
211             }
212 
213             LOG(ERROR) << "sdcardfs exiting";
214             _exit(1);
215         }
216 
217         if (sdcardFsPid == -1) {
218             PLOG(ERROR) << getId() << " failed to fork";
219             return -errno;
220         }
221 
222         nsecs_t start = systemTime(SYSTEM_TIME_BOOTTIME);
223         while (before == GetDevice(mSdcardFsFull)) {
224             LOG(DEBUG) << "Waiting for sdcardfs to spin up...";
225             usleep(50000);  // 50ms
226 
227             nsecs_t now = systemTime(SYSTEM_TIME_BOOTTIME);
228             if (nanoseconds_to_milliseconds(now - start) > 5000) {
229                 LOG(WARNING) << "Timed out while waiting for sdcardfs to spin up";
230                 return -ETIMEDOUT;
231             }
232         }
233         /* sdcardfs will have exited already. The filesystem will still be running */
234         TEMP_FAILURE_RETRY(waitpid(sdcardFsPid, nullptr, 0));
235     }
236 
237     // We need to mount FUSE *after* sdcardfs, since the FUSE daemon may depend
238     // on sdcardfs being up.
239     LOG(INFO) << "Mounting public fuse volume";
240     android::base::unique_fd fd;
241     int user_id = getMountUserId();
242     int result = MountUserFuse(user_id, getInternalPath(), stableName, &fd);
243 
244     if (result != 0) {
245         LOG(ERROR) << "Failed to mount public fuse volume";
246         doUnmount();
247         return -result;
248     }
249 
250     mFuseMounted = true;
251     auto callback = getMountCallback();
252     if (callback) {
253         bool is_ready = false;
254         callback->onVolumeChecking(std::move(fd), getPath(), getInternalPath(), &is_ready);
255         if (!is_ready) {
256             LOG(ERROR) << "Failed to complete public volume mount";
257             doUnmount();
258             return -EIO;
259         }
260     }
261 
262     ConfigureReadAheadForFuse(GetFuseMountPathForUser(user_id, stableName), 256u);
263 
264     // See comment in model/EmulatedVolume.cpp
265     ConfigureMaxDirtyRatioForFuse(GetFuseMountPathForUser(user_id, stableName), 40u);
266 
267     auto vol_manager = VolumeManager::Instance();
268     // Create bind mounts for all running users
269     for (userid_t started_user : vol_manager->getStartedUsers()) {
270         userid_t mountUserId = getMountUserId();
271         if (started_user == mountUserId) {
272             // No need to bind mount for the user that owns the mount
273             continue;
274         }
275         if (mountUserId != VolumeManager::Instance()->getSharedStorageUser(started_user)) {
276             // No need to bind if the user does not share storage with the mount owner
277             continue;
278         }
279         // Create mount directory for the user as there is a chance that no other Volume is mounted
280         // for the user (ex: if the user is just started), so /mnt/user/user_id  does not exist yet.
281         auto mountDirStatus = PrepareMountDirForUser(started_user);
282         if (mountDirStatus != OK) {
283             LOG(ERROR) << "Failed to create Mount Directory for user " << started_user;
284         }
285         auto bindMountStatus = bindMountForUser(started_user);
286         if (bindMountStatus != OK) {
287             LOG(ERROR) << "Bind Mounting Public Volume: " << stableName
288                        << " for user: " << started_user << "Failed. Error: " << bindMountStatus;
289         }
290     }
291     return OK;
292 }
293 
bindMountForUser(userid_t user_id)294 status_t PublicVolume::bindMountForUser(userid_t user_id) {
295     userid_t mountUserId = getMountUserId();
296     std::string stableName = getStableName();
297 
298     LOG(INFO) << "Bind Mounting Public Volume for user: " << user_id
299               << ".Mount owner: " << mountUserId;
300     auto sourcePath = GetFuseMountPathForUser(mountUserId, stableName);
301     auto destPath = GetFuseMountPathForUser(user_id, stableName);
302     PrepareDir(destPath, 0770, AID_ROOT, AID_MEDIA_RW);
303     auto mountRes = BindMount(sourcePath, destPath);
304     LOG(INFO) << "Mount status: " << mountRes;
305 
306     return mountRes;
307 }
308 
doUnmount()309 status_t PublicVolume::doUnmount() {
310     // Unmount the storage before we kill the FUSE process. If we kill
311     // the FUSE process first, most file system operations will return
312     // ENOTCONN until the unmount completes. This is an exotic and unusual
313     // error code and might cause broken behaviour in applications.
314 
315     // We don't kill processes here if enhance_fuse_unmount as we make sure that we kill processes
316     // only if unmounting failed
317     if (!mFuseMounted || !flags::enhance_fuse_unmount()) {
318         KillProcessesUsingPath(getPath());
319     }
320 
321     if (mFuseMounted) {
322         std::string stableName = getStableName();
323 
324         // Unmount bind mounts for running users
325         auto vol_manager = VolumeManager::Instance();
326         userid_t user_id = getMountUserId();
327         std::vector<std::string> bind_mount_paths;
328         for (userid_t started_user : vol_manager->getStartedUsers()) {
329             if (started_user == user_id) {
330                 // No need to remove bind mount for the user that owns the mount
331                 continue;
332             }
333             if (user_id != VolumeManager::Instance()->getSharedStorageUser(started_user)) {
334                 // No need to remove bind mount
335                 // if the user does not share storage with the mount owner
336                 continue;
337             }
338 
339             auto mountPath = GetFuseMountPathForUser(started_user, stableName);
340             if (flags::enhance_fuse_unmount()) {
341                 // Add it to list so that we unmount it as part of UnmountUserFuseEnhanced
342                 bind_mount_paths.push_back(mountPath);
343             } else {
344                 LOG(INFO) << "Removing Public Volume Bind Mount for: " << started_user;
345                 ForceUnmount(mountPath);
346                 rmdir(mountPath.c_str());
347             }
348         }
349 
350         if (flags::enhance_fuse_unmount()) {
351             status_t result = UnmountUserFuseEnhanced(getMountUserId(), getInternalPath(),
352                                                       stableName, getPath(), bind_mount_paths);
353             if (result != OK) {
354                 PLOG(INFO) << "UnmountUserFuseEnhanced failed on public fuse volume";
355                 return result;
356             }
357         } else {
358             if (UnmountUserFuse(getMountUserId(), getInternalPath(), stableName) != OK) {
359                 PLOG(INFO) << "UnmountUserFuse failed on public fuse volume";
360                 return -errno;
361             }
362         }
363 
364 
365         mFuseMounted = false;
366     }
367 
368     ForceUnmount(kAsecPath);
369 
370     if (mUseSdcardFs) {
371         ForceUnmount(mSdcardFsDefault);
372         ForceUnmount(mSdcardFsRead);
373         ForceUnmount(mSdcardFsWrite);
374         ForceUnmount(mSdcardFsFull);
375 
376         rmdir(mSdcardFsDefault.c_str());
377         rmdir(mSdcardFsRead.c_str());
378         rmdir(mSdcardFsWrite.c_str());
379         rmdir(mSdcardFsFull.c_str());
380 
381         mSdcardFsDefault.clear();
382         mSdcardFsRead.clear();
383         mSdcardFsWrite.clear();
384         mSdcardFsFull.clear();
385     }
386 
387     if (ForceUnmount(mRawPath) != 0){
388         umount2(mRawPath.c_str(),MNT_DETACH);
389         PLOG(INFO) << "use umount lazy if force unmount fail";
390     }
391     if(rmdir(mRawPath.c_str()) != 0) {
392         PLOG(INFO) << "rmdir mRawPath=" << mRawPath << " fail";
393         KillProcessesUsingPath(getPath());
394     }
395     mRawPath.clear();
396 
397     return OK;
398 }
399 
doFormat(const std::string & fsType)400 status_t PublicVolume::doFormat(const std::string& fsType) {
401     bool isVfatSup = vfat::IsSupported();
402     bool isExfatSup = exfat::IsSupported();
403     status_t res = OK;
404 
405     enum { NONE, VFAT, EXFAT } fsPick = NONE;
406 
407     // Resolve auto requests
408     if (fsType == "auto" && isVfatSup && isExfatSup) {
409         uint64_t size = 0;
410 
411         res = GetBlockDevSize(mDevPath, &size);
412         if (res != OK) {
413             LOG(ERROR) << "Couldn't get device size " << mDevPath;
414             return res;
415         }
416 
417         // If both vfat & exfat are supported use exfat for SDXC (>~32GiB) cards
418         if (size > 32896LL * 1024 * 1024) {
419             fsPick = EXFAT;
420         } else {
421             fsPick = VFAT;
422         }
423     } else if (fsType == "auto" && isExfatSup) {
424         fsPick = EXFAT;
425     } else if (fsType == "auto" && isVfatSup) {
426         fsPick = VFAT;
427     }
428 
429     // Resolve explicit requests
430     if (fsType == "vfat" && isVfatSup) {
431         fsPick = VFAT;
432     } else if (fsType == "exfat" && isExfatSup) {
433         fsPick = EXFAT;
434     }
435 
436     if (WipeBlockDevice(mDevPath) != OK) {
437         LOG(WARNING) << getId() << " failed to wipe";
438     }
439 
440     if (fsPick == VFAT) {
441         res = vfat::Format(mDevPath, 0);
442     } else if (fsPick == EXFAT) {
443         res = exfat::Format(mDevPath);
444     } else {
445         LOG(ERROR) << "Unsupported filesystem " << fsType;
446         return -EINVAL;
447     }
448 
449     if (res != OK) {
450         LOG(ERROR) << getId() << " failed to format";
451         res = -errno;
452     }
453 
454     return res;
455 }
456 
457 }  // namespace vold
458 }  // namespace android
459