summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKees Cook <keescook@chromium.org>2012-04-03 11:57:04 -0700
committerGerrit <chrome-bot@google.com>2012-04-05 13:27:17 -0700
commitf9e82e9695d3f208b549cc0208baf24985bbb488 (patch)
treeb4f751815a5190dbd1a88f5c1f52626ab760e62a
parent498977af89510bf5e44af0a0b8171d23fb770f4b (diff)
downloadvboot-f9e82e9695d3f208b549cc0208baf24985bbb488.tar.gz
mount-encrypted: close TPM when spawning resizer
When the filesystem resizing process starts, it has the TPM open, which means it can collide with tcsd after the main process exits. Additionally, improve the debugging around TPM usage for better timing analysis. BUG=None TEST=lumpy build & manual testing Change-Id: I7028131015fb972c99e8b3d035f58346f08fbd06 Signed-off-by: Kees Cook <keescook@chromium.org> Reviewed-on: https://gerrit.chromium.org/gerrit/19535 Reviewed-by: Elly Jones <ellyjones@chromium.org>
-rw-r--r--firmware/include/tlcl.h4
-rw-r--r--firmware/lib/tpm_lite/tlcl.c4
-rw-r--r--utility/mount-encrypted.c128
-rw-r--r--utility/mount-encrypted.h1
-rw-r--r--utility/mount-helpers.c29
-rw-r--r--utility/mount-helpers.h2
6 files changed, 116 insertions, 52 deletions
diff --git a/firmware/include/tlcl.h b/firmware/include/tlcl.h
index c8632e43..b69d8fbc 100644
--- a/firmware/include/tlcl.h
+++ b/firmware/include/tlcl.h
@@ -21,6 +21,10 @@
*/
uint32_t TlclLibInit(void);
+/* Call this on shutdown. Returns 0 if success, nonzero if error.
+ */
+uint32_t TlclLibClose(void);
+
/* Logs to stdout. Arguments like printf.
*/
void TlclLog(char* format, ...);
diff --git a/firmware/lib/tpm_lite/tlcl.c b/firmware/lib/tpm_lite/tlcl.c
index 9e9ece84..df63399d 100644
--- a/firmware/lib/tpm_lite/tlcl.c
+++ b/firmware/lib/tpm_lite/tlcl.c
@@ -136,6 +136,10 @@ uint32_t TlclLibInit(void) {
return VbExTpmInit();
}
+uint32_t TlclLibClose(void) {
+ return VbExTpmClose();
+}
+
uint32_t TlclStartup(void) {
VBDEBUG(("TPM: Startup\n"));
return Send(tpm_startup_cmd.buffer);
diff --git a/utility/mount-encrypted.c b/utility/mount-encrypted.c
index 2a1a49d5..6b7ee5e5 100644
--- a/utility/mount-encrypted.c
+++ b/utility/mount-encrypted.c
@@ -89,6 +89,42 @@ static struct bind_mount {
int has_tpm = 0;
+void tpm_init(void)
+{
+ int tpm;
+
+ DEBUG("Opening TPM");
+ tpm = open(kTpmDev, O_RDWR);
+ if (tpm >= 0) {
+ has_tpm = 1;
+ close(tpm);
+ }
+ else {
+ /* TlclLibInit does not fail, it exits, so instead,
+ * have it open /dev/null if the TPM is not available.
+ */
+ setenv("TPM_DEVICE_PATH", kNullDev, 1);
+ }
+ TlclLibInit();
+ DEBUG("TPM Ready");
+}
+
+uint32_t tpm_flags(TPM_PERMANENT_FLAGS *pflags)
+{
+ uint32_t result;
+
+ DEBUG("Reading TPM Permanent Flags");
+ result = TlclGetPermanentFlags(pflags);
+ DEBUG("TPM Permanent Flags returned: %s", result ? "FAIL" : "ok");
+
+ return result;
+}
+
+void tpm_close(void)
+{
+ TlclLibClose();
+}
+
static void sha256(char *string, uint8_t *digest)
{
SHA256((unsigned char *)string, strlen(string), digest);
@@ -129,6 +165,17 @@ static int get_key_from_cmdline(uint8_t *digest)
return result;
}
+static int get_system_property(const char *prop, char *buf, size_t length)
+{
+ const char *rc;
+
+ DEBUG("Fetching System Property '%s'", prop);
+ rc = VbGetSystemPropertyString(prop, buf, length);
+ DEBUG("Got System Property 'mainfw_type': %s", rc ? buf : "FAIL");
+
+ return rc != NULL;
+}
+
static int has_chromefw(void)
{
static int state = -1;
@@ -138,7 +185,7 @@ static int has_chromefw(void)
if (state != -1)
return state;
- if (!VbGetSystemPropertyString("mainfw_type", fw, sizeof(fw)))
+ if (!get_system_property("mainfw_type", fw, sizeof(fw)))
state = 0;
else
state = strcmp(fw, "nonchrome") != 0;
@@ -154,7 +201,7 @@ static int is_cr48(void)
if (state != -1)
return state;
- if (!VbGetSystemPropertyString("hwid", hwid, sizeof(hwid)))
+ if (!get_system_property("hwid", hwid, sizeof(hwid)))
state = 0;
else
state = strstr(hwid, "MARIO") != NULL;
@@ -164,12 +211,18 @@ static int is_cr48(void)
static int
_read_nvram(uint8_t *buffer, size_t len, uint32_t index, uint32_t size)
{
+ int rc;
+
if (size > len) {
ERROR("NVRAM size (0x%x > 0x%zx) is too big", size, len);
return 0;
}
- return TlclRead(index, buffer, size);
+ DEBUG("Reading NVRAM area 0x%x (size %u)", index, size);
+ rc = TlclRead(index, buffer, size);
+ DEBUG("NVRAM read returned: %s", rc ? "FAIL" : "ok");
+
+ return rc;
}
/*
@@ -180,7 +233,6 @@ _read_nvram(uint8_t *buffer, size_t len, uint32_t index, uint32_t size)
* - legacy NVRAM area (migration needed)
* - modern NVRAM area (\o/)
*/
-// TODO(keescook): recovery code needs to wipe NVRAM area to new size?
static int get_nvram_key(uint8_t *digest, int *old_lockbox)
{
TPM_PERMANENT_FLAGS pflags;
@@ -189,7 +241,14 @@ static int get_nvram_key(uint8_t *digest, int *old_lockbox)
uint8_t *rand_bytes;
uint32_t rand_size;
- /* Start by expecting modern NVRAM area. */
+ /* Reading the NVRAM takes 40ms. Instead of querying the NVRAM area
+ * for its size (which takes time), just read the expected size. If
+ * it fails, then fall back to the older size. This means cleared
+ * devices take 80ms (2 failed reads), legacy devices take 80ms
+ * (1 failed read, 1 good read), and populated devices take 40ms,
+ * which is the minimum possible time (instead of 40ms + time to
+ * query NVRAM size).
+ */
*old_lockbox = 0;
size = kLockboxSizeV2;
result = _read_nvram(value, sizeof(value), kLockboxIndex, size);
@@ -211,7 +270,11 @@ static int get_nvram_key(uint8_t *digest, int *old_lockbox)
debug_dump_hex("nvram", value, size);
/* Ignore defined but unowned NVRAM area. */
- result = TlclGetPermanentFlags(&pflags);
+ /* TODO(keescook): remove this check (it adds 40ms) once the
+ * NVRAM area is bound to owner so that it will be wiped out
+ * across device mode changes.
+ */
+ result = tpm_flags(&pflags);
if (result) {
INFO("Could not read TPM Permanent Flags.");
return 0;
@@ -481,6 +544,35 @@ static int finalize_from_cmdline(char *key)
return EXIT_SUCCESS;
}
+void spawn_resizer(const char *device, size_t blocks, size_t blocks_max)
+{
+ pid_t pid;
+
+ fflush(NULL);
+ pid = fork();
+ if (pid < 0) {
+ PERROR("fork");
+ return;
+ }
+ if (pid != 0) {
+ INFO("Started filesystem resizing process %d.", pid);
+ return;
+ }
+
+ /* Child */
+ tpm_close();
+
+ if (daemon(0, 1)) {
+ PERROR("daemon");
+ goto out;
+ }
+
+ filesystem_resize(device, blocks, blocks_max);
+
+out:
+ exit(0);
+}
+
static int setup_encrypted(void)
{
int has_system_key;
@@ -622,7 +714,7 @@ static int setup_encrypted(void)
/* Always spawn filesystem resizer, in case growth was interrupted. */
/* TODO(keescook): if already full size, don't resize. */
- filesystem_resizer(kCryptDev, blocks_min, blocks_max);
+ spawn_resizer(kCryptDev, blocks_min, blocks_max);
/* If the legacy lockbox NVRAM area exists, we've rebuilt the
* filesystem, and there are old bind sources on disk, attempt
@@ -739,7 +831,7 @@ int device_details(void)
printf("TPM: %s\n", has_tpm ? "yes" : "no");
if (has_tpm) {
- printf("TPM Owned: %s\n", TlclGetPermanentFlags(&pflags) ?
+ printf("TPM Owned: %s\n", tpm_flags(&pflags) ?
"fail" : (pflags.ownership ? "yes" : "no"));
}
printf("ChromeOS: %s\n", has_chromefw() ? "yes" : "no");
@@ -762,30 +854,12 @@ int device_details(void)
return EXIT_SUCCESS;
}
-void init_tpm(void)
-{
- int tpm;
-
- tpm = open(kTpmDev, O_RDWR);
- if (tpm >= 0) {
- has_tpm = 1;
- close(tpm);
- }
- else {
- /* TlclLibInit does not fail, it exits, so instead,
- * have it open /dev/null if the TPM is not available.
- */
- setenv("TPM_DEVICE_PATH", kNullDev, 1);
- }
- TlclLibInit();
-}
-
int main(int argc, char *argv[])
{
int okay;
INFO_INIT("Starting.");
- init_tpm();
+ tpm_init();
if (argc > 1) {
if (!strcmp(argv[1], "device"))
diff --git a/utility/mount-encrypted.h b/utility/mount-encrypted.h
index df5b1d2d..856949df 100644
--- a/utility/mount-encrypted.h
+++ b/utility/mount-encrypted.h
@@ -74,6 +74,7 @@ static struct timeval tick;
} while (0)
#if DEBUG_ENABLED
# define DEBUG(f, a...) do { \
+ TICK_REPORT(); \
printf(f, ## a); \
printf("\n"); \
} while (0)
diff --git a/utility/mount-helpers.c b/utility/mount-helpers.c
index b6f31c30..462d0541 100644
--- a/utility/mount-helpers.c
+++ b/utility/mount-helpers.c
@@ -425,29 +425,11 @@ out:
}
/* Spawns a filesystem resizing process. */
-void filesystem_resizer(const char *device, size_t blocks, size_t blocks_max)
+int filesystem_resize(const char *device, size_t blocks, size_t blocks_max)
{
- pid_t pid;
-
/* Ignore resizing if we know the filesystem was built to max size. */
if (blocks >= blocks_max)
- return;
-
- fflush(NULL);
- pid = fork();
- if (pid < 0) {
- PERROR("fork");
- return;
- }
- if (pid != 0) {
- INFO("Started filesystem resizing process %d.", pid);
- return;
- }
-
- if (setsid() < 0) {
- PERROR("setsid");
- goto out;
- }
+ return 1;
/* TODO(keescook): Read superblock to find out the current size of
* the filesystem (since statvfs does not report the correct value).
@@ -470,7 +452,7 @@ void filesystem_resizer(const char *device, size_t blocks, size_t blocks_max)
blocks_str = g_strdup_printf("%zu", blocks);
if (!blocks_str) {
PERROR("g_strdup_printf");
- goto out;
+ return 0;
}
const gchar *resize[] = {
@@ -484,14 +466,13 @@ void filesystem_resizer(const char *device, size_t blocks, size_t blocks_max)
INFO("Resizing filesystem on %s to %zu.", device, blocks);
if (runcmd(resize, NULL)) {
ERROR("resize2fs failed");
- goto out;
+ return 0;
}
g_free(blocks_str);
} while (blocks < blocks_max);
INFO("Resizing finished.");
-out:
- exit(0);
+ return 1;
}
char *keyfile_read(const char *keyfile, uint8_t *system_key)
diff --git a/utility/mount-helpers.h b/utility/mount-helpers.h
index bc50fe54..66fb1026 100644
--- a/utility/mount-helpers.h
+++ b/utility/mount-helpers.h
@@ -31,7 +31,7 @@ int sparse_create(const char *path, size_t size);
/* Filesystem creation. */
int filesystem_build(const char *device, size_t block_bytes, size_t blocks_min,
size_t blocks_max);
-void filesystem_resizer(const char *device, size_t blocks, size_t blocks_max);
+int filesystem_resize(const char *device, size_t blocks, size_t blocks_max);
/* Encrypted keyfile handling. */
char *keyfile_read(const char *keyfile, uint8_t *system_key);