Presentation is loading. Please wait.

Presentation is loading. Please wait.

How to write a Samba VFS module

Similar presentations


Presentation on theme: "How to write a Samba VFS module"— Presentation transcript:

1 How to write a Samba VFS module
Jeremy Allison Samba Team

2 Why write a VFS module ? The Samba fileserver (smbd) consists of an upper layer SMB1/2/3+ parsing layer, a asynchronous state machine, a file system access layer (VFS), and a host of helper functions. ALL filesystem access in smbd goes through interposable, stackable VFS functions. This allows complete redirection of every access to the filesystem. Gives complete control over exported filesystem – very powerful concept. VFS modules can be end points (non-stackable) or pass- through (modifying all aspects of the data flow).

3 Great Programmers are Lazy and they Steal
Start by looking at existing VFS modules. There are 61 .c files inside the source3/modules/ directory Maybe someone already wrote the thing you need. If not, take a look and see if you can adapt what is already there to something you need. There are existing modules that do many different activities with pathname, remote backends etc. The best code is code you don't have to write !

4 So you have to write a VFS module
Isolate the functionality you need to change. Does the existing VFS interface work for you ? Existing interface is defined in source3/include/vfs.h If you need to modify anything in there, or referenced in there, you must update the #define SMB_VFS_INTERFACE_VERSION (currently at 37). Remember, within a major release stream X.Y.Z (X.Y is the major release ID) the VFS ABI must remain fixed. No interface changes allowed with minor (.Z) releases. This allows existing binary modules to keep working. If you need an interface change, you must wait for a major release.

5 Building – The Basics An easy way to start is to copy an example module from examples/VFS/ - e.g. skel_transparent.c Copy into source3/modules/vfs_my_module.c Samba uses the waf (python based) build system. Your new module needs an entry inside of the wscript_build file in source3/modules/. Pretty easy to cut-and-paste a similar stanza from an existing module and adjust to fit. Add a DBG_XX(0,) statement so you can see if it loads. Ensure your module builds and test it before doing anything else. Load into a share by adding: vfs objects = my_module

6 VFS Module lifecycle All modules start with a vfs_my_module_init() function. Just call smb_register_vfs() to add your function table. On each new connect to the share you're attached to (SMB2_OP_TCON), the connect_fn() is called. On disconnect (SMB2_OP_TDIS) disconnect_fn() is called. Note this does not unload the module from memory space, merely asks you to release resources from the connection. These functions are called as root. You can do anything here.

7 Share Connection Resource Management
All functions get passed struct vfs_handle_struct. pointer that can be used to hang module-specific structures from. Useful for storing configuration data. talloc() your structure off handle->conn, then store using SMB_VFS_HANDLE_SET_DATA(handle,..) macro. If you use a talloc'ed struct, add a destructor for cleanup (old SMB_VFS_HANDLE_FREE_DATA now deprecated). All subsequent calls can get access to this data using SMB_VFS_HANDLE_GET_DATA(handle,..) macro.

8 Module Parameters Samba has a host of useful functions to allow modules to pull module-specific parameters from smb.conf. Parameters look like: modulename:parameter = value Check out lp_parm_XXX() functions in source3/include/proto.h Anything from an enum, bool, int, string or even string list can be read. Functions take the module name and the parameter name, return the value. Common use is to read on connect, then cache on long lived module-private handle struct.

9 File Handle Resource Management
One of the main SMB2 functions is Create – converts a pathname to a handle. Internally represented as files_struct. On creation of a handle a module private data struct can be added to the files_struct pointer using the following macros. VFS_ADD_FSP_EXTENSION() VFS_GET_FSP_EXTENSION() Use these to store extra meta-data associated with a particular file (study vfs_fruit.c for details).

10 Stacking or not ? If you're writing a module that is designed to filter pathnames/data in some way, you must be careful to ensure it can be stacked. NO direct calls to filesystem functions (open/close/read/write) etc. Everything must go though the SMB_VFS_NEXT_XXX() macros. Simple example: vfs_audit.c. Passes though calls then calls syslog() with the result. Pathname modification example: vfs_catia.c. Modifies all pathname-based calls via a mapping function, then calls _NEXT().

