ANDROID: fuse-bpf: Use stored bpf for create_open

create_open would always take its parent directory's bpf for the created
object. Modify to use the bpf stored in fuse_dentry which is set by
lookup.

Bug: 291705489
Test: fuse_test passes, adb push file /sdcard/Android/data works
Signed-off-by: Paul Lawrence <paullawrence@google.com>
Change-Id: I0a1ea2a291a8fdf67923f1827176b2ea96bd4c2d
This commit is contained in:
Paul Lawrence 2023-07-25 11:20:11 -07:00
parent 74d9daa59a
commit 295e779e8f
3 changed files with 73 additions and 8 deletions

View File

@ -208,6 +208,7 @@ int fuse_create_open_backing(
struct file *file, unsigned int flags, umode_t mode)
{
struct fuse_inode *dir_fuse_inode = get_fuse_inode(dir);
struct fuse_dentry *fuse_entry = get_fuse_dentry(entry);
struct fuse_dentry *dir_fuse_dentry = get_fuse_dentry(entry->d_parent);
struct dentry *backing_dentry = NULL;
struct inode *inode = NULL;
@ -239,19 +240,19 @@ int fuse_create_open_backing(
if (err)
goto out;
if (get_fuse_dentry(entry)->backing_path.dentry)
path_put(&get_fuse_dentry(entry)->backing_path);
get_fuse_dentry(entry)->backing_path = (struct path) {
if (fuse_entry->backing_path.dentry)
path_put(&fuse_entry->backing_path);
fuse_entry->backing_path = (struct path) {
.mnt = dir_fuse_dentry->backing_path.mnt,
.dentry = backing_dentry,
};
path_get(&get_fuse_dentry(entry)->backing_path);
path_get(&fuse_entry->backing_path);
if (d_inode)
target_nodeid = get_fuse_inode(d_inode)->nodeid;
inode = fuse_iget_backing(dir->i_sb, target_nodeid,
get_fuse_dentry(entry)->backing_path.dentry->d_inode);
fuse_entry->backing_path.dentry->d_inode);
if (!inode) {
err = -EIO;
goto out;
@ -259,9 +260,8 @@ int fuse_create_open_backing(
if (get_fuse_inode(inode)->bpf)
bpf_prog_put(get_fuse_inode(inode)->bpf);
get_fuse_inode(inode)->bpf = dir_fuse_inode->bpf;
if (get_fuse_inode(inode)->bpf)
bpf_prog_inc(dir_fuse_inode->bpf);
get_fuse_inode(inode)->bpf = fuse_entry->bpf;
fuse_entry->bpf = NULL;
newent = d_splice_alias(inode, entry);
if (IS_ERR(newent)) {

View File

@ -2009,6 +2009,44 @@ static int bpf_test_lookup_postfilter(const char *mount_dir)
return result;
}
/**
* Test that a file made via create_and_open correctly gets the bpf assigned
* from the negative lookup
* bpf blocks file open, but also removes itself from children
* This test will fail if the 'remove' is unsuccessful
*/
static int bpf_test_create_and_remove_bpf(const char *mount_dir)
{
const char *file = "file";
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_create_remove", &bpf_fd,
NULL, NULL), 0);
TESTEQUAL(mount_fuse_no_init(mount_dir, bpf_fd, src_fd, &fuse_dev), 0);
TEST(fd = s_creat(s_path(s(mount_dir), s(file)), 0777),
fd != -1);
TEST(fd2 = s_open(s_path(s(mount_dir), s(file)), 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;
@ -2136,6 +2174,7 @@ int main(int argc, char *argv[])
MAKE_TEST(bpf_test_revalidate_handle_backing_fd),
MAKE_TEST(bpf_test_lookup_postfilter),
MAKE_TEST(flock_test),
MAKE_TEST(bpf_test_create_and_remove_bpf),
};
#undef MAKE_TEST

View File

@ -505,3 +505,29 @@ int lookuppostfilter_test(struct fuse_bpf_args *fa)
return FUSE_BPF_BACKING;
}
}
SEC("test_create_remove")
int createremovebpf_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_OPEN | FUSE_PREFILTER: {
return -EIO;
}
default:
return FUSE_BPF_BACKING;
}
}