fs_mgr: trigger dm-verity error handling for invalid signatures

Currently, the device doesn't mount verified partitions if the
verity table signature is invalid, which usually means it fails to
boot. This changes instead set up dm-verity with an invalid root
hash and triggers device-specific error handling to recover from
the corruption.

Change-Id: I6d693306fa0e7459c5500b028e433df61ecea6fb
This commit is contained in:
Sami Tolvanen 2015-09-21 15:12:29 +01:00
parent 1814816b1b
commit 47caa5c386

View file

@ -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];
@ -979,6 +1009,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) {
@ -998,13 +1029,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
@ -1013,6 +1037,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