ANDROID: Incremental fs: Set credentials before reading/writing

Bug: 174692664
Test: incfs_test passes, incremental installs work with ag/13082306
Signed-off-by: Paul Lawrence <paullawrence@google.com>

Change-Id: Ib1c924bbaff759f58f7d83bad8e23d7224ba7ed9
This commit is contained in:
Paul Lawrence
2020-12-09 11:17:58 -08:00
parent af56fc8070
commit 8278cda5d9
4 changed files with 54 additions and 33 deletions

View File

@@ -244,7 +244,7 @@ struct data_file *incfs_open_data_file(struct mount_info *mi, struct file *bf)
if (!S_ISREG(bf->f_inode->i_mode))
return ERR_PTR(-EBADF);
bfc = incfs_alloc_bfc(bf);
bfc = incfs_alloc_bfc(mi, bf);
if (IS_ERR(bfc))
return ERR_CAST(bfc);
@@ -570,8 +570,8 @@ static void log_block_read(struct mount_info *mi, incfs_uuid_t *id,
schedule_delayed_work(&log->ml_wakeup_work, msecs_to_jiffies(16));
}
static int validate_hash_tree(struct file *bf, struct file *f, int block_index,
struct mem_range data, u8 *buf)
static int validate_hash_tree(struct backing_file_context *bfc, struct file *f,
int block_index, struct mem_range data, u8 *buf)
{
struct data_file *df = get_incfs_data_file(f);
u8 stored_digest[INCFS_MAX_HASH_SIZE] = {};
@@ -628,7 +628,7 @@ static int validate_hash_tree(struct file *bf, struct file *f, int block_index,
if (page)
put_page(page);
res = incfs_kread(bf, buf, INCFS_DATA_FILE_BLOCK_SIZE,
res = incfs_kread(bfc, buf, INCFS_DATA_FILE_BLOCK_SIZE,
hash_block_offset[lvl] + sig->hash_offset);
if (res < 0)
return res;
@@ -1142,7 +1142,7 @@ ssize_t incfs_read_data_file_block(struct mem_range dst, struct file *f,
ssize_t result;
size_t bytes_to_read;
struct mount_info *mi = NULL;
struct file *bf = NULL;
struct backing_file_context *bfc = NULL;
struct data_file_block block = {};
struct data_file *df = get_incfs_data_file(f);
@@ -1153,7 +1153,7 @@ ssize_t incfs_read_data_file_block(struct mem_range dst, struct file *f,
return -ERANGE;
mi = df->df_mount_info;
bf = df->df_backing_file_context->bc_file;
bfc = df->df_backing_file_context;
result = wait_for_data_block(df, index, min_time_us,
min_pending_time_us, max_pending_time_us, &block);
@@ -1163,21 +1163,21 @@ ssize_t incfs_read_data_file_block(struct mem_range dst, struct file *f,
pos = block.db_backing_file_data_offset;
if (block.db_comp_alg == COMPRESSION_NONE) {
bytes_to_read = min(dst.len, block.db_stored_size);
result = incfs_kread(bf, dst.data, bytes_to_read, pos);
result = incfs_kread(bfc, dst.data, bytes_to_read, pos);
/* Some data was read, but not enough */
if (result >= 0 && result != bytes_to_read)
result = -EIO;
} else {
bytes_to_read = min(tmp.len, block.db_stored_size);
result = incfs_kread(bf, tmp.data, bytes_to_read, pos);
result = incfs_kread(bfc, tmp.data, bytes_to_read, pos);
if (result == bytes_to_read) {
result =
decompress(mi, range(tmp.data, bytes_to_read),
dst, block.db_comp_alg);
if (result < 0) {
const char *name =
bf->f_path.dentry->d_name.name;
bfc->bc_file->f_path.dentry->d_name.name;
pr_warn_once("incfs: Decompression error. %s",
name);
@@ -1189,7 +1189,7 @@ ssize_t incfs_read_data_file_block(struct mem_range dst, struct file *f,
}
if (result > 0) {
int err = validate_hash_tree(bf, f, index, dst, tmp.data);
int err = validate_hash_tree(bfc, f, index, dst, tmp.data);
if (err < 0)
result = err;
@@ -1264,14 +1264,13 @@ int incfs_process_new_data_block(struct data_file *df,
up_write(&segment->rwsem);
if (error)
pr_debug("incfs: %s %d error: %d\n", __func__,
block->block_index, error);
pr_debug("%d error: %d\n", block->block_index, error);
return error;
}
int incfs_read_file_signature(struct data_file *df, struct mem_range dst)
{
struct file *bf = df->df_backing_file_context->bc_file;
struct backing_file_context *bfc = df->df_backing_file_context;
struct incfs_df_signature *sig;
int read_res = 0;
@@ -1285,7 +1284,7 @@ int incfs_read_file_signature(struct data_file *df, struct mem_range dst)
if (dst.len < sig->sig_size)
return -E2BIG;
read_res = incfs_kread(bf, dst.data, sig->sig_size, sig->sig_offset);
read_res = incfs_kread(bfc, dst.data, sig->sig_size, sig->sig_offset);
if (read_res < 0)
return read_res;
@@ -1395,7 +1394,7 @@ static int process_file_signature_md(struct incfs_file_signature *sg,
goto out;
}
read = incfs_kread(df->df_backing_file_context->bc_file, buf,
read = incfs_kread(df->df_backing_file_context, buf,
signature->sig_size, signature->sig_offset);
if (read < 0) {
error = read;

View File

@@ -15,7 +15,8 @@
#include "format.h"
#include "data_mgmt.h"
struct backing_file_context *incfs_alloc_bfc(struct file *backing_file)
struct backing_file_context *incfs_alloc_bfc(struct mount_info *mi,
struct file *backing_file)
{
struct backing_file_context *result = NULL;
@@ -24,6 +25,7 @@ struct backing_file_context *incfs_alloc_bfc(struct file *backing_file)
return ERR_PTR(-ENOMEM);
result->bc_file = get_file(backing_file);
result->bc_cred = mi->mi_owner;
mutex_init(&result->bc_mutex);
return result;
}
@@ -92,7 +94,7 @@ static int truncate_backing_file(struct backing_file_context *bfc,
static int write_to_bf(struct backing_file_context *bfc, const void *buf,
size_t count, loff_t pos)
{
ssize_t res = incfs_kwrite(bfc->bc_file, buf, count, pos);
ssize_t res = incfs_kwrite(bfc, buf, count, pos);
if (res < 0)
return res;
@@ -346,13 +348,13 @@ int incfs_write_status_to_backing_file(struct backing_file_context *bfc,
return write_new_status_to_backing_file(bfc,
data_blocks_written, hash_blocks_written);
result = incfs_kread(bfc->bc_file, &is, sizeof(is), status_offset);
result = incfs_kread(bfc, &is, sizeof(is), status_offset);
if (result != sizeof(is))
return -EIO;
is.is_data_blocks_written = cpu_to_le32(data_blocks_written);
is.is_hash_blocks_written = cpu_to_le32(hash_blocks_written);
result = incfs_kwrite(bfc->bc_file, &is, sizeof(is), status_offset);
result = incfs_kwrite(bfc, &is, sizeof(is), status_offset);
if (result != sizeof(is))
return -EIO;
@@ -539,8 +541,7 @@ int incfs_read_blockmap_entries(struct backing_file_context *bfc,
if (start_index < 0 || bm_base_off <= 0)
return -ENODATA;
result = incfs_kread(bfc->bc_file, entries, bytes_to_read,
bm_entry_off);
result = incfs_kread(bfc, entries, bytes_to_read, bm_entry_off);
if (result < 0)
return result;
return result / sizeof(*entries);
@@ -556,7 +557,7 @@ int incfs_read_file_header(struct backing_file_context *bfc,
if (!bfc || !first_md_off)
return -EFAULT;
bytes_read = incfs_kread(bfc->bc_file, &fh, sizeof(fh), 0);
bytes_read = incfs_kread(bfc, &fh, sizeof(fh), 0);
if (bytes_read < 0)
return bytes_read;
@@ -607,8 +608,8 @@ int incfs_read_next_metadata_record(struct backing_file_context *bfc,
return -EPERM;
memset(&handler->md_buffer, 0, max_md_size);
bytes_read = incfs_kread(bfc->bc_file, &handler->md_buffer,
max_md_size, handler->md_record_offset);
bytes_read = incfs_kread(bfc, &handler->md_buffer, max_md_size,
handler->md_record_offset);
if (bytes_read < 0)
return bytes_read;
if (bytes_read < sizeof(*md_hdr))
@@ -679,12 +680,22 @@ int incfs_read_next_metadata_record(struct backing_file_context *bfc,
return res;
}
ssize_t incfs_kread(struct file *f, void *buf, size_t size, loff_t pos)
ssize_t incfs_kread(struct backing_file_context *bfc, void *buf, size_t size,
loff_t pos)
{
return kernel_read(f, buf, size, &pos);
const struct cred *old_cred = override_creds(bfc->bc_cred);
int ret = kernel_read(bfc->bc_file, buf, size, &pos);
revert_creds(old_cred);
return ret;
}
ssize_t incfs_kwrite(struct file *f, const void *buf, size_t size, loff_t pos)
ssize_t incfs_kwrite(struct backing_file_context *bfc, const void *buf,
size_t size, loff_t pos)
{
return kernel_write(f, buf, size, &pos);
const struct cred *old_cred = override_creds(bfc->bc_cred);
int ret = kernel_write(bfc->bc_file, buf, size, &pos);
revert_creds(old_cred);
return ret;
}

View File

@@ -272,6 +272,13 @@ struct backing_file_context {
* 0 means there are no metadata records.
*/
loff_t bc_last_md_record_offset;
/*
* Credentials to set before reads/writes
* Note that this is a pointer to the mount_info mi_owner field so
* there is no need to get/put the creds
*/
const struct cred *bc_cred;
};
struct metadata_handler {
@@ -297,7 +304,9 @@ struct metadata_handler {
FIELD_SIZEOF(struct metadata_handler, md_buffer)
/* Backing file context management */
struct backing_file_context *incfs_alloc_bfc(struct file *backing_file);
struct mount_info;
struct backing_file_context *incfs_alloc_bfc(struct mount_info *mi,
struct file *backing_file);
void incfs_free_bfc(struct backing_file_context *bfc);
@@ -348,7 +357,9 @@ int incfs_read_blockmap_entries(struct backing_file_context *bfc,
int incfs_read_next_metadata_record(struct backing_file_context *bfc,
struct metadata_handler *handler);
ssize_t incfs_kread(struct file *f, void *buf, size_t size, loff_t pos);
ssize_t incfs_kwrite(struct file *f, const void *buf, size_t size, loff_t pos);
ssize_t incfs_kread(struct backing_file_context *bfc, void *buf, size_t size,
loff_t pos);
ssize_t incfs_kwrite(struct backing_file_context *bfc, const void *buf,
size_t size, loff_t pos);
#endif /* _INCFS_FORMAT_H */

View File

@@ -465,7 +465,7 @@ static int init_new_file(struct mount_info *mi, struct dentry *dentry,
goto out;
}
bfc = incfs_alloc_bfc(new_file);
bfc = incfs_alloc_bfc(mi, new_file);
fput(new_file);
if (IS_ERR(bfc)) {
error = PTR_ERR(bfc);
@@ -784,7 +784,7 @@ static int init_new_mapped_file(struct mount_info *mi, struct dentry *dentry,
goto out;
}
bfc = incfs_alloc_bfc(new_file);
bfc = incfs_alloc_bfc(mi, new_file);
fput(new_file);
if (IS_ERR(bfc)) {
error = PTR_ERR(bfc);