Strace outil de dépannage Linux / debugging
strace est un utilitaire permettant de tracer/suivre les appels systèmes. Comment utiliser strace pour debugguer des applications ou des exécutables ?
strace est un utilitaire permettant de tracer/suivre les appels systèmes. Les appels systèmes sont les interfaces fondamentales entre les applications et le noyau. Généralement, ils ne sont pas appelés directement, mais via des wrappers de la glibc. Par exemples: fstat, mmap, open, close
open("/usr/lib/locale/fr_FR.utf8/LC_MONETARY", O_RDONLY) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=290, ...}) = 0
mmap(NULL, 290, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f841bde9000
close(3)
En utilisant strace, on peut intercepter ces appels systèmes pour un processus ou une commande donnée. strace est donc un outil puissant de dépannage pour tous les administrateurs et utilisateurs unix/linux.
Strace utilisation basique
strace commande
root@kali:~# strace ifconfig eth0
execve("/sbin/ifconfig", ["ifconfig", "eth0"], [/* 34 vars */]) = 0
brk(0) = 0x1b0f000
...
write(1, " inet adr:192.168.1.14 "..., 75
inet adr:192.168.1.14 Bcast:192.168.1.255 Masque:255.255.255.0
) = 75
open("/proc/net/if_inet6", O_RDONLY) = 6
...
close(5) = 0
exit_group(0)
Appels systèmes dans un fichier
Si vous voulez enregistrer la sortie strace dans un fichier, utilisez: strace -o filename commande
Par exemple:
root@kali:~# strace -o strace.txt ifconfig eth0
eth0
Link encap:Ethernet HWaddr 00:0c:29:b9:0e:c0
inet adr:192.168.1.14 Bcast:192.168.1.255 Masque:255.255.255.0
adr inet6: 2a01:e35:2f20:ed90:20c:29ff:feb9:ec0/64 Scope:Global
adr inet6: fe80::20c:29ff:feb9:ec0/64 Scope:Lien
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:17876 errors:0 dropped:0 overruns:0 frame:0
TX packets:10953 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 lg file transmission:1000
RX bytes:18635399 (17.7 MiB) TX bytes:980986 (957.9 KiB)
root@kali:~# head -n 2 strace.txt
execve("/sbin/ifconfig", ["ifconfig", "eth0"], [/* 34 vars */]) = 0
brk(0) = 0x1437000
Rapport/sommaire d’appels systèmes
strace -c command permet de faire un rapport des appels systèmes. Par exemple:
root@kali:~# strace -c ifconfig eth0
eth0 Link encap:Ethernet HWaddr 00:0c:29:b9:0e:c0
inet adr:192.168.1.14 Bcast:192.168.1.255 Masque:255.255.255.0
adr inet6: 2a01:e35:2f20:ed90:20c:29ff:feb9:ec0/64 Scope:Global
adr inet6: fe80::20c:29ff:feb9:ec0/64 Scope:Lien
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:17294 errors:0 dropped:0 overruns:0 frame:0
TX packets:10524 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 lg file transmission:1000
RX bytes:18290334 (17.4 MiB) TX bytes:924666 (902.9 KiB)
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
100.00 0.040000 2857 14 11 access
0.00 0.000000 0 8 read
0.00 0.000000 0 10 write
0.00 0.000000 0 35 14 open
0.00 0.000000 0 22 close
0.00 0.000000 0 22 fstat
0.00 0.000000 0 28 mmap
0.00 0.000000 0 6 mprotect
0.00 0.000000 0 4 munmap
0.00 0.000000 0 3 brk
0.00 0.000000 0 11 ioctl
0.00 0.000000 0 3 socket
0.00 0.000000 0 1 execve
0.00 0.000000 0 1 uname
0.00 0.000000 0 1 arch_prctl
------ ----------- ----------- --------- --------- ----------------
100.00 0.040000 169 25 total
Ici, l’appel système open génère 14 erreurs. Comment tracer spécifiquement ces appels systèmes ?
Tracer un appel système spécifique
On utilise l’option -e de strace:
root@kali:~# strace -e open ifconfig eth0
open("/etc/ld.so.cache", O_RDONLY) = 3
open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY) = 3
open("/usr/lib/locale/locale-archive", O_RDONLY) = -1 ENOENT (No such file or directory)
...
open("/usr/lib/x86_64-linux-gnu/gconv/ISO8859-1.so", O_RDONLY) = 6
eth0 Link encap:Ethernet HWaddr 00:0c:29:b9:0e:c0
inet adr:192.168.1.14 Bcast:192.168.1.255 Masque:255.255.255.0
open("/proc/net/if_inet6", O_RDONLY) = 6
adr inet6: 2a01:e35:2f20:ed90:20c:29ff:feb9:ec0/64 Scope:Global
adr inet6: fe80::20c:29ff:feb9:ec0/64 Scope:Lien
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:17783 errors:0 dropped:0 overruns:0 frame:0
TX packets:10915 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 lg file transmission:1000
RX bytes:18626514 (17.7 MiB) TX bytes:978630 (955.6 KiB)
On voit clairement que ifconfig essaye d’ouvrir des fichiers absents. Combien ?
root@kali:~# strace -e open ifconfig eth0 2>&1 | grep "No such file or directory" | wc -l
14
Exactement 14 !!! comme l’indiquait le rapport d’appels systèmes.
Tracer plusieurs appels systèmes spécifiques
On peut utiliser l’option -e trace=function1,function2, … Par exemple pour tracer les appels systèmes mprotect ou brk:
root@kali:~# strace -e trace=mprotect,brk ifconfig eth0
brk(0) = 0x1c1f000
mprotect(0x7f400429c000, 2097152, PROT_NONE) = 0
mprotect(0x7f400449c000, 16384, PROT_READ) = 0
mprotect(0x60f000, 4096, PROT_READ) = 0
mprotect(0x7f40046c5000, 4096, PROT_READ) = 0
brk(0) = 0x1c1f000
brk(0x1c40000) = 0x1c40000
mprotect(0x7f4003f1b000, 2093056, PROT_NONE) = 0
mprotect(0x7f400411a000, 4096, PROT_READ) = 0
eth0 Link encap:Ethernet HWaddr 00:0c:29:b9:0e:c0
inet adr:192.168.1.14 Bcast:192.168.1.255 Masque:255.255.255.0
adr inet6: 2a01:e35:2f20:ed90:20c:29ff:feb9:ec0/64 Scope:Global
adr inet6: fe80::20c:29ff:feb9:ec0/64 Scope:Lien
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:17822 errors:0 dropped:0 overruns:0 frame:0
TX packets:10932 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 lg file transmission:1000
RX bytes:18630337 (17.7 MiB) TX bytes:979684 (956.7 KiB)
Tracer une catégorie spécifique d’appels systèmes
-e trace=file On peut penser qu’il s’agit là d’une abréviation de -e trace=open,stat,chmod,unlink,…En outre, utiliser cette abréviation permet de s’assurer que l’on n’omet pas d’inclure les appels lstat
-e trace=process Trace tous les appels systèmes liés à la gestion des processus. C’est particulièrement utile pour suivre les étapes fork, wait et exec d’un process.
-e trace=network Trace tous les appels systèmes de type réseau.
-e trace=signal Trace tous les appels systèmes de type signal.
-e trace=ipc Trace tous les appels systèmes IPC.
-e trace=desc Trace tous les appels systèmes liés aux descripteurs.
Par exemple pour tracer les appels spécifiques au réseau (network):
root@kali:~# strace -e trace=network ifconfig eth0
socket(PF_FILE, SOCK_DGRAM, 0) = 3
socket(PF_INET, SOCK_DGRAM, IPPROTO_IP) = 4
socket(PF_INET6, SOCK_DGRAM, IPPROTO_IP) = 5
eth0 Link encap:Ethernet HWaddr 00:0c:29:b9:0e:c0
inet adr:192.168.1.14 Bcast:192.168.1.255 Masque:255.255.255.0
adr inet6: 2a01:e35:2f20:ed90:20c:29ff:feb9:ec0/64 Scope:Global
adr inet6: fe80::20c:29ff:feb9:ec0/64 Scope:Lien
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:17836 errors:0 dropped:0 overruns:0 frame:0
TX packets:10940 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 lg file transmission:1000
RX bytes:18631824 (17.7 MiB) TX bytes:980182 (957.2 KiB)
Récupérer les horodatages/timestamps et les temps d’appels sytèmes
Il peut àªtre utile de récupérer les temps d’appels systèmes et leur timestamp:
strace -r Timestamp relatif - temps passé pour un appel système strace -t Préfixer chaque ligne par la date du jour strace -tt Préfixer chaque ligne par la date du jour à la microseconde près strace -ttt Préfixer chaque ligne par la date du jour à la microseconde près depuis le 1er janvier 1970 (The Epoch)
root@kali:~# strace -r -o strace_r.txt ifconfig eth0 > /dev/null
root@kali:~# strace -t -o strace_t.txt ifconfig eth0 > /dev/null
root@kali:~# strace -tt -o strace_tt.txt ifconfig eth0 > /dev/null
root@kali:~# strace -ttt -o strace_ttt.txt ifconfig eth0 > /dev/null
root@kali:~# ls -rt strace_*
strace_r.txt strace_t.txt strace_tt.txt strace_ttt.txt
root@kali:~# head -n 2 strace_*
==> strace_r.txt <==
0.000000 execve("/sbin/ifconfig", ["ifconfig", "eth0"], [/* 34 vars */]) = 0
0.000192 brk(0) = 0x75a000
==> strace_ttt.txt <==
1399201553.405215 execve("/sbin/ifconfig", ["ifconfig", "eth0"], [/* 34 vars */]) = 0
1399201553.405410 brk(0) = 0x159d000
==> strace_tt.txt <==
07:05:50.173343 execve("/sbin/ifconfig", ["ifconfig", "eth0"], [/* 34 vars */]) = 0
07:05:50.173648 brk(0) = 0x1398000
==> strace_t.txt <==
07:05:41 execve("/sbin/ifconfig", ["ifconfig", "eth0"], [/* 34 vars */]) = 0
07:05:41 brk(0)
Que faire lorsqu’un processus fork
Vous pouvez suivre les appels systèmes, si un processus fork en utilisant l’option -f
root@kali:~# strace -f -o strace_acroread.txt acroread > /dev/null
Attacher à un processus existant
Pour attacher strace à un processus existant: strace -p PID
Par exemple:
root@kali:~# pidof sshd
6177
root@kali:~# strace -p 6177
Process 6177 attached - interrupt to quit
select(7, [3 4], NULL, NULL, NULL
Essayons maintenant de nous connecter sur le serveur kali (IP:192.168.1.14):
root@station:~# ssh kali
Maintenant on a quelque chose du type:
root@kali:~# strace -p 6177
Process 6177 attached - interrupt to quit
select(7, [3 4], NULL, NULL, NULL) = 1 (in [3])
accept(3, {sa_family=AF_INET, sin_port=htons(45468), sin_addr=inet_addr("192.168.1.23")}, [16]) = 5
fcntl(5, F_GETFL) = 0x2 (flags O_RDWR)
pipe([6, 7]) = 0
socketpair(PF_FILE, SOCK_STREAM, 0, [8, 9]) = 0
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f22b8b91a90) = 12420
close(7) = 0
write(8, "\0\0\2\263\0", 5) = 5
write(8, "\0\0\2\252\n\n\n\nPort 22\n\n\n\nProtocol 2\n\nH"..., 690) = 690
close(8) = 0
close(9) = 0
close(5) = 0
select(7, [3 4 6], NULL, NULL, NULL) = 1 (in [6])
close(6) = 0
select(7, [3 4], NULL, NULL, NULL
Une pair de sockets connectés est créé socketpair(…) avec pour addresse distante 192.168.1.23:45468
En outre, on voit clairement que la connection est établie :
root@kali:~# netstat -at | grep -F '192.168.1.23'
tcp 0 0 192.168.1.14:ssh 192.168.1.23:45468 ESTABLISHED
J’espère avoir pu vous aider !!! Strace est un outil très puissant, ne pas oublier man strace !!!
Si vous avez trouvé cet article ou ce site utile et souhaitez soutenir notre travail, veuillez envisager de faire un don. Merci !
Aidez-nous