diff options
Diffstat (limited to 'fs_mgr/fs_mgr_verity.c')
-rw-r--r-- | fs_mgr/fs_mgr_verity.c | 126 |
1 files changed, 78 insertions, 48 deletions
diff --git a/fs_mgr/fs_mgr_verity.c b/fs_mgr/fs_mgr_verity.c index 01f7844..51555a1 100644 --- a/fs_mgr/fs_mgr_verity.c +++ b/fs_mgr/fs_mgr_verity.c @@ -43,7 +43,6 @@ #include "fs_mgr_priv_verity.h" #define VERITY_METADATA_SIZE 32768 -#define VERITY_METADATA_MAGIC_NUMBER 0xb001b001 #define VERITY_TABLE_RSA_KEY "/verity_key" extern struct fs_info info; @@ -87,11 +86,11 @@ static RSAPublicKey *load_key(char *path) static int verify_table(char *signature, char *table, int table_length) { RSAPublicKey *key; - uint8_t hash_buf[SHA_DIGEST_SIZE]; + uint8_t hash_buf[SHA256_DIGEST_SIZE]; int retval = -1; // Hash the table - SHA_hash((uint8_t*)table, table_length, hash_buf); + SHA256_hash((uint8_t*)table, table_length, hash_buf); // Now get the public key from the keyfile key = load_key(VERITY_TABLE_RSA_KEY); @@ -105,7 +104,7 @@ static int verify_table(char *signature, char *table, int table_length) (uint8_t*) signature, RSANUMBYTES, (uint8_t*) hash_buf, - SHA_DIGEST_SIZE)) { + SHA256_DIGEST_SIZE)) { ERROR("Couldn't verify table."); goto out; } @@ -125,28 +124,28 @@ static int get_target_device_size(char *blk_device, uint64_t *device_size) info.len = 0; /* Only len is set to 0 to ask the device for real size. */ - data_device = open(blk_device, O_RDONLY); - if (data_device < 0) { + data_device = TEMP_FAILURE_RETRY(open(blk_device, O_RDONLY | O_CLOEXEC)); + if (data_device == -1) { ERROR("Error opening block device (%s)", strerror(errno)); return -1; } - if (lseek64(data_device, 1024, SEEK_SET) < 0) { + if (TEMP_FAILURE_RETRY(lseek64(data_device, 1024, SEEK_SET)) < 0) { ERROR("Error seeking to superblock"); - close(data_device); + TEMP_FAILURE_RETRY(close(data_device)); return -1; } - if (read(data_device, &sb, sizeof(sb)) != sizeof(sb)) { + if (TEMP_FAILURE_RETRY(read(data_device, &sb, sizeof(sb))) != sizeof(sb)) { ERROR("Error reading superblock"); - close(data_device); + TEMP_FAILURE_RETRY(close(data_device)); return -1; } ext4_parse_sb(&sb, &info); *device_size = info.len; - close(data_device); + TEMP_FAILURE_RETRY(close(data_device)); return 0; } @@ -156,11 +155,13 @@ static int read_verity_metadata(char *block_device, char **signature, char **tab unsigned table_length; uint64_t device_length; int protocol_version; - FILE *device; - int retval = -1; + int device; + int retval = FS_MGR_SETUP_VERITY_FAIL; + *signature = 0; + *table = 0; - device = fopen(block_device, "r"); - if (!device) { + device = TEMP_FAILURE_RETRY(open(block_device, O_RDONLY | O_CLOEXEC)); + if (device == -1) { ERROR("Could not open block device %s (%s).\n", block_device, strerror(errno)); goto out; } @@ -170,23 +171,35 @@ static int read_verity_metadata(char *block_device, char **signature, char **tab ERROR("Could not get target device size.\n"); goto out; } - if (fseek(device, device_length, SEEK_SET) < 0) { + if (TEMP_FAILURE_RETRY(lseek64(device, device_length, SEEK_SET)) < 0) { ERROR("Could not seek to start of verity metadata block.\n"); goto out; } // check the magic number - if (!fread(&magic_number, sizeof(int), 1, device)) { + if (TEMP_FAILURE_RETRY(read(device, &magic_number, sizeof(magic_number))) != + sizeof(magic_number)) { ERROR("Couldn't read magic number!\n"); goto out; } + +#ifdef ALLOW_ADBD_DISABLE_VERITY + if (magic_number == VERITY_METADATA_MAGIC_DISABLE) { + retval = FS_MGR_SETUP_VERITY_DISABLED; + INFO("Attempt to cleanly disable verity - only works in USERDEBUG"); + goto out; + } +#endif + if (magic_number != VERITY_METADATA_MAGIC_NUMBER) { - ERROR("Couldn't find verity metadata at offset %"PRIu64"!\n", device_length); + ERROR("Couldn't find verity metadata at offset %"PRIu64"!\n", + device_length); goto out; } // check the protocol version - if (!fread(&protocol_version, sizeof(int), 1, device)) { + if (TEMP_FAILURE_RETRY(read(device, &protocol_version, + sizeof(protocol_version))) != sizeof(protocol_version)) { ERROR("Couldn't read verity metadata protocol version!\n"); goto out; } @@ -196,43 +209,49 @@ static int read_verity_metadata(char *block_device, char **signature, char **tab } // get the signature - *signature = (char*) malloc(RSANUMBYTES * sizeof(char)); + *signature = (char*) malloc(RSANUMBYTES); if (!*signature) { ERROR("Couldn't allocate memory for signature!\n"); goto out; } - if (!fread(*signature, RSANUMBYTES, 1, device)) { + if (TEMP_FAILURE_RETRY(read(device, *signature, RSANUMBYTES)) != RSANUMBYTES) { ERROR("Couldn't read signature from verity metadata!\n"); - free(*signature); goto out; } // get the size of the table - if (!fread(&table_length, sizeof(int), 1, device)) { + if (TEMP_FAILURE_RETRY(read(device, &table_length, sizeof(table_length))) != + sizeof(table_length)) { ERROR("Couldn't get the size of the verity table from metadata!\n"); - free(*signature); goto out; } // get the table + null terminator - table_length += 1; - *table = malloc(table_length); - if(!*table) { + *table = malloc(table_length + 1); + if (!*table) { ERROR("Couldn't allocate memory for verity table!\n"); goto out; } - if (!fgets(*table, table_length, device)) { + if (TEMP_FAILURE_RETRY(read(device, *table, table_length)) != + (ssize_t)table_length) { ERROR("Couldn't read the verity table from metadata!\n"); - free(*table); - free(*signature); goto out; } - retval = 0; + (*table)[table_length] = 0; + retval = FS_MGR_SETUP_VERITY_SUCCESS; out: - if (device) - fclose(device); + if (device != -1) + TEMP_FAILURE_RETRY(close(device)); + + if (retval != FS_MGR_SETUP_VERITY_SUCCESS) { + free(*table); + free(*signature); + *table = 0; + *signature = 0; + } + return retval; } @@ -359,11 +378,12 @@ static int set_verified_property(char *name) { int fs_mgr_setup_verity(struct fstab_rec *fstab) { - int retval = -1; + int retval = FS_MGR_SETUP_VERITY_FAIL; + int fd = -1; - char *verity_blk_name; - char *verity_table; - char *verity_table_signature; + char *verity_blk_name = 0; + char *verity_table = 0; + char *verity_table_signature = 0; char buffer[DM_BUF_SIZE]; struct dm_ioctl *io = (struct dm_ioctl *) buffer; @@ -380,11 +400,21 @@ int fs_mgr_setup_verity(struct fstab_rec *fstab) { return retval; } + // read the verity block at the end of the block device + // send error code up the chain so we can detect attempts to disable verity + retval = read_verity_metadata(fstab->blk_device, + &verity_table_signature, + &verity_table); + if (retval < 0) { + goto out; + } + + retval = FS_MGR_SETUP_VERITY_FAIL; + // get the device mapper fd - int fd; if ((fd = open("/dev/device-mapper", O_RDWR)) < 0) { ERROR("Error opening device mapper (%s)", strerror(errno)); - return retval; + goto out; } // create the device @@ -399,14 +429,6 @@ int fs_mgr_setup_verity(struct fstab_rec *fstab) { goto out; } - verity_table = verity_table_signature = NULL; - // read the verity block at the end of the block device - if (read_verity_metadata(fstab->blk_device, - &verity_table_signature, - &verity_table) < 0) { - goto out; - } - // verify the signature on the table if (verify_table(verity_table_signature, verity_table, @@ -427,6 +449,7 @@ int fs_mgr_setup_verity(struct fstab_rec *fstab) { // assign the new verity block device as the block device free(fstab->blk_device); fstab->blk_device = verity_blk_name; + verity_blk_name = 0; // make sure we've set everything up properly if (test_access(fstab->blk_device) < 0) { @@ -437,6 +460,13 @@ int fs_mgr_setup_verity(struct fstab_rec *fstab) { retval = set_verified_property(mount_point); out: - close(fd); + if (fd != -1) { + close(fd); + } + + free(verity_table); + free(verity_table_signature); + free(verity_blk_name); + return retval; } |