summaryrefslogtreecommitdiffstats
path: root/fs_mgr/fs_mgr_verity.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs_mgr/fs_mgr_verity.c')
-rw-r--r--fs_mgr/fs_mgr_verity.c126
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;
}