Skip to content

Commit d42eb23

Browse files
author
Miklos Szeredi
committed
fuse: don't require /dev/fuse fd to be kept open during mount
With the new mount API the sequence of syscalls would be: fs_fd = fsopen("fuse", 0); snprintf(opt, sizeof(opt), "%i", devfd); fsconfig(fs_fd, FSCONFIG_SET_STRING, "fd", opt, 0); /* ... */ fsconfig(fs_fd, FSCONFIG_CMD_CREATE, 0, 0, 0); Current mount code just stores the value of devfd in the fs_context and uses it in during FSCONFIG_CMD_CREATE, which is inelegant. Instead grab a reference to the underlying fuse_dev, and use that during the filesystem creation. Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
1 parent e9bf385 commit d42eb23

2 files changed

Lines changed: 34 additions & 27 deletions

File tree

fs/fuse/fuse_i.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -606,13 +606,11 @@ static inline bool fuse_is_inode_dax_mode(enum fuse_dax_mode mode)
606606
}
607607

608608
struct fuse_fs_context {
609-
int fd;
610-
struct file *file;
609+
struct fuse_dev *fud;
611610
unsigned int rootmode;
612611
kuid_t user_id;
613612
kgid_t group_id;
614613
bool is_bdev:1;
615-
bool fd_present:1;
616614
bool rootmode_present:1;
617615
bool user_id_present:1;
618616
bool group_id_present:1;

fs/fuse/inode.c

Lines changed: 33 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -803,6 +803,29 @@ static const struct fs_parameter_spec fuse_fs_parameters[] = {
803803
{}
804804
};
805805

806+
static int fuse_opt_fd(struct fs_context *fsc, int fd)
807+
{
808+
struct fuse_fs_context *ctx = fsc->fs_private;
809+
struct file *file __free(fput) = fget(fd);
810+
811+
if (!file)
812+
return -EBADF;
813+
814+
if (file->f_op != &fuse_dev_operations)
815+
return invalfc(fsc, "fd is not a fuse device");
816+
/*
817+
* Require mount to happen from the same user namespace which
818+
* opened /dev/fuse to prevent potential attacks.
819+
*/
820+
if (file->f_cred->user_ns != fsc->user_ns)
821+
return invalfc(fsc, "wrong user namespace for fuse device");
822+
823+
ctx->fud = file->private_data;
824+
refcount_inc(&ctx->fud->ref);
825+
826+
return 0;
827+
}
828+
806829
static int fuse_parse_param(struct fs_context *fsc, struct fs_parameter *param)
807830
{
808831
struct fs_parse_result result;
@@ -842,9 +865,7 @@ static int fuse_parse_param(struct fs_context *fsc, struct fs_parameter *param)
842865
return 0;
843866

844867
case OPT_FD:
845-
ctx->fd = result.uint_32;
846-
ctx->fd_present = true;
847-
break;
868+
return fuse_opt_fd(fsc, result.uint_32);
848869

849870
case OPT_ROOTMODE:
850871
if (!fuse_valid_type(result.uint_32))
@@ -907,6 +928,8 @@ static void fuse_free_fsc(struct fs_context *fsc)
907928
struct fuse_fs_context *ctx = fsc->fs_private;
908929

909930
if (ctx) {
931+
if (ctx->fud)
932+
fuse_dev_put(ctx->fud);
910933
kfree(ctx->subtype);
911934
kfree(ctx);
912935
}
@@ -1849,7 +1872,7 @@ EXPORT_SYMBOL_GPL(fuse_init_fs_context_submount);
18491872

18501873
int fuse_fill_super_common(struct super_block *sb, struct fuse_fs_context *ctx)
18511874
{
1852-
struct fuse_dev *fud = ctx->file ? fuse_file_to_fud(ctx->file) : NULL;
1875+
struct fuse_dev *fud = ctx->fud;
18531876
struct fuse_mount *fm = get_fuse_mount_super(sb);
18541877
struct fuse_conn *fc = fm->fc;
18551878
struct inode *root;
@@ -1950,18 +1973,10 @@ static int fuse_fill_super(struct super_block *sb, struct fs_context *fsc)
19501973
struct fuse_mount *fm;
19511974
int err;
19521975

1953-
if (!ctx->file || !ctx->rootmode_present ||
1976+
if (!ctx->fud || !ctx->rootmode_present ||
19541977
!ctx->user_id_present || !ctx->group_id_present)
19551978
return -EINVAL;
19561979

1957-
/*
1958-
* Require mount to happen from the same user namespace which
1959-
* opened /dev/fuse to prevent potential attacks.
1960-
*/
1961-
if ((ctx->file->f_op != &fuse_dev_operations) ||
1962-
(ctx->file->f_cred->user_ns != sb->s_user_ns))
1963-
return -EINVAL;
1964-
19651980
err = fuse_fill_super_common(sb, ctx);
19661981
if (err)
19671982
return err;
@@ -1982,14 +1997,14 @@ static int fuse_set_no_super(struct super_block *sb, struct fs_context *fsc)
19821997

19831998
static int fuse_test_super(struct super_block *sb, struct fs_context *fsc)
19841999
{
2000+
struct fuse_dev *fud = fsc->sget_key;
19852001

1986-
return fsc->sget_key == get_fuse_conn_super(sb);
2002+
return fuse_dev_fc_get(fud) == get_fuse_conn_super(sb);
19872003
}
19882004

19892005
static int fuse_get_tree(struct fs_context *fsc)
19902006
{
19912007
struct fuse_fs_context *ctx = fsc->fs_private;
1992-
struct fuse_dev *fud;
19932008
struct fuse_conn *fc;
19942009
struct fuse_mount *fm;
19952010
struct super_block *sb;
@@ -2010,9 +2025,6 @@ static int fuse_get_tree(struct fs_context *fsc)
20102025

20112026
fsc->s_fs_info = fm;
20122027

2013-
if (ctx->fd_present)
2014-
ctx->file = fget(ctx->fd);
2015-
20162028
if (IS_ENABLED(CONFIG_BLOCK) && ctx->is_bdev) {
20172029
err = get_tree_bdev(fsc, fuse_fill_super);
20182030
goto out;
@@ -2022,16 +2034,15 @@ static int fuse_get_tree(struct fs_context *fsc)
20222034
* (found by device name), normal fuse mounts can't
20232035
*/
20242036
err = -EINVAL;
2025-
if (!ctx->file)
2037+
if (!ctx->fud)
20262038
goto out;
20272039

20282040
/*
20292041
* Allow creating a fuse mount with an already initialized fuse
20302042
* connection
20312043
*/
2032-
fud = __fuse_get_dev(ctx->file);
2033-
if (ctx->file->f_op == &fuse_dev_operations && fud) {
2034-
fsc->sget_key = fud->fc;
2044+
if (fuse_dev_fc_get(ctx->fud)) {
2045+
fsc->sget_key = ctx->fud;
20352046
sb = sget_fc(fsc, fuse_test_super, fuse_set_no_super);
20362047
err = PTR_ERR_OR_ZERO(sb);
20372048
if (!IS_ERR(sb))
@@ -2042,8 +2053,6 @@ static int fuse_get_tree(struct fs_context *fsc)
20422053
out:
20432054
if (fsc->s_fs_info)
20442055
fuse_mount_destroy(fm);
2045-
if (ctx->file)
2046-
fput(ctx->file);
20472056
return err;
20482057
}
20492058

0 commit comments

Comments
 (0)