-
Notifications
You must be signed in to change notification settings - Fork 11
Description
What is the Problem:
When calling ptrace(PTRACE_TRACEME, 0 , NULL, NULL), the current process will be traced by it's parent (according to the ptrace man pages). It also states, that "the remaining requests are used only by the tracer". This also includes the PTRACE_DETACH request. The control-flow of the provided test suggests, that the tracing of the current process should stop if ptrace was successful (It will be called regardless, but this is a non issue in theory).
Here is the relevant code section taken from test_ptrace.c
static int detect(void)
{
if (ptrace(PTRACE_TRACEME, 0, NULL, NULL) == -1) {
return RESULT_YES;
}
ptrace(PTRACE_DETACH, 0, NULL, NULL);
return RESULT_NO;
}When testing the Code, the PTRACE_DETACH request will always end in failure (which is to be expected given the man page entry). When including errno, it can be found that the returned error code is 3, which refers to NO SUCH PROCESS. Which is not surprising, considering the provided arguments. Therefore, the initiated trace (if no other process already initiated a ptrace on this process), will not be stopped as expected.
Is the functionality of the provided test affected:
Kind-of: The Test will work fine if it is only run once. But due to the fact that the tracing is not properly stopped, it will always fail to complete the "PTRACE_TRACEME" request if it succeeded once before. This is not a problem for the "proof of concept" testing done is this project, but it becomes one when a project requires to continuously check this condition.
How to fix:
I'm still debating with myself how to implement this test properly in a simple and fast manner. This is also why I raised an Issue before anything else, since I myself am not sure what the best replacement would be.
One solution might be, to fork the current process and handle the test in the child process. Then PTRACE_DETACH can be called from the parent.
On the other hand: One might just start a ptrace on program startup (and refuse to start if ptrace failed), therefore blocking all further ptrace attempts. But this also has some nasty side effects (e.g. weird program behavior on SIGNALS except SIGKILL (The program will just stop instead of crash))