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
Git-commit: ecd6f86bed
Git-repo: https://android.googlesource.com/kernel/common/
Signed-off-by: Sayali Lokhande <sayalil@codeaurora.org>
tirimbino
Paul Lawrence 5 years ago committed by Blagovest Kolenichev
parent c7871f201b
commit d39fc35928
  1. 1
      fs/incfs/data_mgmt.c
  2. 3
      fs/incfs/vfs.c
  3. 3
      include/uapi/linux/incrementalfs.h
  4. 52
      tools/testing/selftests/filesystems/incfs/incfs_test.c

@ -437,6 +437,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");

@ -1447,6 +1447,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;

@ -328,6 +328,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;

@ -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 @@ failure:
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;
}

Loading…
Cancel
Save