summaryrefslogtreecommitdiffstats
path: root/fs_mgr
diff options
context:
space:
mode:
Diffstat (limited to 'fs_mgr')
-rw-r--r--fs_mgr/Android.mk4
-rw-r--r--fs_mgr/fs_mgr.c29
-rw-r--r--fs_mgr/fs_mgr_fstab.c5
-rw-r--r--fs_mgr/fs_mgr_priv_verity.h5
-rw-r--r--fs_mgr/fs_mgr_verity.c126
-rw-r--r--fs_mgr/include/fs_mgr.h8
6 files changed, 121 insertions, 56 deletions
diff --git a/fs_mgr/Android.mk b/fs_mgr/Android.mk
index 7cffc37..61bf1ee 100644
--- a/fs_mgr/Android.mk
+++ b/fs_mgr/Android.mk
@@ -13,6 +13,10 @@ LOCAL_C_INCLUDES += system/extras/ext4_utils
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
LOCAL_CFLAGS := -Werror
+ifneq (,$(filter userdebug,$(TARGET_BUILD_VARIANT)))
+LOCAL_CFLAGS += -DALLOW_ADBD_DISABLE_VERITY=1
+endif
+
include $(BUILD_STATIC_LIBRARY)
diff --git a/fs_mgr/fs_mgr.c b/fs_mgr/fs_mgr.c
index 91e6c33..d1e92f2 100644
--- a/fs_mgr/fs_mgr.c
+++ b/fs_mgr/fs_mgr.c
@@ -141,9 +141,10 @@ static void check_fs(char *blk_device, char *fs_type, char *target)
} else if (!strcmp(fs_type, "f2fs")) {
char *f2fs_fsck_argv[] = {
F2FS_FSCK_BIN,
+ "-f",
blk_device
};
- INFO("Running %s on %s\n", F2FS_FSCK_BIN, blk_device);
+ INFO("Running %s -f %s\n", F2FS_FSCK_BIN, blk_device);
ret = android_fork_execvp_ext(ARRAY_SIZE(f2fs_fsck_argv), f2fs_fsck_argv,
&status, true, LOG_KLOG | LOG_FILE,
@@ -245,6 +246,16 @@ static int device_is_debuggable() {
return strcmp(value, "1") ? 0 : 1;
}
+static int device_is_secure() {
+ int ret = -1;
+ char value[PROP_VALUE_MAX];
+ ret = __system_property_get("ro.secure", value);
+ /* If error, we want to fail secure */
+ if (ret < 0)
+ return 1;
+ return strcmp(value, "0") ? 1 : 0;
+}
+
/*
* Tries to mount any of the consecutive fstab entries that match
* the mountpoint of the one given by fstab->recs[start_idx].
@@ -350,9 +361,11 @@ int fs_mgr_mount_all(struct fstab *fstab)
wait_for_file(fstab->recs[i].blk_device, WAIT_TIMEOUT);
}
- if ((fstab->recs[i].fs_mgr_flags & MF_VERIFY) &&
- !device_is_debuggable()) {
- if (fs_mgr_setup_verity(&fstab->recs[i]) < 0) {
+ if ((fstab->recs[i].fs_mgr_flags & MF_VERIFY) && device_is_secure()) {
+ int rc = fs_mgr_setup_verity(&fstab->recs[i]);
+ if (device_is_debuggable() && rc == FS_MGR_SETUP_VERITY_DISABLED) {
+ INFO("Verity disabled");
+ } else if (rc != FS_MGR_SETUP_VERITY_SUCCESS) {
ERROR("Could not set up verified partition, skipping!\n");
continue;
}
@@ -467,9 +480,11 @@ int fs_mgr_do_mount(struct fstab *fstab, char *n_name, char *n_blk_device,
fstab->recs[i].mount_point);
}
- if ((fstab->recs[i].fs_mgr_flags & MF_VERIFY) &&
- !device_is_debuggable()) {
- if (fs_mgr_setup_verity(&fstab->recs[i]) < 0) {
+ if ((fstab->recs[i].fs_mgr_flags & MF_VERIFY) && device_is_secure()) {
+ int rc = fs_mgr_setup_verity(&fstab->recs[i]);
+ if (device_is_debuggable() && rc == FS_MGR_SETUP_VERITY_DISABLED) {
+ INFO("Verity disabled");
+ } else if (rc != FS_MGR_SETUP_VERITY_SUCCESS) {
ERROR("Could not set up verified partition, skipping!\n");
continue;
}
diff --git a/fs_mgr/fs_mgr_fstab.c b/fs_mgr/fs_mgr_fstab.c
index 3f84179..ab8f128 100644
--- a/fs_mgr/fs_mgr_fstab.c
+++ b/fs_mgr/fs_mgr_fstab.c
@@ -418,6 +418,11 @@ int fs_mgr_is_nonremovable(struct fstab_rec *fstab)
return fstab->fs_mgr_flags & MF_NONREMOVABLE;
}
+int fs_mgr_is_verified(struct fstab_rec *fstab)
+{
+ return fstab->fs_mgr_flags & MF_VERIFY;
+}
+
int fs_mgr_is_encryptable(struct fstab_rec *fstab)
{
return fstab->fs_mgr_flags & (MF_CRYPT | MF_FORCECRYPT);
diff --git a/fs_mgr/fs_mgr_priv_verity.h b/fs_mgr/fs_mgr_priv_verity.h
index 6193784..f90e596 100644
--- a/fs_mgr/fs_mgr_priv_verity.h
+++ b/fs_mgr/fs_mgr_priv_verity.h
@@ -14,4 +14,7 @@
* limitations under the License.
*/
-int fs_mgr_setup_verity(struct fstab_rec *fstab); \ No newline at end of file
+#define FS_MGR_SETUP_VERITY_DISABLED -2
+#define FS_MGR_SETUP_VERITY_FAIL -1
+#define FS_MGR_SETUP_VERITY_SUCCESS 0
+int fs_mgr_setup_verity(struct fstab_rec *fstab);
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;
}
diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h
index 0c7eb20..5e2ff41 100644
--- a/fs_mgr/include/fs_mgr.h
+++ b/fs_mgr/include/fs_mgr.h
@@ -20,6 +20,13 @@
#include <stdint.h>
#include <linux/dm-ioctl.h>
+// Magic number at start of verity metadata
+#define VERITY_METADATA_MAGIC_NUMBER 0xb001b001
+
+// Replacement magic number at start of verity metadata to cleanly
+// turn verity off in userdebug builds.
+#define VERITY_METADATA_MAGIC_DISABLE 0x46464f56 // "VOFF"
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -74,6 +81,7 @@ int fs_mgr_add_entry(struct fstab *fstab,
struct fstab_rec *fs_mgr_get_entry_for_mount_point(struct fstab *fstab, const char *path);
int fs_mgr_is_voldmanaged(struct fstab_rec *fstab);
int fs_mgr_is_nonremovable(struct fstab_rec *fstab);
+int fs_mgr_is_verified(struct fstab_rec *fstab);
int fs_mgr_is_encryptable(struct fstab_rec *fstab);
int fs_mgr_is_noemulatedsd(struct fstab_rec *fstab);
int fs_mgr_swapon_all(struct fstab *fstab);