1 | // SPDX-License-Identifier: MIT |
2 | /* |
3 | * VirtualBox Guest Shared Folders support: Virtual File System. |
4 | * |
5 | * Module initialization/finalization |
6 | * File system registration/deregistration |
7 | * Superblock reading |
8 | * Few utility functions |
9 | * |
10 | * Copyright (C) 2006-2018 Oracle Corporation |
11 | */ |
12 | |
13 | #include <linux/idr.h> |
14 | #include <linux/fs_parser.h> |
15 | #include <linux/magic.h> |
16 | #include <linux/module.h> |
17 | #include <linux/nls.h> |
18 | #include <linux/statfs.h> |
19 | #include <linux/vbox_utils.h> |
20 | #include "vfsmod.h" |
21 | |
22 | #define VBOXSF_SUPER_MAGIC 0x786f4256 /* 'VBox' little endian */ |
23 | |
24 | static const unsigned char VBSF_MOUNT_SIGNATURE[4] = "\000\377\376\375" ; |
25 | |
26 | static int follow_symlinks; |
27 | module_param(follow_symlinks, int, 0444); |
28 | MODULE_PARM_DESC(follow_symlinks, |
29 | "Let host resolve symlinks rather than showing them" ); |
30 | |
31 | static DEFINE_IDA(vboxsf_bdi_ida); |
32 | static DEFINE_MUTEX(vboxsf_setup_mutex); |
33 | static bool vboxsf_setup_done; |
34 | static struct super_operations vboxsf_super_ops; /* forward declaration */ |
35 | static struct kmem_cache *vboxsf_inode_cachep; |
36 | |
37 | static char * const vboxsf_default_nls = CONFIG_NLS_DEFAULT; |
38 | |
39 | enum { opt_nls, opt_uid, opt_gid, opt_ttl, opt_dmode, opt_fmode, |
40 | opt_dmask, opt_fmask }; |
41 | |
42 | static const struct fs_parameter_spec vboxsf_fs_parameters[] = { |
43 | fsparam_string ("nls" , opt_nls), |
44 | fsparam_u32 ("uid" , opt_uid), |
45 | fsparam_u32 ("gid" , opt_gid), |
46 | fsparam_u32 ("ttl" , opt_ttl), |
47 | fsparam_u32oct ("dmode" , opt_dmode), |
48 | fsparam_u32oct ("fmode" , opt_fmode), |
49 | fsparam_u32oct ("dmask" , opt_dmask), |
50 | fsparam_u32oct ("fmask" , opt_fmask), |
51 | {} |
52 | }; |
53 | |
54 | static int vboxsf_parse_param(struct fs_context *fc, struct fs_parameter *param) |
55 | { |
56 | struct vboxsf_fs_context *ctx = fc->fs_private; |
57 | struct fs_parse_result result; |
58 | kuid_t uid; |
59 | kgid_t gid; |
60 | int opt; |
61 | |
62 | opt = fs_parse(fc, desc: vboxsf_fs_parameters, param, result: &result); |
63 | if (opt < 0) |
64 | return opt; |
65 | |
66 | switch (opt) { |
67 | case opt_nls: |
68 | if (ctx->nls_name || fc->purpose != FS_CONTEXT_FOR_MOUNT) { |
69 | vbg_err(fmt: "vboxsf: Cannot reconfigure nls option\n" ); |
70 | return -EINVAL; |
71 | } |
72 | ctx->nls_name = param->string; |
73 | param->string = NULL; |
74 | break; |
75 | case opt_uid: |
76 | uid = make_kuid(current_user_ns(), uid: result.uint_32); |
77 | if (!uid_valid(uid)) |
78 | return -EINVAL; |
79 | ctx->o.uid = uid; |
80 | break; |
81 | case opt_gid: |
82 | gid = make_kgid(current_user_ns(), gid: result.uint_32); |
83 | if (!gid_valid(gid)) |
84 | return -EINVAL; |
85 | ctx->o.gid = gid; |
86 | break; |
87 | case opt_ttl: |
88 | ctx->o.ttl = msecs_to_jiffies(m: result.uint_32); |
89 | break; |
90 | case opt_dmode: |
91 | if (result.uint_32 & ~0777) |
92 | return -EINVAL; |
93 | ctx->o.dmode = result.uint_32; |
94 | ctx->o.dmode_set = true; |
95 | break; |
96 | case opt_fmode: |
97 | if (result.uint_32 & ~0777) |
98 | return -EINVAL; |
99 | ctx->o.fmode = result.uint_32; |
100 | ctx->o.fmode_set = true; |
101 | break; |
102 | case opt_dmask: |
103 | if (result.uint_32 & ~07777) |
104 | return -EINVAL; |
105 | ctx->o.dmask = result.uint_32; |
106 | break; |
107 | case opt_fmask: |
108 | if (result.uint_32 & ~07777) |
109 | return -EINVAL; |
110 | ctx->o.fmask = result.uint_32; |
111 | break; |
112 | default: |
113 | return -EINVAL; |
114 | } |
115 | |
116 | return 0; |
117 | } |
118 | |
119 | static int vboxsf_fill_super(struct super_block *sb, struct fs_context *fc) |
120 | { |
121 | struct vboxsf_fs_context *ctx = fc->fs_private; |
122 | struct shfl_string *folder_name, root_path; |
123 | struct vboxsf_sbi *sbi; |
124 | struct dentry *droot; |
125 | struct inode *iroot; |
126 | char *nls_name; |
127 | size_t size; |
128 | int err; |
129 | |
130 | if (!fc->source) |
131 | return -EINVAL; |
132 | |
133 | sbi = kzalloc(size: sizeof(*sbi), GFP_KERNEL); |
134 | if (!sbi) |
135 | return -ENOMEM; |
136 | |
137 | sbi->o = ctx->o; |
138 | idr_init(idr: &sbi->ino_idr); |
139 | spin_lock_init(&sbi->ino_idr_lock); |
140 | sbi->next_generation = 1; |
141 | sbi->bdi_id = -1; |
142 | |
143 | /* Load nls if not utf8 */ |
144 | nls_name = ctx->nls_name ? ctx->nls_name : vboxsf_default_nls; |
145 | if (strcmp(nls_name, "utf8" ) != 0) { |
146 | if (nls_name == vboxsf_default_nls) |
147 | sbi->nls = load_nls_default(); |
148 | else |
149 | sbi->nls = load_nls(charset: nls_name); |
150 | |
151 | if (!sbi->nls) { |
152 | vbg_err(fmt: "vboxsf: Count not load '%s' nls\n" , nls_name); |
153 | err = -EINVAL; |
154 | goto fail_destroy_idr; |
155 | } |
156 | } |
157 | |
158 | sbi->bdi_id = ida_alloc(ida: &vboxsf_bdi_ida, GFP_KERNEL); |
159 | if (sbi->bdi_id < 0) { |
160 | err = sbi->bdi_id; |
161 | goto fail_free; |
162 | } |
163 | |
164 | err = super_setup_bdi_name(sb, fmt: "vboxsf-%d" , sbi->bdi_id); |
165 | if (err) |
166 | goto fail_free; |
167 | sb->s_bdi->ra_pages = 0; |
168 | sb->s_bdi->io_pages = 0; |
169 | |
170 | /* Turn source into a shfl_string and map the folder */ |
171 | size = strlen(fc->source) + 1; |
172 | folder_name = kmalloc(SHFLSTRING_HEADER_SIZE + size, GFP_KERNEL); |
173 | if (!folder_name) { |
174 | err = -ENOMEM; |
175 | goto fail_free; |
176 | } |
177 | folder_name->size = size; |
178 | folder_name->length = size - 1; |
179 | strscpy(folder_name->string.utf8, fc->source, size); |
180 | err = vboxsf_map_folder(folder_name, root: &sbi->root); |
181 | kfree(objp: folder_name); |
182 | if (err) { |
183 | vbg_err(fmt: "vboxsf: Host rejected mount of '%s' with error %d\n" , |
184 | fc->source, err); |
185 | goto fail_free; |
186 | } |
187 | |
188 | root_path.length = 1; |
189 | root_path.size = 2; |
190 | root_path.string.utf8[0] = '/'; |
191 | root_path.string.utf8[1] = 0; |
192 | err = vboxsf_stat(sbi, path: &root_path, info: &sbi->root_info); |
193 | if (err) |
194 | goto fail_unmap; |
195 | |
196 | sb->s_magic = VBOXSF_SUPER_MAGIC; |
197 | sb->s_blocksize = 1024; |
198 | sb->s_maxbytes = MAX_LFS_FILESIZE; |
199 | sb->s_op = &vboxsf_super_ops; |
200 | sb->s_d_op = &vboxsf_dentry_ops; |
201 | |
202 | iroot = iget_locked(sb, 0); |
203 | if (!iroot) { |
204 | err = -ENOMEM; |
205 | goto fail_unmap; |
206 | } |
207 | vboxsf_init_inode(sbi, inode: iroot, info: &sbi->root_info, reinit: false); |
208 | unlock_new_inode(iroot); |
209 | |
210 | droot = d_make_root(iroot); |
211 | if (!droot) { |
212 | err = -ENOMEM; |
213 | goto fail_unmap; |
214 | } |
215 | |
216 | sb->s_root = droot; |
217 | sb->s_fs_info = sbi; |
218 | return 0; |
219 | |
220 | fail_unmap: |
221 | vboxsf_unmap_folder(root: sbi->root); |
222 | fail_free: |
223 | if (sbi->bdi_id >= 0) |
224 | ida_free(&vboxsf_bdi_ida, id: sbi->bdi_id); |
225 | if (sbi->nls) |
226 | unload_nls(sbi->nls); |
227 | fail_destroy_idr: |
228 | idr_destroy(&sbi->ino_idr); |
229 | kfree(objp: sbi); |
230 | return err; |
231 | } |
232 | |
233 | static void vboxsf_inode_init_once(void *data) |
234 | { |
235 | struct vboxsf_inode *sf_i = data; |
236 | |
237 | mutex_init(&sf_i->handle_list_mutex); |
238 | inode_init_once(&sf_i->vfs_inode); |
239 | } |
240 | |
241 | static struct inode *vboxsf_alloc_inode(struct super_block *sb) |
242 | { |
243 | struct vboxsf_inode *sf_i; |
244 | |
245 | sf_i = alloc_inode_sb(sb, cache: vboxsf_inode_cachep, GFP_NOFS); |
246 | if (!sf_i) |
247 | return NULL; |
248 | |
249 | sf_i->force_restat = 0; |
250 | INIT_LIST_HEAD(list: &sf_i->handle_list); |
251 | |
252 | return &sf_i->vfs_inode; |
253 | } |
254 | |
255 | static void vboxsf_free_inode(struct inode *inode) |
256 | { |
257 | struct vboxsf_sbi *sbi = VBOXSF_SBI(inode->i_sb); |
258 | unsigned long flags; |
259 | |
260 | spin_lock_irqsave(&sbi->ino_idr_lock, flags); |
261 | idr_remove(&sbi->ino_idr, id: inode->i_ino); |
262 | spin_unlock_irqrestore(lock: &sbi->ino_idr_lock, flags); |
263 | kmem_cache_free(s: vboxsf_inode_cachep, VBOXSF_I(inode)); |
264 | } |
265 | |
266 | static void vboxsf_put_super(struct super_block *sb) |
267 | { |
268 | struct vboxsf_sbi *sbi = VBOXSF_SBI(sb); |
269 | |
270 | vboxsf_unmap_folder(root: sbi->root); |
271 | if (sbi->bdi_id >= 0) |
272 | ida_free(&vboxsf_bdi_ida, id: sbi->bdi_id); |
273 | if (sbi->nls) |
274 | unload_nls(sbi->nls); |
275 | |
276 | /* |
277 | * vboxsf_free_inode uses the idr, make sure all delayed rcu free |
278 | * inodes are flushed. |
279 | */ |
280 | rcu_barrier(); |
281 | idr_destroy(&sbi->ino_idr); |
282 | kfree(objp: sbi); |
283 | } |
284 | |
285 | static int vboxsf_statfs(struct dentry *dentry, struct kstatfs *stat) |
286 | { |
287 | struct super_block *sb = dentry->d_sb; |
288 | struct shfl_volinfo shfl_volinfo; |
289 | struct vboxsf_sbi *sbi; |
290 | u32 buf_len; |
291 | int err; |
292 | |
293 | sbi = VBOXSF_SBI(sb); |
294 | buf_len = sizeof(shfl_volinfo); |
295 | err = vboxsf_fsinfo(root: sbi->root, handle: 0, SHFL_INFO_GET | SHFL_INFO_VOLUME, |
296 | buf_len: &buf_len, buf: &shfl_volinfo); |
297 | if (err) |
298 | return err; |
299 | |
300 | stat->f_type = VBOXSF_SUPER_MAGIC; |
301 | stat->f_bsize = shfl_volinfo.bytes_per_allocation_unit; |
302 | |
303 | do_div(shfl_volinfo.total_allocation_bytes, |
304 | shfl_volinfo.bytes_per_allocation_unit); |
305 | stat->f_blocks = shfl_volinfo.total_allocation_bytes; |
306 | |
307 | do_div(shfl_volinfo.available_allocation_bytes, |
308 | shfl_volinfo.bytes_per_allocation_unit); |
309 | stat->f_bfree = shfl_volinfo.available_allocation_bytes; |
310 | stat->f_bavail = shfl_volinfo.available_allocation_bytes; |
311 | |
312 | stat->f_files = 1000; |
313 | /* |
314 | * Don't return 0 here since the guest may then think that it is not |
315 | * possible to create any more files. |
316 | */ |
317 | stat->f_ffree = 1000000; |
318 | stat->f_fsid.val[0] = 0; |
319 | stat->f_fsid.val[1] = 0; |
320 | stat->f_namelen = 255; |
321 | return 0; |
322 | } |
323 | |
324 | static struct super_operations vboxsf_super_ops = { |
325 | .alloc_inode = vboxsf_alloc_inode, |
326 | .free_inode = vboxsf_free_inode, |
327 | .put_super = vboxsf_put_super, |
328 | .statfs = vboxsf_statfs, |
329 | }; |
330 | |
331 | static int vboxsf_setup(void) |
332 | { |
333 | int err; |
334 | |
335 | mutex_lock(&vboxsf_setup_mutex); |
336 | |
337 | if (vboxsf_setup_done) |
338 | goto success; |
339 | |
340 | vboxsf_inode_cachep = |
341 | kmem_cache_create(name: "vboxsf_inode_cache" , |
342 | size: sizeof(struct vboxsf_inode), align: 0, |
343 | SLAB_RECLAIM_ACCOUNT | SLAB_ACCOUNT, |
344 | ctor: vboxsf_inode_init_once); |
345 | if (!vboxsf_inode_cachep) { |
346 | err = -ENOMEM; |
347 | goto fail_nomem; |
348 | } |
349 | |
350 | err = vboxsf_connect(); |
351 | if (err) { |
352 | vbg_err(fmt: "vboxsf: err %d connecting to guest PCI-device\n" , err); |
353 | vbg_err(fmt: "vboxsf: make sure you are inside a VirtualBox VM\n" ); |
354 | vbg_err(fmt: "vboxsf: and check dmesg for vboxguest errors\n" ); |
355 | goto fail_free_cache; |
356 | } |
357 | |
358 | err = vboxsf_set_utf8(); |
359 | if (err) { |
360 | vbg_err(fmt: "vboxsf_setutf8 error %d\n" , err); |
361 | goto fail_disconnect; |
362 | } |
363 | |
364 | if (!follow_symlinks) { |
365 | err = vboxsf_set_symlinks(); |
366 | if (err) |
367 | vbg_warn(fmt: "vboxsf: Unable to show symlinks: %d\n" , err); |
368 | } |
369 | |
370 | vboxsf_setup_done = true; |
371 | success: |
372 | mutex_unlock(lock: &vboxsf_setup_mutex); |
373 | return 0; |
374 | |
375 | fail_disconnect: |
376 | vboxsf_disconnect(); |
377 | fail_free_cache: |
378 | kmem_cache_destroy(s: vboxsf_inode_cachep); |
379 | fail_nomem: |
380 | mutex_unlock(lock: &vboxsf_setup_mutex); |
381 | return err; |
382 | } |
383 | |
384 | static int vboxsf_parse_monolithic(struct fs_context *fc, void *data) |
385 | { |
386 | if (data && !memcmp(p: data, q: VBSF_MOUNT_SIGNATURE, size: 4)) { |
387 | vbg_err(fmt: "vboxsf: Old binary mount data not supported, remove obsolete mount.vboxsf and/or update your VBoxService.\n" ); |
388 | return -EINVAL; |
389 | } |
390 | |
391 | return generic_parse_monolithic(fc, data); |
392 | } |
393 | |
394 | static int vboxsf_get_tree(struct fs_context *fc) |
395 | { |
396 | int err; |
397 | |
398 | err = vboxsf_setup(); |
399 | if (err) |
400 | return err; |
401 | |
402 | return get_tree_nodev(fc, fill_super: vboxsf_fill_super); |
403 | } |
404 | |
405 | static int vboxsf_reconfigure(struct fs_context *fc) |
406 | { |
407 | struct vboxsf_sbi *sbi = VBOXSF_SBI(fc->root->d_sb); |
408 | struct vboxsf_fs_context *ctx = fc->fs_private; |
409 | struct inode *iroot = fc->root->d_sb->s_root->d_inode; |
410 | |
411 | /* Apply changed options to the root inode */ |
412 | sbi->o = ctx->o; |
413 | vboxsf_init_inode(sbi, inode: iroot, info: &sbi->root_info, reinit: true); |
414 | |
415 | return 0; |
416 | } |
417 | |
418 | static void vboxsf_free_fc(struct fs_context *fc) |
419 | { |
420 | struct vboxsf_fs_context *ctx = fc->fs_private; |
421 | |
422 | kfree(objp: ctx->nls_name); |
423 | kfree(objp: ctx); |
424 | } |
425 | |
426 | static const struct fs_context_operations vboxsf_context_ops = { |
427 | .free = vboxsf_free_fc, |
428 | .parse_param = vboxsf_parse_param, |
429 | .parse_monolithic = vboxsf_parse_monolithic, |
430 | .get_tree = vboxsf_get_tree, |
431 | .reconfigure = vboxsf_reconfigure, |
432 | }; |
433 | |
434 | static int vboxsf_init_fs_context(struct fs_context *fc) |
435 | { |
436 | struct vboxsf_fs_context *ctx; |
437 | |
438 | ctx = kzalloc(size: sizeof(*ctx), GFP_KERNEL); |
439 | if (!ctx) |
440 | return -ENOMEM; |
441 | |
442 | current_uid_gid(&ctx->o.uid, &ctx->o.gid); |
443 | |
444 | fc->fs_private = ctx; |
445 | fc->ops = &vboxsf_context_ops; |
446 | return 0; |
447 | } |
448 | |
449 | static struct file_system_type vboxsf_fs_type = { |
450 | .owner = THIS_MODULE, |
451 | .name = "vboxsf" , |
452 | .init_fs_context = vboxsf_init_fs_context, |
453 | .kill_sb = kill_anon_super |
454 | }; |
455 | |
456 | /* Module initialization/finalization handlers */ |
457 | static int __init vboxsf_init(void) |
458 | { |
459 | return register_filesystem(&vboxsf_fs_type); |
460 | } |
461 | |
462 | static void __exit vboxsf_fini(void) |
463 | { |
464 | unregister_filesystem(&vboxsf_fs_type); |
465 | |
466 | mutex_lock(&vboxsf_setup_mutex); |
467 | if (vboxsf_setup_done) { |
468 | vboxsf_disconnect(); |
469 | /* |
470 | * Make sure all delayed rcu free inodes are flushed |
471 | * before we destroy the cache. |
472 | */ |
473 | rcu_barrier(); |
474 | kmem_cache_destroy(s: vboxsf_inode_cachep); |
475 | } |
476 | mutex_unlock(lock: &vboxsf_setup_mutex); |
477 | } |
478 | |
479 | module_init(vboxsf_init); |
480 | module_exit(vboxsf_fini); |
481 | |
482 | MODULE_DESCRIPTION("Oracle VM VirtualBox Module for Host File System Access" ); |
483 | MODULE_AUTHOR("Oracle Corporation" ); |
484 | MODULE_LICENSE("GPL v2" ); |
485 | MODULE_ALIAS_FS("vboxsf" ); |
486 | |