diff --git a/fs_mgr/fs_mgr_verity.c b/fs_mgr/fs_mgr_verity.c index 60f53982f..a9e3358b2 100644 --- a/fs_mgr/fs_mgr_verity.c +++ b/fs_mgr/fs_mgr_verity.c @@ -47,6 +47,8 @@ #define VERITY_METADATA_SIZE 32768 #define VERITY_TABLE_RSA_KEY "/verity_key" +#define VERITY_TABLE_HASH_IDX 8 +#define VERITY_TABLE_SALT_IDX 9 #define METADATA_MAGIC 0x01564c54 #define METADATA_TAG_MAX_LENGTH 63 @@ -141,6 +143,33 @@ out: return retval; } +static int invalidate_table(char *table, int table_length) +{ + int n = 0; + int idx = 0; + int cleared = 0; + + while (n < table_length) { + if (table[n++] == ' ') { + ++idx; + } + + if (idx != VERITY_TABLE_HASH_IDX && idx != VERITY_TABLE_SALT_IDX) { + continue; + } + + while (n < table_length && table[n] != ' ') { + table[n++] = '0'; + } + + if (++cleared == 2) { + return 0; + } + } + + return -1; +} + static int squashfs_get_target_device_size(char *blk_device, uint64_t *device_size) { struct squashfs_info sq_info; @@ -957,6 +986,7 @@ int fs_mgr_setup_verity(struct fstab_rec *fstab) { char *verity_blk_name = 0; char *verity_table = 0; char *verity_table_signature = 0; + int verity_table_length = 0; uint64_t device_size = 0; _Alignas(struct dm_ioctl) char buffer[DM_BUF_SIZE]; @@ -983,6 +1013,7 @@ int fs_mgr_setup_verity(struct fstab_rec *fstab) { } retval = FS_MGR_SETUP_VERITY_FAIL; + verity_table_length = strlen(verity_table); // get the device mapper fd if ((fd = open("/dev/device-mapper", O_RDWR)) < 0) { @@ -1002,13 +1033,6 @@ int fs_mgr_setup_verity(struct fstab_rec *fstab) { goto out; } - // verify the signature on the table - if (verify_table(verity_table_signature, - verity_table, - strlen(verity_table)) < 0) { - goto out; - } - if (load_verity_state(fstab, &mode) < 0) { /* if accessing or updating the state failed, switch to the default * safe mode. This makes sure the device won't end up in an endless @@ -1017,6 +1041,22 @@ int fs_mgr_setup_verity(struct fstab_rec *fstab) { mode = VERITY_MODE_EIO; } + // verify the signature on the table + if (verify_table(verity_table_signature, + verity_table, + verity_table_length) < 0) { + if (mode == VERITY_MODE_LOGGING) { + // the user has been warned, allow mounting without dm-verity + retval = FS_MGR_SETUP_VERITY_SUCCESS; + goto out; + } + + // invalidate root hash and salt to trigger device-specific recovery + if (invalidate_table(verity_table, verity_table_length) < 0) { + goto out; + } + } + INFO("Enabling dm-verity for %s (mode %d)\n", mount_point, mode); // load the verity mapping table