diff options
Diffstat (limited to 'mountd')
| -rw-r--r-- | mountd/ASEC.c | 18 | ||||
| -rw-r--r-- | mountd/Android.mk | 3 | ||||
| -rw-r--r-- | mountd/AutoMount.c | 62 | ||||
| -rw-r--r-- | mountd/dm-ioctl.h | 304 | ||||
| -rw-r--r-- | mountd/logwrapper.c | 154 | ||||
| -rw-r--r-- | mountd/mountd.h | 2 |
6 files changed, 198 insertions, 345 deletions
diff --git a/mountd/ASEC.c b/mountd/ASEC.c index 3d8e50e0..a6aab9c5 100644 --- a/mountd/ASEC.c +++ b/mountd/ASEC.c @@ -35,13 +35,15 @@ #include <sys/mount.h> #include <sys/stat.h> +#include <linux/dm-ioctl.h> #include <linux/loop.h> #include <cutils/properties.h> #include <cutils/misc.h> #include "ASEC.h" -#include "dm-ioctl.h" + +//#define MODULE_FAILURE_IS_FATAL extern int init_module(void *, unsigned long, const char *); extern int delete_module(const char *, unsigned int); @@ -104,14 +106,12 @@ void *AsecInit(const char *Name, const char *SrcPath, const char *BackingFile, { 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 (!AsecIsEnabled()) { - LOG_ERROR("AsecInit(): Disabled\n"); - return NULL; - } - if (!Name || !SrcPath || !BackingFile || !Size || !DstPath || !Crypt) { LOG_ERROR("AsecInit(): Invalid arguments\n"); return NULL; @@ -159,7 +159,7 @@ static int AsecLoadModules() sprintf(moduleFile, "%s/%s.ko", MODULE_PATH, moduleName); module = load_file(moduleFile, &size); if (!module) { - LOG_ERROR("Failed to load module %s\n", moduleFile); + LOG_ERROR("Failed to load module %s (%d)\n", moduleFile, errno); return -1; } @@ -659,8 +659,10 @@ int AsecStart(void *Handle) 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))) { @@ -759,8 +761,10 @@ int AsecStop(void *Handle) 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 } } diff --git a/mountd/Android.mk b/mountd/Android.mk index bc128ac0..2fb76400 100644 --- a/mountd/Android.mk +++ b/mountd/Android.mk @@ -7,7 +7,8 @@ LOCAL_SRC_FILES:= \ ProcessKiller.c \ Server.c \ mountd.c \ - ASEC.c + ASEC.c \ + logwrapper.c LOCAL_MODULE:= mountd diff --git a/mountd/AutoMount.c b/mountd/AutoMount.c index 0aac871d..0853b41c 100644 --- a/mountd/AutoMount.c +++ b/mountd/AutoMount.c @@ -109,7 +109,7 @@ 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"; +static const char FSCK_MSDOS_PATH[] = "/system/bin/dosfsck"; // number of mount points that have timeouts pending static int sRetriesPending = 0; @@ -209,40 +209,32 @@ static int CheckFilesystem(const char *device) int result = access(FSCK_MSDOS_PATH, X_OK); if (result != 0) { - LOG_MOUNT("CheckFilesystem(%s): fsck_msdos not found (skipping checks)\n", device); + LOG_MOUNT("CheckFilesystem(%s): %s not found (skipping checks)\n", FSCK_MSDOS_PATH, 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); + 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 (invalid usage)\n"); + LOG_MOUNT("Filesystem check failed (general failure)\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"); + LOG_MOUNT("Filesystem check failed (invalid usage)\n"); return -EIO; } else { LOG_MOUNT("Filesystem check failed (unknown exit code %d)\n", rc); @@ -252,7 +244,7 @@ static int CheckFilesystem(const char *device) static int DoMountDevice(const char* device, const char* mountPoint) { - LOG_MOUNT("mounting %s at %s\n", device, mountPoint); + LOG_MOUNT("Attempting mount of %s on %s\n", device, mountPoint); #if CREATE_MOUNT_POINTS // make sure mount point exists @@ -292,8 +284,10 @@ static int DoMountDevice(const char* device, const char* mountPoint) } int result = access(device, R_OK); - if (result != 0) - return result; + if (result) { + LOG_ERROR("Unable to access '%s' (%d)\n", device, errno); + return -errno; + } if ((result = CheckFilesystem(device))) { LOG_ERROR("Not mounting filesystem due to check failure (%d)\n", result); @@ -304,7 +298,6 @@ static int DoMountDevice(const char* device, const char* mountPoint) // - SD cards with bad filesystem return result; } - // Extra safety measures: flags |= MS_NODEV | MS_NOEXEC | MS_NOSUID | MS_DIRSYNC; @@ -319,9 +312,9 @@ static int DoMountDevice(const char* device, const char* mountPoint) result = mount(device, mountPoint, "vfat", flags, "utf8,uid=1000,gid=1000,fmask=711,dmask=700"); } - LOG_MOUNT("mount returned %d errno: %d\n", result, errno); if (result == 0) { + LOG_MOUNT("Partition %s mounted on %s\n", device, mountPoint); NotifyMediaState(mountPoint, MEDIA_MOUNTED, (flags & MS_RDONLY) != 0); MountPoint* mp = sMountPointList; @@ -342,13 +335,13 @@ static int DoMountDevice(const char* device, const char* mountPoint) mp = mp -> next; } } else if (errno == EBUSY) { - // ignore EBUSY, since it usually means the device is already mounted + LOG_MOUNT("Mount failed (already mounted)\n"); result = 0; } else { #if CREATE_MOUNT_POINTS rmdir(mountPoint); #endif - LOG_MOUNT("mount failed, errno: %d\n", errno); + LOG_MOUNT("Unable to mount %s on %s\n", device, mountPoint); } return result; @@ -404,8 +397,11 @@ static int MountPartition(const char* device, const char* mountPoint) // attempt to mount subpartitions of the device for (i = 1; i < 10; i++) { + int rc; snprintf(buf, sizeof(buf), "%sp%d", device, i); - if (DoMountDevice(buf, mountPoint) == 0) + rc = DoMountDevice(buf, mountPoint); + LOG_MOUNT("DoMountDevice(%s, %s) = %d\n", buf, mountPoint, rc); + if (rc == 0) return 0; } diff --git a/mountd/dm-ioctl.h b/mountd/dm-ioctl.h deleted file mode 100644 index ee5c3508..00000000 --- a/mountd/dm-ioctl.h +++ /dev/null @@ -1,304 +0,0 @@ -/* - * Copyright (C) 2001 - 2003 Sistina Software (UK) Limited. - * Copyright (C) 2004 - 2005 Red Hat, Inc. All rights reserved. - * - * This file is released under the LGPL. - */ - -#ifndef _LINUX_DM_IOCTL_V4_H -#define _LINUX_DM_IOCTL_V4_H - -#ifdef linux -# include <linux/types.h> -#endif - -#define DM_DIR "mapper" /* Slashes not supported */ -#define DM_MAX_TYPE_NAME 16 -#define DM_NAME_LEN 128 -#define DM_UUID_LEN 129 - -/* - * A traditional ioctl interface for the device mapper. - * - * Each device can have two tables associated with it, an - * 'active' table which is the one currently used by io passing - * through the device, and an 'inactive' one which is a table - * that is being prepared as a replacement for the 'active' one. - * - * DM_VERSION: - * Just get the version information for the ioctl interface. - * - * DM_REMOVE_ALL: - * Remove all dm devices, destroy all tables. Only really used - * for debug. - * - * DM_LIST_DEVICES: - * Get a list of all the dm device names. - * - * DM_DEV_CREATE: - * Create a new device, neither the 'active' or 'inactive' table - * slots will be filled. The device will be in suspended state - * after creation, however any io to the device will get errored - * since it will be out-of-bounds. - * - * DM_DEV_REMOVE: - * Remove a device, destroy any tables. - * - * DM_DEV_RENAME: - * Rename a device. - * - * DM_SUSPEND: - * This performs both suspend and resume, depending which flag is - * passed in. - * Suspend: This command will not return until all pending io to - * the device has completed. Further io will be deferred until - * the device is resumed. - * Resume: It is no longer an error to issue this command on an - * unsuspended device. If a table is present in the 'inactive' - * slot, it will be moved to the active slot, then the old table - * from the active slot will be _destroyed_. Finally the device - * is resumed. - * - * DM_DEV_STATUS: - * Retrieves the status for the table in the 'active' slot. - * - * DM_DEV_WAIT: - * Wait for a significant event to occur to the device. This - * could either be caused by an event triggered by one of the - * targets of the table in the 'active' slot, or a table change. - * - * DM_TABLE_LOAD: - * Load a table into the 'inactive' slot for the device. The - * device does _not_ need to be suspended prior to this command. - * - * DM_TABLE_CLEAR: - * Destroy any table in the 'inactive' slot (ie. abort). - * - * DM_TABLE_DEPS: - * Return a set of device dependencies for the 'active' table. - * - * DM_TABLE_STATUS: - * Return the targets status for the 'active' table. - * - * DM_TARGET_MSG: - * Pass a message string to the target at a specific offset of a device. - * - * DM_DEV_SET_GEOMETRY: - * Set the geometry of a device by passing in a string in this format: - * - * "cylinders heads sectors_per_track start_sector" - * - * Beware that CHS geometry is nearly obsolete and only provided - * for compatibility with dm devices that can be booted by a PC - * BIOS. See struct hd_geometry for range limits. Also note that - * the geometry is erased if the device size changes. - */ - -/* - * All ioctl arguments consist of a single chunk of memory, with - * this structure at the start. If a uuid is specified any - * lookup (eg. for a DM_INFO) will be done on that, *not* the - * name. - */ -struct dm_ioctl { - /* - * The version number is made up of three parts: - * major - no backward or forward compatibility, - * minor - only backwards compatible, - * patch - both backwards and forwards compatible. - * - * All clients of the ioctl interface should fill in the - * version number of the interface that they were - * compiled with. - * - * All recognised ioctl commands (ie. those that don't - * return -ENOTTY) fill out this field, even if the - * command failed. - */ - uint32_t version[3]; /* in/out */ - uint32_t data_size; /* total size of data passed in - * including this struct */ - - uint32_t data_start; /* offset to start of data - * relative to start of this struct */ - - uint32_t target_count; /* in/out */ - int32_t open_count; /* out */ - uint32_t flags; /* in/out */ - uint32_t event_nr; /* in/out */ - uint32_t padding; - - uint64_t dev; /* in/out */ - - char name[DM_NAME_LEN]; /* device name */ - char uuid[DM_UUID_LEN]; /* unique identifier for - * the block device */ - char data[7]; /* padding or data */ -}; - -/* - * Used to specify tables. These structures appear after the - * dm_ioctl. - */ -struct dm_target_spec { - uint64_t sector_start; - uint64_t length; - int32_t status; /* used when reading from kernel only */ - - /* - * Location of the next dm_target_spec. - * - When specifying targets on a DM_TABLE_LOAD command, this value is - * the number of bytes from the start of the "current" dm_target_spec - * to the start of the "next" dm_target_spec. - * - When retrieving targets on a DM_TABLE_STATUS command, this value - * is the number of bytes from the start of the first dm_target_spec - * (that follows the dm_ioctl struct) to the start of the "next" - * dm_target_spec. - */ - uint32_t next; - - char target_type[DM_MAX_TYPE_NAME]; - - /* - * Parameter string starts immediately after this object. - * Be careful to add padding after string to ensure correct - * alignment of subsequent dm_target_spec. - */ -}; - -/* - * Used to retrieve the target dependencies. - */ -struct dm_target_deps { - uint32_t count; /* Array size */ - uint32_t padding; /* unused */ - uint64_t dev[0]; /* out */ -}; - -/* - * Used to get a list of all dm devices. - */ -struct dm_name_list { - uint64_t dev; - uint32_t next; /* offset to the next record from - the _start_ of this */ - char name[0]; -}; - -/* - * Used to retrieve the target versions - */ -struct dm_target_versions { - uint32_t next; - uint32_t version[3]; - - char name[0]; -}; - -/* - * Used to pass message to a target - */ -struct dm_target_msg { - uint64_t sector; /* Device sector */ - - char message[0]; -}; - -/* - * If you change this make sure you make the corresponding change - * to dm-ioctl.c:lookup_ioctl() - */ -enum { - /* Top level cmds */ - DM_VERSION_CMD = 0, - DM_REMOVE_ALL_CMD, - DM_LIST_DEVICES_CMD, - - /* device level cmds */ - DM_DEV_CREATE_CMD, - DM_DEV_REMOVE_CMD, - DM_DEV_RENAME_CMD, - DM_DEV_SUSPEND_CMD, - DM_DEV_STATUS_CMD, - DM_DEV_WAIT_CMD, - - /* Table level cmds */ - DM_TABLE_LOAD_CMD, - DM_TABLE_CLEAR_CMD, - DM_TABLE_DEPS_CMD, - DM_TABLE_STATUS_CMD, - - /* Added later */ - DM_LIST_VERSIONS_CMD, - DM_TARGET_MSG_CMD, - DM_DEV_SET_GEOMETRY_CMD -}; - -#define DM_IOCTL 0xfd - -#define DM_VERSION _IOWR(DM_IOCTL, DM_VERSION_CMD, struct dm_ioctl) -#define DM_REMOVE_ALL _IOWR(DM_IOCTL, DM_REMOVE_ALL_CMD, struct dm_ioctl) -#define DM_LIST_DEVICES _IOWR(DM_IOCTL, DM_LIST_DEVICES_CMD, struct dm_ioctl) - -#define DM_DEV_CREATE _IOWR(DM_IOCTL, DM_DEV_CREATE_CMD, struct dm_ioctl) -#define DM_DEV_REMOVE _IOWR(DM_IOCTL, DM_DEV_REMOVE_CMD, struct dm_ioctl) -#define DM_DEV_RENAME _IOWR(DM_IOCTL, DM_DEV_RENAME_CMD, struct dm_ioctl) -#define DM_DEV_SUSPEND _IOWR(DM_IOCTL, DM_DEV_SUSPEND_CMD, struct dm_ioctl) -#define DM_DEV_STATUS _IOWR(DM_IOCTL, DM_DEV_STATUS_CMD, struct dm_ioctl) -#define DM_DEV_WAIT _IOWR(DM_IOCTL, DM_DEV_WAIT_CMD, struct dm_ioctl) - -#define DM_TABLE_LOAD _IOWR(DM_IOCTL, DM_TABLE_LOAD_CMD, struct dm_ioctl) -#define DM_TABLE_CLEAR _IOWR(DM_IOCTL, DM_TABLE_CLEAR_CMD, struct dm_ioctl) -#define DM_TABLE_DEPS _IOWR(DM_IOCTL, DM_TABLE_DEPS_CMD, struct dm_ioctl) -#define DM_TABLE_STATUS _IOWR(DM_IOCTL, DM_TABLE_STATUS_CMD, struct dm_ioctl) - -#define DM_LIST_VERSIONS _IOWR(DM_IOCTL, DM_LIST_VERSIONS_CMD, struct dm_ioctl) - -#define DM_TARGET_MSG _IOWR(DM_IOCTL, DM_TARGET_MSG_CMD, struct dm_ioctl) -#define DM_DEV_SET_GEOMETRY _IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD, struct dm_ioctl) - -#define DM_VERSION_MAJOR 4 -#define DM_VERSION_MINOR 13 -#define DM_VERSION_PATCHLEVEL 0 -#define DM_VERSION_EXTRA "-ioctl (2007-10-18)" - -/* Status bits */ -#define DM_READONLY_FLAG (1 << 0) /* In/Out */ -#define DM_SUSPEND_FLAG (1 << 1) /* In/Out */ -#define DM_PERSISTENT_DEV_FLAG (1 << 3) /* In */ - -/* - * Flag passed into ioctl STATUS command to get table information - * rather than current status. - */ -#define DM_STATUS_TABLE_FLAG (1 << 4) /* In */ - -/* - * Flags that indicate whether a table is present in either of - * the two table slots that a device has. - */ -#define DM_ACTIVE_PRESENT_FLAG (1 << 5) /* Out */ -#define DM_INACTIVE_PRESENT_FLAG (1 << 6) /* Out */ - -/* - * Indicates that the buffer passed in wasn't big enough for the - * results. - */ -#define DM_BUFFER_FULL_FLAG (1 << 8) /* Out */ - -/* - * This flag is now ignored. - */ -#define DM_SKIP_BDGET_FLAG (1 << 9) /* In */ - -/* - * Set this to avoid attempting to freeze any filesystem when suspending. - */ -#define DM_SKIP_LOCKFS_FLAG (1 << 10) /* In */ - -/* - * Set this to suspend without flushing queued ios. - */ -#define DM_NOFLUSH_FLAG (1 << 11) /* In */ - -#endif /* _LINUX_DM_IOCTL_H */ diff --git a/mountd/logwrapper.c b/mountd/logwrapper.c new file mode 100644 index 00000000..69606ab6 --- /dev/null +++ b/mountd/logwrapper.c @@ -0,0 +1,154 @@ +/* + * 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 <string.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <errno.h> +#include <fcntl.h> + +#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.h b/mountd/mountd.h index 9b624847..c4bc91df 100644 --- a/mountd/mountd.h +++ b/mountd/mountd.h @@ -177,6 +177,8 @@ const char *AsecMountPoint(void *Handle); void KillProcessesWithOpenFiles(const char* mountPoint, boolean sigkill, pid_t *excluded, int num_excluded); +// logwrapper.c +int logwrap(int argc, char* argv[]); // Server.c |
