@@ -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+
806829static 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
18501873int 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
19831998static 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
19892005static 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)
20422053out :
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