summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Hajnoczi <stefanha@redhat.com>2018-06-13 05:23:04 -0400
committerMiklos Szeredi <mszeredi@redhat.com>2019-09-12 08:59:40 -0400
commit0cc2656cdb0b1f234e6d29378cb061e29d7522bc (patch)
tree131a397c92997fcfac727b37f1237b31b68c3f55
parent4388c5aac4bae5c83a2c66882043942002ba09a2 (diff)
fuse: extract fuse_fill_super_common()
fuse_fill_super() includes code to process the fd= option and link the struct fuse_dev to the fd's struct file. In virtio-fs there is no file descriptor because /dev/fuse is not used. This patch extracts fuse_fill_super_common() so that both classic fuse and virtio-fs can share the code to initialize a mount. Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
-rw-r--r--fs/fuse/fuse_i.h27
-rw-r--r--fs/fuse/inode.c112
2 files changed, 80 insertions, 59 deletions
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 5f910c99e8dd..1902148281cc 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -416,6 +416,26 @@ struct fuse_dev {
416 struct list_head entry; 416 struct list_head entry;
417}; 417};
418 418
419struct fuse_fs_context {
420 int fd;
421 unsigned int rootmode;
422 kuid_t user_id;
423 kgid_t group_id;
424 bool is_bdev:1;
425 bool fd_present:1;
426 bool rootmode_present:1;
427 bool user_id_present:1;
428 bool group_id_present:1;
429 bool default_permissions:1;
430 bool allow_other:1;
431 unsigned int max_read;
432 unsigned int blksize;
433 const char *subtype;
434
435 /* fuse_dev pointer to fill in, should contain NULL on entry */
436 void **fudptr;
437};
438
419/** 439/**
420 * A Fuse connection. 440 * A Fuse connection.
421 * 441 *
@@ -874,6 +894,13 @@ void fuse_dev_free(struct fuse_dev *fud);
874void fuse_send_init(struct fuse_conn *fc); 894void fuse_send_init(struct fuse_conn *fc);
875 895
876/** 896/**
897 * Fill in superblock and initialize fuse connection
898 * @sb: partially-initialized superblock to fill in
899 * @ctx: mount context
900 */
901int fuse_fill_super_common(struct super_block *sb, struct fuse_fs_context *ctx);
902
903/**
877 * Add connection to control filesystem 904 * Add connection to control filesystem
878 */ 905 */
879int fuse_ctl_add_conn(struct fuse_conn *fc); 906int fuse_ctl_add_conn(struct fuse_conn *fc);
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 5d455f4d6195..30d92e633ece 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -64,23 +64,6 @@ MODULE_PARM_DESC(max_user_congthresh,
64static struct file_system_type fuseblk_fs_type; 64static struct file_system_type fuseblk_fs_type;
65#endif 65#endif
66 66
67struct fuse_fs_context {
68 const char *subtype;
69 bool is_bdev;
70 int fd;
71 unsigned rootmode;
72 kuid_t user_id;
73 kgid_t group_id;
74 unsigned fd_present:1;
75 unsigned rootmode_present:1;
76 unsigned user_id_present:1;
77 unsigned group_id_present:1;
78 unsigned default_permissions:1;
79 unsigned allow_other:1;
80 unsigned max_read;
81 unsigned blksize;
82};
83
84struct fuse_forget_link *fuse_alloc_forget(void) 67struct fuse_forget_link *fuse_alloc_forget(void)
85{ 68{
86 return kzalloc(sizeof(struct fuse_forget_link), GFP_KERNEL); 69 return kzalloc(sizeof(struct fuse_forget_link), GFP_KERNEL);
@@ -1100,16 +1083,13 @@ void fuse_dev_free(struct fuse_dev *fud)
1100} 1083}
1101EXPORT_SYMBOL_GPL(fuse_dev_free); 1084EXPORT_SYMBOL_GPL(fuse_dev_free);
1102 1085
1103static int fuse_fill_super(struct super_block *sb, struct fs_context *fsc) 1086int fuse_fill_super_common(struct super_block *sb, struct fuse_fs_context *ctx)
1104{ 1087{
1105 struct fuse_fs_context *ctx = fsc->fs_private;
1106 struct fuse_dev *fud; 1088 struct fuse_dev *fud;
1107 struct fuse_conn *fc; 1089 struct fuse_conn *fc = get_fuse_conn_super(sb);
1108 struct inode *root; 1090 struct inode *root;
1109 struct file *file;
1110 struct dentry *root_dentry; 1091 struct dentry *root_dentry;
1111 int err; 1092 int err;
1112 int is_bdev = sb->s_bdev != NULL;
1113 1093
1114 err = -EINVAL; 1094 err = -EINVAL;
1115 if (sb->s_flags & SB_MANDLOCK) 1095 if (sb->s_flags & SB_MANDLOCK)
@@ -1117,7 +1097,7 @@ static int fuse_fill_super(struct super_block *sb, struct fs_context *fsc)
1117 1097
1118 sb->s_flags &= ~(SB_NOSEC | SB_I_VERSION); 1098 sb->s_flags &= ~(SB_NOSEC | SB_I_VERSION);
1119 1099
1120 if (is_bdev) { 1100 if (ctx->is_bdev) {
1121#ifdef CONFIG_BLOCK 1101#ifdef CONFIG_BLOCK
1122 err = -EINVAL; 1102 err = -EINVAL;
1123 if (!sb_set_blocksize(sb, ctx->blksize)) 1103 if (!sb_set_blocksize(sb, ctx->blksize))
@@ -1140,19 +1120,6 @@ static int fuse_fill_super(struct super_block *sb, struct fs_context *fsc)
1140 if (sb->s_user_ns != &init_user_ns) 1120 if (sb->s_user_ns != &init_user_ns)
1141 sb->s_iflags |= SB_I_UNTRUSTED_MOUNTER; 1121 sb->s_iflags |= SB_I_UNTRUSTED_MOUNTER;
1142 1122
1143 file = fget(ctx->fd);
1144 err = -EINVAL;
1145 if (!file)
1146 goto err;
1147
1148 /*
1149 * Require mount to happen from the same user namespace which
1150 * opened /dev/fuse to prevent potential attacks.
1151 */
1152 if (file->f_op != &fuse_dev_operations ||
1153 file->f_cred->user_ns != sb->s_user_ns)
1154 goto err_fput;
1155
1156 /* 1123 /*
1157 * If we are not in the initial user namespace posix 1124 * If we are not in the initial user namespace posix
1158 * acls must be translated. 1125 * acls must be translated.
@@ -1160,17 +1127,9 @@ static int fuse_fill_super(struct super_block *sb, struct fs_context *fsc)
1160 if (sb->s_user_ns != &init_user_ns) 1127 if (sb->s_user_ns != &init_user_ns)
1161 sb->s_xattr = fuse_no_acl_xattr_handlers; 1128 sb->s_xattr = fuse_no_acl_xattr_handlers;
1162 1129
1163 fc = kmalloc(sizeof(*fc), GFP_KERNEL);
1164 err = -ENOMEM;
1165 if (!fc)
1166 goto err_fput;
1167
1168 fuse_conn_init(fc, sb->s_user_ns);
1169 fc->release = fuse_free_conn;
1170
1171 fud = fuse_dev_alloc(fc); 1130 fud = fuse_dev_alloc(fc);
1172 if (!fud) 1131 if (!fud)
1173 goto err_put_conn; 1132 goto err;
1174 1133
1175 fc->dev = sb->s_dev; 1134 fc->dev = sb->s_dev;
1176 fc->sb = sb; 1135 fc->sb = sb;
@@ -1188,10 +1147,7 @@ static int fuse_fill_super(struct super_block *sb, struct fs_context *fsc)
1188 fc->user_id = ctx->user_id; 1147 fc->user_id = ctx->user_id;
1189 fc->group_id = ctx->group_id; 1148 fc->group_id = ctx->group_id;
1190 fc->max_read = max_t(unsigned, 4096, ctx->max_read); 1149 fc->max_read = max_t(unsigned, 4096, ctx->max_read);
1191 fc->destroy = is_bdev; 1150 fc->destroy = ctx->is_bdev;
1192
1193 /* Used by get_root_inode() */
1194 sb->s_fs_info = fc;
1195 1151
1196 err = -ENOMEM; 1152 err = -ENOMEM;
1197 root = fuse_get_root_inode(sb, ctx->rootmode); 1153 root = fuse_get_root_inode(sb, ctx->rootmode);
@@ -1204,7 +1160,7 @@ static int fuse_fill_super(struct super_block *sb, struct fs_context *fsc)
1204 1160
1205 mutex_lock(&fuse_mutex); 1161 mutex_lock(&fuse_mutex);
1206 err = -EINVAL; 1162 err = -EINVAL;
1207 if (file->private_data) 1163 if (*ctx->fudptr)
1208 goto err_unlock; 1164 goto err_unlock;
1209 1165
1210 err = fuse_ctl_add_conn(fc); 1166 err = fuse_ctl_add_conn(fc);
@@ -1213,24 +1169,62 @@ static int fuse_fill_super(struct super_block *sb, struct fs_context *fsc)
1213 1169
1214 list_add_tail(&fc->entry, &fuse_conn_list); 1170 list_add_tail(&fc->entry, &fuse_conn_list);
1215 sb->s_root = root_dentry; 1171 sb->s_root = root_dentry;
1216 file->private_data = fud; 1172 *ctx->fudptr = fud;
1217 mutex_unlock(&fuse_mutex); 1173 mutex_unlock(&fuse_mutex);
1174 return 0;
1175
1176 err_unlock:
1177 mutex_unlock(&fuse_mutex);
1178 dput(root_dentry);
1179 err_dev_free:
1180 fuse_dev_free(fud);
1181 err:
1182 return err;
1183}
1184EXPORT_SYMBOL_GPL(fuse_fill_super_common);
1185
1186static int fuse_fill_super(struct super_block *sb, struct fs_context *fsc)
1187{
1188 struct fuse_fs_context *ctx = fsc->fs_private;
1189 struct file *file;
1190 int err;
1191 struct fuse_conn *fc;
1192
1193 err = -EINVAL;
1194 file = fget(ctx->fd);
1195 if (!file)
1196 goto err;
1197
1198 /*
1199 * Require mount to happen from the same user namespace which
1200 * opened /dev/fuse to prevent potential attacks.
1201 */
1202 if ((file->f_op != &fuse_dev_operations) ||
1203 (file->f_cred->user_ns != sb->s_user_ns))
1204 goto err_fput;
1205 ctx->fudptr = &file->private_data;
1206
1207 fc = kmalloc(sizeof(*fc), GFP_KERNEL);
1208 err = -ENOMEM;
1209 if (!fc)
1210 goto err_fput;
1211
1212 fuse_conn_init(fc, sb->s_user_ns);
1213 fc->release = fuse_free_conn;
1214 sb->s_fs_info = fc;
1215
1216 err = fuse_fill_super_common(sb, ctx);
1217 if (err)
1218 goto err_put_conn;
1218 /* 1219 /*
1219 * atomic_dec_and_test() in fput() provides the necessary 1220 * atomic_dec_and_test() in fput() provides the necessary
1220 * memory barrier for file->private_data to be visible on all 1221 * memory barrier for file->private_data to be visible on all
1221 * CPUs after this 1222 * CPUs after this
1222 */ 1223 */
1223 fput(file); 1224 fput(file);
1224 1225 fuse_send_init(get_fuse_conn_super(sb));
1225 fuse_send_init(fc);
1226
1227 return 0; 1226 return 0;
1228 1227
1229 err_unlock:
1230 mutex_unlock(&fuse_mutex);
1231 dput(root_dentry);
1232 err_dev_free:
1233 fuse_dev_free(fud);
1234 err_put_conn: 1228 err_put_conn:
1235 fuse_conn_put(fc); 1229 fuse_conn_put(fc);
1236 sb->s_fs_info = NULL; 1230 sb->s_fs_info = NULL;