1/*
2 * Copyright (C) 2008 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 <stdlib.h>
18#include <string.h>
19#include <dirent.h>
20#include <errno.h>
21#include <fcntl.h>
22
23#include <sys/types.h>
24#include <sys/stat.h>
25#include <sys/types.h>
26#include <sys/mman.h>
27#include <sys/mount.h>
28#include <sys/param.h>
29
30#include <linux/kdev_t.h>
31
32#include <cutils/properties.h>
33
34#include <diskconfig/diskconfig.h>
35
36#include <private/android_filesystem_config.h>
37
38#define LOG_TAG "Vold"
39
40#include <cutils/fs.h>
41#include <cutils/log.h>
42
43#include <string>
44
45#include "Volume.h"
46#include "VolumeManager.h"
47#include "ResponseCode.h"
48#include "Fat.h"
49#include "Process.h"
50#include "cryptfs.h"
51
52extern "C" void dos_partition_dec(void const *pp, struct dos_partition *d);
53extern "C" void dos_partition_enc(void *pp, struct dos_partition *d);
54
55
56/*
57 * Media directory - stuff that only media_rw user can see
58 */
59const char *Volume::MEDIA_DIR           = "/mnt/media_rw";
60
61/*
62 * Fuse directory - location where fuse wrapped filesystems go
63 */
64const char *Volume::FUSE_DIR           = "/storage";
65
66/*
67 * Path to external storage where *only* root can access ASEC image files
68 */
69const char *Volume::SEC_ASECDIR_EXT   = "/mnt/secure/asec";
70
71/*
72 * Path to internal storage where *only* root can access ASEC image files
73 */
74const char *Volume::SEC_ASECDIR_INT   = "/data/app-asec";
75
76/*
77 * Path to where secure containers are mounted
78 */
79const char *Volume::ASECDIR           = "/mnt/asec";
80
81/*
82 * Path to where OBBs are mounted
83 */
84const char *Volume::LOOPDIR           = "/mnt/obb";
85
86const char *Volume::BLKID_PATH = "/system/bin/blkid";
87
88static const char *stateToStr(int state) {
89    if (state == Volume::State_Init)
90        return "Initializing";
91    else if (state == Volume::State_NoMedia)
92        return "No-Media";
93    else if (state == Volume::State_Idle)
94        return "Idle-Unmounted";
95    else if (state == Volume::State_Pending)
96        return "Pending";
97    else if (state == Volume::State_Mounted)
98        return "Mounted";
99    else if (state == Volume::State_Unmounting)
100        return "Unmounting";
101    else if (state == Volume::State_Checking)
102        return "Checking";
103    else if (state == Volume::State_Formatting)
104        return "Formatting";
105    else if (state == Volume::State_Shared)
106        return "Shared-Unmounted";
107    else if (state == Volume::State_SharedMnt)
108        return "Shared-Mounted";
109    else
110        return "Unknown-Error";
111}
112
113Volume::Volume(VolumeManager *vm, const fstab_rec* rec, int flags) {
114    mVm = vm;
115    mDebug = false;
116    mLabel = strdup(rec->label);
117    mUuid = NULL;
118    mUserLabel = NULL;
119    mState = Volume::State_Init;
120    mFlags = flags;
121    mCurrentlyMountedKdev = -1;
122    mPartIdx = rec->partnum;
123    mRetryMount = false;
124}
125
126Volume::~Volume() {
127    free(mLabel);
128    free(mUuid);
129    free(mUserLabel);
130}
131
132void Volume::setDebug(bool enable) {
133    mDebug = enable;
134}
135
136dev_t Volume::getDiskDevice() {
137    return MKDEV(0, 0);
138};
139
140dev_t Volume::getShareDevice() {
141    return getDiskDevice();
142}
143
144void Volume::handleVolumeShared() {
145}
146
147void Volume::handleVolumeUnshared() {
148}
149
150int Volume::handleBlockEvent(NetlinkEvent * /*evt*/) {
151    errno = ENOSYS;
152    return -1;
153}
154
155void Volume::setUuid(const char* uuid) {
156    char msg[256];
157
158    if (mUuid) {
159        free(mUuid);
160    }
161
162    if (uuid) {
163        mUuid = strdup(uuid);
164        snprintf(msg, sizeof(msg), "%s %s \"%s\"", getLabel(),
165                getFuseMountpoint(), mUuid);
166    } else {
167        mUuid = NULL;
168        snprintf(msg, sizeof(msg), "%s %s", getLabel(), getFuseMountpoint());
169    }
170
171    mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeUuidChange, msg,
172            false);
173}
174
175void Volume::setUserLabel(const char* userLabel) {
176    char msg[256];
177
178    if (mUserLabel) {
179        free(mUserLabel);
180    }
181
182    if (userLabel) {
183        mUserLabel = strdup(userLabel);
184        snprintf(msg, sizeof(msg), "%s %s \"%s\"", getLabel(),
185                getFuseMountpoint(), mUserLabel);
186    } else {
187        mUserLabel = NULL;
188        snprintf(msg, sizeof(msg), "%s %s", getLabel(), getFuseMountpoint());
189    }
190
191    mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeUserLabelChange,
192            msg, false);
193}
194
195void Volume::setState(int state) {
196    char msg[255];
197    int oldState = mState;
198
199    if (oldState == state) {
200        SLOGW("Duplicate state (%d)\n", state);
201        return;
202    }
203
204    if ((oldState == Volume::State_Pending) && (state != Volume::State_Idle)) {
205        mRetryMount = false;
206    }
207
208    mState = state;
209
210    SLOGD("Volume %s state changing %d (%s) -> %d (%s)", mLabel,
211         oldState, stateToStr(oldState), mState, stateToStr(mState));
212    snprintf(msg, sizeof(msg),
213             "Volume %s %s state changed from %d (%s) to %d (%s)", getLabel(),
214             getFuseMountpoint(), oldState, stateToStr(oldState), mState,
215             stateToStr(mState));
216
217    mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeStateChange,
218                                         msg, false);
219}
220
221int Volume::createDeviceNode(const char *path, int major, int minor) {
222    mode_t mode = 0660 | S_IFBLK;
223    dev_t dev = (major << 8) | minor;
224    if (mknod(path, mode, dev) < 0) {
225        if (errno != EEXIST) {
226            return -1;
227        }
228    }
229    return 0;
230}
231
232int Volume::formatVol(bool wipe) {
233
234    if (getState() == Volume::State_NoMedia) {
235        errno = ENODEV;
236        return -1;
237    } else if (getState() != Volume::State_Idle) {
238        errno = EBUSY;
239        return -1;
240    }
241
242    if (isMountpointMounted(getMountpoint())) {
243        SLOGW("Volume is idle but appears to be mounted - fixing");
244        setState(Volume::State_Mounted);
245        // mCurrentlyMountedKdev = XXX
246        errno = EBUSY;
247        return -1;
248    }
249
250    bool formatEntireDevice = (mPartIdx == -1);
251    char devicePath[255];
252    dev_t diskNode = getDiskDevice();
253    dev_t partNode =
254        MKDEV(MAJOR(diskNode),
255              MINOR(diskNode) + (formatEntireDevice ? 1 : mPartIdx));
256
257    setState(Volume::State_Formatting);
258
259    int ret = -1;
260    // Only initialize the MBR if we are formatting the entire device
261    if (formatEntireDevice) {
262        sprintf(devicePath, "/dev/block/vold/%d:%d",
263                major(diskNode), minor(diskNode));
264
265        if (initializeMbr(devicePath)) {
266            SLOGE("Failed to initialize MBR (%s)", strerror(errno));
267            goto err;
268        }
269    }
270
271    sprintf(devicePath, "/dev/block/vold/%d:%d",
272            major(partNode), minor(partNode));
273
274    if (mDebug) {
275        SLOGI("Formatting volume %s (%s)", getLabel(), devicePath);
276    }
277
278    if (Fat::format(devicePath, 0, wipe)) {
279        SLOGE("Failed to format (%s)", strerror(errno));
280        goto err;
281    }
282
283    ret = 0;
284
285err:
286    setState(Volume::State_Idle);
287    return ret;
288}
289
290bool Volume::isMountpointMounted(const char *path) {
291    char device[256];
292    char mount_path[256];
293    char rest[256];
294    FILE *fp;
295    char line[1024];
296
297    if (!(fp = fopen("/proc/mounts", "r"))) {
298        SLOGE("Error opening /proc/mounts (%s)", strerror(errno));
299        return false;
300    }
301
302    while(fgets(line, sizeof(line), fp)) {
303        line[strlen(line)-1] = '\0';
304        sscanf(line, "%255s %255s %255s\n", device, mount_path, rest);
305        if (!strcmp(mount_path, path)) {
306            fclose(fp);
307            return true;
308        }
309    }
310
311    fclose(fp);
312    return false;
313}
314
315int Volume::mountVol() {
316    dev_t deviceNodes[4];
317    int n, i, rc = 0;
318    char errmsg[255];
319
320    int flags = getFlags();
321    bool providesAsec = (flags & VOL_PROVIDES_ASEC) != 0;
322
323    // TODO: handle "bind" style mounts, for emulated storage
324
325    char decrypt_state[PROPERTY_VALUE_MAX];
326    char crypto_state[PROPERTY_VALUE_MAX];
327    char encrypt_progress[PROPERTY_VALUE_MAX];
328
329    property_get("vold.decrypt", decrypt_state, "");
330    property_get("vold.encrypt_progress", encrypt_progress, "");
331
332    /* Don't try to mount the volumes if we have not yet entered the disk password
333     * or are in the process of encrypting.
334     */
335    if ((getState() == Volume::State_NoMedia) ||
336        ((!strcmp(decrypt_state, "1") || encrypt_progress[0]) && providesAsec)) {
337        snprintf(errmsg, sizeof(errmsg),
338                 "Volume %s %s mount failed - no media",
339                 getLabel(), getFuseMountpoint());
340        mVm->getBroadcaster()->sendBroadcast(
341                                         ResponseCode::VolumeMountFailedNoMedia,
342                                         errmsg, false);
343        errno = ENODEV;
344        return -1;
345    } else if (getState() != Volume::State_Idle) {
346        errno = EBUSY;
347        if (getState() == Volume::State_Pending) {
348            mRetryMount = true;
349        }
350        return -1;
351    }
352
353    if (isMountpointMounted(getMountpoint())) {
354        SLOGW("Volume is idle but appears to be mounted - fixing");
355        setState(Volume::State_Mounted);
356        // mCurrentlyMountedKdev = XXX
357        return 0;
358    }
359
360    n = getDeviceNodes((dev_t *) &deviceNodes, 4);
361    if (!n) {
362        SLOGE("Failed to get device nodes (%s)\n", strerror(errno));
363        return -1;
364    }
365
366    /* If we're running encrypted, and the volume is marked as encryptable and nonremovable,
367     * and also marked as providing Asec storage, then we need to decrypt
368     * that partition, and update the volume object to point to it's new decrypted
369     * block device
370     */
371    property_get("ro.crypto.state", crypto_state, "");
372    if (providesAsec &&
373        ((flags & (VOL_NONREMOVABLE | VOL_ENCRYPTABLE))==(VOL_NONREMOVABLE | VOL_ENCRYPTABLE)) &&
374        !strcmp(crypto_state, "encrypted") && !isDecrypted()) {
375       char new_sys_path[MAXPATHLEN];
376       char nodepath[256];
377       int new_major, new_minor;
378
379       if (n != 1) {
380           /* We only expect one device node returned when mounting encryptable volumes */
381           SLOGE("Too many device nodes returned when mounting %s\n", getMountpoint());
382           return -1;
383       }
384
385       if (cryptfs_setup_volume(getLabel(), MAJOR(deviceNodes[0]), MINOR(deviceNodes[0]),
386                                new_sys_path, sizeof(new_sys_path),
387                                &new_major, &new_minor)) {
388           SLOGE("Cannot setup encryption mapping for %s\n", getMountpoint());
389           return -1;
390       }
391       /* We now have the new sysfs path for the decrypted block device, and the
392        * majore and minor numbers for it.  So, create the device, update the
393        * path to the new sysfs path, and continue.
394        */
395        snprintf(nodepath,
396                 sizeof(nodepath), "/dev/block/vold/%d:%d",
397                 new_major, new_minor);
398        if (createDeviceNode(nodepath, new_major, new_minor)) {
399            SLOGE("Error making device node '%s' (%s)", nodepath,
400                                                       strerror(errno));
401        }
402
403        // Todo: Either create sys filename from nodepath, or pass in bogus path so
404        //       vold ignores state changes on this internal device.
405        updateDeviceInfo(nodepath, new_major, new_minor);
406
407        /* Get the device nodes again, because they just changed */
408        n = getDeviceNodes((dev_t *) &deviceNodes, 4);
409        if (!n) {
410            SLOGE("Failed to get device nodes (%s)\n", strerror(errno));
411            return -1;
412        }
413    }
414
415    for (i = 0; i < n; i++) {
416        char devicePath[255];
417
418        sprintf(devicePath, "/dev/block/vold/%d:%d", major(deviceNodes[i]),
419                minor(deviceNodes[i]));
420
421        SLOGI("%s being considered for volume %s\n", devicePath, getLabel());
422
423        errno = 0;
424        setState(Volume::State_Checking);
425
426        if (Fat::check(devicePath)) {
427            if (errno == ENODATA) {
428                SLOGW("%s does not contain a FAT filesystem\n", devicePath);
429                continue;
430            }
431            errno = EIO;
432            /* Badness - abort the mount */
433            SLOGE("%s failed FS checks (%s)", devicePath, strerror(errno));
434            setState(Volume::State_Idle);
435            return -1;
436        }
437
438        errno = 0;
439        int gid;
440
441        if (Fat::doMount(devicePath, getMountpoint(), false, false, false,
442                AID_MEDIA_RW, AID_MEDIA_RW, 0007, true)) {
443            SLOGE("%s failed to mount via VFAT (%s)\n", devicePath, strerror(errno));
444            continue;
445        }
446
447        extractMetadata(devicePath);
448
449        if (providesAsec && mountAsecExternal() != 0) {
450            SLOGE("Failed to mount secure area (%s)", strerror(errno));
451            umount(getMountpoint());
452            setState(Volume::State_Idle);
453            return -1;
454        }
455
456        char service[64];
457        snprintf(service, 64, "fuse_%s", getLabel());
458        property_set("ctl.start", service);
459
460        setState(Volume::State_Mounted);
461        mCurrentlyMountedKdev = deviceNodes[i];
462        return 0;
463    }
464
465    SLOGE("Volume %s found no suitable devices for mounting :(\n", getLabel());
466    setState(Volume::State_Idle);
467
468    return -1;
469}
470
471int Volume::mountAsecExternal() {
472    char legacy_path[PATH_MAX];
473    char secure_path[PATH_MAX];
474
475    snprintf(legacy_path, PATH_MAX, "%s/android_secure", getMountpoint());
476    snprintf(secure_path, PATH_MAX, "%s/.android_secure", getMountpoint());
477
478    // Recover legacy secure path
479    if (!access(legacy_path, R_OK | X_OK) && access(secure_path, R_OK | X_OK)) {
480        if (rename(legacy_path, secure_path)) {
481            SLOGE("Failed to rename legacy asec dir (%s)", strerror(errno));
482        }
483    }
484
485    if (fs_prepare_dir(secure_path, 0770, AID_MEDIA_RW, AID_MEDIA_RW) != 0) {
486        SLOGW("fs_prepare_dir failed: %s", strerror(errno));
487        return -1;
488    }
489
490    if (mount(secure_path, SEC_ASECDIR_EXT, "", MS_BIND, NULL)) {
491        SLOGE("Failed to bind mount points %s -> %s (%s)", secure_path,
492                SEC_ASECDIR_EXT, strerror(errno));
493        return -1;
494    }
495
496    return 0;
497}
498
499int Volume::doUnmount(const char *path, bool force) {
500    int retries = 10;
501
502    if (mDebug) {
503        SLOGD("Unmounting {%s}, force = %d", path, force);
504    }
505
506    while (retries--) {
507        if (!umount(path) || errno == EINVAL || errno == ENOENT) {
508            SLOGI("%s sucessfully unmounted", path);
509            return 0;
510        }
511
512        int action = 0;
513
514        if (force) {
515            if (retries == 1) {
516                action = 2; // SIGKILL
517            } else if (retries == 2) {
518                action = 1; // SIGHUP
519            }
520        }
521
522        SLOGW("Failed to unmount %s (%s, retries %d, action %d)",
523                path, strerror(errno), retries, action);
524
525        Process::killProcessesWithOpenFiles(path, action);
526        usleep(1000*1000);
527    }
528    errno = EBUSY;
529    SLOGE("Giving up on unmount %s (%s)", path, strerror(errno));
530    return -1;
531}
532
533int Volume::unmountVol(bool force, bool revert) {
534    int i, rc;
535
536    int flags = getFlags();
537    bool providesAsec = (flags & VOL_PROVIDES_ASEC) != 0;
538
539    if (getState() != Volume::State_Mounted) {
540        SLOGE("Volume %s unmount request when not mounted", getLabel());
541        errno = EINVAL;
542        return UNMOUNT_NOT_MOUNTED_ERR;
543    }
544
545    setState(Volume::State_Unmounting);
546    usleep(1000 * 1000); // Give the framework some time to react
547
548    char service[64];
549    snprintf(service, 64, "fuse_%s", getLabel());
550    property_set("ctl.stop", service);
551    /* Give it a chance to stop.  I wish we had a synchronous way to determine this... */
552    sleep(1);
553
554    // TODO: determine failure mode if FUSE times out
555
556    if (providesAsec && doUnmount(Volume::SEC_ASECDIR_EXT, force) != 0) {
557        SLOGE("Failed to unmount secure area on %s (%s)", getMountpoint(), strerror(errno));
558        goto out_mounted;
559    }
560
561    /* Now that the fuse daemon is dead, unmount it */
562    if (doUnmount(getFuseMountpoint(), force) != 0) {
563        SLOGE("Failed to unmount %s (%s)", getFuseMountpoint(), strerror(errno));
564        goto fail_remount_secure;
565    }
566
567    /* Unmount the real sd card */
568    if (doUnmount(getMountpoint(), force) != 0) {
569        SLOGE("Failed to unmount %s (%s)", getMountpoint(), strerror(errno));
570        goto fail_remount_secure;
571    }
572
573    SLOGI("%s unmounted successfully", getMountpoint());
574
575    /* If this is an encrypted volume, and we've been asked to undo
576     * the crypto mapping, then revert the dm-crypt mapping, and revert
577     * the device info to the original values.
578     */
579    if (revert && isDecrypted()) {
580        cryptfs_revert_volume(getLabel());
581        revertDeviceInfo();
582        SLOGI("Encrypted volume %s reverted successfully", getMountpoint());
583    }
584
585    setUuid(NULL);
586    setUserLabel(NULL);
587    setState(Volume::State_Idle);
588    mCurrentlyMountedKdev = -1;
589    return 0;
590
591fail_remount_secure:
592    if (providesAsec && mountAsecExternal() != 0) {
593        SLOGE("Failed to remount secure area (%s)", strerror(errno));
594        goto out_nomedia;
595    }
596
597out_mounted:
598    setState(Volume::State_Mounted);
599    return -1;
600
601out_nomedia:
602    setState(Volume::State_NoMedia);
603    return -1;
604}
605
606int Volume::initializeMbr(const char *deviceNode) {
607    struct disk_info dinfo;
608
609    memset(&dinfo, 0, sizeof(dinfo));
610
611    if (!(dinfo.part_lst = (struct part_info *) malloc(MAX_NUM_PARTS * sizeof(struct part_info)))) {
612        SLOGE("Failed to malloc prt_lst");
613        return -1;
614    }
615
616    memset(dinfo.part_lst, 0, MAX_NUM_PARTS * sizeof(struct part_info));
617    dinfo.device = strdup(deviceNode);
618    dinfo.scheme = PART_SCHEME_MBR;
619    dinfo.sect_size = 512;
620    dinfo.skip_lba = 2048;
621    dinfo.num_lba = 0;
622    dinfo.num_parts = 1;
623
624    struct part_info *pinfo = &dinfo.part_lst[0];
625
626    pinfo->name = strdup("android_sdcard");
627    pinfo->flags |= PART_ACTIVE_FLAG;
628    pinfo->type = PC_PART_TYPE_FAT32;
629    pinfo->len_kb = -1;
630
631    int rc = apply_disk_config(&dinfo, 0);
632
633    if (rc) {
634        SLOGE("Failed to apply disk configuration (%d)", rc);
635        goto out;
636    }
637
638 out:
639    free(pinfo->name);
640    free(dinfo.device);
641    free(dinfo.part_lst);
642
643    return rc;
644}
645
646/*
647 * Use blkid to extract UUID and label from device, since it handles many
648 * obscure edge cases around partition types and formats. Always broadcasts
649 * updated metadata values.
650 */
651int Volume::extractMetadata(const char* devicePath) {
652    int res = 0;
653
654    std::string cmd;
655    cmd = BLKID_PATH;
656    cmd += " -c /dev/null ";
657    cmd += devicePath;
658
659    FILE* fp = popen(cmd.c_str(), "r");
660    if (!fp) {
661        ALOGE("Failed to run %s: %s", cmd.c_str(), strerror(errno));
662        res = -1;
663        goto done;
664    }
665
666    char line[1024];
667    char value[128];
668    if (fgets(line, sizeof(line), fp) != NULL) {
669        ALOGD("blkid identified as %s", line);
670
671        char* start = strstr(line, "UUID=");
672        if (start != NULL && sscanf(start + 5, "\"%127[^\"]\"", value) == 1) {
673            setUuid(value);
674        } else {
675            setUuid(NULL);
676        }
677
678        start = strstr(line, "LABEL=");
679        if (start != NULL && sscanf(start + 6, "\"%127[^\"]\"", value) == 1) {
680            setUserLabel(value);
681        } else {
682            setUserLabel(NULL);
683        }
684    } else {
685        ALOGW("blkid failed to identify %s", devicePath);
686        res = -1;
687    }
688
689    pclose(fp);
690
691done:
692    if (res == -1) {
693        setUuid(NULL);
694        setUserLabel(NULL);
695    }
696    return res;
697}
698