ANDROID: fuse-bpf: Get correct inode in mkdir

We were getting the inode with the parent inode info
Also change variable names to remove confusion
Also set bpf correctly in new inode

Bug: 293838958
Test: fuse_test, atest ScopedStorageDeviceTest,
	atest CtsScopedStorageHostTest
Change-Id: I0b6a6951599e0d211afd2243daacb98679503448
Signed-off-by: Paul Lawrence <paullawrence@google.com>
This commit is contained in:
Paul Lawrence 2023-08-29 11:17:44 -07:00
parent 0fdb44964c
commit 8fb9de0877
3 changed files with 73 additions and 11 deletions

View File

@ -1446,32 +1446,34 @@ int fuse_mkdir_initialize(
int fuse_mkdir_backing(
struct fuse_bpf_args *fa,
struct inode *dir, struct dentry *entry, umode_t mode)
struct inode *dir_inode, struct dentry *entry, umode_t mode)
{
int err = 0;
const struct fuse_mkdir_in *fmi = fa->in_args[0].value;
struct fuse_inode *fuse_inode = get_fuse_inode(dir);
struct inode *backing_inode = fuse_inode->backing_inode;
struct fuse_inode *dir_fuse_inode = get_fuse_inode(dir_inode);
struct inode *dir_backing_inode = dir_fuse_inode->backing_inode;
struct path backing_path = {};
struct inode *inode = NULL;
struct dentry *d;
//TODO Actually deal with changing the backing entry in mkdir
get_fuse_backing_path(entry, &backing_path);
if (!backing_path.dentry)
return -EBADF;
inode_lock_nested(backing_inode, I_MUTEX_PARENT);
inode_lock_nested(dir_backing_inode, I_MUTEX_PARENT);
mode = fmi->mode;
if (!IS_POSIXACL(backing_inode))
if (!IS_POSIXACL(dir_backing_inode))
mode &= ~fmi->umask;
err = vfs_mkdir(&init_user_ns, backing_inode, backing_path.dentry, mode);
err = vfs_mkdir(&init_user_ns, dir_backing_inode, backing_path.dentry,
mode);
if (err)
goto out;
if (d_really_is_negative(backing_path.dentry) ||
unlikely(d_unhashed(backing_path.dentry))) {
d = lookup_one_len(entry->d_name.name, backing_path.dentry->d_parent,
entry->d_name.len);
struct dentry *d = lookup_one_len(entry->d_name.name,
backing_path.dentry->d_parent,
entry->d_name.len);
if (IS_ERR(d)) {
err = PTR_ERR(d);
goto out;
@ -1479,14 +1481,19 @@ int fuse_mkdir_backing(
dput(backing_path.dentry);
backing_path.dentry = d;
}
inode = fuse_iget_backing(dir->i_sb, fuse_inode->nodeid, backing_inode);
inode = fuse_iget_backing(dir_inode->i_sb, 0,
backing_path.dentry->d_inode);
if (IS_ERR(inode)) {
err = PTR_ERR(inode);
goto out;
}
d_instantiate(entry, inode);
if (get_fuse_inode(inode)->bpf)
bpf_prog_put(get_fuse_inode(inode)->bpf);
get_fuse_inode(inode)->bpf = get_fuse_dentry(entry)->bpf;
get_fuse_dentry(entry)->bpf = NULL;
out:
inode_unlock(backing_inode);
inode_unlock(dir_backing_inode);
path_put(&backing_path);
return err;
}

View File

@ -2047,6 +2047,38 @@ static int bpf_test_create_and_remove_bpf(const char *mount_dir)
return result;
}
static int bpf_test_mkdir_and_remove_bpf(const char *mount_dir)
{
const char *dir = "dir";
int result = TEST_FAILURE;
int src_fd = -1;
int bpf_fd = -1;
int fuse_dev = -1;
int fd = -1;
int fd2 = -1;
TEST(src_fd = open(ft_src, O_DIRECTORY | O_RDONLY | O_CLOEXEC),
src_fd != -1);
TESTEQUAL(install_elf_bpf("test_bpf.bpf", "test_mkdir_remove", &bpf_fd,
NULL, NULL), 0);
TESTEQUAL(mount_fuse_no_init(mount_dir, bpf_fd, src_fd, &fuse_dev), 0);
TEST(fd = s_mkdir(s_path(s(mount_dir), s(dir)), 0777),
fd != -1);
TEST(fd2 = s_open(s_path(s(mount_dir), s(dir)), O_RDONLY),
fd2 != -1);
result = TEST_SUCCESS;
out:
close(fd2);
close(fd);
close(fuse_dev);
close(bpf_fd);
close(src_fd);
umount(mount_dir);
return result;
}
static void parse_range(const char *ranges, bool *run_test, size_t tests)
{
size_t i;
@ -2175,6 +2207,7 @@ int main(int argc, char *argv[])
MAKE_TEST(bpf_test_lookup_postfilter),
MAKE_TEST(flock_test),
MAKE_TEST(bpf_test_create_and_remove_bpf),
MAKE_TEST(bpf_test_mkdir_and_remove_bpf),
};
#undef MAKE_TEST

View File

@ -530,4 +530,26 @@ int createremovebpf_test(struct fuse_bpf_args *fa)
}
}
SEC("test_mkdir_remove")
int mkdirremovebpf_test(struct fuse_bpf_args *fa)
{
switch (fa->opcode) {
case FUSE_LOOKUP | FUSE_PREFILTER: {
return FUSE_BPF_BACKING | FUSE_BPF_POST_FILTER;
}
case FUSE_LOOKUP | FUSE_POSTFILTER: {
struct fuse_entry_bpf_out *febo = fa->out_args[1].value;
febo->bpf_action = FUSE_ACTION_REMOVE;
return 0;
}
case FUSE_OPENDIR | FUSE_PREFILTER: {
return -EIO;
}
default:
return FUSE_BPF_BACKING;
}
}