11 Non-stackable modules
Non-stackable modules must be listed last in the vfs objects smb.conf line (modules are called in order). Used for final redirection to a non-local filesystem such as Gluster or Ceph. An SMB2 → other protocols (NFSv4?) converter is a possibility here. The vfs_default.c module is non-stackable by definition as it is the final link in the chain. At least the last module must access persistent storage somewhere.

12 Pathnames and process state
Pathnames are passed into VFS calls as struct smb_filename. Contains $cwd-relative pathname. Windows :STREAM name. Bitfield of flags (currently only one, POSIX_PATH). Stat struct for an existing file. Planning to add snapshot timestamp. Due to symlink security race condition, $cwd is no longer left at root of share – changes for open() calls. Remember for threaded backends. $cwd is process-wide. Current $cwd may be read from handle->conn->cwd.

13 Asynchronous calls Get familiar with talloc and tevent.
Main Samba libraries used for allocation/resource management and asynchronous (event-based) programming. All Samba daemons are big state machines internally. Some (mostly read and write) VFS calls return tevent_req structures. E.g. pread_send()/pread_recv(). As smb.conf parameters control whether a read is allowed to be async implementors must also implement sync versions also Although internally you can fake sync using async :-)

14 Asynchronous calls continued
Care must be taken with process global state (might change between XXX_send() invocation and XX_recv() reply). Look at defer_rename() code in source3/smbd/smb2_setinfo.c More VFS calls are planned to be converted to asnyc XX_send()/XX_recv() format. Depends on being able to break up the NTFS emulation layer inside smbd. With multi-channel and expansion of channel processing by smbd, expect more complexity here. Protocol structure makes things hard here. Multiple credentials multiplexed down one client connection.

15 Threaded backends The pthreadpool library (Volker Lendecke created) is widely used inside Samba to control worker threads. DO NOT CALL back into Samba functions from worker threads. Most of Samba is thread-unsafe. All current use of threads in smbd VFS modules purely call system calls/thread-safe C library functions. A worker thread module usually is an end-point VFS module. Look into source3/smbd/aio.c and source3/modules/vfs_aio_pthread.c for an example of this.

16 Care with global state In traditional POSIX, process credentials (uid, gid-list) and the current working directory are process global state. Modern POSIX works around $cwd state by using XXXat() pathname functions, which take a file descriptor from which the rest of the path is relatively processed. This works well within threads. seteuid() and friends are a MUCH bigger problem. On Linux threads can have per-thread credentials. By default glibc changes credentials across all threads in a process on seteuid() call. For a real horror show, look into glibc seteuid() code on Linux.

17 Credentials In order to make per-thread credentials work in Samba, smbd makes direct Linux system calls for all credential changing. Avoids the nightmare code in glibc. This doesn’t work on FreeBSD (or any other UNIX). Ganesha (userspace NFS server) avoids this by doing everything as root, then changing ownership of filesystem objects afterwards. Eventually we might move to adding credentials to the stored state for XX_send()/XX_recv() calls. If you need to use become_root()/unbecome_root(). Use sparingly.

18

19 Calls into Samba All Samba utility functions are available from non-threaded VFS backend code. Many utility functions here: unfortunately many are not documented. A few examples: parent_dirname(), tdb library, wide character string library, errno → NTSTATUS conversion. If you need it, someone probably already wrote it. Ask for help ! Someone in the Team will know this. The more familiar you are with Samba code the easier this will get.

20 The good, the bad, and the ugly
Good vfs modules: vfs_fruit: You can learn a lot from this ! vfs_btrfs: Good example of how to make use of advanced Linux filesystem specific features. Bad vfs module: nfs4_acls, vfs_posix_aio: They work but I wish we didn’t need them. Ugly: vfs_shadow_copy2: Read this and then do everything differently.

21 Licensing and Legal ALL Samba VFS modules must be GPLv3
“Ah crap, that breaks my business plan”. Code that is called by Samba VFS modules may or may not have to be GPLv3. The devil is in the details. Now follows an off the record discussion about MY PERSONAL VIEWS on where this boundary lies. Engineering and lawyering is usually an immiscible fluid.

22 Questions and Comments ?
Slides available at:


Download ppt "How to write a Samba VFS module"

Similar presentations


Ads by Google