I remember Synology ships their NAS with custom vendor syscalls that used unassigned syscall numbers at the time, but those numbers are now clashing with real syscalls - causing undefined behaviour when running arbitrary code (e.g. Docker)
So TL;DR only implement custom syscalls if you intend to maintain for all of its consequences in the future.
Synology is a bad example. Many of their custom syscalls are related to filesystem things like btrfs raid5 self repair and carefully removed from their gpl source code. Ianal but imho this is a gpl violation.
Technically, it's not a violation. They're releasing code; just not the code. So long as they (offer to, and then actually) provide the source code on request, licensed under GPLv2, they're allowed to do that.
Though it probably is a violation, because they probably don't do that.
> It's definitely against the license terms. You're supposed to distribute the code that generated the distributed binaries.
It does look like Synology are not abiding by the GPL here, but a minor nitpick: GPL v2 has no such requirement to distribute the source with the binaries. But if you don't, you do have to tell people they can get it and provide it in "machine-readable" format on request.
Lawyers aren't that pedantic. That's why law isn't just some computer program. The point is that human interpretation is important ie: terms like "best efforts", "reasonable doubt", etc.
What you're describing would likely not pass as being a reasonable interpretation of the license.
Don't you think the TL;DR is never add your own syscalls when implementing your own character device driver is almost always the better option if you want something to run in the kernel?
Foolish but that's still a much smarter mistake to make than the ones we've seen from Western Digital exposing system calls over the network where some blogger can root your NAS by sending an abc123 cookie XHR to its unsecured PHP CGI script interface. If the guys making my NAS are smart enough to make mistakes hacking the kernel then that's reassuring.
One suggestion, though: Choose higher syscall numbers. The syscall numbers that this guide uses (334) is already taken in a recent kernel update. Syscalls are added to almost every kernel version, so if you choose, say, syscall #400, in a decade or so you'll have to make a choice between your syscall and the new "official" one.
Yes. A device doesn't even need to support reading and writing. The driver simply registers some name in /dev and the userspace code opens it and does ioctl.
You could also register a name under /proc. There is really no reason to have custom system calls.
The name probably originally came from controlling i/o ports and devices at a meta level. But they're just a mechanism for sending a chunk of data to the kernel, and if something in the kernel is watching that path (e.g. /sys/foobar) then it'll be in invoked.
Wow. I cant believe how simple the building of a custom kernel has become. I fiddled with this 15 years ago and it all seemed very unapproachable at the time.
Interesting, my thought is opposite, that not much has changed - download, unzip, modify (optional), make menuconfig, make, make install, fix grub config, profit. :)
EDIT: it is true however that someone has shown me the steps, I would have wasted a lot of time without their guidance.
Technology has come so far! What used to take overnight on a very expensive new machine can be done in a matter of minutes on a late model laptop. git bisect run, connected to a script that boots a VM to test the kernel is the holy Grail of... something, not sure what, but looking back at how things used to be, that's a feat of software (and hardware, eg CPU vmx extensions) engineering and progress that blows my mind.
I'm a little confused on how this tutorial somehow explains several tasks at completely different levels of difficulty (setting up a VM, installing a compiler via apt-get, modifying/updating the bootloader, building a custom kernel, and finally creating a new syscall) with a relatively constant depth of explanations.
It's difficult for me to judge the usefulness of this guide because I'm familiar with those steps, but I'm wondering if it might have been better to define a more narrow scope for this tutorial with certain prerequisites, and going into detail about the ramifications of adding a new syscall? Especially since I feel the guide barely mentions a few interesting details:
1. Only arch/x86/entry/syscalls/syscall_64.tbl is modified in this tutorial, glossing over the fact that that file only affects x86_64 syscalls (disclaimer: I'm 90% sure on this one, but don't quote me on this). Of course I wouldn't expect the tutorial to explain how to modify all the architecture-specific files, but I'd say this fact is worth noting.
2. The user-space story: The post doesn't mention how to actually use this syscall - even though that's one of the critical parts of a syscall. Essentially, if you call open() in a C program, you're not actually issuing any syscall directly. Rather the C library (e.g. glibc) implements an open() function that internally performs the syscall. This is primarily because many syscalls don't map 1:1 to C library functions, in addition to some differences between platforms and architectures. So if you'd want to use the syscall you'd have to implement a syscall wrapper yourself or use the low-level syscall(2) [1] function that allows you to access system calls not provided by glibc.
There is also some political drama attached to this, essentially the glibc maintainers don't want to implement/provide functions for certain Linux syscalls because of certain reasons (IIRC it's mostly about portability concerns, but I think there are some syscalls that the glibc maintainers just don't like for whatever reason).
3. The "What if you really wanted to add a syscall to Linux?" story, which boils down to: The Linux maintainers don't want to add any new syscalls except in very few cases (because syscalls generally can't be changed once they're introduced). Instead, you're supposed to use more flexible kernel interfaces, such as sysfs or debugfs (or previously, ioctl and procfs, but they're frowned upon nowadays and only used in certain areas). See the Linux documentation on adding syscalls [2].
This tutorial was the perfect level of depth for me — someone who has experience programming but never experienced modifying the Linux kernel. I don’t need a lot of info on setting up a VM or installing tools. I just need info on where the hooks are in the kernel itself. How do you compile it and where do you put the new stuff in?
There aren't very many syscalls in Linux - 335 for x86_64[1], 190 for i386[2], etc. I tend to like GUIDs, but AFAIK it would cause a massive backward-compatibility problem to switch to something other than an integer.
If I'm reading the kernel source[3] correctly, the syscall interface itself accepts a 32-bit unsigned integer for the call number, but only the lowest 16 bits can be used because the upper 16 bits are used to represent the version. That would still mean that something like 80% of the effective ID space is unused at present.
Registering paths in /dev, /proc, or /sys seems like the way to go. Slightly slower than a syscall, because the kernel has to do text comparison with the path (such as /dev/foobar) you're reading/writing/ioctling.
In Linux, the system call number is used as an index into an array of function pointers. Making it a GUID won't really help with table lookup performance -- O(1) random access lookup versus O(log n) binary search.
So TL;DR only implement custom syscalls if you intend to maintain for all of its consequences in the future.
Here's the tweet on Synology - https://twitter.com/RichFelker/status/1357733309737021444