Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d16e7edb authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "ANDROID: Incremental fs: Set credentials before reading/writing"

parents 24793476 84bb7a65
Loading
Loading
Loading
Loading
+15 −15
Original line number Original line Diff line number Diff line
@@ -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;
+22 −12
Original line number Original line Diff line number Diff line
@@ -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;
}
}
+14 −3
Original line number Original line Diff line number Diff line
@@ -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 */
+10 −0
Original line number Original line Diff line number Diff line
@@ -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 scnprintf(buff, PAGE_SIZE, "%s", "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,
};
};


+14 −8
Original line number Original line Diff line number Diff line
@@ -604,8 +604,11 @@ static ssize_t log_read(struct file *f, char __user *buf, size_t len,


	reads_to_collect = min_t(ssize_t, rl_size, reads_to_collect);
	reads_to_collect = min_t(ssize_t, rl_size, reads_to_collect);
	while (reads_to_collect > 0) {
	while (reads_to_collect > 0) {
		struct read_log_state next_state = READ_ONCE(log_state->state);
		struct read_log_state next_state;
		int reads_collected = incfs_collect_logged_reads(
		int reads_collected;

		memcpy(&next_state, &log_state->state, sizeof(next_state));
		reads_collected = incfs_collect_logged_reads(
			mi, &next_state, reads_buf,
			mi, &next_state, reads_buf,
			min_t(ssize_t, reads_to_collect, reads_per_page));
			min_t(ssize_t, reads_to_collect, reads_per_page));
		if (reads_collected <= 0) {
		if (reads_collected <= 0) {
@@ -624,7 +627,7 @@ static ssize_t log_read(struct file *f, char __user *buf, size_t len,
			goto out;
			goto out;
		}
		}


		WRITE_ONCE(log_state->state, next_state);
		memcpy(&log_state->state, &next_state, sizeof(next_state));
		total_reads_collected += reads_collected;
		total_reads_collected += reads_collected;
		buf += reads_collected * sizeof(*reads_buf);
		buf += reads_collected * sizeof(*reads_buf);
		reads_to_collect -= reads_collected;
		reads_to_collect -= reads_collected;
@@ -897,14 +900,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);
@@ -1025,7 +1028,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);
@@ -1903,10 +1906,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)) {