From 6bfed20c77184d00d948130d88d86db7ddd8a3f1 Mon Sep 17 00:00:00 2001 From: Paul Lawrence Date: Mon, 28 Jul 2014 12:47:22 -0700 Subject: [PATCH] When encryption fails, reboot into recovery Set flag on starting encryption to say it failed, and only clear when we get into a recoverable state (partially or fully encrypted.) Go to recovery on seeing this flag on boot Bug: 16552363 Change-Id: I7e452b653edf3a087ecfaba8f81f41765a1c8daf --- cryptfs.c | 38 +++++++++++++++++++++++++++----------- cryptfs.h | 7 +++++-- 2 files changed, 32 insertions(+), 13 deletions(-) diff --git a/cryptfs.c b/cryptfs.c index d11c133..252be0a 100644 --- a/cryptfs.c +++ b/cryptfs.c @@ -1524,7 +1524,8 @@ static int do_crypto_complete(char *mount_point UNUSED) } } - if (crypt_ftr.flags & CRYPT_ENCRYPTION_IN_PROGRESS) { + if (crypt_ftr.flags + & (CRYPT_ENCRYPTION_IN_PROGRESS | CRYPT_INCONSISTENT_STATE)) { SLOGE("Encryption process didn't finish successfully\n"); return -2; /* -2 is the clue to the UI that there is no usable data on the disk, * and give the user an option to wipe the disk */ @@ -2412,6 +2413,15 @@ int cryptfs_enable_internal(char *howarg, int crypt_type, char *passwd, && (crypt_ftr.flags & CRYPT_ENCRYPTION_IN_PROGRESS)) { previously_encrypted_upto = crypt_ftr.encrypted_upto; crypt_ftr.encrypted_upto = 0; + crypt_ftr.flags &= ~CRYPT_ENCRYPTION_IN_PROGRESS; + + /* At this point, we are in an inconsistent state. Until we successfully + complete encryption, a reboot will leave us broken. So mark the + encryption failed in case that happens. + On successfully completing encryption, remove this flag */ + crypt_ftr.flags |= CRYPT_INCONSISTENT_STATE; + + put_crypt_ftr_and_key(&crypt_ftr); } property_get("ro.crypto.state", encrypted_state, ""); @@ -2561,7 +2571,11 @@ int cryptfs_enable_internal(char *howarg, int crypt_type, char *passwd, } else { crypt_ftr.fs_size = nr_sec; } - crypt_ftr.flags |= CRYPT_ENCRYPTION_IN_PROGRESS; + /* At this point, we are in an inconsistent state. Until we successfully + complete encryption, a reboot will leave us broken. So mark the + encryption failed in case that happens. + On successfully completing encryption, remove this flag */ + crypt_ftr.flags |= CRYPT_INCONSISTENT_STATE; crypt_ftr.crypt_type = crypt_type; strcpy((char *)crypt_ftr.crypto_type_name, "aes-cbc-essiv:sha256"); @@ -2629,18 +2643,15 @@ int cryptfs_enable_internal(char *howarg, int crypt_type, char *passwd, if (! rc) { /* Success */ + crypt_ftr.flags &= ~CRYPT_INCONSISTENT_STATE; - /* Clear the encryption in progress flag in the footer */ - if (crypt_ftr.encrypted_upto == crypt_ftr.fs_size) { - crypt_ftr.flags &= ~CRYPT_ENCRYPTION_IN_PROGRESS; - } else { + if (crypt_ftr.encrypted_upto != crypt_ftr.fs_size) { SLOGD("Encrypted up to sector %lld - will continue after reboot", crypt_ftr.encrypted_upto); + crypt_ftr.flags |= CRYPT_ENCRYPTION_IN_PROGRESS; } - if (crypt_ftr.encrypted_upto) { - put_crypt_ftr_and_key(&crypt_ftr); - } + put_crypt_ftr_and_key(&crypt_ftr); sleep(2); /* Give the UI a chance to show 100% progress */ /* Partially encrypted - ensure writes are flushed to ssd */ @@ -2924,9 +2935,10 @@ int cryptfs_mount_default_encrypted(void) } } - /** @TODO make sure we factory wipe in this situation - * In general if we got here there is no recovery + /** Corrupt. Allow us to boot into framework, which will detect bad + crypto when it calls do_crypto_complete, then do a factory reset */ + property_set("vold.decrypt", "trigger_restart_min_framework"); return 0; } @@ -2941,6 +2953,10 @@ int cryptfs_get_password_type(void) return -1; } + if (crypt_ftr.flags & CRYPT_INCONSISTENT_STATE) { + return -1; + } + return crypt_ftr.crypt_type; } diff --git a/cryptfs.h b/cryptfs.h index ea72c9e..e765847 100644 --- a/cryptfs.h +++ b/cryptfs.h @@ -44,8 +44,11 @@ /* definitions of flags in the structure below */ #define CRYPT_MNT_KEY_UNENCRYPTED 0x1 /* The key for the partition is not encrypted. */ -#define CRYPT_ENCRYPTION_IN_PROGRESS 0x2 /* Set when starting encryption, - * clear when done before rebooting */ +#define CRYPT_ENCRYPTION_IN_PROGRESS 0x2 /* Encryption partially completed, + encrypted_upto valid*/ +#define CRYPT_INCONSISTENT_STATE 0x4 /* Set when starting encryption, clear when + exit cleanly, either through success or + correctly marked partial encryption */ /* Allowed values for type in the structure below */ #define CRYPT_TYPE_PASSWORD 0 /* master_key is encrypted with a password