-
Notifications
You must be signed in to change notification settings - Fork 666
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
Added ptrace utilities. #614
Conversation
src/sys/ptrace.rs
Outdated
@@ -91,6 +92,18 @@ fn ptrace_peek(request: ptrace::PtraceRequest, pid: pid_t, addr: *mut c_void, da | |||
} | |||
} | |||
|
|||
/// Function for ptrace requests that return values from the data field. | |||
/// Not all structs that can currently be gotten via ptrace are implemented in |
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.
"be returned" instead of "be gotten"
How many different specialization of these functions do you expect? Is it a relatively small, finite number? If so, I'd rather keep Also, is this available across all platforms? |
I think it's only 2 or 3 more. But until the next version of libc comes out I can't implement them. I see what you mean with the breaking change and I'll move it to private as that's likely the best approach. Some of them work across all platforms, looking at the ptrace documentation some won't work on SPARC systems like Solaris. However, the cfg in ptrace.rs limits it to x86, x86_64 and arm and I don't see a reason in the docs why it won't work on all of them. |
Actually looking at the ptrace documentation I think it's more like 4 specialisations. Either way it is a finite number. |
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.
Mostly minor nitpicks, primarily around documentation. Please be more verbose and descriptive as it'll make reviewers happier! 😄
src/sys/ptrace.rs
Outdated
ptrace_get_data::<c_long>(PTRACE_GETEVENTMSG, pid) | ||
} | ||
|
||
pub fn ptrace_getsiginfo(pid: pid_t) -> Result<siginfo_t> { |
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.
Needs a doccomment. Also linking to the manpages describing this functionality would be a good idea.
src/sys/ptrace.rs
Outdated
ptrace_get_data::<siginfo_t>(PTRACE_GETSIGINFO, pid) | ||
} | ||
|
||
pub fn ptrace_setsiginfo(pid: pid_t, mut sig: siginfo_t) -> Result<c_long> { |
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.
Needs a doccomment. Also linking to the manpages describing this functionality would be a good idea.
src/sys/ptrace.rs
Outdated
@@ -102,3 +112,19 @@ pub fn ptrace_setoptions(pid: pid_t, options: ptrace::PtraceOptions) -> Result<( | |||
|
|||
ptrace(PTRACE_SETOPTIONS, pid, ptr::null_mut(), options as *mut c_void).map(drop) | |||
} | |||
|
|||
/// Get the details of a ptrace event. |
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.
Can you be more descriptive than this? Also please link to a manpage here.
CHANGELOG.md
Outdated
@@ -7,13 +7,15 @@ This project adheres to [Semantic Versioning](http://semver.org/). | |||
|
|||
### Added | |||
- Added `sys::signal::SigAction::{ flags, mask, handler}` | |||
([#611](https://github.com/nix-rust/nix/pull/609) | |||
([#611](https://github.com/nix-rust/nix/pull/609)) |
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 these syntax fixes in a separate commit.
src/sys/ptrace.rs
Outdated
|
||
/// Get the details of a ptrace event. | ||
pub fn ptrace_getevent(pid: pid_t) -> Result<c_long> { | ||
use self::ptrace::*; |
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 should be unnecessary.
src/sys/ptrace.rs
Outdated
@@ -91,6 +92,15 @@ fn ptrace_peek(request: ptrace::PtraceRequest, pid: pid_t, addr: *mut c_void, da | |||
} | |||
} | |||
|
|||
/// Function for ptrace requests that return values from the data field. | |||
fn ptrace_get_data<T>(request: ptrace::PtraceRequest, pid: pid_t) -> Result<T> { | |||
let data: Box<T> = Box::new(unsafe { mem::uninitialized() }); |
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 seems pretty complicated. Please improve the doccomment and also add inline comments describing why it's doing things. It's rather hard to parse right now.
src/sys/ptrace.rs
Outdated
@@ -76,6 +77,7 @@ pub fn ptrace(request: ptrace::PtraceRequest, pid: pid_t, addr: *mut c_void, dat | |||
|
|||
match request { | |||
PTRACE_PEEKTEXT | PTRACE_PEEKDATA | PTRACE_PEEKUSER => ptrace_peek(request, pid, addr, data), | |||
PTRACE_GETEVENTMSG => ptrace_get_data::<c_long>(request, pid), |
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 isn't this a standalone function like the others you had?
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.
It was originally but I've of the review comments was that it seemed an unnecessary function. Unless I misunderstood?
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.
No you didn't, but I think I was in the wrong there. I'd like to move towards all ptrace calls being implemented as dedicated functions. I'm wondering if we should also enforce that for the ones we make by making ptrace()
return an error if you try to use GETEVENTMSG
(or any of the other ones ) with it to get people to switch.
src/sys/ptrace.rs
Outdated
// This creates a pointer to type T which is uninitialised. This is because | ||
// not all types may implement a default struct and some may have private members. | ||
let data: Box<T> = Box::new(unsafe { mem::uninitialized() }); | ||
// Convert the pointer to store a result into a void ptr to input into ptrace |
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 is a useless comment.
So I'm working on some more tweaks based on comments. Regarding the suggestion to return errors when a user uses the ptrace function versus a specialisation. I'm not sure if that's the best approach given it may confuse users between actual ptrace errors and misuse of nix. Also, the ptrace API is complicated and not oft used so documentation and examples are lacking. I wouldn't be fully confident that the specialisations are the only valid ways to use those ptrace requests and there aren't extended features for any of them available on other systems. |
The error would be something like
Addressing this and the above, the goal of |
That makes sense. Made the changes in question including the unsupported operation error return. I did have a look through the errno constants and that does seem to be the best fitting error. |
I was actually thinking about specifying a new enum variant |
Adding an Error::Unsupported operation does make more sense. It is a bigger change though so I'd just like to clear a few things up before I push another commit.
|
For both of these I don't think there should be a mapping. Mapping from |
I've made the suggested changes, hopefully this clears up all the issues :) |
src/lib.rs
Outdated
@@ -97,6 +96,7 @@ pub enum Error { | |||
/// The operation involved a conversion to Rust's native String type, which failed because the | |||
/// string did not contain all valid UTF-8. | |||
InvalidUtf8, | |||
UnsupportedOperation, |
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 needs a doccomment. It should make it clear that this isn't a libc
error, but a nix
-specific error indicating that the operation is not supported.
@@ -116,14 +116,6 @@ impl Error { | |||
Error::Sys(errno::EINVAL) | |||
} | |||
|
|||
/// Get the errno associated with this error |
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 is a public API, so removing this needs to be mentioned in the CHANGELOG under the Removed
section.
&Error::Sys(errno) => write!(f, "{:?}: {}", errno, errno.desc()), | ||
} | ||
} | ||
} | ||
|
||
impl From<Error> for io::Error { |
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.
Another public API removed, please list this in the Removed
section of the CHANGELOG.
Hi, updated the changelog and the doc comments, sorry about the delay! |
src/sys/ptrace.rs
Outdated
} | ||
|
||
/// Set siginfo as with `ptrace(PTRACE_SETSIGINFO,...)` | ||
pub fn ptrace_setsiginfo(pid: pid_t, mut sig: siginfo_t) -> Result<c_long> { |
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.
Shouldn't sig
be &mut
instead?
Just one last comment to address. Could you also rebase this on top of the latest HEAD and also squash all commits into 1? |
Done 👍 |
Could you also address my comment about the argument type for |
Ah sorry missed that completely! I've made the fix and squashed the commits again so it's only one |
Reading the docs a bit more it seems like Looking at the possible error modes for these, it seems they will always return a valid system error, yes? So I think both |
ptrace_getevent() returns the event value which is specific to the event. For the fork/clone etc events it's the PID or TID of the new process for the exit event it's the exit code. The event type is determined by what waitpid returns (the nix-rust implementation of waitpid is great cause it lets you match to the events you're interested in). I agree with you for ptrace_setsiginfo matching ptrace_setoptions but the c_long in getevent is important. ptrace_setsiginfo's arguments are getting reverted and I'm making changes to the return type. I don't think ptrace_getevent needs changing at all so I'll leave that for now. |
With |
pub fn ptrace(request: ptrace::PtraceRequest, pid: pid_t, addr: *mut c_void, data: *mut c_void) -> Result<c_long> I believe it's calling the public ptrace function we expose. I tried with const and without mut and I only got compiler errors. I could directly call the ptrace defined in the ffi namespace and that will likely solve it so I'll try that |
Yeah, call |
I was about to do that but then I realised that it was inconsistent with ptrace_setoptions. I can change ptrace_setoptions to make it consistent or might it be easier to just have it mutable since it's only in local scope and doesn't affect the caller (correct me if I'm wrong). |
I'm okay with those being inconsistent at the implementation level. At least for consumers of this API, they won't be surprised by |
The whole |
src/sys/ptrace.rs
Outdated
} | ||
|
||
/// Set siginfo as with `ptrace(PTRACE_SETSIGINFO,...)` | ||
pub fn ptrace_setsiginfo(pid: pid_t, sig: siginfo_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.
There's no reason to take sig
by-value since the values are copied out of the struct by the system. Let's change ptrace_setsiginfo
to take it by-reference instead.
In addition to changing that variable to be by-reference, is there any way to set up tests for this? Since |
I'd have to look up more about the signal API in nix than I already know as I can't guarantee that writing certain signals won't affect the internal state of ptrace and cause error calls on some supported systems. I have just ended up in a utter faff with git cause something messed up with my squashes and I ended up detaching my head so personally I'd prefer to close this once everything checks out. Then when the next version of libc is released and the user_regs struct is exposed I can implement the get and set regs ptrace function and do the tests for that and the get and set sig at the same time since there's potential for reuse there. |
That's fair. Once this pasts tests then let's merge this! Except I don't see our FreeBSD buildbot running on these PRs. @asomers Can you look into this? |
It looks like more PRs have been merged in the meantime. Should I bother rebasing now or wait until the freebsd issue is identified and we can be sure that we're ready to merge? |
Some ptrace functions return structures through the data argument. This commit adds utilities to return data through this mechanism and function specialisations for a few of these functions (getting event messages or the siginfo_t struct). Once the next version of libc is released these utilities will be expanded to include the fpregs and user_regs structs. Ptrace requests that are now satisfied by a more specific public function will return an unsupported operation error. This has involved adding an UnsupportedOperation to the nix::Error enum and removed the mapping from Error to Errno and from Error to std::io::Error.
I decided since it was only quick I'd do it anyway. |
I think the consensus is that if i686 freeBSD is working, then we'll keep plowing ahead. @asomers will be looking at it in the meantime. |
bors r+ |
614: Added ptrace utilities. r=Susurrus Some ptrace functions return structures through the data argument. This commit adds utilities to return data through this mechanism and function specialisations for a few of these functions (getting event messages or the siginfo_t struct). Once the next version of libc is released these utilities will be expanded to include the fpregs and user_regs structs. Due to the need to use unsafe blocks to utilise these ptrace features I feel these are good candidates for inclusion into rust-nix
Build succeeded |
This seems to have regressed I don't totally follow the reasoning for making these return |
@geofft do you still require input on this? If you read back through the PR there's a preference to use the higher level functions when they are available instead of the lower level ptrace call (avoids the user keeping unsafe blocks to move their data to a c_void). I'm sure @Susurrus can weigh in with any input if you still need it. |
@xd009642 I think @geofft's point is that you cannot use |
Wait, doesn't the same problem also apply to Anyway, my questions are
|
Oh I see. Dammit. I had code that used the previous pre-UnsupportedOperation version but after I got my issue debugged I didn't need it anymore. I'd personally scrap the UnsupportedOperation although I see the pros of having each function go through the ffi. I just feel that exposing the ptrace function as it was may result in some people using lower level access, but they're still using one less unsafe block in their code and every little helps :) In terms of me raising a PR, I'm going on holiday after tomorrow so I won't be able to give it the time I'd want to for a couple of weeks. Would it be possible for @geofft to sneak the fix in with his PR? I could raise the PR I'm just conscious that there might be a longer delay in resolving it compared to if someone else did it. |
686: Fix special ptraces r=Susurrus In #614 we added specializations of `ptrace()` that added more type safety. As part of this, the `UnsupportedOperation` error was introduced for the requests that are covered by specialized versions so they couldn't be used with the general `ptrace()`. Unfortunately, no tests were added with this PR and so it slipped through that you could not do those operations at all anymore: `ptrace()` reported `UnsupportedOperation` for them and `ptrace_*` called `ptrace`, not `ffi::ptrace` and so also reported `UnsupportedOperation`! Whoops! This minimally-invasive surgery corrects this by adding tests that call all the specialized `ptrace_*` ignoring the return value save checking for `UnsupportedOperation`. It also changes the functions calls to use `ffi::ptrace()` directly to fix the bug. As this was never a bug in a released version of `nix`, there's no need for a changelog entry here.
686: Fix special ptraces r=Susurrus In #614 we added specializations of `ptrace()` that added more type safety. As part of this, the `UnsupportedOperation` error was introduced for the requests that are covered by specialized versions so they couldn't be used with the general `ptrace()`. Unfortunately, no tests were added with this PR and so it slipped through that you could not do those operations at all anymore: `ptrace()` reported `UnsupportedOperation` for them and `ptrace_*` called `ptrace`, not `ffi::ptrace` and so also reported `UnsupportedOperation`! Whoops! This minimally-invasive surgery corrects this by adding tests that call all the specialized `ptrace_*` ignoring the return value save checking for `UnsupportedOperation`. It also changes the functions calls to use `ffi::ptrace()` directly to fix the bug. As this was never a bug in a released version of `nix`, there's no need for a changelog entry here.
686: Fix special ptraces r=Susurrus In #614 we added specializations of `ptrace()` that added more type safety. As part of this, the `UnsupportedOperation` error was introduced for the requests that are covered by specialized versions so they couldn't be used with the general `ptrace()`. Unfortunately, no tests were added with this PR and so it slipped through that you could not do those operations at all anymore: `ptrace()` reported `UnsupportedOperation` for them and `ptrace_*` called `ptrace`, not `ffi::ptrace` and so also reported `UnsupportedOperation`! Whoops! This minimally-invasive surgery corrects this by adding tests that call all the specialized `ptrace_*` ignoring the return value save checking for `UnsupportedOperation`. It also changes the functions calls to use `ffi::ptrace()` directly to fix the bug. As this was never a bug in a released version of `nix`, there's no need for a changelog entry here.
Some ptrace functions return structures through the data argument. This commit adds utilities to return data through this mechanism and function specialisations for a few of these functions (getting event messages or the siginfo_t struct). Once the next version of libc is released these utilities will be expanded to include the fpregs and user_regs structs.
Due to the need to use unsafe blocks to utilise these ptrace features I feel these are good candidates for inclusion into rust-nix