system callのtraceについて
system call trace
起動プログラムからOSのシステムコールを呼び出される箇所をトレースするコマンドがあります。
strace / itrace / ktrace / kdumpなど。
単純なPHPのプログラムでは特にトレースする意味はないと思いますが、PHPのエクステンション作成やミドルウェア構築の時にはトレースして状態を確認してみるのが良いかと考えます。 今回はstraceの使い方についてまとめます。
使いそうなオプション
strace
オプション 意味 -c カウント数やコール、エラーなどを記録し、サマリーも表示 -e 特定のシステムコールのみ拾う -f forkされた子プロセスも拾う -F vforkを拾う -T 処理にかかった時間を表示 -o ファイルに記録する -p プロセスIDを指定する
通常の起動
strace httpd
execve("/usr/sbin/httpd", ["httpd"], [/* 16 vars */]) = 0 brk(0) = 0x2ae87fab0000 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x2ae879abe000 uname({sys="Linux", node="localhost.localdomain", ...}) = 0 access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory) open("/etc/ld.so.cache", O_RDONLY) = 3 fstat(3, {st_mode=S_IFREG|0644, st_size=111599, ...}) = 0 mmap(NULL, 111599, PROT_READ, MAP_PRIVATE, 3, 0) = 0x2ae879abf000 close(3) = 0 open("/lib64/libm.so.6", O_RDONLY) = 3 (略)
処理にかかった時間を表示( -T )
strace -T httpd
execve("/usr/sbin/httpd", ["httpd"], [/* 16 vars */]) = 0 <0.001002> brk(0) = 0x2ac1fd186000 <0.000019> mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x2ac1ddf60000 <0.000021> uname({sys="Linux", node="localhost.localdomain", ...}) = 0 <0.000018> access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory) <0.000033> open("/etc/ld.so.cache", O_RDONLY) = 3 <0.000026> fstat(3, {st_mode=S_IFREG|0644, st_size=111599, ...}) = 0 <0.000020> mmap(NULL, 111599, PROT_READ, MAP_PRIVATE, 3, 0) = 0x2ac1ddf61000 <0.000022> close(3) = 0 <0.000019> open("/lib64/libm.so.6", O_RDONLY) = 3 <0.000034> (略)
特定のシステムコールのみ拾う( -e )
strace -e write httpd
write(2, "(13)Permission denied: make_sock"..., 68(13)Permission denied: make_sock: could not bind to address [::]:80 ) = 68 write(2, "(13)Permission denied: make_sock"..., 71(13)Permission denied: make_sock: could not bind to address 0.0.0.0:80 ) = 71 write(2, "no listening sockets available, "..., 46no listening sockets available, shutting down ) = 46 write(2, "Unable to open logs\n", 20Unable to open logs ) = 20
サマリー表示( -c ), forkを拾う( -f , -F )
strace -c -f -F httpd
% time seconds usecs/call calls errors syscall ------ ----------- ----------- --------- --------- ---------------- 34.33 0.000721 9 84 munmap 31.43 0.000660 3 232 mmap 15.81 0.000332 3 105 mprotect 5.29 0.000111 1 131 6 open 3.67 0.000077 1 144 read 3.48 0.000073 7 11 6 connect 3.10 0.000065 0 142 close 1.62 0.000034 5 7 setsockopt 1.29 0.000027 0 121 fstat 0.00 0.000000 0 4 write 0.00 0.000000 0 20 3 stat 0.00 0.000000 0 1 lseek 0.00 0.000000 0 12 brk 0.00 0.000000 0 2 rt_sigaction 0.00 0.000000 0 1 rt_sigprocmask 0.00 0.000000 0 2 readv 0.00 0.000000 0 2 1 access 0.00 0.000000 0 18 socket 0.00 0.000000 0 3 sendto 0.00 0.000000 0 1 sendmsg 0.00 0.000000 0 9 recvmsg 0.00 0.000000 0 5 2 bind 0.00 0.000000 0 7 getsockname 0.00 0.000000 0 1 execve 0.00 0.000000 0 2 uname 0.00 0.000000 0 19 fcntl 0.00 0.000000 0 2 getdents 0.00 0.000000 0 1 getrlimit 0.00 0.000000 0 1 getuid 0.00 0.000000 0 1 getppid 0.00 0.000000 0 1 arch_prctl 0.00 0.000000 0 1 gettid 0.00 0.000000 0 4 futex 0.00 0.000000 0 1 set_tid_address 0.00 0.000000 0 1 set_robust_list ------ ----------- ----------- --------- --------- ---------------- 100.00 0.002100 1099 18 total
トレース結果をファイルに保存( -o )
strace -c -f -F -o trace.txt httpd
※トレースした結果をtrace.txtに保存
プロセスIDを指定する( -p )
strace -p `ps auxww | grep 'httpd' | awk '{ print $2 }' | head -n 1`
※psなどの結果からプロセスIDを取得しstraceに流す
おまけ( -e execve )
strace -e execve -p PID
※不審なプロセスを調査する。
http://www.atmarkit.co.jp/fsecurity/rensai/securitytips/012strace.html