ANDROID: Incremental fs: Remove signature checks from kernel
Test: selftests pass
Bug: 133435829
Signed-off-by: Paul Lawrence <paullawrence@google.com>
Change-Id: Ia7e69b1b0176202da4b418ea815b370cbdacd5c2
Git-commit: 73e7d65693
Git-repo: https://android.googlesource.com/kernel/common/
Signed-off-by: Sayali Lokhande <sayalil@codeaurora.org>
This commit is contained in:
committed by
Blagovest Kolenichev
parent
79efcc39b7
commit
183696eacf
@@ -250,7 +250,7 @@ static int validate_hash_tree(struct file *bf, struct data_file *df,
|
||||
{
|
||||
u8 digest[INCFS_MAX_HASH_SIZE] = {};
|
||||
struct mtree *tree = NULL;
|
||||
struct ondisk_signature *sig = NULL;
|
||||
struct incfs_df_signature *sig = NULL;
|
||||
struct mem_range calc_digest_rng;
|
||||
struct mem_range saved_digest_rng;
|
||||
struct mem_range root_hash_rng;
|
||||
@@ -273,8 +273,8 @@ static int validate_hash_tree(struct file *bf, struct data_file *df,
|
||||
return res;
|
||||
|
||||
for (lvl = 0; lvl < tree->depth; lvl++) {
|
||||
loff_t lvl_off = tree->hash_level_suboffset[lvl] +
|
||||
sig->mtree_offset;
|
||||
loff_t lvl_off =
|
||||
tree->hash_level_suboffset[lvl] + sig->hash_offset;
|
||||
loff_t hash_block_off = lvl_off +
|
||||
round_down(hash_block_index * digest_size,
|
||||
INCFS_DATA_FILE_BLOCK_SIZE);
|
||||
@@ -322,72 +322,6 @@ static int validate_hash_tree(struct file *bf, struct data_file *df,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int revalidate_signature(struct file *bf, struct data_file *df)
|
||||
{
|
||||
struct ondisk_signature *sig = df->df_signature;
|
||||
struct mem_range root_hash = {};
|
||||
int result = 0;
|
||||
u8 *sig_buf = NULL;
|
||||
u8 *add_data_buf = NULL;
|
||||
ssize_t read_res;
|
||||
|
||||
/* File has no signature. */
|
||||
if (!sig || !df->df_hash_tree || sig->sig_size == 0)
|
||||
return 0;
|
||||
|
||||
/* Signature has already been validated. */
|
||||
if (df->df_signature_validated)
|
||||
return 0;
|
||||
|
||||
add_data_buf = kzalloc(sig->add_data_size, GFP_NOFS);
|
||||
if (!add_data_buf) {
|
||||
result = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
read_res = incfs_kread(bf, add_data_buf, sig->add_data_size,
|
||||
sig->add_data_offset);
|
||||
if (read_res < 0) {
|
||||
result = read_res;
|
||||
goto out;
|
||||
}
|
||||
if (read_res != sig->add_data_size) {
|
||||
result = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
sig_buf = kzalloc(sig->sig_size, GFP_NOFS);
|
||||
if (!sig_buf) {
|
||||
result = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
read_res = incfs_kread(bf, sig_buf, sig->sig_size, sig->sig_offset);
|
||||
if (read_res < 0) {
|
||||
result = read_res;
|
||||
goto out;
|
||||
}
|
||||
if (read_res != sig->sig_size) {
|
||||
result = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
root_hash = range(df->df_hash_tree->root_hash,
|
||||
df->df_hash_tree->alg->digest_size);
|
||||
|
||||
result = incfs_validate_pkcs7_signature(
|
||||
range(sig_buf, sig->sig_size),
|
||||
root_hash,
|
||||
range(add_data_buf, sig->add_data_size));
|
||||
|
||||
if (result == 0)
|
||||
df->df_signature_validated = true;
|
||||
out:
|
||||
kfree(sig_buf);
|
||||
kfree(add_data_buf);
|
||||
return result;
|
||||
}
|
||||
|
||||
static struct data_file_segment *get_file_segment(struct data_file *df,
|
||||
int block_index)
|
||||
{
|
||||
@@ -683,13 +617,6 @@ ssize_t incfs_read_data_file_block(struct mem_range dst, struct data_file *df,
|
||||
result = err;
|
||||
}
|
||||
|
||||
if (result > 0) {
|
||||
int err = revalidate_signature(bf, df);
|
||||
|
||||
if (err < 0)
|
||||
result = err;
|
||||
}
|
||||
|
||||
if (result >= 0)
|
||||
log_block_read(mi, &df->df_id, index, false /*timed out*/);
|
||||
|
||||
@@ -755,7 +682,7 @@ int incfs_process_new_data_block(struct data_file *df,
|
||||
int incfs_read_file_signature(struct data_file *df, struct mem_range dst)
|
||||
{
|
||||
struct file *bf = df->df_backing_file_context->bc_file;
|
||||
struct ondisk_signature *sig;
|
||||
struct incfs_df_signature *sig;
|
||||
int read_res = 0;
|
||||
|
||||
if (!dst.data)
|
||||
@@ -785,7 +712,7 @@ int incfs_process_new_hash_block(struct data_file *df,
|
||||
struct backing_file_context *bfc = NULL;
|
||||
struct mount_info *mi = NULL;
|
||||
struct mtree *hash_tree = NULL;
|
||||
struct ondisk_signature *sig = NULL;
|
||||
struct incfs_df_signature *sig = NULL;
|
||||
loff_t hash_area_base = 0;
|
||||
loff_t hash_area_size = 0;
|
||||
int error = 0;
|
||||
@@ -804,11 +731,11 @@ int incfs_process_new_hash_block(struct data_file *df,
|
||||
|
||||
hash_tree = df->df_hash_tree;
|
||||
sig = df->df_signature;
|
||||
if (!hash_tree || !sig || sig->mtree_offset == 0)
|
||||
if (!hash_tree || !sig || sig->hash_offset == 0)
|
||||
return -ENOTSUPP;
|
||||
|
||||
hash_area_base = sig->mtree_offset;
|
||||
hash_area_size = sig->mtree_size;
|
||||
hash_area_base = sig->hash_offset;
|
||||
hash_area_size = sig->hash_size;
|
||||
if (hash_area_size < block->block_index * INCFS_DATA_FILE_BLOCK_SIZE
|
||||
+ block->data_len) {
|
||||
/* Hash block goes beyond dedicated hash area of this file. */
|
||||
@@ -866,58 +793,69 @@ static int process_file_signature_md(struct incfs_file_signature *sg,
|
||||
{
|
||||
struct data_file *df = handler->context;
|
||||
struct mtree *hash_tree = NULL;
|
||||
struct ondisk_signature *signature = NULL;
|
||||
int error = 0;
|
||||
loff_t base_tree_off = le64_to_cpu(sg->sg_hash_tree_offset);
|
||||
u32 tree_size = le32_to_cpu(sg->sg_hash_tree_size);
|
||||
loff_t sig_off = le64_to_cpu(sg->sg_sig_offset);
|
||||
u32 sig_size = le32_to_cpu(sg->sg_sig_size);
|
||||
loff_t add_data_off = le64_to_cpu(sg->sg_add_data_offset);
|
||||
u32 add_data_size = le32_to_cpu(sg->sg_add_data_size);
|
||||
struct incfs_df_signature *signature =
|
||||
kzalloc(sizeof(*signature), GFP_NOFS);
|
||||
void *buf = 0;
|
||||
ssize_t read;
|
||||
|
||||
if (!df)
|
||||
return -ENOENT;
|
||||
if (!df || !df->df_backing_file_context ||
|
||||
!df->df_backing_file_context->bc_file) {
|
||||
error = -ENOENT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
signature = kzalloc(sizeof(*signature), GFP_NOFS);
|
||||
if (!signature) {
|
||||
signature->hash_offset = le64_to_cpu(sg->sg_hash_tree_offset);
|
||||
signature->hash_size = le32_to_cpu(sg->sg_hash_tree_size);
|
||||
signature->sig_offset = le64_to_cpu(sg->sg_sig_offset);
|
||||
signature->sig_size = le32_to_cpu(sg->sg_sig_size);
|
||||
|
||||
buf = kzalloc(signature->sig_size, GFP_NOFS);
|
||||
if (!buf) {
|
||||
error = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
signature->add_data_offset = add_data_off;
|
||||
signature->add_data_size = add_data_size;
|
||||
signature->sig_offset = sig_off;
|
||||
signature->sig_size = sig_size;
|
||||
signature->mtree_offset = base_tree_off;
|
||||
signature->mtree_size = tree_size;
|
||||
read = incfs_kread(df->df_backing_file_context->bc_file, buf,
|
||||
signature->sig_size, signature->sig_offset);
|
||||
if (read < 0) {
|
||||
error = read;
|
||||
goto out;
|
||||
}
|
||||
|
||||
hash_tree = incfs_alloc_mtree(sg->sg_hash_alg, df->df_block_count,
|
||||
range(sg->sg_root_hash, sizeof(sg->sg_root_hash)));
|
||||
if (read != signature->sig_size) {
|
||||
error = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
hash_tree = incfs_alloc_mtree(range(buf, signature->sig_size),
|
||||
df->df_block_count);
|
||||
if (IS_ERR(hash_tree)) {
|
||||
error = PTR_ERR(hash_tree);
|
||||
hash_tree = NULL;
|
||||
goto out;
|
||||
}
|
||||
if (hash_tree->hash_tree_area_size != tree_size) {
|
||||
if (hash_tree->hash_tree_area_size != signature->hash_size) {
|
||||
error = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
if (tree_size > 0 && handler->md_record_offset <= base_tree_off) {
|
||||
if (signature->hash_size > 0 &&
|
||||
handler->md_record_offset <= signature->hash_offset) {
|
||||
error = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
if (handler->md_record_offset <= signature->add_data_offset ||
|
||||
handler->md_record_offset <= signature->sig_offset) {
|
||||
if (handler->md_record_offset <= signature->sig_offset) {
|
||||
error = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
df->df_hash_tree = hash_tree;
|
||||
hash_tree = NULL;
|
||||
df->df_signature = signature;
|
||||
signature = NULL;
|
||||
out:
|
||||
if (error) {
|
||||
incfs_free_mtree(hash_tree);
|
||||
kfree(signature);
|
||||
}
|
||||
incfs_free_mtree(hash_tree);
|
||||
kfree(signature);
|
||||
kfree(buf);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user