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 "fs/Vfat.h" 18 #include "PublicVolume.h" 19 #include "Utils.h" 20 #include "VolumeManager.h" 21 #include "ResponseCode.h" 22 23 #include <base/stringprintf.h> 24 #include <base/logging.h> 25 #include <cutils/fs.h> 26 #include <private/android_filesystem_config.h> 27 28 #include <fcntl.h> 29 #include <stdlib.h> 30 #include <sys/mount.h> 31 #include <sys/stat.h> 32 #include <sys/types.h> 33 #include <sys/wait.h> 34 35 using android::base::StringPrintf; 36 37 namespace android { 38 namespace vold { 39 40 static const char* kFusePath = "/system/bin/sdcard"; 41 42 static const char* kAsecPath = "/mnt/secure/asec"; 43 44 PublicVolume::PublicVolume(dev_t device) : 45 VolumeBase(Type::kPublic), mDevice(device), mFusePid(0) { 46 setId(StringPrintf("public:%u,%u", major(device), minor(device))); 47 mDevPath = StringPrintf("/dev/block/vold/%s", getId().c_str()); 48 } 49 50 PublicVolume::~PublicVolume() { 51 } 52 53 status_t PublicVolume::readMetadata() { 54 status_t res = ReadMetadataUntrusted(mDevPath, mFsType, mFsUuid, mFsLabel); 55 notifyEvent(ResponseCode::VolumeFsTypeChanged, mFsType); 56 notifyEvent(ResponseCode::VolumeFsUuidChanged, mFsUuid); 57 notifyEvent(ResponseCode::VolumeFsLabelChanged, mFsLabel); 58 return res; 59 } 60 61 status_t PublicVolume::initAsecStage() { 62 std::string legacyPath(mRawPath + "/android_secure"); 63 std::string securePath(mRawPath + "/.android_secure"); 64 65 // Recover legacy secure path 66 if (!access(legacyPath.c_str(), R_OK | X_OK) 67 && access(securePath.c_str(), R_OK | X_OK)) { 68 if (rename(legacyPath.c_str(), securePath.c_str())) { 69 PLOG(WARNING) << getId() << " failed to rename legacy ASEC dir"; 70 } 71 } 72 73 if (TEMP_FAILURE_RETRY(mkdir(securePath.c_str(), 0700))) { 74 if (errno != EEXIST) { 75 PLOG(WARNING) << getId() << " creating ASEC stage failed"; 76 return -errno; 77 } 78 } 79 80 BindMount(securePath, kAsecPath); 81 82 return OK; 83 } 84 85 status_t PublicVolume::doCreate() { 86 return CreateDeviceNode(mDevPath, mDevice); 87 } 88 89 status_t PublicVolume::doDestroy() { 90 return DestroyDeviceNode(mDevPath); 91 } 92 93 status_t PublicVolume::doMount() { 94 // TODO: expand to support mounting other filesystems 95 readMetadata(); 96 97 if (mFsType != "vfat") { 98 LOG(ERROR) << getId() << " unsupported filesystem " << mFsType; 99 return -EIO; 100 } 101 102 if (vfat::Check(mDevPath)) { 103 LOG(ERROR) << getId() << " failed filesystem check"; 104 return -EIO; 105 } 106 107 // Use UUID as stable name, if available 108 std::string stableName = getId(); 109 if (!mFsUuid.empty()) { 110 stableName = mFsUuid; 111 } 112 113 mRawPath = StringPrintf("/mnt/media_rw/%s", stableName.c_str()); 114 115 mFuseDefault = StringPrintf("/mnt/runtime/default/%s", stableName.c_str()); 116 mFuseRead = StringPrintf("/mnt/runtime/read/%s", stableName.c_str()); 117 mFuseWrite = StringPrintf("/mnt/runtime/write/%s", stableName.c_str()); 118 119 setInternalPath(mRawPath); 120 if (getMountFlags() & MountFlags::kVisible) { 121 setPath(StringPrintf("/storage/%s", stableName.c_str())); 122 } else { 123 setPath(mRawPath); 124 } 125 126 if (fs_prepare_dir(mRawPath.c_str(), 0700, AID_ROOT, AID_ROOT) || 127 fs_prepare_dir(mFuseDefault.c_str(), 0700, AID_ROOT, AID_ROOT) || 128 fs_prepare_dir(mFuseRead.c_str(), 0700, AID_ROOT, AID_ROOT) || 129 fs_prepare_dir(mFuseWrite.c_str(), 0700, AID_ROOT, AID_ROOT)) { 130 PLOG(ERROR) << getId() << " failed to create mount points"; 131 return -errno; 132 } 133 134 if (vfat::Mount(mDevPath, mRawPath, false, false, false, 135 AID_MEDIA_RW, AID_MEDIA_RW, 0007, true)) { 136 PLOG(ERROR) << getId() << " failed to mount " << mDevPath; 137 return -EIO; 138 } 139 140 if (getMountFlags() & MountFlags::kPrimary) { 141 initAsecStage(); 142 } 143 144 if (!(getMountFlags() & MountFlags::kVisible)) { 145 // Not visible to apps, so no need to spin up FUSE 146 return OK; 147 } 148 149 dev_t before = GetDevice(mFuseWrite); 150 151 if (!(mFusePid = fork())) { 152 if (getMountFlags() & MountFlags::kPrimary) { 153 if (execl(kFusePath, kFusePath, 154 "-u", "1023", // AID_MEDIA_RW 155 "-g", "1023", // AID_MEDIA_RW 156 "-U", std::to_string(getMountUserId()).c_str(), 157 "-w", 158 mRawPath.c_str(), 159 stableName.c_str(), 160 NULL)) { 161 PLOG(ERROR) << "Failed to exec"; 162 } 163 } else { 164 if (execl(kFusePath, kFusePath, 165 "-u", "1023", // AID_MEDIA_RW 166 "-g", "1023", // AID_MEDIA_RW 167 "-U", std::to_string(getMountUserId()).c_str(), 168 mRawPath.c_str(), 169 stableName.c_str(), 170 NULL)) { 171 PLOG(ERROR) << "Failed to exec"; 172 } 173 } 174 175 LOG(ERROR) << "FUSE exiting"; 176 _exit(1); 177 } 178 179 if (mFusePid == -1) { 180 PLOG(ERROR) << getId() << " failed to fork"; 181 return -errno; 182 } 183 184 while (before == GetDevice(mFuseWrite)) { 185 LOG(VERBOSE) << "Waiting for FUSE to spin up..."; 186 usleep(50000); // 50ms 187 } 188 189 return OK; 190 } 191 192 status_t PublicVolume::doUnmount() { 193 if (mFusePid > 0) { 194 kill(mFusePid, SIGTERM); 195 TEMP_FAILURE_RETRY(waitpid(mFusePid, nullptr, 0)); 196 mFusePid = 0; 197 } 198 199 ForceUnmount(kAsecPath); 200 201 ForceUnmount(mFuseDefault); 202 ForceUnmount(mFuseRead); 203 ForceUnmount(mFuseWrite); 204 ForceUnmount(mRawPath); 205 206 rmdir(mFuseDefault.c_str()); 207 rmdir(mFuseRead.c_str()); 208 rmdir(mFuseWrite.c_str()); 209 rmdir(mRawPath.c_str()); 210 211 mFuseDefault.clear(); 212 mFuseRead.clear(); 213 mFuseWrite.clear(); 214 mRawPath.clear(); 215 216 return OK; 217 } 218 219 status_t PublicVolume::doFormat(const std::string& fsType) { 220 if (fsType == "vfat" || fsType == "auto") { 221 if (WipeBlockDevice(mDevPath) != OK) { 222 LOG(WARNING) << getId() << " failed to wipe"; 223 } 224 if (vfat::Format(mDevPath, 0)) { 225 LOG(ERROR) << getId() << " failed to format"; 226 return -errno; 227 } 228 } else { 229 LOG(ERROR) << "Unsupported filesystem " << fsType; 230 return -EINVAL; 231 } 232 233 return OK; 234 } 235 236 } // namespace vold 237 } // namespace android 238