5

I have a hypothetical situation:

  1. Let us say we have two strace processes S1 & S2, which are simply monitoring each other.
    How can this be possible?
    Well, in the command-line options for strace, -p PID is the way to pass the required PID, which (in our case) is not yet known when we issue the strace command. We could change the strace source code, such that -P 0 means, ask user for PID. E.g., read() from STDIN. When we can run two strace processes in two shell sessions and find the PIDs in a third shell, we can provide that input to S1 & S2 and let them monitor each other.
    Would S1 & S2 get stuck? Or, go into infinite loops, or crash immediately or...?

  2. Again, let us say we have another strace process S3, with -p -1, which, by modifying the source code, we use to tell S3 to monitor itself. E.g., use getpid() without using STDIN. Would S3 crash? Or, would it hang with no further processing possible? Would it wait for some event to happen, but, because it is waiting, no event would happen?

In the strace man-page, it says that we can not monitor an init process. Is there any other limitation enforced by strace, or by the kernel, to avoid a circular dependency or loop?

Some Special Cases :
S4 monitors S5, S5 monitors S6, S6 monitors S4.
S7 & S8 monitoring each other where S7 is the Parent of S8.
More special cases are possible.

EDIT (after comments by @Ralph Rönnquist & @pfnuesel) :
https://github.com/bnoordhuis/strace/blob/master/strace.c#L941

if (pid <= 0) {
    error_msg_and_die("Invalid process id: '%s'", opt);
}
if (pid == strace_tracer_pid) {
    error_msg_and_die("I'm sorry, I can't let you do that, Dave.");
}

Specifically, what will happen if strace.c does not check for pid == strace_tracer_pid or any other special cases? Is there any technical limitation (in kernel) over one process monitoring itself? How about a group of 2 (or 3 or more) processes monitoring themselves? Will the system crash or hang?

3

I will answer for Linux only.

Surprisingly, in newer kernels, the ptrace system call, which is used by strace in order to actually perform the tracing, is allowed to trace the init process. The manual page says:

   EPERM  The specified process cannot be traced.  This could  be  because
          the  tracer has insufficient privileges (the required capability
          is CAP_SYS_PTRACE); unprivileged  processes  cannot  trace  pro‐
          cesses  that  they  cannot send signals to or those running set-
          user-ID/set-group-ID programs, for  obvious  reasons.   Alterna‐
          tively,  the process may already be being traced, or (on kernels
          before 2.6.26) be init(8) (PID 1).

implying that starting in version 2.6.26, you can trace init, although of course you must still be root in order to do so. The strace binary on my system allows me to trace init, and in fact I can even use gdb to attach to init and kill it. (When I did this, the system immediately came to a halt.)

ptrace cannot be used by a process to trace itself, so if strace did not check, it would nevertheless fail at tracing itself. The following program:

#include <sys/ptrace.h>
#include <stdio.h>
#include <unistd.h>
int main() {
    if (ptrace(PTRACE_ATTACH, getpid(), 0, 0) == -1) {
        perror(NULL);
    }
}

prints Operation not permitted (i.e., the result is EPERM). The kernel performs this check in ptrace.c:

 retval = -EPERM;
 if (unlikely(task->flags & PF_KTHREAD))
         goto out;
 if (same_thread_group(task, current)) // <-- this is the one
         goto out;

Now, it is possible for two strace processes can trace each other; the kernel will not prevent this, and you can observe the result yourself. For me, the last thing that the first strace process (PID = 5882) prints is:

