@@ -8,6 +8,10 @@ references:
88 title : Extern types
99 url : https://rust-lang.github.io/rfcs/1861-extern-types.html
1010 id : RFC-1861
11+ - type : web
12+ title : Memory model
13+ url : https://doc.rust-lang.org/core/ptr/index.html
14+ id : memory-model
1115 - type : web
1216 title : Unwinding
1317 url : https://doc.rust-lang.org/stable/reference/items/functions.html#unwinding
@@ -235,7 +239,7 @@ the specific target platform.
235239
236240[libc]: https://crates.io/crates/libc
237241
238- ### Non-robust types: references, function pointers, enums
242+ ### Non-robust types: references, function pointers, enums {#robustness}
239243
240244A *trap representation* of a particular type is a representation (pattern of
241245bits) that respects the type's representation constraints (such as size and
@@ -311,12 +315,9 @@ LLVM's `-fsanitize=bool` may be used.
311315
312316#### References and pointers
313317
314- Although they are allowed by the Rust compiler, the use of Rust references in
315- FFI may break Rust memory safety. Because their “unsafety” is more explicit,
316- pointers are preferred over Rust references when binding to another language.
317-
318- On the one hand, reference types are very non-robust: they allow only pointers
319- to valid memory objects. Any deviation leads to undefined behavior.
318+ The types &mut T and &T are subject to the same validity requirements as the
319+ type T, with the additional constraint that they must refer to a properly
320+ allocated value. Any deviation leads to undefined behavior
320321
321322When binding to and from C, the problem is particularly severe because C has
322323no references (in the sense of valid pointers) and the compiler does not offer
@@ -331,17 +332,32 @@ Rust references may be used reasonably with other C-compatible languages
331332including C variants allowing for non-null type checking, e.g. Microsoft SAL
332333annotated code.
333334
334- On the other hand, Rust *pointer types* may also lead to undefined behaviors
335- but are more verifiable, mostly against `std/core::ptr::null()` (C's `(void*)0`)
335+ By contrast, Rust’s raw pointer types (`*const T` and `*mut T`) defer validity
336+ checks from the point of binding to the point of use. Furthermore, they allow
337+ validity to be assessed primarily against `std/core::ptr::null()` (C's `(void*)0`)
336338but also in some contexts against a known valid memory range (particularly in
337- embedded systems or kernel-level programming). Another advantage of using Rust
339+ embedded systems or kernel-level programming) or against alignment requirements.
340+
341+ Another advantage of using Rust
338342pointers in FFI is that any load of the pointed value is clearly marked inside
339343an `unsafe` block or function.
340344
341- <div class="reco" id="FFI-NOREF" type="Rule" title="Do not use reference types in a FFI but pointer types">
345+ <div class="reco" id="FFI-CK-PTR-VALID" type="Rule" title="Check foreign pointers">
346+
347+ In a secure Rust development, any Rust code that dereferences a foreign
348+ pointer MUST check their validity beforehand.
349+ In particular, pointers MUST be checked to be non-null before any use.
342350
343- In a secure Rust development, the Rust *low-level* code (the `*-sys` crate) in a FFI MUST NOT use reference types
344- but pointer types.
351+ Stronger approaches are advisable when possible. They include checking
352+ pointers against known valid memory range, tagging (or signing) pointers
353+ (particularly applicable if the pointed value is only manipulated from Rust)
354+ or checking data alignment.
355+
356+ </div>
357+
358+ <div class="reco" id="FFI-INPUT-PTR" type="Recommendation" title="Use raw pointer to encode pointers coming from the external language">
359+
360+ In a secure Rust development, pointers received from the external language SHOULD be encoded by Rust *raw pointers*.
345361
346362Exceptions include:
347363
@@ -354,9 +370,10 @@ Exceptions include:
354370
355371</div>
356372
357- <!-- -->
373+ Where the previous recommendation cannot be applied, pointer validity checks must
374+ be carried out by the language from which the pointer originates (that is, the external language).
358375
359- <div class="reco" id="FFI-CKREF " type="Rule" title="Do not use unchecked foreign references">
376+ <div class="reco" id="FFI-CK-INPUT-REF-VALID " type="Rule" title="Do not use unchecked foreign references">
360377
361378In a secure Rust development, every foreign reference that is transmitted to
362379Rust through FFI MUST be **checked on the foreign side** either automatically
@@ -370,18 +387,6 @@ and manipulated only from the Rust side and `Option`-wrapped references
370387
371388<!-- -->
372389
373- <div class="reco" id="FFI-CKPTR" type="Rule" title="Check foreign pointers">
374-
375- In a secure Rust development, any Rust code that dereferences a foreign
376- pointer MUST check their validity beforehand.
377- In particular, pointers MUST be checked to be non-null before any use.
378-
379- Stronger approaches are advisable when possible. They include checking
380- pointers against known valid memory range or tagging (or signing) pointers
381- (particularly applicable if the pointed value is only manipulated from Rust).
382-
383- </div>
384-
385390The following code a simple example of foreign pointer use in an exported Rust
386391function:
387392
@@ -523,6 +528,77 @@ Example of opaque Rust type:
523528{{#include ../../../examples/src/ffi.rs:opaque_internal}}
524529```
525530
531+ ### Preserving Rust memory model {#ffi-memory-model}
532+
533+ The Rust compiler uses information from the * borrow checker* to optimize code execution.
534+ In doing so, it assumes that the conditions verified by the borrow checker,
535+ in particular the [ aliasing] ( https://doc.rust-lang.org/nomicon/aliasing.html ) rules,
536+ are valid, and it bases its optimizations on these assumptions. More details about this
537+ memory model can be found in the [ ` core ` API documentation @memory-model ] .
538+
539+ Violating these assumptions can therefore lead to the occurrence of UB.
540+
541+ <div class =" reco " id =" FFI-CK-REF-MODEL " type =" Rule " title =" Preservation of Rust’s memory model when transferring indirections at its boundary " >
542+
543+ In secure development in Rust, the use of indirection (pointers, references)
544+ crossing the boundary MUST preserve Rust’s memory model.
545+
546+ </div >
547+
548+ <div class =" example " >
549+
550+ In the following example, the Rust code manipulates pointers originating from C,
551+ showing the importance of respecting Rust’s invariants from the C side.
552+
553+ The ` swap ` function defined below produces undefined behaviour (UB) if it is
554+ called from the following C code, because Rust’s memory model forbids the * aliasing* of mutable references.
555+
556+
557+ ``` rust,noplaypen
558+ {{#include ../../../examples/src/ffi.rs:input_pointer_alias}}
559+ ```
560+
561+ ``` c ub
562+ {{#include ../../../examples/src/ffi.c: input_pointer_alias }}
563+ ```
564+
565+ </div>
566+
567+ <div class="example">
568+
569+ In the following example, the Rust code passes a pointer to C code,
570+ illustrating the importance of reflecting, in Rust’s type system,
571+ the operations performed on the C side.
572+
573+ The imported function `inc_wrap` increments the variable `a`.
574+
575+ ```c
576+ {{#include ../../../examples/src/ffi.c:output_pointer}}
577+ ```
578+ The Rust code passes a pointer to the immutable variable ` val `
579+ to the C function, thereby violating Rust’s memory model and resulting in * UB* .
580+
581+
582+ ``` rust,noplaypen
583+ {{#include ../../../examples/src/ffi.rs:output_pointer}}
584+ ```
585+
586+ In this example, the error could have been detected by placing stronger constraints
587+ on the binding to the C library API, either by modifying its signature directly,
588+ or by wrapping the ` inc_wrap ` function, as in the following example.
589+
590+ ``` rust good
591+ {{#include .. / .. / .. / examples / src / ffi . rs: output_pointer_good }}
592+ ```
593+
594+ The ` safe_inc_wrap ` function is indeed * safe* because:
595+
596+ * any memory value can be interpreted as a value of type ` u8 ` (the ` u8 ` type is [ robust] ( #robustness ) ),
597+ * the type of the ` safe_inc_wrap ` function enforces the * non-aliasing* and * mutability* constraints,
598+ * the C code neither frees the pointer nor “retains” it (via a ` static ` variable, for example) beyond the call to the ` inc_wrap ` function.
599+
600+ </div >
601+
526602## Memory and resource management
527603
528604Programming languages handle memory in various ways. As a result, it is
0 commit comments