This library provides a stable polyfill for Rust's Strict Provenance experiment.

Related tags

Utilities sptr
Overview

sptr: The Strict Provenance Polyfill

crates.io

This library provides a stable polyfill for Rust's Strict Provenance experiment.

Mapping to STD APIs:

// core::ptr (sptr)
pub fn invalid(addr: usize) -> *const T;
pub fn invalid_mut(addr: usize) -> *mut T;

// core::pointer (sptr::Strict)
pub fn addr(self) -> usize;
pub fn with_addr(self, addr: usize) -> Self;
pub fn map_addr(self, f: impl FnOnce(usize) -> usize) -> Self;

// NON-STANDARD EXTENSIONS (feature = uptr)
sptr::uptr
sptr::iptr

// NON-STANDARD EXTENSIONS (feature = opaque_fn)
sptr::OpaqueFn

// DEPRECATED BY THIS MODEL in core::pointer (sptr::Strict)
// (disable with `default-features = false`)
pub fn to_bits(self) -> usize;
pub fn from_bits(usize) -> Self;

Swapping between the two should be as simple as switching between sptr:: and ptr:: for static functions. For methods, you must import sptr::Strict into your module for the extension trait's methods to overlay std. The compiler will (understandably) complain that you are overlaying std, so you will need to also silence that as seen in the following example:

#![allow(unstable_name_collisions)]
use sptr::Strict;

let ptr = sptr::invalid_mut::<u8>(1);
println!("{}", ptr.addr());

By default, this crate will also mark methods on pointers as "deprecated" if they are incompatible with strict_provenance. If you don't want this, set default-features = false in your Cargo.toml.

Rust is the canonical source of definitions for these APIs and semantics, but the docs here will vaguely try to mirror the docs checked into Rust.

Comments
  • One-way address exposure for FFI

    One-way address exposure for FFI

    Hi!

    I am maintaining rust code that provides direct access to the linux syscalls. In a lot of scenarios the linux kernel uses u64 for pointers to make sure 32bit/64bit mixed systems have a single ABI (kernel calls workarounds for it 'compat'-mode). In other scenarios, unsigned long or u64 basically contain unions of lots of different argument options. If I understood correctly, there is no inherent conflict with strict provenance, though I struggle to properly implement it.

    I understand that the recommendation is to make FFI calls take a pointer-type as argument, even if the other side takes an unsigned long (or similar). However, what if the full set of possible arguments is either too big or unknown? In my case, I have syscall0() up to syscall6() which corresponds to the libc syscall(...) function. They are implemented in rust with inline assembly and simply take 0 to 6 usize arguments. No external linkage required at all. On top, I have typed per-syscall wrappers. But under strict provenance, I cannot implement the typed-wrappers but have to resort to expose_addr(), even though I never use from_exposed_addr(). I want to avoid implementing the syscall stubs in C or other FFI. This is pure rust (minus inline assembly).

    My ideal solution would be a way to take a pointer in rust and format it as an integer of my choice. I am fine with it still being a pointer, but I want it to be formatted like a u64 (or another integer of my choice bigger than usize, depending on platform). I can then pass it to the syscall and be done with it. Alternatively, there must be some state-change that miri/etc. apply to a pointer passed through FFI, and I would be fine calling the same function on that pointer. Something like publish_addr() that tells miri/etc. to assume the address was exposed via FFI.

    Note that formatting the value as union does not work here. For instance, assume a big-endian 32bit architecture with a 64bit syscall argument. The union would look like this:

    #[repr(C)]
    union Arg {
        ptr: *mut core::ffi::c_void,
        int: u64,
    }
    

    Assigning a pointer to Arg.ptr would differ from assigning its address to Arg.int, since on big-endian the 32bit Arg.ptr would be aligned to the start of the union, while in Arg.int the lower 32bits would be at the end of the union (I could use ptrs: [*mut core::ffi::c_void; 2] and store in the right bucket, but not sure that is the right solution?).

    So I am a bit out of ideas what to do and looking for help! Thanks David

    opened by dvdhrm 5
  • `expose_addr` is marked as `#[must_use]`

    `expose_addr` is marked as `#[must_use]`

    I noticed that expose_addr is marked as #[must_use] even though in some cases the returned value won't be used.

    My use case involves using mmap to get a large chunk of memory with a specific alignment so that any references to values placed in that memory can be used to compute the start address of that memory (where some metadata is located and from which relative offsets can be added).

    So in this case, expose_addr is used once after getting the memory from mmap and later the address to provide to from_exposed_addr is independently computed.

    opened by Imberflur 4
  • use transmute for ptr.addr

    use transmute for ptr.addr

    Syncs with https://github.com/rust-lang/rust/pull/97710

    Once https://github.com/rust-lang/miri/issues/2133 is complete, this then correctly implements the distinction between addr and expose_addr, as well as between invalid and from_exposed_addr. Misuses of these APIs are detected by Miri, and ptr-int-ptr roundtrips only work if you use expose_addr and from_exposed_addr. :)

    opened by RalfJung 3
  • Support MSRV 1.31

    Support MSRV 1.31

    As a polyfill, it makes sense for this crate to try to support older rustc as much as possible. I was able to get it back to Rust 1.31 without any compromises, but any older would have to deal with conditional support for const fn.

    opened by cuviper 2
  • AtomicPtr support

    AtomicPtr support

    We have strict provenance APIs for AtomicPtr in the stdlib, but not in sptr.

    I think its reasonably likely that the last two get renamed, since the name is rather misleading at the moment. It might be worth leaving them out, since they can be replicated in terms of fetch_byte_{add,sub} anyway.

    I don't really know how to shim this best. The most "accurate" way would be in terms of fetch_update that uses with_addr in it's closure. But this would... kinda destroy performance. An approach that special-cases miri might be worth using.

    I'll try to PR these next weekend I guess, but if someone else feels like taking it they should feel free.

    opened by thomcc 0
