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 17f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#include <stdio.h> 18fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat#include <stdlib.h> 19fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat#include <string.h> 20f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#include <errno.h> 21a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#include <fcntl.h> 22344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root#include <fts.h> 23344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root#include <unistd.h> 24a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat#include <sys/stat.h> 25a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat#include <sys/types.h> 26a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat#include <sys/mount.h> 27fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg#include <sys/ioctl.h> 28425524dba1552ab3d2ad39e205e65d0a2af997f2Ken Sumrall#include <dirent.h> 29a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat 30a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#include <linux/kdev_t.h> 31f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat 32f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#define LOG_TAG "Vold" 33f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat 347b18a7b36f61574c0f0bdde0a7409dc36676fa12Kenny Root#include <openssl/md5.h> 357b18a7b36f61574c0f0bdde0a7409dc36676fa12Kenny Root 3671ebe154a5fbbb4b394a439ff0b6b9c84fbd04f5Jeff Sharkey#include <cutils/fs.h> 37f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#include <cutils/log.h> 38f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat 39b9e3ba56cb4075f894a73b02ee70571456494ac1Robert Craig#include <selinux/android.h> 40b9e3ba56cb4075f894a73b02ee70571456494ac1Robert Craig 41fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat#include <sysutils/NetlinkEvent.h> 42fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat 43344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root#include <private/android_filesystem_config.h> 44344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root 45f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#include "VolumeManager.h" 46ae10b91044bf76b40b77d81c169e48e0bbdf6d75San Mehat#include "DirectVolume.h" 47a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#include "ResponseCode.h" 48a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat#include "Loop.h" 49344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root#include "Ext4.h" 50a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat#include "Fat.h" 51b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat#include "Devmapper.h" 52586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat#include "Process.h" 53fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat#include "Asec.h" 5429d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall#include "cryptfs.h" 5523969931fad6e993832208f099f6eea0f6f76eb5San Mehat 5697f2fc110b2ace7914671c2f5852379bd78922e4Mike Lockwood#define MASS_STORAGE_FILE_PATH "/sys/class/android_usb/android0/f_mass_storage/lun/file" 5797f2fc110b2ace7914671c2f5852379bd78922e4Mike Lockwood 586a74dcaa6e646fea8e00b7c04332fc60fe7e017cDaniel Rosenberg#define ROUND_UP_POWER_OF_2(number, po2) (((!!(number & ((1U << po2) - 1))) << po2)\ 596a74dcaa6e646fea8e00b7c04332fc60fe7e017cDaniel Rosenberg + (number & (~((1U << po2) - 1)))) 606a74dcaa6e646fea8e00b7c04332fc60fe7e017cDaniel Rosenberg 61fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg/* writes superblock at end of file or device given by name */ 62fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenbergstatic int writeSuperBlock(const char* name, struct asec_superblock *sb, unsigned int numImgSectors) { 63fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg int sbfd = open(name, O_RDWR); 64fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg if (sbfd < 0) { 65fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg SLOGE("Failed to open %s for superblock write (%s)", name, strerror(errno)); 66fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg return -1; 67fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg } 68fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg 69fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg if (lseek(sbfd, (numImgSectors * 512), SEEK_SET) < 0) { 70fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg SLOGE("Failed to lseek for superblock (%s)", strerror(errno)); 71fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg close(sbfd); 72fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg return -1; 73fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg } 74fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg 75fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg if (write(sbfd, sb, sizeof(struct asec_superblock)) != sizeof(struct asec_superblock)) { 76fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg SLOGE("Failed to write superblock (%s)", strerror(errno)); 77fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg close(sbfd); 78fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg return -1; 79fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg } 80fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg close(sbfd); 81fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg return 0; 82fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg} 83fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg 84fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenbergstatic int adjustSectorNumExt4(unsigned numSectors) { 85e9196fecbb08ead0b5dcdf1b38b81a0419c24bf4Daniel Rosenberg // Ext4 started to reserve 2% or 4096 clusters, whichever is smaller for 86e9196fecbb08ead0b5dcdf1b38b81a0419c24bf4Daniel Rosenberg // preventing costly operations or unexpected ENOSPC error. 87e9196fecbb08ead0b5dcdf1b38b81a0419c24bf4Daniel Rosenberg // Ext4::format() uses default block size without clustering. 88e9196fecbb08ead0b5dcdf1b38b81a0419c24bf4Daniel Rosenberg unsigned clusterSectors = 4096 / 512; 89e9196fecbb08ead0b5dcdf1b38b81a0419c24bf4Daniel Rosenberg unsigned reservedSectors = (numSectors * 2)/100 + (numSectors % 50 > 0); 90e9196fecbb08ead0b5dcdf1b38b81a0419c24bf4Daniel Rosenberg numSectors += reservedSectors > (4096 * clusterSectors) ? (4096 * clusterSectors) : reservedSectors; 91fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg return ROUND_UP_POWER_OF_2(numSectors, 3); 92fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg} 93fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg 94fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenbergstatic int adjustSectorNumFAT(unsigned numSectors) { 95fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg /* 96fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg * Add some headroom 97fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg */ 98fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg unsigned fatSize = (((numSectors * 4) / 512) + 1) * 2; 99fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg numSectors += fatSize + 2; 100fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg /* 101fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg * FAT is aligned to 32 kb with 512b sectors. 102fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg */ 103fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg return ROUND_UP_POWER_OF_2(numSectors, 6); 104fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg} 105fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg 106fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenbergstatic int setupLoopDevice(char* buffer, size_t len, const char* asecFileName, const char* idHash, bool debug) { 107fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg if (Loop::lookupActive(idHash, buffer, len)) { 108fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg if (Loop::create(idHash, asecFileName, buffer, len)) { 109fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg SLOGE("ASEC loop device creation failed for %s (%s)", asecFileName, strerror(errno)); 110fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg return -1; 111fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg } 112fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg if (debug) { 113fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg SLOGD("New loop device created at %s", buffer); 114fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg } 115fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg } else { 116fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg if (debug) { 117fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg SLOGD("Found active loopback for %s at %s", asecFileName, buffer); 118fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg } 119fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg } 120fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg return 0; 121fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg} 122fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg 123fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel 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) { 124fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg if (strcmp(key, "none")) { 125fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg if (Devmapper::lookupActive(idHash, buffer, len)) { 126fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg if (Devmapper::create(idHash, loopDevice, key, numImgSectors, 127fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg buffer, len)) { 128fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg SLOGE("ASEC device mapping failed for %s (%s)", asecFileName, strerror(errno)); 129fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg return -1; 130fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg } 131fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg if (debug) { 132fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg SLOGD("New devmapper instance created at %s", buffer); 133fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg } 134fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg } else { 135fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg if (debug) { 136fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg SLOGD("Found active devmapper for %s at %s", asecFileName, buffer); 137fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg } 138fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg } 139fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg *createdDMDevice = true; 140fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg } else { 141fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg strcpy(buffer, loopDevice); 142fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg *createdDMDevice = false; 143fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg } 144fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg return 0; 145fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg} 146fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg 147fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenbergstatic void waitForDevMapper(const char *dmDevice) { 148fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg /* 149fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg * Wait for the device mapper node to be created. Sometimes it takes a 150fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg * while. Wait for up to 1 second. We could also inspect incoming uevents, 151fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg * but that would take more effort. 152fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg */ 153fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg int tries = 25; 154fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg while (tries--) { 155fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg if (!access(dmDevice, F_OK) || errno != ENOENT) { 156fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg break; 157fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg } 158fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg usleep(40 * 1000); 159fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg } 160fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg} 161fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg 162f1b736bc5605e92e917ab27f5abf3ba839be2270San MehatVolumeManager *VolumeManager::sInstance = NULL; 163f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat 164f1b736bc5605e92e917ab27f5abf3ba839be2270San MehatVolumeManager *VolumeManager::Instance() { 165f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat if (!sInstance) 166f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat sInstance = new VolumeManager(); 167f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat return sInstance; 168f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat} 169f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat 170f1b736bc5605e92e917ab27f5abf3ba839be2270San MehatVolumeManager::VolumeManager() { 171d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat mDebug = false; 172f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat mVolumes = new VolumeCollection(); 17388705166ab82057090a070c6d4200c3d9db76f11San Mehat mActiveContainers = new AsecIdCollection(); 174f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat mBroadcaster = NULL; 175a28056b38275003895ff5d9576681aca01544822Mike Lockwood mUmsSharingCount = 0; 176a28056b38275003895ff5d9576681aca01544822Mike Lockwood mSavedDirtyRatio = -1; 177a28056b38275003895ff5d9576681aca01544822Mike Lockwood // set dirty ratio to 0 when UMS is active 178a28056b38275003895ff5d9576681aca01544822Mike Lockwood mUmsDirtyRatio = 0; 1793b17005083be230509480ea65ae67c237142fadaKen Sumrall mVolManagerDisabled = 0; 180f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat} 181f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat 182f1b736bc5605e92e917ab27f5abf3ba839be2270San MehatVolumeManager::~VolumeManager() { 18388705166ab82057090a070c6d4200c3d9db76f11San Mehat delete mVolumes; 18488705166ab82057090a070c6d4200c3d9db76f11San Mehat delete mActiveContainers; 185f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat} 186f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat 187d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehatchar *VolumeManager::asecHash(const char *id, char *buffer, size_t len) { 188acc9e7dcca8978fc809fa5b4d9b819c515a980ffKenny Root static const char* digits = "0123456789abcdef"; 189acc9e7dcca8978fc809fa5b4d9b819c515a980ffKenny Root 1907b18a7b36f61574c0f0bdde0a7409dc36676fa12Kenny Root unsigned char sig[MD5_DIGEST_LENGTH]; 191d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat 192acc9e7dcca8978fc809fa5b4d9b819c515a980ffKenny Root if (buffer == NULL) { 193acc9e7dcca8978fc809fa5b4d9b819c515a980ffKenny Root SLOGE("Destination buffer is NULL"); 194acc9e7dcca8978fc809fa5b4d9b819c515a980ffKenny Root errno = ESPIPE; 195acc9e7dcca8978fc809fa5b4d9b819c515a980ffKenny Root return NULL; 196acc9e7dcca8978fc809fa5b4d9b819c515a980ffKenny Root } else if (id == NULL) { 197acc9e7dcca8978fc809fa5b4d9b819c515a980ffKenny Root SLOGE("Source buffer is NULL"); 198acc9e7dcca8978fc809fa5b4d9b819c515a980ffKenny Root errno = ESPIPE; 199acc9e7dcca8978fc809fa5b4d9b819c515a980ffKenny Root return NULL; 200acc9e7dcca8978fc809fa5b4d9b819c515a980ffKenny Root } else if (len < MD5_ASCII_LENGTH_PLUS_NULL) { 20159846b654e8b4a22a1be11cd21d6c5b81375abd2Colin Cross SLOGE("Target hash buffer size < %d bytes (%zu)", 202acc9e7dcca8978fc809fa5b4d9b819c515a980ffKenny Root MD5_ASCII_LENGTH_PLUS_NULL, len); 203d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat errno = ESPIPE; 204d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat return NULL; 205d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat } 2067b18a7b36f61574c0f0bdde0a7409dc36676fa12Kenny Root 2077b18a7b36f61574c0f0bdde0a7409dc36676fa12Kenny Root MD5(reinterpret_cast<const unsigned char*>(id), strlen(id), sig); 208d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat 209acc9e7dcca8978fc809fa5b4d9b819c515a980ffKenny Root char *p = buffer; 2107b18a7b36f61574c0f0bdde0a7409dc36676fa12Kenny Root for (int i = 0; i < MD5_DIGEST_LENGTH; i++) { 211acc9e7dcca8978fc809fa5b4d9b819c515a980ffKenny Root *p++ = digits[sig[i] >> 4]; 212acc9e7dcca8978fc809fa5b4d9b819c515a980ffKenny Root *p++ = digits[sig[i] & 0x0F]; 213d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat } 214acc9e7dcca8978fc809fa5b4d9b819c515a980ffKenny Root *p = '\0'; 215d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat 216d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat return buffer; 217d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat} 218d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat 219d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehatvoid VolumeManager::setDebug(bool enable) { 220d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat mDebug = enable; 221d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat VolumeCollection::iterator it; 222d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat for (it = mVolumes->begin(); it != mVolumes->end(); ++it) { 223d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat (*it)->setDebug(enable); 224d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat } 225d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat} 226d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat 227f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehatint VolumeManager::start() { 228f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat return 0; 229f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat} 230f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat 231f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehatint VolumeManager::stop() { 232f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat return 0; 233f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat} 234f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat 235f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehatint VolumeManager::addVolume(Volume *v) { 236f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat mVolumes->push_back(v); 237f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat return 0; 238f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat} 239f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat 240fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehatvoid VolumeManager::handleBlockEvent(NetlinkEvent *evt) { 241fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat const char *devpath = evt->findParam("DEVPATH"); 242f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat 243fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat /* Lookup a volume to handle this device */ 244f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat VolumeCollection::iterator it; 245f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat bool hit = false; 246f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat for (it = mVolumes->begin(); it != mVolumes->end(); ++it) { 247fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat if (!(*it)->handleBlockEvent(evt)) { 248a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#ifdef NETLINK_DEBUG 24997ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGD("Device '%s' event handled by volume %s\n", devpath, (*it)->getLabel()); 250a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#endif 251f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat hit = true; 252f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat break; 253f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat } 254f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat } 255f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat 256f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat if (!hit) { 257a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#ifdef NETLINK_DEBUG 25897ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGW("No volumes handled block event for '%s'", devpath); 259a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#endif 260f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat } 261f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat} 262f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat 26340b64a684124809132e04e3c499aa1e101fe808fJP Abgrallint VolumeManager::listVolumes(SocketClient *cli, bool broadcast) { 264f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat VolumeCollection::iterator i; 26540b64a684124809132e04e3c499aa1e101fe808fJP Abgrall char msg[256]; 266f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat 267f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat for (i = mVolumes->begin(); i != mVolumes->end(); ++i) { 268f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat char *buffer; 269f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat asprintf(&buffer, "%s %s %d", 270ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey (*i)->getLabel(), (*i)->getFuseMountpoint(), 271f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat (*i)->getState()); 272a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat cli->sendMsg(ResponseCode::VolumeListResult, buffer, false); 273f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat free(buffer); 27440b64a684124809132e04e3c499aa1e101fe808fJP Abgrall if (broadcast) { 27540b64a684124809132e04e3c499aa1e101fe808fJP Abgrall if((*i)->getUuid()) { 27640b64a684124809132e04e3c499aa1e101fe808fJP Abgrall snprintf(msg, sizeof(msg), "%s %s \"%s\"", (*i)->getLabel(), 27740b64a684124809132e04e3c499aa1e101fe808fJP Abgrall (*i)->getFuseMountpoint(), (*i)->getUuid()); 27840b64a684124809132e04e3c499aa1e101fe808fJP Abgrall mBroadcaster->sendBroadcast(ResponseCode::VolumeUuidChange, 27940b64a684124809132e04e3c499aa1e101fe808fJP Abgrall msg, false); 28040b64a684124809132e04e3c499aa1e101fe808fJP Abgrall } 28140b64a684124809132e04e3c499aa1e101fe808fJP Abgrall if((*i)->getUserLabel()) { 28240b64a684124809132e04e3c499aa1e101fe808fJP Abgrall snprintf(msg, sizeof(msg), "%s %s \"%s\"", (*i)->getLabel(), 28340b64a684124809132e04e3c499aa1e101fe808fJP Abgrall (*i)->getFuseMountpoint(), (*i)->getUserLabel()); 28440b64a684124809132e04e3c499aa1e101fe808fJP Abgrall mBroadcaster->sendBroadcast(ResponseCode::VolumeUserLabelChange, 28540b64a684124809132e04e3c499aa1e101fe808fJP Abgrall msg, false); 28640b64a684124809132e04e3c499aa1e101fe808fJP Abgrall } 28740b64a684124809132e04e3c499aa1e101fe808fJP Abgrall } 288f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat } 289a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat cli->sendMsg(ResponseCode::CommandOkay, "Volumes listed.", false); 290f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat return 0; 291f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat} 29249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat 2939caab76c6b5aefdeeb1715a3695491ca793b8c18Ken Sumrallint VolumeManager::formatVolume(const char *label, bool wipe) { 294a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat Volume *v = lookupVolume(label); 295a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 296a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat if (!v) { 297a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat errno = ENOENT; 298a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat return -1; 299a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat } 300a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 3013b17005083be230509480ea65ae67c237142fadaKen Sumrall if (mVolManagerDisabled) { 3023b17005083be230509480ea65ae67c237142fadaKen Sumrall errno = EBUSY; 3033b17005083be230509480ea65ae67c237142fadaKen Sumrall return -1; 3043b17005083be230509480ea65ae67c237142fadaKen Sumrall } 3053b17005083be230509480ea65ae67c237142fadaKen Sumrall 3069caab76c6b5aefdeeb1715a3695491ca793b8c18Ken Sumrall return v->formatVol(wipe); 307a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat} 308a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 309508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Rootint VolumeManager::getObbMountPath(const char *sourceFile, char *mountPath, int mountPathLen) { 310508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root char idHash[33]; 311508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root if (!asecHash(sourceFile, idHash, sizeof(idHash))) { 312508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root SLOGE("Hash of '%s' failed (%s)", sourceFile, strerror(errno)); 313508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root return -1; 314508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root } 315508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root 316508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root memset(mountPath, 0, mountPathLen); 317d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig int written = snprintf(mountPath, mountPathLen, "%s/%s", Volume::LOOPDIR, idHash); 318d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig if ((written < 0) || (written >= mountPathLen)) { 319d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig errno = EINVAL; 320d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig return -1; 321d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig } 322508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root 323508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root if (access(mountPath, F_OK)) { 324508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root errno = ENOENT; 325508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root return -1; 326508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root } 327508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root 328508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root return 0; 329508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root} 330508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root 331a19b250bd273455933ca3502cf2c2e0a803aff77San Mehatint VolumeManager::getAsecMountPath(const char *id, char *buffer, int maxlen) { 33288ac2c06539485942bf414efda2d39647fa1a415San Mehat char asecFileName[255]; 333344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root 3340de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich if (!isLegalAsecId(id)) { 3350de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich SLOGE("getAsecMountPath: Invalid asec id \"%s\"", id); 3360de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich errno = EINVAL; 3370de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich return -1; 3380de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich } 3390de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich 340344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root if (findAsec(id, asecFileName, sizeof(asecFileName))) { 341344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root SLOGE("Couldn't find ASEC %s", id); 342344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root return -1; 343344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root } 34488ac2c06539485942bf414efda2d39647fa1a415San Mehat 34588ac2c06539485942bf414efda2d39647fa1a415San Mehat memset(buffer, 0, maxlen); 34688ac2c06539485942bf414efda2d39647fa1a415San Mehat if (access(asecFileName, F_OK)) { 34788ac2c06539485942bf414efda2d39647fa1a415San Mehat errno = ENOENT; 34888ac2c06539485942bf414efda2d39647fa1a415San Mehat return -1; 34988ac2c06539485942bf414efda2d39647fa1a415San Mehat } 350a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat 351d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig int written = snprintf(buffer, maxlen, "%s/%s", Volume::ASECDIR, id); 352d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig if ((written < 0) || (written >= maxlen)) { 353d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig SLOGE("getAsecMountPath failed for %s: couldn't construct path in buffer", id); 354d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig errno = EINVAL; 355d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig return -1; 356d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig } 357d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig 358a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat return 0; 359a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat} 360a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat 361736910ca99a40b9add4353bf619e778c40938948Dianne Hackbornint VolumeManager::getAsecFilesystemPath(const char *id, char *buffer, int maxlen) { 362736910ca99a40b9add4353bf619e778c40938948Dianne Hackborn char asecFileName[255]; 363344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root 3640de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich if (!isLegalAsecId(id)) { 3650de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich SLOGE("getAsecFilesystemPath: Invalid asec id \"%s\"", id); 3660de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich errno = EINVAL; 3670de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich return -1; 3680de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich } 3690de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich 370344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root if (findAsec(id, asecFileName, sizeof(asecFileName))) { 371344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root SLOGE("Couldn't find ASEC %s", id); 372344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root return -1; 373344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root } 374736910ca99a40b9add4353bf619e778c40938948Dianne Hackborn 375736910ca99a40b9add4353bf619e778c40938948Dianne Hackborn memset(buffer, 0, maxlen); 376736910ca99a40b9add4353bf619e778c40938948Dianne Hackborn if (access(asecFileName, F_OK)) { 377736910ca99a40b9add4353bf619e778c40938948Dianne Hackborn errno = ENOENT; 378736910ca99a40b9add4353bf619e778c40938948Dianne Hackborn return -1; 379736910ca99a40b9add4353bf619e778c40938948Dianne Hackborn } 380736910ca99a40b9add4353bf619e778c40938948Dianne Hackborn 381d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig int written = snprintf(buffer, maxlen, "%s", asecFileName); 382d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig if ((written < 0) || (written >= maxlen)) { 383d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig errno = EINVAL; 384d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig return -1; 385d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig } 386d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig 387736910ca99a40b9add4353bf619e778c40938948Dianne Hackborn return 0; 388736910ca99a40b9add4353bf619e778c40938948Dianne Hackborn} 389736910ca99a40b9add4353bf619e778c40938948Dianne Hackborn 390344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Rootint VolumeManager::createAsec(const char *id, unsigned int numSectors, const char *fstype, 391344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root const char *key, const int ownerUid, bool isExternal) { 392fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat struct asec_superblock sb; 393fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat memset(&sb, 0, sizeof(sb)); 394fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat 3950de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich if (!isLegalAsecId(id)) { 3960de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich SLOGE("createAsec: Invalid asec id \"%s\"", id); 3970de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich errno = EINVAL; 3980de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich return -1; 3990de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich } 4000de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich 401344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root const bool wantFilesystem = strcmp(fstype, "none"); 402344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root bool usingExt4 = false; 403344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root if (wantFilesystem) { 404344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root usingExt4 = !strcmp(fstype, "ext4"); 405344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root if (usingExt4) { 406344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root sb.c_opts |= ASEC_SB_C_OPTS_EXT4; 407344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root } else if (strcmp(fstype, "fat")) { 408344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root SLOGE("Invalid filesystem type %s", fstype); 409344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root errno = EINVAL; 410344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root return -1; 411344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root } 412344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root } 413344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root 414fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat sb.magic = ASEC_SB_MAGIC; 415fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat sb.ver = ASEC_SB_VER; 416a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat 417d31e380bd9689dd9629b510ffe324707e261b439San Mehat if (numSectors < ((1024*1024)/512)) { 41897ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGE("Invalid container size specified (%d sectors)", numSectors); 419d31e380bd9689dd9629b510ffe324707e261b439San Mehat errno = EINVAL; 420d31e380bd9689dd9629b510ffe324707e261b439San Mehat return -1; 421d31e380bd9689dd9629b510ffe324707e261b439San Mehat } 422d31e380bd9689dd9629b510ffe324707e261b439San Mehat 423a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat if (lookupVolume(id)) { 42497ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGE("ASEC id '%s' currently exists", id); 425a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat errno = EADDRINUSE; 426a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat return -1; 427a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat } 428a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat 429a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat char asecFileName[255]; 430344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root 431344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root if (!findAsec(id, asecFileName, sizeof(asecFileName))) { 432344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root SLOGE("ASEC file '%s' currently exists - destroy it first! (%s)", 433344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root asecFileName, strerror(errno)); 434344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root errno = EADDRINUSE; 435344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root return -1; 436344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root } 437344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root 438344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root const char *asecDir = isExternal ? Volume::SEC_ASECDIR_EXT : Volume::SEC_ASECDIR_INT; 439344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root 440d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig int written = snprintf(asecFileName, sizeof(asecFileName), "%s/%s.asec", asecDir, id); 441d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig if ((written < 0) || (size_t(written) >= sizeof(asecFileName))) { 442d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig errno = EINVAL; 443d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig return -1; 444d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig } 445a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat 446a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat if (!access(asecFileName, F_OK)) { 44797ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGE("ASEC file '%s' currently exists - destroy it first! (%s)", 448344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root asecFileName, strerror(errno)); 449a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat errno = EADDRINUSE; 450a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat return -1; 451a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat } 452a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat 453fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg unsigned numImgSectors; 4546a74dcaa6e646fea8e00b7c04332fc60fe7e017cDaniel Rosenberg if (usingExt4) 455fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg numImgSectors = adjustSectorNumExt4(numSectors); 4566a74dcaa6e646fea8e00b7c04332fc60fe7e017cDaniel Rosenberg else 457fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg numImgSectors = adjustSectorNumFAT(numSectors); 458fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat 459fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat // Add +1 for our superblock which is at the end 460fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat if (Loop::createImageFile(asecFileName, numImgSectors + 1)) { 46197ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGE("ASEC image file creation failed (%s)", strerror(errno)); 462a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat return -1; 463a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat } 464a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat 465d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat char idHash[33]; 466d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat if (!asecHash(id, idHash, sizeof(idHash))) { 46797ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGE("Hash of '%s' failed (%s)", id, strerror(errno)); 468d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat unlink(asecFileName); 469d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat return -1; 470d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat } 471d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat 472a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat char loopDevice[255]; 473d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat if (Loop::create(idHash, asecFileName, loopDevice, sizeof(loopDevice))) { 47497ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGE("ASEC loop device creation failed (%s)", strerror(errno)); 475a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat unlink(asecFileName); 476a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat return -1; 477a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat } 478a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat 479b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat char dmDevice[255]; 480b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat bool cleanupDm = false; 481a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat 482b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat if (strcmp(key, "none")) { 483fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat // XXX: This is all we support for now 484fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat sb.c_cipher = ASEC_SB_C_CIPHER_TWOFISH; 485d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat if (Devmapper::create(idHash, loopDevice, key, numImgSectors, dmDevice, 486b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat sizeof(dmDevice))) { 48797ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGE("ASEC device mapping failed (%s)", strerror(errno)); 488b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat Loop::destroyByDevice(loopDevice); 489b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat unlink(asecFileName); 490b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat return -1; 491b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat } 492b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat cleanupDm = true; 493b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat } else { 494fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat sb.c_cipher = ASEC_SB_C_CIPHER_NONE; 495b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat strcpy(dmDevice, loopDevice); 496b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat } 497b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 498fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat /* 499fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat * Drop down the superblock at the end of the file 500fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat */ 501fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg if (writeSuperBlock(loopDevice, &sb, numImgSectors)) { 502fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat if (cleanupDm) { 503d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat Devmapper::destroy(idHash); 504fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat } 505fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat Loop::destroyByDevice(loopDevice); 506fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat unlink(asecFileName); 507fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat return -1; 508fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat } 509fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat 510344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root if (wantFilesystem) { 511344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root int formatStatus; 512a54e13a3dca8ad15141a9f1084b6e121caeddce5rpcraig char mountPoint[255]; 513a54e13a3dca8ad15141a9f1084b6e121caeddce5rpcraig 514d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id); 515d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) { 516d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig SLOGE("ASEC fs format failed: couldn't construct mountPoint"); 517d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig if (cleanupDm) { 518d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig Devmapper::destroy(idHash); 519d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig } 520d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig Loop::destroyByDevice(loopDevice); 521d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig unlink(asecFileName); 522d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig return -1; 523d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig } 524a54e13a3dca8ad15141a9f1084b6e121caeddce5rpcraig 525344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root if (usingExt4) { 5266a74dcaa6e646fea8e00b7c04332fc60fe7e017cDaniel Rosenberg formatStatus = Ext4::format(dmDevice, numImgSectors, mountPoint); 527344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root } else { 5289caab76c6b5aefdeeb1715a3695491ca793b8c18Ken Sumrall formatStatus = Fat::format(dmDevice, numImgSectors, 0); 529b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat } 530a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat 531344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root if (formatStatus < 0) { 532344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root SLOGE("ASEC fs format failed (%s)", strerror(errno)); 533b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat if (cleanupDm) { 534d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat Devmapper::destroy(idHash); 535b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat } 536eb13a90bb96b329d8e24a6c3d4720ae88451d301San Mehat Loop::destroyByDevice(loopDevice); 537eb13a90bb96b329d8e24a6c3d4720ae88451d301San Mehat unlink(asecFileName); 538eb13a90bb96b329d8e24a6c3d4720ae88451d301San Mehat return -1; 539eb13a90bb96b329d8e24a6c3d4720ae88451d301San Mehat } 540344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root 541344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root if (mkdir(mountPoint, 0000)) { 542a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat if (errno != EEXIST) { 54397ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGE("Mountpoint creation failed (%s)", strerror(errno)); 544a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat if (cleanupDm) { 545d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat Devmapper::destroy(idHash); 546a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat } 547a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat Loop::destroyByDevice(loopDevice); 548a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat unlink(asecFileName); 549a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat return -1; 550a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat } 551a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat } 552a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat 553344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root int mountStatus; 554344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root if (usingExt4) { 555344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root mountStatus = Ext4::doMount(dmDevice, mountPoint, false, false, false); 556344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root } else { 557344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root mountStatus = Fat::doMount(dmDevice, mountPoint, false, false, false, ownerUid, 0, 0000, 558344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root false); 559344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root } 560344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root 561344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root if (mountStatus) { 56297ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGE("ASEC FAT mount failed (%s)", strerror(errno)); 563a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat if (cleanupDm) { 564d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat Devmapper::destroy(idHash); 565a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat } 566a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat Loop::destroyByDevice(loopDevice); 567a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat unlink(asecFileName); 568a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat return -1; 569b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat } 570344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root 571344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root if (usingExt4) { 572344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root int dirfd = open(mountPoint, O_DIRECTORY); 573344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root if (dirfd >= 0) { 574344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root if (fchown(dirfd, ownerUid, AID_SYSTEM) 575344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root || fchmod(dirfd, S_IRUSR | S_IWUSR | S_IXUSR | S_ISGID | S_IRGRP | S_IXGRP)) { 576344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root SLOGI("Cannot chown/chmod new ASEC mount point %s", mountPoint); 577344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root } 578344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root close(dirfd); 579344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root } 580344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root } 581a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat } else { 58297ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGI("Created raw secure container %s (no filesystem)", id); 583a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat } 58488705166ab82057090a070c6d4200c3d9db76f11San Mehat 585cbacf78eff70bd43bb899e164ec2ab409bc0904cKenny Root mActiveContainers->push_back(new ContainerData(strdup(id), ASEC)); 586a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat return 0; 587a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat} 588a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat 589fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenbergint VolumeManager::resizeAsec(const char *id, unsigned numSectors, const char *key) { 590fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg char asecFileName[255]; 591fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg char mountPoint[255]; 592fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg bool cleanupDm = false; 593fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg 594fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg if (!isLegalAsecId(id)) { 595fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg SLOGE("resizeAsec: Invalid asec id \"%s\"", id); 596fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg errno = EINVAL; 597fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg return -1; 598fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg } 599fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg 600fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg if (findAsec(id, asecFileName, sizeof(asecFileName))) { 601fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg SLOGE("Couldn't find ASEC %s", id); 602fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg return -1; 603fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg } 604fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg 605fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id); 606fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) { 607fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg SLOGE("ASEC resize failed for %s: couldn't construct mountpoint", id); 608fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg return -1; 609fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg } 610fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg 611fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg if (isMountpointMounted(mountPoint)) { 612fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg SLOGE("ASEC %s mounted. Unmount before resizing", id); 613fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg errno = EBUSY; 614fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg return -1; 615fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg } 616fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg 617fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg struct asec_superblock sb; 618fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg int fd; 619fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg unsigned int oldNumSec = 0; 620fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg 621fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg if ((fd = open(asecFileName, O_RDONLY)) < 0) { 622fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg SLOGE("Failed to open ASEC file (%s)", strerror(errno)); 623fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg return -1; 624fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg } 625fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg 626fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg struct stat info; 627fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg if (fstat(fd, &info) < 0) { 628fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg SLOGE("Failed to get file size (%s)", strerror(errno)); 629fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg close(fd); 630fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg return -1; 631fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg } 632fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg 633fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg oldNumSec = info.st_size / 512; 634fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg 635fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg unsigned numImgSectors; 636fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg if (sb.c_opts & ASEC_SB_C_OPTS_EXT4) 637fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg numImgSectors = adjustSectorNumExt4(numSectors); 638fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg else 639fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg numImgSectors = adjustSectorNumFAT(numSectors); 640fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg /* 641fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg * add one block for the superblock 642fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg */ 643fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg SLOGD("Resizing from %d sectors to %d sectors", oldNumSec, numImgSectors + 1); 64443ed123d3fc1a3edf3660cd0e2528e971abc399eJeff Sharkey if (oldNumSec == numImgSectors + 1) { 64543ed123d3fc1a3edf3660cd0e2528e971abc399eJeff Sharkey SLOGW("Size unchanged; ignoring resize request"); 64643ed123d3fc1a3edf3660cd0e2528e971abc399eJeff Sharkey return 0; 64743ed123d3fc1a3edf3660cd0e2528e971abc399eJeff Sharkey } else if (oldNumSec > numImgSectors + 1) { 648fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg SLOGE("Only growing is currently supported."); 649fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg close(fd); 650fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg return -1; 651fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg } 652fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg 653fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg /* 654fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg * Try to read superblock. 655fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg */ 656fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg memset(&sb, 0, sizeof(struct asec_superblock)); 657fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg if (lseek(fd, ((oldNumSec - 1) * 512), SEEK_SET) < 0) { 658fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg SLOGE("lseek failed (%s)", strerror(errno)); 659fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg close(fd); 660fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg return -1; 661fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg } 662fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg if (read(fd, &sb, sizeof(struct asec_superblock)) != sizeof(struct asec_superblock)) { 663fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg SLOGE("superblock read failed (%s)", strerror(errno)); 664fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg close(fd); 665fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg return -1; 666fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg } 667fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg close(fd); 668fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg 669fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg if (mDebug) { 670fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg SLOGD("Container sb magic/ver (%.8x/%.2x)", sb.magic, sb.ver); 671fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg } 672fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg if (sb.magic != ASEC_SB_MAGIC || sb.ver != ASEC_SB_VER) { 673fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg SLOGE("Bad container magic/version (%.8x/%.2x)", sb.magic, sb.ver); 674fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg errno = EMEDIUMTYPE; 675fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg return -1; 676fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg } 677fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg 678fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg if (!(sb.c_opts & ASEC_SB_C_OPTS_EXT4)) { 679fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg SLOGE("Only ext4 partitions are supported for resize"); 680fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg errno = EINVAL; 681fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg return -1; 682fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg } 683fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg 684fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg if (Loop::resizeImageFile(asecFileName, numImgSectors + 1)) { 685fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg SLOGE("Resize of ASEC image file failed. Could not resize %s", id); 686fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg return -1; 687fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg } 688fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg 689fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg /* 690fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg * Drop down a copy of the superblock at the end of the file 691fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg */ 692fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg if (writeSuperBlock(asecFileName, &sb, numImgSectors)) 693fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg goto fail; 694fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg 695fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg char idHash[33]; 696fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg if (!asecHash(id, idHash, sizeof(idHash))) { 697fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg SLOGE("Hash of '%s' failed (%s)", id, strerror(errno)); 698fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg goto fail; 699fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg } 700fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg 701fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg char loopDevice[255]; 702fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg if (setupLoopDevice(loopDevice, sizeof(loopDevice), asecFileName, idHash, mDebug)) 703fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg goto fail; 704fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg 705fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg char dmDevice[255]; 706fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg 707fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg if (setupDevMapperDevice(dmDevice, sizeof(dmDevice), loopDevice, asecFileName, key, idHash, numImgSectors, &cleanupDm, mDebug)) { 708fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg Loop::destroyByDevice(loopDevice); 709fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg goto fail; 710fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg } 711fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg 712fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg /* 713fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg * Wait for the device mapper node to be created. 714fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg */ 715fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg waitForDevMapper(dmDevice); 716fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg 717fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg if (Ext4::resize(dmDevice, numImgSectors)) { 718fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg SLOGE("Unable to resize %s (%s)", id, strerror(errno)); 719fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg if (cleanupDm) { 720fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg Devmapper::destroy(idHash); 721fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg } 722fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg Loop::destroyByDevice(loopDevice); 723fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg goto fail; 724fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg } 725fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg 726fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg return 0; 727fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenbergfail: 728fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg Loop::resizeImageFile(asecFileName, oldNumSec); 729fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg return -1; 730fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg} 731fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg 732a19b250bd273455933ca3502cf2c2e0a803aff77San Mehatint VolumeManager::finalizeAsec(const char *id) { 733a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat char asecFileName[255]; 734a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat char loopDevice[255]; 735a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat char mountPoint[255]; 736a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat 7370de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich if (!isLegalAsecId(id)) { 7380de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich SLOGE("finalizeAsec: Invalid asec id \"%s\"", id); 7390de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich errno = EINVAL; 7400de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich return -1; 7410de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich } 7420de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich 743344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root if (findAsec(id, asecFileName, sizeof(asecFileName))) { 744344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root SLOGE("Couldn't find ASEC %s", id); 745344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root return -1; 746344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root } 747a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat 748d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat char idHash[33]; 749d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat if (!asecHash(id, idHash, sizeof(idHash))) { 75097ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGE("Hash of '%s' failed (%s)", id, strerror(errno)); 751d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat return -1; 752d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat } 753d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat 754d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat if (Loop::lookupActive(idHash, loopDevice, sizeof(loopDevice))) { 75597ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGE("Unable to finalize %s (%s)", id, strerror(errno)); 756a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat return -1; 757a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat } 758a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat 759344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root unsigned int nr_sec = 0; 760344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root struct asec_superblock sb; 761344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root 762344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root if (Loop::lookupInfo(loopDevice, &sb, &nr_sec)) { 763344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root return -1; 764344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root } 765344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root 766d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id); 767d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) { 768d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig SLOGE("ASEC finalize failed: couldn't construct mountPoint"); 769d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig return -1; 770d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig } 771344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root 772344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root int result = 0; 773344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root if (sb.c_opts & ASEC_SB_C_OPTS_EXT4) { 774344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root result = Ext4::doMount(loopDevice, mountPoint, true, true, true); 775344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root } else { 776344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root result = Fat::doMount(loopDevice, mountPoint, true, true, true, 0, 0, 0227, false); 777344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root } 778344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root 779344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root if (result) { 78097ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGE("ASEC finalize mount failed (%s)", strerror(errno)); 781a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat return -1; 782a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat } 783a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat 784d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat if (mDebug) { 78597ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGD("ASEC %s finalized", id); 786d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat } 787a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat return 0; 788a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat} 789a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat 790344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Rootint VolumeManager::fixupAsecPermissions(const char *id, gid_t gid, const char* filename) { 791344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root char asecFileName[255]; 792344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root char loopDevice[255]; 793344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root char mountPoint[255]; 794344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root 795344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root if (gid < AID_APP) { 796344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root SLOGE("Group ID is not in application range"); 797344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root return -1; 798344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root } 799344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root 8000de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich if (!isLegalAsecId(id)) { 8010de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich SLOGE("fixupAsecPermissions: Invalid asec id \"%s\"", id); 8020de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich errno = EINVAL; 8030de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich return -1; 8040de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich } 8050de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich 806344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root if (findAsec(id, asecFileName, sizeof(asecFileName))) { 807344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root SLOGE("Couldn't find ASEC %s", id); 808344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root return -1; 809344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root } 810344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root 811344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root char idHash[33]; 812344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root if (!asecHash(id, idHash, sizeof(idHash))) { 813344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root SLOGE("Hash of '%s' failed (%s)", id, strerror(errno)); 814344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root return -1; 815344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root } 816344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root 817344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root if (Loop::lookupActive(idHash, loopDevice, sizeof(loopDevice))) { 818344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root SLOGE("Unable fix permissions during lookup on %s (%s)", id, strerror(errno)); 819344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root return -1; 820344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root } 821344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root 822344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root unsigned int nr_sec = 0; 823344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root struct asec_superblock sb; 824344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root 825344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root if (Loop::lookupInfo(loopDevice, &sb, &nr_sec)) { 826344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root return -1; 827344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root } 828344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root 829d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id); 830d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) { 831d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig SLOGE("Unable remount to fix permissions for %s: couldn't construct mountpoint", id); 832d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig return -1; 833d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig } 834344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root 835344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root int result = 0; 836344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root if ((sb.c_opts & ASEC_SB_C_OPTS_EXT4) == 0) { 837344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root return 0; 838344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root } 839344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root 840344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root int ret = Ext4::doMount(loopDevice, mountPoint, 841344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root false /* read-only */, 842344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root true /* remount */, 843344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root false /* executable */); 844344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root if (ret) { 845344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root SLOGE("Unable remount to fix permissions for %s (%s)", id, strerror(errno)); 846344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root return -1; 847344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root } 848344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root 849344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root char *paths[] = { mountPoint, NULL }; 850344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root 851344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root FTS *fts = fts_open(paths, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, NULL); 852344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root if (fts) { 853344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root // Traverse the entire hierarchy and chown to system UID. 854344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root for (FTSENT *ftsent = fts_read(fts); ftsent != NULL; ftsent = fts_read(fts)) { 855344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root // We don't care about the lost+found directory. 856344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root if (!strcmp(ftsent->fts_name, "lost+found")) { 857344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root continue; 858344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root } 859344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root 860344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root /* 861344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root * There can only be one file marked as private right now. 862344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root * This should be more robust, but it satisfies the requirements 863344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root * we have for right now. 864344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root */ 865344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root const bool privateFile = !strcmp(ftsent->fts_name, filename); 866344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root 867344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root int fd = open(ftsent->fts_accpath, O_NOFOLLOW); 868344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root if (fd < 0) { 869344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root SLOGE("Couldn't open file %s: %s", ftsent->fts_accpath, strerror(errno)); 870344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root result = -1; 871344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root continue; 872344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root } 873344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root 874344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root result |= fchown(fd, AID_SYSTEM, privateFile? gid : AID_SYSTEM); 875344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root 876344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root if (ftsent->fts_info & FTS_D) { 8771a673c868c2d2d81fcaeab34b4a7c75d4a978584Kenny Root result |= fchmod(fd, 0755); 878348c8aba0d2df2996e0fe57900ef518c6aeb4b29Kenny Root } else if (ftsent->fts_info & FTS_F) { 879344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root result |= fchmod(fd, privateFile ? 0640 : 0644); 880344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root } 881b9e3ba56cb4075f894a73b02ee70571456494ac1Robert Craig 8825093e6187da9c237c88383540f544c8dbaf37754Stephen Smalley if (selinux_android_restorecon(ftsent->fts_path, 0) < 0) { 883b9e3ba56cb4075f894a73b02ee70571456494ac1Robert Craig SLOGE("restorecon failed for %s: %s\n", ftsent->fts_path, strerror(errno)); 884b9e3ba56cb4075f894a73b02ee70571456494ac1Robert Craig result |= -1; 885b9e3ba56cb4075f894a73b02ee70571456494ac1Robert Craig } 886b9e3ba56cb4075f894a73b02ee70571456494ac1Robert Craig 887344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root close(fd); 888344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root } 889344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root fts_close(fts); 890344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root 891344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root // Finally make the directory readable by everyone. 892344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root int dirfd = open(mountPoint, O_DIRECTORY); 893344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root if (dirfd < 0 || fchmod(dirfd, 0755)) { 894344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root SLOGE("Couldn't change owner of existing directory %s: %s", mountPoint, strerror(errno)); 895344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root result |= -1; 896344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root } 897344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root close(dirfd); 898344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root } else { 899344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root result |= -1; 900344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root } 901344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root 902344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root result |= Ext4::doMount(loopDevice, mountPoint, 903344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root true /* read-only */, 904344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root true /* remount */, 905344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root true /* execute */); 906344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root 907344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root if (result) { 908344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root SLOGE("ASEC fix permissions failed (%s)", strerror(errno)); 909344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root return -1; 910344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root } 911344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root 912344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root if (mDebug) { 913344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root SLOGD("ASEC %s permissions fixed", id); 914344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root } 915344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root return 0; 916344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root} 917344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root 918048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehatint VolumeManager::renameAsec(const char *id1, const char *id2) { 919344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root char asecFilename1[255]; 920048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat char *asecFilename2; 921048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat char mountPoint[255]; 922048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat 923344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root const char *dir; 924344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root 9250de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich if (!isLegalAsecId(id1)) { 9260de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich SLOGE("renameAsec: Invalid asec id1 \"%s\"", id1); 9270de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich errno = EINVAL; 9280de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich return -1; 9290de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich } 9300de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich 9310de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich if (!isLegalAsecId(id2)) { 9320de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich SLOGE("renameAsec: Invalid asec id2 \"%s\"", id2); 9330de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich errno = EINVAL; 9340de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich return -1; 9350de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich } 9360de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich 937344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root if (findAsec(id1, asecFilename1, sizeof(asecFilename1), &dir)) { 938344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root SLOGE("Couldn't find ASEC %s", id1); 939344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root return -1; 940344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root } 941344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root 942344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root asprintf(&asecFilename2, "%s/%s.asec", dir, id2); 943048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat 944d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id1); 945d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) { 946d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig SLOGE("Rename failed: couldn't construct mountpoint"); 947d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig goto out_err; 948d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig } 949d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig 950048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat if (isMountpointMounted(mountPoint)) { 95197ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGW("Rename attempt when src mounted"); 952048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat errno = EBUSY; 953048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat goto out_err; 954048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat } 955048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat 956d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id2); 957d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) { 958d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig SLOGE("Rename failed: couldn't construct mountpoint2"); 959d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig goto out_err; 960d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig } 961d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig 96296956ed0e220cb62a4a96136976ded0d8c2d9075San Mehat if (isMountpointMounted(mountPoint)) { 96397ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGW("Rename attempt when dst mounted"); 96496956ed0e220cb62a4a96136976ded0d8c2d9075San Mehat errno = EBUSY; 96596956ed0e220cb62a4a96136976ded0d8c2d9075San Mehat goto out_err; 96696956ed0e220cb62a4a96136976ded0d8c2d9075San Mehat } 96796956ed0e220cb62a4a96136976ded0d8c2d9075San Mehat 968048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat if (!access(asecFilename2, F_OK)) { 96997ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGE("Rename attempt when dst exists"); 970048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat errno = EADDRINUSE; 971048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat goto out_err; 972048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat } 973048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat 974048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat if (rename(asecFilename1, asecFilename2)) { 97597ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGE("Rename of '%s' to '%s' failed (%s)", asecFilename1, asecFilename2, strerror(errno)); 976048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat goto out_err; 977048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat } 978048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat 979048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat free(asecFilename2); 980048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat return 0; 981048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat 982048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehatout_err: 983048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat free(asecFilename2); 984048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat return -1; 985048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat} 986048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat 987fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root#define UNMOUNT_RETRIES 5 988fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root#define UNMOUNT_SLEEP_BETWEEN_RETRY_MS (1000 * 1000) 9894ba8948dc16463053e21cda5744f519a555080d0San Mehatint VolumeManager::unmountAsec(const char *id, bool force) { 990a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat char asecFileName[255]; 991a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat char mountPoint[255]; 992a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat 9930de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich if (!isLegalAsecId(id)) { 9940de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich SLOGE("unmountAsec: Invalid asec id \"%s\"", id); 9950de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich errno = EINVAL; 9960de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich return -1; 9970de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich } 9980de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich 999344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root if (findAsec(id, asecFileName, sizeof(asecFileName))) { 1000344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root SLOGE("Couldn't find ASEC %s", id); 1001344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root return -1; 1002344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root } 1003344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root 1004d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id); 1005d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) { 1006d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig SLOGE("ASEC unmount failed for %s: couldn't construct mountpoint", id); 1007d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig return -1; 1008d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig } 1009a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat 1010d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat char idHash[33]; 1011d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat if (!asecHash(id, idHash, sizeof(idHash))) { 101297ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGE("Hash of '%s' failed (%s)", id, strerror(errno)); 1013d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat return -1; 1014d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat } 1015d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat 1016fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root return unmountLoopImage(id, idHash, asecFileName, mountPoint, force); 1017fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root} 1018fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root 1019508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Rootint VolumeManager::unmountObb(const char *fileName, bool force) { 1020fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root char mountPoint[255]; 1021fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root 1022fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root char idHash[33]; 1023fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root if (!asecHash(fileName, idHash, sizeof(idHash))) { 1024fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root SLOGE("Hash of '%s' failed (%s)", fileName, strerror(errno)); 1025fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root return -1; 1026fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root } 1027fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root 1028d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::LOOPDIR, idHash); 1029d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) { 1030d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig SLOGE("OBB unmount failed for %s: couldn't construct mountpoint", fileName); 1031d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig return -1; 1032d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig } 1033fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root 1034fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root return unmountLoopImage(fileName, idHash, fileName, mountPoint, force); 1035fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root} 1036fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root 1037fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Rootint VolumeManager::unmountLoopImage(const char *id, const char *idHash, 1038fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root const char *fileName, const char *mountPoint, bool force) { 10390586d54053ee00e6d6523d4f125282ccb9a24aabSan Mehat if (!isMountpointMounted(mountPoint)) { 1040fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root SLOGE("Unmount request for %s when not mounted", id); 1041918e5f9f10b9c1ff929683743ffbf229027ce240Kenny Root errno = ENOENT; 1042b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat return -1; 1043b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat } 104423969931fad6e993832208f099f6eea0f6f76eb5San Mehat 1045b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat int i, rc; 1046fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root for (i = 1; i <= UNMOUNT_RETRIES; i++) { 1047b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat rc = umount(mountPoint); 1048b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat if (!rc) { 1049b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat break; 1050a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat } 1051b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat if (rc && (errno == EINVAL || errno == ENOENT)) { 1052fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root SLOGI("Container %s unmounted OK", id); 1053b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat rc = 0; 1054b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat break; 1055a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat } 1056fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root SLOGW("%s unmount attempt %d failed (%s)", 10578c940ef7dbd423cadc92982b44a65ed1014389e2San Mehat id, i, strerror(errno)); 10588c940ef7dbd423cadc92982b44a65ed1014389e2San Mehat 10594ba8948dc16463053e21cda5744f519a555080d0San Mehat int action = 0; // default is to just complain 10604ba8948dc16463053e21cda5744f519a555080d0San Mehat 10614ba8948dc16463053e21cda5744f519a555080d0San Mehat if (force) { 1062fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root if (i > (UNMOUNT_RETRIES - 2)) 10634ba8948dc16463053e21cda5744f519a555080d0San Mehat action = 2; // SIGKILL 1064fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root else if (i > (UNMOUNT_RETRIES - 3)) 10654ba8948dc16463053e21cda5744f519a555080d0San Mehat action = 1; // SIGHUP 10664ba8948dc16463053e21cda5744f519a555080d0San Mehat } 10678c940ef7dbd423cadc92982b44a65ed1014389e2San Mehat 1068586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat Process::killProcessesWithOpenFiles(mountPoint, action); 1069fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root usleep(UNMOUNT_SLEEP_BETWEEN_RETRY_MS); 1070b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat } 1071b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 1072b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat if (rc) { 10734ba8948dc16463053e21cda5744f519a555080d0San Mehat errno = EBUSY; 107497ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGE("Failed to unmount container %s (%s)", id, strerror(errno)); 1075b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat return -1; 1076b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat } 1077b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 107812f4b89046b54de1bdc188b7057ba77d7566e573San Mehat int retries = 10; 107912f4b89046b54de1bdc188b7057ba77d7566e573San Mehat 108012f4b89046b54de1bdc188b7057ba77d7566e573San Mehat while(retries--) { 108112f4b89046b54de1bdc188b7057ba77d7566e573San Mehat if (!rmdir(mountPoint)) { 108212f4b89046b54de1bdc188b7057ba77d7566e573San Mehat break; 108312f4b89046b54de1bdc188b7057ba77d7566e573San Mehat } 108412f4b89046b54de1bdc188b7057ba77d7566e573San Mehat 108597ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGW("Failed to rmdir %s (%s)", mountPoint, strerror(errno)); 1086fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root usleep(UNMOUNT_SLEEP_BETWEEN_RETRY_MS); 108712f4b89046b54de1bdc188b7057ba77d7566e573San Mehat } 108812f4b89046b54de1bdc188b7057ba77d7566e573San Mehat 108912f4b89046b54de1bdc188b7057ba77d7566e573San Mehat if (!retries) { 109097ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGE("Timed out trying to rmdir %s (%s)", mountPoint, strerror(errno)); 1091f5c61980969a0b49bda37b5dc94ffe675ebd5a5aSan Mehat } 109288705166ab82057090a070c6d4200c3d9db76f11San Mehat 109360dec16c5026d29a52791ad790860d247f47f8f2Paul Lawrence for (i=1; i <= UNMOUNT_RETRIES; i++) { 109460dec16c5026d29a52791ad790860d247f47f8f2Paul Lawrence if (Devmapper::destroy(idHash) && errno != ENXIO) { 109560dec16c5026d29a52791ad790860d247f47f8f2Paul Lawrence SLOGE("Failed to destroy devmapper instance (%s)", strerror(errno)); 109660dec16c5026d29a52791ad790860d247f47f8f2Paul Lawrence usleep(UNMOUNT_SLEEP_BETWEEN_RETRY_MS); 109760dec16c5026d29a52791ad790860d247f47f8f2Paul Lawrence continue; 109860dec16c5026d29a52791ad790860d247f47f8f2Paul Lawrence } else { 109960dec16c5026d29a52791ad790860d247f47f8f2Paul Lawrence break; 110060dec16c5026d29a52791ad790860d247f47f8f2Paul Lawrence } 1101a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat } 1102a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat 1103a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat char loopDevice[255]; 1104d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat if (!Loop::lookupActive(idHash, loopDevice, sizeof(loopDevice))) { 1105a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat Loop::destroyByDevice(loopDevice); 1106d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat } else { 1107fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root SLOGW("Failed to find loop device for {%s} (%s)", fileName, strerror(errno)); 1108a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat } 110988705166ab82057090a070c6d4200c3d9db76f11San Mehat 111088705166ab82057090a070c6d4200c3d9db76f11San Mehat AsecIdCollection::iterator it; 111188705166ab82057090a070c6d4200c3d9db76f11San Mehat for (it = mActiveContainers->begin(); it != mActiveContainers->end(); ++it) { 1112cbacf78eff70bd43bb899e164ec2ab409bc0904cKenny Root ContainerData* cd = *it; 1113cbacf78eff70bd43bb899e164ec2ab409bc0904cKenny Root if (!strcmp(cd->id, id)) { 111488705166ab82057090a070c6d4200c3d9db76f11San Mehat free(*it); 111588705166ab82057090a070c6d4200c3d9db76f11San Mehat mActiveContainers->erase(it); 111688705166ab82057090a070c6d4200c3d9db76f11San Mehat break; 111788705166ab82057090a070c6d4200c3d9db76f11San Mehat } 111888705166ab82057090a070c6d4200c3d9db76f11San Mehat } 111988705166ab82057090a070c6d4200c3d9db76f11San Mehat if (it == mActiveContainers->end()) { 112097ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGW("mActiveContainers is inconsistent!"); 112188705166ab82057090a070c6d4200c3d9db76f11San Mehat } 1122b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat return 0; 1123b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat} 1124b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 11254ba8948dc16463053e21cda5744f519a555080d0San Mehatint VolumeManager::destroyAsec(const char *id, bool force) { 1126b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat char asecFileName[255]; 1127b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat char mountPoint[255]; 1128b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 11290de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich if (!isLegalAsecId(id)) { 11300de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich SLOGE("destroyAsec: Invalid asec id \"%s\"", id); 11310de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich errno = EINVAL; 11320de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich return -1; 11330de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich } 11340de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich 1135344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root if (findAsec(id, asecFileName, sizeof(asecFileName))) { 1136344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root SLOGE("Couldn't find ASEC %s", id); 1137344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root return -1; 1138344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root } 1139344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root 1140d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id); 1141d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) { 1142d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig SLOGE("ASEC destroy failed for %s: couldn't construct mountpoint", id); 1143d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig return -1; 1144d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig } 1145b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 11460586d54053ee00e6d6523d4f125282ccb9a24aabSan Mehat if (isMountpointMounted(mountPoint)) { 1147d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat if (mDebug) { 114897ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGD("Unmounting container before destroy"); 1149d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat } 11504ba8948dc16463053e21cda5744f519a555080d0San Mehat if (unmountAsec(id, force)) { 115197ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGE("Failed to unmount asec %s for destroy (%s)", id, strerror(errno)); 11520586d54053ee00e6d6523d4f125282ccb9a24aabSan Mehat return -1; 11530586d54053ee00e6d6523d4f125282ccb9a24aabSan Mehat } 11540586d54053ee00e6d6523d4f125282ccb9a24aabSan Mehat } 1155a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat 11560586d54053ee00e6d6523d4f125282ccb9a24aabSan Mehat if (unlink(asecFileName)) { 115797ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGE("Failed to unlink asec '%s' (%s)", asecFileName, strerror(errno)); 11580586d54053ee00e6d6523d4f125282ccb9a24aabSan Mehat return -1; 11590586d54053ee00e6d6523d4f125282ccb9a24aabSan Mehat } 1160a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat 1161d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat if (mDebug) { 116297ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGD("ASEC %s destroyed", id); 1163d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat } 1164a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat return 0; 1165a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat} 1166a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat 11670de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich/* 11680de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich * Legal ASEC ids consist of alphanumeric characters, '-', 11690de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich * '_', or '.'. ".." is not allowed. The first or last character 11700de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich * of the ASEC id cannot be '.' (dot). 11710de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich */ 11720de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevichbool VolumeManager::isLegalAsecId(const char *id) const { 11730de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich size_t i; 11740de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich size_t len = strlen(id); 11750de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich 11760de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich if (len == 0) { 11770de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich return false; 11780de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich } 11790de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich if ((id[0] == '.') || (id[len - 1] == '.')) { 11800de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich return false; 11810de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich } 11820de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich 11830de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich for (i = 0; i < len; i++) { 11840de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich if (id[i] == '.') { 11850de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich // i=0 is guaranteed never to have a dot. See above. 11860de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich if (id[i-1] == '.') return false; 11870de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich continue; 11880de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich } 11890de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich if (id[i] == '_' || id[i] == '-') continue; 11900de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich if (id[i] >= 'a' && id[i] <= 'z') continue; 11910de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich if (id[i] >= 'A' && id[i] <= 'Z') continue; 11920de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich if (id[i] >= '0' && id[i] <= '9') continue; 11930de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich return false; 11940de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich } 11950de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich 11960de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich return true; 11970de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich} 11980de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich 1199344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Rootbool VolumeManager::isAsecInDirectory(const char *dir, const char *asecName) const { 1200344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root int dirfd = open(dir, O_DIRECTORY); 1201344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root if (dirfd < 0) { 1202344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root SLOGE("Couldn't open internal ASEC dir (%s)", strerror(errno)); 1203344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root return -1; 1204344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root } 1205344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root 1206344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root bool ret = false; 1207344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root 1208344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root if (!faccessat(dirfd, asecName, F_OK, AT_SYMLINK_NOFOLLOW)) { 1209344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root ret = true; 1210344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root } 1211344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root 1212344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root close(dirfd); 1213344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root 1214344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root return ret; 1215344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root} 1216344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root 1217344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Rootint VolumeManager::findAsec(const char *id, char *asecPath, size_t asecPathLen, 1218344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root const char **directory) const { 1219344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root int dirfd, fd; 1220344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root const int idLen = strlen(id); 1221344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root char *asecName; 1222344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root 12230de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich if (!isLegalAsecId(id)) { 12240de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich SLOGE("findAsec: Invalid asec id \"%s\"", id); 12250de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich errno = EINVAL; 12260de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich return -1; 12270de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich } 12280de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich 1229344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root if (asprintf(&asecName, "%s.asec", id) < 0) { 1230344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root SLOGE("Couldn't allocate string to write ASEC name"); 1231344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root return -1; 1232344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root } 1233344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root 1234344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root const char *dir; 1235344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root if (isAsecInDirectory(Volume::SEC_ASECDIR_INT, asecName)) { 1236344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root dir = Volume::SEC_ASECDIR_INT; 1237344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root } else if (isAsecInDirectory(Volume::SEC_ASECDIR_EXT, asecName)) { 1238344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root dir = Volume::SEC_ASECDIR_EXT; 1239344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root } else { 1240344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root free(asecName); 1241344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root return -1; 1242344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root } 1243344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root 1244344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root if (directory != NULL) { 1245344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root *directory = dir; 1246344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root } 1247344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root 1248344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root if (asecPath != NULL) { 1249344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root int written = snprintf(asecPath, asecPathLen, "%s/%s", dir, asecName); 1250d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig if ((written < 0) || (size_t(written) >= asecPathLen)) { 1251d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig SLOGE("findAsec failed for %s: couldn't construct ASEC path", id); 1252344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root free(asecName); 1253344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root return -1; 1254344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root } 1255344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root } 1256344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root 1257344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root free(asecName); 1258344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root return 0; 1259344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root} 1260344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root 126143ed123d3fc1a3edf3660cd0e2528e971abc399eJeff Sharkeyint VolumeManager::mountAsec(const char *id, const char *key, int ownerUid, bool readOnly) { 1262a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat char asecFileName[255]; 1263a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat char mountPoint[255]; 1264a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat 12650de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich if (!isLegalAsecId(id)) { 12660de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich SLOGE("mountAsec: Invalid asec id \"%s\"", id); 12670de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich errno = EINVAL; 12680de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich return -1; 12690de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich } 12700de7c61102611ccd5df1ca48cb733bf037512c6bNick Kralevich 1271344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root if (findAsec(id, asecFileName, sizeof(asecFileName))) { 1272344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root SLOGE("Couldn't find ASEC %s", id); 1273344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root return -1; 1274344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root } 1275344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root 1276d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id); 1277d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) { 127859846b654e8b4a22a1be11cd21d6c5b81375abd2Colin Cross SLOGE("ASEC mount failed for %s: couldn't construct mountpoint", id); 1279d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig return -1; 1280d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig } 1281a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat 1282a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat if (isMountpointMounted(mountPoint)) { 128397ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGE("ASEC %s already mounted", id); 1284a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat errno = EBUSY; 1285a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat return -1; 1286a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat } 1287a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat 1288d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat char idHash[33]; 1289d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat if (!asecHash(id, idHash, sizeof(idHash))) { 129097ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGE("Hash of '%s' failed (%s)", id, strerror(errno)); 1291d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat return -1; 1292d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat } 12937b18a7b36f61574c0f0bdde0a7409dc36676fa12Kenny Root 1294a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat char loopDevice[255]; 1295fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg if (setupLoopDevice(loopDevice, sizeof(loopDevice), asecFileName, idHash, mDebug)) 1296fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg return -1; 1297b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 1298b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat char dmDevice[255]; 1299b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat bool cleanupDm = false; 1300fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat int fd; 1301fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat unsigned int nr_sec = 0; 1302fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat struct asec_superblock sb; 1303344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root 1304344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root if (Loop::lookupInfo(loopDevice, &sb, &nr_sec)) { 1305fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat return -1; 1306fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat } 1307fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat 1308d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat if (mDebug) { 130997ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGD("Container sb magic/ver (%.8x/%.2x)", sb.magic, sb.ver); 1310d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat } 1311fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat if (sb.magic != ASEC_SB_MAGIC || sb.ver != ASEC_SB_VER) { 131297ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGE("Bad container magic/version (%.8x/%.2x)", sb.magic, sb.ver); 1313fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat Loop::destroyByDevice(loopDevice); 1314fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat errno = EMEDIUMTYPE; 1315fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat return -1; 1316fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat } 1317fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat nr_sec--; // We don't want the devmapping to extend onto our superblock 1318fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat 1319fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg if (setupDevMapperDevice(dmDevice, sizeof(dmDevice), loopDevice, asecFileName, key, idHash , nr_sec, &cleanupDm, mDebug)) { 1320fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg Loop::destroyByDevice(loopDevice); 1321fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg return -1; 1322a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat } 1323a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat 1324344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root if (mkdir(mountPoint, 0000)) { 1325b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat if (errno != EEXIST) { 132697ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGE("Mountpoint creation failed (%s)", strerror(errno)); 1327b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat if (cleanupDm) { 1328d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat Devmapper::destroy(idHash); 1329b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat } 1330b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat Loop::destroyByDevice(loopDevice); 1331b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat return -1; 1332b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat } 1333a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat } 1334a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat 1335cdc2a1c83575a349ee44035de8c3b38b8b401003Kenny Root /* 1336fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg * Wait for the device mapper node to be created. 1337cdc2a1c83575a349ee44035de8c3b38b8b401003Kenny Root */ 1338fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg waitForDevMapper(dmDevice); 1339cdc2a1c83575a349ee44035de8c3b38b8b401003Kenny Root 1340344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root int result; 1341344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root if (sb.c_opts & ASEC_SB_C_OPTS_EXT4) { 134243ed123d3fc1a3edf3660cd0e2528e971abc399eJeff Sharkey result = Ext4::doMount(dmDevice, mountPoint, readOnly, false, readOnly); 1343344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root } else { 134443ed123d3fc1a3edf3660cd0e2528e971abc399eJeff Sharkey result = Fat::doMount(dmDevice, mountPoint, readOnly, false, readOnly, ownerUid, 0, 0222, false); 1345344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root } 1346344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root 1347344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root if (result) { 134897ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGE("ASEC mount failed (%s)", strerror(errno)); 1349b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat if (cleanupDm) { 1350d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat Devmapper::destroy(idHash); 1351b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat } 1352b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat Loop::destroyByDevice(loopDevice); 1353a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat return -1; 1354a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat } 1355a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat 1356cbacf78eff70bd43bb899e164ec2ab409bc0904cKenny Root mActiveContainers->push_back(new ContainerData(strdup(id), ASEC)); 1357d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat if (mDebug) { 135897ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGD("ASEC %s mounted", id); 1359d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat } 1360a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat return 0; 1361a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat} 1362a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat 136393ecb38daded7583a4a61f4f22519bb7a8a8c154Kenny RootVolume* VolumeManager::getVolumeForFile(const char *fileName) { 136493ecb38daded7583a4a61f4f22519bb7a8a8c154Kenny Root VolumeCollection::iterator i; 136593ecb38daded7583a4a61f4f22519bb7a8a8c154Kenny Root 136693ecb38daded7583a4a61f4f22519bb7a8a8c154Kenny Root for (i = mVolumes->begin(); i != mVolumes->end(); ++i) { 1367ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey const char* mountPoint = (*i)->getFuseMountpoint(); 136893ecb38daded7583a4a61f4f22519bb7a8a8c154Kenny Root if (!strncmp(fileName, mountPoint, strlen(mountPoint))) { 136993ecb38daded7583a4a61f4f22519bb7a8a8c154Kenny Root return *i; 137093ecb38daded7583a4a61f4f22519bb7a8a8c154Kenny Root } 137193ecb38daded7583a4a61f4f22519bb7a8a8c154Kenny Root } 137293ecb38daded7583a4a61f4f22519bb7a8a8c154Kenny Root 137393ecb38daded7583a4a61f4f22519bb7a8a8c154Kenny Root return NULL; 137493ecb38daded7583a4a61f4f22519bb7a8a8c154Kenny Root} 137593ecb38daded7583a4a61f4f22519bb7a8a8c154Kenny Root 1376fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root/** 1377fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root * Mounts an image file <code>img</code>. 1378fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root */ 13796947904a76b69a1db20a3ddd30c0bcd281922fdeJeff Sharkeyint VolumeManager::mountObb(const char *img, const char *key, int ownerGid) { 1380fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root char mountPoint[255]; 1381fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root 1382fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root char idHash[33]; 1383fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root if (!asecHash(img, idHash, sizeof(idHash))) { 1384fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root SLOGE("Hash of '%s' failed (%s)", img, strerror(errno)); 1385fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root return -1; 1386fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root } 1387fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root 1388d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::LOOPDIR, idHash); 1389d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) { 139059846b654e8b4a22a1be11cd21d6c5b81375abd2Colin Cross SLOGE("OBB mount failed for %s: couldn't construct mountpoint", img); 1391d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig return -1; 1392d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig } 1393fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root 1394fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root if (isMountpointMounted(mountPoint)) { 1395fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root SLOGE("Image %s already mounted", img); 1396fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root errno = EBUSY; 1397fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root return -1; 1398fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root } 1399fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root 1400fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root char loopDevice[255]; 1401fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg if (setupLoopDevice(loopDevice, sizeof(loopDevice), img, idHash, mDebug)) 1402fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg return -1; 1403fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root 1404fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root char dmDevice[255]; 1405fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root bool cleanupDm = false; 1406fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root int fd; 1407fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root unsigned int nr_sec = 0; 1408fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root 1409fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root if ((fd = open(loopDevice, O_RDWR)) < 0) { 1410fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root SLOGE("Failed to open loopdevice (%s)", strerror(errno)); 1411fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root Loop::destroyByDevice(loopDevice); 1412fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root return -1; 1413fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root } 1414fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root 1415fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root if (ioctl(fd, BLKGETSIZE, &nr_sec)) { 1416fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root SLOGE("Failed to get loop size (%s)", strerror(errno)); 1417fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root Loop::destroyByDevice(loopDevice); 1418fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root close(fd); 1419fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root return -1; 1420fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root } 1421fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root 1422fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root close(fd); 1423fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root 1424fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg if (setupDevMapperDevice(dmDevice, sizeof(loopDevice), loopDevice, img,key, idHash , nr_sec, &cleanupDm, mDebug)) { 1425fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg Loop::destroyByDevice(loopDevice); 1426fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg return -1; 1427fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root } 1428fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root 1429fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root if (mkdir(mountPoint, 0755)) { 1430fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root if (errno != EEXIST) { 1431fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root SLOGE("Mountpoint creation failed (%s)", strerror(errno)); 1432fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root if (cleanupDm) { 1433fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root Devmapper::destroy(idHash); 1434fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root } 1435fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root Loop::destroyByDevice(loopDevice); 1436fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root return -1; 1437fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root } 1438fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root } 1439fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root 14406947904a76b69a1db20a3ddd30c0bcd281922fdeJeff Sharkey if (Fat::doMount(dmDevice, mountPoint, true, false, true, 0, ownerGid, 1441fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root 0227, false)) { 1442fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root SLOGE("Image mount failed (%s)", strerror(errno)); 1443fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root if (cleanupDm) { 1444fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root Devmapper::destroy(idHash); 1445fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root } 1446fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root Loop::destroyByDevice(loopDevice); 1447fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root return -1; 1448fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root } 1449fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root 1450cbacf78eff70bd43bb899e164ec2ab409bc0904cKenny Root mActiveContainers->push_back(new ContainerData(strdup(img), OBB)); 1451fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root if (mDebug) { 1452fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root SLOGD("Image %s mounted", img); 1453fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root } 1454fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root return 0; 1455fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root} 1456fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root 145749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehatint VolumeManager::mountVolume(const char *label) { 145849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat Volume *v = lookupVolume(label); 145949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat 146049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat if (!v) { 146149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat errno = ENOENT; 146249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat return -1; 146349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat } 146449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat 1465a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat return v->mountVol(); 1466a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat} 1467a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 1468508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Rootint VolumeManager::listMountedObbs(SocketClient* cli) { 1469508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root char device[256]; 1470508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root char mount_path[256]; 1471508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root char rest[256]; 1472508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root FILE *fp; 1473508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root char line[1024]; 1474508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root 1475508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root if (!(fp = fopen("/proc/mounts", "r"))) { 1476508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root SLOGE("Error opening /proc/mounts (%s)", strerror(errno)); 1477508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root return -1; 1478508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root } 1479508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root 1480508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root // Create a string to compare against that has a trailing slash 148193ecb38daded7583a4a61f4f22519bb7a8a8c154Kenny Root int loopDirLen = strlen(Volume::LOOPDIR); 1482508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root char loopDir[loopDirLen + 2]; 1483508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root strcpy(loopDir, Volume::LOOPDIR); 1484508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root loopDir[loopDirLen++] = '/'; 1485508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root loopDir[loopDirLen] = '\0'; 1486508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root 1487508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root while(fgets(line, sizeof(line), fp)) { 1488508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root line[strlen(line)-1] = '\0'; 1489508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root 1490508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root /* 1491508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root * Should look like: 1492508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root * /dev/block/loop0 /mnt/obb/fc99df1323fd36424f864dcb76b76d65 ... 1493508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root */ 1494508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root sscanf(line, "%255s %255s %255s\n", device, mount_path, rest); 1495508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root 1496508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root if (!strncmp(mount_path, loopDir, loopDirLen)) { 1497508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root int fd = open(device, O_RDONLY); 1498508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root if (fd >= 0) { 1499508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root struct loop_info64 li; 1500508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root if (ioctl(fd, LOOP_GET_STATUS64, &li) >= 0) { 1501508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root cli->sendMsg(ResponseCode::AsecListResult, 1502508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root (const char*) li.lo_file_name, false); 1503508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root } 1504508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root close(fd); 1505508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root } 1506508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root } 1507508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root } 1508508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root 1509508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root fclose(fp); 1510508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root return 0; 1511508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root} 1512508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root 1513eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehatint VolumeManager::shareEnabled(const char *label, const char *method, bool *enabled) { 1514eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat Volume *v = lookupVolume(label); 1515eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat 1516eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat if (!v) { 1517eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat errno = ENOENT; 1518eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat return -1; 1519eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat } 1520eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat 1521eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat if (strcmp(method, "ums")) { 1522eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat errno = ENOSYS; 1523eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat return -1; 1524eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat } 1525eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat 1526eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat if (v->getState() != Volume::State_Shared) { 1527eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat *enabled = false; 1528b9aed74b146beb7499ebc5775e8ae179d16900efSan Mehat } else { 1529b9aed74b146beb7499ebc5775e8ae179d16900efSan Mehat *enabled = true; 1530eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat } 1531eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat return 0; 1532eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat} 1533eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat 1534a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatint VolumeManager::shareVolume(const char *label, const char *method) { 1535a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat Volume *v = lookupVolume(label); 1536a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 1537a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat if (!v) { 1538a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat errno = ENOENT; 1539a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat return -1; 1540a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat } 1541a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 1542a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat /* 1543a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat * Eventually, we'll want to support additional share back-ends, 1544a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat * some of which may work while the media is mounted. For now, 1545a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat * we just support UMS 1546a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat */ 1547a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat if (strcmp(method, "ums")) { 1548a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat errno = ENOSYS; 1549a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat return -1; 1550a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat } 1551a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 1552a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat if (v->getState() == Volume::State_NoMedia) { 1553a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat errno = ENODEV; 1554a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat return -1; 1555a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat } 1556a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 155749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat if (v->getState() != Volume::State_Idle) { 1558a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat // You need to unmount manually befoe sharing 155949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat errno = EBUSY; 156049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat return -1; 156149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat } 156249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat 15633b17005083be230509480ea65ae67c237142fadaKen Sumrall if (mVolManagerDisabled) { 15643b17005083be230509480ea65ae67c237142fadaKen Sumrall errno = EBUSY; 15653b17005083be230509480ea65ae67c237142fadaKen Sumrall return -1; 15663b17005083be230509480ea65ae67c237142fadaKen Sumrall } 15673b17005083be230509480ea65ae67c237142fadaKen Sumrall 15682dfe297ec47559dbe2297a72bea71cf515c03797Mike Lockwood dev_t d = v->getShareDevice(); 1569a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat if ((MAJOR(d) == 0) && (MINOR(d) == 0)) { 1570a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat // This volume does not support raw disk access 1571a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat errno = EINVAL; 1572a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat return -1; 1573a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat } 1574a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 1575a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat int fd; 1576a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat char nodepath[255]; 1577d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig int written = snprintf(nodepath, 1578a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat sizeof(nodepath), "/dev/block/vold/%d:%d", 1579346c5b20cbbced7edacf240015c4a89e5b2ca44fColin Cross major(d), minor(d)); 1580a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 1581d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig if ((written < 0) || (size_t(written) >= sizeof(nodepath))) { 1582d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig SLOGE("shareVolume failed: couldn't construct nodepath"); 1583d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig return -1; 1584d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig } 1585d1c226fce359e6de2b7334bf202c8f97af9fb9e0rpcraig 158697f2fc110b2ace7914671c2f5852379bd78922e4Mike Lockwood if ((fd = open(MASS_STORAGE_FILE_PATH, O_WRONLY)) < 0) { 158797ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGE("Unable to open ums lunfile (%s)", strerror(errno)); 1588a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat return -1; 1589a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat } 1590a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 1591a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat if (write(fd, nodepath, strlen(nodepath)) < 0) { 159297ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGE("Unable to write to ums lunfile (%s)", strerror(errno)); 1593a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat close(fd); 1594a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat return -1; 1595a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat } 1596a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 1597a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat close(fd); 1598a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat v->handleVolumeShared(); 1599a28056b38275003895ff5d9576681aca01544822Mike Lockwood if (mUmsSharingCount++ == 0) { 1600a28056b38275003895ff5d9576681aca01544822Mike Lockwood FILE* fp; 1601a28056b38275003895ff5d9576681aca01544822Mike Lockwood mSavedDirtyRatio = -1; // in case we fail 1602a28056b38275003895ff5d9576681aca01544822Mike Lockwood if ((fp = fopen("/proc/sys/vm/dirty_ratio", "r+"))) { 1603a28056b38275003895ff5d9576681aca01544822Mike Lockwood char line[16]; 1604a28056b38275003895ff5d9576681aca01544822Mike Lockwood if (fgets(line, sizeof(line), fp) && sscanf(line, "%d", &mSavedDirtyRatio)) { 1605a28056b38275003895ff5d9576681aca01544822Mike Lockwood fprintf(fp, "%d\n", mUmsDirtyRatio); 1606a28056b38275003895ff5d9576681aca01544822Mike Lockwood } else { 1607a28056b38275003895ff5d9576681aca01544822Mike Lockwood SLOGE("Failed to read dirty_ratio (%s)", strerror(errno)); 1608a28056b38275003895ff5d9576681aca01544822Mike Lockwood } 1609a28056b38275003895ff5d9576681aca01544822Mike Lockwood fclose(fp); 1610a28056b38275003895ff5d9576681aca01544822Mike Lockwood } else { 1611a28056b38275003895ff5d9576681aca01544822Mike Lockwood SLOGE("Failed to open /proc/sys/vm/dirty_ratio (%s)", strerror(errno)); 1612a28056b38275003895ff5d9576681aca01544822Mike Lockwood } 1613a28056b38275003895ff5d9576681aca01544822Mike Lockwood } 1614a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat return 0; 1615a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat} 1616a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 1617a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatint VolumeManager::unshareVolume(const char *label, const char *method) { 1618a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat Volume *v = lookupVolume(label); 1619a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 1620a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat if (!v) { 1621a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat errno = ENOENT; 1622a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat return -1; 1623a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat } 1624a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 1625a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat if (strcmp(method, "ums")) { 1626a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat errno = ENOSYS; 1627a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat return -1; 1628a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat } 1629a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 1630a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat if (v->getState() != Volume::State_Shared) { 1631a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat errno = EINVAL; 1632a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat return -1; 1633a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat } 1634a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 1635a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat int fd; 163697f2fc110b2ace7914671c2f5852379bd78922e4Mike Lockwood if ((fd = open(MASS_STORAGE_FILE_PATH, O_WRONLY)) < 0) { 163797ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGE("Unable to open ums lunfile (%s)", strerror(errno)); 1638a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat return -1; 1639a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat } 1640a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 1641a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat char ch = 0; 1642a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat if (write(fd, &ch, 1) < 0) { 164397ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGE("Unable to write to ums lunfile (%s)", strerror(errno)); 1644a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat close(fd); 1645a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat return -1; 1646a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat } 1647a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 1648a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat close(fd); 1649a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat v->handleVolumeUnshared(); 1650a28056b38275003895ff5d9576681aca01544822Mike Lockwood if (--mUmsSharingCount == 0 && mSavedDirtyRatio != -1) { 1651a28056b38275003895ff5d9576681aca01544822Mike Lockwood FILE* fp; 1652a28056b38275003895ff5d9576681aca01544822Mike Lockwood if ((fp = fopen("/proc/sys/vm/dirty_ratio", "r+"))) { 1653a28056b38275003895ff5d9576681aca01544822Mike Lockwood fprintf(fp, "%d\n", mSavedDirtyRatio); 1654a28056b38275003895ff5d9576681aca01544822Mike Lockwood fclose(fp); 1655a28056b38275003895ff5d9576681aca01544822Mike Lockwood } else { 1656a28056b38275003895ff5d9576681aca01544822Mike Lockwood SLOGE("Failed to open /proc/sys/vm/dirty_ratio (%s)", strerror(errno)); 1657a28056b38275003895ff5d9576681aca01544822Mike Lockwood } 1658a28056b38275003895ff5d9576681aca01544822Mike Lockwood mSavedDirtyRatio = -1; 1659a28056b38275003895ff5d9576681aca01544822Mike Lockwood } 1660a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat return 0; 166149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat} 166249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat 16633b17005083be230509480ea65ae67c237142fadaKen Sumrallextern "C" int vold_disableVol(const char *label) { 166429d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall VolumeManager *vm = VolumeManager::Instance(); 16653b17005083be230509480ea65ae67c237142fadaKen Sumrall vm->disableVolumeManager(); 16663b17005083be230509480ea65ae67c237142fadaKen Sumrall vm->unshareVolume(label, "ums"); 16670b8b59719357fb80c330442787f7d5b1e332263bKen Sumrall return vm->unmountVolume(label, true, false); 166829d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall} 166929d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall 167029d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrallextern "C" int vold_getNumDirectVolumes(void) { 167129d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall VolumeManager *vm = VolumeManager::Instance(); 167229d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall return vm->getNumDirectVolumes(); 167329d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall} 167429d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall 167529d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrallint VolumeManager::getNumDirectVolumes(void) { 167629d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall VolumeCollection::iterator i; 167729d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall int n=0; 167829d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall 167929d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall for (i = mVolumes->begin(); i != mVolumes->end(); ++i) { 168029d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall if ((*i)->getShareDevice() != (dev_t)0) { 168129d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall n++; 168229d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall } 168329d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall } 168429d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall return n; 168529d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall} 168629d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall 168729d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrallextern "C" int vold_getDirectVolumeList(struct volume_info *vol_list) { 168829d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall VolumeManager *vm = VolumeManager::Instance(); 168929d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall return vm->getDirectVolumeList(vol_list); 169029d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall} 169129d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall 169229d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrallint VolumeManager::getDirectVolumeList(struct volume_info *vol_list) { 169329d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall VolumeCollection::iterator i; 169429d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall int n=0; 169529d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall dev_t d; 169629d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall 169729d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall for (i = mVolumes->begin(); i != mVolumes->end(); ++i) { 169829d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall if ((d=(*i)->getShareDevice()) != (dev_t)0) { 169929d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall (*i)->getVolInfo(&vol_list[n]); 170029d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall snprintf(vol_list[n].blk_dev, sizeof(vol_list[n].blk_dev), 1701346c5b20cbbced7edacf240015c4a89e5b2ca44fColin Cross "/dev/block/vold/%d:%d", major(d), minor(d)); 170229d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall n++; 170329d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall } 170429d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall } 170529d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall 170629d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall return 0; 170729d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall} 170829d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall 17090b8b59719357fb80c330442787f7d5b1e332263bKen Sumrallint VolumeManager::unmountVolume(const char *label, bool force, bool revert) { 171049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat Volume *v = lookupVolume(label); 171149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat 171249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat if (!v) { 171349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat errno = ENOENT; 171449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat return -1; 171549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat } 171649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat 1717a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat if (v->getState() == Volume::State_NoMedia) { 1718a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat errno = ENODEV; 1719a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat return -1; 1720a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat } 1721a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 172249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat if (v->getState() != Volume::State_Mounted) { 172397ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGW("Attempt to unmount volume which isn't mounted (%d)\n", 1724a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat v->getState()); 172549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat errno = EBUSY; 1726319b1043bbbd410aa2d572d88b5936f26072d026Ken Sumrall return UNMOUNT_NOT_MOUNTED_ERR; 172749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat } 172849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat 17291a06edaf4db4e9c520624bcc06e0e13ee470d90eSan Mehat cleanupAsec(v, force); 173088705166ab82057090a070c6d4200c3d9db76f11San Mehat 17310b8b59719357fb80c330442787f7d5b1e332263bKen Sumrall return v->unmountVol(force, revert); 173249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat} 173349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat 1734425524dba1552ab3d2ad39e205e65d0a2af997f2Ken Sumrallextern "C" int vold_unmountAllAsecs(void) { 1735425524dba1552ab3d2ad39e205e65d0a2af997f2Ken Sumrall int rc; 1736425524dba1552ab3d2ad39e205e65d0a2af997f2Ken Sumrall 1737425524dba1552ab3d2ad39e205e65d0a2af997f2Ken Sumrall VolumeManager *vm = VolumeManager::Instance(); 1738425524dba1552ab3d2ad39e205e65d0a2af997f2Ken Sumrall rc = vm->unmountAllAsecsInDir(Volume::SEC_ASECDIR_EXT); 1739425524dba1552ab3d2ad39e205e65d0a2af997f2Ken Sumrall if (vm->unmountAllAsecsInDir(Volume::SEC_ASECDIR_INT)) { 1740425524dba1552ab3d2ad39e205e65d0a2af997f2Ken Sumrall rc = -1; 1741425524dba1552ab3d2ad39e205e65d0a2af997f2Ken Sumrall } 1742425524dba1552ab3d2ad39e205e65d0a2af997f2Ken Sumrall return rc; 1743425524dba1552ab3d2ad39e205e65d0a2af997f2Ken Sumrall} 1744425524dba1552ab3d2ad39e205e65d0a2af997f2Ken Sumrall 1745425524dba1552ab3d2ad39e205e65d0a2af997f2Ken Sumrall#define ID_BUF_LEN 256 1746425524dba1552ab3d2ad39e205e65d0a2af997f2Ken Sumrall#define ASEC_SUFFIX ".asec" 1747425524dba1552ab3d2ad39e205e65d0a2af997f2Ken Sumrall#define ASEC_SUFFIX_LEN (sizeof(ASEC_SUFFIX) - 1) 1748425524dba1552ab3d2ad39e205e65d0a2af997f2Ken Sumrallint VolumeManager::unmountAllAsecsInDir(const char *directory) { 1749425524dba1552ab3d2ad39e205e65d0a2af997f2Ken Sumrall DIR *d = opendir(directory); 1750425524dba1552ab3d2ad39e205e65d0a2af997f2Ken Sumrall int rc = 0; 1751425524dba1552ab3d2ad39e205e65d0a2af997f2Ken Sumrall 1752425524dba1552ab3d2ad39e205e65d0a2af997f2Ken Sumrall if (!d) { 1753425524dba1552ab3d2ad39e205e65d0a2af997f2Ken Sumrall SLOGE("Could not open asec dir %s", directory); 1754425524dba1552ab3d2ad39e205e65d0a2af997f2Ken Sumrall return -1; 1755425524dba1552ab3d2ad39e205e65d0a2af997f2Ken Sumrall } 1756425524dba1552ab3d2ad39e205e65d0a2af997f2Ken Sumrall 1757425524dba1552ab3d2ad39e205e65d0a2af997f2Ken Sumrall size_t dirent_len = offsetof(struct dirent, d_name) + 17588c480f73eed963eeca9b7df3e4c4543c6e43b0d7Elliott Hughes fpathconf(dirfd(d), _PC_NAME_MAX) + 1; 1759425524dba1552ab3d2ad39e205e65d0a2af997f2Ken Sumrall 1760425524dba1552ab3d2ad39e205e65d0a2af997f2Ken Sumrall struct dirent *dent = (struct dirent *) malloc(dirent_len); 1761425524dba1552ab3d2ad39e205e65d0a2af997f2Ken Sumrall if (dent == NULL) { 1762425524dba1552ab3d2ad39e205e65d0a2af997f2Ken Sumrall SLOGE("Failed to allocate memory for asec dir"); 1763425524dba1552ab3d2ad39e205e65d0a2af997f2Ken Sumrall return -1; 1764425524dba1552ab3d2ad39e205e65d0a2af997f2Ken Sumrall } 1765425524dba1552ab3d2ad39e205e65d0a2af997f2Ken Sumrall 1766425524dba1552ab3d2ad39e205e65d0a2af997f2Ken Sumrall struct dirent *result; 1767425524dba1552ab3d2ad39e205e65d0a2af997f2Ken Sumrall while (!readdir_r(d, dent, &result) && result != NULL) { 1768425524dba1552ab3d2ad39e205e65d0a2af997f2Ken Sumrall if (dent->d_name[0] == '.') 1769425524dba1552ab3d2ad39e205e65d0a2af997f2Ken Sumrall continue; 1770425524dba1552ab3d2ad39e205e65d0a2af997f2Ken Sumrall if (dent->d_type != DT_REG) 1771425524dba1552ab3d2ad39e205e65d0a2af997f2Ken Sumrall continue; 1772425524dba1552ab3d2ad39e205e65d0a2af997f2Ken Sumrall size_t name_len = strlen(dent->d_name); 1773425524dba1552ab3d2ad39e205e65d0a2af997f2Ken Sumrall if (name_len > 5 && name_len < (ID_BUF_LEN + ASEC_SUFFIX_LEN - 1) && 1774425524dba1552ab3d2ad39e205e65d0a2af997f2Ken Sumrall !strcmp(&dent->d_name[name_len - 5], ASEC_SUFFIX)) { 1775425524dba1552ab3d2ad39e205e65d0a2af997f2Ken Sumrall char id[ID_BUF_LEN]; 1776425524dba1552ab3d2ad39e205e65d0a2af997f2Ken Sumrall strlcpy(id, dent->d_name, name_len - 4); 1777425524dba1552ab3d2ad39e205e65d0a2af997f2Ken Sumrall if (unmountAsec(id, true)) { 1778425524dba1552ab3d2ad39e205e65d0a2af997f2Ken Sumrall /* Register the error, but try to unmount more asecs */ 1779425524dba1552ab3d2ad39e205e65d0a2af997f2Ken Sumrall rc = -1; 1780425524dba1552ab3d2ad39e205e65d0a2af997f2Ken Sumrall } 1781425524dba1552ab3d2ad39e205e65d0a2af997f2Ken Sumrall } 1782425524dba1552ab3d2ad39e205e65d0a2af997f2Ken Sumrall } 1783425524dba1552ab3d2ad39e205e65d0a2af997f2Ken Sumrall closedir(d); 1784425524dba1552ab3d2ad39e205e65d0a2af997f2Ken Sumrall 1785425524dba1552ab3d2ad39e205e65d0a2af997f2Ken Sumrall free(dent); 1786425524dba1552ab3d2ad39e205e65d0a2af997f2Ken Sumrall 1787425524dba1552ab3d2ad39e205e65d0a2af997f2Ken Sumrall return rc; 1788425524dba1552ab3d2ad39e205e65d0a2af997f2Ken Sumrall} 1789425524dba1552ab3d2ad39e205e65d0a2af997f2Ken Sumrall 1790a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat/* 1791a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat * Looks up a volume by it's label or mount-point 1792a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat */ 179349e2bce5b74129c26a35e25d4693cbfe98c4688eSan MehatVolume *VolumeManager::lookupVolume(const char *label) { 179449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat VolumeCollection::iterator i; 179549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat 179649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat for (i = mVolumes->begin(); i != mVolumes->end(); ++i) { 1797a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat if (label[0] == '/') { 1798ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey if (!strcmp(label, (*i)->getFuseMountpoint())) 1799a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat return (*i); 1800a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat } else { 1801a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat if (!strcmp(label, (*i)->getLabel())) 1802a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat return (*i); 1803a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat } 180449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat } 180549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat return NULL; 180649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat} 1807a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat 1808a19b250bd273455933ca3502cf2c2e0a803aff77San Mehatbool VolumeManager::isMountpointMounted(const char *mp) 1809a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat{ 1810a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat char device[256]; 1811a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat char mount_path[256]; 1812a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat char rest[256]; 1813a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat FILE *fp; 1814a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat char line[1024]; 1815a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat 1816a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat if (!(fp = fopen("/proc/mounts", "r"))) { 181797ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGE("Error opening /proc/mounts (%s)", strerror(errno)); 1818a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat return false; 1819a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat } 1820a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat 1821a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat while(fgets(line, sizeof(line), fp)) { 1822a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat line[strlen(line)-1] = '\0'; 1823a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat sscanf(line, "%255s %255s %255s\n", device, mount_path, rest); 1824a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat if (!strcmp(mount_path, mp)) { 1825a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat fclose(fp); 1826a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat return true; 1827a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat } 1828a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat } 1829a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat 1830a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat fclose(fp); 1831a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat return false; 1832a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat} 1833a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat 18341a06edaf4db4e9c520624bcc06e0e13ee470d90eSan Mehatint VolumeManager::cleanupAsec(Volume *v, bool force) { 18358c2c15b1c611708c85b3f1ba86b6db79c5c004d5Jeff Sharkey int rc = 0; 18368c2c15b1c611708c85b3f1ba86b6db79c5c004d5Jeff Sharkey 18378c2c15b1c611708c85b3f1ba86b6db79c5c004d5Jeff Sharkey char asecFileName[255]; 18388c2c15b1c611708c85b3f1ba86b6db79c5c004d5Jeff Sharkey 18398c2c15b1c611708c85b3f1ba86b6db79c5c004d5Jeff Sharkey AsecIdCollection removeAsec; 18408c2c15b1c611708c85b3f1ba86b6db79c5c004d5Jeff Sharkey AsecIdCollection removeObb; 184193ecb38daded7583a4a61f4f22519bb7a8a8c154Kenny Root 184293ecb38daded7583a4a61f4f22519bb7a8a8c154Kenny Root for (AsecIdCollection::iterator it = mActiveContainers->begin(); it != mActiveContainers->end(); 184393ecb38daded7583a4a61f4f22519bb7a8a8c154Kenny Root ++it) { 1844cbacf78eff70bd43bb899e164ec2ab409bc0904cKenny Root ContainerData* cd = *it; 184593ecb38daded7583a4a61f4f22519bb7a8a8c154Kenny Root 1846cbacf78eff70bd43bb899e164ec2ab409bc0904cKenny Root if (cd->type == ASEC) { 18478c2c15b1c611708c85b3f1ba86b6db79c5c004d5Jeff Sharkey if (findAsec(cd->id, asecFileName, sizeof(asecFileName))) { 18488c2c15b1c611708c85b3f1ba86b6db79c5c004d5Jeff Sharkey SLOGE("Couldn't find ASEC %s; cleaning up", cd->id); 18498c2c15b1c611708c85b3f1ba86b6db79c5c004d5Jeff Sharkey removeAsec.push_back(cd); 18508c2c15b1c611708c85b3f1ba86b6db79c5c004d5Jeff Sharkey } else { 18518c2c15b1c611708c85b3f1ba86b6db79c5c004d5Jeff Sharkey SLOGD("Found ASEC at path %s", asecFileName); 18528c2c15b1c611708c85b3f1ba86b6db79c5c004d5Jeff Sharkey if (!strncmp(asecFileName, Volume::SEC_ASECDIR_EXT, 18538c2c15b1c611708c85b3f1ba86b6db79c5c004d5Jeff Sharkey strlen(Volume::SEC_ASECDIR_EXT))) { 18548c2c15b1c611708c85b3f1ba86b6db79c5c004d5Jeff Sharkey removeAsec.push_back(cd); 18558c2c15b1c611708c85b3f1ba86b6db79c5c004d5Jeff Sharkey } 18568c2c15b1c611708c85b3f1ba86b6db79c5c004d5Jeff Sharkey } 1857cbacf78eff70bd43bb899e164ec2ab409bc0904cKenny Root } else if (cd->type == OBB) { 185893ecb38daded7583a4a61f4f22519bb7a8a8c154Kenny Root if (v == getVolumeForFile(cd->id)) { 18598c2c15b1c611708c85b3f1ba86b6db79c5c004d5Jeff Sharkey removeObb.push_back(cd); 1860cbacf78eff70bd43bb899e164ec2ab409bc0904cKenny Root } 1861cbacf78eff70bd43bb899e164ec2ab409bc0904cKenny Root } else { 1862cbacf78eff70bd43bb899e164ec2ab409bc0904cKenny Root SLOGE("Unknown container type %d!", cd->type); 18631a06edaf4db4e9c520624bcc06e0e13ee470d90eSan Mehat } 18641a06edaf4db4e9c520624bcc06e0e13ee470d90eSan Mehat } 186593ecb38daded7583a4a61f4f22519bb7a8a8c154Kenny Root 18668c2c15b1c611708c85b3f1ba86b6db79c5c004d5Jeff Sharkey for (AsecIdCollection::iterator it = removeAsec.begin(); it != removeAsec.end(); ++it) { 18678c2c15b1c611708c85b3f1ba86b6db79c5c004d5Jeff Sharkey ContainerData *cd = *it; 18688c2c15b1c611708c85b3f1ba86b6db79c5c004d5Jeff Sharkey SLOGI("Unmounting ASEC %s (dependent on %s)", cd->id, v->getLabel()); 18698c2c15b1c611708c85b3f1ba86b6db79c5c004d5Jeff Sharkey if (unmountAsec(cd->id, force)) { 18708c2c15b1c611708c85b3f1ba86b6db79c5c004d5Jeff Sharkey SLOGE("Failed to unmount ASEC %s (%s)", cd->id, strerror(errno)); 18718c2c15b1c611708c85b3f1ba86b6db79c5c004d5Jeff Sharkey rc = -1; 18728c2c15b1c611708c85b3f1ba86b6db79c5c004d5Jeff Sharkey } 18738c2c15b1c611708c85b3f1ba86b6db79c5c004d5Jeff Sharkey } 18748c2c15b1c611708c85b3f1ba86b6db79c5c004d5Jeff Sharkey 18758c2c15b1c611708c85b3f1ba86b6db79c5c004d5Jeff Sharkey for (AsecIdCollection::iterator it = removeObb.begin(); it != removeObb.end(); ++it) { 187693ecb38daded7583a4a61f4f22519bb7a8a8c154Kenny Root ContainerData *cd = *it; 18778c2c15b1c611708c85b3f1ba86b6db79c5c004d5Jeff Sharkey SLOGI("Unmounting OBB %s (dependent on %s)", cd->id, v->getLabel()); 187893ecb38daded7583a4a61f4f22519bb7a8a8c154Kenny Root if (unmountObb(cd->id, force)) { 187993ecb38daded7583a4a61f4f22519bb7a8a8c154Kenny Root SLOGE("Failed to unmount OBB %s (%s)", cd->id, strerror(errno)); 188093ecb38daded7583a4a61f4f22519bb7a8a8c154Kenny Root rc = -1; 188193ecb38daded7583a4a61f4f22519bb7a8a8c154Kenny Root } 188293ecb38daded7583a4a61f4f22519bb7a8a8c154Kenny Root } 188393ecb38daded7583a4a61f4f22519bb7a8a8c154Kenny Root 188493ecb38daded7583a4a61f4f22519bb7a8a8c154Kenny Root return rc; 18851a06edaf4db4e9c520624bcc06e0e13ee470d90eSan Mehat} 18861a06edaf4db4e9c520624bcc06e0e13ee470d90eSan Mehat 188771ebe154a5fbbb4b394a439ff0b6b9c84fbd04f5Jeff Sharkeyint VolumeManager::mkdirs(char* path) { 188827cfee3fa4e44d3a542312938df12cadfad3425eCylen Yao // Require that path lives under a volume we manage and is mounted 188971ebe154a5fbbb4b394a439ff0b6b9c84fbd04f5Jeff Sharkey const char* emulated_source = getenv("EMULATED_STORAGE_SOURCE"); 189071ebe154a5fbbb4b394a439ff0b6b9c84fbd04f5Jeff Sharkey const char* root = NULL; 18915ab02e787a05eda1d3382654d5496d6c763c2474Marco Nelissen if (emulated_source && !strncmp(path, emulated_source, strlen(emulated_source))) { 189271ebe154a5fbbb4b394a439ff0b6b9c84fbd04f5Jeff Sharkey root = emulated_source; 189371ebe154a5fbbb4b394a439ff0b6b9c84fbd04f5Jeff Sharkey } else { 189471ebe154a5fbbb4b394a439ff0b6b9c84fbd04f5Jeff Sharkey Volume* vol = getVolumeForFile(path); 189527cfee3fa4e44d3a542312938df12cadfad3425eCylen Yao if (vol && vol->getState() == Volume::State_Mounted) { 189671ebe154a5fbbb4b394a439ff0b6b9c84fbd04f5Jeff Sharkey root = vol->getMountpoint(); 189771ebe154a5fbbb4b394a439ff0b6b9c84fbd04f5Jeff Sharkey } 189871ebe154a5fbbb4b394a439ff0b6b9c84fbd04f5Jeff Sharkey } 189971ebe154a5fbbb4b394a439ff0b6b9c84fbd04f5Jeff Sharkey 190071ebe154a5fbbb4b394a439ff0b6b9c84fbd04f5Jeff Sharkey if (!root) { 190127cfee3fa4e44d3a542312938df12cadfad3425eCylen Yao SLOGE("Failed to find mounted volume for %s", path); 190271ebe154a5fbbb4b394a439ff0b6b9c84fbd04f5Jeff Sharkey return -EINVAL; 190371ebe154a5fbbb4b394a439ff0b6b9c84fbd04f5Jeff Sharkey } 190471ebe154a5fbbb4b394a439ff0b6b9c84fbd04f5Jeff Sharkey 190571ebe154a5fbbb4b394a439ff0b6b9c84fbd04f5Jeff Sharkey /* fs_mkdirs() does symlink checking and relative path enforcement */ 190671ebe154a5fbbb4b394a439ff0b6b9c84fbd04f5Jeff Sharkey return fs_mkdirs(path, 0700); 190771ebe154a5fbbb4b394a439ff0b6b9c84fbd04f5Jeff Sharkey} 1908