-
Notifications
You must be signed in to change notification settings - Fork 682
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
ptrace support for BSDs #949
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good start so far. You should also try enabling the tests in test/sys/test_ptrace.rs.
.travis.yml
Outdated
@@ -141,6 +141,7 @@ branches: | |||
# bors-ng branches; see https://bors-ng.github.io/getting-started/ | |||
- trying | |||
- staging | |||
- issue-947 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This line shouldn't be necessary. Travis automatically builds PRs. This line is only necessary if you want nix-rust/nix to have a branch named "issue-947".
src/sys/ptrace/bsd.rs
Outdated
None => 0, | ||
}; | ||
unsafe { | ||
ptrace_other(Request::PT_CONTINUE, pid, ptr::null_mut(), data).map(|_| ()) // ignore the useless return value |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please line wrap to 80 cols.
src/sys/ptrace/bsd.rs
Outdated
/// } | ||
/// } | ||
/// ``` | ||
#[cfg(not(any(target_os = "netbsd", target_os = "openbsd")))] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not enabled for these OSes? They both define PT_STEP
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They must be in a different header then. I'm looking at https://man.openbsd.org/ptrace and http://netbsd.gw.com/cgi-bin/man-cgi?ptrace++NetBSD-current
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NetBSD supports PT_STEP in CPU specific headers, not all CPUs support it.
src/sys/ptrace/bsd.rs
Outdated
|
||
/// Step isn't supported on netbsd or openbsd | ||
#[cfg(any(target_os = "netbsd", target_os = "openbsd"))] | ||
pub fn Step<T: Into<Option<Signal>>>(pid: Pid, sig: T) -> Result<()> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You shouldn't define this function. It's better to make programs fail at compile time than at runtime. Also, the capitalization is wrong.
src/sys/ptrace/linux.rs
Outdated
@@ -20,7 +20,7 @@ cfg_if! { | |||
} | |||
|
|||
libc_enum!{ | |||
#[cfg_attr(not(any(target_env = "musl", target_os = "android")), repr(u32))] | |||
#[cfg_attr(not(any(target_env = "musl", target_os = "android", target_os = "macos")), repr(u32))] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change shouldn't be necessary, since the file is not included on OSX.
Well that didn't quite go as expected. I'm unsure what setup the buildbot instances are (guessing freebsd though) and the apple ptrace calls just seem to be returning |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The compile failure is because src/sys/mod.rs needs a change, too.
test/sys/mod.rs
Outdated
@@ -26,6 +26,5 @@ mod test_uio; | |||
#[cfg(target_os = "linux")] | |||
mod test_epoll; | |||
mod test_pthread; | |||
#[cfg(any(target_os = "android", | |||
target_os = "linux"))] | |||
#[cfg(not(target_os = "ios"))] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This #[cfg()]
statement is too broad. Nix runs on many platforms. You should opt-in, not opt-out.
Okay well I've just opened a libc PR that adds PT_STEP for the relevant archs. So once that's merged I'll update accordingly. Any idea about the |
"libc PR that adds PT_STEP" where? |
In libc rust-lang/libc#1091 (comment) none of the ptrace requests were available in BSDs so I did a PR, did another one to add the arch specific requests today 😄 Edit: Just realised you're more of a BSD person not a rust person! libc is a rust library we use to reexport libc functions and constants etc. |
I don't know. Have you tried it on real Apple hardware? I don't have any. |
I don't have any either, I'm trying to add OSX support for one of my projects for a user that asked for it. I'll ask them if they can run it |
Well it doesn't seem to work on an actual apple pc as well. I think it might need additional fiddling via functions that aren't in libc but are in https://github.com/fitzgen/mach/ In the interest of moving this along I could remove apple support from bsd, fix the buildbot errors then work on apple support as an additional PR? Or try and do it all in this one. How would you feel about adding a dependency on https://github.com/fitzgen/mach/ for apple users? |
I might be onto something, I've got |
Okay I might be all good now! One potential issue with the tests I noticed there was a spurious test_wait failure, this might be caused by test_wait and test_ptrace_cont being ran at the same time by rustc-test if waitpid will respond to any signal from the same Either way I'll check back tomorrow and see what travis/buildbot says |
Tsk Tsk. You should always compile and test before pushing to Travis. Travis shouldn't be finding your unclosed delimiters for you. |
I know, it's this apple stuff has made me sloppy. I realised doing stuff in the bsd mode that cargo check and build didn't flag up syntax errors at all. If I make a habit of OSX based PRs I'll try to figure out how to cross compile for OSX |
While that did sort the apple issue for that one run TEST_THREADS was already 1 in the cargo cfg. So that might just be down to the fact the multiple processes essentially make this is a threading probably. I've added an extra ptrace::cont which isn't checked after the check for the kill just because some systems may need a continue to transition from raising the SIGKILL signal to actually exiting (I'll also try detach if that doesn't work). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
test_ptrace_cont
should grab the FORK_MTX
, just like other tests that fork. That will fix your conflict with test_wait
.
ci/script.sh
Outdated
@@ -21,7 +21,7 @@ main() { | |||
|
|||
# Run tests on debug and release targets. | |||
cross test --target $t | |||
cross test --target $t --release | |||
cross test --target $t --release |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make sure to revert this whitespace change.
@@ -10,25 +12,29 @@ fn test_ptrace() { | |||
// Just make sure ptrace can be called at all, for now. | |||
// FIXME: qemu-user doesn't implement ptrace on all arches, so permit ENOSYS | |||
let err = ptrace::attach(getpid()).unwrap_err(); | |||
assert!(err == Error::Sys(Errno::EPERM) || err == Error::Sys(Errno::ENOSYS)); | |||
assert!(err == Error::Sys(Errno::EPERM) || err == Error::Sys(Errno::EINVAL) || |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are you allowing EINVAL?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://www.freebsd.org/cgi/man.cgi?query=ptrace the BSDs seem to use EINVAL for attempting to attach to yourself. I don't know if all BSDs do that or if some mimic linux and do EPERM so I just had it as that for now. I can investigate and make it more specific though
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NetBSD returns EINVAL
@asomers |
If you find anything wrong with NetBSD and ptrace(2), please let me know! |
BTW. you might find it useful http://netbsd.org/~kamil/ptrace-netbsd/presentation.html a little bit dated, but quite good starter. |
The compile failure on NetBSD is purely a problem in your PR. You have an unused
|
|
Great, I figured as much. I'll try things that come to mind as potential fixes, (like currently ptrace::detach) and also in parallel try to find some documentation or blogs that shed light on the differences between apple and the rest of the world |
I've seemingly cracked it, this part of the linux man page for ptrace helped me realise what may be happening:
And then in the apple man page for ptrace
I know they're different OSes but if PT_KILL in apple is subject to the same potential pitfalls of linux that would explain the issues we've observed. Therefore after waitpid catches the kill we sent, just in case it's a false positive kill I send a direct kill to the tracee. I've also added a comment to document this behaviour in the test to explain the rationale for future maintainers. |
The Linux manpage surely doesn't apply. ptrace(2) is very different in Linux than in the BSDs. OSX takes after the BSDs, but adds its own differences to ptrace(2) due to Mach. I'm not saying that your solution is wrong, but I don't accept the rationale. |
No idea about Darwin, but while PT_KILL is broken on Linux, it's perfectly fine on BSDs (at least NetBSD). |
It might be tenuous but it is the only source that could explain this strange apple behaviour. I'm now going to see if I've also gone over all the signal and tracing stuff in http://newosxbook.com/MOXiI.pdf and can find no justification. Apart from the fact ptrace is crippled on apple for security/obfuscation reasons, there are undocumented parts and it's generally a pain as a result. |
Thinking of the kill, does it actually effect what the test is attempting to show. |
@asomers any thoughts/issues RE my last comment? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah that's exactly the point I was making 😄 also rebased and squashed! |
So I've just had to rebase this onto master again because of another changelog change, @Susurrus any comments before merging? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few minor nits. I would prefer to see the kill, read, write additions to linux done first as a separate commit from adding all the BSD support, but I won't hold up merging this just for that change.
src/sys/mod.rs
Outdated
@@ -38,7 +38,13 @@ pub mod mman; | |||
|
|||
pub mod pthread; | |||
|
|||
#[cfg(any(target_os = "android", target_os = "linux"))] | |||
#[cfg(any(target_os = "dragonfly", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These should be in alphabetical order.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This still isn't alphabetical.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed, squashed and pushed. Sorry about that!
src/sys/ptrace/bsd.rs
Outdated
pub type RequestType = c_int; | ||
|
||
cfg_if! { | ||
if #[cfg(any(target_os = "macos", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alphabetical order here as well.
src/sys/ptrace/bsd.rs
Outdated
PT_WRITE_U, | ||
PT_CONTINUE, | ||
PT_KILL, | ||
#[cfg(any(any(target_os = "macos", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alphabetical order
test/sys/mod.rs
Outdated
@@ -26,6 +26,11 @@ mod test_uio; | |||
#[cfg(target_os = "linux")] | |||
mod test_epoll; | |||
mod test_pthread; | |||
#[cfg(any(target_os = "android", | |||
target_os = "linux"))] | |||
#[cfg(any(target_os = "dragonfly", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alphabetical order here too.
test/sys/test_ptrace.rs
Outdated
@@ -50,10 +57,12 @@ fn test_ptrace_setsiginfo() { | |||
fn test_ptrace_cont() { | |||
use nix::sys::ptrace; | |||
use nix::sys::signal::{raise, Signal}; | |||
use nix::sys::wait::{waitpid, WaitStatus}; | |||
use nix::sys::wait::{waitpid, WaitStatus, WaitPidFlag}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alphabetical order
src/sys/ptrace/bsd.rs
Outdated
} | ||
|
||
/// Issues a kill request as with ptrace(PT_KILL, ..-) | ||
/// This request is equivalent to ptrace(PT_CONTINUE, ..., SIGKILL); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please put a blank comment line above this one. Otherwise this line looks weird in the generated docs. I know this was carried over from the Linux one, but we should fix it here anyways (feel free to fix it there if you'd like too).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix it as in a blank line above each function? I'm not sure which bit looks weird in the generated docs. Is it the function summary? https://docs.rs/nix/0.11.0/nix/sys/ptrace/index.html
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just these 3 things, then let's squash and merge!
src/sys/ptrace/linux.rs
Outdated
|
||
/// Issues a kill request as with ptrace(PTRACE_KILL, ..-) | ||
/// This request is equivalent to ptrace(PTRACE_CONT, ..., SIGKILL); | ||
/// |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry I wasn't clear, can you put this blank comment line between the two existing comment lines on 326 and 327? A blank line separates a brief summary line from a further longer description. Otherwise this shows as one really long line on the main ptrace doc page.
71f77ea
to
373536c
Compare
@Susurrus I think we're all good to go now 👍 |
* Moved ptrace API into it's own module with cfg'ed modules exported for linux/android or BSDs. * Replicated current linux API for BSD * Added API functions to peek and poke memory to avoid needing to replicate deprecated linux API and remaining feature complete * Added helper function for `PTRACE_KILL` requests * Updated tests based on new API changes * Added addition kill calls to `test_ptrace_cont` as inferior death doesn't happen immediately on OSX which caused issues in the tests.
bors r+ |
949: ptrace support for BSDs r=Susurrus a=xd009642 This PR adds support to the ptrace API for BSDs to close #947. It also adds a read and write method for reading and writing to a traced processes memory. The ptrace API created for linux offers this via a deprecated function so I added this so they can be feature equivalent without replicating a deprecated part of the API. Due to the differences in ptrace on BSD and linux I've made a ptrace module to keep things readable. Still to do - revert travis config to remove my feature branch and update the changelog. Co-authored-by: xd009642 <[email protected]>
1083: Allow signal injection in ptrace::syscall and ptrace::detach r=asomers a=frangio Fixes #1049 Should I add tests for this functionality? By the way, I noticed that the BSD module doesn't have `ptrace::syscall`. I couldn't find a reason behind this in #949. Should we add it? Co-authored-by: Francisco Giordano <[email protected]>
This PR adds support to the ptrace API for BSDs to close #947. It also adds a read and write method for reading and writing to a traced processes memory. The ptrace API created for linux offers this via a deprecated function so I added this so they can be feature equivalent without replicating a deprecated part of the API.
Due to the differences in ptrace on BSD and linux I've made a ptrace module to keep things readable.
Still to do - revert travis config to remove my feature branch and update the changelog.