Earlier quoted context omitted.
> One example that immediately comes to mind from Rust is a bug with O_PATH file descriptors I found a while ago[1], which would've made certain code we use in runc not work. [...] Neither of these issues exist in C programs. This issue doesn't intrinsically affect Rust as a language (when compared to C), because you can just do exactly the same thing as you'd have done in C: let fd = libc::open(b"/path\0".as_ptr().c…
I'm aware you can work around it, there are workarounds for issues in Go as well. In general, C programs do not require workarounds for dealing with kernel APIs for the simple reason that the vast majority of kernel APIs are developed with test programs written in C, so kernel developers will usually not design an API that is awful to use in C. Another thing that surprised me when I first started programming in Rust…
Barco: Linux Containers from Scratch in C
71–75 of 75 posts
Re: Barco: Linux Containers from Scratch in C
#72Earlier quoted context omitted.
I'm aware you can work around it, there are workarounds for issues in Go as well. In general, C programs do not require workarounds for dealing with kernel APIs for the simple reason that the vast majority of kernel APIs are developed with test programs written in C, so kernel developers will usually not design an API that is awful to use in C. Another thing that surprised me when I first started programming in Rust…
Where can I learn more about this? This seems very uninutive to me, as I'm learning Rust myself.
This does happen elsewhere in Rust, but often when you have methods on &self that return something you use later, the method returns something with the same lifetime (fn foo(&'a self) -> Foo) and thus the original object will be kept alive until the end of the scope. It just so happens that file descriptors are tied to the lifetime of the File in a way that Rust cannot express nor detect.
I don't know if clippy has a warning for this particular case. It might be useful to add it.
Re: Barco: Linux Containers from Scratch in C
#73Earlier quoted context omitted.
> One example that immediately comes to mind from Rust is a bug with O_PATH file descriptors I found a while ago[1], which would've made certain code we use in runc not work. [...] Neither of these issues exist in C programs. This issue doesn't intrinsically affect Rust as a language (when compared to C), because you can just do exactly the same thing as you'd have done in C: let fd = libc::open(b"/path\0".as_ptr().c…
I'm aware you can work around it, there are workarounds for issues in Go as well. In general, C programs do not require workarounds for dealing with kernel APIs for the simple reason that the vast majority of kernel APIs are developed with test programs written in C, so kernel developers will usually not design an API that is awful to use in C. Another thing that surprised me when I first started programming in Rust…
[0] https://doc.rust-lang.org/std/os/fd/struct.BorrowedFd.html
Re: Barco: Linux Containers from Scratch in C
#74Earlier quoted context omitted.
> One example that immediately comes to mind from Rust is a bug with O_PATH file descriptors I found a while ago[1], which would've made certain code we use in runc not work. [...] Neither of these issues exist in C programs. This issue doesn't intrinsically affect Rust as a language (when compared to C), because you can just do exactly the same thing as you'd have done in C: let fd = libc::open(b"/path\0".as_ptr().c…
I'm aware you can work around it, there are workarounds for issues in Go as well. In general, C programs do not require workarounds for dealing with kernel APIs for the simple reason that the vast majority of kernel APIs are developed with test programs written in C, so kernel developers will usually not design an API that is awful to use in C. Another thing that surprised me when I first started programming in Rust…
And `open` is not a kernel API either. It's a libc API. If you want to directly access the API provided by the kernel you're supposed to make a syscall, which essentially is exactly the same in Rust and in C.
And to make the point of `open` in C *not* being a kernel API more clear, in glibc the `open` function *doesn't* actually call the `open` syscall, but `openat` with `AT_FDCWD`. Glibc doesn't guarantee that a given function will actually call a given syscall, and new versions of glibc often change which syscalls are called by a given function. This is important if you're also doing e.g. seccomp sandboxing, because suddenly your program might stop working if glibc is updated. For example, glibc 2.34 started using the `clone3` syscall under the hood, which broke Chromium Embedded Framework's sandbox.
So, again, your argument that a language like Rust "makes it harder to understand what exactly your program is doing" compared to C in this particular case isn't really valid, because C has exactly the same problem if you use libc functions, and the only way to guarantee that the program is doing exactly what you want is to use syscalls, which is the same both in C and Rust.
> Another thing that surprised me when I first started programming in Rust
Yep. That's one of the Rust's few badly designed APIs.
Re: Barco: Linux Containers from Scratch in C
#75Earlier quoted context omitted.
Possibly, but I'd say that Google's experience with kCTF was that allowing io_uring on hosts running containers has allowed for multiple breakouts. They paid out over $1m on io_uring related bug bounties https://security.googleblog.com/2023/06/learnings-from-kctf-... Also while user namespaces help in theory, in practice expanding the attack surface of the kernel exposed to unprivileged users has consequences in allo…
io_uring was blocked by the default Docker seccomp profile until somewhat recently. The primary issue with io_uring is that there is no mechanism to apply seccomp-like rules. > Also while user namespaces help in theory You should use user namespaces to contain untrusted code, you absolutely should not enable CLONE_NEWUSER inside a container. I was referring to the former, you're talking about the latter.
I'd agree that unprivileged user namespaces should not be available inside containers, however the default stances of some Linux distros (enable unprivileged user namespaces) and Kubernetes (disable the CRIs seccomp filter by default) mean that an awful lot of envirionments will end up in a situation where this is possible.