diff --git a/changelog/2448.changed.md b/changelog/2448.changed.md new file mode 100644 index 0000000000..00774b665e --- /dev/null +++ b/changelog/2448.changed.md @@ -0,0 +1 @@ +Module sys/ptrace changes `ptrace::getregs` for x86_64/x86 to be unsafe function. \ No newline at end of file diff --git a/src/sys/ptrace/linux.rs b/src/sys/ptrace/linux.rs index 8abaf4d71b..38ec554ad5 100644 --- a/src/sys/ptrace/linux.rs +++ b/src/sys/ptrace/linux.rs @@ -304,12 +304,17 @@ fn ptrace_peek( } } -/// Get user registers, as with `ptrace(PTRACE_GETREGS, ...)` +/// Get user registers, as with `ptrace(PTRACE_GETREGS, ...)`. Call `getregset` for safe version /// /// Note that since `PTRACE_GETREGS` are not available on all platforms (as in [ptrace(2)]), /// `ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, ...)` is used instead to achieve the same effect /// on aarch64 and riscv64. /// +/// # Safety +/// +/// Currently, in x86_64 platform, if the tracer is 64bit and tracee is 32bit, the return value is +/// undefined. +/// /// [ptrace(2)]: https://www.man7.org/linux/man-pages/man2/ptrace.2.html #[cfg(all( target_os = "linux", @@ -321,7 +326,7 @@ fn ptrace_peek( all(target_arch = "x86", target_env = "gnu") ) ))] -pub fn getregs(pid: Pid) -> Result { +pub unsafe fn getregs(pid: Pid) -> Result { ptrace_get_data::(Request::PTRACE_GETREGS, pid) } @@ -342,6 +347,9 @@ pub fn getregs(pid: Pid) -> Result { } /// Get a particular set of user registers, as with `ptrace(PTRACE_GETREGSET, ...)` +/// +/// Currently, in x86_64 platform, if the tracer is 64bit and tracee is 32bit, this function +/// will return EIO error. #[cfg(all( target_os = "linux", target_env = "gnu", @@ -367,6 +375,9 @@ pub fn getregset(pid: Pid) -> Result { (&mut iov as *mut libc::iovec).cast(), )?; }; + if iov.iov_len != mem::size_of::() { + return Err(Errno::EIO); + } Ok(unsafe { data.assume_init() }) } diff --git a/test/sys/test_ptrace.rs b/test/sys/test_ptrace.rs index c99c6762c3..3914921b69 100644 --- a/test/sys/test_ptrace.rs +++ b/test/sys/test_ptrace.rs @@ -224,12 +224,16 @@ fn test_ptrace_syscall() { .unwrap(); #[cfg(target_arch = "x86_64")] - let get_syscall_id = - || ptrace::getregs(child).unwrap().orig_rax as libc::c_long; + let get_syscall_id = || { + unsafe { ptrace::getregs(child) }.unwrap().orig_rax + as libc::c_long + }; #[cfg(target_arch = "x86")] - let get_syscall_id = - || ptrace::getregs(child).unwrap().orig_eax as libc::c_long; + let get_syscall_id = || { + unsafe { ptrace::getregs(child) }.unwrap().orig_eax + as libc::c_long + }; #[cfg(target_arch = "aarch64")] let get_syscall_id =