UPSTREAM: ANDROID: fuse-bpf: Avoid reusing uint64_t for file

This moves the backing/fd files to their own space, instead of reusing
the userspace provided fds.

Bug: 222619123
Test: fuse_test passes, on cuttlefish CtsCameraTestCases passes
Signed-off-by: Daniel Rosenberg <drosen@google.com>
Change-Id: I5d3b1ea8299f249ef5adc1ce2b7f45404a041208
This commit is contained in:
Daniel Rosenberg 2022-03-08 17:23:14 -08:00 • committed by Alexander Martinz
commit 66d1fc6d06
No known key found for this signature in database
GPG key ID: CF15BDD9A321A9B2
6 changed files with 34 additions and 30 deletions

View file

@ -874,8 +874,8 @@ int fuse_lookup_initialize(struct fuse_args *fa, struct fuse_lookup_io *fli,
.value = &fli->feo,
},
.out_args[1] = (struct fuse_arg) {
.size = sizeof(fli->febo),
.value = &fli->febo,
.size = sizeof(fli->feb.out),
.value = &fli->feb.out,
},
};
@ -917,6 +917,7 @@ struct dentry *fuse_lookup_finalize(struct fuse_args *fa, struct inode *dir,
struct inode *inode, *backing_inode;
struct fuse_entry_out *feo = fa->out_args[0].value;
struct fuse_entry_bpf_out *febo = fa->out_args[1].value;
struct fuse_entry_bpf *feb = container_of(febo, struct fuse_entry_bpf, out);
fd = get_fuse_dentry(entry);
if (!fd)
@ -952,7 +953,7 @@ struct dentry *fuse_lookup_finalize(struct fuse_args *fa, struct inode *dir,
break;
case FUSE_ACTION_REPLACE: {
struct file *bpf_file = (struct file*) febo->bpf_fd;
struct file *bpf_file = feb->bpf_file;
struct bpf_prog *bpf_prog = ERR_PTR(-EINVAL);
if (bpf_file && !IS_ERR(bpf_file))
@ -985,7 +986,7 @@ struct dentry *fuse_lookup_finalize(struct fuse_args *fa, struct inode *dir,
struct file *backing_file;
fc = get_fuse_mount(dir)->fc;
backing_file = (struct file *) febo->backing_fd;
backing_file = feb->backing_file;
if (!backing_file || IS_ERR(backing_file))
return ERR_PTR(-EIO);

View file

@ -1964,11 +1964,12 @@ static ssize_t fuse_dev_do_write(struct fuse_dev *fud,
req->args->out_args[1].size == sizeof(struct fuse_entry_bpf_out)) {
struct fuse_entry_bpf_out *febo = (struct fuse_entry_bpf_out *)
req->args->out_args[1].value;
struct fuse_entry_bpf *feb = container_of(febo, struct fuse_entry_bpf, out);
if (febo->backing_action == FUSE_ACTION_REPLACE)
febo->backing_fd = (uint64_t) fget(febo->backing_fd);
feb->backing_file = fget(febo->backing_fd);
if (febo->bpf_action == FUSE_ACTION_REPLACE)
febo->bpf_fd = (uint64_t) fget(febo->bpf_fd);
feb->bpf_file = fget(febo->bpf_fd);
}
spin_lock(&fpq->lock);

View file

@ -196,7 +196,7 @@ static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags)
else if (time_before64(fuse_dentry_time(entry), get_jiffies_64()) ||
(flags & LOOKUP_REVAL)) {
struct fuse_entry_out outarg;
struct fuse_entry_bpf_out bpf_outarg;
struct fuse_entry_bpf bpf_arg;
FUSE_ARGS(args);
struct fuse_forget_link *forget;
u64 attr_version;
@ -234,7 +234,7 @@ static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags)
parent = dget_parent(entry);
fuse_lookup_init(fm->fc, &args, get_node_id(d_inode(parent)),
&entry->d_name, &outarg, &bpf_outarg);
&entry->d_name, &outarg, &bpf_arg.out);
ret = fuse_simple_request(fm, &args);
dput(parent);
@ -243,15 +243,15 @@ static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags)
* change the backing file ever, so not sure what is correct
* here yet, especially as we can't return an error to user
*/
if (bpf_outarg.backing_action == FUSE_ACTION_REPLACE) {
struct file *file = (struct file *) bpf_outarg.backing_fd;
if (bpf_arg.out.backing_action == FUSE_ACTION_REPLACE) {
struct file *file = bpf_arg.backing_file;
if (file && !IS_ERR(file))
fput(file);
}
if (bpf_outarg.bpf_action == FUSE_ACTION_REPLACE) {
struct file *file = (struct file *) bpf_outarg.bpf_fd;
if (bpf_arg.out.bpf_action == FUSE_ACTION_REPLACE) {
struct file *file = bpf_arg.bpf_file;
if (file && !IS_ERR(file))
fput(file);
@ -498,12 +498,12 @@ bool fuse_invalid_attr(struct fuse_attr *attr)
int fuse_lookup_name(struct super_block *sb, u64 nodeid, const struct qstr *name,
struct fuse_entry_out *outarg,
struct fuse_entry_bpf_out *bpf_outarg,
struct dentry *entry,
struct inode **inode)
{
struct fuse_mount *fm = get_fuse_mount_super(sb);
FUSE_ARGS(args);
struct fuse_entry_bpf bpf_arg = {0};
struct fuse_forget_link *forget;
u64 attr_version;
int err;
@ -521,11 +521,11 @@ int fuse_lookup_name(struct super_block *sb, u64 nodeid, const struct qstr *name
attr_version = fuse_get_attr_version(fm->fc);
fuse_lookup_init(fm->fc, &args, nodeid, name, outarg, bpf_outarg);
fuse_lookup_init(fm->fc, &args, nodeid, name, outarg, &bpf_arg.out);
err = fuse_simple_request(fm, &args);
#ifdef CONFIG_FUSE_BPF
if (err == sizeof(*bpf_outarg)) {
if (err == sizeof(bpf_arg.out)) {
/* TODO Make sure this handles invalid handles */
/* TODO Do we need the same code in revalidate */
struct file *backing_file;
@ -536,20 +536,20 @@ int fuse_lookup_name(struct super_block *sb, u64 nodeid, const struct qstr *name
goto out_queue_forget;
err = -EINVAL;
if (bpf_outarg->backing_action != FUSE_ACTION_REPLACE)
if (bpf_arg.out.backing_action != FUSE_ACTION_REPLACE)
goto out_queue_forget;
backing_file = (struct file *) bpf_outarg->backing_fd;
backing_file = bpf_arg.backing_file;
if (!backing_file || IS_ERR(backing_file))
goto out_queue_forget;
backing_inode = backing_file->f_inode;
*inode = fuse_iget_backing(sb, backing_inode);
if (!*inode)
goto bpf_outarg_out;
goto bpf_arg_out;
if (bpf_outarg->bpf_action == FUSE_ACTION_REPLACE) {
struct file *bpf_file = (struct file*) bpf_outarg->bpf_fd;
if (bpf_arg.out.bpf_action == FUSE_ACTION_REPLACE) {
struct file *bpf_file = bpf_arg.bpf_file;
struct bpf_prog *bpf_prog = ERR_PTR(-EINVAL);
if (bpf_file && !IS_ERR(bpf_file))
@ -559,7 +559,7 @@ int fuse_lookup_name(struct super_block *sb, u64 nodeid, const struct qstr *name
iput(*inode);
*inode = NULL;
err = PTR_ERR(bpf_prog);
goto bpf_outarg_out;
goto bpf_arg_out;
}
get_fuse_inode(*inode)->bpf = bpf_prog;
}
@ -567,7 +567,7 @@ int fuse_lookup_name(struct super_block *sb, u64 nodeid, const struct qstr *name
get_fuse_dentry(entry)->backing_path = backing_file->f_path;
path_get(&get_fuse_dentry(entry)->backing_path);
bpf_outarg_out:
bpf_arg_out:
fput(backing_file);
} else
#endif
@ -608,7 +608,6 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
{
int err;
struct fuse_entry_out outarg;
struct fuse_entry_bpf_out bpf_outarg = {0};
struct inode *inode;
struct dentry *newent;
bool outarg_valid = true;
@ -630,7 +629,7 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
locked = fuse_lock_inode(dir);
err = fuse_lookup_name(dir->i_sb, get_node_id(dir), &entry->d_name,
&outarg, &bpf_outarg, entry, &inode);
&outarg, entry, &inode);
fuse_unlock_inode(dir, locked);
if (err == -ENOENT) {
outarg_valid = false;

View file

@ -949,7 +949,6 @@ struct inode *fuse_iget(struct super_block *sb, u64 nodeid,
int fuse_lookup_name(struct super_block *sb, u64 nodeid, const struct qstr *name,
struct fuse_entry_out *outarg,
struct fuse_entry_bpf_out *bpf_outarg,
struct dentry *entry, struct inode **inode);
/**
@ -1519,7 +1518,7 @@ void *fuse_file_fallocate_finalize(struct fuse_args *fa,
struct fuse_lookup_io {
struct fuse_entry_out feo;
struct fuse_entry_bpf_out febo;
struct fuse_entry_bpf feb;
};
int fuse_lookup_initialize(struct fuse_args *fa, struct fuse_lookup_io *feo,

View file

@ -933,14 +933,13 @@ static struct dentry *fuse_get_dentry(struct super_block *sb,
inode = ilookup5(sb, handle->nodeid, fuse_inode_eq, &fii);
if (!inode) {
struct fuse_entry_out outarg;
struct fuse_entry_bpf_out bpf_outarg;
const struct qstr name = QSTR_INIT(".", 1);
if (!fc->export_support)
goto out_err;
err = fuse_lookup_name(sb, handle->nodeid, &name, &outarg,
&bpf_outarg, NULL, &inode);
NULL, &inode);
if (err && err != -ENOENT)
goto out_err;
if (err || !inode) {
@ -1034,7 +1033,6 @@ static struct dentry *fuse_get_parent(struct dentry *child)
struct inode *inode;
struct dentry *parent;
struct fuse_entry_out outarg;
struct fuse_entry_bpf_out bpf_outarg;
const struct qstr name = QSTR_INIT("..", 2);
int err;
@ -1042,7 +1040,7 @@ static struct dentry *fuse_get_parent(struct dentry *child)
return ERR_PTR(-ESTALE);
err = fuse_lookup_name(child_inode->i_sb, get_node_id(child_inode),
&name, &outarg, &bpf_outarg, NULL, &inode);
&name, &outarg, NULL, &inode);
if (err) {
if (err == -ENOENT)
return ERR_PTR(-ESTALE);

View file

@ -527,6 +527,12 @@ struct fuse_entry_bpf_out {
uint64_t bpf_fd;
};
struct fuse_entry_bpf {
struct fuse_entry_bpf_out out;
struct file *backing_file;
struct file *bpf_file;
};
struct fuse_forget_in {
uint64_t nlookup;
};