ANDROID: Incremental fs: Set credentials before reading/writing
Use same selinux scheme as incfs v2 Fix memory leak Bug: 174692664 Test: incfs_test passes Signed-off-by: Paul Lawrence <paullawrence@google.com> Change-Id: I6058ddad9d43ba01b2eabd7d3c576f2cc9b42292
This commit is contained in:
parent
a035201d12
commit
fad2655cb7
@ -144,7 +144,7 @@ struct data_file *incfs_open_data_file(struct mount_info *mi, struct file *bf)
|
|||||||
if (!S_ISREG(bf->f_inode->i_mode))
|
if (!S_ISREG(bf->f_inode->i_mode))
|
||||||
return ERR_PTR(-EBADF);
|
return ERR_PTR(-EBADF);
|
||||||
|
|
||||||
bfc = incfs_alloc_bfc(bf);
|
bfc = incfs_alloc_bfc(mi, bf);
|
||||||
if (IS_ERR(bfc))
|
if (IS_ERR(bfc))
|
||||||
return ERR_CAST(bfc);
|
return ERR_CAST(bfc);
|
||||||
|
|
||||||
@ -199,6 +199,7 @@ void incfs_free_data_file(struct data_file *df)
|
|||||||
for (i = 0; i < ARRAY_SIZE(df->df_segments); i++)
|
for (i = 0; i < ARRAY_SIZE(df->df_segments); i++)
|
||||||
data_file_segment_destroy(&df->df_segments[i]);
|
data_file_segment_destroy(&df->df_segments[i]);
|
||||||
incfs_free_bfc(df->df_backing_file_context);
|
incfs_free_bfc(df->df_backing_file_context);
|
||||||
|
kfree(df->df_signature);
|
||||||
kfree(df);
|
kfree(df);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -387,8 +388,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));
|
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,
|
static int validate_hash_tree(struct backing_file_context *bfc, struct file *f,
|
||||||
struct mem_range data, u8 *buf)
|
int block_index, struct mem_range data, u8 *buf)
|
||||||
{
|
{
|
||||||
struct data_file *df = get_incfs_data_file(f);
|
struct data_file *df = get_incfs_data_file(f);
|
||||||
u8 stored_digest[INCFS_MAX_HASH_SIZE] = {};
|
u8 stored_digest[INCFS_MAX_HASH_SIZE] = {};
|
||||||
@ -445,7 +446,7 @@ static int validate_hash_tree(struct file *bf, struct file *f, int block_index,
|
|||||||
if (page)
|
if (page)
|
||||||
put_page(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);
|
hash_block_offset[lvl] + sig->hash_offset);
|
||||||
if (res < 0)
|
if (res < 0)
|
||||||
return res;
|
return res;
|
||||||
@ -918,7 +919,7 @@ ssize_t incfs_read_data_file_block(struct mem_range dst, struct file *f,
|
|||||||
ssize_t result;
|
ssize_t result;
|
||||||
size_t bytes_to_read;
|
size_t bytes_to_read;
|
||||||
struct mount_info *mi = NULL;
|
struct mount_info *mi = NULL;
|
||||||
struct file *bf = NULL;
|
struct backing_file_context *bfc = NULL;
|
||||||
struct data_file_block block = {};
|
struct data_file_block block = {};
|
||||||
struct data_file *df = get_incfs_data_file(f);
|
struct data_file *df = get_incfs_data_file(f);
|
||||||
|
|
||||||
@ -929,7 +930,7 @@ ssize_t incfs_read_data_file_block(struct mem_range dst, struct file *f,
|
|||||||
return -ERANGE;
|
return -ERANGE;
|
||||||
|
|
||||||
mi = df->df_mount_info;
|
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, timeout_ms, &block);
|
result = wait_for_data_block(df, index, timeout_ms, &block);
|
||||||
if (result < 0)
|
if (result < 0)
|
||||||
@ -938,20 +939,20 @@ ssize_t incfs_read_data_file_block(struct mem_range dst, struct file *f,
|
|||||||
pos = block.db_backing_file_data_offset;
|
pos = block.db_backing_file_data_offset;
|
||||||
if (block.db_comp_alg == COMPRESSION_NONE) {
|
if (block.db_comp_alg == COMPRESSION_NONE) {
|
||||||
bytes_to_read = min(dst.len, block.db_stored_size);
|
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 */
|
/* Some data was read, but not enough */
|
||||||
if (result >= 0 && result != bytes_to_read)
|
if (result >= 0 && result != bytes_to_read)
|
||||||
result = -EIO;
|
result = -EIO;
|
||||||
} else {
|
} else {
|
||||||
bytes_to_read = min(tmp.len, block.db_stored_size);
|
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) {
|
if (result == bytes_to_read) {
|
||||||
result =
|
result =
|
||||||
decompress(range(tmp.data, bytes_to_read), dst);
|
decompress(range(tmp.data, bytes_to_read), dst);
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
const char *name =
|
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",
|
pr_warn_once("incfs: Decompression error. %s",
|
||||||
name);
|
name);
|
||||||
@ -963,7 +964,7 @@ ssize_t incfs_read_data_file_block(struct mem_range dst, struct file *f,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (result > 0) {
|
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)
|
if (err < 0)
|
||||||
result = err;
|
result = err;
|
||||||
@ -1026,14 +1027,13 @@ int incfs_process_new_data_block(struct data_file *df,
|
|||||||
unlock:
|
unlock:
|
||||||
mutex_unlock(&segment->blockmap_mutex);
|
mutex_unlock(&segment->blockmap_mutex);
|
||||||
if (error)
|
if (error)
|
||||||
pr_debug("incfs: %s %d error: %d\n", __func__,
|
pr_debug("%d error: %d\n", block->block_index, error);
|
||||||
block->block_index, error);
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
int incfs_read_file_signature(struct data_file *df, struct mem_range dst)
|
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;
|
struct incfs_df_signature *sig;
|
||||||
int read_res = 0;
|
int read_res = 0;
|
||||||
|
|
||||||
@ -1047,7 +1047,7 @@ int incfs_read_file_signature(struct data_file *df, struct mem_range dst)
|
|||||||
if (dst.len < sig->sig_size)
|
if (dst.len < sig->sig_size)
|
||||||
return -E2BIG;
|
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)
|
if (read_res < 0)
|
||||||
return read_res;
|
return read_res;
|
||||||
@ -1173,7 +1173,7 @@ static int process_file_signature_md(struct incfs_file_signature *sg,
|
|||||||
goto out;
|
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);
|
signature->sig_size, signature->sig_offset);
|
||||||
if (read < 0) {
|
if (read < 0) {
|
||||||
error = read;
|
error = read;
|
||||||
|
@ -15,7 +15,8 @@
|
|||||||
#include "format.h"
|
#include "format.h"
|
||||||
#include "data_mgmt.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;
|
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);
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
result->bc_file = get_file(backing_file);
|
result->bc_file = get_file(backing_file);
|
||||||
|
result->bc_cred = mi->mi_owner;
|
||||||
mutex_init(&result->bc_mutex);
|
mutex_init(&result->bc_mutex);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -116,7 +118,7 @@ static int append_zeros(struct backing_file_context *bfc, size_t len)
|
|||||||
static int write_to_bf(struct backing_file_context *bfc, const void *buf,
|
static int write_to_bf(struct backing_file_context *bfc, const void *buf,
|
||||||
size_t count, loff_t pos)
|
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)
|
if (res < 0)
|
||||||
return res;
|
return res;
|
||||||
@ -531,8 +533,7 @@ int incfs_read_blockmap_entries(struct backing_file_context *bfc,
|
|||||||
if (start_index < 0 || bm_base_off <= 0)
|
if (start_index < 0 || bm_base_off <= 0)
|
||||||
return -ENODATA;
|
return -ENODATA;
|
||||||
|
|
||||||
result = incfs_kread(bfc->bc_file, entries, bytes_to_read,
|
result = incfs_kread(bfc, entries, bytes_to_read, bm_entry_off);
|
||||||
bm_entry_off);
|
|
||||||
if (result < 0)
|
if (result < 0)
|
||||||
return result;
|
return result;
|
||||||
return result / sizeof(*entries);
|
return result / sizeof(*entries);
|
||||||
@ -548,8 +549,7 @@ int incfs_read_file_header(struct backing_file_context *bfc,
|
|||||||
if (!bfc || !first_md_off)
|
if (!bfc || !first_md_off)
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
LOCK_REQUIRED(bfc->bc_mutex);
|
bytes_read = incfs_kread(bfc, &fh, sizeof(fh), 0);
|
||||||
bytes_read = incfs_kread(bfc->bc_file, &fh, sizeof(fh), 0);
|
|
||||||
if (bytes_read < 0)
|
if (bytes_read < 0)
|
||||||
return bytes_read;
|
return bytes_read;
|
||||||
|
|
||||||
@ -603,8 +603,8 @@ int incfs_read_next_metadata_record(struct backing_file_context *bfc,
|
|||||||
return -EPERM;
|
return -EPERM;
|
||||||
|
|
||||||
memset(&handler->md_buffer, 0, max_md_size);
|
memset(&handler->md_buffer, 0, max_md_size);
|
||||||
bytes_read = incfs_kread(bfc->bc_file, &handler->md_buffer,
|
bytes_read = incfs_kread(bfc, &handler->md_buffer, max_md_size,
|
||||||
max_md_size, handler->md_record_offset);
|
handler->md_record_offset);
|
||||||
if (bytes_read < 0)
|
if (bytes_read < 0)
|
||||||
return bytes_read;
|
return bytes_read;
|
||||||
if (bytes_read < sizeof(*md_hdr))
|
if (bytes_read < sizeof(*md_hdr))
|
||||||
@ -680,12 +680,22 @@ int incfs_read_next_metadata_record(struct backing_file_context *bfc,
|
|||||||
return res;
|
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;
|
||||||
}
|
}
|
||||||
|
@ -256,6 +256,13 @@ struct backing_file_context {
|
|||||||
* 0 means there are no metadata records.
|
* 0 means there are no metadata records.
|
||||||
*/
|
*/
|
||||||
loff_t bc_last_md_record_offset;
|
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 {
|
struct metadata_handler {
|
||||||
@ -283,7 +290,9 @@ struct metadata_handler {
|
|||||||
loff_t incfs_get_end_offset(struct file *f);
|
loff_t incfs_get_end_offset(struct file *f);
|
||||||
|
|
||||||
/* Backing file context management */
|
/* 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);
|
void incfs_free_bfc(struct backing_file_context *bfc);
|
||||||
|
|
||||||
@ -334,7 +343,9 @@ int incfs_read_blockmap_entries(struct backing_file_context *bfc,
|
|||||||
int incfs_read_next_metadata_record(struct backing_file_context *bfc,
|
int incfs_read_next_metadata_record(struct backing_file_context *bfc,
|
||||||
struct metadata_handler *handler);
|
struct metadata_handler *handler);
|
||||||
|
|
||||||
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,
|
||||||
ssize_t incfs_kwrite(struct file *f, const void *buf, size_t size, loff_t pos);
|
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 */
|
#endif /* _INCFS_FORMAT_H */
|
||||||
|
@ -30,8 +30,18 @@ static ssize_t corefs_show(struct kobject *kobj,
|
|||||||
|
|
||||||
static struct kobj_attribute corefs_attr = __ATTR_RO(corefs);
|
static struct kobj_attribute corefs_attr = __ATTR_RO(corefs);
|
||||||
|
|
||||||
|
static ssize_t mounter_context_for_backing_rw_show(struct kobject *kobj,
|
||||||
|
struct kobj_attribute *attr, char *buff)
|
||||||
|
{
|
||||||
|
return snprintf(buff, PAGE_SIZE, "supported\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct kobj_attribute mounter_context_for_backing_rw_attr =
|
||||||
|
__ATTR_RO(mounter_context_for_backing_rw);
|
||||||
|
|
||||||
static struct attribute *attributes[] = {
|
static struct attribute *attributes[] = {
|
||||||
&corefs_attr.attr,
|
&corefs_attr.attr,
|
||||||
|
&mounter_context_for_backing_rw_attr.attr,
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -898,14 +898,14 @@ static int init_new_file(struct mount_info *mi, struct dentry *dentry,
|
|||||||
.dentry = dentry
|
.dentry = dentry
|
||||||
};
|
};
|
||||||
new_file = dentry_open(&path, O_RDWR | O_NOATIME | O_LARGEFILE,
|
new_file = dentry_open(&path, O_RDWR | O_NOATIME | O_LARGEFILE,
|
||||||
mi->mi_owner);
|
current_cred());
|
||||||
|
|
||||||
if (IS_ERR(new_file)) {
|
if (IS_ERR(new_file)) {
|
||||||
error = PTR_ERR(new_file);
|
error = PTR_ERR(new_file);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
bfc = incfs_alloc_bfc(new_file);
|
bfc = incfs_alloc_bfc(mi, new_file);
|
||||||
fput(new_file);
|
fput(new_file);
|
||||||
if (IS_ERR(bfc)) {
|
if (IS_ERR(bfc)) {
|
||||||
error = PTR_ERR(bfc);
|
error = PTR_ERR(bfc);
|
||||||
@ -1026,7 +1026,7 @@ static int dir_relative_path_resolve(
|
|||||||
if (dir_fd < 0)
|
if (dir_fd < 0)
|
||||||
return dir_fd;
|
return dir_fd;
|
||||||
|
|
||||||
dir_f = dentry_open(base_path, O_RDONLY | O_NOATIME, mi->mi_owner);
|
dir_f = dentry_open(base_path, O_RDONLY | O_NOATIME, current_cred());
|
||||||
|
|
||||||
if (IS_ERR(dir_f)) {
|
if (IS_ERR(dir_f)) {
|
||||||
error = PTR_ERR(dir_f);
|
error = PTR_ERR(dir_f);
|
||||||
@ -1904,10 +1904,13 @@ static int file_open(struct inode *inode, struct file *file)
|
|||||||
struct file *backing_file = NULL;
|
struct file *backing_file = NULL;
|
||||||
struct path backing_path = {};
|
struct path backing_path = {};
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
const struct cred *old_cred;
|
||||||
|
|
||||||
get_incfs_backing_path(file->f_path.dentry, &backing_path);
|
get_incfs_backing_path(file->f_path.dentry, &backing_path);
|
||||||
backing_file = dentry_open(
|
old_cred = override_creds(mi->mi_owner);
|
||||||
&backing_path, O_RDWR | O_NOATIME | O_LARGEFILE, mi->mi_owner);
|
backing_file = dentry_open(&backing_path,
|
||||||
|
O_RDWR | O_NOATIME | O_LARGEFILE, current_cred());
|
||||||
|
revert_creds(old_cred);
|
||||||
path_put(&backing_path);
|
path_put(&backing_path);
|
||||||
|
|
||||||
if (IS_ERR(backing_file)) {
|
if (IS_ERR(backing_file)) {
|
||||||
|
Loading…
Reference in New Issue
Block a user