ptrace(PTRACE_SEIZE, 5882, 0, 0x11

whereas the second strace process (PID = 5890) prints nothing at all. ps shows both processes in the state t, which, according to the proc(5) manual page, means trace-stopped.

This occurs because a tracee stops whenever it enters or exits a system call and whenever a signal is about to be delivered to it (other than SIGKILL).

Assume process 5882 is already tracing process 5890. Then, we can deduce the following sequence of events:

  1. Process 5890 enters the ptrace system call, attempting to trace process 5882. Process 5890 enters trace-stop.
  2. Process 5882 receives SIGCHLD to inform it that its tracee, process 5890 has stopped. (A trace-stopped process appears as though it received the `SIGTRAP signal.)
  3. Process 5882, seeing that its tracee has made a system call, dutifully prints out the information about the syscall that process 5890 is about to make, and the arguments. This is the last output you see.
  4. Process 5882 calls ptrace(PTRACE_SYSCALL, 5890, ...) to allow process 5890 to continue.
  5. Process 5890 leaves trace-stop and performs its ptrace(PTRACE_SEIZE, 5882, ...). When the latter returns, process 5890 enters trace-stop.
  6. Process 5882 is sent SIGCHLD since its tracee has just stopped again. Since it is being traced, the receipt of the signal causes it to enter trace-stop.

Now both processes are stopped. The end.

As you can see from this example, the situation of two process tracing each other does not create any inherent logical difficulties for the kernel, which is probably why the kernel code does not contain a check to prevent this situation from happening. It just happens to not be very useful for two processes to trace each other.

  • +1 ; Nice analysis !! I will be taking some time to analyze this further, but it does sound Practical & logical !! – Prem Feb 13 '17 at 13:38
7
% sh -c 'exec strace -p $$'    
strace: I'm sorry, I can't let you do that, Dave.

:-)

  • Is the quote actually correct? – pfnuesel Feb 29 '16 at 4:59
  • That's what happens for me. Made my day :-) – Ralph Rönnquist Feb 29 '16 at 5:01
  • Yes, for me, too, and I didn't know about it, so +1. But I'm just wondering, if the quote should not be: I'm sorry, Dave, I can't let you do that.. ;-) – pfnuesel Feb 29 '16 at 5:03
  • You're right, it's "Dave Bowman: Open the pod bay doors, HAL. HAL: I'm sorry, Dave. I'm afraid I can't do that." – Ralph Rönnquist Feb 29 '16 at 5:06
  • +1 , Would you believe me if I said my initial thinking was about "self-aware" Processes, moving on to "Artificial Intelligence" ? It seems to be leading to 2001 . . . . – Prem Feb 29 '16 at 6:50
2

Just want to show you a real example of circular Dependency or loop which could cause the system freeze.

In your X session and graphical terminal emulator, run this command to get the Xorg.bin pid:

[xiaobai@xiaobai tmp]$ pgrep Xorg
1780
[xiaobai@xiaobai tmp]$

Then do:

[xiaobai@xiaobai tmp]$ sudo strace -p 1780

It will freeze entire desktop after a few seconds (~5), at least in my fedora 21 gnome 3.14.0, i have to turn off the power button.

But if you try either run sudo strace -p 1780 in the other tty via Ctrl-alt-F1|7 OR sudo strace -p 1780 2>/tmp/strace.log, both will not freeze.

So we can conclude that strace receive Xorg's output then print it to Xorg and cause infinitely loop and freeze.

  • 1
    +1 , I like this experiment. My interpretation is like this : When 1 Xevent happens, many (say around 10) system calls are made. Each of these system calls will have to be captured and printed by strace. Each of the strace prints will generate many (say around 10) Xevents. We now have 10*10 Xevents, which require 10*10*10 system calls, which will require 10*10*10 lines of strace output, which require 10*10*10*10 Xevents. Pretty quickly, this exponential growth will fill up the internal event queues or output buffers , hence the system will freeze. Well, it sure highlights a specific problem ! – Prem May 10 '16 at 13:22
  • 1
    @Prem The other example is strace -p "pid of terminal emulator A" in terminal emulator A, same conceptual above except might take longer to freeze and it only freeze the relevant terminal emulator(s). And one more example is konsole strace gnome-terminal and gnome-terminal strace konsole, both will freeze. When testing, use mouse to hover the terminal emulator will generate a lot of log and freeze soon. – 林果皞 May 10 '16 at 15:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.