diff --git a/mountd/ASEC.c b/mountd/ASEC.c deleted file mode 100644 index a6aab9c52..000000000 --- a/mountd/ASEC.c +++ /dev/null @@ -1,774 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* -** Android Secure External Cache -*/ - -#include "mountd.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include - -#include -#include - -#include "ASEC.h" - -//#define MODULE_FAILURE_IS_FATAL - -extern int init_module(void *, unsigned long, const char *); -extern int delete_module(const char *, unsigned int); - -struct asec_context -{ - char *name; // Device mapper volume name - char *srcPath; // Path to the source (original) mount - char *backingFile; // Name of the image file - unsigned int sectors; // Number of sectors - char *dstPath; // Destination mount point - char *crypt; // Crypt options - - boolean needs_format; - boolean started; - int cacheFd; - int lo_num; - int dm_num; - unsigned char key[16]; -}; - -static const char *MODULES[] = { "dm_mod", "crypto", "crypto_algapi", "crypto_blkcipher", - "cryptomgr", "dm_crypt", "jbd", - "twofish_common", "twofish", "cbc", - "mbcache", "ext3", - NULL }; -static const char KEY_PATH[] = "/data/system/asec.key"; -static const char MODULE_PATH[] = "/system/lib/modules"; -static const char MKE2FS_PATH[] = "/system/bin/mke2fs"; -static const char E2FSCK_PATH[] = "/system/bin/e2fsck"; - -boolean AsecIsStarted(void *Handle) -{ - struct asec_context *ctx = (struct asec_context *) Handle; - - return ctx->started; -} - -const char *AsecMountPoint(void *Handle) -{ - struct asec_context *ctx = (struct asec_context *) Handle; - - return ctx->dstPath; -} - -static boolean AsecIsEnabled() -{ - char value[PROPERTY_VALUE_MAX]; - int enabled; - - property_get(ASEC_ENABLED, value, "0"); - - if (atoi(value) == 1) - return true; - return false; -} - -void *AsecInit(const char *Name, const char *SrcPath, const char *BackingFile, - const char *Size, const char *DstPath, const char *Crypt) -{ - struct asec_context *ctx; - - if (!AsecIsEnabled()) - return NULL; - - LOG_ASEC("AsecInit(%s, %s, %s, %s, %s, %s):\n", - Name, SrcPath, BackingFile, Size, DstPath, Crypt); - - if (!Name || !SrcPath || !BackingFile || !Size || !DstPath || !Crypt) { - LOG_ERROR("AsecInit(): Invalid arguments\n"); - return NULL; - } - - if (!(ctx = malloc(sizeof(struct asec_context)))) { - LOG_ERROR("AsecInit(): Out of memory\n"); - return NULL; - } - - memset(ctx, 0, sizeof(struct asec_context)); - ctx->name = strdup(Name); - ctx->srcPath = strdup(SrcPath); - ctx->backingFile = strdup(BackingFile); - ctx->sectors = atoi(Size); - ctx->dstPath = strdup(DstPath); - ctx->crypt = strdup(Crypt); - return ctx; -} - -void AsecDeinit(void *Handle) -{ - struct asec_context *ctx = (struct asec_context *) Handle; - - free(ctx->name); - free(ctx->srcPath); - free(ctx->backingFile); - free(ctx->dstPath); - free(ctx->crypt); - - free(ctx); -} - -static int AsecLoadModules() -{ - int i; - - for (i = 0; MODULES[i] != NULL; i++) { - const char *moduleName = MODULES[i]; - char moduleFile[255]; - int rc = 0; - void *module; - unsigned int size; - - sprintf(moduleFile, "%s/%s.ko", MODULE_PATH, moduleName); - module = load_file(moduleFile, &size); - if (!module) { - LOG_ERROR("Failed to load module %s (%d)\n", moduleFile, errno); - return -1; - } - - rc = init_module(module, size, ""); - free(module); - if (rc && errno != EEXIST) { - LOG_ERROR("Failed to init module %s (%d)\n", moduleFile, errno); - return -errno; - } - } - return 0; -} - -static int AsecUnloadModules() -{ - int i, j, rc; - - for (i = 0; MODULES[i] != NULL; i++); - - for (j = (i - 1); j >= 0; j--) { - const char *moduleName = MODULES[j]; - int maxretry = 10; - while(maxretry-- > 0) { - rc = delete_module(moduleName, O_NONBLOCK | O_EXCL); - if (rc < 0 && errno == EAGAIN) - usleep(500000); - else - break; - } - if (rc != 0) { - LOG_ERROR("Failed to unload module %s\n", moduleName); - return -errno; - } - } - return 0; -} - -static int AsecGenerateKey(struct asec_context *ctx) -{ - LOG_ASEC("AsecGenerateKey():\n"); - - memset((void *) ctx->key, 0x69, sizeof(ctx->key)); - return 0; -} - -static int AsecLoadGenerateKey(struct asec_context *ctx) -{ - int fd; - int rc = 0; - - if ((fd = open(KEY_PATH, O_RDWR | O_CREAT, 0600)) < 0) { - LOG_ERROR("Error opening / creating keyfile (%d)\n", errno); - return -errno; - } - - if (read(fd, ctx->key, sizeof(ctx->key)) != sizeof(ctx->key)) { - LOG_ASEC("Generating key\n"); - if ((rc = AsecGenerateKey(ctx)) < 0) { - LOG_ERROR("Error generating key (%d)\n", rc); - goto out; - } - if (write(fd, ctx->key, sizeof(ctx->key)) != sizeof(ctx->key)) { - LOG_ERROR("Error writing keyfile (%d)\n", errno); - rc = -1; - goto out; - } - } - - out: - close (fd); - return rc; -} - -static int AsecFormatFilesystem(struct asec_context *ctx) -{ - char cmdline[255]; - int rc; - - sprintf(cmdline, - "%s -b 4096 -m 1 -j -L \"%s\" /dev/block/dm-%d", - MKE2FS_PATH, ctx->name, ctx->dm_num); - - LOG_ASEC("Formatting filesystem (%s)\n", cmdline); - // XXX: PROTECT FROM VIKING KILLER - if ((rc = system(cmdline)) < 0) { - LOG_ERROR("Error executing format command (%d)\n", errno); - return -errno; - } - - rc = WEXITSTATUS(rc); - - if (!rc) { - LOG_ASEC("Format completed\n"); - } else { - LOG_ASEC("Format failed (%d)\n", rc); - } - - return rc; -} - -static int AsecCheckFilesystem(struct asec_context *ctx) -{ - char cmdline[255]; - int rc; - - sprintf(cmdline, "%s -p /dev/block/dm-%d", E2FSCK_PATH, ctx->dm_num); - - LOG_ASEC("Checking filesystem (%s)\n", cmdline); - // XXX: PROTECT FROM VIKING KILLER - if ((rc = system(cmdline)) < 0) { - LOG_ERROR("Error executing check command (%d)\n", errno); - return -errno; - } - - rc = WEXITSTATUS(rc); - - if (rc == 0) { - LOG_ASEC("ASEC volume '%s' had no errors\n", ctx->name); - } else if (rc == 1) { - LOG_ASEC("ASEC volume '%s' had corrected errors\n", ctx->name); - rc = 0; - } else if (rc == 2) { - LOG_ERROR("ASEC volume '%s' had corrected errors (system should be rebooted)\n", ctx->name); - } else if (rc == 4) { - LOG_ERROR("ASEC volume '%s' had uncorrectable errors\n", ctx->name); - } else if (rc == 8) { - LOG_ERROR("Operational error while checking volume '%s'\n", ctx->name); - } else { - LOG_ERROR("Unknown e2fsck exit code (%d)\n", rc); - } - return rc; -} - -static int AsecOpenCreateCache(struct asec_context *ctx) -{ - char filepath[255]; - - sprintf(filepath, "%s/%s", ctx->srcPath, ctx->backingFile); - - if ((ctx->cacheFd = open(filepath, O_RDWR)) < 0) { - if (errno == ENOENT) { - int rc = 0; - - LOG_ASEC("Creating cache file (%u sectors)\n", ctx->sectors); - if ((ctx->cacheFd = creat(filepath, 0600)) < 0) { - LOG_ERROR("Error creating cache (%d)\n", errno); - return -errno; - } - if (ftruncate(ctx->cacheFd, ctx->sectors * 512) < 0) { - LOG_ERROR("Error truncating cache (%d)\n", errno); - close(ctx->cacheFd); - unlink(filepath); - return -errno; - } - LOG_ASEC("Cache created (%u sectors) \n", ctx->sectors); - close(ctx->cacheFd); // creat() is WRONLY - - if ((ctx->cacheFd = open(filepath, O_RDWR)) < 0) { - LOG_ERROR("Error opening cache file (%d)\n", errno); - close(ctx->cacheFd); - unlink(filepath); - return -errno; - } - - ctx->needs_format = 1; - } else - return -errno; - } else { - struct stat stat_buf; - - if (fstat(ctx->cacheFd, &stat_buf) < 0) { - LOG_ERROR("Failed to fstat cache (%d)\n", errno); - close(ctx->cacheFd); - return -errno; - } - if (stat_buf.st_size != ctx->sectors * 512) { - LOG_ERROR("Cache size %lld != configured size %u\n", - stat_buf.st_size, ctx->sectors * 512); - } - - // XXX: Verify volume label matches ctx->name - } - - return 0; -} - -static void AsecCloseCache(struct asec_context *ctx) -{ - close(ctx->cacheFd); -} - -static void *_align(void *ptr, unsigned int a) -{ - register unsigned long agn = --a; - - return (void *) (((unsigned long) ptr + agn) & ~agn); -} - -static struct dm_ioctl *_dm_ioctl_setup(struct asec_context *ctx, int flags) -{ - void *buffer; - void *p; - const size_t min_size = 16 * 1024; - size_t len = sizeof(struct dm_ioctl); - struct dm_ioctl *io; - struct dm_target_spec *tgt; - int i; - char params[1024]; - char key[80]; - - key[0] = '\0'; - - for (i = 0; i < (int) sizeof(ctx->key); i++) { - char tmp[8]; - - sprintf(tmp, "%02x", ctx->key[i]); - strcat(key, tmp); - } - - // XXX: Handle ctx->crypt - sprintf(params, "twofish %s 0 /dev/block/loop%d 0", key, ctx->lo_num); - - if (len < min_size) - len = min_size; - - if (!(buffer = malloc(len))) { - LOG_ERROR("Unable to allocate memory\n"); - return NULL; - } - - memset(buffer, 0, len); - io = buffer; - tgt = (struct dm_target_spec *) &buffer[sizeof(struct dm_ioctl)]; - - io->version[0] = 4; - io->version[1] = 0; - io->version[2] = 0; - - io->data_size = len; - io->data_start = sizeof(struct dm_ioctl); - - io->flags = flags; - io->dev = 0; - - io->target_count = 1; - io->event_nr = 1; - strncpy(io->name, ctx->name, sizeof(io->name)); - - tgt->status = 0; - tgt->sector_start = 0; - tgt->length = ctx->sectors; - strncpy(tgt->target_type, "crypt", sizeof(tgt->target_type)); - - p = buffer + sizeof(struct dm_ioctl) + sizeof(struct dm_target_spec); - strcpy((char *) p, params); - p+= strlen(params) + 1; - - p = _align(p, 8); - tgt->next = p - buffer; - - return io; -} - -static int FindNextAvailableDm() -{ - int i; - - for (i = 0; i < 8; i++) { - char path[255]; - sprintf(path, "/dev/block/dm-%d", i); - if ((access(path, F_OK) < 0) && (errno == ENOENT)) - return i; - } - - LOG_ERROR("Out of device mapper numbers\n"); - return -1; -} - -static int AsecCreateDeviceMapping(struct asec_context *ctx) -{ - struct dm_ioctl *io; - int dmFd; - int rc = 0; - - ctx->dm_num = FindNextAvailableDm(); - - if ((dmFd = open("/dev/device-mapper", O_RDWR)) < 0) { - LOG_ERROR("Error opening device mapper (%d)\n", errno); - return -errno; - } - - if (!(io = _dm_ioctl_setup(ctx, 0))) { - LOG_ERROR("Unable to setup ioctl (out of memory)\n"); - close(dmFd); - return -ENOMEM; - } - - if ((rc = ioctl(dmFd, DM_DEV_CREATE, io)) < 0) { - LOG_ERROR("device-mapper create ioctl failed (%d)\n", errno); - rc = -errno; - goto out_free; - } - - free(io); - - if (!(io = _dm_ioctl_setup(ctx, DM_STATUS_TABLE_FLAG))) { - LOG_ERROR("Unable to setup ioctl (out of memory)\n"); - rc = -ENOMEM; - goto out_nofree; - } - - if ((rc = ioctl(dmFd, DM_TABLE_LOAD, io)) < 0) { - LOG_ERROR("device-mapper load ioctl failed (%d)\n", errno); - rc = -errno; - goto out_free; - } - - free(io); - - if (!(io = _dm_ioctl_setup(ctx, 0))) { - LOG_ERROR("Unable to setup ioctl (out of memory)\n"); - rc = -ENOMEM; - goto out_nofree; - } - - if ((rc = ioctl(dmFd, DM_DEV_SUSPEND, io)) < 0) { - LOG_ERROR("device-mapper resume ioctl failed (%d)\n", errno); - rc = -errno; - goto out_free; - } - -out_free: - free (io); -out_nofree: - close (dmFd); - return rc; -} - -static int AsecDestroyDeviceMapping(struct asec_context *ctx) -{ - struct dm_ioctl *io; - int dmFd; - int rc = 0; - - if ((dmFd = open("/dev/device-mapper", O_RDWR)) < 0) { - LOG_ERROR("Error opening device mapper (%d)\n", errno); - return -errno; - } - - if (!(io = _dm_ioctl_setup(ctx, DM_PERSISTENT_DEV_FLAG))) { - LOG_ERROR("Unable to setup ioctl (out of memory)\n"); - rc = -ENOMEM; - goto out_nofree; - } - - if ((rc = ioctl(dmFd, DM_DEV_REMOVE, io)) < 0) { - LOG_ERROR("device-mapper remove ioctl failed (%d)\n", errno); - rc = -errno; - goto out_free; - } - -out_free: - free (io); -out_nofree: - close (dmFd); - return rc; -} - -static int AsecMountCache(struct asec_context *ctx) -{ - int flags = MS_NODEV | MS_NOEXEC | MS_NOSUID | MS_NOATIME | MS_NODIRATIME; - char devname[255]; - - if (access(ctx->dstPath, R_OK)) { - LOG_ERROR("Destination mount point '%s' unavailable (%d)\n", ctx->dstPath, errno); - return -errno; - } - - sprintf(devname, "/dev/block/dm-%d", ctx->dm_num); - - if (mount(devname, ctx->dstPath, "ext3", flags, NULL)) { - LOG_ERROR("ASEC mount failed (%d)\n", errno); - return -errno; - } - - return 0; -} - -static int AsecUnmountCache(struct asec_context *ctx) -{ - if (umount(ctx->dstPath)) { - if (errno == EBUSY) { - LOG_ASEC("ASEC volume '%s' still busy\n", ctx->name); - } else { - LOG_ERROR("ASEC umount failed (%d)\n", errno); - } - return -errno; - } - LOG_ASEC("ASEC volume '%s' unmounted\n", ctx->name); - return 0; -} - -static int FindNextAvailableLoop() -{ - int i; - - for (i = 0; i < MAX_LOOP; i++) { - struct loop_info info; - char devname[255]; - int fd; - - sprintf(devname, "/dev/block/loop%d", i); - - if ((fd = open(devname, O_RDONLY)) < 0) { - LOG_ERROR("Unable to open %s (%d)\n", devname, errno); - return -errno; - } - - if (ioctl(fd, LOOP_GET_STATUS, &info) < 0) { - close(fd); - - if (errno == ENXIO) - return i; - - LOG_ERROR("Unable to get loop status for %s (%d)\n", devname, errno); - return -errno; - } - close(fd); - } - return -ENXIO; -} - -static int AsecCreateLoop(struct asec_context *ctx) -{ - char devname[255]; - int device_fd; - int rc = 0; - - ctx->lo_num = FindNextAvailableLoop(); - if (ctx->lo_num < 0) { - LOG_ERROR("No loop devices available\n"); - return -ENXIO; - } - - sprintf(devname, "/dev/block/loop%d", ctx->lo_num); - device_fd = open(devname, O_RDWR); - if (device_fd < 0) { - LOG_ERROR("failed to open loop device (%d)\n", errno); - return -errno; - } - - if (ioctl(device_fd, LOOP_SET_FD, ctx->cacheFd) < 0) { - LOG_ERROR("loop_set_fd ioctl failed (%d)\n", errno); - rc = -errno; - } - close(device_fd); - return rc; -} - -static int AsecDestroyLoop(struct asec_context *ctx) -{ - char devname[255]; - int device_fd; - int rc = 0; - - sprintf(devname, "/dev/block/loop%d", ctx->lo_num); - device_fd = open(devname, O_RDONLY); - if (device_fd < 0) { - LOG_ERROR("Failed to open loop (%d)\n", errno); - return -errno; - } - - if (ioctl(device_fd, LOOP_CLR_FD, 0) < 0) { - LOG_ERROR("Failed to destroy loop (%d)\n", errno); - rc = -errno; - } - - close(device_fd); - return rc; -} - -int AsecStart(void *Handle) -{ - struct asec_context *ctx = (struct asec_context *) Handle; - char value[PROPERTY_VALUE_MAX]; - int rc = 0; - - if (!ctx) - return -EINVAL; - - if (ctx->started) - return -EBUSY; - - LOG_ASEC("AsecStart(%s):\n", ctx->name); - - NotifyAsecState(ASEC_BUSY, ctx->dstPath); - - if ((rc = AsecLoadModules()) < 0) { - LOG_ERROR("AsecStart: Failed to load kernel modules\n"); -#ifdef MODULE_FAILURE_IS_FATAL - NotifyAsecState(ASEC_FAILED_INTERR, ctx->dstPath); - return rc; -#endif - } - - if ((rc = AsecLoadGenerateKey(ctx))) { - LOG_ERROR("AsecStart: Failed to load / generate key\n"); - NotifyAsecState(ASEC_FAILED_INTERR, ctx->dstPath); - return rc; - } - - if ((rc = AsecOpenCreateCache(ctx)) < 0) { - LOG_ERROR("AsecStart: Failed to open / create cache\n"); - NotifyAsecState(ASEC_FAILED_INTERR, ctx->dstPath); - return rc; - } - - if ((rc = AsecCreateLoop(ctx)) < 0) { - LOG_ERROR("AsecStart: Failed to create loop\n"); - NotifyAsecState(ASEC_FAILED_INTERR, ctx->dstPath); - goto fail_closecache; - } - - if ((rc = AsecCreateDeviceMapping(ctx)) < 0) { - LOG_ERROR("AsecStart: Failed to create devmapping (%d)\n", rc); - NotifyAsecState(ASEC_FAILED_INTERR, ctx->dstPath); - goto fail_destroyloop; - } - - if (ctx->needs_format) { - if ((rc = AsecFormatFilesystem(ctx))) { - LOG_ERROR("AsecStart: Failed to format cache (%d)\n", rc); - NotifyAsecState(ASEC_FAILED_INTERR, ctx->dstPath); - goto fail_destroydm; - } - ctx->needs_format = 0; - } else { - if ((rc = AsecCheckFilesystem(ctx))) { - LOG_ERROR("AsecStart: Failed to check filesystem (%d)\n", rc); - NotifyAsecState(ASEC_FAILED_INTERR, ctx->dstPath); - goto fail_destroydm; - } - } - - if ((rc = AsecMountCache(ctx)) < 0) { - LOG_ERROR("AsecStart: Failed to mount cache (%d)\n", rc); - NotifyAsecState(ASEC_FAILED_INTERR, ctx->dstPath); - goto fail_destroydm; - } - - NotifyAsecState(ASEC_AVAILABLE, ctx->dstPath); - ctx->started = true; - - return rc; - - fail_destroydm: - AsecDestroyDeviceMapping(ctx); - fail_destroyloop: - AsecDestroyLoop(ctx); - fail_closecache: - AsecCloseCache(ctx); - return rc; -} - -int AsecStop(void *Handle) -{ - struct asec_context *ctx = (struct asec_context *) Handle; - int rc = 0; - - if (!ctx->started) - return -EINVAL; - - LOG_ASEC("AsecStop(%s):\n", ctx->name); - - NotifyAsecState(ASEC_BUSY, ctx->dstPath); - - if ((rc = AsecUnmountCache(ctx)) < 0) { - LOG_ERROR("AsecStop: Failed to unmount cache (%d)\n", rc); - NotifyAsecState(ASEC_FAILED_INTERR, ctx->dstPath); - return rc; - } - - if ((rc = AsecDestroyDeviceMapping(ctx)) < 0) { - LOG_ERROR("AsecStop: Failed to destroy devmapping (%d)\n", rc); - NotifyAsecState(ASEC_FAILED_INTERR, ctx->dstPath); - return rc; - } - - if ((rc = AsecDestroyLoop(ctx)) < 0) { - LOG_ERROR("AsecStop: Failed to destroy loop device (%d)\n", rc); - NotifyAsecState(ASEC_FAILED_INTERR, ctx->dstPath); - return rc; - } - - AsecCloseCache(ctx); - - if ((rc = AsecUnloadModules()) < 0) { - if (rc == -EAGAIN) { - LOG_ASEC("AsecStop: Kernel modules still in use\n"); - } else { - LOG_ERROR("AsecStop: Failed to unload kernel modules (%d)\n", rc); -#ifdef MODULE_FAILURE_IS_FATAL - NotifyAsecState(ASEC_FAILED_INTERR, ctx->dstPath); - return rc; -#endif - } - } - - ctx->started = false; - NotifyAsecState(ASEC_DISABLED, ctx->dstPath); - return rc; -} diff --git a/mountd/ASEC.h b/mountd/ASEC.h deleted file mode 100644 index c87b28877..000000000 --- a/mountd/ASEC.h +++ /dev/null @@ -1,66 +0,0 @@ -#ifndef _ASEC_H -#define _ASEC_H - -#define ASEC_STORES_MAX 4 -#define MAX_LOOP 8 - -typedef enum AsecState { - // Feature disabled - ASEC_DISABLED, - - // Feature enabled and operational - ASEC_AVAILABLE, - - // Busy - ASEC_BUSY, - - // Internal Error - ASEC_FAILED_INTERR, - - // No media available - ASEC_FAILED_NOMEDIA, - - // Media is corrupt - ASEC_FAILED_BADMEDIA, - - // Key mismatch - ASEC_FAILED_BADKEY, -} AsecState; - -/* - * ASEC commands - */ -#define ASEC_CMD_SEND_STATUS "asec_send_status" -#define ASEC_CMD_ENABLE "asec_enable" -#define ASEC_CMD_DISABLE "asec_disable" - -/* - * ASEC events - */ - -// These events correspond to the states in the AsecState enum. -// A path to the ASEC mount point follows the colon -#define ASEC_EVENT_DISABLED "asec_disabled:" -#define ASEC_EVENT_AVAILABLE "asec_available:" -#define ASEC_EVENT_BUSY "asec_busy:" -#define ASEC_EVENT_FAILED_INTERR "asec_failed_interror:" -#define ASEC_EVENT_FAILED_NOMEDIA "asec_failed_nomedia" -#define ASEC_EVENT_FAILED_BADMEDIA "asec_failed_badmedia:" -#define ASEC_EVENT_FAILED_BADKEY "asec_failed_badkey:" - -/* - * System Properties - */ - -#define ASEC_ENABLED "asec.enabled" - -#define ASEC_STATUS "ro.asec.status" -#define ASEC_STATUS_DISABLED "disabled" -#define ASEC_STATUS_AVAILABLE "available" -#define ASEC_STATUS_BUSY "busy" -#define ASEC_STATUS_FAILED_INTERR "internal_error" -#define ASEC_STATUS_FAILED_NOMEDIA "no_media" -#define ASEC_STATUS_FAILED_BADMEDIA "bad_media" -#define ASEC_STATUS_FAILED_BADKEY "bad_key" - -#endif diff --git a/mountd/Android.mk b/mountd/Android.mk deleted file mode 100644 index 16532fa04..000000000 --- a/mountd/Android.mk +++ /dev/null @@ -1,22 +0,0 @@ -LOCAL_PATH:= $(call my-dir) - -include $(CLEAR_VARS) - -LOCAL_SRC_FILES:= \ - AutoMount.c \ - ProcessKiller.c \ - Server.c \ - mountd.c \ - ASEC.c \ - logwrapper.c - -LOCAL_MODULE:= mountd - -LOCAL_C_INCLUDES := $(KERNEL_HEADERS) - -LOCAL_CFLAGS := -DCREATE_MOUNT_POINTS=0 - -LOCAL_SHARED_LIBRARIES := libcutils - -# disabled - we are using vold now instead -# include $(BUILD_EXECUTABLE) diff --git a/mountd/AutoMount.c b/mountd/AutoMount.c deleted file mode 100644 index 12ad572e9..000000000 --- a/mountd/AutoMount.c +++ /dev/null @@ -1,1062 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* -** mountd automount support -*/ - -#include "mountd.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#define DEVPATH "/dev/block/" -#define DEVPATHLENGTH 11 // strlen(DEVPATH) - -// FIXME - only one loop mount is supported at a time -#define LOOP_DEVICE "/dev/block/loop0" - -// timeout value for poll() when retries are pending -#define POLL_TIMEOUT 1000 - -#define MAX_MOUNT_RETRIES 3 -#define MAX_UNMOUNT_RETRIES 5 - -typedef enum { - // device is unmounted - kUnmounted, - - // attempting to mount device - kMounting, - - // device is unmounted - kMounted, - - // attempting to unmount device - // so the media can be removed - kUnmountingForEject, - - // attempting to mount device - // so it can be shared via USB mass storage - kUnmountingForUms, -} MountState; - -typedef struct MountPoint { - // block device to mount - const char* device; - - // mount point for device - const char* mountPoint; - - // path to the UMS driver file for specifying the block device path - const char* driverStorePath; - - // true if device can be shared via - // USB mass storage - boolean enableUms; - - // Array of ASEC handles - void *asecHandles[ASEC_STORES_MAX]; - - // true if the device is being shared via USB mass storage - boolean umsActive; - - // current state of the mount point - MountState state; - - // number of mount or unmount retries so far, - // when attempting to mount or unmount the device - int retryCount; - - // next in sMountPointList linked list - struct MountPoint* next; -} MountPoint; - -// list of our mount points (does not change after initialization) -static MountPoint* sMountPointList = NULL; -boolean gMassStorageEnabled = false; -boolean gMassStorageConnected = false; - -static pthread_t sAutoMountThread = 0; -static pid_t gExcludedPids[2] = {-1, -1}; - -static const char FSCK_MSDOS_PATH[] = "/system/bin/dosfsck"; - -// number of mount points that have timeouts pending -static int sRetriesPending = 0; - -// for synchronization between sAutoMountThread and the server thread -static pthread_mutex_t sMutex = PTHREAD_MUTEX_INITIALIZER; - -// requests the USB mass_storage driver to begin or end sharing a block device -// via USB mass storage. -static void SetBackingStore(MountPoint* mp, boolean enable) -{ - int fd; - - if (!mp->driverStorePath) { - LOG_ERROR("no driver_store_path specified in config file for %s", mp->device); - return; - } - - LOG_MOUNT("SetBackingStore enable: %s\n", (enable ? "true" : "false")); - fd = open(mp->driverStorePath, O_WRONLY); - if (fd < 0) - { - LOG_ERROR("could not open driver_store_path %s\n", mp->driverStorePath); - } - else - { - if (enable) - { - write(fd, mp->device, strlen(mp->device)); - mp->umsActive = true; - } - else - { - char ch = 0; - write(fd, &ch, 1); - mp->umsActive = false; - } - close(fd); - } -} - -static boolean ReadMassStorageState() -{ - FILE* file = fopen("/sys/class/switch/usb_mass_storage/state", "r"); - if (file) - { - char buffer[20]; - fgets(buffer, sizeof(buffer), file); - fclose(file); - return (strncmp(buffer, "online", strlen("online")) == 0); - } - else - { - LOG_ERROR("could not read initial mass storage state\n"); - return false; - } -} - -static boolean IsLoopMounted(const char* path) -{ - FILE* f; - int count; - char device[256]; - char mount_path[256]; - char rest[256]; - int result = 0; - int path_length = strlen(path); - - f = fopen("/proc/mounts", "r"); - if (!f) { - LOG_ERROR("could not open /proc/mounts\n"); - return -1; - } - - do { - count = fscanf(f, "%255s %255s %255s\n", device, mount_path, rest); - if (count == 3) { - if (strcmp(LOOP_DEVICE, device) == 0 && strcmp(path, mount_path) == 0) - { - result = 1; - break; - } - } - } while (count == 3); - - fclose(f); - LOG_MOUNT("IsLoopMounted: %s returning %d\n", path, result); - return result; -} - -static int CheckFilesystem(const char *device) -{ - char cmdline[255]; - int rc; - - // XXX: SAN: Check for FAT signature - - int result = access(FSCK_MSDOS_PATH, X_OK); - if (result != 0) { - LOG_MOUNT("CheckFilesystem(%s): %s not found (skipping checks)\n", FSCK_MSDOS_PATH, device); - return 0; - } - - char *args[7]; - args[0] = FSCK_MSDOS_PATH; - args[1] = "-v"; - args[2] = "-V"; - args[3] = "-w"; - args[4] = "-p"; - args[5] = device; - args[6] = NULL; - - LOG_MOUNT("Checking filesystem on %s\n", device); - rc = logwrap(6, args); - - // XXX: We need to be able to distinguish between a FS with an error - // and a block device which does not have a FAT fs at all on it - if (rc == 0) { - LOG_MOUNT("Filesystem check completed OK\n"); - return 0; - } else if (rc == 1) { - LOG_MOUNT("Filesystem check failed (general failure)\n"); - return -EINVAL; - } else if (rc == 2) { - LOG_MOUNT("Filesystem check failed (invalid usage)\n"); - return -EIO; - } else { - LOG_MOUNT("Filesystem check failed (unknown exit code %d)\n", rc); - return -EIO; - } -} - -static int DoMountDevice(const char* device, const char* mountPoint) -{ - LOG_MOUNT("Attempting mount of %s on %s\n", device, mountPoint); - -#if CREATE_MOUNT_POINTS - // make sure mount point exists - mkdir(mountPoint, 0000); -#endif - - int flags = 0; - - if (device && strncmp(device, "/dev/", 5)) - { - // mount with the loop driver if device does not start with "/dev/" - int file_fd, device_fd; - - // FIXME - only one loop mount supported at a time - file_fd = open(device, O_RDWR); - if (file_fd < -1) { - LOG_ERROR("open backing file %s failed\n", device); - return 1; - } - device_fd = open(LOOP_DEVICE, O_RDWR); - if (device_fd < -1) { - LOG_ERROR("open %s failed", LOOP_DEVICE); - close(file_fd); - return 1; - } - if (ioctl(device_fd, LOOP_SET_FD, file_fd) < 0) - { - LOG_ERROR("ioctl LOOP_SET_FD failed\n"); - close(file_fd); - close(device_fd); - return 1; - } - - close(file_fd); - close(device_fd); - device = "/dev/block/loop0"; - } - - int result = access(device, R_OK); - if (result) { - LOG_ERROR("Unable to access '%s' (%d)\n", device, errno); - return -errno; - } - -#if 0 - if ((result = CheckFilesystem(device))) { - LOG_ERROR("Not mounting filesystem due to check failure (%d)\n", result); - // XXX: Notify framework - need a new SDCARD state for the following: - // - SD cards which are not present - // - SD cards with no partition table - // - SD cards with no filesystem - // - SD cards with bad filesystem - return result; - } -#endif - - // Extra safety measures: - flags |= MS_NODEV | MS_NOEXEC | MS_NOSUID | MS_DIRSYNC; - // Also, set fmask = 711 so that files cannot be marked executable, - // and cannot by opened by uid 1000 (system). Similar, dmask = 700 - // so that directories cannot be accessed by uid 1000. - result = mount(device, mountPoint, "vfat", flags, - "utf8,uid=1000,gid=1000,fmask=711,dmask=700"); - if (result && errno == EROFS) { - LOG_ERROR("mount failed EROFS, try again read-only\n"); - flags |= MS_RDONLY; - result = mount(device, mountPoint, "vfat", flags, - "utf8,uid=1000,gid=1000,fmask=711,dmask=700"); - } - - if (result == 0) { - LOG_MOUNT("Partition %s mounted on %s\n", device, mountPoint); - NotifyMediaState(mountPoint, MEDIA_MOUNTED, (flags & MS_RDONLY) != 0); - - MountPoint* mp = sMountPointList; - while (mp) { - if (!strcmp(mountPoint, mp->mountPoint)) { - int i; - - for (i = 0; i < ASEC_STORES_MAX; i++) { - if (mp->asecHandles[i] != NULL) { - int a_result; - if ((a_result = AsecStart(mp->asecHandles[i])) < 0) { - LOG_ERROR("ASEC start failure (%d)\n", a_result); - } - } - } - break; - } - mp = mp -> next; - } - } else if (errno == EBUSY) { - LOG_MOUNT("Mount failed (already mounted)\n"); - result = 0; - } else { -#if CREATE_MOUNT_POINTS - rmdir(mountPoint); -#endif - LOG_MOUNT("Unable to mount %s on %s\n", device, mountPoint); - } - - return result; -} - -static int DoUnmountDevice(MountPoint *mp) -{ - boolean loop = IsLoopMounted(mp->mountPoint); - int i; - - for (i = 0; i < ASEC_STORES_MAX; i++) { - if (mp->asecHandles[i] && AsecIsStarted(mp->asecHandles[i])) - AsecStop(mp->asecHandles[i]); - } - - int result = umount(mp->mountPoint); - LOG_MOUNT("umount returned %d errno: %d\n", result, errno); - - if (result == 0) - { -#if CREATE_MOUNT_POINTS - rmdir(mountPoint); -#endif - NotifyMediaState(mp->mountPoint, MEDIA_UNMOUNTED, false); - } - - if (loop) - { - // free the loop device - int loop_fd = open(LOOP_DEVICE, O_RDONLY); - if (loop_fd < -1) { - LOG_ERROR("open loop device failed\n"); - } - if (ioctl(loop_fd, LOOP_CLR_FD, 0) < 0) { - LOG_ERROR("ioctl LOOP_CLR_FD failed\n"); - } - - close(loop_fd); - } - - // ignore EINVAL and ENOENT, since it usually means the device is already unmounted - if (result && (errno == EINVAL || errno == ENOENT)) - result = 0; - - return result; -} - -static int MountPartition(const char* device, const char* mountPoint) -{ - char buf[100]; - int i; - - // attempt to mount subpartitions of the device - for (i = 1; i < 10; i++) - { - int rc; - snprintf(buf, sizeof(buf), "%sp%d", device, i); - rc = DoMountDevice(buf, mountPoint); - LOG_MOUNT("DoMountDevice(%s, %s) = %d\n", buf, mountPoint, rc); - if (rc == 0) - return 0; - } - - return -1; -} - -/***************************************************** - * - * AUTO-MOUNTER STATE ENGINE IMPLEMENTATION - * - *****************************************************/ - -static void SetState(MountPoint* mp, MountState state) -{ - mp->state = state; -} - -// Enter a state that requires retries and timeouts. -static void SetRetries(MountPoint* mp, MountState state) -{ - SetState(mp, state); - mp->retryCount = 0; - - sRetriesPending++; - // wake up the automounter thread if we are being called - // from somewhere else with no retries pending - if (sRetriesPending == 1 && sAutoMountThread != 0 && - pthread_self() != sAutoMountThread) - pthread_kill(sAutoMountThread, SIGUSR1); -} - -// Exit a state that requires retries and timeouts. -static void ClearRetries(MountPoint* mp, MountState state) -{ - SetState(mp, state); - sRetriesPending--; -} - -// attempt to mount the specified mount point. -// set up retry/timeout if it does not succeed at first. -static void RequestMount(MountPoint* mp) -{ - LOG_MOUNT("RequestMount %s\n", mp->mountPoint); - - if (mp->state != kMounted && mp->state != kMounting && - access(mp->device, R_OK) == 0) { - // try raw device first - if (DoMountDevice(mp->device, mp->mountPoint) == 0 || - MountPartition(mp->device, mp->mountPoint) == 0) - { - SetState(mp, kMounted); - } - else - { - SetState(mp, kMounting); - mp->retryCount = 0; - SetRetries(mp, kMounting); - } - } -} - -// Force the kernel to drop all caches. -static void DropSystemCaches(void) -{ - int fd; - - LOG_MOUNT("Dropping system caches\n"); - fd = open("/proc/sys/vm/drop_caches", O_WRONLY); - - if (fd > 0) { - char ch = 3; - int rc; - - rc = write(fd, &ch, 1); - if (rc <= 0) - LOG_MOUNT("Error dropping caches (%d)\n", rc); - close(fd); - } -} - -// attempt to unmount the specified mount point. -// set up retry/timeout if it does not succeed at first. -static void RequestUnmount(MountPoint* mp, MountState retryState) -{ - int result; - - LOG_MOUNT("RequestUnmount %s retryState: %d\n", mp->mountPoint, retryState); - - if (mp->state == kMounted) - { - SendUnmountRequest(mp->mountPoint); - - // do this in case the user pulls the SD card before we can successfully unmount - sync(); - DropSystemCaches(); - - if (DoUnmountDevice(mp) == 0) - { - SetState(mp, kUnmounted); - if (retryState == kUnmountingForUms) - { - SetBackingStore(mp, true); - NotifyMediaState(mp->mountPoint, MEDIA_SHARED, false); - } - } - else - { - LOG_MOUNT("unmount failed, set retry\n"); - SetRetries(mp, retryState); - } - } - else if (mp->state == kMounting) - { - SetState(mp, kUnmounted); - } -} - -// returns true if the mount point should be shared via USB mass storage -static boolean MassStorageEnabledForMountPoint(const MountPoint* mp) -{ - return (gMassStorageEnabled && gMassStorageConnected && mp->enableUms); -} - -// handles changes in gMassStorageEnabled and gMassStorageConnected -static void MassStorageStateChanged() -{ - MountPoint* mp = sMountPointList; - - boolean enable = (gMassStorageEnabled && gMassStorageConnected); - LOG_MOUNT("MassStorageStateChanged enable: %s\n", (enable ? "true" : "false")); - - while (mp) - { - if (mp->enableUms) - { - if (enable) - { - if (mp->state == kMounting) - SetState(mp, kUnmounted); - if (mp->state == kUnmounted) - { - SetBackingStore(mp, true); - NotifyMediaState(mp->mountPoint, MEDIA_SHARED, false); - } - else - { - LOG_MOUNT("MassStorageStateChanged requesting unmount\n"); - // need to successfully unmount first - RequestUnmount(mp, kUnmountingForUms); - } - } else if (mp->umsActive) { - SetBackingStore(mp, false); - if (mp->state == kUnmountingForUms) - { - ClearRetries(mp, kMounted); - NotifyMediaState(mp->mountPoint, MEDIA_MOUNTED, false); - } - else if (mp->state == kUnmounted) - { - NotifyMediaState(mp->mountPoint, MEDIA_UNMOUNTED, false); - RequestMount(mp); - } - } - } - - mp = mp->next; - } -} - -// called when USB mass storage connected state changes -static void HandleMassStorageOnline(boolean connected) -{ - if (connected != gMassStorageConnected) - { - gMassStorageConnected = connected; - SendMassStorageConnected(connected); - - // we automatically reset to mass storage off after USB is connected - if (!connected) - gMassStorageEnabled = false; - - MassStorageStateChanged(); - } -} - -// called when a new block device has been created -static void HandleMediaInserted(const char* device) -{ - MountPoint* mp = sMountPointList; - - LOG_MOUNT("HandleMediaInserted(%s):\n", device); - - while (mp) - { - // see if the device matches mount point's block device - if (mp->state == kUnmounted && - strncmp(device, mp->device + DEVPATHLENGTH, strlen(mp->device) - DEVPATHLENGTH) == 0) - { - if (MassStorageEnabledForMountPoint(mp)) - { - SetBackingStore(mp, true); - NotifyMediaState(mp->mountPoint, MEDIA_SHARED, false); - } - else - RequestMount(mp); - } - mp = mp->next; - } -} - -// called when a new block device has been deleted -static void HandleMediaRemoved(const char* device) -{ - MountPoint* mp = sMountPointList; - while (mp) - { - if (strncmp(device, mp->device + DEVPATHLENGTH, strlen(mp->device) - DEVPATHLENGTH) == 0) - { - if (mp->enableUms) - SetBackingStore(mp, false); - - if (mp->state == kMounted) - { - RequestUnmount(mp, kUnmountingForEject); - NotifyMediaState(mp->mountPoint, MEDIA_BAD_REMOVAL, false); - } - - NotifyMediaState(mp->mountPoint, MEDIA_REMOVED, false); - break; - } - mp = mp->next; - } -} - -// Handle retrying to mount or unmount devices, -// and handle timeout condition if we have tried too many times -static void HandleRetries() -{ - MountPoint* mp = sMountPointList; - - while (mp) - { - if (mp->state == kMounting) - { - if (MountPartition(mp->device, mp->mountPoint) == 0) - { - // mount succeeded - clear the retry for this mount point - ClearRetries(mp, kMounted); - } - else - { - mp->retryCount++; - if (mp->retryCount == MAX_MOUNT_RETRIES) - { - // we failed to mount the device too many times - ClearRetries(mp, kUnmounted); - // notify that we failed to mount - NotifyMediaState(mp->mountPoint, MEDIA_UNMOUNTABLE, false); - } - } - } - else if (mp->state == kUnmountingForEject || mp->state == kUnmountingForUms) - { - if (DoUnmountDevice(mp) == 0) - { - // unmounting succeeded - // start mass storage, if state is kUnmountingForUms - if (mp->state == kUnmountingForUms) - { - SetBackingStore(mp, true); - NotifyMediaState(mp->mountPoint, MEDIA_SHARED, false); - } - // clear the retry for this mount point - ClearRetries(mp, kUnmounted); - } - else - { - mp->retryCount++; - if (mp->retryCount >= MAX_UNMOUNT_RETRIES) - { - // kill any processes that are preventing the device from unmounting - // send SIGKILL instead of SIGTERM if the first attempt did not succeed - boolean sigkill = (mp->retryCount > MAX_UNMOUNT_RETRIES); - - int i; - - for (i = 0; i < ASEC_STORES_MAX; i++) { - if (mp->asecHandles[i] && AsecIsStarted(mp->asecHandles[i])) { - LOG_MOUNT("Killing processes for ASEC path '%s'\n", - AsecMountPoint(mp->asecHandles[i])); - KillProcessesWithOpenFiles(AsecMountPoint(mp->asecHandles[i]), - sigkill, - gExcludedPids, sizeof(gExcludedPids) / sizeof(pid_t)); - - // Now that we've killed the processes, try to stop the volume again - AsecStop(mp->asecHandles[i]); - } - } - - // unmounting the device is failing, so start killing processes - KillProcessesWithOpenFiles(mp->mountPoint, sigkill, gExcludedPids, - sizeof(gExcludedPids) / sizeof(pid_t)); - - } - } - } - - mp = mp->next; - } -} - -/***************************************************** - * - * AUTO-MOUNTER THREAD - * - *****************************************************/ - -static void sigusr1_handler(int signo) -{ - // don't need to do anything here -} - -// create a socket for listening to inotify events -int CreateINotifySocket() -{ - // initialize inotify - int fd = inotify_init(); - - if (fd < 0) { - LOG_ERROR("inotify_init failed, %s\n", strerror(errno)); - return -1; - } - - fcntl(fd, F_SETFL, O_NONBLOCK | fcntl(fd, F_GETFL)); - - return fd; -} - - -// create a socket for listening to uevents -int CreateUEventSocket() -{ - struct sockaddr_nl addr; - int sz = 64*1024; - int fd; - - memset(&addr, 0, sizeof(addr)); - addr.nl_family = AF_NETLINK; - addr.nl_pid = getpid(); - addr.nl_groups = 0xffffffff; - - fd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT); - if(fd < 0) - { - LOG_ERROR("could not create NETLINK_KOBJECT_UEVENT socket\n"); - return -1; - } - - setsockopt(fd, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz)); - - if(bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - LOG_ERROR("could not bind NETLINK_KOBJECT_UEVENT socket\n"); - close(fd); - return -1; - } - - return fd; -} - -/* - * Automounter main event thread. - * This thread listens for block devices being created and deleted via inotify, - * and listens for changes in the USB mass storage connected/disconnected via uevents from the - * power supply driver. - * This thread also handles retries and timeouts for requests to mount or unmount a device. - */ -static void* AutoMountThread(void* arg) -{ - int inotify_fd; - int uevent_fd; - int id; - struct sigaction actions; - - gExcludedPids[1] = getpid(); - - memset(&actions, 0, sizeof(actions)); - sigemptyset(&actions.sa_mask); - actions.sa_flags = 0; - actions.sa_handler = sigusr1_handler; - sigaction(SIGUSR1, &actions, NULL); - - // initialize inotify - inotify_fd = CreateINotifySocket(); - // watch for files created and deleted in "/dev" - inotify_add_watch(inotify_fd, DEVPATH, IN_CREATE|IN_DELETE); - - // initialize uevent watcher - uevent_fd = CreateUEventSocket(); - if (uevent_fd < 0) - { - LOG_ERROR("CreateUEventSocket failed, %s\n", strerror(errno)); - return NULL; - } - - while (1) - { - struct pollfd fds[2]; - int timeout, result; - -#define INOTIFY_IDX 0 -#define UEVENT_IDX 1 - - fds[INOTIFY_IDX].fd = inotify_fd; - fds[INOTIFY_IDX].events = POLLIN; - fds[INOTIFY_IDX].revents = 0; - fds[UEVENT_IDX].fd = uevent_fd; - fds[UEVENT_IDX].events = POLLIN; - fds[UEVENT_IDX].revents = 0; - - // wait for an event or a timeout to occur. - // poll() can also return in response to a SIGUSR1 signal - timeout = (sRetriesPending ? POLL_TIMEOUT : -1); - result = poll(fds, 2, timeout); - - // lock the mutex while we are handling events - pthread_mutex_lock(&sMutex); - - // handle inotify notifications for block device creation and deletion - if (fds[INOTIFY_IDX].revents == POLLIN) - { - struct inotify_event event; - char buffer[512]; - int length = read(inotify_fd, buffer, sizeof(buffer)); - int offset = 0; - - while (length >= (int)sizeof(struct inotify_event)) - { - struct inotify_event* event = (struct inotify_event *)&buffer[offset]; - - if (event->mask == IN_CREATE) - { - LOG_MOUNT("/dev/block/%s created\n", event->name); - HandleMediaInserted(event->name); - } - else if (event->mask == IN_DELETE) - { - LOG_MOUNT("/dev/block/%s deleted\n", event->name); - HandleMediaRemoved(event->name); - } - - int size = sizeof(struct inotify_event) + event->len; - length -= size; - offset += size; - } - } - - // handle uevent notifications for USB state changes - if (fds[UEVENT_IDX].revents == POLLIN) - { - char buffer[64*1024]; - int count; - - count = recv(uevent_fd, buffer, sizeof(buffer), 0); - if (count > 0) { - char* s = buffer; - char* end = s + count; - char* type = NULL; - char* online = NULL; - char* switchName = NULL; - char* switchState = NULL; - - while (s < end) { - if (!strncmp("POWER_SUPPLY_TYPE=", s, strlen("POWER_SUPPLY_TYPE="))) - type = s + strlen("POWER_SUPPLY_TYPE="); - else if (!strncmp("POWER_SUPPLY_ONLINE=", s, strlen("POWER_SUPPLY_ONLINE="))) - online = s + strlen("POWER_SUPPLY_ONLINE="); - else if (!strncmp("SWITCH_NAME=", s, strlen("SWITCH_NAME="))) - switchName = s + strlen("SWITCH_NAME="); - else if (!strncmp("SWITCH_STATE=", s, strlen("SWITCH_STATE="))) - switchState = s + strlen("SWITCH_STATE="); - s += (strlen(s) + 1); - } - - // we use the usb_mass_storage switch state to tell us when USB is online - if (switchName && switchState && - !strcmp(switchName, "usb_mass_storage") && !strcmp(switchState, "online")) - { - LOG_MOUNT("USB online\n"); - HandleMassStorageOnline(true); - } - - // and we use the power supply state to tell us when USB is offline - // we can't rely on the switch for offline detection because we get false positives - // when USB is reenumerated by the host. - if (type && online && !strcmp(type, "USB") && !strcmp(online, "0")) - { - LOG_MOUNT("USB offline\n"); - HandleMassStorageOnline(false); - } - } - } - - // handle retries - if (sRetriesPending) - HandleRetries(); - - // done handling events, so unlock the mutex - pthread_mutex_unlock(&sMutex); - } - - inotify_rm_watch(inotify_fd, id); - close(inotify_fd); - close(uevent_fd); - - return NULL; -} - -/***************************************************** - * - * THESE FUNCTIONS ARE CALLED FROM THE SERVER THREAD - * - *****************************************************/ - -// Called to enable or disable USB mass storage support -void EnableMassStorage(boolean enable) -{ - pthread_mutex_lock(&sMutex); - - LOG_MOUNT("EnableMassStorage %s\n", (enable ? "true" : "false")); - gMassStorageEnabled = enable; - MassStorageStateChanged(); - pthread_mutex_unlock(&sMutex); - } - -// Called to request that the specified mount point be mounted -void MountMedia(const char* mountPoint) -{ - MountPoint* mp = sMountPointList; - - LOG_MOUNT("MountMedia(%s)\n", mountPoint); - - pthread_mutex_lock(&sMutex); - while (mp) - { - if (strcmp(mp->mountPoint, mountPoint) == 0) - { - if (mp->state == kUnmountingForEject) - { - // handle the case where we try to remount before we actually unmounted - ClearRetries(mp, kMounted); - } - - // don't attempt to mount if mass storage is active - if (!MassStorageEnabledForMountPoint(mp)) - RequestMount(mp); - } - - mp = mp->next; - } - pthread_mutex_unlock(&sMutex); - } - -// Called to request that the specified mount point be unmounted -void UnmountMedia(const char* mountPoint) -{ - MountPoint* mp = sMountPointList; - - pthread_mutex_lock(&sMutex); - while (mp) - { - if (strcmp(mp->mountPoint, mountPoint) == 0) - RequestUnmount(mp, kUnmountingForEject); - - mp = mp->next; - } - pthread_mutex_unlock(&sMutex); -} - -boolean IsMassStorageEnabled() -{ - return gMassStorageEnabled; -} - -boolean IsMassStorageConnected() -{ - return gMassStorageConnected; -} - -/*********************************************** - * - * THESE FUNCTIONS ARE CALLED ONLY AT STARTUP - * - ***********************************************/ - -void *AddMountPoint(const char* device, const char* mountPoint, const char * driverStorePath, boolean enableUms) -{ - MountPoint* newMountPoint; - - LOG_MOUNT("AddMountPoint device: %s, mountPoint: %s driverStorePath: %s\n", device, mountPoint, driverStorePath); - // add a new MountPoint to the head of our linked list - newMountPoint = (MountPoint *)malloc(sizeof(MountPoint)); - newMountPoint->device = device; - newMountPoint->mountPoint = mountPoint; - newMountPoint->driverStorePath = driverStorePath; - newMountPoint->enableUms = enableUms; - newMountPoint->umsActive = false; - newMountPoint->state = kUnmounted; - newMountPoint->retryCount = 0; - - // add to linked list - newMountPoint->next = sMountPointList; - sMountPointList = newMountPoint; - return newMountPoint; -} - -int AddAsecToMountPoint(void *Mp, const char *name, const char *backing_file, const char *size, - const char *mount_point, const char *crypt) -{ - MountPoint *mp = (MountPoint *) Mp; - int i; - - for (i = 0; i < ASEC_STORES_MAX; i++) { - if (!mp->asecHandles[i]) - break; - } - - if (i == ASEC_STORES_MAX) { - LOG_ERROR("Maximum # of ASEC stores exceeded\n"); - return -EINVAL; - } - - if (!(mp->asecHandles[i] = AsecInit(name, mp->mountPoint, backing_file, size, mount_point, crypt))) - return -1; - - return 0; -} -static void MountDevices() -{ - MountPoint* mp = sMountPointList; - while (mp) - { - RequestMount(mp); - mp = mp->next; - } -} - -void StartAutoMounter() -{ - gExcludedPids[0] = getpid(); - - gMassStorageConnected = ReadMassStorageState(); - LOG_MOUNT(gMassStorageConnected ? "USB online\n" : "USB offline\n"); - - MountDevices(); - pthread_create(&sAutoMountThread, NULL, AutoMountThread, NULL); -} diff --git a/mountd/MODULE_LICENSE_APACHE2 b/mountd/MODULE_LICENSE_APACHE2 deleted file mode 100644 index e69de29bb..000000000 diff --git a/mountd/NOTICE b/mountd/NOTICE deleted file mode 100644 index c5b1efa7a..000000000 --- a/mountd/NOTICE +++ /dev/null @@ -1,190 +0,0 @@ - - Copyright (c) 2005-2008, The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - diff --git a/mountd/ProcessKiller.c b/mountd/ProcessKiller.c deleted file mode 100644 index e37777446..000000000 --- a/mountd/ProcessKiller.c +++ /dev/null @@ -1,222 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* -** mountd process killer -*/ - -#include "mountd.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -static boolean ReadSymLink(const char* path, char* link) -{ - struct stat s; - int length; - - if (lstat(path, &s) < 0) - return false; - if ((s.st_mode & S_IFMT) != S_IFLNK) - return false; - - // we have a symlink - length = readlink(path, link, PATH_MAX - 1); - if (length <= 0) - return false; - link[length] = 0; - return true; -} - -static boolean PathMatchesMountPoint(const char* path, const char* mountPoint) -{ - int length = strlen(mountPoint); - if (length > 1 && strncmp(path, mountPoint, length) == 0) - { - // we need to do extra checking if mountPoint does not end in a '/' - if (mountPoint[length - 1] == '/') - return true; - // if mountPoint does not have a trailing slash, we need to make sure - // there is one in the path to avoid partial matches. - return (path[length] == 0 || path[length] == '/'); - } - - return false; -} - -static void GetProcessName(int pid, char buffer[PATH_MAX]) -{ - int fd; - sprintf(buffer, "/proc/%d/cmdline", pid); - fd = open(buffer, O_RDONLY); - if (fd < 0) { - strcpy(buffer, "???"); - } else { - int length = read(fd, buffer, PATH_MAX - 1); - buffer[length] = 0; - close(fd); - } -} - -static boolean CheckFileDescriptorSymLinks(int pid, const char* mountPoint) -{ - DIR* dir; - struct dirent* de; - boolean fileOpen = false; - char path[PATH_MAX]; - char link[PATH_MAX]; - int parent_length; - - // compute path to process's directory of open files - sprintf(path, "/proc/%d/fd", pid); - dir = opendir(path); - if (!dir) - return false; - - // remember length of the path - parent_length = strlen(path); - // append a trailing '/' - path[parent_length++] = '/'; - - while ((de = readdir(dir)) != 0 && !fileOpen) { - if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) - continue; - - // append the file name, after truncating to parent directory - path[parent_length] = 0; - strcat(path, de->d_name); - - if (ReadSymLink(path, link) && PathMatchesMountPoint(link, mountPoint)) - { - char name[PATH_MAX]; - GetProcessName(pid, name); - LOG_ERROR("process %s (%d) has open file %s\n", name, pid, link); - fileOpen = true; - } - } - - closedir(dir); - return fileOpen; -} - -static boolean CheckFileMaps(int pid, const char* mountPoint) -{ - FILE* file; - char buffer[PATH_MAX + 100]; - boolean mapOpen = false; - - sprintf(buffer, "/proc/%d/maps", pid); - file = fopen(buffer, "r"); - if (!file) - return false; - - while (!mapOpen && fgets(buffer, sizeof(buffer), file)) - { - // skip to the path - const char* path = strchr(buffer, '/'); - if (path && PathMatchesMountPoint(path, mountPoint)) - { - char name[PATH_MAX]; - GetProcessName(pid, name); - LOG_ERROR("process %s (%d) has open file map for %s\n", name, pid, path); - mapOpen = true; - } - } - - fclose(file); - return mapOpen; -} - -static boolean CheckSymLink(int pid, const char* mountPoint, const char* name, const char* message) -{ - char path[PATH_MAX]; - char link[PATH_MAX]; - - sprintf(path, "/proc/%d/%s", pid, name); - if (ReadSymLink(path, link) && PathMatchesMountPoint(link, mountPoint)) - { - char name[PATH_MAX]; - GetProcessName(pid, name); - LOG_ERROR("process %s (%d) has %s in %s\n", name, pid, message, mountPoint); - return true; - } - else - return false; -} - -static int get_pid(const char* s) -{ - int result = 0; - while (*s) { - if (!isdigit(*s)) return -1; - result = 10 * result + (*s++ - '0'); - } - return result; -} - -// hunt down and kill processes that have files open on the given mount point -void KillProcessesWithOpenFiles(const char* mountPoint, boolean sigkill, int *excluded, int num_excluded) -{ - DIR* dir; - struct dirent* de; - - LOG_ERROR("KillProcessesWithOpenFiles %s\n", mountPoint); - dir = opendir("/proc"); - if (!dir) return; - - while ((de = readdir(dir)) != 0) - { - boolean killed = false; - // does the name look like a process ID? - int pid = get_pid(de->d_name); - if (pid == -1) continue; - - if (CheckFileDescriptorSymLinks(pid, mountPoint) // check for open files - || CheckFileMaps(pid, mountPoint) // check for mmap() - || CheckSymLink(pid, mountPoint, "cwd", "working directory") // check working directory - || CheckSymLink(pid, mountPoint, "root", "chroot") // check for chroot() - || CheckSymLink(pid, mountPoint, "exe", "executable path") // check executable path - ) - { - int i; - boolean hit = false; - - for (i = 0; i < num_excluded; i++) { - if (pid == excluded[i]) { - LOG_ERROR("I just need a little more TIME captain!\n"); - hit = true; - break; - } - } - - if (!hit) { - LOG_ERROR("Killing process %d\n", pid); - kill(pid, (sigkill ? SIGKILL : SIGTERM)); - } - } - } - - closedir(dir); -} diff --git a/mountd/Server.c b/mountd/Server.c deleted file mode 100644 index 64459bd88..000000000 --- a/mountd/Server.c +++ /dev/null @@ -1,313 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* -** mountd server support -*/ - -#include "mountd.h" -#include "ASEC.h" - -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include - - -// current client file descriptor -static int sFD = -1; - -// to synchronize writing to client -static pthread_mutex_t sWriteMutex = PTHREAD_MUTEX_INITIALIZER; - -// path for media that failed to mount before the runtime is connected -static char* sDeferredUnmountableMediaPath = NULL; - -// last asec msg before the runtime was connected -static char* sAsecDeferredMessage = NULL; -static char* sAsecDeferredArgument = NULL; - -static int Write(const char* message) -{ - int result = -1; - - pthread_mutex_lock(&sWriteMutex); - - LOG_SERVER("Write: %s\n", message); - if (sFD >= 0) - result = write(sFD, message, strlen(message) + 1); - - pthread_mutex_unlock(&sWriteMutex); - - return result; -} - -static int Write2(const char* message, const char* data) -{ - int result = -1; - - char* buffer = (char *)alloca(strlen(message) + strlen(data) + 1); - if (!buffer) - { - LOG_ERROR("alloca failed in Write2\n"); - return -1; - } - - strcpy(buffer, message); - strcat(buffer, data); - return Write(buffer); -} - -static void SendStatus() -{ - Write(IsMassStorageConnected() ? MOUNTD_UMS_CONNECTED : MOUNTD_UMS_DISCONNECTED); - Write(IsMassStorageEnabled() ? MOUNTD_UMS_ENABLED : MOUNTD_UMS_DISABLED); -} - -static void DoCommand(const char* command) -{ - LOG_SERVER("DoCommand %s\n", command); - - if (strcmp(command, MOUNTD_ENABLE_UMS) == 0) - { - EnableMassStorage(true); - Write(MOUNTD_UMS_ENABLED); - } - else if (strcmp(command, MOUNTD_DISABLE_UMS) == 0) - { - EnableMassStorage(false); - Write(MOUNTD_UMS_DISABLED); - } - else if (strcmp(command, MOUNTD_SEND_STATUS) == 0) - { - SendStatus(); - } - else if (strncmp(command, MOUNTD_MOUNT_MEDIA, strlen(MOUNTD_MOUNT_MEDIA)) == 0) - { - const char* path = command + strlen(MOUNTD_MOUNT_MEDIA); - MountMedia(path); - } - else if (strncmp(command, MOUNTD_EJECT_MEDIA, strlen(MOUNTD_EJECT_MEDIA)) == 0) - { - const char* path = command + strlen(MOUNTD_EJECT_MEDIA); - UnmountMedia(path); - } - else if (strncmp(command, ASEC_CMD_ENABLE, strlen(ASEC_CMD_ENABLE)) == 0) { - LOG_ASEC("Got ASEC_CMD_ENABLE\n"); - // XXX: SAN: Impliment - } - else if (strncmp(command, ASEC_CMD_DISABLE, strlen(ASEC_CMD_DISABLE)) == 0) { - LOG_ASEC("Got ASEC_CMD_DISABLE\n"); - // XXX: SAN: Impliment - } - else if (strncmp(command, ASEC_CMD_SEND_STATUS, strlen(ASEC_CMD_SEND_STATUS)) == 0) { - LOG_ASEC("Got ASEC_CMD_SEND_STATUS\n"); - // XXX: SAN: Impliment - } - else - LOGE("unknown command %s\n", command); -} - -int RunServer() -{ - int socket = android_get_control_socket(MOUNTD_SOCKET); - if (socket < 0) { - LOGE("Obtaining file descriptor for socket '%s' failed: %s", - MOUNTD_SOCKET, strerror(errno)); - return -1; - } - - if (listen(socket, 4) < 0) { - LOGE("Unable to listen on file descriptor '%d' for socket '%s': %s", - socket, MOUNTD_SOCKET, strerror(errno)); - return -1; - } - - while (1) - { - struct sockaddr addr; - socklen_t alen; - struct ucred cred; - socklen_t size; - - alen = sizeof(addr); - sFD = accept(socket, &addr, &alen); - if (sFD < 0) - continue; - - if (sDeferredUnmountableMediaPath) { - NotifyMediaState(sDeferredUnmountableMediaPath, MEDIA_UNMOUNTABLE, false); - free(sDeferredUnmountableMediaPath); - sDeferredUnmountableMediaPath = NULL; - } - - if (sAsecDeferredMessage) { - - if (Write2(sAsecDeferredMessage, sAsecDeferredArgument) < 0) - LOG_ERROR("Failed to deliver deferred ASEC msg to framework\n"); - free(sAsecDeferredMessage); - free(sAsecDeferredArgument); - sAsecDeferredMessage = sAsecDeferredArgument = NULL; - } - - while (1) - { - char buffer[101]; - int result = read(sFD, buffer, sizeof(buffer) - 1); - if (result > 0) - { - int start = 0; - int i; - // command should be zero terminated, but just in case - buffer[result] = 0; - for (i = 0; i < result; i++) - { - if (buffer[i] == 0) - { - DoCommand(buffer + start); - start = i + 1; - } - } - } - else - { - close(sFD); - sFD = -1; - break; - } - } - } - - // should never get here - return 0; -} - -void SendMassStorageConnected(boolean connected) -{ - Write(connected ? MOUNTD_UMS_CONNECTED : MOUNTD_UMS_DISCONNECTED); -} - -void SendUnmountRequest(const char* path) -{ - Write2(MOUNTD_REQUEST_EJECT, path); -} - -void NotifyAsecState(AsecState state, const char *argument) -{ - const char *event = NULL; - const char *status = NULL; - boolean deferr = true;; - - switch (state) { - case ASEC_DISABLED: - event = ASEC_EVENT_DISABLED; - status = ASEC_STATUS_DISABLED; - break; - case ASEC_AVAILABLE: - event = ASEC_EVENT_AVAILABLE; - status = ASEC_STATUS_AVAILABLE; - break; - case ASEC_BUSY: - event = ASEC_EVENT_BUSY; - status = ASEC_STATUS_BUSY; - deferr = false; - break; - case ASEC_FAILED_INTERR: - event = ASEC_EVENT_FAILED_INTERR; - status = ASEC_STATUS_FAILED_INTERR; - break; - case ASEC_FAILED_NOMEDIA: - event = ASEC_EVENT_FAILED_NOMEDIA; - status = ASEC_STATUS_FAILED_NOMEDIA; - break; - case ASEC_FAILED_BADMEDIA: - event = ASEC_EVENT_FAILED_BADMEDIA; - status = ASEC_STATUS_FAILED_BADMEDIA; - break; - case ASEC_FAILED_BADKEY: - event = ASEC_EVENT_FAILED_BADKEY; - status = ASEC_STATUS_FAILED_BADKEY; - break; - default: - LOG_ERROR("unknown AsecState %d in NotifyAsecState\n", state); - return; - } - - property_set(ASEC_STATUS, status); - - int result = Write2(event, argument); - if ((result < 0) && deferr) { - if (sAsecDeferredMessage) - free(sAsecDeferredMessage); - sAsecDeferredMessage = strdup(event); - if (sAsecDeferredArgument) - free(sAsecDeferredArgument); - sAsecDeferredArgument = strdup(argument); - LOG_ASEC("Deferring event '%s' arg '%s' until framework connects\n", event, argument); - } -} - -void NotifyMediaState(const char* path, MediaState state, boolean readOnly) -{ - const char* event = NULL; - const char* propertyValue = NULL; - - switch (state) { - case MEDIA_REMOVED: - event = MOUNTD_MEDIA_REMOVED; - propertyValue = EXTERNAL_STORAGE_REMOVED; - break; - case MEDIA_UNMOUNTED: - event = MOUNTD_MEDIA_UNMOUNTED; - propertyValue = EXTERNAL_STORAGE_UNMOUNTED; - break; - case MEDIA_MOUNTED: - event = (readOnly ? MOUNTD_MEDIA_MOUNTED_READ_ONLY : MOUNTD_MEDIA_MOUNTED); - propertyValue = (readOnly ? EXTERNAL_STORAGE_MOUNTED_READ_ONLY : EXTERNAL_STORAGE_MOUNTED); - break; - case MEDIA_SHARED: - event = MOUNTD_MEDIA_SHARED; - propertyValue = EXTERNAL_STORAGE_SHARED; - break; - case MEDIA_BAD_REMOVAL: - event = MOUNTD_MEDIA_BAD_REMOVAL; - propertyValue = EXTERNAL_STORAGE_BAD_REMOVAL; - break; - case MEDIA_UNMOUNTABLE: - event = MOUNTD_MEDIA_UNMOUNTABLE; - propertyValue = EXTERNAL_STORAGE_UNMOUNTABLE; - break; - default: - LOG_ERROR("unknown MediaState %d in NotifyMediaState\n", state); - return; - } - - property_set(EXTERNAL_STORAGE_STATE, propertyValue); - int result = Write2(event, path); - if (result < 0 && state == MEDIA_UNMOUNTABLE) { - - // if we cannot communicate with the runtime, defer this message until the runtime is available - sDeferredUnmountableMediaPath = strdup(path); - } -} diff --git a/mountd/logwrapper.c b/mountd/logwrapper.c deleted file mode 100644 index 69606ab62..000000000 --- a/mountd/logwrapper.c +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "private/android_filesystem_config.h" -#include "cutils/log.h" - -int parent(const char *tag, int parent_read) { - int status; - char buffer[4096]; - - int a = 0; // start index of unprocessed data - int b = 0; // end index of unprocessed data - int sz; - while ((sz = read(parent_read, &buffer[b], sizeof(buffer) - 1 - b)) > 0) { - - sz += b; - // Log one line at a time - for (b = 0; b < sz; b++) { - if (buffer[b] == '\r') { - buffer[b] = '\0'; - } else if (buffer[b] == '\n') { - buffer[b] = '\0'; - LOG(LOG_INFO, tag, &buffer[a]); - a = b + 1; - } - } - - if (a == 0 && b == sizeof(buffer) - 1) { - // buffer is full, flush - buffer[b] = '\0'; - LOG(LOG_INFO, tag, &buffer[a]); - b = 0; - } else if (a != b) { - // Keep left-overs - b -= a; - memmove(buffer, &buffer[a], b); - a = 0; - } else { - a = 0; - b = 0; - } - - } - // Flush remaining data - if (a != b) { - buffer[b] = '\0'; - LOG(LOG_INFO, tag, &buffer[a]); - } - status = 0xAAAA; - if (wait(&status) != -1) { // Wait for child - if (WIFEXITED(status)) { - LOG(LOG_INFO, "logwrapper", "%s terminated by exit(%d)", tag, - WEXITSTATUS(status)); - return WEXITSTATUS(status); - } else if (WIFSIGNALED(status)) - LOG(LOG_INFO, "logwrapper", "%s terminated by signal %d", tag, - WTERMSIG(status)); - else if (WIFSTOPPED(status)) - LOG(LOG_INFO, "logwrapper", "%s stopped by signal %d", tag, - WSTOPSIG(status)); - } else - LOG(LOG_INFO, "logwrapper", "%s wait() failed: %s (%d)", tag, - strerror(errno), errno); - return -EAGAIN; -} - -void child(int argc, char* argv[]) { - // create null terminated argv_child array - char* argv_child[argc + 1]; - memcpy(argv_child, argv, argc * sizeof(char *)); - argv_child[argc] = NULL; - - // XXX: PROTECT FROM VIKING KILLER - if (execvp(argv_child[0], argv_child)) { - LOG(LOG_ERROR, "logwrapper", - "executing %s failed: %s\n", argv_child[0], strerror(errno)); - exit(-1); - } -} - -int logwrap(int argc, char* argv[]) -{ - pid_t pid; - - int parent_ptty; - int child_ptty; - char *child_devname = NULL; - - /* Use ptty instead of socketpair so that STDOUT is not buffered */ - parent_ptty = open("/dev/ptmx", O_RDWR); - if (parent_ptty < 0) { - LOG(LOG_ERROR, "logwrapper", "Cannot create parent ptty\n"); - return -errno; - } - - if (grantpt(parent_ptty) || unlockpt(parent_ptty) || - ((child_devname = (char*)ptsname(parent_ptty)) == 0)) { - LOG(LOG_ERROR, "logwrapper", "Problem with /dev/ptmx\n"); - return -1; - } - - pid = fork(); - if (pid < 0) { - LOG(LOG_ERROR, "logwrapper", "Failed to fork\n"); - return -errno; - } else if (pid == 0) { - child_ptty = open(child_devname, O_RDWR); - if (child_ptty < 0) { - LOG(LOG_ERROR, "logwrapper", "Problem with child ptty\n"); - return -errno; - } - - // redirect stdout and stderr - close(parent_ptty); - dup2(child_ptty, 1); - dup2(child_ptty, 2); - close(child_ptty); - - child(argc, argv); - } else { - // switch user and group to "log" - // this may fail if we are not root, - // but in that case switching user/group is unnecessary - - // setgid(AID_LOG); - // setuid(AID_LOG); - - return parent(argv[0], parent_ptty); - } - - return 0; -} diff --git a/mountd/mountd.c b/mountd/mountd.c deleted file mode 100644 index 27ec8de90..000000000 --- a/mountd/mountd.c +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* -** mountd main program -*/ - -#include "mountd.h" - -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include - -#include - -#ifdef MOUNTD_LOG -FILE* logFile; -#endif - -struct asec_cfg { - const char *name; - const char *backing_file; - const char *size; - const char *mount_point; - const char *crypt; -}; - -static int ProcessAsecData(cnode *node, struct asec_cfg *stores, int idx) -{ - cnode *child = node->first_child; - const char *name = NULL; - const char *file = NULL; - const char *size = NULL; - const char *mp = NULL; - const char *crypt = NULL; - - LOG_ASEC("ProcessAsecData(%s, %p, %d)\n", node->name, stores, idx); - - while (child) { - if (!strcmp(child->name, "name")) - name = child->value; - else if (!strcmp(child->name, "backing_file")) - file = child->value; - else if (!strcmp(child->name, "size")) - size = child->value; - else if (!strcmp(child->name, "mount_point")) - mp = child->value; - else if (!strcmp(child->name, "crypt")) - crypt = child->value; - child = child->next; - } - - if (!name || !file || !size || !mp || !crypt) { - LOG_ERROR("Missing required token from config. Skipping ASEC volume\n"); - return -1; - } else if (idx == ASEC_STORES_MAX) { - LOG_ERROR("Maximum # of ASEC stores already defined\n"); - return -1; - } - - stores[idx].name = name; - stores[idx].backing_file = file; - stores[idx].size = size; - stores[idx].mount_point = mp; - stores[idx].crypt = crypt; - return ++idx; -} - -static void ReadConfigFile(const char* path) -{ - cnode* root = config_node("", ""); - cnode* node; - - config_load_file(root, path); - node = root->first_child; - - while (node) - { - if (strcmp(node->name, "mount") == 0) - { - const char* block_device = NULL; - const char* mount_point = NULL; - const char* driver_store_path = NULL; - boolean enable_ums = false; - cnode* child = node->first_child; - struct asec_cfg asec_stores[ASEC_STORES_MAX]; - int asec_idx = 0; - - memset(asec_stores, 0, sizeof(asec_stores)); - - while (child) - { - const char* name = child->name; - const char* value = child->value; - - if (!strncmp(name, "asec_", 5)) { - int rc = ProcessAsecData(child, asec_stores, asec_idx); - if (rc < 0) { - LOG_ERROR("Error processing ASEC cfg data\n"); - } else - asec_idx = rc; - } else if (strcmp(name, "block_device") == 0) - block_device = value; - else if (strcmp(name, "mount_point") == 0) - mount_point = value; - else if (strcmp(name, "driver_store_path") == 0) - driver_store_path = value; - else if (strcmp(name, "enable_ums") == 0 && - strcmp(value, "true") == 0) - enable_ums = true; - - child = child->next; - } - - // mount point and removable fields are optional - if (block_device && mount_point) - { - void *mp = AddMountPoint(block_device, mount_point, driver_store_path, enable_ums); - int i; - - for (i = 0; i < asec_idx; i++) { - AddAsecToMountPoint(mp, asec_stores[i].name, asec_stores[i].backing_file, - asec_stores[i].size, asec_stores[i].mount_point, - asec_stores[i].crypt); - } - } - } - - node = node->next; - } -} - -int main(int argc, char* argv[]) -{ - const char* configPath = "/system/etc/mountd.conf"; - int i; - - for (i = 1; i < argc; i++) - { - const char* arg = argv[i]; - - if (strcmp(arg, "-f") == 0) - { - if (i < argc - 1) - configPath = argv[++i]; - } - } - - ReadConfigFile(configPath); - StartAutoMounter(); - return RunServer(); -} diff --git a/mountd/mountd.h b/mountd/mountd.h deleted file mode 100644 index c4bc91df6..000000000 --- a/mountd/mountd.h +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef MOUNTD_H__ -#define MOUNTD_H__ - -#define LOG_TAG "mountd" -#include "cutils/log.h" - -#include "ASEC.h" - -typedef int boolean; -enum { - false = 0, - true = 1 -}; - -#define WEXITSTATUS(status) (((status) & 0xff00) >> 8) - -// Set this for logging error messages -#define ENABLE_LOG_ERROR - -// set this to log automounter events -#define ENABLE_LOG_MOUNT - -// set this to log server events -//#define ENABLE_LOG_SERVER - -// set this to log ASEC events -#define ENABLE_LOG_ASEC - -#ifdef ENABLE_LOG_ERROR -#define LOG_ERROR(fmt, args...) \ - { LOGE(fmt , ## args); } -#else -#define LOG_ERROR(fmt, args...) \ - do { } while (0) -#endif /* ENABLE_LOG_ERROR */ - -#ifdef ENABLE_LOG_MOUNT -#define LOG_MOUNT(fmt, args...) \ - { LOGD(fmt , ## args); } -#else -#define LOG_MOUNT(fmt, args...) \ - do { } while (0) -#endif /* ENABLE_LOG_MOUNT */ - -#ifdef ENABLE_LOG_SERVER -#define LOG_SERVER(fmt, args...) \ - { LOGD(fmt , ## args); } -#else -#define LOG_SERVER(fmt, args...) \ - do { } while (0) -#endif /* ENABLE_LOG_SERVER */ - -#ifdef ENABLE_LOG_ASEC -#define LOG_ASEC(fmt, args...) \ - { LOGD(fmt , ## args); } -#else -#define LOG_ASEC(fmt, args...) \ - do { } while (0) -#endif /* ENABLE_LOG_ASEC */ - - -typedef enum MediaState { - // no media in SD card slot - MEDIA_REMOVED, - - // media in SD card slot, but not mounted - MEDIA_UNMOUNTED, - - // media in SD card slot and mounted at its mount point - MEDIA_MOUNTED, - - // media in SD card slot, unmounted, and shared as a mass storage device - MEDIA_SHARED, - - // media was removed from SD card slot, but mount point was not unmounted - // this state is cleared after the mount point is unmounted - MEDIA_BAD_REMOVAL, - - // media in SD card slot could not be mounted (corrupt file system?) - MEDIA_UNMOUNTABLE, -} MediaState; - -// socket name for connecting to mountd -#define MOUNTD_SOCKET "mountd" - -// mountd commands -// these must match the corresponding strings in //device/java/android/android/os/UsbListener.java -#define MOUNTD_ENABLE_UMS "enable_ums" -#define MOUNTD_DISABLE_UMS "disable_ums" -#define MOUNTD_SEND_STATUS "send_status" - -// these commands should contain a mount point following the colon -#define MOUNTD_MOUNT_MEDIA "mount_media:" -#define MOUNTD_EJECT_MEDIA "eject_media:" - -// mountd events -// these must match the corresponding strings in //device/java/android/android/os/UsbListener.java -#define MOUNTD_UMS_ENABLED "ums_enabled" -#define MOUNTD_UMS_DISABLED "ums_disabled" -#define MOUNTD_UMS_CONNECTED "ums_connected" -#define MOUNTD_UMS_DISCONNECTED "ums_disconnected" - -// these events correspond to the states in the MediaState enum. -// a path to the mount point follows the colon. -#define MOUNTD_MEDIA_REMOVED "media_removed:" -#define MOUNTD_MEDIA_UNMOUNTED "media_unmounted:" -#define MOUNTD_MEDIA_MOUNTED "media_mounted:" -#define MOUNTD_MEDIA_MOUNTED_READ_ONLY "media_mounted_ro:" -#define MOUNTD_MEDIA_SHARED "media_shared:" -#define MOUNTD_MEDIA_BAD_REMOVAL "media_bad_removal:" -#define MOUNTD_MEDIA_UNMOUNTABLE "media_unmountable:" - -// this event sent to request unmount for media mount point -#define MOUNTD_REQUEST_EJECT "request_eject:" - -// system properties -// these must match the corresponding strings in //device/java/android/android/os/Environment.java -#define EXTERNAL_STORAGE_STATE "EXTERNAL_STORAGE_STATE" -#define EXTERNAL_STORAGE_REMOVED "removed" -#define EXTERNAL_STORAGE_UNMOUNTED "unmounted" -#define EXTERNAL_STORAGE_MOUNTED "mounted" -#define EXTERNAL_STORAGE_MOUNTED_READ_ONLY "mounted_ro" -#define EXTERNAL_STORAGE_SHARED "shared" -#define EXTERNAL_STORAGE_BAD_REMOVAL "bad_removal" -#define EXTERNAL_STORAGE_UNMOUNTABLE "unmountable" - -// AutoMount.c - -boolean IsMassStorageEnabled(); -boolean IsMassStorageConnected(); - -void MountMedia(const char* mountPoint); -void UnmountMedia(const char* mountPoint); -void EnableMassStorage(boolean enable); - -// call this before StartAutoMounter() to add a mount point to monitor -void *AddMountPoint(const char* device, const char* mountPoint, const char* driverStorePath, - boolean enableUms); - -int AddAsecToMountPoint(void *Mp, const char *name, const char *backing_file, - const char *size, const char *mount_point, const char *crypt); - -// start automounter thread -void StartAutoMounter(); - -// check /proc/mounts for mounted file systems, and notify mount or unmount for any that are in our automount list -void NotifyExistingMounts(); - - -// ASEC.c - -void *AsecInit(const char *Name, const char *SrcPath, const char *BackingFile, - const char *Size, const char *DstPath, const char *Crypt); -int AsecStart(void *Handle); -int AsecStop(void *Handle); -void AsecDeinit(void *Handle); -boolean AsecIsStarted(void *Handle); -const char *AsecMountPoint(void *Handle); - -// ProcessKiller.c - -void KillProcessesWithOpenFiles(const char* mountPoint, boolean sigkill, pid_t *excluded, int num_excluded); - -// logwrapper.c -int logwrap(int argc, char* argv[]); - -// Server.c - -int RunServer(); -void SendMassStorageConnected(boolean connected); -void SendUnmountRequest(const char* path); -void NotifyMediaState(const char* path, MediaState state, boolean readOnly); -void NotifyAsecState(AsecState state, const char *argument); -#endif // MOUNTD_H__