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#include "Utils.h"
19#include "VolumeManager.h"
20#include "fs/Exfat.h"
21#include "fs/Vfat.h"
22
23#include <android-base/stringprintf.h>
24#include <android-base/logging.h>
25#include <cutils/fs.h>
26#include <private/android_filesystem_config.h>
27#include <utils/Timers.h>
28
29#include <fcntl.h>
30#include <stdlib.h>
31#include <sys/mount.h>
32#include <sys/stat.h>
33#include <sys/types.h>
34#include <sys/sysmacros.h>
35#include <sys/wait.h>
36
37using android::base::StringPrintf;
38
39namespace android {
40namespace vold {
41
42static const char* kFusePath = "/system/bin/sdcard";
43
44static const char* kAsecPath = "/mnt/secure/asec";
45
46PublicVolume::PublicVolume(dev_t device) :
47        VolumeBase(Type::kPublic), mDevice(device), mFusePid(0) {
48    setId(StringPrintf("public:%u,%u", major(device), minor(device)));
49    mDevPath = StringPrintf("/dev/block/vold/%s", getId().c_str());
50}
51
52PublicVolume::~PublicVolume() {
53}
54
55status_t PublicVolume::readMetadata() {
56    status_t res = ReadMetadataUntrusted(mDevPath, &mFsType, &mFsUuid, &mFsLabel);
57
58    auto listener = getListener();
59    if (listener) listener->onVolumeMetadataChanged(getId(), mFsType, mFsUuid, mFsLabel);
60
61    return res;
62}
63
64status_t PublicVolume::initAsecStage() {
65    std::string legacyPath(mRawPath + "/android_secure");
66    std::string securePath(mRawPath + "/.android_secure");
67
68    // Recover legacy secure path
69    if (!access(legacyPath.c_str(), R_OK | X_OK)
70            && access(securePath.c_str(), R_OK | X_OK)) {
71        if (rename(legacyPath.c_str(), securePath.c_str())) {
72            PLOG(WARNING) << getId() << " failed to rename legacy ASEC dir";
73        }
74    }
75
76    if (TEMP_FAILURE_RETRY(mkdir(securePath.c_str(), 0700))) {
77        if (errno != EEXIST) {
78            PLOG(WARNING) << getId() << " creating ASEC stage failed";
79            return -errno;
80        }
81    }
82
83    BindMount(securePath, kAsecPath);
84
85    return OK;
86}
87
88status_t PublicVolume::doCreate() {
89    return CreateDeviceNode(mDevPath, mDevice);
90}
91
92status_t PublicVolume::doDestroy() {
93    return DestroyDeviceNode(mDevPath);
94}
95
96status_t PublicVolume::doMount() {
97    readMetadata();
98
99    if (mFsType == "vfat" && vfat::IsSupported()) {
100        if (vfat::Check(mDevPath)) {
101            LOG(ERROR) << getId() << " failed filesystem check";
102            return -EIO;
103        }
104    } else if (mFsType == "exfat" && exfat::IsSupported()) {
105        if (exfat::Check(mDevPath)) {
106            LOG(ERROR) << getId() << " failed filesystem check";
107            return -EIO;
108        }
109    } else {
110        LOG(ERROR) << getId() << " unsupported filesystem " << mFsType;
111        return -EIO;
112    }
113
114    // Use UUID as stable name, if available
115    std::string stableName = getId();
116    if (!mFsUuid.empty()) {
117        stableName = mFsUuid;
118    }
119
120    mRawPath = StringPrintf("/mnt/media_rw/%s", stableName.c_str());
121
122    mFuseDefault = StringPrintf("/mnt/runtime/default/%s", stableName.c_str());
123    mFuseRead = StringPrintf("/mnt/runtime/read/%s", stableName.c_str());
124    mFuseWrite = StringPrintf("/mnt/runtime/write/%s", stableName.c_str());
125
126    setInternalPath(mRawPath);
127    if (getMountFlags() & MountFlags::kVisible) {
128        setPath(StringPrintf("/storage/%s", stableName.c_str()));
129    } else {
130        setPath(mRawPath);
131    }
132
133    if (fs_prepare_dir(mRawPath.c_str(), 0700, AID_ROOT, AID_ROOT)) {
134        PLOG(ERROR) << getId() << " failed to create mount points";
135        return -errno;
136    }
137
138    if (mFsType == "vfat") {
139        if (vfat::Mount(mDevPath, mRawPath, false, false, false, AID_MEDIA_RW, AID_MEDIA_RW, 0007,
140                        true)) {
141            PLOG(ERROR) << getId() << " failed to mount " << mDevPath;
142            return -EIO;
143        }
144    } else if (mFsType == "exfat") {
145        if (exfat::Mount(mDevPath, mRawPath, AID_MEDIA_RW, AID_MEDIA_RW, 0007)) {
146            PLOG(ERROR) << getId() << " failed to mount " << mDevPath;
147            return -EIO;
148        }
149    }
150
151    if (getMountFlags() & MountFlags::kPrimary) {
152        initAsecStage();
153    }
154
155    if (!(getMountFlags() & MountFlags::kVisible)) {
156        // Not visible to apps, so no need to spin up FUSE
157        return OK;
158    }
159
160    if (fs_prepare_dir(mFuseDefault.c_str(), 0700, AID_ROOT, AID_ROOT) ||
161            fs_prepare_dir(mFuseRead.c_str(), 0700, AID_ROOT, AID_ROOT) ||
162            fs_prepare_dir(mFuseWrite.c_str(), 0700, AID_ROOT, AID_ROOT)) {
163        PLOG(ERROR) << getId() << " failed to create FUSE mount points";
164        return -errno;
165    }
166
167    dev_t before = GetDevice(mFuseWrite);
168
169    if (!(mFusePid = fork())) {
170        if (getMountFlags() & MountFlags::kPrimary) {
171            if (execl(kFusePath, kFusePath,
172                    "-u", "1023", // AID_MEDIA_RW
173                    "-g", "1023", // AID_MEDIA_RW
174                    "-U", std::to_string(getMountUserId()).c_str(),
175                    "-w",
176                    mRawPath.c_str(),
177                    stableName.c_str(),
178                    NULL)) {
179                PLOG(ERROR) << "Failed to exec";
180            }
181        } else {
182            if (execl(kFusePath, kFusePath,
183                    "-u", "1023", // AID_MEDIA_RW
184                    "-g", "1023", // AID_MEDIA_RW
185                    "-U", std::to_string(getMountUserId()).c_str(),
186                    mRawPath.c_str(),
187                    stableName.c_str(),
188                    NULL)) {
189                PLOG(ERROR) << "Failed to exec";
190            }
191        }
192
193        LOG(ERROR) << "FUSE exiting";
194        _exit(1);
195    }
196
197    if (mFusePid == -1) {
198        PLOG(ERROR) << getId() << " failed to fork";
199        return -errno;
200    }
201
202    nsecs_t start = systemTime(SYSTEM_TIME_BOOTTIME);
203    while (before == GetDevice(mFuseWrite)) {
204        LOG(VERBOSE) << "Waiting for FUSE to spin up...";
205        usleep(50000); // 50ms
206
207        nsecs_t now = systemTime(SYSTEM_TIME_BOOTTIME);
208        if (nanoseconds_to_milliseconds(now - start) > 5000) {
209            LOG(WARNING) << "Timed out while waiting for FUSE to spin up";
210            return -ETIMEDOUT;
211        }
212    }
213    /* sdcardfs will have exited already. FUSE will still be running */
214    if (TEMP_FAILURE_RETRY(waitpid(mFusePid, nullptr, WNOHANG)) == mFusePid)
215        mFusePid = 0;
216
217    return OK;
218}
219
220status_t PublicVolume::doUnmount() {
221    // Unmount the storage before we kill the FUSE process. If we kill
222    // the FUSE process first, most file system operations will return
223    // ENOTCONN until the unmount completes. This is an exotic and unusual
224    // error code and might cause broken behaviour in applications.
225    KillProcessesUsingPath(getPath());
226
227    ForceUnmount(kAsecPath);
228
229    ForceUnmount(mFuseDefault);
230    ForceUnmount(mFuseRead);
231    ForceUnmount(mFuseWrite);
232    ForceUnmount(mRawPath);
233
234    if (mFusePid > 0) {
235        kill(mFusePid, SIGTERM);
236        TEMP_FAILURE_RETRY(waitpid(mFusePid, nullptr, 0));
237        mFusePid = 0;
238    }
239
240    rmdir(mFuseDefault.c_str());
241    rmdir(mFuseRead.c_str());
242    rmdir(mFuseWrite.c_str());
243    rmdir(mRawPath.c_str());
244
245    mFuseDefault.clear();
246    mFuseRead.clear();
247    mFuseWrite.clear();
248    mRawPath.clear();
249
250    return OK;
251}
252
253status_t PublicVolume::doFormat(const std::string& fsType) {
254    if ((fsType == "vfat" || fsType == "auto") && vfat::IsSupported()) {
255        if (WipeBlockDevice(mDevPath) != OK) {
256            LOG(WARNING) << getId() << " failed to wipe";
257        }
258        if (vfat::Format(mDevPath, 0)) {
259            LOG(ERROR) << getId() << " failed to format";
260            return -errno;
261        }
262    } else if ((fsType == "exfat" || fsType == "auto") && exfat::IsSupported()) {
263        if (WipeBlockDevice(mDevPath) != OK) {
264            LOG(WARNING) << getId() << " failed to wipe";
265        }
266        if (exfat::Format(mDevPath)) {
267            LOG(ERROR) << getId() << " failed to format";
268            return -errno;
269        }
270    } else {
271        LOG(ERROR) << "Unsupported filesystem " << fsType;
272        return -EINVAL;
273    }
274
275    return OK;
276}
277
278}  // namespace vold
279}  // namespace android
280