← Back to context

Comment by eikenberry

2 years ago

And this is generally a bad pattern unless those libc equivalents are services you call (like syscalls) and not a library you have to import or FFI. Requiring importing a library, probably from another language, is not a good alternative to syscalls.

A bad pattern according to whom? Most language runtime libraries import other system libraries as needed. For better or for worse, libc is typically considered to be a system library. It's something that every distribution or Unix flavor provides that is guaranteed to work within the POSIX standard for interfacing with the operating system. It's up to the distribution maintainers to make that happen, even if they tweak things to support syscall pinning or seccomp rules.

Userland directly calling a stable syscall API is a rare thing outside of Linux, and there is no guarantee that it will last forever even in Linux given the latest attacks. With modern ROP mitigations like syscall pinning, it will in fact be more dangerous to make syscalls directly -- if allowed in your distribution -- than it would be to call the minimal footprint of libc required to bootstrap a high level language runtime.

Of course, with special pleading, it could be possible for distribution or OS maintainers to carve out an exception for syscall pinning for a particular language runtime. Ask Go how that's going for their OpenBSD port.

  • The problem with system libraries requiring importing them as C libraries isn't new and doesn't seem to be going away. It has caused all sorts of problems for alternative languages over the years that it seems like an alternative would give all of computing a giant boost by allowing different models that don't work well with C. Stabilizing and standardizing the syscall interfaces would be one way to accomplish this and is the closest thing we have to it now. Implementing syscalls as a separate service might also work but then you have the IPC overhead. That might not be as bad though as we'll end up with something like that anyways as requirements ramp up for C to have it's own runtime (eg. https://dslab.epfl.ch/research/cpi/).

    • For most language runtimes, the minimal requirement for libc integration is to cover the standard Unix calls (unistd) which don't require specific memory management and typically just pass buffers directly from the caller to the kernel. For most of the system calls in which a high level language runtime would be interested, the libc code is largely a direct pass-through already. As such, either directly using the system calls or calling them through libc will have negligible impact on how the high level language chooses to model these things.

      libc isn't really getting in the way here.

      Perhaps POSIX might come up with an alternative library to wrap system calls in the future, but I would suspect that it would probably be written in C on most platforms, or at least using a C compatible ABI. So, even if a platform chose to use Rust with a large littering of unsafe all over to make it work with the kernel, it would still have to be able to be linked with C userland.

      1 reply →

  • > there is no guarantee that [syscall stability] will last forever even in Linux given the latest attacks

    That's true, but what of it? Linus won't last forever, Linux won't last forever, computers won't last forever, and Homo sapiens won't last forever. Everything needs maintenance sooner or later. "The Rockies may crumble / Gibraltar may crumble / They're only made of clay."

    • What you say is true, but you've inserted an inaccurate context with the quote.

      There is no guarantee that _direct access to system calls_ will last forever...

      Stability in the syscall API exists because Linux is a kernel that supports multiple distributions. Not because random applications could call it. The latter is an emergent feature, but not one that distribution maintainers will necessarily respect. POSIX only guarantees access to functions in libc that can perform these calls. As mentioned elsewhere in this thread, there are specific reasons why future direct access to system calls in user code could be restricted. Whether they will or not comes down to how distribution maintainers decide to deal with syscall related ROP gadgets.

No, it’s fine. And common, macOS and Windows do the same.

  • To be fair, linking to kernel32 is a bit different than linking to msvcrt, but yeah, it’s Linux who’s the slightly insane person in the room, not the other way around.