1f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat/*
2f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * Copyright (C) 2008 The Android Open Source Project
3f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat *
4f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * Licensed under the Apache License, Version 2.0 (the "License");
5f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * you may not use this file except in compliance with the License.
6f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * You may obtain a copy of the License at
7f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat *
8f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat *      http://www.apache.org/licenses/LICENSE-2.0
9f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat *
10f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * Unless required by applicable law or agreed to in writing, software
11f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * distributed under the License is distributed on an "AS IS" BASIS,
12f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * See the License for the specific language governing permissions and
14f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * limitations under the License.
15f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat */
16f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
17d1104f75a736210a95ba890473d78e8dfc8b8915Yabin Cui#include <dirent.h>
18f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#include <errno.h>
19a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#include <fcntl.h>
20344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root#include <fts.h>
21d1104f75a736210a95ba890473d78e8dfc8b8915Yabin Cui#include <mntent.h>
22d1104f75a736210a95ba890473d78e8dfc8b8915Yabin Cui#include <stdio.h>
23d1104f75a736210a95ba890473d78e8dfc8b8915Yabin Cui#include <stdlib.h>
24d1104f75a736210a95ba890473d78e8dfc8b8915Yabin Cui#include <string.h>
25d1104f75a736210a95ba890473d78e8dfc8b8915Yabin Cui#include <sys/ioctl.h>
26d1104f75a736210a95ba890473d78e8dfc8b8915Yabin Cui#include <sys/mount.h>
27a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat#include <sys/stat.h>
28a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat#include <sys/types.h>
2966270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey#include <sys/wait.h>
30d1104f75a736210a95ba890473d78e8dfc8b8915Yabin Cui#include <unistd.h>
31a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
32a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#include <linux/kdev_t.h>
33f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
34f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#define LOG_TAG "Vold"
35f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
367b18a7b36f61574c0f0bdde0a7409dc36676fa12Kenny Root#include <openssl/md5.h>
377b18a7b36f61574c0f0bdde0a7409dc36676fa12Kenny Root
3836801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey#include <base/logging.h>
3936801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey#include <base/stringprintf.h>
4071ebe154a5fbbb4b394a439ff0b6b9c84fbd04f5Jeff Sharkey#include <cutils/fs.h>
41f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#include <cutils/log.h>
42f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
43b9e3ba56cb4075f894a73b02ee70571456494ac1Robert Craig#include <selinux/android.h>
44b9e3ba56cb4075f894a73b02ee70571456494ac1Robert Craig
45fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat#include <sysutils/NetlinkEvent.h>
46fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat
47344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root#include <private/android_filesystem_config.h>
48344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
495a6bfca1638760b87cf64c5ffb48ff3557cc0563Jeff Sharkey#include "Benchmark.h"
5036801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey#include "EmulatedVolume.h"
51f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#include "VolumeManager.h"
5236801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey#include "NetlinkManager.h"
53a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#include "ResponseCode.h"
54a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat#include "Loop.h"
55d0640f6358041f7e2657167560b357078db73526Jeff Sharkey#include "fs/Ext4.h"
56d0640f6358041f7e2657167560b357078db73526Jeff Sharkey#include "fs/Vfat.h"
5736801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey#include "Utils.h"
58b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat#include "Devmapper.h"
59586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat#include "Process.h"
60fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat#include "Asec.h"
6114eab550e8a4f28889cc9ffbb92ddff8f18c4f03Hiroaki Miyazawa#include "VoldUtil.h"
6229d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall#include "cryptfs.h"
6323969931fad6e993832208f099f6eea0f6f76eb5San Mehat
6497f2fc110b2ace7914671c2f5852379bd78922e4Mike Lockwood#define MASS_STORAGE_FILE_PATH  "/sys/class/android_usb/android0/f_mass_storage/lun/file"
6597f2fc110b2ace7914671c2f5852379bd78922e4Mike Lockwood
666a74dcaa6e646fea8e00b7c04332fc60fe7e017cDaniel Rosenberg#define ROUND_UP_POWER_OF_2(number, po2) (((!!(number & ((1U << po2) - 1))) << po2)\
676a74dcaa6e646fea8e00b7c04332fc60fe7e017cDaniel Rosenberg                                         + (number & (~((1U << po2) - 1))))
686a74dcaa6e646fea8e00b7c04332fc60fe7e017cDaniel Rosenberg
6936801cccf27152c9eca5aab6ba3527221525110fJeff Sharkeyusing android::base::StringPrintf;
7036801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey
719f18fe7807a4e4089778243dbbd08d154ec15540Jeff Sharkey/*
729f18fe7807a4e4089778243dbbd08d154ec15540Jeff Sharkey * Path to external storage where *only* root can access ASEC image files
739f18fe7807a4e4089778243dbbd08d154ec15540Jeff Sharkey */
749f18fe7807a4e4089778243dbbd08d154ec15540Jeff Sharkeyconst char *VolumeManager::SEC_ASECDIR_EXT   = "/mnt/secure/asec";
759f18fe7807a4e4089778243dbbd08d154ec15540Jeff Sharkey
769f18fe7807a4e4089778243dbbd08d154ec15540Jeff Sharkey/*
779f18fe7807a4e4089778243dbbd08d154ec15540Jeff Sharkey * Path to internal storage where *only* root can access ASEC image files
789f18fe7807a4e4089778243dbbd08d154ec15540Jeff Sharkey */
799f18fe7807a4e4089778243dbbd08d154ec15540Jeff Sharkeyconst char *VolumeManager::SEC_ASECDIR_INT   = "/data/app-asec";
809f18fe7807a4e4089778243dbbd08d154ec15540Jeff Sharkey
819f18fe7807a4e4089778243dbbd08d154ec15540Jeff Sharkey/*
829f18fe7807a4e4089778243dbbd08d154ec15540Jeff Sharkey * Path to where secure containers are mounted
839f18fe7807a4e4089778243dbbd08d154ec15540Jeff Sharkey */
849f18fe7807a4e4089778243dbbd08d154ec15540Jeff Sharkeyconst char *VolumeManager::ASECDIR           = "/mnt/asec";
859f18fe7807a4e4089778243dbbd08d154ec15540Jeff Sharkey
869f18fe7807a4e4089778243dbbd08d154ec15540Jeff Sharkey/*
879f18fe7807a4e4089778243dbbd08d154ec15540Jeff Sharkey * Path to where OBBs are mounted
889f18fe7807a4e4089778243dbbd08d154ec15540Jeff Sharkey */
899f18fe7807a4e4089778243dbbd08d154ec15540Jeff Sharkeyconst char *VolumeManager::LOOPDIR           = "/mnt/obb";
909f18fe7807a4e4089778243dbbd08d154ec15540Jeff Sharkey
9136801cccf27152c9eca5aab6ba3527221525110fJeff Sharkeystatic const char* kUserMountPath = "/mnt/user";
9236801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey
9336801cccf27152c9eca5aab6ba3527221525110fJeff Sharkeystatic const unsigned int kMajorBlockMmc = 179;
9436801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey
95fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg/* writes superblock at end of file or device given by name */
96fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenbergstatic int writeSuperBlock(const char* name, struct asec_superblock *sb, unsigned int numImgSectors) {
97ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey    int sbfd = open(name, O_RDWR | O_CLOEXEC);
98fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    if (sbfd < 0) {
99fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        SLOGE("Failed to open %s for superblock write (%s)", name, strerror(errno));
100fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        return -1;
101fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    }
102fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg
103fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    if (lseek(sbfd, (numImgSectors * 512), SEEK_SET) < 0) {
104fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        SLOGE("Failed to lseek for superblock (%s)", strerror(errno));
105fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        close(sbfd);
106fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        return -1;
107fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    }
108fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg
109fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    if (write(sbfd, sb, sizeof(struct asec_superblock)) != sizeof(struct asec_superblock)) {
110fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        SLOGE("Failed to write superblock (%s)", strerror(errno));
111fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        close(sbfd);
112fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        return -1;
113fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    }
114fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    close(sbfd);
115fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    return 0;
116fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg}
117fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg
118fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenbergstatic int adjustSectorNumExt4(unsigned numSectors) {
119e9196fecbb08ead0b5dcdf1b38b81a0419c24bf4Daniel Rosenberg    // Ext4 started to reserve 2% or 4096 clusters, whichever is smaller for
120e9196fecbb08ead0b5dcdf1b38b81a0419c24bf4Daniel Rosenberg    // preventing costly operations or unexpected ENOSPC error.
121e9196fecbb08ead0b5dcdf1b38b81a0419c24bf4Daniel Rosenberg    // Ext4::format() uses default block size without clustering.
122e9196fecbb08ead0b5dcdf1b38b81a0419c24bf4Daniel Rosenberg    unsigned clusterSectors = 4096 / 512;
123e9196fecbb08ead0b5dcdf1b38b81a0419c24bf4Daniel Rosenberg    unsigned reservedSectors = (numSectors * 2)/100 + (numSectors % 50 > 0);
124e9196fecbb08ead0b5dcdf1b38b81a0419c24bf4Daniel Rosenberg    numSectors += reservedSectors > (4096 * clusterSectors) ? (4096 * clusterSectors) : reservedSectors;
125fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    return ROUND_UP_POWER_OF_2(numSectors, 3);
126fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg}
127fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg
128fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenbergstatic int adjustSectorNumFAT(unsigned numSectors) {
129fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    /*
130fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    * Add some headroom
131fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    */
132fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    unsigned fatSize = (((numSectors * 4) / 512) + 1) * 2;
133fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    numSectors += fatSize + 2;
134fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    /*
135fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    * FAT is aligned to 32 kb with 512b sectors.
136fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    */
137fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    return ROUND_UP_POWER_OF_2(numSectors, 6);
138fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg}
139fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg
140fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenbergstatic int setupLoopDevice(char* buffer, size_t len, const char* asecFileName, const char* idHash, bool debug) {
141fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    if (Loop::lookupActive(idHash, buffer, len)) {
142fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        if (Loop::create(idHash, asecFileName, buffer, len)) {
143fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg            SLOGE("ASEC loop device creation failed for %s (%s)", asecFileName, strerror(errno));
144fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg            return -1;
145fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        }
146fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        if (debug) {
147fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg            SLOGD("New loop device created at %s", buffer);
148fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        }
149fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    } else {
150fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        if (debug) {
151fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg            SLOGD("Found active loopback for %s at %s", asecFileName, buffer);
152fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        }
153fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    }
154fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    return 0;
155fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg}
156fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg
157fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenbergstatic int setupDevMapperDevice(char* buffer, size_t len, const char* loopDevice, const char* asecFileName, const char* key, const char* idHash , int numImgSectors, bool* createdDMDevice, bool debug) {
158fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    if (strcmp(key, "none")) {
159fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        if (Devmapper::lookupActive(idHash, buffer, len)) {
160fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg            if (Devmapper::create(idHash, loopDevice, key, numImgSectors,
161fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg                                  buffer, len)) {
162fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg                SLOGE("ASEC device mapping failed for %s (%s)", asecFileName, strerror(errno));
163fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg                return -1;
164fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg            }
165fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg            if (debug) {
166fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg                SLOGD("New devmapper instance created at %s", buffer);
167fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg            }
168fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        } else {
169fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg            if (debug) {
170fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg                SLOGD("Found active devmapper for %s at %s", asecFileName, buffer);
171fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg            }
172fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        }
173fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        *createdDMDevice = true;
174fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    } else {
175fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        strcpy(buffer, loopDevice);
176fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        *createdDMDevice = false;
177fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    }
178fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    return 0;
179fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg}
180fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg
181fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenbergstatic void waitForDevMapper(const char *dmDevice) {
182fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    /*
183fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg     * Wait for the device mapper node to be created. Sometimes it takes a
184fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg     * while. Wait for up to 1 second. We could also inspect incoming uevents,
185fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg     * but that would take more effort.
186fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg     */
187fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    int tries = 25;
188fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    while (tries--) {
189fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        if (!access(dmDevice, F_OK) || errno != ENOENT) {
190fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg            break;
191fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        }
192fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        usleep(40 * 1000);
193fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    }
194fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg}
195fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg
196f1b736bc5605e92e917ab27f5abf3ba839be2270San MehatVolumeManager *VolumeManager::sInstance = NULL;
197f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
198f1b736bc5605e92e917ab27f5abf3ba839be2270San MehatVolumeManager *VolumeManager::Instance() {
199f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    if (!sInstance)
200f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat        sInstance = new VolumeManager();
201f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    return sInstance;
202f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
203f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
204f1b736bc5605e92e917ab27f5abf3ba839be2270San MehatVolumeManager::VolumeManager() {
205d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    mDebug = false;
20688705166ab82057090a070c6d4200c3d9db76f11San Mehat    mActiveContainers = new AsecIdCollection();
207f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    mBroadcaster = NULL;
208a28056b38275003895ff5d9576681aca01544822Mike Lockwood    mUmsSharingCount = 0;
209a28056b38275003895ff5d9576681aca01544822Mike Lockwood    mSavedDirtyRatio = -1;
210a28056b38275003895ff5d9576681aca01544822Mike Lockwood    // set dirty ratio to 0 when UMS is active
211a28056b38275003895ff5d9576681aca01544822Mike Lockwood    mUmsDirtyRatio = 0;
212f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
213f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
214f1b736bc5605e92e917ab27f5abf3ba839be2270San MehatVolumeManager::~VolumeManager() {
21588705166ab82057090a070c6d4200c3d9db76f11San Mehat    delete mActiveContainers;
216f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
217f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
218d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehatchar *VolumeManager::asecHash(const char *id, char *buffer, size_t len) {
219acc9e7dcca8978fc809fa5b4d9b819c515a980ffKenny Root    static const char* digits = "0123456789abcdef";
220acc9e7dcca8978fc809fa5b4d9b819c515a980ffKenny Root
2217b18a7b36f61574c0f0bdde0a7409dc36676fa12Kenny Root    unsigned char sig[MD5_DIGEST_LENGTH];
222d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat
223acc9e7dcca8978fc809fa5b4d9b819c515a980ffKenny Root    if (buffer == NULL) {
224acc9e7dcca8978fc809fa5b4d9b819c515a980ffKenny Root        SLOGE("Destination buffer is NULL");
225acc9e7dcca8978fc809fa5b4d9b819c515a980ffKenny Root        errno = ESPIPE;
226acc9e7dcca8978fc809fa5b4d9b819c515a980ffKenny Root        return NULL;
227acc9e7dcca8978fc809fa5b4d9b819c515a980ffKenny Root    } else if (id == NULL) {
228acc9e7dcca8978fc809fa5b4d9b819c515a980ffKenny Root        SLOGE("Source buffer is NULL");
229acc9e7dcca8978fc809fa5b4d9b819c515a980ffKenny Root        errno = ESPIPE;
230acc9e7dcca8978fc809fa5b4d9b819c515a980ffKenny Root        return NULL;
231acc9e7dcca8978fc809fa5b4d9b819c515a980ffKenny Root    } else if (len < MD5_ASCII_LENGTH_PLUS_NULL) {
23259846b654e8b4a22a1be11cd21d6c5b81375abd2Colin Cross        SLOGE("Target hash buffer size < %d bytes (%zu)",
233acc9e7dcca8978fc809fa5b4d9b819c515a980ffKenny Root                MD5_ASCII_LENGTH_PLUS_NULL, len);
234d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        errno = ESPIPE;
235d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        return NULL;
236d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    }
2377b18a7b36f61574c0f0bdde0a7409dc36676fa12Kenny Root
2387b18a7b36f61574c0f0bdde0a7409dc36676fa12Kenny Root    MD5(reinterpret_cast<const unsigned char*>(id), strlen(id), sig);
239d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat
240acc9e7dcca8978fc809fa5b4d9b819c515a980ffKenny Root    char *p = buffer;
2417b18a7b36f61574c0f0bdde0a7409dc36676fa12Kenny Root    for (int i = 0; i < MD5_DIGEST_LENGTH; i++) {
242acc9e7dcca8978fc809fa5b4d9b819c515a980ffKenny Root        *p++ = digits[sig[i] >> 4];
243acc9e7dcca8978fc809fa5b4d9b819c515a980ffKenny Root        *p++ = digits[sig[i] & 0x0F];
244d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    }
245acc9e7dcca8978fc809fa5b4d9b819c515a980ffKenny Root    *p = '\0';
246d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat
247d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    return buffer;
248d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat}
249d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat
250f1b996df6f8283aac6953b22bd9e2496d8c30c86Jeff Sharkeyint VolumeManager::setDebug(bool enable) {
251d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    mDebug = enable;
252f1b996df6f8283aac6953b22bd9e2496d8c30c86Jeff Sharkey    return 0;
253d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat}
254d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat
255f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehatint VolumeManager::start() {
25636801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    // Always start from a clean slate by unmounting everything in
25736801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    // directories that we own, in case we crashed.
2589c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    unmountAll();
25936801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey
26036801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    // Assume that we always have an emulated volume on internal
26136801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    // storage; the framework will decide if it should be mounted.
262c8e04c5a8285de07d2c84bfbda8eda2c14a9457dJeff Sharkey    CHECK(mInternalEmulated == nullptr);
26336801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    mInternalEmulated = std::shared_ptr<android::vold::VolumeBase>(
2643161fb3702830b586b2e36fa9ca4519f59f951b4Jeff Sharkey            new android::vold::EmulatedVolume("/data/media"));
26536801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    mInternalEmulated->create();
26636801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey
267f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    return 0;
268f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
269f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
270f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehatint VolumeManager::stop() {
271c8e04c5a8285de07d2c84bfbda8eda2c14a9457dJeff Sharkey    CHECK(mInternalEmulated != nullptr);
27236801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    mInternalEmulated->destroy();
27336801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    mInternalEmulated = nullptr;
274f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    return 0;
275f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
276f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
277fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehatvoid VolumeManager::handleBlockEvent(NetlinkEvent *evt) {
278c8e04c5a8285de07d2c84bfbda8eda2c14a9457dJeff Sharkey    std::lock_guard<std::mutex> lock(mLock);
279c8e04c5a8285de07d2c84bfbda8eda2c14a9457dJeff Sharkey
280f1b996df6f8283aac6953b22bd9e2496d8c30c86Jeff Sharkey    if (mDebug) {
281f1b996df6f8283aac6953b22bd9e2496d8c30c86Jeff Sharkey        LOG(VERBOSE) << "----------------";
282f1b996df6f8283aac6953b22bd9e2496d8c30c86Jeff Sharkey        LOG(VERBOSE) << "handleBlockEvent with action " << (int) evt->getAction();
283f1b996df6f8283aac6953b22bd9e2496d8c30c86Jeff Sharkey        evt->dump();
284f1b996df6f8283aac6953b22bd9e2496d8c30c86Jeff Sharkey    }
285f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
28636801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    std::string eventPath(evt->findParam("DEVPATH"));
28736801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    std::string devType(evt->findParam("DEVTYPE"));
28836801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey
28936801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    if (devType != "disk") return;
29036801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey
29136801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    int major = atoi(evt->findParam("MAJOR"));
29236801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    int minor = atoi(evt->findParam("MINOR"));
29336801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    dev_t device = makedev(major, minor);
29436801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey
29536801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    switch (evt->getAction()) {
29636801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    case NetlinkEvent::Action::kAdd: {
29736801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey        for (auto source : mDiskSources) {
29836801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey            if (source->matches(eventPath)) {
29936801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey                // For now, assume that MMC devices are SD, and that
30036801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey                // everything else is USB
30136801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey                int flags = source->getFlags();
30236801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey                if (major == kMajorBlockMmc) {
30336801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey                    flags |= android::vold::Disk::Flags::kSd;
30436801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey                } else {
30536801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey                    flags |= android::vold::Disk::Flags::kUsb;
30636801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey                }
30736801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey
30836801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey                auto disk = new android::vold::Disk(eventPath, device,
30936801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey                        source->getNickname(), flags);
31036801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey                disk->create();
31136801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey                mDisks.push_back(std::shared_ptr<android::vold::Disk>(disk));
31236801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey                break;
31336801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey            }
31436801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey        }
31536801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey        break;
31636801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    }
31736801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    case NetlinkEvent::Action::kChange: {
3187d9d0118658648d85c6ce649a9f8d2893a7b5a78Jeff Sharkey        LOG(DEBUG) << "Disk at " << major << ":" << minor << " changed";
31936801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey        for (auto disk : mDisks) {
32036801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey            if (disk->getDevice() == device) {
32136801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey                disk->readMetadata();
32236801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey                disk->readPartitions();
32336801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey            }
32436801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey        }
32536801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey        break;
32636801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    }
32736801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    case NetlinkEvent::Action::kRemove: {
32836801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey        auto i = mDisks.begin();
32936801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey        while (i != mDisks.end()) {
33036801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey            if ((*i)->getDevice() == device) {
33136801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey                (*i)->destroy();
33236801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey                i = mDisks.erase(i);
33336801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey            } else {
33436801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey                ++i;
33536801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey            }
336f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat        }
33736801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey        break;
33836801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    }
33936801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    default: {
34036801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey        LOG(WARNING) << "Unexpected block event action " << (int) evt->getAction();
34136801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey        break;
342f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    }
34336801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    }
34436801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey}
345f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
34636801cccf27152c9eca5aab6ba3527221525110fJeff Sharkeyvoid VolumeManager::addDiskSource(const std::shared_ptr<DiskSource>& diskSource) {
34736801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    mDiskSources.push_back(diskSource);
34836801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey}
34936801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey
35036801cccf27152c9eca5aab6ba3527221525110fJeff Sharkeystd::shared_ptr<android::vold::Disk> VolumeManager::findDisk(const std::string& id) {
35136801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    for (auto disk : mDisks) {
35236801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey        if (disk->getId() == id) {
35336801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey            return disk;
35436801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey        }
355f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    }
35636801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    return nullptr;
35736801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey}
35836801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey
35936801cccf27152c9eca5aab6ba3527221525110fJeff Sharkeystd::shared_ptr<android::vold::VolumeBase> VolumeManager::findVolume(const std::string& id) {
36036801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    if (mInternalEmulated->getId() == id) {
36136801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey        return mInternalEmulated;
36236801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    }
36336801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    for (auto disk : mDisks) {
36436801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey        auto vol = disk->findVolume(id);
36536801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey        if (vol != nullptr) {
36636801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey            return vol;
36736801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey        }
36836801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    }
36936801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    return nullptr;
37036801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey}
37136801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey
372c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkeyvoid VolumeManager::listVolumes(android::vold::VolumeBase::Type type,
373c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey        std::list<std::string>& list) {
374c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey    list.clear();
375c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey    for (auto disk : mDisks) {
376c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey        disk->listVolumes(type, list);
377c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey    }
378c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey}
379c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey
380c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkeynsecs_t VolumeManager::benchmarkPrivate(const std::string& id) {
3815a6bfca1638760b87cf64c5ffb48ff3557cc0563Jeff Sharkey    std::string path;
382c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey    if (id == "private" || id == "null") {
383c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey        path = "/data";
384c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey    } else {
385c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey        auto vol = findVolume(id);
386c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey        if (vol != nullptr && vol->getState() == android::vold::VolumeBase::State::kMounted) {
3875a6bfca1638760b87cf64c5ffb48ff3557cc0563Jeff Sharkey            path = vol->getPath();
3885a6bfca1638760b87cf64c5ffb48ff3557cc0563Jeff Sharkey        }
3895a6bfca1638760b87cf64c5ffb48ff3557cc0563Jeff Sharkey    }
3905a6bfca1638760b87cf64c5ffb48ff3557cc0563Jeff Sharkey
3915a6bfca1638760b87cf64c5ffb48ff3557cc0563Jeff Sharkey    if (path.empty()) {
3925a6bfca1638760b87cf64c5ffb48ff3557cc0563Jeff Sharkey        LOG(WARNING) << "Failed to find volume for " << id;
3935a6bfca1638760b87cf64c5ffb48ff3557cc0563Jeff Sharkey        return -1;
3945a6bfca1638760b87cf64c5ffb48ff3557cc0563Jeff Sharkey    }
3955a6bfca1638760b87cf64c5ffb48ff3557cc0563Jeff Sharkey
396c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey    return android::vold::BenchmarkPrivate(path);
3975a6bfca1638760b87cf64c5ffb48ff3557cc0563Jeff Sharkey}
3985a6bfca1638760b87cf64c5ffb48ff3557cc0563Jeff Sharkey
399bc40cc8f07f69e0e26fc41516e2a83f0a8becbe0Jeff Sharkeyint VolumeManager::forgetPartition(const std::string& partGuid) {
400bc40cc8f07f69e0e26fc41516e2a83f0a8becbe0Jeff Sharkey    std::string normalizedGuid;
401bc40cc8f07f69e0e26fc41516e2a83f0a8becbe0Jeff Sharkey    if (android::vold::NormalizeHex(partGuid, normalizedGuid)) {
402bc40cc8f07f69e0e26fc41516e2a83f0a8becbe0Jeff Sharkey        LOG(WARNING) << "Invalid GUID " << partGuid;
403bc40cc8f07f69e0e26fc41516e2a83f0a8becbe0Jeff Sharkey        return -1;
404bc40cc8f07f69e0e26fc41516e2a83f0a8becbe0Jeff Sharkey    }
405bc40cc8f07f69e0e26fc41516e2a83f0a8becbe0Jeff Sharkey
406bc40cc8f07f69e0e26fc41516e2a83f0a8becbe0Jeff Sharkey    std::string keyPath = android::vold::BuildKeyPath(normalizedGuid);
407bc40cc8f07f69e0e26fc41516e2a83f0a8becbe0Jeff Sharkey    if (unlink(keyPath.c_str()) != 0) {
408bc40cc8f07f69e0e26fc41516e2a83f0a8becbe0Jeff Sharkey        LOG(ERROR) << "Failed to unlink " << keyPath;
409bc40cc8f07f69e0e26fc41516e2a83f0a8becbe0Jeff Sharkey        return -1;
410bc40cc8f07f69e0e26fc41516e2a83f0a8becbe0Jeff Sharkey    }
411bc40cc8f07f69e0e26fc41516e2a83f0a8becbe0Jeff Sharkey
412bc40cc8f07f69e0e26fc41516e2a83f0a8becbe0Jeff Sharkey    return 0;
413bc40cc8f07f69e0e26fc41516e2a83f0a8becbe0Jeff Sharkey}
414bc40cc8f07f69e0e26fc41516e2a83f0a8becbe0Jeff Sharkey
41536801cccf27152c9eca5aab6ba3527221525110fJeff Sharkeyint VolumeManager::linkPrimary(userid_t userId) {
41636801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    std::string source(mPrimary->getPath());
41736801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    if (mPrimary->getType() == android::vold::VolumeBase::Type::kEmulated) {
41836801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey        source = StringPrintf("%s/%d", source.c_str(), userId);
41932679a82d9542ec26ea8b4e32d29dd7b02202611Jeff Sharkey        fs_prepare_dir(source.c_str(), 0755, AID_ROOT, AID_ROOT);
42036801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    }
42136801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey
42236801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    std::string target(StringPrintf("/mnt/user/%d/primary", userId));
42336801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    if (TEMP_FAILURE_RETRY(unlink(target.c_str()))) {
42436801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey        if (errno != ENOENT) {
42536801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey            SLOGW("Failed to unlink %s: %s", target.c_str(), strerror(errno));
42636801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey        }
42736801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    }
4281bfb375f77c093a8e16bef4ddeab2681ca126d56Jeff Sharkey    LOG(DEBUG) << "Linking " << source << " to " << target;
42936801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    if (TEMP_FAILURE_RETRY(symlink(source.c_str(), target.c_str()))) {
43036801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey        SLOGW("Failed to link %s to %s: %s", source.c_str(), target.c_str(),
43136801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey                strerror(errno));
43236801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey        return -errno;
43336801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    }
43436801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    return 0;
43536801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey}
43636801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey
437bd3038df74ace540d46c530a11e3145f922e1b42Jeff Sharkeyint VolumeManager::onUserAdded(userid_t userId, int userSerialNumber) {
438bd3038df74ace540d46c530a11e3145f922e1b42Jeff Sharkey    mAddedUsers[userId] = userSerialNumber;
439bd3038df74ace540d46c530a11e3145f922e1b42Jeff Sharkey    return 0;
440bd3038df74ace540d46c530a11e3145f922e1b42Jeff Sharkey}
441bd3038df74ace540d46c530a11e3145f922e1b42Jeff Sharkey
442bd3038df74ace540d46c530a11e3145f922e1b42Jeff Sharkeyint VolumeManager::onUserRemoved(userid_t userId) {
443bd3038df74ace540d46c530a11e3145f922e1b42Jeff Sharkey    mAddedUsers.erase(userId);
444bd3038df74ace540d46c530a11e3145f922e1b42Jeff Sharkey    return 0;
445bd3038df74ace540d46c530a11e3145f922e1b42Jeff Sharkey}
446bd3038df74ace540d46c530a11e3145f922e1b42Jeff Sharkey
447bd3038df74ace540d46c530a11e3145f922e1b42Jeff Sharkeyint VolumeManager::onUserStarted(userid_t userId) {
44836801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    // Note that sometimes the system will spin up processes from Zygote
44936801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    // before actually starting the user, so we're okay if Zygote
45036801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    // already created this directory.
45136801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    std::string path(StringPrintf("%s/%d", kUserMountPath, userId));
45236801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    fs_prepare_dir(path.c_str(), 0755, AID_ROOT, AID_ROOT);
45336801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey
454bd3038df74ace540d46c530a11e3145f922e1b42Jeff Sharkey    mStartedUsers.insert(userId);
45536801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    if (mPrimary) {
45636801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey        linkPrimary(userId);
45736801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    }
45836801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    return 0;
45936801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey}
46036801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey
461bd3038df74ace540d46c530a11e3145f922e1b42Jeff Sharkeyint VolumeManager::onUserStopped(userid_t userId) {
462bd3038df74ace540d46c530a11e3145f922e1b42Jeff Sharkey    mStartedUsers.erase(userId);
46336801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    return 0;
46436801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey}
46536801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey
46636801cccf27152c9eca5aab6ba3527221525110fJeff Sharkeyint VolumeManager::setPrimary(const std::shared_ptr<android::vold::VolumeBase>& vol) {
46736801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    mPrimary = vol;
468bd3038df74ace540d46c530a11e3145f922e1b42Jeff Sharkey    for (userid_t userId : mStartedUsers) {
46936801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey        linkPrimary(userId);
47036801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    }
47136801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    return 0;
47236801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey}
47336801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey
474c7b5b570bd05ed3bc921b0c2dc346416a52b4e3eJeff Sharkeystatic int sane_readlinkat(int dirfd, const char* path, char* buf, size_t bufsiz) {
475c7b5b570bd05ed3bc921b0c2dc346416a52b4e3eJeff Sharkey    ssize_t len = readlinkat(dirfd, path, buf, bufsiz);
476c7b5b570bd05ed3bc921b0c2dc346416a52b4e3eJeff Sharkey    if (len < 0) {
477c7b5b570bd05ed3bc921b0c2dc346416a52b4e3eJeff Sharkey        return -1;
478c7b5b570bd05ed3bc921b0c2dc346416a52b4e3eJeff Sharkey    } else if (len == (ssize_t) bufsiz) {
479c7b5b570bd05ed3bc921b0c2dc346416a52b4e3eJeff Sharkey        return -1;
480c7b5b570bd05ed3bc921b0c2dc346416a52b4e3eJeff Sharkey    } else {
481c7b5b570bd05ed3bc921b0c2dc346416a52b4e3eJeff Sharkey        buf[len] = '\0';
482c7b5b570bd05ed3bc921b0c2dc346416a52b4e3eJeff Sharkey        return 0;
483c7b5b570bd05ed3bc921b0c2dc346416a52b4e3eJeff Sharkey    }
484c7b5b570bd05ed3bc921b0c2dc346416a52b4e3eJeff Sharkey}
485c7b5b570bd05ed3bc921b0c2dc346416a52b4e3eJeff Sharkey
486c7b5b570bd05ed3bc921b0c2dc346416a52b4e3eJeff Sharkeystatic int unmount_tree(const char* path) {
487c7b5b570bd05ed3bc921b0c2dc346416a52b4e3eJeff Sharkey    size_t path_len = strlen(path);
488c7b5b570bd05ed3bc921b0c2dc346416a52b4e3eJeff Sharkey
489c7b5b570bd05ed3bc921b0c2dc346416a52b4e3eJeff Sharkey    FILE* fp = setmntent("/proc/mounts", "r");
490c7b5b570bd05ed3bc921b0c2dc346416a52b4e3eJeff Sharkey    if (fp == NULL) {
491c7b5b570bd05ed3bc921b0c2dc346416a52b4e3eJeff Sharkey        ALOGE("Error opening /proc/mounts: %s", strerror(errno));
492c7b5b570bd05ed3bc921b0c2dc346416a52b4e3eJeff Sharkey        return -errno;
493c7b5b570bd05ed3bc921b0c2dc346416a52b4e3eJeff Sharkey    }
494c7b5b570bd05ed3bc921b0c2dc346416a52b4e3eJeff Sharkey
495c7b5b570bd05ed3bc921b0c2dc346416a52b4e3eJeff Sharkey    // Some volumes can be stacked on each other, so force unmount in
496c7b5b570bd05ed3bc921b0c2dc346416a52b4e3eJeff Sharkey    // reverse order to give us the best chance of success.
497c7b5b570bd05ed3bc921b0c2dc346416a52b4e3eJeff Sharkey    std::list<std::string> toUnmount;
498c7b5b570bd05ed3bc921b0c2dc346416a52b4e3eJeff Sharkey    mntent* mentry;
499c7b5b570bd05ed3bc921b0c2dc346416a52b4e3eJeff Sharkey    while ((mentry = getmntent(fp)) != NULL) {
500c7b5b570bd05ed3bc921b0c2dc346416a52b4e3eJeff Sharkey        if (strncmp(mentry->mnt_dir, path, path_len) == 0) {
501c7b5b570bd05ed3bc921b0c2dc346416a52b4e3eJeff Sharkey            toUnmount.push_front(std::string(mentry->mnt_dir));
502c7b5b570bd05ed3bc921b0c2dc346416a52b4e3eJeff Sharkey        }
503c7b5b570bd05ed3bc921b0c2dc346416a52b4e3eJeff Sharkey    }
504c7b5b570bd05ed3bc921b0c2dc346416a52b4e3eJeff Sharkey    endmntent(fp);
505c7b5b570bd05ed3bc921b0c2dc346416a52b4e3eJeff Sharkey
506c7b5b570bd05ed3bc921b0c2dc346416a52b4e3eJeff Sharkey    for (auto path : toUnmount) {
507c7b5b570bd05ed3bc921b0c2dc346416a52b4e3eJeff Sharkey        if (umount2(path.c_str(), MNT_DETACH)) {
508c7b5b570bd05ed3bc921b0c2dc346416a52b4e3eJeff Sharkey            ALOGW("Failed to unmount %s: %s", path.c_str(), strerror(errno));
509c7b5b570bd05ed3bc921b0c2dc346416a52b4e3eJeff Sharkey        }
510c7b5b570bd05ed3bc921b0c2dc346416a52b4e3eJeff Sharkey    }
511c7b5b570bd05ed3bc921b0c2dc346416a52b4e3eJeff Sharkey    return 0;
512c7b5b570bd05ed3bc921b0c2dc346416a52b4e3eJeff Sharkey}
513c7b5b570bd05ed3bc921b0c2dc346416a52b4e3eJeff Sharkey
51466270a21df1058434e4d63691221f11ff5387a0fJeff Sharkeyint VolumeManager::remountUid(uid_t uid, const std::string& mode) {
51566270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey    LOG(DEBUG) << "Remounting " << uid << " as mode " << mode;
51666270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey
51766270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey    DIR* dir;
51866270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey    struct dirent* de;
51966270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey    char rootName[PATH_MAX];
52066270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey    char pidName[PATH_MAX];
52166270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey    int pidFd;
52266270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey    int nsFd;
52366270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey    struct stat sb;
52466270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey    pid_t child;
52566270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey
52666270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey    if (!(dir = opendir("/proc"))) {
52766270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey        PLOG(ERROR) << "Failed to opendir";
52866270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey        return -1;
52966270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey    }
53066270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey
53166270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey    // Figure out root namespace to compare against below
532c7b5b570bd05ed3bc921b0c2dc346416a52b4e3eJeff Sharkey    if (sane_readlinkat(dirfd(dir), "1/ns/mnt", rootName, PATH_MAX) == -1) {
53366270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey        PLOG(ERROR) << "Failed to readlink";
53466270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey        closedir(dir);
53566270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey        return -1;
53666270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey    }
53766270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey
53866270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey    // Poke through all running PIDs look for apps running as UID
53966270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey    while ((de = readdir(dir))) {
54066270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey        pidFd = -1;
54166270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey        nsFd = -1;
54266270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey
54366270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey        pidFd = openat(dirfd(dir), de->d_name, O_RDONLY | O_DIRECTORY | O_CLOEXEC);
54466270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey        if (pidFd < 0) {
54566270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey            goto next;
54666270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey        }
54766270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey        if (fstat(pidFd, &sb) != 0) {
54866270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey            PLOG(WARNING) << "Failed to stat " << de->d_name;
54966270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey            goto next;
55066270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey        }
55166270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey        if (sb.st_uid != uid) {
55266270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey            goto next;
55366270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey        }
55466270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey
55566270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey        // Matches so far, but refuse to touch if in root namespace
55666270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey        LOG(DEBUG) << "Found matching PID " << de->d_name;
557c7b5b570bd05ed3bc921b0c2dc346416a52b4e3eJeff Sharkey        if (sane_readlinkat(pidFd, "ns/mnt", pidName, PATH_MAX) == -1) {
55866270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey            PLOG(WARNING) << "Failed to read namespace for " << de->d_name;
55966270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey            goto next;
56066270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey        }
56166270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey        if (!strcmp(rootName, pidName)) {
56266270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey            LOG(WARNING) << "Skipping due to root namespace";
56366270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey            goto next;
56466270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey        }
56566270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey
56666270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey        // We purposefully leave the namespace open across the fork
56766270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey        nsFd = openat(pidFd, "ns/mnt", O_RDONLY);
56866270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey        if (nsFd < 0) {
569c7b5b570bd05ed3bc921b0c2dc346416a52b4e3eJeff Sharkey            PLOG(WARNING) << "Failed to open namespace for " << de->d_name;
57066270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey            goto next;
57166270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey        }
57266270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey
57366270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey        if (!(child = fork())) {
57466270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey            if (setns(nsFd, CLONE_NEWNS) != 0) {
575c7b5b570bd05ed3bc921b0c2dc346416a52b4e3eJeff Sharkey                PLOG(ERROR) << "Failed to setns for " << de->d_name;
57666270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey                _exit(1);
57766270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey            }
57866270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey
579c7b5b570bd05ed3bc921b0c2dc346416a52b4e3eJeff Sharkey            unmount_tree("/storage");
58066270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey
58166270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey            std::string storageSource;
58266270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey            if (mode == "default") {
5831bd078fa7b5ca613cb3e793d67ccd86d2602787dJeff Sharkey                storageSource = "/mnt/runtime/default";
58466270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey            } else if (mode == "read") {
5851bd078fa7b5ca613cb3e793d67ccd86d2602787dJeff Sharkey                storageSource = "/mnt/runtime/read";
58666270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey            } else if (mode == "write") {
5871bd078fa7b5ca613cb3e793d67ccd86d2602787dJeff Sharkey                storageSource = "/mnt/runtime/write";
58866270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey            } else {
58966270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey                // Sane default of no storage visible
59066270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey                _exit(0);
59166270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey            }
59266270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey            if (TEMP_FAILURE_RETRY(mount(storageSource.c_str(), "/storage",
59366270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey                    NULL, MS_BIND | MS_REC | MS_SLAVE, NULL)) == -1) {
594c7b5b570bd05ed3bc921b0c2dc346416a52b4e3eJeff Sharkey                PLOG(ERROR) << "Failed to mount " << storageSource << " for "
595c7b5b570bd05ed3bc921b0c2dc346416a52b4e3eJeff Sharkey                        << de->d_name;
596c7b5b570bd05ed3bc921b0c2dc346416a52b4e3eJeff Sharkey                _exit(1);
59766270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey            }
598c7b5b570bd05ed3bc921b0c2dc346416a52b4e3eJeff Sharkey
599c7b5b570bd05ed3bc921b0c2dc346416a52b4e3eJeff Sharkey            // Mount user-specific symlink helper into place
600c7b5b570bd05ed3bc921b0c2dc346416a52b4e3eJeff Sharkey            userid_t user_id = multiuser_get_user_id(uid);
601c7b5b570bd05ed3bc921b0c2dc346416a52b4e3eJeff Sharkey            std::string userSource(StringPrintf("/mnt/user/%d", user_id));
602c7b5b570bd05ed3bc921b0c2dc346416a52b4e3eJeff Sharkey            if (TEMP_FAILURE_RETRY(mount(userSource.c_str(), "/storage/self",
603c7b5b570bd05ed3bc921b0c2dc346416a52b4e3eJeff Sharkey                    NULL, MS_BIND, NULL)) == -1) {
604c7b5b570bd05ed3bc921b0c2dc346416a52b4e3eJeff Sharkey                PLOG(ERROR) << "Failed to mount " << userSource << " for "
605c7b5b570bd05ed3bc921b0c2dc346416a52b4e3eJeff Sharkey                        << de->d_name;
606c7b5b570bd05ed3bc921b0c2dc346416a52b4e3eJeff Sharkey                _exit(1);
607c7b5b570bd05ed3bc921b0c2dc346416a52b4e3eJeff Sharkey            }
608c7b5b570bd05ed3bc921b0c2dc346416a52b4e3eJeff Sharkey
60966270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey            _exit(0);
61066270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey        }
61166270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey
61266270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey        if (child == -1) {
61366270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey            PLOG(ERROR) << "Failed to fork";
61466270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey            goto next;
61566270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey        } else {
61666270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey            TEMP_FAILURE_RETRY(waitpid(child, nullptr, 0));
61766270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey        }
61866270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey
61966270a21df1058434e4d63691221f11ff5387a0fJeff Sharkeynext:
62066270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey        close(nsFd);
62166270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey        close(pidFd);
62266270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey    }
62366270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey    closedir(dir);
62466270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey    return 0;
62566270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey}
62666270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey
62736801cccf27152c9eca5aab6ba3527221525110fJeff Sharkeyint VolumeManager::reset() {
62836801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    // Tear down all existing disks/volumes and start from a blank slate so
62936801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    // newly connected framework hears all events.
63036801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    mInternalEmulated->destroy();
63136801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    mInternalEmulated->create();
63236801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    for (auto disk : mDisks) {
63336801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey        disk->destroy();
63436801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey        disk->create();
63536801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    }
636bd3038df74ace540d46c530a11e3145f922e1b42Jeff Sharkey    mAddedUsers.clear();
637bd3038df74ace540d46c530a11e3145f922e1b42Jeff Sharkey    mStartedUsers.clear();
63836801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    return 0;
63936801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey}
64036801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey
64136801cccf27152c9eca5aab6ba3527221525110fJeff Sharkeyint VolumeManager::shutdown() {
6429c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    mInternalEmulated->destroy();
64336801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    for (auto disk : mDisks) {
64436801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey        disk->destroy();
64536801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    }
64636801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    mDisks.clear();
64736801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    return 0;
648f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
649f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
6509c48498f4529f623650c56d03e63324c8d813032Jeff Sharkeyint VolumeManager::unmountAll() {
651c8e04c5a8285de07d2c84bfbda8eda2c14a9457dJeff Sharkey    std::lock_guard<std::mutex> lock(mLock);
652c8e04c5a8285de07d2c84bfbda8eda2c14a9457dJeff Sharkey
6539c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    // First, try gracefully unmounting all known devices
6549c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    if (mInternalEmulated != nullptr) {
6559c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey        mInternalEmulated->unmount();
6569c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    }
6579c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    for (auto disk : mDisks) {
6589c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey        disk->unmountAll();
6599c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    }
6609c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey
6619c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    // Worst case we might have some stale mounts lurking around, so
6629c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    // force unmount those just to be safe.
6639c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    FILE* fp = setmntent("/proc/mounts", "r");
6649c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    if (fp == NULL) {
6659c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey        SLOGE("Error opening /proc/mounts: %s", strerror(errno));
6669c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey        return -errno;
6679c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    }
6689c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey
6699c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    // Some volumes can be stacked on each other, so force unmount in
6709c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    // reverse order to give us the best chance of success.
6719c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    std::list<std::string> toUnmount;
6729c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    mntent* mentry;
6739c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    while ((mentry = getmntent(fp)) != NULL) {
6749c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey        if (strncmp(mentry->mnt_dir, "/mnt/", 5) == 0
6759c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey                || strncmp(mentry->mnt_dir, "/storage/", 9) == 0) {
6769c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey            toUnmount.push_front(std::string(mentry->mnt_dir));
6779c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey        }
6789c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    }
6799c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    endmntent(fp);
6809c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey
6819c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    for (auto path : toUnmount) {
6829c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey        SLOGW("Tearing down stale mount %s", path.c_str());
6839c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey        android::vold::ForceUnmount(path);
6849c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    }
6859c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey
6869c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    return 0;
6879c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey}
6889c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey
689508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Rootint VolumeManager::getObbMountPath(const char *sourceFile, char *mountPath, int mountPathLen) {
690508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root    char idHash[33];
691508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root    if (!asecHash(sourceFile, idHash, sizeof(idHash))) {
692508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root        SLOGE("Hash of '%s' failed (%s)", sourceFile, strerror(errno));
693508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root        return -1;
694508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root    }
695508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root
696508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root    memset(mountPath, 0, mountPathLen);
6979f18fe7807a4e4089778243dbbd08d154ec15540Jeff Sharkey    int written = snprintf(mountPath, mountPathLen, "%s/%s", VolumeManager::LOOPDIR, idHash);
698d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig    if ((written < 0) || (written >= mountPathLen)) {
699d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig        errno = EINVAL;
700d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig        return -1;
701d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig    }
702508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root
703508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root    if (access(mountPath, F_OK)) {
704508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root        errno = ENOENT;
705508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root        return -1;
706508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root    }
707508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root
708508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root    return 0;
709508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root}
710508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root
711a19b250bd273455933ca3502cf2c2e0a803aff77San Mehatint VolumeManager::getAsecMountPath(const char *id, char *buffer, int maxlen) {
71288ac2c06539485942bf414efda2d39647fa1a415San Mehat    char asecFileName[255];
713344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
7140de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich    if (!isLegalAsecId(id)) {
7150de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich        SLOGE("getAsecMountPath: Invalid asec id \"%s\"", id);
7160de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich        errno = EINVAL;
7170de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich        return -1;
7180de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich    }
7190de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich
720344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    if (findAsec(id, asecFileName, sizeof(asecFileName))) {
721344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        SLOGE("Couldn't find ASEC %s", id);
722344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        return -1;
723344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    }
72488ac2c06539485942bf414efda2d39647fa1a415San Mehat
72588ac2c06539485942bf414efda2d39647fa1a415San Mehat    memset(buffer, 0, maxlen);
72688ac2c06539485942bf414efda2d39647fa1a415San Mehat    if (access(asecFileName, F_OK)) {
72788ac2c06539485942bf414efda2d39647fa1a415San Mehat        errno = ENOENT;
72888ac2c06539485942bf414efda2d39647fa1a415San Mehat        return -1;
72988ac2c06539485942bf414efda2d39647fa1a415San Mehat    }
730a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
7319f18fe7807a4e4089778243dbbd08d154ec15540Jeff Sharkey    int written = snprintf(buffer, maxlen, "%s/%s", VolumeManager::ASECDIR, id);
732d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig    if ((written < 0) || (written >= maxlen)) {
733d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig        SLOGE("getAsecMountPath failed for %s: couldn't construct path in buffer", id);
734d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig        errno = EINVAL;
735d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig        return -1;
736d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig    }
737d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig
738a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    return 0;
739a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat}
740a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
741736910ca99a40b9add4353bf619e778c40938948Dianne Hackbornint VolumeManager::getAsecFilesystemPath(const char *id, char *buffer, int maxlen) {
742736910ca99a40b9add4353bf619e778c40938948Dianne Hackborn    char asecFileName[255];
743344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
7440de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich    if (!isLegalAsecId(id)) {
7450de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich        SLOGE("getAsecFilesystemPath: Invalid asec id \"%s\"", id);
7460de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich        errno = EINVAL;
7470de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich        return -1;
7480de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich    }
7490de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich
750344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    if (findAsec(id, asecFileName, sizeof(asecFileName))) {
751344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        SLOGE("Couldn't find ASEC %s", id);
752344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        return -1;
753344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    }
754736910ca99a40b9add4353bf619e778c40938948Dianne Hackborn
755736910ca99a40b9add4353bf619e778c40938948Dianne Hackborn    memset(buffer, 0, maxlen);
756736910ca99a40b9add4353bf619e778c40938948Dianne Hackborn    if (access(asecFileName, F_OK)) {
757736910ca99a40b9add4353bf619e778c40938948Dianne Hackborn        errno = ENOENT;
758736910ca99a40b9add4353bf619e778c40938948Dianne Hackborn        return -1;
759736910ca99a40b9add4353bf619e778c40938948Dianne Hackborn    }
760736910ca99a40b9add4353bf619e778c40938948Dianne Hackborn
761d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig    int written = snprintf(buffer, maxlen, "%s", asecFileName);
762d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig    if ((written < 0) || (written >= maxlen)) {
763d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig        errno = EINVAL;
764d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig        return -1;
765d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig    }
766d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig
767736910ca99a40b9add4353bf619e778c40938948Dianne Hackborn    return 0;
768736910ca99a40b9add4353bf619e778c40938948Dianne Hackborn}
769736910ca99a40b9add4353bf619e778c40938948Dianne Hackborn
770344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Rootint VolumeManager::createAsec(const char *id, unsigned int numSectors, const char *fstype,
771344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        const char *key, const int ownerUid, bool isExternal) {
772fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    struct asec_superblock sb;
773fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    memset(&sb, 0, sizeof(sb));
774fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat
7750de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich    if (!isLegalAsecId(id)) {
7760de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich        SLOGE("createAsec: Invalid asec id \"%s\"", id);
7770de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich        errno = EINVAL;
7780de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich        return -1;
7790de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich    }
7800de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich
781344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    const bool wantFilesystem = strcmp(fstype, "none");
782344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    bool usingExt4 = false;
783344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    if (wantFilesystem) {
784344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        usingExt4 = !strcmp(fstype, "ext4");
785344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        if (usingExt4) {
786344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            sb.c_opts |= ASEC_SB_C_OPTS_EXT4;
787344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        } else if (strcmp(fstype, "fat")) {
788344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            SLOGE("Invalid filesystem type %s", fstype);
789344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            errno = EINVAL;
790344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            return -1;
791344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        }
792344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    }
793344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
794fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    sb.magic = ASEC_SB_MAGIC;
795fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    sb.ver = ASEC_SB_VER;
796a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
797d31e380bd9689dd9629b510ffe324707e261b439San Mehat    if (numSectors < ((1024*1024)/512)) {
79897ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Invalid container size specified (%d sectors)", numSectors);
799d31e380bd9689dd9629b510ffe324707e261b439San Mehat        errno = EINVAL;
800d31e380bd9689dd9629b510ffe324707e261b439San Mehat        return -1;
801d31e380bd9689dd9629b510ffe324707e261b439San Mehat    }
802d31e380bd9689dd9629b510ffe324707e261b439San Mehat
803a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char asecFileName[255];
804344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
805344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    if (!findAsec(id, asecFileName, sizeof(asecFileName))) {
806344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        SLOGE("ASEC file '%s' currently exists - destroy it first! (%s)",
807344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root                asecFileName, strerror(errno));
808344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        errno = EADDRINUSE;
809344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        return -1;
810344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    }
811344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
8129f18fe7807a4e4089778243dbbd08d154ec15540Jeff Sharkey    const char *asecDir = isExternal ? VolumeManager::SEC_ASECDIR_EXT : VolumeManager::SEC_ASECDIR_INT;
813344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
814d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig    int written = snprintf(asecFileName, sizeof(asecFileName), "%s/%s.asec", asecDir, id);
815d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig    if ((written < 0) || (size_t(written) >= sizeof(asecFileName))) {
816d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig        errno = EINVAL;
817d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig        return -1;
818d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig    }
819a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
820a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (!access(asecFileName, F_OK)) {
82197ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("ASEC file '%s' currently exists - destroy it first! (%s)",
822344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root                asecFileName, strerror(errno));
823a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        errno = EADDRINUSE;
824a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
825a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
826a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
827fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    unsigned numImgSectors;
8286a74dcaa6e646fea8e00b7c04332fc60fe7e017cDaniel Rosenberg    if (usingExt4)
829fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        numImgSectors = adjustSectorNumExt4(numSectors);
8306a74dcaa6e646fea8e00b7c04332fc60fe7e017cDaniel Rosenberg    else
831fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        numImgSectors = adjustSectorNumFAT(numSectors);
832fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat
833fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    // Add +1 for our superblock which is at the end
834fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    if (Loop::createImageFile(asecFileName, numImgSectors + 1)) {
83597ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("ASEC image file creation failed (%s)", strerror(errno));
836a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
837a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
838a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
839d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    char idHash[33];
840d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    if (!asecHash(id, idHash, sizeof(idHash))) {
84197ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Hash of '%s' failed (%s)", id, strerror(errno));
842d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        unlink(asecFileName);
843d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        return -1;
844d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    }
845d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat
846a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char loopDevice[255];
847d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    if (Loop::create(idHash, asecFileName, loopDevice, sizeof(loopDevice))) {
84897ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("ASEC loop device creation failed (%s)", strerror(errno));
849a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        unlink(asecFileName);
850a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
851a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
852a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
853b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    char dmDevice[255];
854b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    bool cleanupDm = false;
855a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
856b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    if (strcmp(key, "none")) {
857fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        // XXX: This is all we support for now
858fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        sb.c_cipher = ASEC_SB_C_CIPHER_TWOFISH;
859d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        if (Devmapper::create(idHash, loopDevice, key, numImgSectors, dmDevice,
860b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat                             sizeof(dmDevice))) {
86197ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat            SLOGE("ASEC device mapping failed (%s)", strerror(errno));
862b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            Loop::destroyByDevice(loopDevice);
863b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            unlink(asecFileName);
864b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            return -1;
865b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        }
866b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        cleanupDm = true;
867b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    } else {
868fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        sb.c_cipher = ASEC_SB_C_CIPHER_NONE;
869b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        strcpy(dmDevice, loopDevice);
870b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    }
871b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
872fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    /*
873fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat     * Drop down the superblock at the end of the file
874fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat     */
875fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    if (writeSuperBlock(loopDevice, &sb, numImgSectors)) {
876fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        if (cleanupDm) {
877d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat            Devmapper::destroy(idHash);
878fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        }
879fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        Loop::destroyByDevice(loopDevice);
880fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        unlink(asecFileName);
881fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        return -1;
882fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    }
883fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat
884344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    if (wantFilesystem) {
885344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        int formatStatus;
886a54e13a3dca8ad15141a9f1084b6e121caeddce5rpcraig        char mountPoint[255];
887a54e13a3dca8ad15141a9f1084b6e121caeddce5rpcraig
8889f18fe7807a4e4089778243dbbd08d154ec15540Jeff Sharkey        int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", VolumeManager::ASECDIR, id);
889d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig        if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) {
890d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig            SLOGE("ASEC fs format failed: couldn't construct mountPoint");
891d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig            if (cleanupDm) {
892d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig                Devmapper::destroy(idHash);
893d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig            }
894d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig            Loop::destroyByDevice(loopDevice);
895d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig            unlink(asecFileName);
896d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig            return -1;
897d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig        }
898a54e13a3dca8ad15141a9f1084b6e121caeddce5rpcraig
899344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        if (usingExt4) {
900d0640f6358041f7e2657167560b357078db73526Jeff Sharkey            formatStatus = android::vold::ext4::Format(dmDevice, numImgSectors, mountPoint);
901344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        } else {
902d0640f6358041f7e2657167560b357078db73526Jeff Sharkey            formatStatus = android::vold::vfat::Format(dmDevice, numImgSectors);
903b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        }
904a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
905344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        if (formatStatus < 0) {
906344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            SLOGE("ASEC fs format failed (%s)", strerror(errno));
907b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            if (cleanupDm) {
908d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat                Devmapper::destroy(idHash);
909b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            }
910eb13a90bb96b329d8e24a6c3d4720ae88451d301San Mehat            Loop::destroyByDevice(loopDevice);
911eb13a90bb96b329d8e24a6c3d4720ae88451d301San Mehat            unlink(asecFileName);
912eb13a90bb96b329d8e24a6c3d4720ae88451d301San Mehat            return -1;
913eb13a90bb96b329d8e24a6c3d4720ae88451d301San Mehat        }
914344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
915344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        if (mkdir(mountPoint, 0000)) {
916a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat            if (errno != EEXIST) {
91797ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat                SLOGE("Mountpoint creation failed (%s)", strerror(errno));
918a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat                if (cleanupDm) {
919d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat                    Devmapper::destroy(idHash);
920a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat                }
921a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat                Loop::destroyByDevice(loopDevice);
922a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat                unlink(asecFileName);
923a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat                return -1;
924a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat            }
925a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat        }
926a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
927344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        int mountStatus;
928344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        if (usingExt4) {
929d0640f6358041f7e2657167560b357078db73526Jeff Sharkey            mountStatus = android::vold::ext4::Mount(dmDevice, mountPoint,
930d0640f6358041f7e2657167560b357078db73526Jeff Sharkey                    false, false, false);
931344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        } else {
932d0640f6358041f7e2657167560b357078db73526Jeff Sharkey            mountStatus = android::vold::vfat::Mount(dmDevice, mountPoint,
933d0640f6358041f7e2657167560b357078db73526Jeff Sharkey                    false, false, false, ownerUid, 0, 0000, false);
934344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        }
935344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
936344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        if (mountStatus) {
93797ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat            SLOGE("ASEC FAT mount failed (%s)", strerror(errno));
938a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat            if (cleanupDm) {
939d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat                Devmapper::destroy(idHash);
940a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat            }
941a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat            Loop::destroyByDevice(loopDevice);
942a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat            unlink(asecFileName);
943a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat            return -1;
944b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        }
945344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
946344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        if (usingExt4) {
947ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey            int dirfd = open(mountPoint, O_DIRECTORY | O_CLOEXEC);
948344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            if (dirfd >= 0) {
949344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root                if (fchown(dirfd, ownerUid, AID_SYSTEM)
950344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root                        || fchmod(dirfd, S_IRUSR | S_IWUSR | S_IXUSR | S_ISGID | S_IRGRP | S_IXGRP)) {
951344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root                    SLOGI("Cannot chown/chmod new ASEC mount point %s", mountPoint);
952344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root                }
953344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root                close(dirfd);
954344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            }
955344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        }
956a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat    } else {
95797ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGI("Created raw secure container %s (no filesystem)", id);
958a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
95988705166ab82057090a070c6d4200c3d9db76f11San Mehat
960cbacf78eff70bd43bb899e164ec2ab409bc0904cKenny Root    mActiveContainers->push_back(new ContainerData(strdup(id), ASEC));
961a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    return 0;
962a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat}
963a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
964fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenbergint VolumeManager::resizeAsec(const char *id, unsigned numSectors, const char *key) {
965fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    char asecFileName[255];
966fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    char mountPoint[255];
967fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    bool cleanupDm = false;
968fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg
969fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    if (!isLegalAsecId(id)) {
970fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        SLOGE("resizeAsec: Invalid asec id \"%s\"", id);
971fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        errno = EINVAL;
972fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        return -1;
973fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    }
974fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg
975fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    if (findAsec(id, asecFileName, sizeof(asecFileName))) {
976fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        SLOGE("Couldn't find ASEC %s", id);
977fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        return -1;
978fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    }
979fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg
9809f18fe7807a4e4089778243dbbd08d154ec15540Jeff Sharkey    int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", VolumeManager::ASECDIR, id);
981fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) {
982fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg       SLOGE("ASEC resize failed for %s: couldn't construct mountpoint", id);
983fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg       return -1;
984fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    }
985fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg
986fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    if (isMountpointMounted(mountPoint)) {
987fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg       SLOGE("ASEC %s mounted. Unmount before resizing", id);
988fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg       errno = EBUSY;
989fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg       return -1;
990fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    }
991fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg
992fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    struct asec_superblock sb;
993fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    int fd;
994fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    unsigned int oldNumSec = 0;
995fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg
996ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey    if ((fd = open(asecFileName, O_RDONLY | O_CLOEXEC)) < 0) {
997fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        SLOGE("Failed to open ASEC file (%s)", strerror(errno));
998fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        return -1;
999fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    }
1000fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg
1001fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    struct stat info;
1002fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    if (fstat(fd, &info) < 0) {
1003fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        SLOGE("Failed to get file size (%s)", strerror(errno));
1004fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        close(fd);
1005fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        return -1;
1006fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    }
1007fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg
1008fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    oldNumSec = info.st_size / 512;
1009fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg
1010fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    unsigned numImgSectors;
1011fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    if (sb.c_opts & ASEC_SB_C_OPTS_EXT4)
1012fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        numImgSectors = adjustSectorNumExt4(numSectors);
1013fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    else
1014fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        numImgSectors = adjustSectorNumFAT(numSectors);
1015fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    /*
1016fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg     *  add one block for the superblock
1017fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg     */
1018fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    SLOGD("Resizing from %d sectors to %d sectors", oldNumSec, numImgSectors + 1);
101943ed123d3fc1a3edf3660cd0e2528e971abc399eJeff Sharkey    if (oldNumSec == numImgSectors + 1) {
102043ed123d3fc1a3edf3660cd0e2528e971abc399eJeff Sharkey        SLOGW("Size unchanged; ignoring resize request");
102143ed123d3fc1a3edf3660cd0e2528e971abc399eJeff Sharkey        return 0;
102243ed123d3fc1a3edf3660cd0e2528e971abc399eJeff Sharkey    } else if (oldNumSec > numImgSectors + 1) {
1023fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        SLOGE("Only growing is currently supported.");
1024fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        close(fd);
1025fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        return -1;
1026fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    }
1027fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg
1028fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    /*
1029fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg     * Try to read superblock.
1030fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg     */
1031fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    memset(&sb, 0, sizeof(struct asec_superblock));
1032fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    if (lseek(fd, ((oldNumSec - 1) * 512), SEEK_SET) < 0) {
1033fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        SLOGE("lseek failed (%s)", strerror(errno));
1034fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        close(fd);
1035fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        return -1;
1036fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    }
1037fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    if (read(fd, &sb, sizeof(struct asec_superblock)) != sizeof(struct asec_superblock)) {
1038fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        SLOGE("superblock read failed (%s)", strerror(errno));
1039fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        close(fd);
1040fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        return -1;
1041fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    }
1042fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    close(fd);
1043fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg
1044fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    if (mDebug) {
1045fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        SLOGD("Container sb magic/ver (%.8x/%.2x)", sb.magic, sb.ver);
1046fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    }
1047fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    if (sb.magic != ASEC_SB_MAGIC || sb.ver != ASEC_SB_VER) {
1048fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        SLOGE("Bad container magic/version (%.8x/%.2x)", sb.magic, sb.ver);
1049fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        errno = EMEDIUMTYPE;
1050fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        return -1;
1051fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    }
1052fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg
1053fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    if (!(sb.c_opts & ASEC_SB_C_OPTS_EXT4)) {
1054fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        SLOGE("Only ext4 partitions are supported for resize");
1055fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        errno = EINVAL;
1056fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        return -1;
1057fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    }
1058fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg
1059fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    if (Loop::resizeImageFile(asecFileName, numImgSectors + 1)) {
1060fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        SLOGE("Resize of ASEC image file failed. Could not resize %s", id);
1061fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        return -1;
1062fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    }
1063fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg
1064fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    /*
1065fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg     * Drop down a copy of the superblock at the end of the file
1066fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg     */
1067fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    if (writeSuperBlock(asecFileName, &sb, numImgSectors))
1068fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        goto fail;
1069fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg
1070fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    char idHash[33];
1071fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    if (!asecHash(id, idHash, sizeof(idHash))) {
1072fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        SLOGE("Hash of '%s' failed (%s)", id, strerror(errno));
1073fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        goto fail;
1074fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    }
1075fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg
1076fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    char loopDevice[255];
1077fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    if (setupLoopDevice(loopDevice, sizeof(loopDevice), asecFileName, idHash, mDebug))
1078fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        goto fail;
1079fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg
1080fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    char dmDevice[255];
1081fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg
1082fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    if (setupDevMapperDevice(dmDevice, sizeof(dmDevice), loopDevice, asecFileName, key, idHash, numImgSectors, &cleanupDm, mDebug)) {
1083fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        Loop::destroyByDevice(loopDevice);
1084fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        goto fail;
1085fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    }
1086fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg
1087fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    /*
1088fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg     * Wait for the device mapper node to be created.
1089fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg     */
1090fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    waitForDevMapper(dmDevice);
1091fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg
1092d0640f6358041f7e2657167560b357078db73526Jeff Sharkey    if (android::vold::ext4::Resize(dmDevice, numImgSectors)) {
1093fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        SLOGE("Unable to resize %s (%s)", id, strerror(errno));
1094fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        if (cleanupDm) {
1095fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg            Devmapper::destroy(idHash);
1096fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        }
1097fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        Loop::destroyByDevice(loopDevice);
1098fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        goto fail;
1099fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    }
1100fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg
1101fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    return 0;
1102fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenbergfail:
1103fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    Loop::resizeImageFile(asecFileName, oldNumSec);
1104fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    return -1;
1105fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg}
1106fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg
1107a19b250bd273455933ca3502cf2c2e0a803aff77San Mehatint VolumeManager::finalizeAsec(const char *id) {
1108a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char asecFileName[255];
1109a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char loopDevice[255];
1110a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char mountPoint[255];
1111a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
11120de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich    if (!isLegalAsecId(id)) {
11130de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich        SLOGE("finalizeAsec: Invalid asec id \"%s\"", id);
11140de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich        errno = EINVAL;
11150de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich        return -1;
11160de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich    }
11170de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich
1118344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    if (findAsec(id, asecFileName, sizeof(asecFileName))) {
1119344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        SLOGE("Couldn't find ASEC %s", id);
1120344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        return -1;
1121344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    }
1122a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
1123d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    char idHash[33];
1124d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    if (!asecHash(id, idHash, sizeof(idHash))) {
112597ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Hash of '%s' failed (%s)", id, strerror(errno));
1126d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        return -1;
1127d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    }
1128d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat
1129d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    if (Loop::lookupActive(idHash, loopDevice, sizeof(loopDevice))) {
113097ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Unable to finalize %s (%s)", id, strerror(errno));
1131a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
1132a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
1133a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
113414eab550e8a4f28889cc9ffbb92ddff8f18c4f03Hiroaki Miyazawa    unsigned long nr_sec = 0;
1135344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    struct asec_superblock sb;
1136344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
1137344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    if (Loop::lookupInfo(loopDevice, &sb, &nr_sec)) {
1138344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        return -1;
1139344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    }
1140344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
11419f18fe7807a4e4089778243dbbd08d154ec15540Jeff Sharkey    int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", VolumeManager::ASECDIR, id);
1142d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig    if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) {
1143d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig        SLOGE("ASEC finalize failed: couldn't construct mountPoint");
1144d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig        return -1;
1145d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig    }
1146344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
1147344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    int result = 0;
1148344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    if (sb.c_opts & ASEC_SB_C_OPTS_EXT4) {
1149d0640f6358041f7e2657167560b357078db73526Jeff Sharkey        result = android::vold::ext4::Mount(loopDevice, mountPoint,
1150d0640f6358041f7e2657167560b357078db73526Jeff Sharkey                true, true, true);
1151344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    } else {
1152d0640f6358041f7e2657167560b357078db73526Jeff Sharkey        result = android::vold::vfat::Mount(loopDevice, mountPoint,
1153d0640f6358041f7e2657167560b357078db73526Jeff Sharkey                true, true, true, 0, 0, 0227, false);
1154344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    }
1155344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
1156344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    if (result) {
115797ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("ASEC finalize mount failed (%s)", strerror(errno));
1158a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
1159a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
1160a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
1161d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    if (mDebug) {
116297ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGD("ASEC %s finalized", id);
1163d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    }
1164a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    return 0;
1165a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat}
1166a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
1167344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Rootint VolumeManager::fixupAsecPermissions(const char *id, gid_t gid, const char* filename) {
1168344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    char asecFileName[255];
1169344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    char loopDevice[255];
1170344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    char mountPoint[255];
1171344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
1172344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    if (gid < AID_APP) {
1173344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        SLOGE("Group ID is not in application range");
1174344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        return -1;
1175344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    }
1176344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
11770de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich    if (!isLegalAsecId(id)) {
11780de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich        SLOGE("fixupAsecPermissions: Invalid asec id \"%s\"", id);
11790de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich        errno = EINVAL;
11800de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich        return -1;
11810de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich    }
11820de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich
1183344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    if (findAsec(id, asecFileName, sizeof(asecFileName))) {
1184344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        SLOGE("Couldn't find ASEC %s", id);
1185344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        return -1;
1186344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    }
1187344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
1188344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    char idHash[33];
1189344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    if (!asecHash(id, idHash, sizeof(idHash))) {
1190344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        SLOGE("Hash of '%s' failed (%s)", id, strerror(errno));
1191344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        return -1;
1192344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    }
1193344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
1194344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    if (Loop::lookupActive(idHash, loopDevice, sizeof(loopDevice))) {
1195344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        SLOGE("Unable fix permissions during lookup on %s (%s)", id, strerror(errno));
1196344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        return -1;
1197344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    }
1198344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
119914eab550e8a4f28889cc9ffbb92ddff8f18c4f03Hiroaki Miyazawa    unsigned long nr_sec = 0;
1200344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    struct asec_superblock sb;
1201344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
1202344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    if (Loop::lookupInfo(loopDevice, &sb, &nr_sec)) {
1203344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        return -1;
1204344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    }
1205344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
12069f18fe7807a4e4089778243dbbd08d154ec15540Jeff Sharkey    int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", VolumeManager::ASECDIR, id);
1207d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig    if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) {
1208d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig        SLOGE("Unable remount to fix permissions for %s: couldn't construct mountpoint", id);
1209d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig        return -1;
1210d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig    }
1211344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
1212344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    int result = 0;
1213344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    if ((sb.c_opts & ASEC_SB_C_OPTS_EXT4) == 0) {
1214344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        return 0;
1215344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    }
1216344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
1217d0640f6358041f7e2657167560b357078db73526Jeff Sharkey    int ret = android::vold::ext4::Mount(loopDevice, mountPoint,
1218344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            false /* read-only */,
1219344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            true  /* remount */,
1220344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            false /* executable */);
1221344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    if (ret) {
1222344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        SLOGE("Unable remount to fix permissions for %s (%s)", id, strerror(errno));
1223344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        return -1;
1224344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    }
1225344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
1226344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    char *paths[] = { mountPoint, NULL };
1227344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
1228344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    FTS *fts = fts_open(paths, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, NULL);
1229344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    if (fts) {
1230344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        // Traverse the entire hierarchy and chown to system UID.
1231344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        for (FTSENT *ftsent = fts_read(fts); ftsent != NULL; ftsent = fts_read(fts)) {
1232344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            // We don't care about the lost+found directory.
1233344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            if (!strcmp(ftsent->fts_name, "lost+found")) {
1234344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root                continue;
1235344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            }
1236344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
1237344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            /*
1238344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root             * There can only be one file marked as private right now.
1239344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root             * This should be more robust, but it satisfies the requirements
1240344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root             * we have for right now.
1241344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root             */
1242344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            const bool privateFile = !strcmp(ftsent->fts_name, filename);
1243344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
1244ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey            int fd = open(ftsent->fts_accpath, O_NOFOLLOW | O_CLOEXEC);
1245344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            if (fd < 0) {
1246344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root                SLOGE("Couldn't open file %s: %s", ftsent->fts_accpath, strerror(errno));
1247344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root                result = -1;
1248344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root                continue;
1249344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            }
1250344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
1251344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            result |= fchown(fd, AID_SYSTEM, privateFile? gid : AID_SYSTEM);
1252344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
1253344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            if (ftsent->fts_info & FTS_D) {
12541a673c868c2d2d81fcaeab34b4a7c75d4a978584Kenny Root                result |= fchmod(fd, 0755);
1255348c8aba0d2df2996e0fe57900ef518c6aeb4b29Kenny Root            } else if (ftsent->fts_info & FTS_F) {
1256344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root                result |= fchmod(fd, privateFile ? 0640 : 0644);
1257344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            }
1258b9e3ba56cb4075f894a73b02ee70571456494ac1Robert Craig
12595093e6187da9c237c88383540f544c8dbaf37754Stephen Smalley            if (selinux_android_restorecon(ftsent->fts_path, 0) < 0) {
1260b9e3ba56cb4075f894a73b02ee70571456494ac1Robert Craig                SLOGE("restorecon failed for %s: %s\n", ftsent->fts_path, strerror(errno));
1261b9e3ba56cb4075f894a73b02ee70571456494ac1Robert Craig                result |= -1;
1262b9e3ba56cb4075f894a73b02ee70571456494ac1Robert Craig            }
1263b9e3ba56cb4075f894a73b02ee70571456494ac1Robert Craig
1264344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            close(fd);
1265344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        }
1266344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        fts_close(fts);
1267344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
1268344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        // Finally make the directory readable by everyone.
1269ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey        int dirfd = open(mountPoint, O_DIRECTORY | O_CLOEXEC);
1270344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        if (dirfd < 0 || fchmod(dirfd, 0755)) {
1271344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            SLOGE("Couldn't change owner of existing directory %s: %s", mountPoint, strerror(errno));
1272344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            result |= -1;
1273344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        }
1274344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        close(dirfd);
1275344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    } else {
1276344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        result |= -1;
1277344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    }
1278344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
1279d0640f6358041f7e2657167560b357078db73526Jeff Sharkey    result |= android::vold::ext4::Mount(loopDevice, mountPoint,
1280344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            true /* read-only */,
1281344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            true /* remount */,
1282344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            true /* execute */);
1283344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
1284344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    if (result) {
1285344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        SLOGE("ASEC fix permissions failed (%s)", strerror(errno));
1286344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        return -1;
1287344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    }
1288344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
1289344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    if (mDebug) {
1290344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        SLOGD("ASEC %s permissions fixed", id);
1291344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    }
1292344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    return 0;
1293344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root}
1294344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
1295048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehatint VolumeManager::renameAsec(const char *id1, const char *id2) {
1296344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    char asecFilename1[255];
1297048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat    char *asecFilename2;
1298048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat    char mountPoint[255];
1299048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat
1300344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    const char *dir;
1301344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
13020de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich    if (!isLegalAsecId(id1)) {
13030de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich        SLOGE("renameAsec: Invalid asec id1 \"%s\"", id1);
13040de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich        errno = EINVAL;
13050de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich        return -1;
13060de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich    }
13070de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich
13080de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich    if (!isLegalAsecId(id2)) {
13090de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich        SLOGE("renameAsec: Invalid asec id2 \"%s\"", id2);
13100de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich        errno = EINVAL;
13110de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich        return -1;
13120de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich    }
13130de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich
1314344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    if (findAsec(id1, asecFilename1, sizeof(asecFilename1), &dir)) {
1315344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        SLOGE("Couldn't find ASEC %s", id1);
1316344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        return -1;
1317344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    }
1318344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
1319344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    asprintf(&asecFilename2, "%s/%s.asec", dir, id2);
1320048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat
13219f18fe7807a4e4089778243dbbd08d154ec15540Jeff Sharkey    int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", VolumeManager::ASECDIR, id1);
1322d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig    if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) {
1323d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig        SLOGE("Rename failed: couldn't construct mountpoint");
1324d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig        goto out_err;
1325d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig    }
1326d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig
1327048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat    if (isMountpointMounted(mountPoint)) {
132897ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGW("Rename attempt when src mounted");
1329048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat        errno = EBUSY;
1330048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat        goto out_err;
1331048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat    }
1332048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat
13339f18fe7807a4e4089778243dbbd08d154ec15540Jeff Sharkey    written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", VolumeManager::ASECDIR, id2);
1334d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig    if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) {
1335d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig        SLOGE("Rename failed: couldn't construct mountpoint2");
1336d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig        goto out_err;
1337d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig    }
1338d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig
133996956ed0e220cb62a4a96136976ded0d8c2d9075San Mehat    if (isMountpointMounted(mountPoint)) {
134097ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGW("Rename attempt when dst mounted");
134196956ed0e220cb62a4a96136976ded0d8c2d9075San Mehat        errno = EBUSY;
134296956ed0e220cb62a4a96136976ded0d8c2d9075San Mehat        goto out_err;
134396956ed0e220cb62a4a96136976ded0d8c2d9075San Mehat    }
134496956ed0e220cb62a4a96136976ded0d8c2d9075San Mehat
1345048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat    if (!access(asecFilename2, F_OK)) {
134697ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Rename attempt when dst exists");
1347048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat        errno = EADDRINUSE;
1348048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat        goto out_err;
1349048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat    }
1350048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat
1351048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat    if (rename(asecFilename1, asecFilename2)) {
135297ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Rename of '%s' to '%s' failed (%s)", asecFilename1, asecFilename2, strerror(errno));
1353048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat        goto out_err;
1354048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat    }
1355048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat
1356048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat    free(asecFilename2);
1357048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat    return 0;
1358048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat
1359048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehatout_err:
1360048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat    free(asecFilename2);
1361048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat    return -1;
1362048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat}
1363048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat
1364fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root#define UNMOUNT_RETRIES 5
1365fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root#define UNMOUNT_SLEEP_BETWEEN_RETRY_MS (1000 * 1000)
13664ba8948dc16463053e21cda5744f519a555080d0San Mehatint VolumeManager::unmountAsec(const char *id, bool force) {
1367a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char asecFileName[255];
1368a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char mountPoint[255];
1369a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
13700de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich    if (!isLegalAsecId(id)) {
13710de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich        SLOGE("unmountAsec: Invalid asec id \"%s\"", id);
13720de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich        errno = EINVAL;
13730de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich        return -1;
13740de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich    }
13750de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich
1376344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    if (findAsec(id, asecFileName, sizeof(asecFileName))) {
1377344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        SLOGE("Couldn't find ASEC %s", id);
1378344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        return -1;
1379344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    }
1380344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
13819f18fe7807a4e4089778243dbbd08d154ec15540Jeff Sharkey    int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", VolumeManager::ASECDIR, id);
1382d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig    if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) {
1383d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig        SLOGE("ASEC unmount failed for %s: couldn't construct mountpoint", id);
1384d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig        return -1;
1385d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig    }
1386a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
1387d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    char idHash[33];
1388d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    if (!asecHash(id, idHash, sizeof(idHash))) {
138997ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Hash of '%s' failed (%s)", id, strerror(errno));
1390d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        return -1;
1391d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    }
1392d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat
1393fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    return unmountLoopImage(id, idHash, asecFileName, mountPoint, force);
1394fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root}
1395fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root
1396508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Rootint VolumeManager::unmountObb(const char *fileName, bool force) {
1397fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    char mountPoint[255];
1398fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root
1399fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    char idHash[33];
1400fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    if (!asecHash(fileName, idHash, sizeof(idHash))) {
1401fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        SLOGE("Hash of '%s' failed (%s)", fileName, strerror(errno));
1402fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        return -1;
1403fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    }
1404fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root
14059f18fe7807a4e4089778243dbbd08d154ec15540Jeff Sharkey    int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", VolumeManager::LOOPDIR, idHash);
1406d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig    if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) {
1407d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig        SLOGE("OBB unmount failed for %s: couldn't construct mountpoint", fileName);
1408d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig        return -1;
1409d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig    }
1410fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root
1411fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    return unmountLoopImage(fileName, idHash, fileName, mountPoint, force);
1412fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root}
1413fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root
1414fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Rootint VolumeManager::unmountLoopImage(const char *id, const char *idHash,
1415fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        const char *fileName, const char *mountPoint, bool force) {
14160586d54053ee00e6d6523d4f125282ccb9a24aabSan Mehat    if (!isMountpointMounted(mountPoint)) {
1417fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        SLOGE("Unmount request for %s when not mounted", id);
1418918e5f9f10b9c1ff929683743ffbf229027ce240Kenny Root        errno = ENOENT;
1419b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        return -1;
1420b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    }
142123969931fad6e993832208f099f6eea0f6f76eb5San Mehat
1422b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    int i, rc;
1423fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    for (i = 1; i <= UNMOUNT_RETRIES; i++) {
1424b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        rc = umount(mountPoint);
1425b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        if (!rc) {
1426b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            break;
1427a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        }
1428b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        if (rc && (errno == EINVAL || errno == ENOENT)) {
1429fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root            SLOGI("Container %s unmounted OK", id);
1430b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            rc = 0;
1431b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            break;
1432a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        }
1433fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        SLOGW("%s unmount attempt %d failed (%s)",
14348c940ef7dbd423cadc92982b44a65ed1014389e2San Mehat              id, i, strerror(errno));
14358c940ef7dbd423cadc92982b44a65ed1014389e2San Mehat
143636801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey        int signal = 0; // default is to just complain
14374ba8948dc16463053e21cda5744f519a555080d0San Mehat
14384ba8948dc16463053e21cda5744f519a555080d0San Mehat        if (force) {
1439fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root            if (i > (UNMOUNT_RETRIES - 2))
144036801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey                signal = SIGKILL;
1441fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root            else if (i > (UNMOUNT_RETRIES - 3))
144236801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey                signal = SIGTERM;
14434ba8948dc16463053e21cda5744f519a555080d0San Mehat        }
14448c940ef7dbd423cadc92982b44a65ed1014389e2San Mehat
144536801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey        Process::killProcessesWithOpenFiles(mountPoint, signal);
1446fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        usleep(UNMOUNT_SLEEP_BETWEEN_RETRY_MS);
1447b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    }
1448b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
1449b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    if (rc) {
14504ba8948dc16463053e21cda5744f519a555080d0San Mehat        errno = EBUSY;
145197ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Failed to unmount container %s (%s)", id, strerror(errno));
1452b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        return -1;
1453b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    }
1454b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
145512f4b89046b54de1bdc188b7057ba77d7566e573San Mehat    int retries = 10;
145612f4b89046b54de1bdc188b7057ba77d7566e573San Mehat
145712f4b89046b54de1bdc188b7057ba77d7566e573San Mehat    while(retries--) {
145812f4b89046b54de1bdc188b7057ba77d7566e573San Mehat        if (!rmdir(mountPoint)) {
145912f4b89046b54de1bdc188b7057ba77d7566e573San Mehat            break;
146012f4b89046b54de1bdc188b7057ba77d7566e573San Mehat        }
146112f4b89046b54de1bdc188b7057ba77d7566e573San Mehat
146297ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGW("Failed to rmdir %s (%s)", mountPoint, strerror(errno));
1463fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        usleep(UNMOUNT_SLEEP_BETWEEN_RETRY_MS);
146412f4b89046b54de1bdc188b7057ba77d7566e573San Mehat    }
146512f4b89046b54de1bdc188b7057ba77d7566e573San Mehat
146612f4b89046b54de1bdc188b7057ba77d7566e573San Mehat    if (!retries) {
146797ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Timed out trying to rmdir %s (%s)", mountPoint, strerror(errno));
1468f5c61980969a0b49bda37b5dc94ffe675ebd5a5aSan Mehat    }
146988705166ab82057090a070c6d4200c3d9db76f11San Mehat
147060dec16c5026d29a52791ad790860d247f47f8f2Paul Lawrence    for (i=1; i <= UNMOUNT_RETRIES; i++) {
147160dec16c5026d29a52791ad790860d247f47f8f2Paul Lawrence        if (Devmapper::destroy(idHash) && errno != ENXIO) {
147260dec16c5026d29a52791ad790860d247f47f8f2Paul Lawrence            SLOGE("Failed to destroy devmapper instance (%s)", strerror(errno));
147360dec16c5026d29a52791ad790860d247f47f8f2Paul Lawrence            usleep(UNMOUNT_SLEEP_BETWEEN_RETRY_MS);
147460dec16c5026d29a52791ad790860d247f47f8f2Paul Lawrence            continue;
147560dec16c5026d29a52791ad790860d247f47f8f2Paul Lawrence        } else {
147660dec16c5026d29a52791ad790860d247f47f8f2Paul Lawrence          break;
147760dec16c5026d29a52791ad790860d247f47f8f2Paul Lawrence        }
1478a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
1479a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
1480a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char loopDevice[255];
1481d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    if (!Loop::lookupActive(idHash, loopDevice, sizeof(loopDevice))) {
1482a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        Loop::destroyByDevice(loopDevice);
1483d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    } else {
1484fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        SLOGW("Failed to find loop device for {%s} (%s)", fileName, strerror(errno));
1485a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
148688705166ab82057090a070c6d4200c3d9db76f11San Mehat
148788705166ab82057090a070c6d4200c3d9db76f11San Mehat    AsecIdCollection::iterator it;
148888705166ab82057090a070c6d4200c3d9db76f11San Mehat    for (it = mActiveContainers->begin(); it != mActiveContainers->end(); ++it) {
1489cbacf78eff70bd43bb899e164ec2ab409bc0904cKenny Root        ContainerData* cd = *it;
1490cbacf78eff70bd43bb899e164ec2ab409bc0904cKenny Root        if (!strcmp(cd->id, id)) {
149188705166ab82057090a070c6d4200c3d9db76f11San Mehat            free(*it);
149288705166ab82057090a070c6d4200c3d9db76f11San Mehat            mActiveContainers->erase(it);
149388705166ab82057090a070c6d4200c3d9db76f11San Mehat            break;
149488705166ab82057090a070c6d4200c3d9db76f11San Mehat        }
149588705166ab82057090a070c6d4200c3d9db76f11San Mehat    }
149688705166ab82057090a070c6d4200c3d9db76f11San Mehat    if (it == mActiveContainers->end()) {
149797ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGW("mActiveContainers is inconsistent!");
149888705166ab82057090a070c6d4200c3d9db76f11San Mehat    }
1499b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    return 0;
1500b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat}
1501b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
15024ba8948dc16463053e21cda5744f519a555080d0San Mehatint VolumeManager::destroyAsec(const char *id, bool force) {
1503b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    char asecFileName[255];
1504b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    char mountPoint[255];
1505b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
15060de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich    if (!isLegalAsecId(id)) {
15070de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich        SLOGE("destroyAsec: Invalid asec id \"%s\"", id);
15080de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich        errno = EINVAL;
15090de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich        return -1;
15100de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich    }
15110de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich
1512344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    if (findAsec(id, asecFileName, sizeof(asecFileName))) {
1513344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        SLOGE("Couldn't find ASEC %s", id);
1514344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        return -1;
1515344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    }
1516344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
15179f18fe7807a4e4089778243dbbd08d154ec15540Jeff Sharkey    int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", VolumeManager::ASECDIR, id);
1518d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig    if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) {
1519d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig        SLOGE("ASEC destroy failed for %s: couldn't construct mountpoint", id);
1520d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig        return -1;
1521d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig    }
1522b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
15230586d54053ee00e6d6523d4f125282ccb9a24aabSan Mehat    if (isMountpointMounted(mountPoint)) {
1524d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        if (mDebug) {
152597ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat            SLOGD("Unmounting container before destroy");
1526d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        }
15274ba8948dc16463053e21cda5744f519a555080d0San Mehat        if (unmountAsec(id, force)) {
152897ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat            SLOGE("Failed to unmount asec %s for destroy (%s)", id, strerror(errno));
15290586d54053ee00e6d6523d4f125282ccb9a24aabSan Mehat            return -1;
15300586d54053ee00e6d6523d4f125282ccb9a24aabSan Mehat        }
15310586d54053ee00e6d6523d4f125282ccb9a24aabSan Mehat    }
1532a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
15330586d54053ee00e6d6523d4f125282ccb9a24aabSan Mehat    if (unlink(asecFileName)) {
153497ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Failed to unlink asec '%s' (%s)", asecFileName, strerror(errno));
15350586d54053ee00e6d6523d4f125282ccb9a24aabSan Mehat        return -1;
15360586d54053ee00e6d6523d4f125282ccb9a24aabSan Mehat    }
1537a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
1538d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    if (mDebug) {
153997ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGD("ASEC %s destroyed", id);
1540d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    }
1541a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    return 0;
1542a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat}
1543a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
15440de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich/*
15450de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich * Legal ASEC ids consist of alphanumeric characters, '-',
15460de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich * '_', or '.'. ".." is not allowed. The first or last character
15470de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich * of the ASEC id cannot be '.' (dot).
15480de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich */
15490de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevichbool VolumeManager::isLegalAsecId(const char *id) const {
15500de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich    size_t i;
15510de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich    size_t len = strlen(id);
15520de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich
15530de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich    if (len == 0) {
15540de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich        return false;
15550de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich    }
15560de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich    if ((id[0] == '.') || (id[len - 1] == '.')) {
15570de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich        return false;
15580de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich    }
15590de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich
15600de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich    for (i = 0; i < len; i++) {
15610de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich        if (id[i] == '.') {
15620de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich            // i=0 is guaranteed never to have a dot. See above.
15630de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich            if (id[i-1] == '.') return false;
15640de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich            continue;
15650de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich        }
15660de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich        if (id[i] == '_' || id[i] == '-') continue;
15670de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich        if (id[i] >= 'a' && id[i] <= 'z') continue;
15680de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich        if (id[i] >= 'A' && id[i] <= 'Z') continue;
15690de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich        if (id[i] >= '0' && id[i] <= '9') continue;
15700de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich        return false;
15710de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich    }
15720de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich
15730de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich    return true;
15740de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich}
15750de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich
1576344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Rootbool VolumeManager::isAsecInDirectory(const char *dir, const char *asecName) const {
1577ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey    int dirfd = open(dir, O_DIRECTORY | O_CLOEXEC);
1578344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    if (dirfd < 0) {
1579344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        SLOGE("Couldn't open internal ASEC dir (%s)", strerror(errno));
158025e581a11c2752a9fe857c4859469f367d53f35eNick Kralevich        return false;
1581344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    }
1582344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
158325e581a11c2752a9fe857c4859469f367d53f35eNick Kralevich    struct stat sb;
158425e581a11c2752a9fe857c4859469f367d53f35eNick Kralevich    bool ret = (fstatat(dirfd, asecName, &sb, AT_SYMLINK_NOFOLLOW) == 0)
158525e581a11c2752a9fe857c4859469f367d53f35eNick Kralevich        && S_ISREG(sb.st_mode);
1586344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
1587344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    close(dirfd);
1588344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
1589344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    return ret;
1590344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root}
1591344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
1592344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Rootint VolumeManager::findAsec(const char *id, char *asecPath, size_t asecPathLen,
1593344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        const char **directory) const {
1594344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    char *asecName;
1595344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
15960de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich    if (!isLegalAsecId(id)) {
15970de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich        SLOGE("findAsec: Invalid asec id \"%s\"", id);
15980de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich        errno = EINVAL;
15990de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich        return -1;
16000de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich    }
16010de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich
1602344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    if (asprintf(&asecName, "%s.asec", id) < 0) {
1603344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        SLOGE("Couldn't allocate string to write ASEC name");
1604344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        return -1;
1605344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    }
1606344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
1607344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    const char *dir;
16089f18fe7807a4e4089778243dbbd08d154ec15540Jeff Sharkey    if (isAsecInDirectory(VolumeManager::SEC_ASECDIR_INT, asecName)) {
16099f18fe7807a4e4089778243dbbd08d154ec15540Jeff Sharkey        dir = VolumeManager::SEC_ASECDIR_INT;
16109f18fe7807a4e4089778243dbbd08d154ec15540Jeff Sharkey    } else if (isAsecInDirectory(VolumeManager::SEC_ASECDIR_EXT, asecName)) {
16119f18fe7807a4e4089778243dbbd08d154ec15540Jeff Sharkey        dir = VolumeManager::SEC_ASECDIR_EXT;
1612344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    } else {
1613344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        free(asecName);
1614344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        return -1;
1615344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    }
1616344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
1617344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    if (directory != NULL) {
1618344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        *directory = dir;
1619344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    }
1620344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
1621344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    if (asecPath != NULL) {
1622344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        int written = snprintf(asecPath, asecPathLen, "%s/%s", dir, asecName);
1623d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig        if ((written < 0) || (size_t(written) >= asecPathLen)) {
1624d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig            SLOGE("findAsec failed for %s: couldn't construct ASEC path", id);
1625344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            free(asecName);
1626344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            return -1;
1627344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        }
1628344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    }
1629344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
1630344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    free(asecName);
1631344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    return 0;
1632344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root}
1633344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
163443ed123d3fc1a3edf3660cd0e2528e971abc399eJeff Sharkeyint VolumeManager::mountAsec(const char *id, const char *key, int ownerUid, bool readOnly) {
1635a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char asecFileName[255];
1636a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char mountPoint[255];
1637a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
16380de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich    if (!isLegalAsecId(id)) {
16390de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich        SLOGE("mountAsec: Invalid asec id \"%s\"", id);
16400de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich        errno = EINVAL;
16410de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich        return -1;
16420de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich    }
16430de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich
1644344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    if (findAsec(id, asecFileName, sizeof(asecFileName))) {
1645344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        SLOGE("Couldn't find ASEC %s", id);
1646344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        return -1;
1647344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    }
1648344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
16499f18fe7807a4e4089778243dbbd08d154ec15540Jeff Sharkey    int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", VolumeManager::ASECDIR, id);
1650d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig    if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) {
165159846b654e8b4a22a1be11cd21d6c5b81375abd2Colin Cross        SLOGE("ASEC mount failed for %s: couldn't construct mountpoint", id);
1652d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig        return -1;
1653d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig    }
1654a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
1655a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (isMountpointMounted(mountPoint)) {
165697ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("ASEC %s already mounted", id);
1657a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        errno = EBUSY;
1658a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
1659a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
1660a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
1661d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    char idHash[33];
1662d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    if (!asecHash(id, idHash, sizeof(idHash))) {
166397ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Hash of '%s' failed (%s)", id, strerror(errno));
1664d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        return -1;
1665d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    }
16667b18a7b36f61574c0f0bdde0a7409dc36676fa12Kenny Root
1667a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char loopDevice[255];
1668fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    if (setupLoopDevice(loopDevice, sizeof(loopDevice), asecFileName, idHash, mDebug))
1669fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        return -1;
1670b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
1671b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    char dmDevice[255];
1672b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    bool cleanupDm = false;
16738439dc9fd569794b1a31f67cf43d9212de33eeccTim Murray
167414eab550e8a4f28889cc9ffbb92ddff8f18c4f03Hiroaki Miyazawa    unsigned long nr_sec = 0;
1675fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    struct asec_superblock sb;
1676344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
1677344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    if (Loop::lookupInfo(loopDevice, &sb, &nr_sec)) {
1678fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        return -1;
1679fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    }
1680fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat
1681d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    if (mDebug) {
168297ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGD("Container sb magic/ver (%.8x/%.2x)", sb.magic, sb.ver);
1683d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    }
1684fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    if (sb.magic != ASEC_SB_MAGIC || sb.ver != ASEC_SB_VER) {
168597ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Bad container magic/version (%.8x/%.2x)", sb.magic, sb.ver);
1686fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        Loop::destroyByDevice(loopDevice);
1687fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        errno = EMEDIUMTYPE;
1688fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        return -1;
1689fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    }
1690fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    nr_sec--; // We don't want the devmapping to extend onto our superblock
1691fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat
1692fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    if (setupDevMapperDevice(dmDevice, sizeof(dmDevice), loopDevice, asecFileName, key, idHash , nr_sec, &cleanupDm, mDebug)) {
1693fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        Loop::destroyByDevice(loopDevice);
1694fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        return -1;
1695a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
1696a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
1697344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    if (mkdir(mountPoint, 0000)) {
1698b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        if (errno != EEXIST) {
169997ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat            SLOGE("Mountpoint creation failed (%s)", strerror(errno));
1700b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            if (cleanupDm) {
1701d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat                Devmapper::destroy(idHash);
1702b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            }
1703b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            Loop::destroyByDevice(loopDevice);
1704b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            return -1;
1705b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        }
1706a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
1707a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
1708cdc2a1c83575a349ee44035de8c3b38b8b401003Kenny Root    /*
1709fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg     * Wait for the device mapper node to be created.
1710cdc2a1c83575a349ee44035de8c3b38b8b401003Kenny Root     */
1711fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    waitForDevMapper(dmDevice);
1712cdc2a1c83575a349ee44035de8c3b38b8b401003Kenny Root
1713344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    int result;
1714344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    if (sb.c_opts & ASEC_SB_C_OPTS_EXT4) {
1715d0640f6358041f7e2657167560b357078db73526Jeff Sharkey        result = android::vold::ext4::Mount(dmDevice, mountPoint,
1716d0640f6358041f7e2657167560b357078db73526Jeff Sharkey                readOnly, false, readOnly);
1717344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    } else {
1718d0640f6358041f7e2657167560b357078db73526Jeff Sharkey        result = android::vold::vfat::Mount(dmDevice, mountPoint,
1719d0640f6358041f7e2657167560b357078db73526Jeff Sharkey                readOnly, false, readOnly, ownerUid, 0, 0222, false);
1720344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    }
1721344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
1722344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    if (result) {
172397ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("ASEC mount failed (%s)", strerror(errno));
1724b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        if (cleanupDm) {
1725d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat            Devmapper::destroy(idHash);
1726b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        }
1727b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        Loop::destroyByDevice(loopDevice);
1728a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
1729a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
1730a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
1731cbacf78eff70bd43bb899e164ec2ab409bc0904cKenny Root    mActiveContainers->push_back(new ContainerData(strdup(id), ASEC));
1732d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    if (mDebug) {
173397ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGD("ASEC %s mounted", id);
1734d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    }
1735a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    return 0;
1736a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat}
1737a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
1738fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root/**
1739fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root * Mounts an image file <code>img</code>.
1740fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root */
17416947904a76b69a1db20a3ddd30c0bcd281922fdeJeff Sharkeyint VolumeManager::mountObb(const char *img, const char *key, int ownerGid) {
1742fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    char mountPoint[255];
1743fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root
1744fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    char idHash[33];
1745fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    if (!asecHash(img, idHash, sizeof(idHash))) {
1746fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        SLOGE("Hash of '%s' failed (%s)", img, strerror(errno));
1747fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        return -1;
1748fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    }
1749fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root
17509f18fe7807a4e4089778243dbbd08d154ec15540Jeff Sharkey    int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", VolumeManager::LOOPDIR, idHash);
1751d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig    if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) {
175259846b654e8b4a22a1be11cd21d6c5b81375abd2Colin Cross        SLOGE("OBB mount failed for %s: couldn't construct mountpoint", img);
1753d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig        return -1;
1754d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig    }
1755fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root
1756fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    if (isMountpointMounted(mountPoint)) {
1757fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        SLOGE("Image %s already mounted", img);
1758fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        errno = EBUSY;
1759fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        return -1;
1760fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    }
1761fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root
1762fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    char loopDevice[255];
1763fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    if (setupLoopDevice(loopDevice, sizeof(loopDevice), img, idHash, mDebug))
1764fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        return -1;
1765fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root
1766fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    char dmDevice[255];
1767fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    bool cleanupDm = false;
1768fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    int fd;
176914eab550e8a4f28889cc9ffbb92ddff8f18c4f03Hiroaki Miyazawa    unsigned long nr_sec = 0;
1770fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root
1771ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey    if ((fd = open(loopDevice, O_RDWR | O_CLOEXEC)) < 0) {
1772fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        SLOGE("Failed to open loopdevice (%s)", strerror(errno));
1773fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        Loop::destroyByDevice(loopDevice);
1774fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        return -1;
1775fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    }
1776fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root
177714eab550e8a4f28889cc9ffbb92ddff8f18c4f03Hiroaki Miyazawa    get_blkdev_size(fd, &nr_sec);
177814eab550e8a4f28889cc9ffbb92ddff8f18c4f03Hiroaki Miyazawa    if (nr_sec == 0) {
1779fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        SLOGE("Failed to get loop size (%s)", strerror(errno));
1780fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        Loop::destroyByDevice(loopDevice);
1781fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        close(fd);
1782fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        return -1;
1783fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    }
1784fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root
1785fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    close(fd);
1786fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root
178714eab550e8a4f28889cc9ffbb92ddff8f18c4f03Hiroaki Miyazawa    if (setupDevMapperDevice(dmDevice, sizeof(loopDevice), loopDevice, img,key, idHash, nr_sec, &cleanupDm, mDebug)) {
1788fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        Loop::destroyByDevice(loopDevice);
1789fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        return -1;
1790fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    }
1791fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root
1792fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    if (mkdir(mountPoint, 0755)) {
1793fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        if (errno != EEXIST) {
1794fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root            SLOGE("Mountpoint creation failed (%s)", strerror(errno));
1795fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root            if (cleanupDm) {
1796fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root                Devmapper::destroy(idHash);
1797fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root            }
1798fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root            Loop::destroyByDevice(loopDevice);
1799fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root            return -1;
1800fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        }
1801fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    }
1802fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root
1803476a627e5562fbe004300d9243927b77c42aff57yoshiyuki hama    /*
1804476a627e5562fbe004300d9243927b77c42aff57yoshiyuki hama     * Wait for the device mapper node to be created.
1805476a627e5562fbe004300d9243927b77c42aff57yoshiyuki hama     */
1806476a627e5562fbe004300d9243927b77c42aff57yoshiyuki hama    waitForDevMapper(dmDevice);
1807476a627e5562fbe004300d9243927b77c42aff57yoshiyuki hama
1808d0640f6358041f7e2657167560b357078db73526Jeff Sharkey    if (android::vold::vfat::Mount(dmDevice, mountPoint,
1809d0640f6358041f7e2657167560b357078db73526Jeff Sharkey            true, false, true, 0, ownerGid, 0227, false)) {
1810fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        SLOGE("Image mount failed (%s)", strerror(errno));
1811fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        if (cleanupDm) {
1812fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root            Devmapper::destroy(idHash);
1813fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        }
1814fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        Loop::destroyByDevice(loopDevice);
1815fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        return -1;
1816fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    }
1817fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root
1818cbacf78eff70bd43bb899e164ec2ab409bc0904cKenny Root    mActiveContainers->push_back(new ContainerData(strdup(img), OBB));
1819fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    if (mDebug) {
1820fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        SLOGD("Image %s mounted", img);
1821fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    }
1822fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    return 0;
1823fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root}
1824fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root
1825508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Rootint VolumeManager::listMountedObbs(SocketClient* cli) {
1826d1104f75a736210a95ba890473d78e8dfc8b8915Yabin Cui    FILE *fp = setmntent("/proc/mounts", "r");
1827d1104f75a736210a95ba890473d78e8dfc8b8915Yabin Cui    if (fp == NULL) {
1828508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root        SLOGE("Error opening /proc/mounts (%s)", strerror(errno));
1829508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root        return -1;
1830508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root    }
1831508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root
1832508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root    // Create a string to compare against that has a trailing slash
18339f18fe7807a4e4089778243dbbd08d154ec15540Jeff Sharkey    int loopDirLen = strlen(VolumeManager::LOOPDIR);
1834508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root    char loopDir[loopDirLen + 2];
18359f18fe7807a4e4089778243dbbd08d154ec15540Jeff Sharkey    strcpy(loopDir, VolumeManager::LOOPDIR);
1836508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root    loopDir[loopDirLen++] = '/';
1837508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root    loopDir[loopDirLen] = '\0';
1838508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root
1839d1104f75a736210a95ba890473d78e8dfc8b8915Yabin Cui    mntent* mentry;
1840d1104f75a736210a95ba890473d78e8dfc8b8915Yabin Cui    while ((mentry = getmntent(fp)) != NULL) {
1841d1104f75a736210a95ba890473d78e8dfc8b8915Yabin Cui        if (!strncmp(mentry->mnt_dir, loopDir, loopDirLen)) {
1842ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey            int fd = open(mentry->mnt_fsname, O_RDONLY | O_CLOEXEC);
1843508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root            if (fd >= 0) {
1844508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root                struct loop_info64 li;
1845508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root                if (ioctl(fd, LOOP_GET_STATUS64, &li) >= 0) {
1846508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root                    cli->sendMsg(ResponseCode::AsecListResult,
1847508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root                            (const char*) li.lo_file_name, false);
1848508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root                }
1849508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root                close(fd);
1850508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root            }
1851508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root        }
1852508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root    }
1853d1104f75a736210a95ba890473d78e8dfc8b8915Yabin Cui    endmntent(fp);
1854508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root    return 0;
1855508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root}
1856508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root
18579c48498f4529f623650c56d03e63324c8d813032Jeff Sharkeyextern "C" int vold_unmountAll(void) {
1858425524dba1552ab3d2ad39e205e65d0a2af997f2Ken Sumrall    VolumeManager *vm = VolumeManager::Instance();
18599c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    return vm->unmountAll();
1860425524dba1552ab3d2ad39e205e65d0a2af997f2Ken Sumrall}
1861425524dba1552ab3d2ad39e205e65d0a2af997f2Ken Sumrall
1862a19b250bd273455933ca3502cf2c2e0a803aff77San Mehatbool VolumeManager::isMountpointMounted(const char *mp)
1863a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat{
1864d1104f75a736210a95ba890473d78e8dfc8b8915Yabin Cui    FILE *fp = setmntent("/proc/mounts", "r");
1865d1104f75a736210a95ba890473d78e8dfc8b8915Yabin Cui    if (fp == NULL) {
186697ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Error opening /proc/mounts (%s)", strerror(errno));
1867a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return false;
1868a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
1869a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
1870d1104f75a736210a95ba890473d78e8dfc8b8915Yabin Cui    bool found_mp = false;
1871d1104f75a736210a95ba890473d78e8dfc8b8915Yabin Cui    mntent* mentry;
1872d1104f75a736210a95ba890473d78e8dfc8b8915Yabin Cui    while ((mentry = getmntent(fp)) != NULL) {
1873d1104f75a736210a95ba890473d78e8dfc8b8915Yabin Cui        if (strcmp(mentry->mnt_dir, mp) == 0) {
1874d1104f75a736210a95ba890473d78e8dfc8b8915Yabin Cui            found_mp = true;
1875d1104f75a736210a95ba890473d78e8dfc8b8915Yabin Cui            break;
1876a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        }
1877a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
1878d1104f75a736210a95ba890473d78e8dfc8b8915Yabin Cui    endmntent(fp);
1879d1104f75a736210a95ba890473d78e8dfc8b8915Yabin Cui    return found_mp;
1880a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat}
1881a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
188271ebe154a5fbbb4b394a439ff0b6b9c84fbd04f5Jeff Sharkeyint VolumeManager::mkdirs(char* path) {
188336801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    // Only offer to create directories for paths managed by vold
188436801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    if (strncmp(path, "/storage/", 9) == 0) {
188536801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey        // fs_mkdirs() does symlink checking and relative path enforcement
188636801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey        return fs_mkdirs(path, 0700);
188771ebe154a5fbbb4b394a439ff0b6b9c84fbd04f5Jeff Sharkey    } else {
188827cfee3fa4e44d3a542312938df12cadfad3425eCylen Yao        SLOGE("Failed to find mounted volume for %s", path);
188971ebe154a5fbbb4b394a439ff0b6b9c84fbd04f5Jeff Sharkey        return -EINVAL;
189071ebe154a5fbbb4b394a439ff0b6b9c84fbd04f5Jeff Sharkey    }
189171ebe154a5fbbb4b394a439ff0b6b9c84fbd04f5Jeff Sharkey}
1892