mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 03:40:35 +09:00
ANDROID: Incremental fs: Add FS_IOC_GETFLAGS
Add FS_IOC_GETFLAGS ioctl to incfs. Currently this will only get the S_VERITY flag. Bug: 160634504 Test: incfs_test passes Signed-off-by: Paul Lawrence <paullawrence@google.com> Change-Id: Id79add0db0d66f604ca0f222fe5faec91450ade5
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/blkdev.h>
|
||||
#include <linux/compat.h>
|
||||
#include <linux/file.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/fs_stack.h>
|
||||
@@ -44,6 +45,11 @@ static int file_release(struct inode *inode, struct file *file);
|
||||
static int read_single_page(struct file *f, struct page *page);
|
||||
static long dispatch_ioctl(struct file *f, unsigned int req, unsigned long arg);
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
static long incfs_compat_ioctl(struct file *file, unsigned int cmd,
|
||||
unsigned long arg);
|
||||
#endif
|
||||
|
||||
static struct inode *alloc_inode(struct super_block *sb);
|
||||
static void free_inode(struct inode *inode);
|
||||
static void evict_inode(struct inode *inode);
|
||||
@@ -109,7 +115,9 @@ const struct file_operations incfs_file_ops = {
|
||||
.splice_read = generic_file_splice_read,
|
||||
.llseek = generic_file_llseek,
|
||||
.unlocked_ioctl = dispatch_ioctl,
|
||||
.compat_ioctl = dispatch_ioctl
|
||||
#ifdef CONFIG_COMPAT
|
||||
.compat_ioctl = incfs_compat_ioctl,
|
||||
#endif
|
||||
};
|
||||
|
||||
const struct inode_operations incfs_file_inode_ops = {
|
||||
@@ -806,6 +814,13 @@ static long ioctl_get_block_count(struct file *f, void __user *arg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int incfs_ioctl_get_flags(struct file *f, void __user *arg)
|
||||
{
|
||||
u32 flags = IS_VERITY(file_inode(f)) ? FS_VERITY_FL : 0;
|
||||
|
||||
return put_user(flags, (int __user *) arg);
|
||||
}
|
||||
|
||||
static long dispatch_ioctl(struct file *f, unsigned int req, unsigned long arg)
|
||||
{
|
||||
switch (req) {
|
||||
@@ -819,11 +834,34 @@ static long dispatch_ioctl(struct file *f, unsigned int req, unsigned long arg)
|
||||
return ioctl_get_block_count(f, (void __user *)arg);
|
||||
case FS_IOC_ENABLE_VERITY:
|
||||
return incfs_ioctl_enable_verity(f, (const void __user *)arg);
|
||||
case FS_IOC_GETFLAGS:
|
||||
return incfs_ioctl_get_flags(f, (void __user *) arg);
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
static long incfs_compat_ioctl(struct file *file, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
switch (cmd) {
|
||||
case FS_IOC32_GETFLAGS:
|
||||
cmd = FS_IOC_GETFLAGS;
|
||||
break;
|
||||
case INCFS_IOC_FILL_BLOCKS:
|
||||
case INCFS_IOC_READ_FILE_SIGNATURE:
|
||||
case INCFS_IOC_GET_FILLED_BLOCKS:
|
||||
case INCFS_IOC_GET_BLOCK_COUNT:
|
||||
case FS_IOC_ENABLE_VERITY:
|
||||
break;
|
||||
default:
|
||||
return -ENOIOCTLCMD;
|
||||
}
|
||||
return dispatch_ioctl(file, cmd, (unsigned long) compat_ptr(arg));
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct dentry *dir_lookup(struct inode *dir_inode, struct dentry *dentry,
|
||||
unsigned int flags)
|
||||
{
|
||||
|
||||
@@ -35,6 +35,10 @@
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
/* Can't include uapi/linux/fs.h because it clashes with mount.h */
|
||||
#define FS_IOC_GETFLAGS _IOR('f', 1, long)
|
||||
#define FS_VERITY_FL 0x00100000 /* Verity protected inode */
|
||||
|
||||
#define TEST_FAILURE 1
|
||||
#define TEST_SUCCESS 0
|
||||
|
||||
@@ -3736,7 +3740,30 @@ out:
|
||||
return result;
|
||||
}
|
||||
|
||||
static int validate_verity(const char *mount_dir, struct test_file *file,
|
||||
static int verity_installed(const char *mount_dir, int cmd_fd, bool *installed)
|
||||
{
|
||||
int result = TEST_FAILURE;
|
||||
char *filename = NULL;
|
||||
int fd = -1;
|
||||
struct test_file *file = &get_test_files_set().files[0];
|
||||
|
||||
TESTEQUAL(emit_file(cmd_fd, NULL, file->name, &file->id, file->size,
|
||||
NULL), 0);
|
||||
TEST(filename = concat_file_name(mount_dir, file->name), filename);
|
||||
TEST(fd = open(filename, O_RDONLY | O_CLOEXEC), fd != -1);
|
||||
TESTEQUAL(ioctl(fd, FS_IOC_ENABLE_VERITY, NULL), -1);
|
||||
*installed = errno != EOPNOTSUPP;
|
||||
|
||||
result = TEST_SUCCESS;
|
||||
out:
|
||||
close(fd);
|
||||
if (filename)
|
||||
remove(filename);
|
||||
free(filename);
|
||||
return result;
|
||||
}
|
||||
|
||||
static int enable_verity(const char *mount_dir, struct test_file *file,
|
||||
EVP_PKEY *key, X509 *cert, bool use_signatures)
|
||||
{
|
||||
int result = TEST_FAILURE;
|
||||
@@ -3776,11 +3803,14 @@ static int validate_verity(const char *mount_dir, struct test_file *file,
|
||||
.digest_algorithm = 1,
|
||||
.digest_size = 32
|
||||
};
|
||||
uint64_t flags;
|
||||
|
||||
memcpy(fsverity_signed_digest.magic, "FSVerity", 8);
|
||||
|
||||
TEST(filename = concat_file_name(mount_dir, file->name), filename);
|
||||
TEST(fd = open(filename, O_RDONLY | O_CLOEXEC), fd != -1);
|
||||
TESTEQUAL(ioctl(fd, FS_IOC_GETFLAGS, &flags), 0);
|
||||
TESTEQUAL(flags & FS_VERITY_FL, 0);
|
||||
|
||||
/* First try to enable verity with random digest */
|
||||
TESTEQUAL(sign(key, cert, (void *)&fsverity_signed_digest,
|
||||
@@ -3823,10 +3853,30 @@ out:
|
||||
return result;
|
||||
}
|
||||
|
||||
static int validate_verity(const char *mount_dir, struct test_file *file)
|
||||
{
|
||||
int result = TEST_FAILURE;
|
||||
char *filename = concat_file_name(mount_dir, file->name);
|
||||
int fd = -1;
|
||||
uint64_t flags;
|
||||
|
||||
TEST(filename = concat_file_name(mount_dir, file->name), filename);
|
||||
TEST(fd = open(filename, O_RDONLY | O_CLOEXEC), fd != -1);
|
||||
TESTEQUAL(ioctl(fd, FS_IOC_GETFLAGS, &flags), 0);
|
||||
TESTEQUAL(flags & FS_VERITY_FL, FS_VERITY_FL);
|
||||
|
||||
result = TEST_SUCCESS;
|
||||
out:
|
||||
close(fd);
|
||||
free(filename);
|
||||
return result;
|
||||
}
|
||||
|
||||
static int verity_test_optional_sigs(const char *mount_dir, bool use_signatures)
|
||||
{
|
||||
int result = TEST_FAILURE;
|
||||
char *backing_dir = NULL;
|
||||
bool installed;
|
||||
int cmd_fd = -1;
|
||||
int i;
|
||||
struct test_files_set test = get_test_files_set();
|
||||
@@ -3845,6 +3895,11 @@ static int verity_test_optional_sigs(const char *mount_dir, bool use_signatures)
|
||||
TESTEQUAL(mount_fs_opt(mount_dir, backing_dir, "readahead=0", false),
|
||||
0);
|
||||
TEST(cmd_fd = open_commands_file(mount_dir), cmd_fd != -1);
|
||||
TESTEQUAL(verity_installed(mount_dir, cmd_fd, &installed), 0);
|
||||
if (!installed) {
|
||||
result = TEST_SUCCESS;
|
||||
goto out;
|
||||
}
|
||||
TEST(key = create_key(), key);
|
||||
TEST(cert = get_cert(key), cert);
|
||||
|
||||
@@ -3869,15 +3924,15 @@ static int verity_test_optional_sigs(const char *mount_dir, bool use_signatures)
|
||||
file->sig.add_data), 0);
|
||||
|
||||
TESTEQUAL(emit_partial_test_file_hash(mount_dir, file), 0);
|
||||
TESTEQUAL(enable_verity(mount_dir, file, key, cert,
|
||||
use_signatures),
|
||||
0);
|
||||
}
|
||||
|
||||
for (i = 0; i < file_num; i++)
|
||||
TESTEQUAL(validate_verity(mount_dir, &test.files[i], key, cert,
|
||||
use_signatures),
|
||||
0);
|
||||
TESTEQUAL(validate_verity(mount_dir, &test.files[i]), 0);
|
||||
|
||||
result = TEST_SUCCESS;
|
||||
|
||||
out:
|
||||
free(line);
|
||||
BIO_free(mem);
|
||||
|
||||
Reference in New Issue
Block a user