Write my own 'everything is a file' interface - linux

I would like to expose the settings and statistics of my program in a 'everything is a file' manner - sort of how /proc/ and /sys/ works.
As an example, imagine for a moment that apache2 had this type of interface. You would then be able to do something like this (hypothetical):
cd /apache2/virtual_hosts
mkdir 172.20.30.50
cd 172.20.30.50
echo '/www/example1' > DocumentRoot
echo 'www.example1.com' > ServerName
echo 1 > control/enabled
cat control/status
enabled true
uptime 4080
hits 0
Now, are there any tutorials or similar on how to do this? I'm mainly looking for techniques for 'pretending to be a file or dir'. I'm on linux, POSIX or other more portable method would be preferable, but not required.

On Linux, have a look at Fuse: implement a fully functional filesystem in a userspace program.
Simple library API
Simple installation (no need to patch or recompile the kernel)
Secure implementation
Userspace - kernel interface is very efficient
Usable by non privileged users
Runs on Linux kernels 2.4.X and 2.6.X
Has proven very stable over time
Look at compatible platforms here. In terms of tutorial, one of good ones I've came across is here.

In addition to FUSE, another solution is to export a 9p filesystem. wmii does this, for example.

Perhaps the way to do this is just use "real" files and use a change-notification library (inotify preferred) to detect when they change and update your behaviour accordingly.
The /proc and /sys are for kernel-user communication and not really intended for userspace programs' IPC - you're expected to use named pipes, sockets, shared memory etc for that.
(ab)using FUSE is not really a nice idea in this case, I think.

Related

linux kernel driver debug log

I'm writing a Linux kernel driver for a device that has quite a bit going on and a bunch of interaction from user-space. In order to debug and troubleshoot these interactions I'm storing them in a data array in the driver and need to export this data to user-space via some sort of file node. It'd be great if I could just export the binary data and let user-space parse it into human-readable text but the requirement from other parties involved is to have this done in-driver so one can just cat the file node from the command line and get something readable.
Currently I'm just using a sysfs node but I'm pretty sure that's the wrong place for that sort of thing and I need to able to write out more than PAGE_SIZE of data. What is the proper filesystem object I should be using for this type of thing? I looked at debugfs but it seems to be for more specific things much like sysfs is.
I think the best way is to use the debugfs as its developed just for debugging purpose and only people with the necessary permission which you can decide will be able to access it.
So go ahead with using debugfs

What is proc and sysfs entries

I'd like to learn about proc and sysfs entries.
So far, what I have understood is that, proc entries are the values which is set to proc file system. I'm not sure whether I'm correct. Could anyone explain it in detail about its real need and where it is used? Please provide me links to know it better. Any kind of guidance is accepted.
The /proc filesystem is a special, software-created filesystem that is used by the kernel to export information to the world. Each file under /proc is tied to a kernel function that generates the file's "contents" on the fly when the file is read. We have already seen some of these files in action; /proc/modules, for example, always returns a list of the currently loaded modules.
/proc is heavily used in the Linux system. Many utilities on a modern Linux distribution, such as ps, top, and uptime, get their information from /proc. Some device drivers also export information via /proc, and yours can do so as well. The /proc filesystem is dynamic, so your module can add or remove entries at any time.
Fully featured /proc entries can be complicated beasts; among other things, they can be written to as well as read from. Most of the time, however, /proc entries are readonly files. This section concerns itself with the simple read-only case. Those who are interested in implementing something more complicated can look here for the basics; the kernel source may then be consulted for the full picture.
Before we continue, however, we should mention that adding files under /proc is discouraged. The /proc filesystem is seen by the kernel developers as a bit of an uncontrolled mess that has gone far beyond its original purpose (which was to provide information about the processes running in the system). The recommended way of making information available in new code is via sysfs. As suggested, working with sysfs requires an understanding of the Linux device model, however, and we do not
source - http://tjworld.net/books/ldd3/#UsingTheProcFilesystem
u can look at the ldd3 for more detailes.
it is often used as a tool for debuging the device drivers.
i am a newbie.
good luck.

How to run aout on linux?

The question is how to execute aout-format binary (I mean old format which for example used on FreeBSD before it has migrated to ELF) on Linux system. Is there a possibility to do so without extra coding (is there some existing solution)? Probably it should be in form of kernel module or patch for the Linux kernel. Another solution could be user-space launcher (may be even run-time linker). I have searched for something similar but was unable to found something. I have not yet checked difference in system calls interfaces, if you have some comments about that, you are welcome to provide them.
P.S. I know that writing user-space launcher for aout static binary is quite trivial but the question is about some existing solution.
Check for CONFIG_BINFMT_AOUT in your kernel config.
If your kernel has /proc/config.gz:
zgrep CONFIG_BINFMT_AOUT /proc/config.gz
On Ubuntu and the like:
grep CONFIG_BINFMT_AOUT /boot/config-$(uname -r)
Kernel option was CONFIG_BINFMT_AOUT, not sure if it's still around or necessary.

Run an untrusted C program in a sandbox in Linux that prevents it from opening files, forking, etc.?

I was wondering if there exists a way to run an untrusted C program under a sandbox in Linux. Something that would prevent the program from opening files, or network connections, or forking, exec, etc?
It would be a small program, a homework assignment, that gets uploaded to a server and has unit tests executed on it. So the program would be short lived.
I have used Systrace to sandbox untrusted programs both interactively and in automatic mode. It has a ptrace()-based backend which allows its use on a Linux system without special privileges, as well as a far faster and more poweful backend which requires patching the kernel.
It is also possible to create a sandbox on Unix-like systems using chroot(1), although that is not quite as easy or secure. Linux Containers and FreeBSD jails are a better alternative to chroot. Another alternative on Linux is to use a security framework like SELinux or AppArmor, which is what I would propose for production systems.
We would be able to help you more if you told as what exactly it is that you want to do.
EDIT:
Systrace would work for your case, but I think that something based on the Linux Security Model like AppArmor or SELinux is a more standard, and thus preferred, alternative, depending on your distribution.
EDIT 2:
While chroot(1) is available on most (all?) Unix-like systems, it has quite a few issues:
It can be broken out of. If you are going to actually compile or run untrusted C programs on your system, you are especially vulnerable to this issue. And if your students are anything like mine, someone WILL try to break out of the jail.
You have to create a full independent filesystem hierarchy with everything that is necessary for your task. You do not have to have a compiler in the chroot, but anything that is required to run the compiled programs should be included. While there are utilities that help with this, it's still not trivial.
You have to maintain the chroot. Since it is independent, the chroot files will not be updated along with your distribution. You will have to either recreate the chroot regularly, or include the necessary update tools in it, which would essentially require that it be a full-blown Linux distribution. You will also have to keep system and user data (passwords, input files e.t.c.) synchronized with the host system.
chroot() only protects the filesystem. It does not prevent a malicious program from opening network sockets or a badly-written one from sucking up every available resource.
The resource usage problem is common among all alternatives. Filesystem quotas will prevent programs from filling the disk. Proper ulimit (setrlimit() in C) settings can protect against memory overuse and any fork bombs, as well as put a stop to CPU hogs. nice(1) can lower the priority of those programs so that the computer can be used for any tasks that are deemed more important with no problem.
I wrote an overview of sandboxing techniques in Linux recently. I think your easiest approach would be to use Linux containers (lxc) if you dont mind about forking and so on, which don't really matter in this environment. You can give the process a read only root file system, an isolated loopback network connection, and you can still kill it easily and set memory limits etc.
Seccomp is going to be a bit difficult, as the code cannot even allocate memory.
Selinux is the other option, but I think it might be more work than a container.
Firejail is one of the most comprehensive tools to do that - it support seccomp, filesystem containers, capabilities and more:
https://firejail.wordpress.com/features-3/
You can use Qemu to test assignments quickly. This procedure below takes less than 5 seconds on my 5 year old laptop.
Let's assume the student has to develop a program that takes unsigned ints, each on their own line, until a line with "-1" arrives. The program should then average all the ints and output "Average: %f". Here's how you could test program completely isolated:
First, get root.bin from Jslinux, we'll use that as the userland (it has the tcc C-compiler):
wget https://github.com/levskaya/jslinux-deobfuscated/raw/master/root.bin
We want to put the student's submission in root.bin, so set up the loop device:
sudo losetup /dev/loop0 root.bin
(you could use fuseext2 for this too, but it's not very stable. If it stabilizes, you won't need root for any of this)
Make an empty directory:
mkdir mountpoint
Mount root.bin:
sudo mount /dev/loop0 mountpoint
Enter the mounted filesystem:
cd mountpoint.
Fix rights:
sudo chown -R `whoami` .
mkdir -p etc/init.d
vi etc/init.d:
#!/bin/sh
cd /root
echo READY 2>&1 > /dev/ttyS0
tcc assignment.c 2>&1 > /dev/ttyS0
./a.out 2>&1 > /dev/ttyS0
chmod +x etc/init.d/rcS
Copy the submission to the VM:
cp ~/student_assignment.c root/assignment.c
Exit the VM's root FS:
cd ..
sudo umount mountpoint
Now the image is ready, we just need to run it. It will compile and run the submission after booting.
mkfifo /tmp/guest_output
Open a seperate terminal and start listening for guest output:
dd if=/tmp/guest_output bs=1
In another terminal:
qemu-system-i386 -kernel vmlinuz-3.5.0-27-generic -initrd root.bin -monitor stdio -nographic -serial pipe:/tmp/guestoutput
(I just used the Ubuntu kernel here, but many kernels will work)
When the guest output shows "READY", you can send keys to the VM from the qemu prompt.
For example, to test this assignment, you could do
(qemu) sendkey 1
(qemu) sendkey 4
(qemu) sendkey ret
(qemu) sendkey 1
(qemu) sendkey 0
(qemu) sendkey ret
(qemu) sendkey minus
(qemu) sendkey 1
(qemu) sendkey ret
Now Average = 12.000000 should appear on the guest output pipe. If it doesn't, the student failed.
Quit qemu: quit
A program passing the test is here: https://stackoverflow.com/a/14424295/309483. Just use tcclib.h instead of stdio.h.
Try User-mode Linux. It has about 1% performance overhead for CPU-intensive jobs, but it may be 6 times slower for I/O-intensive jobs.
Running it inside a virtual machine should offer you all the security and restrictions you want.
QEMU would be a good fit for that and all the work (downloading the application, updating the disk image, starting QEMU, running the application inside it, and saving the output for later retrieval) could be scripted for automated tests runs.
When it goes about sanboxing based on ptrace (strace) check-out:
"sydbox" sandbox and "pinktrace" programming library ( it's C99 but there are bindings to python and ruby as far as I know).
Collected links related to topic:
http://www.diigo.com/user/wierzowiecki/sydbox
(sorry that not direct links, but no enough reputation points yet)
seccomp and seccomp-bpf accomplish this with the least effort: https://www.kernel.org/doc/Documentation/prctl/seccomp_filter.txt
ok thanks to all the answers they helped ME a lot. But i would suggest none of them as an solution for the person who asked the original question. All mentioned tools require to much work for the purpose to test students code as a teacher,tutor,prof. The best way in this case would be in my opinion virtualbox. Ok, its emulates an complete x68-system and has nothing to do with the meaning of sandboxing in this way but if i imagine my programming teacher it would be the best for him. So "apt-get install virtualbox" on debian based systems, all others head over to http://virtualbox.org/ , create a vm, add an iso, click install, wait some time and be lucky. It will be much easier to use as to set up user-mode-linux or doing some heavy strace stuff...
And if you have fears about your students hacking you i guess you have an authority problem and a solution for that would be threaten them that you will sue the living daylights out of them if you can prove just one bite of maleware in the work they give you...
Also if there is a class and 1% of it is as good as he could do such things, dont bore them with such simple tasks and give them some big ones where they have to code some more. Integrative learning is best for everyone so dont relay on old deadlocked structures...
And of cause, never use the same computer for important things (like writing attestations and exams), that you are using for things like browsing the web and testing software.
Use an off line computer for important things and an on line computer for all other things.
However to everyone else who isnt a paranoid teacher (dont want to offend anybody, i am just the opinion that you should learn the basics about security and our society before you start being a programmers teacher...)
... where was i ... for everyone else:
happy hacking !!

Linux - mounting a user space file system(mimicking one :-) ) as a FileSystem

I have a piece of C code which with a chunk of memory(static array) can mimic file operations (It has APIs similar to fopen/fclose etc). So, any code that is compiled with this mimicking FileSystem can use these APIs as a FileSystem for all their needs :)
But I was wondering, if its possible somehow to register these APIs with Linux system/mouning this File system, and hence enabling any client to use this FS by using normal FileSystem calls (without any need of statically linking it with the My_FileSystem).
While searching for a solution, I came across this idea of making my_FileSystem as a Driver!!! =>
Is it possible to compile my code as a device driver (with the memory chunk in the driver) and mount this File_system # say "/mnt/MyFs", and divert FileSystem calls like USB drivers do? (If this can be done, can you please explain how its done or point me to somewhere I can read about this).
I don't want to add these as new System calls and recompile the kernel (And making life of ppl wanting to use this difficult).
This is mainly for embedded systems running Linux... But other suggestions are also welcome. :)
Thank You,
MicroKernel :)
Look at FUSE (Filesystem in Userspace), especially on examples. Its quite easy...
Take a look at tmpfs and ramfs. These already ship with Linux and do all that you're trying to do and more. I don't think either of them would be too expensive for an embedded system.
I would consider PlasticFS, but that will work reliably only if everything uses system C library (i.e. no statically linked binaries).

Resources