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