Importing only safe features from 3rd party crates

Rust is a language people use because it is safe. However, 3rd party rust crates can use the keyword unsafe and deliberately destroy the 'safeness' of rustaceans who trustingly use these non-safe crates.

In the Rust Cargo.toml, when importing a 3rd party crate, is it possible to only import * where the the functions are safe? Leaving unsafefunctions behind? For example

[dependencies] 
futures = {onlysafe = "true",    version="0.3"}

I'm aware that I can put

#![forbid(unsafe_code)]

in my own code. However, I noticed I can import crates that use unsafecode, into my forbid(unsafe_code)project. So this macro does not appear to filter out any unsafe features exposed my project. Am I wrong?

This person demonstrates how to do a buffer over run when you know the name of an unsafe function used in an executable: Tomasz Guz - Playing with buffer overflow in Rust

Would it be fair to say anyone who knows your executable depends on a commonly used library (for example futures) could easily exploit a buffer over run in your program since the unsafe function names are publicly available as open source?

unsafe Rust doesn't "destroy the 'safeness'" of safe Rust... The issue with that buffer-overflow example is not that there is some unsafe involved, but rather that the unsafe code is unsound.

Unsound means that some safety requirements are not met, in particular the ones of ptr::copy. Safe Rust is always sound[1], as the compiler ensures that all safety requirements are met. In unsafe Rust, the responsibility of making sure the code is sound falls on the programmer.

Another responsibility that falls on the programmer is to check that all dependencies are trustworthy. That's hard, I know. There are project that can help with that, such as cargo-audit.

I recommend having a look at the chapters Meet Safe and Unsafe and How Safe and Unsafe Interact of the Rustonomicon.


As an aside, it might be better to ask this kind of questions about the use of Rust on the users forum. This is the internals forum, "a place for discussion about the development of Rust itself"[2].


  1. unless there are bugs in the compiler ↩︎

  2. with words borrowed from Community - Rust Programming Language ↩︎

2 Likes

I'm not sure what the point of this is. The buffer overflow vulnerability comes from using the unsafe function std::ptr::copy to copy a buffer with an attacker-controlled length into a fixed size buffer without performing any checks.

2 Likes

Keep in mind that crates that don't use any unsafe blocks or functions are still able to run arbitrary code that can do unsafe things.

Rust is not a sandbox. Safe/unsafe is for catching honest mistakes of cooperative programmers, and not a barrier for stopping malicious or otherwise dangerous code.

Command that launches arbitrary code is safe. Deletion of files is safe. Reading of files with your cookies and passwords is safe. Messing with Linux /proc filesystem is safe. Linking arbitrary unsafe C code into a Rust program is safe too.

There are known bugs in the Rust compiler and LLVM optimizer that allow "safe" Rust code to execute arbitrary unsafe code. These are weird edge cases that regular users are very unlikely to stumble upon, but malicious authors could exploit them to make crates that pretend to use only safe code, but aren't.

Additionally, Rust is designed to rely on unsafe to make it a fully-functional language. The safe subset of Rust is limited. It's not only for performance, and some things are impossible to do in safe Rust, e.g. the borrow checker can't check iterators returning &mut, and such iterators must use unsafe (or wrap existing iterators/functions that are using unsafe).

12 Likes

that's very true