Skip to content

ptrace::syscall_info does not set addr correctly in Linux. #2660

@ollbx

Description

@ollbx

I was trying to write some code using ptrace::syscall_info and only received garbage / uninitialized data. The reason seems to be that the current implementation passes a null pointer for the addr parameter instead of std::mem::size_of::<libc::ptrace_syscall_info>().

The code for ptrace::syscall_info(pid) uses the function ptrace_get_data:

#[cfg(all(target_os = "linux", target_env = "gnu"))]
pub fn syscall_info(pid: Pid) -> Result<libc::ptrace_syscall_info> {
    ptrace_get_data::<libc::ptrace_syscall_info>(Request::PTRACE_GET_SYSCALL_INFO, pid)
}

This function will always pass a null pointer using ptr::null_mut::<T>() for the third parameter (addr).

fn ptrace_get_data<T>(request: Request, pid: Pid) -> Result<T> {
    let mut data = mem::MaybeUninit::<T>::uninit();
    let res = unsafe {
        libc::ptrace(
            request as RequestType, // op
            libc::pid_t::from(pid), // pid
            ptr::null_mut::<T>(),   // addr
            data.as_mut_ptr(),      // data
        )
    };
    Errno::result(res)?;
    Ok(unsafe { data.assume_init() })
}

This seems to be incorrect. The documentation for PTRACE_GET_SYSCALL_INFO states:

The addr argument contains the size of the buffer pointed to by the data argument (i.e., sizeof(struct ptrace_syscall_info)). [...] If the size of the data to be written by the kernel exceeds the size specified by the addr argument, the output data is truncated.

Therefore I'm guessing that nothing gets written to the buffer if 0 is passed. It also does not seem to be an error condition, so the function still returns Ok(_). The following test code seems to fix the issue:

let mut data = std::mem::MaybeUninit::<libc::ptrace_syscall_info>::uninit();

let res = unsafe {
	libc::ptrace(
			Request::PTRACE_GET_SYSCALL_INFO as c_uint,
			libc::pid_t::from(pid),
			std::mem::size_of::<libc::ptrace_syscall_info>(),
			data.as_mut_ptr())
};

Errno::result(res)?;
let info = unsafe { data.assume_init() };

Tested on kernel:

Linux dev-test 6.8.12-13-pve #1 SMP PREEMPT_DYNAMIC PMX 6.8.12-13 (2025-07-22T10:00Z) x86_64 GNU/Linux

(On Debian bookworm in a Proxmox LXC container)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions