ANDROID: fuse-bpf: Correctly put backing files

Backing files were sometimes put twice before, this fixes it so backing
files sent in response to lookups are closed exactly once always

Test: fuse_test pases, Android no longer throws a double close
Bug: 273737310
Change-Id: Ifa75ffd846185cfabfd1f5bad504078d955c99ed
Signed-off-by: Paul Lawrence <paullawrence@google.com>
Signed-off-by: Alistair Delva <adelva@google.com>
This commit is contained in:
Paul Lawrence
2023-03-20 09:36:15 -07:00
committed by Treehugger Robot
parent 8e6265391e
commit fd28863aa4
2 changed files with 42 additions and 20 deletions

View File

@@ -1172,8 +1172,6 @@ int fuse_handle_backing(struct fuse_entry_bpf *feb, struct inode **backing_inode
path_put(backing_path);
*backing_path = backing_file->f_path;
path_get(backing_path);
fput(backing_file);
break;
}
@@ -1249,36 +1247,55 @@ struct dentry *fuse_lookup_finalize(struct fuse_bpf_args *fa, struct inode *dir,
struct fuse_entry_bpf *feb = container_of(febo, struct fuse_entry_bpf, out);
int error = -1;
u64 target_nodeid = 0;
struct dentry *ret;
fd = get_fuse_dentry(entry);
if (!fd)
return ERR_PTR(-EIO);
if (!fd) {
ret = ERR_PTR(-EIO);
goto out;
}
bd = fd->backing_path.dentry;
if (!bd)
return ERR_PTR(-ENOENT);
if (!bd) {
ret = ERR_PTR(-ENOENT);
goto out;
}
backing_inode = bd->d_inode;
if (!backing_inode)
return 0;
if (!backing_inode) {
ret = 0;
goto out;
}
if (d_inode)
target_nodeid = get_fuse_inode(d_inode)->nodeid;
inode = fuse_iget_backing(dir->i_sb, target_nodeid, backing_inode);
if (IS_ERR(inode))
return ERR_PTR(PTR_ERR(inode));
if (IS_ERR(inode)) {
ret = ERR_PTR(PTR_ERR(inode));
goto out;
}
error = fuse_handle_bpf_prog(feb, dir, &get_fuse_inode(inode)->bpf);
if (error)
return ERR_PTR(error);
if (error) {
ret = ERR_PTR(error);
goto out;
}
error = fuse_handle_backing(feb, &get_fuse_inode(inode)->backing_inode, &fd->backing_path);
if (error)
return ERR_PTR(error);
if (error) {
ret = ERR_PTR(error);
goto out;
}
get_fuse_inode(inode)->nodeid = feo->nodeid;
return d_splice_alias(inode, entry);
ret = d_splice_alias(inode, entry);
out:
if (feb->backing_file)
fput(feb->backing_file);
return ret;
}
int fuse_revalidate_backing(struct dentry *entry, unsigned int flags)

View File

@@ -186,8 +186,10 @@ static bool backing_data_changed(struct fuse_inode *fi, struct dentry *entry,
int err;
bool ret = true;
if (!entry)
return false;
if (!entry) {
ret = false;
goto put_backing_file;
}
get_fuse_backing_path(entry, &new_backing_path);
new_backing_inode = fi->backing_inode;
@@ -210,6 +212,9 @@ put_bpf:
put_inode:
iput(new_backing_inode);
path_put(&new_backing_path);
put_backing_file:
if (bpf_arg->backing_file)
fput(bpf_arg->backing_file);
return ret;
}
#endif
@@ -534,7 +539,7 @@ int fuse_lookup_name(struct super_block *sb, u64 nodeid, const struct qstr *name
backing_inode = backing_file->f_inode;
*inode = fuse_iget_backing(sb, outarg->nodeid, backing_inode);
if (!*inode)
goto bpf_arg_out;
goto out;
err = fuse_handle_backing(&bpf_arg,
&get_fuse_inode(*inode)->backing_inode,
@@ -545,8 +550,6 @@ int fuse_lookup_name(struct super_block *sb, u64 nodeid, const struct qstr *name
err = fuse_handle_bpf_prog(&bpf_arg, NULL, &get_fuse_inode(*inode)->bpf);
if (err)
goto out;
bpf_arg_out:
fput(backing_file);
} else
#endif
{
@@ -578,6 +581,8 @@ out_queue_forget:
out_put_forget:
kfree(forget);
out:
if (bpf_arg.backing_file)
fput(bpf_arg.backing_file);
return err;
}