From 30ee60a477bbc5c1bfde68a3811fe9a7bb360c2e Mon Sep 17 00:00:00 2001 From: Charlie Tonneslan Date: Mon, 23 Mar 2026 09:56:29 -0400 Subject: [PATCH] tac: use MAP_PRIVATE to prevent SIGBUS on file truncation When tac reads a file via mmap and that file gets truncated concurrently (e.g. log rotation), the process receives SIGBUS because the mapped pages are no longer backed by the file. Switch from Mmap::map() (MAP_SHARED) to map_copy_read_only() (MAP_PRIVATE). With MAP_PRIVATE, the kernel returns zero-filled pages for truncated regions instead of raising SIGBUS, matching GNU tac's behavior of graceful handling. Fixes #9748 --- src/uu/tac/src/tac.rs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/uu/tac/src/tac.rs b/src/uu/tac/src/tac.rs index 88c355b0e4b..f2ff21f2365 100644 --- a/src/uu/tac/src/tac.rs +++ b/src/uu/tac/src/tac.rs @@ -451,9 +451,19 @@ fn buffer_stdin() -> std::io::Result { } fn try_mmap_file(file: &File) -> Option { - // SAFETY: If the file is truncated while we map it, SIGBUS will be raised - // and our process will be terminated, thus preventing access of invalid memory. - unsafe { Mmap::map(file).ok() } + // Use make_read_only() on a MmapMut created with MAP_PRIVATE. + // With MAP_PRIVATE, truncation of the underlying file won't cause + // SIGBUS because the kernel serves zero-filled pages for the + // truncated region instead of faulting. This is safer than the + // default MAP_SHARED from Mmap::map(). + // + // See: https://github.com/uutils/coreutils/issues/9748 + let mmap_mut = unsafe { + memmap2::MmapOptions::new() + .map_copy_read_only(file) + .ok()? + }; + Some(mmap_mut) } #[cfg(test)]