Can bash be used to communicate directly with hardware? - linux

I am interested in writing my own tool in bash to act in place of my current network controller (wpa_supplicant) if possible. For example if I want to issue commands in order to begin a wps authentication session with a router's external registrar, is it possible, without using any pre-built tools, to communicate with the kernel to directly access the hardware? I have been told that I can achieve what I desire with a bash plugin called ctypes.sh but I am not too certain.

Generally speaking, the Linux kernel can interact with user-space through the following mechanisms:
Syscalls
Devices in /dev
Entries in /sys
Entries in /proc
Syscalls cannot be directly used from Bash but you need at least a binding through a C program.
You can create a Linux kernel driver or module which reads/writes data in an entry under /proc or /sys and then use a bash program to interact with it. Even if technically feasible, my personal opinion is that it is an overkill, and the usual C/C++ user-level programming with proper entries in /dev is much better.

No, this is generally not possible. Shell scripts can mess around in /proc, but they don't have the ability to perform arbitrary IOCTLs or even multi-step interactive IO. It's the wrong tool for the job.

Related

API for linux /sys nodes

Do all nodes in /sys (and /proc) have an equivalent API? Like an ioctl or a library function. What resource can I use to find those?
Context:
I want to enable RFS by setting values in /proc/sys/net/core/rps_sock_flow_entries and /sys/class/net/<iface>/queues/rx-X/rps_flow_cnt;.
Using those in the terminal or a shell script is ok but it feels wrong in a C program.
Do all nodes in /sys
Yes.
(and /proc) have an equivalent API?
No, but still 99% of them will use POSIX open/read/write operations.
Some of proc entries can be poll or mmap, some not. Also https://elixir.bootlin.com/linux/latest/source/include/linux/proc_fs.h#L29 .
What resource can I use to find those?
Linux Kernel source code and Linux Kernel documentation. Google and internet resources and man pages.

How to trap system calls in a userspace library in Linux?

I have a requirement to write a linux device driver in userspace.
How can I write a library which, when linked to an application, can handle system calls to a particular device.
The application should be able to use open(), read(), write(), ioctl() on a device such as /dev/mydev0, but these calls should terminate in a userspace library instead of a kernel module.
Please advise on if this is possible and how can I achieve this.
Linux is a monolithic kernel which means in general, what you're asking is not possible; you can't write arbitrary drivers in user-mode.
You could (as your title alludes to), use ptrace(2) to trap on system calls, and basically redirect them to functions in your library. That is not a simple, straightforward solution however.
See also:
How to use ptrace(2) to change behaviour of syscalls?
FUSE (Filesystem in USErspace) may be what you're looking for. It's a mechanism that allows filesystem drivers specifically to be implemented via a user-space process. This is how sshfs, for example, is implemented.
Resources:
http://fuse.sourceforge.net/

Do Linux capabilities work with binfmt_misc?

I'm potentially interested in using Linux capabilities for a program (specifically, cap_net_bind_service to allow a program to bind to a TCP port less than 1024).
However, I'd like to do it for a program that is C# running under Mono. Normally, I think that would mean the Mono interpreter itself would need to have the capabilities set on it, rather than the whatever.exe program that it runs.
However, Linux also can have Mono binary kernel support, via the kernel binfmt_misc mechanism.
So, does the kernel binfmt_misc mechanism work with capabilities? That is, so that a particular binfmt_misc-enabled executable file can run with particular capabilities set.
Normally, I think that would mean the Mono interpreter itself would need to have the capabilities set on it[...]
It would take binfmt_misc out of the question if you set capabilities on the process tree in question, rather than on the files.
See cap_set_proc(), and tooling for manipulating it. For instance, if you were using systemd:
[Service]
ExecStart=/usr/bin/mono /path/to/your/executable.exe
User=your_service_account
Capabilities=CAP_NET_BIND_SERVICE

Can containers be implemented purely in userspace?

There are a bunch of container mechanisms for Linux now: LXC, Docker, lmctfy, OpenVZ, Linux-VServer, etc. All of these either involve kernel patches or recently added Linux features like cgroups and seccomp.
I'm wondering if it would be possible to implement similar (OS-level) virtualization purely in userspace.
There's already a precedent for this - User Mode Linux. However, it also requires special kernel features to be reasonably fast and secure. Also, it is literally a Linux kernel running in userspace, which makes networking setup rather difficult.
I'm thinking more along the lines of a process that would act as an intermediary between spawned programs and the Linux kernel. You would start the process with the programs to spawn as arguments; it would track system calls they made, and block or redirect attempts to access the real root filesystem, real network devices, etc. without itself relying on special kernel features.
Is such a thing possible to implement securely, and in a way that could be invoked effectively by a limited user (i.e. not privileged like chroot)?
In summary: would a pure userspace implementation of something like LXC be possible? If yes, what would the penalties be for doing it in userspace? If no, why not?
Surprisingly it turns out the answer is "yes": this is what systrace and sysjail do.
http://sysjail.bsd.lv/
And they are also inherently insecure on modern operating systems.
http://www.watson.org/~robert/2007woot/
So if you want proper sandboxing, it has to be done in kernel space.

Linux - fanotify, but for exec()?

Is there a facility like fanotify, but for exec() operations? Something like kauth in MacOS, but in userland.
fanotify only seems to notify on (and allow/deny) file open/close/read/write.
I've seen code that can notify on fork and exec by other means (also here), but there is no way to allow or deny an exec. Also, it seems there are drawbacks to this approach, because not all kernels are compiled with netlink/proc connector, and it can get overwhelmed with events.
Perhaps you are looking for SELinux, a Linux kernel module which provides the enforcement of fine-grained security policies, like who or what gets to execute a certain file.
Looks like Linux finally added this feature to fanotify in kernel 5.0 (shipped in e.g. Ubuntu 19.04).
See man 2 fanotify_mark for details. The relevant flags are FAN_OPEN_EXEC and FAN_OPEN_EXEC_PERM.
I believe the "Process Events Connector" is what you are looking for. This interface will allow you to receive notifications of fork, exec, and setuid/setguid events.
Read more at LWN (https://lwn.net/Articles/157150/) and a great blog article (not mine) at http://netsplit.com/the-proc-connector-and-socket-filters.

Resources