diff options
-rw-r--r-- | utility/mount-encrypted.c | 34 | ||||
-rw-r--r-- | utility/mount-encrypted.h | 76 | ||||
-rw-r--r-- | utility/mount-helpers.c | 89 | ||||
-rw-r--r-- | utility/mount-helpers.h | 3 |
4 files changed, 155 insertions, 47 deletions
diff --git a/utility/mount-encrypted.c b/utility/mount-encrypted.c index 37c4d607..a62de854 100644 --- a/utility/mount-encrypted.c +++ b/utility/mount-encrypted.c @@ -829,6 +829,34 @@ failed: return 0; } +/* Clean up all bind mounts, mounts, attaches, etc. Only the final + * action informs the return value. This makes it so that failures + * can be cleaned up from, and continue the shutdown process on a + * second call. If the loopback cannot be found, claim success. + */ +static int shutdown(void) +{ + struct bind_mount *bind; + + for (bind = bind_mounts; bind->src; ++ bind) { + INFO("Unmounting %s.", bind->dst); + if (umount(bind->dst)) + PERROR("umount(%s)", bind->dst); + } + + /* TODO(keescook): this can actually succeed with binds mounted. */ + INFO("Unmounting %s.", kEncryptedMount); + if (umount(kEncryptedMount)) + PERROR("umount(%s)", kEncryptedMount); + + INFO("Removing %s.", kCryptDev); + if (!dm_teardown(kCryptDev)) + ERROR("dm_teardown(%s)", kCryptDev); + + INFO("Unlooping %s.", kEncryptedBlock); + return loop_detach_name(kEncryptedBlock) ? EXIT_SUCCESS : EXIT_FAILURE; +} + static void check_mount_states(void) { @@ -909,12 +937,14 @@ int main(int argc, char *argv[]) tpm_init(); if (argc > 1) { + if (!strcmp(argv[1], "umount")) + return shutdown(); if (!strcmp(argv[1], "device")) return device_details(); if (!strcmp(argv[1], "finalize")) return finalize_from_cmdline(argc > 2 ? argv[2] : NULL); - fprintf(stderr, "Usage: %s [device|finalize]\n", + fprintf(stderr, "Usage: %s [device|finalize|umount]\n", argv[0]); return 1; } @@ -929,7 +959,7 @@ int main(int argc, char *argv[]) okay = setup_encrypted(); } - INFO("Done."); + INFO_DONE("Done."); /* Continue boot. */ return !okay; diff --git a/utility/mount-encrypted.h b/utility/mount-encrypted.h index d84de4f9..e3a85d95 100644 --- a/utility/mount-encrypted.h +++ b/utility/mount-encrypted.h @@ -7,7 +7,8 @@ #ifndef _MOUNT_ENCRYPTED_H_ #define _MOUNT_ENCRYPTED_H_ -#define DEBUG_ENABLED 0 +#define DEBUG_ENABLED 1 +#define DEBUG_TIME_DELTA 1 #include <openssl/err.h> #include <openssl/sha.h> @@ -15,8 +16,8 @@ #define DIGEST_LENGTH SHA256_DIGEST_LENGTH #define _ERROR(f, a...) do { \ - fprintf(stderr, "ERROR %s (%s, %d): ", \ - __func__, __FILE__, __LINE__); \ + fprintf(stderr, "ERROR[pid:%d] %s (%s, %d): ", \ + getpid(), __func__, __FILE__, __LINE__); \ fprintf(stderr, f, ## a); \ } while (0) #define ERROR(f, a...) do { \ @@ -39,48 +40,87 @@ #if DEBUG_ENABLED static struct timeval tick; -# define TICK_INIT() gettimeofday(&tick, NULL) +static struct timeval tick_start; +# define TICK_INIT() do { \ + gettimeofday(&tick, NULL); \ + tick_start = tick; \ +} while (0) # ifdef DEBUG_TIME_DELTA +/* This timeval helper copied from glibc manual. */ +static inline int timeval_subtract(struct timeval *result, + struct timeval *x, + struct timeval *y) +{ + /* Perform the carry for the later subtraction by updating y. */ + if (x->tv_usec < y->tv_usec) { + int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1; + y->tv_usec -= 1000000 * nsec; + y->tv_sec += nsec; + } + if (x->tv_usec - y->tv_usec > 1000000) { + int nsec = (x->tv_usec - y->tv_usec) / 1000000; + y->tv_usec += 1000000 * nsec; + y->tv_sec -= nsec; + } + + /* Compute the time remaining to wait. + * tv_usec is certainly positive. + */ + result->tv_sec = x->tv_sec - y->tv_sec; + result->tv_usec = x->tv_usec - y->tv_usec; + + /* Return 1 if result is negative. */ + return x->tv_sec < y->tv_sec; +} # define TICK_REPORT() do { \ struct timeval now, diff; \ gettimeofday(&now, NULL); \ - diff.tv_sec = now.tv_sec - tick.tv_sec; \ - if (tick.tv_usec > now.tv_usec) { \ - diff.tv_sec -= 1; \ - diff.tv_usec = 1000000 - tick.tv_usec + now.tv_usec; \ - } else { \ - diff.tv_usec = now.tv_usec - tick.tv_usec; \ - } \ + timeval_subtract(&diff, &now, &tick); \ + printf("\tTook: [pid:%d, %2lu.%06lus]\n", getpid(), \ + (unsigned long)diff.tv_sec, (unsigned long)diff.tv_usec); \ tick = now; \ - printf("\tTook: [%2d.%06d]\n", (int)diff.tv_sec, (int)diff.tv_usec); \ } while (0) # else # define TICK_REPORT() do { \ gettimeofday(&tick, NULL); \ - printf("[%d:%2d.%06d] ", getpid(), (int)tick.tv_sec, (int)tick.tv_usec); \ + printf("[%2d.%06d] ", (int)tick.tv_sec, (int)tick.tv_usec); \ } while (0) # endif +# define TICK_DONE() do { \ + struct timeval tick_done; \ + TICK_REPORT(); \ + timeval_subtract(&tick_done, &tick, &tick_start); \ + printf("Process Lifetime: [pid:%d, %2d.%06ds]\n", getpid(), \ + (int)tick_done.tv_sec, (int)tick_done.tv_usec); \ +} while (0) #else # define TICK_INIT() do { } while (0) # define TICK_REPORT() do { } while (0) +# define TICK_DONE() do { } while (0) #endif -#define INFO(f, a...) do { \ - TICK_REPORT(); \ +#define _INFO(f, a...) do { \ + printf("[pid:%d] ", getpid()); \ printf(f, ## a); \ printf("\n"); \ fflush(stdout); \ } while (0) +#define INFO(f, a...) do { \ + TICK_REPORT(); \ + _INFO(f, ## a); \ +} while (0) #define INFO_INIT(f, a...) do { \ TICK_INIT(); \ INFO(f, ## a); \ } while (0) +#define INFO_DONE(f, a...) do { \ + TICK_DONE(); \ + INFO(f, ## a); \ +} while (0) #if DEBUG_ENABLED # define DEBUG(f, a...) do { \ TICK_REPORT(); \ - printf(f, ## a); \ - printf("\n"); \ - fflush(stdout); \ + _INFO(f, ## a); \ } while (0) #else # define DEBUG(f, a...) do { } while (0) diff --git a/utility/mount-helpers.c b/utility/mount-helpers.c index bd7a5218..05214973 100644 --- a/utility/mount-helpers.c +++ b/utility/mount-helpers.c @@ -155,23 +155,29 @@ static int is_loop_device(int fd) major(info.st_rdev) == kLoopMajor); } -static int loop_is_attached(int fd) +static int loop_is_attached(int fd, struct loop_info64 *info) { - struct loop_info info; + struct loop_info64 local_info; - errno = 0; - if (ioctl(fd, LOOP_GET_STATUS, &info) && errno == ENXIO) - return 0; - - return 1; + return ioctl(fd, LOOP_GET_STATUS64, info ? info : &local_info) == 0; } -static int loop_allocate(gchar **loopback) +/* Returns either the matching loopback name, or next available, if NULL. */ +static int loop_locate(gchar **loopback, const char *name) { - int i, fd; + int i, fd, namelen = 0; + + if (name) { + namelen = strlen(name); + if (namelen >= LO_NAME_SIZE) + return -1; + } *loopback = NULL; for (i = 0; i < kLoopMax; ++i) { + struct loop_info64 info; + int attached; + g_free(*loopback); *loopback = g_strdup_printf(kLoopTemplate, i); if (!*loopback) { @@ -184,13 +190,24 @@ static int loop_allocate(gchar **loopback) PERROR("open(%s)", *loopback); goto failed; } - if (is_loop_device(fd) && !loop_is_attached(fd)) { + if (!is_loop_device(fd)) { close(fd); + continue; + } + + memset(&info, 0, sizeof(info)); + attached = loop_is_attached(fd, &info); + close(fd); + + if ((attached && name && + strncmp((char *)info.lo_file_name, name, namelen) == 0) || + (!attached && !name)) { + /* Reopen for working on it. */ fd = open(*loopback, O_RDWR | O_NOFOLLOW); - if (is_loop_device(fd) && !loop_is_attached(fd)) + if (is_loop_device(fd) && + loop_is_attached(fd, NULL) == attached) return fd; } - close(fd); } ERROR("Ran out of loopback devices"); @@ -200,37 +217,55 @@ failed: return -1; } +static int loop_detach_fd(int fd) +{ + if (ioctl(fd, LOOP_CLR_FD, 0)) { + PERROR("LOOP_CLR_FD"); + return 0; + } + return 1; +} + int loop_detach(const gchar *loopback) { - int fd; + int fd, rc = 1; fd = open(loopback, O_RDONLY | O_NOFOLLOW); if (fd < 0) { PERROR("open(%s)", loopback); return 0; } - if (!is_loop_device(fd) || !loop_is_attached(fd)) - goto failed; - if (ioctl(fd, LOOP_CLR_FD, 0)) { - PERROR("LOOP_CLR_FD"); - goto failed; - } + if (!is_loop_device(fd) || !loop_is_attached(fd, NULL) || + !loop_detach_fd(fd)) + rc = 0; close (fd); - return 1; + return rc; +} -failed: - close(fd); - return 0; +int loop_detach_name(const char *name) +{ + gchar *loopback = NULL; + int loopfd, rc; + + loopfd = loop_locate(&loopback, name); + if (loopfd < 0) + return 0; + rc = loop_detach_fd(loopfd); + + close(loopfd); + g_free(loopback); + return rc; } +/* Closes fd, returns name of loopback device pathname. */ gchar *loop_attach(int fd, const char *name) { gchar *loopback = NULL; int loopfd; struct loop_info64 info; - loopfd = loop_allocate(&loopback); + loopfd = loop_locate(&loopback, NULL); if (loopfd < 0) return NULL; if (ioctl(loopfd, LOOP_SET_FD, fd) < 0) { @@ -295,7 +330,7 @@ int dm_setup(size_t sectors, const gchar *encryption_key, const char *name, return 1; } -void dm_teardown(const gchar *device) +int dm_teardown(const gchar *device) { const char *argv[] = { "/sbin/dmsetup", @@ -304,7 +339,9 @@ void dm_teardown(const gchar *device) NULL }; /* TODO(keescook): replace with call to libdevmapper. */ - runcmd(argv, NULL); + if (runcmd(argv, NULL) != 0) + return 0; + return 1; } char *dm_get_key(const gchar *device) diff --git a/utility/mount-helpers.h b/utility/mount-helpers.h index 66fb1026..19f6242f 100644 --- a/utility/mount-helpers.h +++ b/utility/mount-helpers.h @@ -18,11 +18,12 @@ uint8_t *hexify_string(char *string, uint8_t *binary, size_t length); /* Loopback device attach/detach helpers. */ gchar *loop_attach(int fd, const char *name); int loop_detach(const gchar *loopback); +int loop_detach_name(const char *name); /* Encrypted device mapper setup/teardown. */ int dm_setup(size_t sectors, const gchar *encryption_key, const char *name, const gchar *device, const char *path); -void dm_teardown(const gchar *device); +int dm_teardown(const gchar *device); char *dm_get_key(const gchar *device); /* Sparse file creation. */ |