I'm looking to make a custom filesystem for a project I'm working on. Currently I am looking at writing it in Python combined with fusepy, but it got me wondering how a compiled non-userspace filesystem is made in Linux. Are there specific libraries that you need to work with or functions you need to implement for the mount command to work properly. Overall I'm not sure how the entire process works.
Yup you'd be programming to the kernel interfaces, specifically the VFS layer at a minimum. Edit Better link [1]
'Full' documentation is in the kernel tree: http://www.mjmwired.net/kernel/Documentation/filesystems/vfs.txt. Of course, the fuse kernel module is programmed to exactly the same interface
This, however, is not what you'd call a library. It is a kernel component and intrinsically there, so the kernel doesn't have to know how a filesystem is implemented to work with one.
[1] google was wrong: the first hit wasn't the best :)
If you'd like to write it in Python, fuse is a good option. There are lots of tutorials for this, such as the one here: http://sourceforge.net/apps/mediawiki/fuse/index.php?title=FUSE_Python_tutorial
In short: Linux is a monolithic kernel with some module-loading capabilities. That means that every kernel feature (filesystems, scheduler, drivers, memory management, etc.) is part of the one big program called Linux. Loadable modules are just a specialized way of run-time linking, which allows the user to pick those features as needed, but they're all still developed mostly as a single program.
So, to create a new filesystem, you just add new C source code files to the kernel code, defining the operations your filesystem has to perform. Then, create an initialization function that allocates a new instance of the VFS structure, fills it with the appropriate function pointers and registers with the VFS.
Note that FUSE is nothing more than a userlevel accessible API to do the same, so the FUSE hooks correspond (roughly) to the VFS operations.
Related
I need to load a C function pointer from a dynamic library for use in my Swift app.
The loading code doesn't have to be Swift, I just need a usable function pointer.
I can do this via dlsym:
let handle = dlopen(theLibrary, RTLD_NOW)
let fun = dlsym(handle, functionName)!
let casted = unsafeBitCast(unsafeBitCast(fun, to: IMP.self), to: (#convention(c)() -> Void).self)
dlclose(handle)
However, I'm concerned about the security of doing this. If the loaded code is being pulled from the dynamic library into my app's process, won't the loaded code have the same permissions as my app's? So, if I disabled app sandbox, couldn't the loaded code modify the users files or make network requests or worse like my app could?
I'm looking for plugin functionality here so I may not get to see the loaded dylibs actual source code, so ideally need a way to restrict the dylib's permissions to prevent possible malware running under the permissions of my app.
How can I either enforce security restrictions on a dylib prior to loading it, or lock-down loaded function pointer code?
Edit Craig Estey makes a very good point that even dlopen can be dangerous.
This is a good question, and a very difficult one to fully address. Most of my answer is, well first thoughts on the topic, however hopefully it will give you ideas on how to proceed.
With Vanilla Kernels
Generally speaking once the code is linked into your binary (e.g. through dynamic loading, it will run with the permissions of your app); You would need the operating system kernel to provide some facility to mark that code "special" somehow in order to restrict the capabilities whilst you're in the context of the plugin.
Darwin
I am not sure if Darwin kernel has the granularity of namespaces that we find e.g. under Linux (which may or may not be enough as well). However you could use end-point-security API available under OS X 11.5 or above to monitor your self. The simple side-channel attack on that is the plugin would unhook you teehee.
Linux
You would set up a new namespace, say using setns and spawn a thread in it after limiting its access and downgrading the context and require the plugin to communicate via an IPC channel rather than direct function calls.
Write a kext
Bad and rather impractical idea. However you could write a kext that tracks and drops the process into a sandbox and then lifts it back up. The only way that would work would be to have an ioctl on a special nonce (e.g. a file descriptor) that is passed from the kernel to the privileged code. The code would then drop down to a sandbox do its job, and release the nonce (e.g. close the file) and that would lift it back up. During this time the code will not be allowed to perform any type of code injection loading of other dlls, spawning of threads, etc. (you would have do a deep dive on possible attack vectors and close them all) that would let the plugin insert trampoline code on the return address of the stack. Here too I would simply say spawn off a new sub-thread or a sub-process that uses IPC rather than communicating through a function call interface.
once the nonce is dropped the app is then reelevated to privileged mode.
I'm working on a LKM which needs to retrieve and write a certain set of information to files. I looked up common ways to do so, but could not find a working one for Linux 4.x. I also found out that it is possible to retrieve system calls from memory and effectively call them.
As I found currently no better way I'd be interested if it'd be feasible to find the system call table, and call open, read/write and close this way.
This is strongly discouraged in most situations.
https://www.linuxjournal.com/article/8110 was a really good read for me the first time I thought I had to do this as well.
From within the Linux kernel, however, reading data out of a file for configuration information is considered to be forbidden. This is due to a vast array of different problems that could result if a developer tries to do this.
Indeed this is possible to do using system calls from within the kernel, but the practice of calling system calls from within the kernel is also generally discouraged. They're designed as interfaces for userspace applications to ask things of the kernel, not for the kernel to get itself to do work.
What kind of files do you want to manipulate from within the kernel? If the kind of file you'd like to manipulate is provided by the proc filesystem or the sysfs filesystem or the dev filesystem, you can modify the contents of the file from within the kernel (since the kernel provides these to userspace itself) -- this should be done NOT with file manipulation calls. If it's a normal userspace file, almost never do you want the kernel to be able to modify it.
If you provide more specifics I'd be interested to hear them, but this is usually a bad idea.
I am going to implement a file system in C and i'm wondering how can i test it without installing it in the kernel nor using FUSE API. Ideally what i'd like to do is to use dd command to create a virtual hard drive and interact with it using linux system calls like write and read (the idea is to not write drivers). Is that posible?
(I'm sorry if i misspelled words, but eanglish isn't my first language. Also i'm sorry if this is off-topic, it's my first question)
Thanks.
If you are really implementing a file system, you can test it in virtual machine.
Otherwise, you can implement a file system in a file which exist in real file system, and implement some functions like read/write/etc...
Virtual hard drive and virtual filesystem are a bit different things, - you write different functions and handle different requests when implementing them. Given that you implement a filesystem, your best bet on linux is to expose your filesystem via FUSE for testing. Then write different tests that will access your FUSE-based filesystem to perform various tasks.
Unfortunately testing a filesystem is hard and requires writing many tests. Manual testing with different software (file managers) is also required.
Okay, I'm reading about Linux kernel development and there are some code snippets using kernel's data structures and stuff. Let's say I'd like to experiment with them, e.g. there's a very simple snippet:
#include <../../linux-2.6.37.1/include/linux/sched.h>
struct task_struct *task;
for_each_process(task) {
printk("%s[%d]\n", task->comm, task->pid);
}
Seems pretty simple, eh? Now then, I can't possibly build the thing. I am using NetBeans. The sched.h is the correct file as if one can CTRL+clicks on it, one is brought to the right file.
Do I need to include somehow my sample file and build the whole kernel from the Makefile? I just wished to see that it builds and possibly that it would work. If I need to build the whole kernel how would I actually test my stuff?
I must be making something really stupid as I am very new to kernel development. I am quite a bit lost.
Thanks guys!
You do not need to compile the whole kernel, but you have to at least create a kernel module, which is far easier to compile. You should have a look at a tutorial, such as this, or even a full blown book like this.
Keep in mind that not all kernel code can be moved to a module - just those that use the public (exported) interfaces of the kernel. Code that is intrinsic to the kernel core parts (e.g. the VM or the scheduler) is probably inaccessible from the rest of the kernel.
Also keep in mind that trying out kernel code on your development machine is not advised - a
slight mistake can easily bring the whole system down. You should look at trying out your kernel code in a separate virtual machine e.g. in VirtualBox.
A detail that makes thing harder: in general you can only insert a module in the kernel that it was built for. A module compiled on the host system can be used on the testing VM if and only if the kernel is identical, i.e. the same kernel package version from the same distribution. Considering that you will want to upgrade your host distribution, in my opinion it is just simpler to build the module on the testing system.
Since you need a full development suite for C, you should probably install one of the popular Linux distrbutions. It should be more stable and you can have access to its user community. If you want to keep its size down, you can just install the base system without an X server or graphical applications.
BTW Netbeans is designed to develop userspace applications. You can probably adapt it for kernel code, but it will never be as suited as it is for userspace programming. As a matter of fact, no IDE is really suitable. Kernel code cannot be run from userspace (let alone using a separate VM), which breaks down the normal edit->compile->run->debug workflow cycle that IDEs automate.
Most kernel developers just use a souped-up editor with syntax highlighting for C, such as Vim or Emacs. Emacs is actually an IDE (and so much more) but, as I mentioned above, you cannot easily use an IDE-based workflow for kernel code development.
You can build a loadable kernel module if you don't want to build the whole kernel - e.g. see http://www.linux-tutorial.info/modules.php?name=Howto&pagename=Module-HOWTO.
All the code you write, compile and run as user programs run as ... well, user programs, in user mode. The kernel runs in kernel mode. Both modes are separated and cannot see each other directly. They communicate through defined interfaces. These interfaces are the C system calls (as opposed to the C library calls).
To be able to access the task_struct structures, your code has to be running in kernel mode. The best choice for this is to write a kernel module, and to load it in the kernel.
Very little kernel code can run outside the kernel in any form. Most kernel code is very 'intertwingled' (to use a phrase I learned from a coworker years ago to describe excessive coupling) with other portions of kernel code. Functions 'know' structure definitions for many many structures away from what they are working on. Typical software engineering people hate code like this:
if (unlikely(inode_init_always(sb, inode))) {
if (inode->i_sb->s_op->destroy_inode)
inode->i_sb->s_op->destroy_inode(inode);
else
kmem_cache_free(inode_cachep, inode);
return NULL;
}
This routine has to know how to destroy inodes through three structures and the calling convention of a function pointer on the other end of the chain. The kernel community knows all these functions very well, and are quite happy to modify member names in structures all throughout the kernel when changes are made, but this sort of tight coupling makes running portions of the kernel in userspace on their own extremely difficult. (And believe me, sometimes I wish I could write tests on my small portions of kernel code that would run in userspace.)
If you want to play around, it's not too hard to get a virtual system up and running these days with qemu+kvm or virtualbox or uml to try making modifications to the kernel. It is pretty hard to just "play" with structures on a live running system, but it is much more feasible than trying to compile portions of the kernel in userspace.
Good luck. :)
You might enjoy using systemtap as a wrapper for small bits of kernel module code:
# stap -g -e 'probe begin { your_function() exit() }
%{
#include <linux/whatever.h>
%}
function your_function() %{
... insert safe c code here ...
%}'
It can automatically cross-compile too (if you use stap --remote=VIRTMACHINE ...).
The term has several definition according to Wikipedia, however what I'm really interested in is creating a program that has all its needed dependencies included within the source folder, so the end user doesn't need to install additional libraries for the app to install. For example, how Mac apps has all its dependencies all within the program itself already...
or is there a function that autotools does this? I'm programming in the Linux environment...
Are you talking about the source code of your application, or about your application binary?
The answer I'd give for both the cases depends on what libraries you're using.
If you're using libraries that you can find anywhere, that are somehow standard and/or that are quite big, you shouldn't attach them to your application, just require them both to build and to run your application.
Anyway don't be much concerned about your source code: little people will build your application, and they probably know something about programming and how a Linux system works; it won't be a big deal to require many (also not-so-common) dependences to build your application.
For what concerns the binary version it could be a little more problematic, since it will be used by end users who often don't know anything about libraries and programming stuff: you could choose to statically link the smallest and most uncommon libraries to your binary, in order to have less dependences.
You could do it, if you link statically, but it'd be somewhat unusual, and depending on what your program is supposed to do, you might be limiting yourself.
The alternative, if this is not just a one-off project, is to create a Linux Standard Base compatible RPM package and restrict yourself to linking against the libraries and symbols that LSB defines.
Run ldd on your program to discover all dependencies, then copy these to your directory, and add a program-wrapper script that issues
#!/bin/sh
LD_LIBRARY_PATH="${0##*/}:$LD_LIBRARY_PATH" exec "${0##*/}/real-program" "$#";
Duplicating the Mac OS X .app behavior on a plain POSIX system is difficult because it is very hard to guarantee that a process can find it's own executable (there are several way that will almost always work...). Mac OS X provides a OS service for this, but Linux (for instance) does not.
Once you've accomplished that feat, this becomes possible. Though, as others have mentioned, it loses the ability to share resource demands (disk space, RAM space, cache space) with other programs that use the same libraries because you'd be using static copies, or dynamically loading your own copy from the .app-like bundle.