# Idea: expose Linux raw syscall interface in std::os::linux

**URL:** <https://internals.rust-lang.org/t/idea-expose-linux-raw-syscall-interface-in-std-linux/10614>\
**Category:** libs\
**Created:** [July 22, 2019, 8:20pm UTC](https://internals.rust-lang.org/t/idea-expose-linux-raw-syscall-interface-in-std-linux/10614 "2019-07-22T20:20:14Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![newpavlov](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/newpavlov/32/3290_2.png) [@newpavlov](https://internals.rust-lang.org/u/newpavlov)\
**Post date:** [July 22, 2019, 8:20pm UTC](https://internals.rust-lang.org/t/idea-expose-linux-raw-syscall-interface-in-std-linux/10614/1 "2019-07-22T20:20:15Z")

</div>

I think it may be useful to expose raw syscall interface for Linux. Right now to use syscall functionality your either have to go via `libc` wrappers, which in turn forces us to use "[broken](https://yarchive.net/comp/linux/errno.html)" `errno` (it's quite funny how syscalls essentially use `Result`-like interface, but we still have to go via `errno`), or use Nightly. API can be as simple as [7 functions](https://docs.rs/syscall/0.2.1/syscall/platform/index.html) and maybe a set of [convenience constants](https://docs.rs/syscall/0.2.1/syscall/platform/nr/index.html).

Why we may need it? For example for experiments with new syscalls (e.g. `io_uring`) or for writing lightweight crates and libraries. Eventually it may be used for implementing [`libc`-free `std`](https://internals.rust-lang.org/t/crazy-idea-incrementally-porting-linux-std-to-syscalls/10404).

What do you think?

UPD: The relevant [PR](https://github.com/rust-lang/rust/pull/63745) got rejected, read this [message](https://internals.rust-lang.org/t/idea-expose-linux-raw-syscall-interface-in-std-linux/10614/23) if you interested in alternative approaches.

---

<div class="post-metadata">

**Author:** ![josh](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/josh/32/5934_2.png) [@josh](https://internals.rust-lang.org/u/josh)\
**Post date:** [July 22, 2019, 8:53pm UTC](https://internals.rust-lang.org/t/idea-expose-linux-raw-syscall-interface-in-std-linux/10614/2 "2019-07-22T20:53:29Z")

</div>

I'd like to see this as well, to common up the underlying interface. (I'd like to see it in `core`, ideally, not `std`, because it enables writing applications directly to the syscall interface.)

One major reason to do this: doing it in a crate requires nightly to invoke inline assembly, but exposing this interface in `core` could occur in stable Rust (because `core` and `std` can use nightly features in their implementation). Having the minimal wrappers available would enable crates to supply safer interfaces atop that, such as wrappers for each syscall, or standardized error handling.

(I'd love to standardize the error handling as well, since _every_ syscall has a standard interface of `-1` to `-4095` for error codes, but that would require some bikeshedding on what the resulting error types look like.)

---

<div class="post-metadata">

**Author:** ![newpavlov](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/newpavlov/32/3290_2.png) [@newpavlov](https://internals.rust-lang.org/u/newpavlov)\
**Post date:** [July 22, 2019, 9:01pm UTC](https://internals.rust-lang.org/t/idea-expose-linux-raw-syscall-interface-in-std-linux/10614/3 "2019-07-22T21:01:04Z")

</div>

> [@josh](#):
>
> I'd like to see it in `core` , ideally, not `std` , because it enables writing applications directly to the syscall interface

I am not sure about this. Right now `core` is completely OS-agnostic and I don't think we should break it with syscalls. I think we better work in direction of incrementally making `std` `libc`-independent (or introduce a separate target like it was proposed [here](https://github.com/rust-lang/rfcs/issues/2610)).

---

<div class="post-metadata">

**Author:** ![josh](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/josh/32/5934_2.png) [@josh](https://internals.rust-lang.org/u/josh)\
**Post date:** [July 22, 2019, 9:12pm UTC](https://internals.rust-lang.org/t/idea-expose-linux-raw-syscall-interface-in-std-linux/10614/4 "2019-07-22T21:12:26Z")

</div>

I can understand that, but that would then make this unusable for some common use cases.

While I'd certainly like to work towards making std `libc`-independent, that doesn't help when trying to build without the rest of `std`. I would _love_ to have a modular `std`, as envisioned by some of the `std`-aware cargo proposals. But I'd like to have a usable solution for stable syscalls before that point.

What would go horribly wrong if an OS-specific `core::os` existed, just like `std::os`? What would that break?

---

<div class="post-metadata">

**Author:** ![kornel](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kornel/32/2711_2.png) [@kornel](https://internals.rust-lang.org/u/kornel)\
**Post date:** [July 22, 2019, 10:46pm UTC](https://internals.rust-lang.org/t/idea-expose-linux-raw-syscall-interface-in-std-linux/10614/5 "2019-07-22T22:46:41Z")

</div>

Could it be a third crate? e.g `stdlinux` crate that depends on `core`?

Rust [already ships private crates](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=262319989e87f5747dab773bc4b755db), so I presume it could ship such crate not marked as private.

---

<div class="post-metadata">

**Author:** ![josh](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/josh/32/5934_2.png) [@josh](https://internals.rust-lang.org/u/josh)\
**Post date:** [July 22, 2019, 10:53pm UTC](https://internals.rust-lang.org/t/idea-expose-linux-raw-syscall-interface-in-std-linux/10614/6 "2019-07-22T22:53:41Z")

</div>

I mean, it _could_ be (nit: should be a more general name), but should it be? Is there some reason it _shouldn't_ be in core?

---

<div class="post-metadata">

**Author:** ![HadrienG](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/hadrieng/32/3294_2.png) [@HadrienG](https://internals.rust-lang.org/u/HadrienG)\
**Post date:** [July 23, 2019, 6:09am UTC](https://internals.rust-lang.org/t/idea-expose-linux-raw-syscall-interface-in-std-linux/10614/7 "2019-07-23T06:09:59Z")

</div>

I thought the point of core was to only expose bare-metal-friendly std functionality which doesn't rely on the presence of an underlying OS/runtime.

From this perspective, exposing syscalls in core would be philosophically strange.

On the other hand, it could be argued that core::arch is an existing example of functionality in core which relies on the presence of specific system resources to function properly.

In an ideal world, there would be `core` + various optional modules with runtime requirements (including Linux syscalls), and using `std` would just be a convenience shorthand for using `core` with all the bells and whistles that can be normally expected of the target platform...

---

<div class="post-metadata">

**Author:** ![josh](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/josh/32/5934_2.png) [@josh](https://internals.rust-lang.org/u/josh)\
**Post date:** [July 23, 2019, 7:11pm UTC](https://internals.rust-lang.org/t/idea-expose-linux-raw-syscall-interface-in-std-linux/10614/8 "2019-07-23T19:11:38Z")

</div>

`core::arch` is indeed very similar. So is `core::ffi`.

The description of `core` says "It links to no upstream libraries, no system libraries, and no libc.".

Raw Linux syscalls don't require linking to a library, and if you're building for a Linux target, having a `core::os` module doesn't seem drastically different than `core::arch`. `core::os` would only invoke some assembly. If appropriately inlined, ideally syscalls will compile down to "make sure the arguments end up in the appropriate registers, then invoke a `syscall` instruction".

To the best of my knowledge, while people expect `core` to compile and run without a memory allocator, and to be _possible_ to compile and run without an OS, that doesn't mean a _compiled build_ of `core` is expected to be OS-independent. As far as I know, there's no degree to which people expect `core` from `x86_64-unknown-linux-gnu` to work on `x86_64-pc-windows-gnu`, for instance; you'd need a separate build of core for that target. So I don't see any obvious issue with having a `core::os` module that contains additional target-specific items, which doesn't exist on other targets.

In any case, I think this is getting a little off-topic from the original point.

I'd very much like to see `syscall` functions introduced into Rust's standard library. I'd be happy to help.

---

<div class="post-metadata">

**Author:** ![fintelia](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/fintelia/32/3558_2.png) [@fintelia](https://internals.rust-lang.org/u/fintelia)\
**Post date:** [July 29, 2019, 12:19am UTC](https://internals.rust-lang.org/t/idea-expose-linux-raw-syscall-interface-in-std-linux/10614/9 "2019-07-29T00:19:24Z")

</div>

Another thing to consider is that `syscall` is a variadic function: in addition to the syscall number it also takes between 0 and 7 other arguments. The standard library is allowed to use nightly features so I don't think it would be a problem necessarily, but it might be worth trying to avoid.

---

<div class="post-metadata">

**Author:** ![josh](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/josh/32/5934_2.png) [@josh](https://internals.rust-lang.org/u/josh)\
**Post date:** [July 29, 2019, 12:22am UTC](https://internals.rust-lang.org/t/idea-expose-linux-raw-syscall-interface-in-std-linux/10614/10 "2019-07-29T00:22:26Z")

</div>

The proposal in this thread is to have functions `syscall0` through `syscall6`, not a variadic function.

---

<div class="post-metadata">

**Author:** ![dhm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/dhm/32/4879_2.png) [@dhm](https://internals.rust-lang.org/u/dhm)\
**Post date:** [July 29, 2019, 10:07am UTC](https://internals.rust-lang.org/t/idea-expose-linux-raw-syscall-interface-in-std-linux/10614/11 "2019-07-29T10:07:24Z")

</div>

> [@fintelia](#):
>
> Another thing to consider is that `syscall` is a variadic function: in addition to the syscall number it also takes between 0 and 7 other arguments. The standard library is allowed to use nightly features so I don't think it would be a problem necessarily, but it might be worth trying to avoid.

The thread mentions the API of the [`::syscall`](https://docs.rs/syscall/0.2.1/syscall/) crate: it provides seven functions of different arity (`syscall0`, ..., `syscall6`), and a macro to cast the arguments to `usize` and dispatch to the right function.

---

<div class="post-metadata">

**Author:** ![derekdreery](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/derekdreery/32/2632_2.png) [@derekdreery](https://internals.rust-lang.org/u/derekdreery)\
**Post date:** [July 29, 2019, 3:24pm UTC](https://internals.rust-lang.org/t/idea-expose-linux-raw-syscall-interface-in-std-linux/10614/12 "2019-07-29T15:24:14Z")

</div>

Not sure if it's relevant but there was some discussion of exposing some arm assembly instructions through the stdlib, things like wait for interrupt `wfi`, that you can't do without assembly. The two other choices are nightly + inline assembly, or separate files + linking + accepting the cost of calling a function.

---

<div class="post-metadata">

**Author:** ![spease](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/spease/32/3042_2.png) [@spease](https://internals.rust-lang.org/u/spease)\
**Post date:** [July 30, 2019, 5:59pm UTC](https://internals.rust-lang.org/t/idea-expose-linux-raw-syscall-interface-in-std-linux/10614/13 "2019-07-30T17:59:06Z")

</div>

Sounds like the better solution here is to fix the libc error handling implementation, which is incidentally easier because it’s a crate and not std.

Putting this in core sounds very wrong, since I understand core to be a minimal subset of standard.

Both of these proposals seem to impose permanent long-term compatibility complications in response to a temporary problem (assembly not available on stable). Seems like it might be better to accelerate inline assembly, which is probably holding other crates back, than to start moving more stuff into std/core as a workaround to use it.

---

<div class="post-metadata">

**Author:** ![notriddle](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/notriddle/32/14082_2.png) [@notriddle](https://internals.rust-lang.org/u/notriddle)\
**Post date:** [July 30, 2019, 8:57pm UTC](https://internals.rust-lang.org/t/idea-expose-linux-raw-syscall-interface-in-std-linux/10614/14 "2019-07-30T20:57:46Z")

</div>

> [@spease](#):
>
> Sounds like the better solution here is to fix the libc error handling implementation

According to [the link in newpavlov's post](https://yarchive.net/comp/linux/errno.html), the `errno` handling isn't a bug in rust's libc bindings. It's claiming that POSIX `errno` semantics are inherently undesirable.

---

<div class="post-metadata">

**Author:** ![bascule](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/bascule/32/3057_2.png) [@bascule](https://internals.rust-lang.org/u/bascule)\
**Post date:** [July 30, 2019, 9:25pm UTC](https://internals.rust-lang.org/t/idea-expose-linux-raw-syscall-interface-in-std-linux/10614/15 "2019-07-30T21:25:26Z")

</div>

> [@spease](#):
>
> Both of these proposals seem to impose permanent long-term compatibility complications in response to a temporary problem (assembly not available on stable).

That seems like a misinterpretation of the goals to me. I think it'd be particularly interesting to support static linking of pure Rust executables on Linux (i.e. without musl).

That said I don't think this belongs in `core`. But it might make sense in `std`, and serve as a foundation for supporting static linking of pure Rust executables with at least a subset of `std` functionality available without the need for musl.

---

<div class="post-metadata">

**Author:** ![spease](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/spease/32/3042_2.png) [@spease](https://internals.rust-lang.org/u/spease)\
**Post date:** [July 31, 2019, 1:04am UTC](https://internals.rust-lang.org/t/idea-expose-linux-raw-syscall-interface-in-std-linux/10614/16 "2019-07-31T01:04:07Z")

</div>

Static linking is fine, but I don’t see why this couldn’t be done as a separate no\_std crate if the nightly features were stabilized. You can still statically link I’d you use third-party crates.

---

<div class="post-metadata">

**Author:** ![fintelia](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/fintelia/32/3558_2.png) [@fintelia](https://internals.rust-lang.org/u/fintelia)\
**Post date:** [July 31, 2019, 4:06pm UTC](https://internals.rust-lang.org/t/idea-expose-linux-raw-syscall-interface-in-std-linux/10614/17 "2019-07-31T16:06:09Z")

</div>

I like the idea of including this in core. It seems more useful there than in std where you already have higher level OS abstractions (and can fallback to libc::syscall if you really need to). The constants for Linux syscall numbers however seems like a much better fit for an external library.

I'd be willing to believe that there are applications targeting exotic OS's that would need to make syscalls, but otherwise wouldn't need any fancy assembly. With this proposal they'd be able to run on a stable compiler, which otherwise wouldn't be possible because inline assembly has been stuck in nightly only for years now and doesn't look to be changing any time soon. Further even if they run on nightly, it isn't like there'd be a ton of variability in the implementation of a syscall() function, I have an almost identical one to the proposal [here in my own code](https://github.com/mit-pdos/RVirt/blob/1ee60adc980394bb2a2780e87428c3874ea62640/src/riscv/sbi.rs#L3).

---

<div class="post-metadata">

**Author:** ![newpavlov](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/newpavlov/32/3290_2.png) [@newpavlov](https://internals.rust-lang.org/u/newpavlov)\
**Post date:** [August 20, 2019, 2:36pm UTC](https://internals.rust-lang.org/t/idea-expose-linux-raw-syscall-interface-in-std-linux/10614/18 "2019-08-20T14:36:48Z")

</div>

I've published a Rust PR with the cnages: [https://github.com/rust-lang/rust/pull/63745](https://github.com/rust-lang/rust/pull/63745)

---

<div class="post-metadata">

**Author:** ![gnzlbg](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/gnzlbg/32/3858_2.png) [@gnzlbg](https://internals.rust-lang.org/u/gnzlbg)\
**Post date:** [September 8, 2019, 12:44pm UTC](https://internals.rust-lang.org/t/idea-expose-linux-raw-syscall-interface-in-std-linux/10614/19 "2019-09-08T12:44:59Z")

</div>

Why can't you use a `#![no_std]` crate from [crates.io](http://crates.io) that exposes this ?

---

<div class="post-metadata">

**Author:** ![newpavlov](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/newpavlov/32/3290_2.png) [@newpavlov](https://internals.rust-lang.org/u/newpavlov)\
**Post date:** [September 8, 2019, 3:29pm UTC](https://internals.rust-lang.org/t/idea-expose-linux-raw-syscall-interface-in-std-linux/10614/20 "2019-09-08T15:29:48Z")

</div>

See my reply in the PR thread.

[Next page](https://internals.rust-lang.org/t/idea-expose-linux-raw-syscall-interface-in-std-linux/10614.md?page=2)
