Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't trap into the debugger on panics under Linux #130810

Merged
merged 1 commit into from
Sep 25, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 1 addition & 78 deletions library/std/src/sys/dbg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,84 +105,7 @@ mod os {
}
}

#[cfg(target_os = "linux")]
mod os {
use super::DebuggerPresence;
use crate::fs::File;
use crate::io::Read;

pub(super) fn is_debugger_present() -> Option<DebuggerPresence> {
// This function is crafted with the following goals:
// * Memory efficiency: It avoids crashing the panicking process due to
// out-of-memory (OOM) conditions by not using large heap buffers or
// allocating significant stack space, which could lead to stack overflow.
// * Minimal binary size: The function uses a minimal set of facilities
// from the standard library to avoid increasing the resulting binary size.
//
// To achieve these goals, the function does not use `[std::io::BufReader]`
// and instead reads the file byte by byte using a sliding window approach.
// It's important to note that the "/proc/self/status" pseudo-file is synthesized
// by the Virtual File System (VFS), meaning it is not read from a slow or
// non-volatile storage medium so buffering might not be as beneficial because
// all data is read from memory, though this approach does incur a syscall for
// each byte read.
//
// We cannot make assumptions about the file size or the position of the
// target prefix ("TracerPid:"), so the function does not use
// `[std::fs::read_to_string]` thus not employing UTF-8 to ASCII checking,
// conversion, or parsing as we're looking for an ASCII prefix.
//
// These condiderations make the function deviate from the familiar concise pattern
// of searching for a string in a text file.

fn read_byte(file: &mut File) -> Option<u8> {
let mut buffer = [0];
file.read_exact(&mut buffer).ok()?;
Some(buffer[0])
}

// The ASCII prefix of the datum we're interested in.
const TRACER_PID: &[u8] = b"TracerPid:\t";

let mut file = File::open("/proc/self/status").ok()?;
let mut matched = 0;

// Look for the `TRACER_PID` prefix.
while let Some(byte) = read_byte(&mut file) {
if byte == TRACER_PID[matched] {
matched += 1;
if matched == TRACER_PID.len() {
break;
}
} else {
matched = 0;
}
}

// Was the prefix found?
if matched != TRACER_PID.len() {
return None;
}

// It was; get the ASCII representation of the first digit
// of the PID. That is enough to see if there is a debugger
// attached as the kernel does not pad the PID on the left
// with the leading zeroes.
let byte = read_byte(&mut file)?;
if byte.is_ascii_digit() && byte != b'0' {
Some(DebuggerPresence::Detected)
} else {
Some(DebuggerPresence::NotDetected)
}
}
}

#[cfg(not(any(
target_os = "windows",
target_vendor = "apple",
target_os = "freebsd",
target_os = "linux"
)))]
#[cfg(not(any(target_os = "windows", target_vendor = "apple", target_os = "freebsd")))]
mod os {
pub(super) fn is_debugger_present() -> Option<super::DebuggerPresence> {
None
Expand Down
Loading