diff --git a/fs/incfs/data_mgmt.c b/fs/incfs/data_mgmt.c index 09b781501d79..657f1ae6b9c8 100644 --- a/fs/incfs/data_mgmt.c +++ b/fs/incfs/data_mgmt.c @@ -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; @@ -1146,7 +1146,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); @@ -1157,7 +1157,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); @@ -1167,21 +1167,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); @@ -1193,7 +1193,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; @@ -1270,14 +1270,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; @@ -1291,7 +1290,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; @@ -1401,7 +1400,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; diff --git a/fs/incfs/format.c b/fs/incfs/format.c index 52079b5a45e6..d8ceb3f51e30 100644 --- a/fs/incfs/format.c +++ b/fs/incfs/format.c @@ -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; } diff --git a/fs/incfs/format.h b/fs/incfs/format.h index 81e3c1a04ce5..fda18fd9ec93 100644 --- a/fs/incfs/format.h +++ b/fs/incfs/format.h @@ -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 { sizeof_field(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 */ diff --git a/fs/incfs/pseudo_files.c b/fs/incfs/pseudo_files.c index 8067f47a920d..fccf06b06dc0 100644 --- a/fs/incfs/pseudo_files.c +++ b/fs/incfs/pseudo_files.c @@ -460,7 +460,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); @@ -779,7 +779,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);