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

Commit e251cfe6 authored by Paul Lawrence's avatar Paul Lawrence
Browse files

ANDROID: Incremental fs: Protect get_fill_block, and add a field



Since INCFS_IOC_GET_FILLED_BLOCKS potentially leaks information about usage
patterns, and is only useful to someone filling the file, best protect it in
the same way as INCFS_IOC_FILL_BLOCKS.

Add useful field data_block_out as well

Test: incfs_test passes
Bug: 152983639
Signed-off-by: default avatarPaul Lawrence <paullawrence@google.com>
Change-Id: I126a8cf711e56592479093e9aadbfd0e7f700752
parent 759d52ee
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -436,6 +436,7 @@ int incfs_get_filled_blocks(struct data_file *df,
	if (end_index > df->df_total_block_count)
		end_index = df->df_total_block_count;
	arg->total_blocks_out = df->df_total_block_count;
	arg->data_blocks_out = df->df_data_block_count;

	if (df->df_header_flags & INCFS_FILE_COMPLETE) {
		pr_debug("File marked full, fast get_filled_blocks");
+3 −0
Original line number Diff line number Diff line
@@ -1444,6 +1444,9 @@ static long ioctl_get_filled_blocks(struct file *f, void __user *arg)
	if (!df)
		return -EINVAL;

	if ((uintptr_t)f->private_data != CAN_FILL)
		return -EPERM;

	if (copy_from_user(&args, args_usr_ptr, sizeof(args)) > 0)
		return -EINVAL;

+3 −0
Original line number Diff line number Diff line
@@ -321,6 +321,9 @@ struct incfs_get_filled_blocks_args {
	/* Actual number of blocks in file */
	__u32 total_blocks_out;

	/* The  number of data blocks in file */
	__u32 data_blocks_out;

	/* Number of bytes written to range buffer */
	__u32 range_buffer_size_out;

+52 −0
Original line number Diff line number Diff line
@@ -2189,12 +2189,29 @@ static int validate_ranges(const char *mount_dir, struct test_file *file)
	int error = TEST_SUCCESS;
	int i;
	int range_cnt;
	int cmd_fd = -1;
	struct incfs_permit_fill permit_fill;

	fd = open(filename, O_RDONLY);
	free(filename);
	if (fd <= 0)
		return TEST_FAILURE;

	error = ioctl(fd, INCFS_IOC_GET_FILLED_BLOCKS, &fba);
	if (error != -1 || errno != EPERM) {
		ksft_print_msg("INCFS_IOC_GET_FILLED_BLOCKS not blocked\n");
		error = -EPERM;
		goto out;
	}

	cmd_fd = open_commands_file(mount_dir);
	permit_fill.file_descriptor = fd;
	if (ioctl(cmd_fd, INCFS_IOC_PERMIT_FILL, &permit_fill)) {
		print_error("INCFS_IOC_PERMIT_FILL failed");
		return -EPERM;
		goto out;
	}

	error = ioctl(fd, INCFS_IOC_GET_FILLED_BLOCKS, &fba);
	if (error && errno != ERANGE)
		goto out;
@@ -2212,6 +2229,11 @@ static int validate_ranges(const char *mount_dir, struct test_file *file)
		goto out;
	}

	if (fba.data_blocks_out != block_cnt) {
		error = -EINVAL;
		goto out;
	}

	range_cnt = (block_cnt + 3) / 4;
	if (range_cnt > 128)
		range_cnt = 128;
@@ -2282,6 +2304,7 @@ static int validate_ranges(const char *mount_dir, struct test_file *file)

out:
	close(fd);
	close(cmd_fd);
	return error;
}

@@ -2392,6 +2415,7 @@ static int emit_partial_test_file_hash(char *mount_dir, struct test_file *file)

static int validate_hash_ranges(const char *mount_dir, struct test_file *file)
{
	int block_cnt = 1 + (file->size - 1) / INCFS_DATA_FILE_BLOCK_SIZE;
	char *filename = concat_file_name(mount_dir, file->name);
	int fd;
	struct incfs_filled_range ranges[128];
@@ -2402,6 +2426,8 @@ static int validate_hash_ranges(const char *mount_dir, struct test_file *file)
	int error = TEST_SUCCESS;
	int file_blocks = (file->size + INCFS_DATA_FILE_BLOCK_SIZE - 1) /
			  INCFS_DATA_FILE_BLOCK_SIZE;
	int cmd_fd = -1;
	struct incfs_permit_fill permit_fill;

	if (file->size <= 4096 / 32 * 4096)
		return 0;
@@ -2411,10 +2437,35 @@ static int validate_hash_ranges(const char *mount_dir, struct test_file *file)
	if (fd <= 0)
		return TEST_FAILURE;

	error = ioctl(fd, INCFS_IOC_GET_FILLED_BLOCKS, &fba);
	if (error != -1 || errno != EPERM) {
		ksft_print_msg("INCFS_IOC_GET_FILLED_BLOCKS not blocked\n");
		error = -EPERM;
		goto out;
	}

	cmd_fd = open_commands_file(mount_dir);
	permit_fill.file_descriptor = fd;
	if (ioctl(cmd_fd, INCFS_IOC_PERMIT_FILL, &permit_fill)) {
		print_error("INCFS_IOC_PERMIT_FILL failed");
		return -EPERM;
		goto out;
	}

	error = ioctl(fd, INCFS_IOC_GET_FILLED_BLOCKS, &fba);
	if (error)
		goto out;

	if (fba.total_blocks_out <= block_cnt) {
		error = -EINVAL;
		goto out;
	}

	if (fba.data_blocks_out != block_cnt) {
		error = -EINVAL;
		goto out;
	}

	if (fba.range_buffer_size_out != sizeof(struct incfs_filled_range)) {
		error = -EINVAL;
		goto out;
@@ -2427,6 +2478,7 @@ static int validate_hash_ranges(const char *mount_dir, struct test_file *file)
	}

out:
	close(cmd_fd);
	close(fd);
	return error;
}