diff options
Diffstat (limited to 'mountd/AutoMount.c')
-rw-r--r-- | mountd/AutoMount.c | 210 |
1 files changed, 175 insertions, 35 deletions
diff --git a/mountd/AutoMount.c b/mountd/AutoMount.c index bfe8ad105..0aac871d5 100644 --- a/mountd/AutoMount.c +++ b/mountd/AutoMount.c @@ -76,17 +76,20 @@ typedef struct MountPoint { // 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; - // logical unit number (for UMS) - int lun; - // current state of the mount point MountState state; @@ -100,11 +103,13 @@ typedef struct MountPoint { // list of our mount points (does not change after initialization) static MountPoint* sMountPointList = NULL; -static int sNextLun = 0; 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/fsck_msdos"; // number of mount points that have timeouts pending static int sRetriesPending = 0; @@ -116,15 +121,18 @@ static pthread_mutex_t sMutex = PTHREAD_MUTEX_INITIALIZER; // via USB mass storage. static void SetBackingStore(MountPoint* mp, boolean enable) { - char path[PATH_MAX]; 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")); - snprintf(path, sizeof(path), "/sys/devices/platform/usb_mass_storage/lun%d/file", mp->lun); - fd = open(path, O_WRONLY); + fd = open(mp->driverStorePath, O_WRONLY); if (fd < 0) { - LOG_ERROR("could not open %s\n", path); + LOG_ERROR("could not open driver_store_path %s\n", mp->driverStorePath); } else { @@ -192,6 +200,56 @@ static boolean IsLoopMounted(const char* path) 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): fsck_msdos not found (skipping checks)\n", device); + return 0; + } + + sprintf(cmdline, "%s -p %s", FSCK_MSDOS_PATH, device); + LOG_MOUNT("Checking filesystem (%s)\n", cmdline); + + // XXX: Notify framework we're disk checking + + // XXX: PROTECT FROM VIKING KILLER + if ((rc = system(cmdline)) < 0) { + LOG_ERROR("Error executing disk check command (%d)\n", errno); + return -errno; + } + + rc = WEXITSTATUS(rc); + + if (rc == 0) { + LOG_MOUNT("Filesystem check completed OK\n"); + return 0; + } else if (rc == 1) { + LOG_MOUNT("Filesystem check failed (invalid usage)\n"); + return -EINVAL; + } else if (rc == 2) { + LOG_MOUNT("Filesystem check failed (unresolved issues)\n"); + return -EIO; + } else if (rc == 4) { + LOG_MOUNT("Filesystem check failed (root changed)\n"); + return -EIO; + } else if (rc == 8) { + LOG_MOUNT("Filesystem check failed (general failure)\n"); + return -EIO; + } else if (rc == 12) { + LOG_MOUNT("Filesystem check failed (exit signaled)\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("mounting %s at %s\n", device, mountPoint); @@ -237,6 +295,17 @@ static int DoMountDevice(const char* device, const char* mountPoint) if (result != 0) return result; + 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; + } + + // Extra safety measures: flags |= MS_NODEV | MS_NOEXEC | MS_NOSUID | MS_DIRSYNC; // Also, set fmask = 711 so that files cannot be marked executable, @@ -254,6 +323,24 @@ static int DoMountDevice(const char* device, const char* mountPoint) if (result == 0) { 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) { // ignore EBUSY, since it usually means the device is already mounted result = 0; @@ -267,32 +354,39 @@ static int DoMountDevice(const char* device, const char* mountPoint) return result; } -static int DoUnmountDevice(const char* mountPoint) +static int DoUnmountDevice(MountPoint *mp) { - boolean loop = IsLoopMounted(mountPoint); - int result = umount(mountPoint); + 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 (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); - } - #if CREATE_MOUNT_POINTS rmdir(mountPoint); #endif - NotifyMediaState(mountPoint, MEDIA_UNMOUNTED, false); + 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 @@ -408,7 +502,7 @@ static void RequestUnmount(MountPoint* mp, MountState retryState) sync(); DropSystemCaches(); - if (DoUnmountDevice(mp->mountPoint) == 0) + if (DoUnmountDevice(mp) == 0) { SetState(mp, kUnmounted); if (retryState == kUnmountingForUms) @@ -502,6 +596,8 @@ 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 @@ -573,7 +669,7 @@ static void HandleRetries() } else if (mp->state == kUnmountingForEject || mp->state == kUnmountingForUms) { - if (DoUnmountDevice(mp->mountPoint) == 0) + if (DoUnmountDevice(mp) == 0) { // unmounting succeeded // start mass storage, if state is kUnmountingForUms @@ -594,8 +690,25 @@ static void HandleRetries() // 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); + KillProcessesWithOpenFiles(mp->mountPoint, sigkill, gExcludedPids, + sizeof(gExcludedPids) / sizeof(pid_t)); + } } } @@ -676,6 +789,8 @@ static void* AutoMountThread(void* arg) int id; struct sigaction actions; + gExcludedPids[1] = getpid(); + memset(&actions, 0, sizeof(actions)); sigemptyset(&actions.sa_mask); actions.sa_flags = 0; @@ -829,7 +944,9 @@ void EnableMassStorage(boolean enable) void MountMedia(const char* mountPoint) { MountPoint* mp = sMountPointList; - + + LOG_MOUNT("MountMedia(%s)\n", mountPoint); + pthread_mutex_lock(&sMutex); while (mp) { @@ -883,27 +1000,48 @@ boolean IsMassStorageConnected() * ***********************************************/ -void AddMountPoint(const char* device, const char* mountPoint, boolean enableUms) +void *AddMountPoint(const char* device, const char* mountPoint, const char * driverStorePath, boolean enableUms) { MountPoint* newMountPoint; - LOG_MOUNT("AddMountPoint device: %s, mountPoint: %s\n", device, mountPoint); + 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; - if (enableUms) - newMountPoint->lun = sNextLun++; 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; @@ -916,6 +1054,8 @@ static void MountDevices() void StartAutoMounter() { + gExcludedPids[0] = getpid(); + gMassStorageConnected = ReadMassStorageState(); LOG_MOUNT(gMassStorageConnected ? "USB online\n" : "USB offline\n"); |