VirtualBox

source: vbox/trunk/src/VBox/Additions/linux/sharedfolders/vfsmod.c@ 68104

Last change on this file since 68104 was 68104, checked in by vboxsync, 7 years ago

Linux shared folder driver: stop using VbglR0SfInit and Term.

bugref:8524: Additions/linux: play nicely with distribution-installed Additions
Stop using the VbglR0SfInit and Term symbols in the Linux shared folders guest
driver and use VbglR0HGCMInit and Terminate instead. Remove the former
symbols from the guest library altogether on Linux. After this, the Linux
shared folder driver only depends on the HGCM code in the guest library.

Signed-off-by: Hans de Goede <hdegoede@…>
Reworked by Oracle.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 16.4 KB
Line 
1/** @file
2 *
3 * vboxsf -- VirtualBox Guest Additions for Linux:
4 * Virtual File System for VirtualBox Shared Folders
5 *
6 * Module initialization/finalization
7 * File system registration/deregistration
8 * Superblock reading
9 * Few utility functions
10 */
11
12/*
13 * Copyright (C) 2006-2016 Oracle Corporation
14 *
15 * This file is part of VirtualBox Open Source Edition (OSE), as
16 * available from http://www.virtualbox.org. This file is free software;
17 * you can redistribute it and/or modify it under the terms of the GNU
18 * General Public License (GPL) as published by the Free Software
19 * Foundation, in version 2 as it comes in the "COPYING" file of the
20 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
21 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
22 */
23
24/**
25 * @note Anyone wishing to make changes here might wish to take a look at
26 * http://www.atnf.csiro.au/people/rgooch/linux/vfs.txt
27 * which seems to be the closest there is to official documentation on
28 * writing filesystem drivers for Linux.
29 */
30
31#include "vfsmod.h"
32#include "version-generated.h"
33#include "revision-generated.h"
34#include "product-generated.h"
35#include "VBGLInternal.h"
36
37MODULE_DESCRIPTION(VBOX_PRODUCT " VFS Module for Host File System Access");
38MODULE_AUTHOR(VBOX_VENDOR);
39MODULE_LICENSE("GPL");
40#ifdef MODULE_ALIAS_FS
41MODULE_ALIAS_FS("vboxsf");
42#endif
43#ifdef MODULE_VERSION
44MODULE_VERSION(VBOX_VERSION_STRING " r" RT_XSTR(VBOX_SVN_REV));
45#endif
46
47/* globals */
48VBGLSFCLIENT client_handle;
49
50/* forward declarations */
51static struct super_operations sf_super_ops;
52
53/* allocate global info, try to map host share */
54static int sf_glob_alloc(struct vbsf_mount_info_new *info, struct sf_glob_info **sf_gp)
55{
56 int err, rc;
57 SHFLSTRING *str_name;
58 size_t name_len, str_len;
59 struct sf_glob_info *sf_g;
60
61 TRACE();
62 sf_g = kmalloc(sizeof(*sf_g), GFP_KERNEL);
63 if (!sf_g)
64 {
65 err = -ENOMEM;
66 LogRelFunc(("could not allocate memory for global info\n"));
67 goto fail0;
68 }
69
70 RT_ZERO(*sf_g);
71
72 if ( info->nullchar != '\0'
73 || info->signature[0] != VBSF_MOUNT_SIGNATURE_BYTE_0
74 || info->signature[1] != VBSF_MOUNT_SIGNATURE_BYTE_1
75 || info->signature[2] != VBSF_MOUNT_SIGNATURE_BYTE_2)
76 {
77 /* An old version of mount.vboxsf made the syscall. Translate the
78 * old parameters to the new structure. */
79 struct vbsf_mount_info_old *info_old = (struct vbsf_mount_info_old *)info;
80 static struct vbsf_mount_info_new info_compat;
81
82 info = &info_compat;
83 memset(info, 0, sizeof(*info));
84 memcpy(&info->name, &info_old->name, MAX_HOST_NAME);
85 memcpy(&info->nls_name, &info_old->nls_name, MAX_NLS_NAME);
86 info->length = offsetof(struct vbsf_mount_info_new, dmode);
87 info->uid = info_old->uid;
88 info->gid = info_old->gid;
89 info->ttl = info_old->ttl;
90 }
91
92 info->name[sizeof(info->name) - 1] = 0;
93 info->nls_name[sizeof(info->nls_name) - 1] = 0;
94
95 name_len = strlen(info->name);
96 if (name_len > 0xfffe)
97 {
98 err = -ENAMETOOLONG;
99 LogFunc(("map name too big\n"));
100 goto fail1;
101 }
102
103 str_len = offsetof(SHFLSTRING, String.utf8) + name_len + 1;
104 str_name = kmalloc(str_len, GFP_KERNEL);
105 if (!str_name)
106 {
107 err = -ENOMEM;
108 LogRelFunc(("could not allocate memory for host name\n"));
109 goto fail1;
110 }
111
112 str_name->u16Length = name_len;
113 str_name->u16Size = name_len + 1;
114 memcpy(str_name->String.utf8, info->name, name_len + 1);
115
116#define _IS_UTF8(_str) \
117 (strcmp(_str, "utf8") == 0)
118#define _IS_EMPTY(_str) \
119 (strcmp(_str, "") == 0)
120
121 /* Check if NLS charset is valid and not points to UTF8 table */
122 if (info->nls_name[0])
123 {
124 if (_IS_UTF8(info->nls_name))
125 sf_g->nls = NULL;
126 else
127 {
128 sf_g->nls = load_nls(info->nls_name);
129 if (!sf_g->nls)
130 {
131 err = -EINVAL;
132 LogFunc(("failed to load nls %s\n", info->nls_name));
133 kfree(str_name);
134 goto fail1;
135 }
136 }
137 }
138 else
139 {
140#ifdef CONFIG_NLS_DEFAULT
141 /* If no NLS charset specified, try to load the default
142 * one if it's not points to UTF8. */
143 if (!_IS_UTF8(CONFIG_NLS_DEFAULT) && !_IS_EMPTY(CONFIG_NLS_DEFAULT))
144 sf_g->nls = load_nls_default();
145 else
146 sf_g->nls = NULL;
147#else
148 sf_g->nls = NULL;
149#endif
150
151#undef _IS_UTF8
152#undef _IS_EMPTY
153 }
154
155 rc = VbglR0SfMapFolder(&client_handle, str_name, &sf_g->map);
156 kfree(str_name);
157
158 if (RT_FAILURE(rc))
159 {
160 err = -EPROTO;
161 LogFunc(("VbglR0SfMapFolder failed rc=%d\n", rc));
162 goto fail2;
163 }
164
165 sf_g->ttl = info->ttl;
166 sf_g->uid = info->uid;
167 sf_g->gid = info->gid;
168
169 if ((unsigned)info->length >= sizeof(struct vbsf_mount_info_new))
170 {
171 /* new fields */
172 sf_g->dmode = info->dmode;
173 sf_g->fmode = info->fmode;
174 sf_g->dmask = info->dmask;
175 sf_g->fmask = info->fmask;
176 }
177 else
178 {
179 sf_g->dmode = ~0;
180 sf_g->fmode = ~0;
181 }
182
183 *sf_gp = sf_g;
184 return 0;
185
186fail2:
187 if (sf_g->nls)
188 unload_nls(sf_g->nls);
189
190fail1:
191 kfree(sf_g);
192
193fail0:
194 return err;
195}
196
197/* unmap the share and free global info [sf_g] */
198static void
199sf_glob_free(struct sf_glob_info *sf_g)
200{
201 int rc;
202
203 TRACE();
204 rc = VbglR0SfUnmapFolder(&client_handle, &sf_g->map);
205 if (RT_FAILURE(rc))
206 LogFunc(("VbglR0SfUnmapFolder failed rc=%d\n", rc));
207
208 if (sf_g->nls)
209 unload_nls(sf_g->nls);
210
211 kfree(sf_g);
212}
213
214/**
215 * This is called (by sf_read_super_[24|26] when vfs mounts the fs and
216 * wants to read super_block.
217 *
218 * calls [sf_glob_alloc] to map the folder and allocate global
219 * information structure.
220 *
221 * initializes [sb], initializes root inode and dentry.
222 *
223 * should respect [flags]
224 */
225static int sf_read_super_aux(struct super_block *sb, void *data, int flags)
226{
227 int err;
228 struct dentry *droot;
229 struct inode *iroot;
230 struct sf_inode_info *sf_i;
231 struct sf_glob_info *sf_g;
232 SHFLFSOBJINFO fsinfo;
233 struct vbsf_mount_info_new *info;
234 bool fInodePut = true;
235
236 TRACE();
237 if (!data)
238 {
239 LogFunc(("no mount info specified\n"));
240 return -EINVAL;
241 }
242
243 info = data;
244
245 if (flags & MS_REMOUNT)
246 {
247 LogFunc(("remounting is not supported\n"));
248 return -ENOSYS;
249 }
250
251 err = sf_glob_alloc(info, &sf_g);
252 if (err)
253 goto fail0;
254
255 sf_i = kmalloc(sizeof (*sf_i), GFP_KERNEL);
256 if (!sf_i)
257 {
258 err = -ENOMEM;
259 LogRelFunc(("could not allocate memory for root inode info\n"));
260 goto fail1;
261 }
262
263 sf_i->handle = SHFL_HANDLE_NIL;
264 sf_i->path = kmalloc(sizeof(SHFLSTRING) + 1, GFP_KERNEL);
265 if (!sf_i->path)
266 {
267 err = -ENOMEM;
268 LogRelFunc(("could not allocate memory for root inode path\n"));
269 goto fail2;
270 }
271
272 sf_i->path->u16Length = 1;
273 sf_i->path->u16Size = 2;
274 sf_i->path->String.utf8[0] = '/';
275 sf_i->path->String.utf8[1] = 0;
276 sf_i->force_reread = 0;
277
278 err = sf_stat(__func__, sf_g, sf_i->path, &fsinfo, 0);
279 if (err)
280 {
281 LogFunc(("could not stat root of share\n"));
282 goto fail3;
283 }
284
285 sb->s_magic = 0xface;
286 sb->s_blocksize = 1024;
287#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 3)
288 /* Required for seek/sendfile.
289 *
290 * Must by less than or equal to INT64_MAX despite the fact that the
291 * declaration of this variable is unsigned long long. See determination
292 * of 'loff_t max' in fs/read_write.c / do_sendfile(). I don't know the
293 * correct limit but MAX_LFS_FILESIZE (8TB-1 on 32-bit boxes) takes the
294 * page cache into account and is the suggested limit. */
295# if defined MAX_LFS_FILESIZE
296 sb->s_maxbytes = MAX_LFS_FILESIZE;
297# else
298 sb->s_maxbytes = 0x7fffffffffffffffULL;
299# endif
300#endif
301 sb->s_op = &sf_super_ops;
302
303#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 25)
304 iroot = iget_locked(sb, 0);
305#else
306 iroot = iget(sb, 0);
307#endif
308 if (!iroot)
309 {
310 err = -ENOMEM; /* XXX */
311 LogFunc(("could not get root inode\n"));
312 goto fail3;
313 }
314
315 if (sf_init_backing_dev(sf_g))
316 {
317 err = -EINVAL;
318 LogFunc(("could not init bdi\n"));
319#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 25)
320 unlock_new_inode(iroot);
321#endif
322 goto fail4;
323 }
324
325 sf_init_inode(sf_g, iroot, &fsinfo);
326 SET_INODE_INFO(iroot, sf_i);
327
328#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 25)
329 unlock_new_inode(iroot);
330#endif
331
332#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
333 droot = d_make_root(iroot);
334#else
335 droot = d_alloc_root(iroot);
336#endif
337 if (!droot)
338 {
339 err = -ENOMEM; /* XXX */
340 LogFunc(("d_alloc_root failed\n"));
341#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
342 fInodePut = false;
343#endif
344 goto fail5;
345 }
346
347 sb->s_root = droot;
348 SET_GLOB_INFO(sb, sf_g);
349 return 0;
350
351fail5:
352 sf_done_backing_dev(sf_g);
353
354fail4:
355 if (fInodePut)
356 iput(iroot);
357
358fail3:
359 kfree(sf_i->path);
360
361fail2:
362 kfree(sf_i);
363
364fail1:
365 sf_glob_free(sf_g);
366
367fail0:
368 return err;
369}
370
371#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
372static struct super_block *
373sf_read_super_24(struct super_block *sb, void *data, int flags)
374{
375 int err;
376
377 TRACE();
378 err = sf_read_super_aux(sb, data, flags);
379 if (err)
380 return NULL;
381
382 return sb;
383}
384#endif
385
386/* this is called when vfs is about to destroy the [inode]. all
387 resources associated with this [inode] must be cleared here */
388#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
389static void sf_clear_inode(struct inode *inode)
390{
391 struct sf_inode_info *sf_i;
392
393 TRACE();
394 sf_i = GET_INODE_INFO(inode);
395 if (!sf_i)
396 return;
397
398 BUG_ON(!sf_i->path);
399 kfree(sf_i->path);
400 kfree(sf_i);
401 SET_INODE_INFO(inode, NULL);
402}
403#else
404static void sf_evict_inode(struct inode *inode)
405{
406 struct sf_inode_info *sf_i;
407
408 TRACE();
409 truncate_inode_pages(&inode->i_data, 0);
410# if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
411 clear_inode(inode);
412# else
413 end_writeback(inode);
414# endif
415
416 sf_i = GET_INODE_INFO(inode);
417 if (!sf_i)
418 return;
419
420 BUG_ON(!sf_i->path);
421 kfree(sf_i->path);
422 kfree(sf_i);
423 SET_INODE_INFO(inode, NULL);
424}
425#endif
426
427/* this is called by vfs when it wants to populate [inode] with data.
428 the only thing that is known about inode at this point is its index
429 hence we can't do anything here, and let lookup/whatever with the
430 job to properly fill then [inode] */
431#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
432static void sf_read_inode(struct inode *inode)
433{
434}
435#endif
436
437/* vfs is done with [sb] (umount called) call [sf_glob_free] to unmap
438 the folder and free [sf_g] */
439static void sf_put_super(struct super_block *sb)
440{
441 struct sf_glob_info *sf_g;
442
443 sf_g = GET_GLOB_INFO(sb);
444 BUG_ON(!sf_g);
445 sf_done_backing_dev(sf_g);
446 sf_glob_free(sf_g);
447}
448
449#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
450static int sf_statfs(struct super_block *sb, STRUCT_STATFS *stat)
451{
452 return sf_get_volume_info(sb, stat);
453}
454#else
455static int sf_statfs(struct dentry *dentry, STRUCT_STATFS *stat)
456{
457 struct super_block *sb = dentry->d_inode->i_sb;
458 return sf_get_volume_info(sb, stat);
459}
460#endif
461
462static int sf_remount_fs(struct super_block *sb, int *flags, char *data)
463{
464#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 23)
465 struct sf_glob_info *sf_g;
466 struct sf_inode_info *sf_i;
467 struct inode *iroot;
468 SHFLFSOBJINFO fsinfo;
469 int err;
470
471 sf_g = GET_GLOB_INFO(sb);
472 BUG_ON(!sf_g);
473 if (data && data[0] != 0)
474 {
475 struct vbsf_mount_info_new *info =
476 (struct vbsf_mount_info_new *)data;
477 if ( info->signature[0] == VBSF_MOUNT_SIGNATURE_BYTE_0
478 && info->signature[1] == VBSF_MOUNT_SIGNATURE_BYTE_1
479 && info->signature[2] == VBSF_MOUNT_SIGNATURE_BYTE_2)
480 {
481 sf_g->uid = info->uid;
482 sf_g->gid = info->gid;
483 sf_g->ttl = info->ttl;
484 sf_g->dmode = info->dmode;
485 sf_g->fmode = info->fmode;
486 sf_g->dmask = info->dmask;
487 sf_g->fmask = info->fmask;
488 }
489 }
490
491 iroot = ilookup(sb, 0);
492 if (!iroot)
493 return -ENOSYS;
494
495 sf_i = GET_INODE_INFO(iroot);
496 err = sf_stat(__func__, sf_g, sf_i->path, &fsinfo, 0);
497 BUG_ON(err != 0);
498 sf_init_inode(sf_g, iroot, &fsinfo);
499 /*unlock_new_inode(iroot);*/
500 return 0;
501#else
502 return -ENOSYS;
503#endif
504}
505
506static struct super_operations sf_super_ops =
507{
508#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
509 .clear_inode = sf_clear_inode,
510#else
511 .evict_inode = sf_evict_inode,
512#endif
513#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
514 .read_inode = sf_read_inode,
515#endif
516 .put_super = sf_put_super,
517 .statfs = sf_statfs,
518 .remount_fs = sf_remount_fs
519};
520
521#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
522static DECLARE_FSTYPE(vboxsf_fs_type, "vboxsf", sf_read_super_24, 0);
523#else
524static int
525sf_read_super_26(struct super_block *sb, void *data, int flags)
526{
527 int err;
528
529 TRACE();
530 err = sf_read_super_aux(sb, data, flags);
531 if (err)
532 printk(KERN_DEBUG "sf_read_super_aux err=%d\n", err);
533
534 return err;
535}
536
537# if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
538static struct super_block *sf_get_sb(struct file_system_type *fs_type, int flags,
539 const char *dev_name, void *data)
540{
541 TRACE();
542 return get_sb_nodev(fs_type, flags, data, sf_read_super_26);
543}
544# elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)
545static int sf_get_sb(struct file_system_type *fs_type, int flags,
546 const char *dev_name, void *data, struct vfsmount *mnt)
547{
548 TRACE();
549 return get_sb_nodev(fs_type, flags, data, sf_read_super_26, mnt);
550}
551# else
552static struct dentry *sf_mount(struct file_system_type *fs_type, int flags,
553 const char *dev_name, void *data)
554{
555 TRACE();
556 return mount_nodev(fs_type, flags, data, sf_read_super_26);
557}
558# endif
559
560static struct file_system_type vboxsf_fs_type =
561{
562 .owner = THIS_MODULE,
563 .name = "vboxsf",
564# if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)
565 .get_sb = sf_get_sb,
566# else
567 .mount = sf_mount,
568# endif
569 .kill_sb = kill_anon_super
570};
571#endif
572
573#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
574static int follow_symlinks = 0;
575module_param(follow_symlinks, int, 0);
576MODULE_PARM_DESC(follow_symlinks, "Let host resolve symlinks rather than showing them");
577#endif
578
579/* Module initialization/finalization handlers */
580static int __init init(void)
581{
582 int rcVBox;
583 int rcRet = 0;
584 int err;
585
586 TRACE();
587
588 if (sizeof(struct vbsf_mount_info_new) > PAGE_SIZE)
589 {
590 printk(KERN_ERR
591 "Mount information structure is too large %lu\n"
592 "Must be less than or equal to %lu\n",
593 (unsigned long)sizeof (struct vbsf_mount_info_new),
594 (unsigned long)PAGE_SIZE);
595 return -EINVAL;
596 }
597
598 err = register_filesystem(&vboxsf_fs_type);
599 if (err)
600 {
601 LogFunc(("register_filesystem err=%d\n", err));
602 return err;
603 }
604
605 rcVBox = VbglR0HGCMInit();
606 if (RT_FAILURE(rcVBox))
607 {
608 LogRelFunc(("VbglR0HGCMInit failed, rc=%d\n", rcVBox));
609 rcRet = -EPROTO;
610 goto fail0;
611 }
612
613 rcVBox = VbglR0SfConnect(&client_handle);
614 if (RT_FAILURE(rcVBox))
615 {
616 LogRelFunc(("VbglR0SfConnect failed, rc=%d\n", rcVBox));
617 rcRet = -EPROTO;
618 goto fail1;
619 }
620
621 rcVBox = VbglR0SfSetUtf8(&client_handle);
622 if (RT_FAILURE(rcVBox))
623 {
624 LogRelFunc(("VbglR0SfSetUtf8 failed, rc=%d\n", rcVBox));
625 rcRet = -EPROTO;
626 goto fail2;
627 }
628
629#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
630 if (!follow_symlinks)
631 {
632 rcVBox = VbglR0SfSetSymlinks(&client_handle);
633 if (RT_FAILURE(rcVBox))
634 {
635 printk(KERN_WARNING
636 "vboxsf: Host unable to show symlinks, rc=%d\n",
637 rcVBox);
638 }
639 }
640#endif
641
642 printk(KERN_DEBUG
643 "vboxsf: Successfully loaded version " VBOX_VERSION_STRING
644 " (interface " RT_XSTR(VMMDEV_VERSION) ")\n");
645
646 return 0;
647
648fail2:
649 VbglR0SfDisconnect(&client_handle);
650
651fail1:
652 VbglR0HGCMTerminate();
653
654fail0:
655 unregister_filesystem(&vboxsf_fs_type);
656 return rcRet;
657}
658
659static void __exit fini(void)
660{
661 TRACE();
662
663 VbglR0SfDisconnect(&client_handle);
664 VbglR0HGCMTerminate();
665 unregister_filesystem(&vboxsf_fs_type);
666}
667
668module_init(init);
669module_exit(fini);
670
671/* C++ hack */
672int __gxx_personality_v0 = 0xdeadbeef;
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette