Pre-RFC: Mark all APIs that allow access to arbitrary files as unsafe


#1
  • Feature Name: proc_tantrum
  • Start Date: 2016-04-01
  • RFC PR: (leave this empty)
  • Rust Issue: (leave this empty)

Summary

Allowing arbitrary filesystem paths to be opened allows Rust’s memory safety guarantees to be violated (even without administrative/“root” access, which can be considered the platform-provided equivalent of an unsafe block), as demonstrated in #32670. To close this soundness hole, filesystem access by path should be marked unsafe, the same way creating references by memory address is already unsafe.

Motivation

To solve a soundness hole. If this soundness hole is not fixed, then all of the machinery and effort in place to make Rust safe is a complete waste of time, and everybody might as well go back to the pervasive unsafety of C and assembler.

Detailed design

The following methods of accessing arbitrary paths exist in Rust:

  • File::create()
  • File::open()
  • OpenOptions::open()
  • FromRawFd::from_raw_fd() (which is already unsafe)
  • redirecting standard input, output, and error

The first three functions would need to be marked unsafe. Since the fourth is done by the creating process, access to those streams would need to be marked unsafe, which means that the following APIs would additionally need to be marked unsafe:

  • println! and print!
  • panic! and it’s relatives (unreachable!, unwrap(), Box::new, etc)
  • io::stdin(), io::stdout(), io::stderr()

Drawbacks

This would result in a large proliferation of unsafe code, and would break a large number of existing Rust programs.

Alternatives

In the LLVM memory model, reading from padding bytes is undefined behavior, but doing so through the filesystem API is not currently optimized by the compiler, so Rust could possibly get away with only marking the write-level APIs as unsafe and disabling any future LLVM optimizations that would violate this expectation.

We could alternatively give up and get back to writing C++.

Unresolved questions

Now what will we do with our spare time and Mozilla’s research money?


#2

It seem to me the problem is not from Rust but from Linux. So It seems to me that the best solution drop Linux support, to keep it shining on real OS.


#3

The joke could have stopped at the Github issue. Like unsafe, pisstaking should be conservatively scoped.


#4

According to the joke std::process::Command should also be unsafe.

(Actually while implementing that I first tried /proc/self/mem hack, but it didn’t work for me - can read, but can’t write).


#5

If you really want you can abuse any function which interacts with the system / hardware. Firstly I can’t see anything good in marking a function unsafe, which is safe except for this one (or more) explicit abuses which you won’t see in normal everyday code and for which you will definitely think about before you even come up with the idea to use those functions in a way like this. I’m pretty sure no one using /proc/self/mem seriously would do it unknowingly what it can cause / expecting rust to clean up such an interference with the normal memory management.

Secondly this would break the entire eco system as it was already mentioned AND will lead to unsafe{} being the new default opener of functions. Rendering unsafe{}, as a warning, into the typical warning dialog every user simply ignores as it’s popping up in every corner, making it worthless.

Thirdly we would see crates in no time, wrapping the unsafe function into safe ones to get rid of the bloat created by every println!, panic!, unreachable!, unwrap() etc call.

This won’t render rust’s approach making it a safer C useless, if you want to call it like this. In 99% of all other cases it will still work as it’s been doing until now. And as Rust is doing at every pointer, mut and dereference logic, preventing many problems, according to all those questions about lifetimes and why X can’t be done that way.

This is more a joke then a serious RFC / bug. It was a nice april fool, please leave it as one.