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: Paul Lawrence <paullawrence@google.com> Change-Id: I126a8cf711e56592479093e9aadbfd0e7f700752
This commit is contained in:
parent
759d52ee9e
commit
e251cfe620
4 changed files with 59 additions and 0 deletions
|
@ -436,6 +436,7 @@ int incfs_get_filled_blocks(struct data_file *df,
|
||||||
if (end_index > df->df_total_block_count)
|
if (end_index > df->df_total_block_count)
|
||||||
end_index = df->df_total_block_count;
|
end_index = df->df_total_block_count;
|
||||||
arg->total_blocks_out = 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) {
|
if (df->df_header_flags & INCFS_FILE_COMPLETE) {
|
||||||
pr_debug("File marked full, fast get_filled_blocks");
|
pr_debug("File marked full, fast get_filled_blocks");
|
||||||
|
|
|
@ -1444,6 +1444,9 @@ static long ioctl_get_filled_blocks(struct file *f, void __user *arg)
|
||||||
if (!df)
|
if (!df)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
if ((uintptr_t)f->private_data != CAN_FILL)
|
||||||
|
return -EPERM;
|
||||||
|
|
||||||
if (copy_from_user(&args, args_usr_ptr, sizeof(args)) > 0)
|
if (copy_from_user(&args, args_usr_ptr, sizeof(args)) > 0)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
|
|
@ -321,6 +321,9 @@ struct incfs_get_filled_blocks_args {
|
||||||
/* Actual number of blocks in file */
|
/* Actual number of blocks in file */
|
||||||
__u32 total_blocks_out;
|
__u32 total_blocks_out;
|
||||||
|
|
||||||
|
/* The number of data blocks in file */
|
||||||
|
__u32 data_blocks_out;
|
||||||
|
|
||||||
/* Number of bytes written to range buffer */
|
/* Number of bytes written to range buffer */
|
||||||
__u32 range_buffer_size_out;
|
__u32 range_buffer_size_out;
|
||||||
|
|
||||||
|
|
|
@ -2189,12 +2189,29 @@ static int validate_ranges(const char *mount_dir, struct test_file *file)
|
||||||
int error = TEST_SUCCESS;
|
int error = TEST_SUCCESS;
|
||||||
int i;
|
int i;
|
||||||
int range_cnt;
|
int range_cnt;
|
||||||
|
int cmd_fd = -1;
|
||||||
|
struct incfs_permit_fill permit_fill;
|
||||||
|
|
||||||
fd = open(filename, O_RDONLY);
|
fd = open(filename, O_RDONLY);
|
||||||
free(filename);
|
free(filename);
|
||||||
if (fd <= 0)
|
if (fd <= 0)
|
||||||
return TEST_FAILURE;
|
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);
|
error = ioctl(fd, INCFS_IOC_GET_FILLED_BLOCKS, &fba);
|
||||||
if (error && errno != ERANGE)
|
if (error && errno != ERANGE)
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -2212,6 +2229,11 @@ static int validate_ranges(const char *mount_dir, struct test_file *file)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fba.data_blocks_out != block_cnt) {
|
||||||
|
error = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
range_cnt = (block_cnt + 3) / 4;
|
range_cnt = (block_cnt + 3) / 4;
|
||||||
if (range_cnt > 128)
|
if (range_cnt > 128)
|
||||||
range_cnt = 128;
|
range_cnt = 128;
|
||||||
|
@ -2282,6 +2304,7 @@ static int validate_ranges(const char *mount_dir, struct test_file *file)
|
||||||
|
|
||||||
out:
|
out:
|
||||||
close(fd);
|
close(fd);
|
||||||
|
close(cmd_fd);
|
||||||
return error;
|
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)
|
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);
|
char *filename = concat_file_name(mount_dir, file->name);
|
||||||
int fd;
|
int fd;
|
||||||
struct incfs_filled_range ranges[128];
|
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 error = TEST_SUCCESS;
|
||||||
int file_blocks = (file->size + INCFS_DATA_FILE_BLOCK_SIZE - 1) /
|
int file_blocks = (file->size + INCFS_DATA_FILE_BLOCK_SIZE - 1) /
|
||||||
INCFS_DATA_FILE_BLOCK_SIZE;
|
INCFS_DATA_FILE_BLOCK_SIZE;
|
||||||
|
int cmd_fd = -1;
|
||||||
|
struct incfs_permit_fill permit_fill;
|
||||||
|
|
||||||
if (file->size <= 4096 / 32 * 4096)
|
if (file->size <= 4096 / 32 * 4096)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -2411,10 +2437,35 @@ static int validate_hash_ranges(const char *mount_dir, struct test_file *file)
|
||||||
if (fd <= 0)
|
if (fd <= 0)
|
||||||
return TEST_FAILURE;
|
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);
|
error = ioctl(fd, INCFS_IOC_GET_FILLED_BLOCKS, &fba);
|
||||||
if (error)
|
if (error)
|
||||||
goto out;
|
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)) {
|
if (fba.range_buffer_size_out != sizeof(struct incfs_filled_range)) {
|
||||||
error = -EINVAL;
|
error = -EINVAL;
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -2427,6 +2478,7 @@ static int validate_hash_ranges(const char *mount_dir, struct test_file *file)
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
close(cmd_fd);
|
||||||
close(fd);
|
close(fd);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue