blob: 11fa2c608353fc225682e285325f6af63cb7e0e7 [file] [log] [blame]
Jeff Sharkeydeb24052015-03-02 21:01:40 -08001/*
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
Jeff Sharkeydeb24052015-03-02 21:01:40 -080017#include "PublicVolume.h"
18#include "Utils.h"
Jeff Sharkey36801cc2015-03-13 16:09:20 -070019#include "VolumeManager.h"
Jeff Sharkey37ba1252018-01-19 10:55:18 +090020#include "fs/Exfat.h"
Dan Pasanend1952662015-10-27 22:52:37 -050021#include "fs/Ext4.h"
22#include "fs/F2fs.h"
23#include "fs/Ntfs.h"
Jeff Sharkey37ba1252018-01-19 10:55:18 +090024#include "fs/Vfat.h"
Jeff Sharkeydeb24052015-03-02 21:01:40 -080025
Elliott Hughes7e128fb2015-12-04 15:50:53 -080026#include <android-base/stringprintf.h>
27#include <android-base/logging.h>
Jeff Sharkeydeb24052015-03-02 21:01:40 -080028#include <cutils/fs.h>
Jeff Sharkeydeb24052015-03-02 21:01:40 -080029#include <private/android_filesystem_config.h>
Jeff Sharkey7bdf4d52017-09-18 14:47:10 -060030#include <utils/Timers.h>
Jeff Sharkeydeb24052015-03-02 21:01:40 -080031
32#include <fcntl.h>
33#include <stdlib.h>
34#include <sys/mount.h>
35#include <sys/stat.h>
36#include <sys/types.h>
Elliott Hughes0e08e842017-05-18 09:08:24 -070037#include <sys/sysmacros.h>
Jeff Sharkeydeb24052015-03-02 21:01:40 -080038#include <sys/wait.h>
39
Dan Albertae9e8902015-03-16 10:35:17 -070040using android::base::StringPrintf;
41
Jeff Sharkeydeb24052015-03-02 21:01:40 -080042namespace android {
43namespace vold {
44
Jeff Sharkeydeb24052015-03-02 21:01:40 -080045static const char* kFusePath = "/system/bin/sdcard";
46
Jeff Sharkey36801cc2015-03-13 16:09:20 -070047static const char* kAsecPath = "/mnt/secure/asec";
Jeff Sharkeydeb24052015-03-02 21:01:40 -080048
Tom Marshalld18795d2015-11-05 11:20:54 -080049PublicVolume::PublicVolume(dev_t device, const std::string& fstype /* = "" */,
50 const std::string& mntopts /* = "" */) :
51 VolumeBase(Type::kPublic), mDevice(device), mFusePid(0),
52 mFsType(fstype), mMntOpts(mntopts) {
Jeff Sharkey36801cc2015-03-13 16:09:20 -070053 setId(StringPrintf("public:%u,%u", major(device), minor(device)));
54 mDevPath = StringPrintf("/dev/block/vold/%s", getId().c_str());
Jeff Sharkeydeb24052015-03-02 21:01:40 -080055}
56
57PublicVolume::~PublicVolume() {
Jeff Sharkeydeb24052015-03-02 21:01:40 -080058}
59
60status_t PublicVolume::readMetadata() {
Jeff Sharkey3472e522017-10-06 18:02:53 -060061 status_t res = ReadMetadataUntrusted(mDevPath, &mFsType, &mFsUuid, &mFsLabel);
Jeff Sharkeycbe69fc2017-09-15 16:50:28 -060062
Jeff Sharkey814e9d32017-09-13 11:49:44 -060063 auto listener = getListener();
64 if (listener) listener->onVolumeMetadataChanged(getId(), mFsType, mFsUuid, mFsLabel);
Jeff Sharkeycbe69fc2017-09-15 16:50:28 -060065
Jeff Sharkey36801cc2015-03-13 16:09:20 -070066 return res;
Jeff Sharkeydeb24052015-03-02 21:01:40 -080067}
68
69status_t PublicVolume::initAsecStage() {
70 std::string legacyPath(mRawPath + "/android_secure");
71 std::string securePath(mRawPath + "/.android_secure");
72
73 // Recover legacy secure path
74 if (!access(legacyPath.c_str(), R_OK | X_OK)
75 && access(securePath.c_str(), R_OK | X_OK)) {
76 if (rename(legacyPath.c_str(), securePath.c_str())) {
Jeff Sharkey9c484982015-03-31 10:35:33 -070077 PLOG(WARNING) << getId() << " failed to rename legacy ASEC dir";
Jeff Sharkeydeb24052015-03-02 21:01:40 -080078 }
79 }
80
Jeff Sharkey36801cc2015-03-13 16:09:20 -070081 if (TEMP_FAILURE_RETRY(mkdir(securePath.c_str(), 0700))) {
82 if (errno != EEXIST) {
Jeff Sharkey9c484982015-03-31 10:35:33 -070083 PLOG(WARNING) << getId() << " creating ASEC stage failed";
Jeff Sharkey36801cc2015-03-13 16:09:20 -070084 return -errno;
85 }
Jeff Sharkeydeb24052015-03-02 21:01:40 -080086 }
87
Jeff Sharkey36801cc2015-03-13 16:09:20 -070088 BindMount(securePath, kAsecPath);
89
Jeff Sharkeydeb24052015-03-02 21:01:40 -080090 return OK;
91}
92
Jeff Sharkey9c484982015-03-31 10:35:33 -070093status_t PublicVolume::doCreate() {
94 return CreateDeviceNode(mDevPath, mDevice);
95}
96
97status_t PublicVolume::doDestroy() {
98 return DestroyDeviceNode(mDevPath);
99}
100
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800101status_t PublicVolume::doMount() {
Jeff Sharkey9c484982015-03-31 10:35:33 -0700102 readMetadata();
103
Dan Pasanend1952662015-10-27 22:52:37 -0500104 if (!IsFilesystemSupported(mFsType)) {
Makoto Onukic82c9ce2015-06-24 13:30:45 -0700105 LOG(ERROR) << getId() << " unsupported filesystem " << mFsType;
106 return -EIO;
107 }
108
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700109 // Use UUID as stable name, if available
110 std::string stableName = getId();
111 if (!mFsUuid.empty()) {
Jeff Sharkeyf0121c52015-04-06 14:08:45 -0700112 stableName = mFsUuid;
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700113 }
114
115 mRawPath = StringPrintf("/mnt/media_rw/%s", stableName.c_str());
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700116
Jeff Sharkey1bd078f2015-08-06 11:40:00 -0700117 mFuseDefault = StringPrintf("/mnt/runtime/default/%s", stableName.c_str());
118 mFuseRead = StringPrintf("/mnt/runtime/read/%s", stableName.c_str());
119 mFuseWrite = StringPrintf("/mnt/runtime/write/%s", stableName.c_str());
Jeff Sharkey66270a22015-06-24 11:49:24 -0700120
121 setInternalPath(mRawPath);
Jeff Sharkey8474ee32015-07-30 16:54:23 -0700122 if (getMountFlags() & MountFlags::kVisible) {
123 setPath(StringPrintf("/storage/%s", stableName.c_str()));
124 } else {
125 setPath(mRawPath);
126 }
Jeff Sharkey66270a22015-06-24 11:49:24 -0700127
Qin Chaoe0074f12015-12-15 15:20:41 +0800128 if (fs_prepare_dir(mRawPath.c_str(), 0700, AID_ROOT, AID_ROOT)) {
Jeff Sharkey66270a22015-06-24 11:49:24 -0700129 PLOG(ERROR) << getId() << " failed to create mount points";
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800130 return -errno;
131 }
132
Dan Pasanend1952662015-10-27 22:52:37 -0500133 int ret = 0;
134 if (mFsType == "exfat") {
135 ret = exfat::Check(mDevPath);
136 } else if (mFsType == "ext4") {
Michael Bestasa66df7c2015-12-06 23:53:55 +0200137 ret = ext4::Check(mDevPath, mRawPath, false);
Dan Pasanend1952662015-10-27 22:52:37 -0500138 } else if (mFsType == "f2fs") {
Michael Bestasa66df7c2015-12-06 23:53:55 +0200139 ret = f2fs::Check(mDevPath, false);
Dan Pasanend1952662015-10-27 22:52:37 -0500140 } else if (mFsType == "ntfs") {
141 ret = ntfs::Check(mDevPath);
142 } else if (mFsType == "vfat") {
143 ret = vfat::Check(mDevPath);
144 } else {
145 LOG(WARNING) << getId() << " unsupported filesystem check, skipping";
146 }
147 if (ret) {
148 LOG(ERROR) << getId() << " failed filesystem check";
149 return -EIO;
150 }
151
152 if (mFsType == "exfat") {
153 ret = exfat::Mount(mDevPath, mRawPath, AID_MEDIA_RW, AID_MEDIA_RW, 0007);
154 } else if (mFsType == "ext4") {
Sam Mortimerbb0533a2015-11-27 15:27:03 -0800155 ret = ext4::Mount(mDevPath, mRawPath, false, false, true, mMntOpts,
156 false, true);
Dan Pasanend1952662015-10-27 22:52:37 -0500157 } else if (mFsType == "f2fs") {
Sam Mortimerbb0533a2015-11-27 15:27:03 -0800158 ret = f2fs::Mount(mDevPath, mRawPath, mMntOpts, false, true);
Dan Pasanend1952662015-10-27 22:52:37 -0500159 } else if (mFsType == "ntfs") {
160 ret = ntfs::Mount(mDevPath, mRawPath, AID_MEDIA_RW, AID_MEDIA_RW, 0007);
161 } else if (mFsType == "vfat") {
162 ret = vfat::Mount(mDevPath, mRawPath, false, false, false,
163 AID_MEDIA_RW, AID_MEDIA_RW, 0007, true);
164 } else {
165 ret = ::mount(mDevPath.c_str(), mRawPath.c_str(), mFsType.c_str(), 0, NULL);
166 }
167 if (ret) {
168 PLOG(ERROR) << getId() << " failed to mount " << mDevPath;
169 return -EIO;
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800170 }
171
Jeff Sharkeyf1b996d2015-04-17 17:35:20 -0700172 if (getMountFlags() & MountFlags::kPrimary) {
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700173 initAsecStage();
174 }
175
Jeff Sharkeyc7b5b572015-06-30 15:54:17 -0700176 if (!(getMountFlags() & MountFlags::kVisible)) {
177 // Not visible to apps, so no need to spin up FUSE
178 return OK;
179 }
180
Qin Chaoe0074f12015-12-15 15:20:41 +0800181 if (fs_prepare_dir(mFuseDefault.c_str(), 0700, AID_ROOT, AID_ROOT) ||
182 fs_prepare_dir(mFuseRead.c_str(), 0700, AID_ROOT, AID_ROOT) ||
183 fs_prepare_dir(mFuseWrite.c_str(), 0700, AID_ROOT, AID_ROOT)) {
184 PLOG(ERROR) << getId() << " failed to create FUSE mount points";
185 return -errno;
186 }
187
Jeff Sharkey66270a22015-06-24 11:49:24 -0700188 dev_t before = GetDevice(mFuseWrite);
189
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800190 if (!(mFusePid = fork())) {
Jeff Sharkeyc7b5b572015-06-30 15:54:17 -0700191 if (getMountFlags() & MountFlags::kPrimary) {
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700192 if (execl(kFusePath, kFusePath,
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800193 "-u", "1023", // AID_MEDIA_RW
194 "-g", "1023", // AID_MEDIA_RW
Jeff Sharkey20642ae2015-07-28 10:57:29 -0700195 "-U", std::to_string(getMountUserId()).c_str(),
Jeff Sharkey66270a22015-06-24 11:49:24 -0700196 "-w",
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800197 mRawPath.c_str(),
Jeff Sharkey66270a22015-06-24 11:49:24 -0700198 stableName.c_str(),
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700199 NULL)) {
200 PLOG(ERROR) << "Failed to exec";
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800201 }
202 } else {
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700203 if (execl(kFusePath, kFusePath,
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800204 "-u", "1023", // AID_MEDIA_RW
205 "-g", "1023", // AID_MEDIA_RW
Jeff Sharkey20642ae2015-07-28 10:57:29 -0700206 "-U", std::to_string(getMountUserId()).c_str(),
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800207 mRawPath.c_str(),
Jeff Sharkey66270a22015-06-24 11:49:24 -0700208 stableName.c_str(),
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700209 NULL)) {
210 PLOG(ERROR) << "Failed to exec";
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800211 }
212 }
213
Jeff Sharkeyc7b5b572015-06-30 15:54:17 -0700214 LOG(ERROR) << "FUSE exiting";
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800215 _exit(1);
216 }
217
218 if (mFusePid == -1) {
Jeff Sharkey9c484982015-03-31 10:35:33 -0700219 PLOG(ERROR) << getId() << " failed to fork";
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800220 return -errno;
221 }
222
Jeff Sharkey7bdf4d52017-09-18 14:47:10 -0600223 nsecs_t start = systemTime(SYSTEM_TIME_BOOTTIME);
Jeff Sharkey66270a22015-06-24 11:49:24 -0700224 while (before == GetDevice(mFuseWrite)) {
225 LOG(VERBOSE) << "Waiting for FUSE to spin up...";
226 usleep(50000); // 50ms
Jeff Sharkey7bdf4d52017-09-18 14:47:10 -0600227
228 nsecs_t now = systemTime(SYSTEM_TIME_BOOTTIME);
229 if (nanoseconds_to_milliseconds(now - start) > 5000) {
230 LOG(WARNING) << "Timed out while waiting for FUSE to spin up";
231 return -ETIMEDOUT;
232 }
Jeff Sharkey66270a22015-06-24 11:49:24 -0700233 }
Daniel Rosenberg1d79d102017-07-11 17:59:55 -0700234 /* sdcardfs will have exited already. FUSE will still be running */
Gao Xiang9aec7a22017-12-07 11:17:57 +0800235 if (TEMP_FAILURE_RETRY(waitpid(mFusePid, nullptr, WNOHANG)) == mFusePid)
236 mFusePid = 0;
Jeff Sharkey66270a22015-06-24 11:49:24 -0700237
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800238 return OK;
239}
240
241status_t PublicVolume::doUnmount() {
John Cormie25cc7e32016-04-18 14:23:29 -0700242 // Unmount the storage before we kill the FUSE process. If we kill
243 // the FUSE process first, most file system operations will return
244 // ENOTCONN until the unmount completes. This is an exotic and unusual
245 // error code and might cause broken behaviour in applications.
Jeff Sharkey8aff8542016-03-30 20:37:28 -0600246 KillProcessesUsingPath(getPath());
247
Jeff Sharkey48d81d32015-04-12 21:50:32 -0700248 ForceUnmount(kAsecPath);
Jeff Sharkey66270a22015-06-24 11:49:24 -0700249
250 ForceUnmount(mFuseDefault);
251 ForceUnmount(mFuseRead);
252 ForceUnmount(mFuseWrite);
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800253 ForceUnmount(mRawPath);
254
John Cormie25cc7e32016-04-18 14:23:29 -0700255 if (mFusePid > 0) {
256 kill(mFusePid, SIGTERM);
257 TEMP_FAILURE_RETRY(waitpid(mFusePid, nullptr, 0));
258 mFusePid = 0;
259 }
260
Jeff Sharkey66270a22015-06-24 11:49:24 -0700261 rmdir(mFuseDefault.c_str());
262 rmdir(mFuseRead.c_str());
263 rmdir(mFuseWrite.c_str());
264 rmdir(mRawPath.c_str());
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700265
Jeff Sharkey66270a22015-06-24 11:49:24 -0700266 mFuseDefault.clear();
267 mFuseRead.clear();
268 mFuseWrite.clear();
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700269 mRawPath.clear();
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800270
271 return OK;
272}
273
Jeff Sharkeyd0640f62015-05-21 22:35:42 -0700274status_t PublicVolume::doFormat(const std::string& fsType) {
Dan Pasanend1952662015-10-27 22:52:37 -0500275 // "auto" is used for newly partitioned disks (see Disk::partition*)
276 // and thus is restricted to external/removable storage.
277 if (!(IsFilesystemSupported(fsType) || fsType == "auto")) {
Jeff Sharkeyd0640f62015-05-21 22:35:42 -0700278 LOG(ERROR) << "Unsupported filesystem " << fsType;
279 return -EINVAL;
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800280 }
Jeff Sharkeyd0640f62015-05-21 22:35:42 -0700281
Dan Pasanend1952662015-10-27 22:52:37 -0500282 if (WipeBlockDevice(mDevPath) != OK) {
283 LOG(WARNING) << getId() << " failed to wipe";
284 }
285
286 int ret = 0;
287 if (fsType == "auto") {
288 ret = vfat::Format(mDevPath, 0);
289 } else if (fsType == "exfat") {
290 ret = exfat::Format(mDevPath);
291 } else if (fsType == "ext4") {
292 ret = ext4::Format(mDevPath, 0, mRawPath);
293 } else if (fsType == "f2fs") {
294 ret = f2fs::Format(mDevPath);
295 } else if (fsType == "ntfs") {
296 ret = ntfs::Format(mDevPath);
297 } else if (fsType == "vfat") {
298 ret = vfat::Format(mDevPath, 0);
299 } else {
300 LOG(ERROR) << getId() << " unrecognized filesystem " << fsType;
301 ret = -1;
302 errno = EIO;
303 }
304
305 if (ret) {
306 LOG(ERROR) << getId() << " failed to format";
307 return -errno;
308 }
309
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800310 return OK;
311}
312
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800313} // namespace vold
314} // namespace android