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

Fix inconsistent reg struct layout for 64bit tracer and 32bit tracee #2448

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 5 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
15 changes: 13 additions & 2 deletions src/sys/ptrace/linux.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
///
Evian-Zhang marked this conversation as resolved.
Show resolved Hide resolved
/// [ptrace(2)]: https://www.man7.org/linux/man-pages/man2/ptrace.2.html
#[cfg(all(
target_os = "linux",
Expand All @@ -321,7 +326,7 @@ fn ptrace_peek(
all(target_arch = "x86", target_env = "gnu")
)
))]
pub fn getregs(pid: Pid) -> Result<user_regs_struct> {
pub unsafe fn getregs(pid: Pid) -> Result<user_regs_struct> {
ptrace_get_data::<user_regs_struct>(Request::PTRACE_GETREGS, pid)
}

Expand All @@ -342,6 +347,9 @@ pub fn getregs(pid: Pid) -> Result<user_regs_struct> {
}

/// 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 an error.
Evian-Zhang marked this conversation as resolved.
Show resolved Hide resolved
#[cfg(all(
target_os = "linux",
target_env = "gnu",
Expand All @@ -367,6 +375,9 @@ pub fn getregset<S: RegisterSet>(pid: Pid) -> Result<S::Regs> {
(&mut iov as *mut libc::iovec).cast(),
)?;
};
if iov.iov_len != mem::size_of::<S::Regs>() {
return Err(Errno::EIO);
}
Ok(unsafe { data.assume_init() })
}

Expand Down
12 changes: 8 additions & 4 deletions test/sys/test_ptrace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
Expand Down