I would like to catch
a system call (more specifically access
) and set a condition
on it based on string comparison (obviously for arguments that are strings).
Specific example: when debugging ls
I would like to catch access
syscalls for specific pathnames (the 1st argument)
int access(const char *pathname, int mode);
So far, I have succeeded in manually inspecting the pathname argument of access
(see [1]
).
I tried to use this blog post:
catch syscall access condition 1 strcmp((char*)($rdi), "/etc/ld.so.preload") == 0
but failed (see [2]
), as gdb informed me of a segfault and that Evaluation of the expression containing the function (strcmp@plt) will be abandoned.
. However gdb suggested set unwindonsignal on
.
Which I tried:
set unwindonsignal on catch syscall access condition 1 strcmp((char*)($rdi), "/etc/ld.so.preload") == 0
but failed again (see [3]
) with a similar error and the suggestion set unwindonsignal off
…
I searched for the The program being debugged was signaled while in a function called from GDB.
error message, but (I think) I didn’t find something relevant.
Any help or ideas?
[1]
$ gdb ls GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.2) 7.7.1 ... Reading symbols from ls...(no debugging symbols found)...done. (gdb) catch syscall access Catchpoint 1 (syscall 'access' [21]) (gdb) r Starting program: /bin/ls Catchpoint 1 (call to syscall access), 0x00007ffff7df3537 in access () at ../sysdeps/unix/syscall-template.S:81 81 ../sysdeps/unix/syscall-template.S: No such file or directory. (gdb) x /s $rdi 0x7ffff7df6911: "/etc/ld.so.nohwcap" (gdb) c Continuing. Catchpoint 1 (returned from syscall access), 0x00007ffff7df3537 in access () at ../sysdeps/unix/syscall-template.S:81 81 in ../sysdeps/unix/syscall-template.S (gdb) x /s $rdi 0x7ffff7df6911: "/etc/ld.so.nohwcap" (gdb) c Continuing. Catchpoint 1 (call to syscall access), 0x00007ffff7df3537 in access () at ../sysdeps/unix/syscall-template.S:81 81 in ../sysdeps/unix/syscall-template.S (gdb) x /s $rdi 0x7ffff7df9420 <preload_file.9747>: "/etc/ld.so.preload"
[2]
$ gdb ls GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.2) 7.7.1 ... Reading symbols from ls...(no debugging symbols found)...done. (gdb) catch syscall access Catchpoint 1 (syscall 'access' [21]) (gdb) condition 1 strcmp((char*)($rdi), "/etc/ld.so.preload") == 0 (gdb) info breakpoints Num Type Disp Enb Address What 1 catchpoint keep y syscall "access" stop only if strcmp((char*)($rdi), "/etc/ld.so.preload") == 0 (gdb) r Starting program: /bin/ls Program received signal SIGSEGV, Segmentation fault. 0x0000000000000000 in ?? () Error in testing breakpoint condition: The program being debugged was signaled while in a function called from GDB. GDB remains in the frame where the signal was received. To change this behavior use "set unwindonsignal on". Evaluation of the expression containing the function (strcmp@plt) will be abandoned. When the function is done executing, GDB will silently stop. Catchpoint 1 (returned from syscall munmap), 0x0000000000000000 in ?? ()
[3]
$ gdb ls GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.2) 7.7.1 ... Reading symbols from ls...(no debugging symbols found)...done. (gdb) set unwindonsignal on (gdb) catch syscall access Catchpoint 1 (syscall 'access' [21]) (gdb) condition 1 strcmp((char*)($rdi), "/etc/ld.so.preload") == 0 (gdb) r Starting program: /bin/ls Program received signal SIGSEGV, Segmentation fault. 0x0000000000000000 in ?? () Error in testing breakpoint condition: The program being debugged was signaled while in a function called from GDB. GDB has restored the context to what it was before the call. To change this behavior use "set unwindonsignal off". Evaluation of the expression containing the function (strcmp@plt) will be abandoned. Catchpoint 1 (returned from syscall munmap), 0x00007ffff7df3537 in access () at ../sysdeps/unix/syscall-template.S:81 81 ../sysdeps/unix/syscall-template.S: No such file or directory. (gdb) x /s $rdi 0x7ffff7df6911: "/etc/ld.so.nohwcap"
Advertisement
Answer
You can use the gdb internal function $_streq
like this:
(gdb) catch syscall access Catchpoint 1 (syscall 'access' [21]) (gdb) condition 1 $_streq((char *)$rdi, "/etc/ld.so.preload") (gdb) ru Starting program: /bin/ls Catchpoint 1 (call to syscall access), 0x00007ffff7df3537 in access () at ../sysdeps/unix/syscall-template.S:81 81 ../sysdeps/unix/syscall-template.S: No such file or directory. (gdb) p (char *)$rdi $1 = 0x7ffff7df9420 <preload_file> "/etc/ld.so.preload"