Owner
Aria Beingessner
Aria Beingessner
A strict, yet friendly mocking library for Rust 2018

Mockiato A strict, yet friendly mocking library for Rust 2018 ⚠️ Disclaimer for working with stable rust Mockiato relies on the unstable proc_macro_di

Mockiato 228 Dec 30, 2022
Proof of Concept / Experiment: Use IDF-HAL-LL from bare metal Rust

Proof of Concept / Experiment: Use IDF-HAL-LL from BM Rust idf-ll-compile pre-compiles a static library for ESP32C3 and ESP32 esp-ll a simple crate th

Björn Quentin 0 Aug 11, 2022
Error context library with support for type-erased sources and backtraces, targeting full support of all features on stable Rust

Error context library with support for type-erased sources and backtraces, targeting full support of all features on stable Rust, and with an eye towards serializing runtime errors using serde.

Findora Foundation 1 Feb 12, 2022
A lean, minimal, and stable set of types for color interoperation between crates in Rust.

This library provides a lean, minimal, and stable set of types for color interoperation between crates in Rust. Its goal is to serve the same function that mint provides for (linear algebra) math types.

Gray Olson 16 Sep 21, 2022
A cross-platform serial port library in Rust. Provides a blocking I/O interface and port enumeration including USB device information.

Note: This is a fork of the original serialport-rs project on GitLab. Please note there have been some changes to both the supported targets and which

Serialport 128 Jan 4, 2023
A rust interval arithmetic library which provides flags that detect domain errors.

intervals-good A Rust interval arithmetic library which provides flags that detect domain errors, supports more functions than any other interval arit

Oliver Flatt 3 Jul 27, 2022
Rust crate which provides direct access to files within a Debian archive

debarchive This Rust crate provides direct access to files within a Debian archive. This crate is used by our debrep utility to generate the Packages

Pop!_OS 11 Dec 18, 2021
hy-rs, pronounced high rise, provides a unified and portable to the hypervisor APIs provided by various platforms.

Introduction The hy-rs crate, pronounced as high rise, provides a unified and portable interface to the hypervisor APIs provided by various platforms.

S.J.R. van Schaik 12 Nov 1, 2022
This plugin provides an interface for storing unencrypted values on the application cache folder.

Tauri Plugin Store This plugin provides an interface for storing unencrypted values on the application cache folder. Architecture This repo shape migh

Tauri 128 Jan 1, 2023
Rust crate that provides a convenient macro to quickly plot variables.

Debug Plotter This crate provides a convenient macro to quickly plot variables. Documentation For more information on how to use this crate, please ta

Fabian Bösiger 82 Dec 31, 2022
Provides utility functions to perform a graceful shutdown on an tokio-rs based service

tokio-graceful-shutdown IMPORTANT: This crate is in an early stage and not ready for production. This crate provides utility functions to perform a gr

null 61 Jan 8, 2023
archive-rs provides a generic way of dealing with multiple archive and compression formats in Rust

archive-rs A Rust crate that aims to provide a generic way of dealing with multiple archive and compression formats by providing a generic abstraction

S.J.R. van Schaik 2 Nov 21, 2021
A Rust crate that provides a simple interface for LZMA compression and decompression.

rust-lzma Documentation This crate provides a simple interface to liblzma. LZMA is more commonly known as XZ or 7zip, (as in, files with the .xz or .7

null 52 Nov 26, 2022
Stack buffer provides alternatives to Buf{Reader,Writer} allocated on the stack instead of the heap.

StackBuf{Reader,Writer} Stack buffer provides alternatives to BufReader and BufWriter allocated on the stack instead of the heap. Its implementation i

Alex Saveau 14 Nov 20, 2022
untyped-arena provides an Arena allocator implementation that is safe and untyped with minimal complexity

untyped-arena untyped-arena provides an Arena allocator implementation that is safe and untyped with minimal complexity Usage let arena = Arena::new()

Max Bruce 1 Jan 9, 2022
Stdto provides a set of functional traits for conversion between various data representations.

Stdto stdto provides a set of functional traits for conversion between various data representations. | Examples | Docs | Latest Note | stdto = "0.13.0

Doha Lee 5 Dec 21, 2022
Scaffold that provides a basic setup for a Yew app with DaisyUI for styling.

Yew and Tailwind CSS Scaffold This scaffold provides a basic setup for a Yew app with Tailwind CSS for styling. It also includes DaisyUI, a Tailwind C

Alessio Marchi 6 Mar 3, 2023
UnlimCloud provides unlimited cloud storage for your files, utilizing Telegram as the storage solution

UnlimCloud provides unlimited cloud storage for your files, utilizing Telegram as the storage solution. Simply log in using your Telegram ID, and you are good to go.

inulute 5 Nov 27, 2023
A library to compile USDT probes into a Rust library

sonde sonde is a library to compile USDT probes into a Rust library, and to generate a friendly Rust idiomatic API around it. Userland Statically Defi

Ivan Enderlin 40 Jan 7, 2023