Last active
August 29, 2015 14:02
-
-
Save simark/61915d6b62715a10d084 to your computer and use it in GitHub Desktop.
Global breakpoints comments
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
* 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