Skip to content

Commit ec96121

Browse files
authored
Add safety comments for mmap etc. (#1188)
* Add safety comments for `mmap` etc. Add proper safety comments for `mmap` and related functions. Many of the tricky things around `mmap` are about handing out Rust references to mapped memory, and that technically isn't rustix's responsibility to worry about, so these safety comments can be pretty simple. And, several other miscellaneous documentation and comment cleanups. * Document the new safety precondition for `split_init`.
1 parent 873bac5 commit ec96121

10 files changed

Lines changed: 93 additions & 52 deletions

File tree

.github/workflows/test-users.yml

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ jobs:
112112
rustup target add ${{ matrix.target }}
113113
if: matrix.target != ''
114114

115-
- uses: actions/cache@v3
115+
- uses: actions/cache@v4
116116
with:
117117
path: ${{ runner.tool_cache }}/qemu
118118
key: qemu-${{ matrix.target }}-${{ env.QEMU_BUILD_VERSION }}-patched
@@ -281,7 +281,7 @@ jobs:
281281
rustup target add ${{ matrix.target }}
282282
if: matrix.target != ''
283283

284-
- uses: actions/cache@v3
284+
- uses: actions/cache@v4
285285
with:
286286
path: ${{ runner.tool_cache }}/qemu
287287
key: qemu-${{ matrix.target }}-${{ env.QEMU_BUILD_VERSION }}-patched
@@ -437,7 +437,7 @@ jobs:
437437
rustup target add ${{ matrix.target }}
438438
if: matrix.target != ''
439439

440-
- uses: actions/cache@v3
440+
- uses: actions/cache@v4
441441
with:
442442
path: ${{ runner.tool_cache }}/qemu
443443
key: qemu-${{ matrix.target }}-${{ env.QEMU_BUILD_VERSION }}-patched
@@ -622,7 +622,7 @@ jobs:
622622
rustup target add ${{ matrix.target }}
623623
if: matrix.target != ''
624624

625-
- uses: actions/cache@v3
625+
- uses: actions/cache@v4
626626
with:
627627
path: ${{ runner.tool_cache }}/qemu
628628
key: qemu-${{ matrix.target }}-${{ env.QEMU_BUILD_VERSION }}-patched
@@ -773,7 +773,7 @@ jobs:
773773
rustup target add ${{ matrix.target }}
774774
if: matrix.target != ''
775775

776-
- uses: actions/cache@v3
776+
- uses: actions/cache@v4
777777
with:
778778
path: ${{ runner.tool_cache }}/qemu
779779
key: qemu-${{ matrix.target }}-${{ env.QEMU_BUILD_VERSION }}-patched
@@ -924,7 +924,7 @@ jobs:
924924
rustup target add ${{ matrix.target }}
925925
if: matrix.target != ''
926926

927-
- uses: actions/cache@v3
927+
- uses: actions/cache@v4
928928
with:
929929
path: ${{ runner.tool_cache }}/qemu
930930
key: qemu-${{ matrix.target }}-${{ env.QEMU_BUILD_VERSION }}-patched
@@ -1075,7 +1075,7 @@ jobs:
10751075
rustup target add ${{ matrix.target }}
10761076
if: matrix.target != ''
10771077

1078-
- uses: actions/cache@v3
1078+
- uses: actions/cache@v4
10791079
with:
10801080
path: ${{ runner.tool_cache }}/qemu
10811081
key: qemu-${{ matrix.target }}-${{ env.QEMU_BUILD_VERSION }}-patched
@@ -1226,7 +1226,7 @@ jobs:
12261226
rustup target add ${{ matrix.target }}
12271227
if: matrix.target != ''
12281228

1229-
- uses: actions/cache@v3
1229+
- uses: actions/cache@v4
12301230
with:
12311231
path: ${{ runner.tool_cache }}/qemu
12321232
key: qemu-${{ matrix.target }}-${{ env.QEMU_BUILD_VERSION }}-patched
@@ -1382,7 +1382,7 @@ jobs:
13821382
rustup target add ${{ matrix.target }}
13831383
if: matrix.target != ''
13841384

1385-
- uses: actions/cache@v3
1385+
- uses: actions/cache@v4
13861386
with:
13871387
path: ${{ runner.tool_cache }}/qemu
13881388
key: qemu-${{ matrix.target }}-${{ env.QEMU_BUILD_VERSION }}-patched
@@ -1538,7 +1538,7 @@ jobs:
15381538
rustup target add ${{ matrix.target }}
15391539
if: matrix.target != ''
15401540

1541-
- uses: actions/cache@v3
1541+
- uses: actions/cache@v4
15421542
with:
15431543
path: ${{ runner.tool_cache }}/qemu
15441544
key: qemu-${{ matrix.target }}-${{ env.QEMU_BUILD_VERSION }}-patched
@@ -1759,7 +1759,7 @@ jobs:
17591759
rustup target add ${{ matrix.target }}
17601760
if: matrix.target != ''
17611761

1762-
- uses: actions/cache@v3
1762+
- uses: actions/cache@v4
17631763
with:
17641764
path: ${{ runner.tool_cache }}/qemu
17651765
key: qemu-${{ matrix.target }}-${{ env.QEMU_BUILD_VERSION }}-patched

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ itoa = { version = "1.0.1", default-features = false, optional = true }
2121

2222
# Special dependencies used in rustc-dep-of-std mode.
2323
core = { version = "1.0.0", optional = true, package = "rustc-std-workspace-core" }
24-
rustc-std-workspace-alloc = { version = "1.0.0", optional = true } # not aliased here but in lib.rs casuse of name collision with the alloc feature
24+
rustc-std-workspace-alloc = { version = "1.0.0", optional = true } # not aliased here but in lib.rs because of name collision with the alloc feature
2525
compiler_builtins = { version = '0.1.49', optional = true }
2626

2727
# The procfs feature needs once_cell.

src/backend/libc/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ pub(crate) mod fd {
7878
///
7979
/// [`AsFd`]: https://doc.rust-lang.org/stable/std/os/fd/trait.AsFd.html
8080
pub trait AsFd {
81-
/// An `as_fd` function for Winsock, where a `Fd` is a `Socket`.
81+
/// An `as_fd` function for Winsock, where an `Fd` is a `Socket`.
8282
fn as_fd(&self) -> BorrowedFd;
8383
}
8484
impl<T: AsSocket> AsFd for T {

src/backend/libc/net/addr.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ impl SocketAddrUnix {
7474
})
7575
}
7676

77-
fn init() -> c::sockaddr_un {
77+
const fn init() -> c::sockaddr_un {
7878
c::sockaddr_un {
7979
#[cfg(any(
8080
bsd,

src/backend/linux_raw/vdso_wrappers.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -530,9 +530,9 @@ fn init() {
530530
if ok {
531531
assert!(!ptr.is_null());
532532

533-
// Store the computed function addresses in static
534-
// storage so that we don't need to compute it again (but if
535-
// we do, it doesn't hurt anything).
533+
// Store the computed function addresses in static storage so
534+
// that we don't need to compute them again (but if we do, it
535+
// doesn't hurt anything).
536536
CLOCK_GETTIME.store(ptr.cast(), Relaxed);
537537
}
538538
}
@@ -583,9 +583,9 @@ fn init() {
583583
if ok {
584584
assert!(!ptr.is_null());
585585

586-
// Store the computed function addresses in static
587-
// storage so that we don't need to compute it again (but if
588-
// we do, it doesn't hurt anything).
586+
// Store the computed function addresses in static storage so
587+
// that we don't need to compute them again (but if we do, it
588+
// doesn't hurt anything).
589589
GETCPU.store(ptr.cast(), Relaxed);
590590
}
591591
}

src/buffer.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ use core::slice;
99
///
1010
/// # Safety
1111
///
12-
/// At least `init_len` bytes must be initialized.
12+
/// `init_len` must not be greater than `buf.len()`, and at least `init_len`
13+
/// bytes must be initialized.
1314
#[inline]
1415
pub(super) unsafe fn split_init(
1516
buf: &mut [MaybeUninit<u8>],

src/event/poll.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ pub use backend::event::poll_fd::{PollFd, PollFlags};
77
/// On macOS, `poll` doesn't work on fds for /dev/tty or /dev/null, however
88
/// [`select`] is available and does work on these fds.
99
///
10-
/// [`select`]: crate::event::select
10+
/// [`select`]: crate::event::select()
1111
///
1212
/// # References
1313
/// - [Beej's Guide to Network Programming]

src/mm/mmap.rs

Lines changed: 59 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
//! # Safety
44
//!
55
//! `mmap` and related functions manipulate raw pointers and have special
6-
//! semantics and are wildly unsafe.
6+
//! semantics.
77
#![allow(unsafe_code)]
88

99
use crate::{backend, io};
@@ -52,7 +52,16 @@ impl MapFlags {
5252
///
5353
/// # Safety
5454
///
55-
/// Raw pointers and lots of special semantics.
55+
/// If `ptr` is not null, it must be aligned to the applicable page size, and
56+
/// the range of memory starting at `ptr` and extending for `len` bytes,
57+
/// rounded up to the applicable page size, must be valid to mutate using
58+
/// `ptr`'s provenance.
59+
///
60+
/// If there exist any Rust references referring to the memory region, or if
61+
/// you subsequently create a Rust reference referring to the resulting region,
62+
/// it is your responsibility to ensure that the Rust reference invariants are
63+
/// preserved, including ensuring that the memory is not mutated in a way that
64+
/// a Rust reference would not expect.
5665
///
5766
/// # References
5867
/// - [POSIX]
@@ -93,7 +102,10 @@ pub unsafe fn mmap<Fd: AsFd>(
93102
///
94103
/// # Safety
95104
///
96-
/// Raw pointers and lots of special semantics.
105+
/// If `ptr` is not null, it must be aligned to the applicable page size, and
106+
/// the range of memory starting at `ptr` and extending for `len` bytes,
107+
/// rounded up to the applicable page size, must be valid to mutate with
108+
/// `ptr`'s provenance.
97109
///
98110
/// # References
99111
/// - [POSIX]
@@ -130,7 +142,10 @@ pub unsafe fn mmap_anonymous(
130142
///
131143
/// # Safety
132144
///
133-
/// Raw pointers and lots of special semantics.
145+
/// `ptr` must be aligned to the applicable page size, and the range of memory
146+
/// starting at `ptr` and extending for `len` bytes, rounded up to the
147+
/// applicable page size, must be valid to mutate with `ptr`'s provenance. And
148+
/// there must be no Rust references referring to that memory.
134149
///
135150
/// # References
136151
/// - [POSIX]
@@ -165,7 +180,15 @@ pub unsafe fn munmap(ptr: *mut c_void, len: usize) -> io::Result<()> {
165180
///
166181
/// # Safety
167182
///
168-
/// Raw pointers and lots of special semantics.
183+
/// `old_address` must be aligned to the applicable page size, and the range of
184+
/// memory starting at `old_address` and extending for `old_size` bytes,
185+
/// rounded up to the applicable page size, must be valid to mutate with
186+
/// `old_address`'s provenance. If `MremapFlags::MAY_MOVE` is set in `flags`,
187+
/// there must be no Rust references referring to that the memory.
188+
///
189+
/// If `new_size` is less than `old_size`, than there must be no Rust
190+
/// references referring to the memory starting at offset `new_size` and ending
191+
/// at `old_size`.
169192
///
170193
/// # References
171194
/// - [Linux]
@@ -190,7 +213,16 @@ pub unsafe fn mremap(
190213
///
191214
/// # Safety
192215
///
193-
/// Raw pointers and lots of special semantics.
216+
/// `old_address` and `new_address` must be aligned to the applicable page
217+
/// size, the range of memory starting at `old_address` and extending for
218+
/// `old_size` bytes, rounded up to the applicable page size, must be valid to
219+
/// mutate with `old_address`'s provenance, and the range of memory starting at
220+
/// `new_address` and extending for `new_size` bytes, rounded up to the
221+
/// applicable page size, must be valid to mutate with `new_address`'s
222+
/// provenance.
223+
///
224+
/// There must be no Rust references referring to either of those memory
225+
/// regions.
194226
///
195227
/// # References
196228
/// - [Linux]
@@ -214,7 +246,9 @@ pub unsafe fn mremap_fixed(
214246
///
215247
/// # Safety
216248
///
217-
/// Raw pointers and lots of special semantics.
249+
/// The range of memory starting at `ptr` and extending for `len` bytes,
250+
/// rounded up to the applicable page size, must be valid to read with `ptr`'s
251+
/// provenance.
218252
///
219253
/// # References
220254
/// - [POSIX]
@@ -241,18 +275,17 @@ pub unsafe fn mprotect(ptr: *mut c_void, len: usize, flags: MprotectFlags) -> io
241275

242276
/// `mlock(ptr, len)`—Lock memory into RAM.
243277
///
244-
/// # Safety
245-
///
246-
/// This function operates on raw pointers, but it should only be used on
247-
/// memory which the caller owns. Technically, locking memory shouldn't violate
248-
/// any invariants, but since unlocking it can violate invariants, this
249-
/// function is also unsafe for symmetry.
250-
///
251278
/// Some implementations implicitly round the memory region out to the nearest
252279
/// page boundaries, so this function may lock more memory than explicitly
253280
/// requested if the memory isn't page-aligned. Other implementations fail if
254281
/// the memory isn't page-aligned.
255282
///
283+
/// # Safety
284+
///
285+
/// The range of memory starting at `ptr`, rounded down to the applicable page
286+
/// boundary, and extending for `len` bytes, rounded up to the applicable page
287+
/// size, must be valid to read with `ptr`'s provenance.
288+
///
256289
/// # References
257290
/// - [POSIX]
258291
/// - [Linux]
@@ -282,17 +315,16 @@ pub unsafe fn mlock(ptr: *mut c_void, len: usize) -> io::Result<()> {
282315
///
283316
/// `mlock_with` is the same as [`mlock`] but adds an additional flags operand.
284317
///
285-
/// # Safety
286-
///
287-
/// This function operates on raw pointers, but it should only be used on
288-
/// memory which the caller owns. Technically, locking memory shouldn't violate
289-
/// any invariants, but since unlocking it can violate invariants, this
290-
/// function is also unsafe for symmetry.
291-
///
292318
/// Some implementations implicitly round the memory region out to the nearest
293319
/// page boundaries, so this function may lock more memory than explicitly
294320
/// requested if the memory isn't page-aligned.
295321
///
322+
/// # Safety
323+
///
324+
/// The range of memory starting at `ptr`, rounded down to the applicable page
325+
/// boundary, and extending for `len` bytes, rounded up to the applicable page
326+
/// size, must be valid to read with `ptr`'s provenance.
327+
///
296328
/// # References
297329
/// - [Linux]
298330
/// - [glibc]
@@ -308,16 +340,16 @@ pub unsafe fn mlock_with(ptr: *mut c_void, len: usize, flags: MlockFlags) -> io:
308340

309341
/// `munlock(ptr, len)`—Unlock memory.
310342
///
311-
/// # Safety
312-
///
313-
/// This function operates on raw pointers, but it should only be used on
314-
/// memory which the caller owns, to avoid compromising the `mlock` invariants
315-
/// of other unrelated code in the process.
316-
///
317343
/// Some implementations implicitly round the memory region out to the nearest
318344
/// page boundaries, so this function may unlock more memory than explicitly
319345
/// requested if the memory isn't page-aligned.
320346
///
347+
/// # Safety
348+
///
349+
/// The range of memory starting at `ptr`, rounded down to the applicable page
350+
/// boundary, and extending for `len` bytes, rounded up to the applicable page
351+
/// size, must be valid to read with `ptr`'s provenance.
352+
///
321353
/// # References
322354
/// - [POSIX]
323355
/// - [Linux]

src/net/send_recv/msg.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -593,6 +593,11 @@ impl FusedIterator for AncillaryDrain<'_> {}
593593

594594
/// `sendmsg(msghdr)`—Sends a message on a socket.
595595
///
596+
/// This function is for use on connected sockets, as it doesn't have
597+
/// a way to specify an address. See the [`sendmsg_v4`], [`sendmsg_v6`]
598+
/// [`sendmsg_unix`], [`sendmsg_xdp`], and [`sendmsg_any`] to send
599+
/// messages on unconnected sockets.
600+
///
596601
/// # References
597602
/// - [POSIX]
598603
/// - [Linux]

src/process/procctl.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -134,9 +134,11 @@ pub enum DumpableBehavior {
134134
}
135135

136136
/// Set the state of the `dumpable` attribute for the process indicated by
137-
/// `idtype` and `id`. This determines whether the process can be traced and
138-
/// whether core dumps are produced for the process upon delivery of a signal
139-
/// whose default behavior is to produce a core dump.
137+
/// `idtype` and `id`.
138+
///
139+
/// This determines whether the process can be traced and whether core dumps
140+
/// are produced for the process upon delivery of a signal whose default
141+
/// behavior is to produce a core dump.
140142
///
141143
/// This is similar to `set_dumpable_behavior` on Linux, with the exception
142144
/// that on FreeBSD there is an extra argument `process`. When `process` is set
@@ -453,6 +455,7 @@ pub enum TrapCapBehavior {
453455
}
454456

455457
/// Set the current value of the capability mode violation trapping behavior.
458+
///
456459
/// If this behavior is enabled, the kernel would deliver a [`Signal::Trap`]
457460
/// signal on any return from a system call that would result in a
458461
/// [`io::Errno::NOTCAPABLE`] or [`io::Errno::CAPMODE`] error.

0 commit comments

Comments
 (0)