Skip to content

Instantly share code, notes, and snippets.

@simark
Last active August 29, 2015 14:02
Show Gist options
  • Save simark/61915d6b62715a10d084 to your computer and use it in GitHub Desktop.
Save simark/61915d6b62715a10d084 to your computer and use it in GitHub Desktop.
Global breakpoints comments
* Permissions and scope (system-global vs user-global)
Use case:
A user would like to debug its CGI web application written in C with
GDB. It is hosted on a shared server, where Apache runs as www-data.
When a request comes in, Apache forks, does some some suid magic to run
the CGI program as the user and the program finishes. It can be
difficult to debug this, since the user can't attach a debugger to
Apache. He can use the trick of putting a sleep or infinite loop in its
program, but that is always inconvenient.
The user could put a global breakpoint in its CGI binary. When a request
comes in, the breakpoint would hit and he could start debugging from
there.
To enable this use case, it should be possible for a non-root user to
use global breakpoints. Obviously, those breakpoints should only affect
the processes of that user, whereas breakpoints installed by the root
user could affect all processes in the system.
* Multiple gdbs
With the proposed solution, we believe that only one instance of gdb
could use global breakpoints at the time. How would it work with
multiple gdbs "selecting" uprobe_gb_active simultaneously?
* Behaviour when gdb is already attached
When a process hits a global breakpoint, if gdb is already attached to
it (the task is ptraced), the kernel could simply send an SIGINT to the
process, as it does normally. This way, nothing needs to change in gdb,
the hit is processed exactly like any other breakpoint hit.
The only problem I see: this only works if you use gdb. If you are
stracing a process and it hits a global breakpoint, it will receive a
random SIGINT, which is not good.
* gdb crashes
When gdb exits cleanly, it can correctly remove the global breakpoints
it added.
If gdb crashes (it absolutely never happens, but let's imagine for a
moment that it does), the debugged process will keep hitting the global
breakpoints. Of course, you can go fiddle with files in
/sys/kernel/debug/tracing, but end-users won't know that. For them, it
will just appear like their processes are stuck.
If they restart gdb and enable the global breakpoints feature, should
gdb go read the uprobe_events file and learn about existing global
breakpoints? It could then remove them when it exits cleanly.
But what about global breakpoints inserted by other processes (by hand,
for example)? gdb will delete those as well, which is not good.
* Info about which global breakpoint was hit
In uprobe_gb_active, it would be convenient if the name of the breakpoint
that was hit was dislpayed along with the pid. I guess it's not
absolutely needed, it would just make gdb's life a bit easier.
* Breakpoint memory shadowing
Since the program code may change at runtime, gdb goes to the process
memory to read the code instead of going to the executable file.
When reading memory from the debugged process (PTRACE_PEEK*), the int3
appears in the program code. gdb has no way to know what was the value
of the byte that was replaced. This is a problem for a few things,
including displaying disassembly. Since this int3 is inserted by the
kernel, it would be the kernel's responsibility to hide such
side-effects.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment