Skip to content
Advertisement

gdb catch syscall condition and string comparisson

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"
User contributions licensed under: CC BY-SA
10 People found this is helpful
Advertisement