A truss example

      我一直认为,truss是Solaris里面一个非常重要的诊断工具,也是我最喜欢使用的工具。基本上80%的软件问题,我都通过truss找到了线索。Solaris 10提供了更有效的工具dtrace,但是很多时候,truss使用起来更简单,也更容易发现线索(当然,有些问题是truss无法诊断,并且可能导致问题恶化的,比如与时间相关的性能问题等)


      truss可以跟踪进程执行的系统调用(system calls)和信号(signals)情况。其用法如下:


     truss [-fcaeildDE] [- [tTvx] [!] syscall ,...]
          [- [sS] [!] signal ,...] [- [mM] [!] fault ,...]
          [- [rw] [!] fd ,...]
          [- [uU] [!] lib ,... : [:] [!] func ,...]
          [-o outfile] command | -p pid[/lwps]...


      参数比较多,我一般的用法是


      truss -afield -rall -wall -vall -o outputfile -p pid 或者


      truss -afield -rall -wall -vall -o outputfile app


其中outputfile是truss跟踪信息的输出文件,如果不指定-o,缺省会从STDOUT输出,pid是需要跟踪的进程的pid,或者可以直接跟踪一个程序app的执行。


       -rall 表示跟踪所有read()系统调用的I/O buffer的内容


       -wall 表示跟踪所有write()系统调用的I/O buffer的内容


       -vall 表示显示详细信息,比如传递给系统调用的数据结构的信息


       -afield实际上就是-a -f -i -e -l -d的连写,为了便于记忆,你可以把它理解成"一个现场工程师"(field engineer),呵呵。


       这些参数的含义我就不在这里列出,大家请参考man truss


       收集完truss跟踪文件后,我们就可以对跟踪文件进行分析。对此文件的分析需要有一定的系统调用知识。下面是一个具体例子。


-------------------------------------


    [ 问题 ]


    系统无法telnet或者ftp上去(提示连接被拒绝),但是系统的TCP/IP是激活的,可以获得ping响应


    [ 现象 ]


从系统console登录,检查/etc/inetd.conf,有如下内容


ftp     stream  tcp6    nowait  root    /usr/sbin/in.ftpd       in.ftpd
telnet  stream  tcp6    nowait  root    /usr/sbin/in.telnetd    in.telnetd


      inetd进程在运行


   root   952     1  0   May 05 ?       27:39 /usr/sbin/inetd -s
      端口号21,23都在侦听


      \*.21                 \*.\*                0      0 24576      0 LISTEN
      \*.23                 \*.\*                0      0 24576      0 LISTEN


    [ 诊断 ]


      请现场工程师在console里运行:  truss -afield -rall -wall -o /var/tmp/inetd.truss -p 952,


      同时,从另外一台服务器上执行telnet的操作,等到出现连接被拒绝时,Ctrl+C中断上面的truss程序,然后分析inetd.truss


      下面是截取的inetd.truss中关键的信息。(建议从文件结尾往前倒着看,因为问题出现时,我们就中断了truss执行,因此线索应该位于跟踪文件的后半段)


...


22707/1:        44.5740 stat64("/usr/lib/security/pam_seos.so", 0xFFBEF7D0) = 0
22707/1:        44.5741 stat("/usr/lib/security/pam_seos.so", 0xFFBEF10C) = 0
22707/1:        44.5742 open("/usr/lib/security/pam_seos.so", O_RDONLY) = 3
22707/1:        44.5743 fstat(3, 0xFFBEF10C)                            = 0
22707/1:        44.5744 mmap(0x00000000, 8192, PROT_READ|PROT_EXEC, MAP_PRIVATE, 3, 0) = 0xFF1D0000
22707/1:        44.5745 mmap(0x00000000, 950272, PROT_NONE, MAP_PRIVATE|MAP_NORESERVE|MAP_ANON, -1, 0) = 0xFED80000
22707/1:        44.5746 mmap(0xFED80000, 224774, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED, 3, 0) = 0xFED80000
22707/1:        44.5746 mmap(0xFEDC6000, 33970, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_FIXED, 3, 221184) = 0xFEDC6000
22707/1:        44.5748 mmap(0xFEDD0000, 620336, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_ANON, -1, 0) = 0xFEDD0000
22707/1:        44.5749 munmap(0xFEDB8000, 57344)                       = 0
22707/1:        44.5751 memcntl(0xFED80000, 74796, MC_ADVISE, MADV_WILLNEED, 0, 0) = 0
22707/1:        44.5751 close(3)                                        = 0
22707/1:        44.5766 munmap(0xFF1D0000, 8192)                        = 0
22707/1:        44.5767 open("/etc/seos.ini", O_RDONLY)                 Err#2 ENOENT
22707/1:        44.5769 open("/usr/seos/seos.ini", O_RDONLY)            Err#2 ENOENT
22707/1:        44.5770 open("/usr/local/seos/seos.ini", O_RDONLY)      Err#2 ENOENT
22707/1:        44.5771 open("/usr/seos/data/seos.ini", O_RDONLY)       Err#2 ENOENT
22707/1:        44.5772 open("/usr/local/seos/data/seos.ini", O_RDONLY) Err#2 ENOENT
22707/1:        44.5774 open(".//seos.ini", O_RDONLY)                   Err#2 ENOENT
22707/1:        44.5776 open(".//etc/osver", O_RDONLY)                  Err#2 ENOENT
22707/1:        44.5777     Incurred fault #6, FLTBOUNDS  %pc = 0xFF19131C
22707/1:              siginfo: SIGSEGV SEGV_MAPERR addr=0x0000000C
22707/1:        44.5778     Received signal #11, SIGSEGV [default]
22707/1:              siginfo: SIGSEGV SEGV_MAPERR addr=0x0000000C

...


      此段大概位于truss跟踪文件的98%位置处。


      注意看粗体部分。


     /usr/lib/security/pam_seos.so 这个动态连接库应该与PAM(Pluggable Authentication Module)模块有关,注意它的pam_前缀。seos应该是CA eTrust的产品。应该是用户对此系统作了安全加固。查看pam.conf,最后几行如下:


#
# eTrust integrate auth and account
#
other   auth    optional        /usr/lib/security/pam_seos.so
rlogin  auth    optional        /usr/lib/security/pam_seos.so
other   account optional        /usr/lib/security/pam_seos.so


      再看上面truss跟踪文件,从open返回ENOENT错误,可以看出inetd无法找到与pam_seos相干的配置文件seos.ini。那么找不到配置文件,会有什么后果呢?看下面紧接着的SIGSEGV就应该知道,后果很严重,直接导致这个22707的子进程终止


22707/1:                \*\*\* process killed \*\*\*


     22707执行的是/bin/login程序(从truss跟踪文件可以得到此信息,在此略去),由于/bin/login无法执行,因此用户无法使用telnet/ftp登录。


   [ 解决办法 ]


    1. 注释掉/etc/pam.conf中与pam_seos相关的行


    2. 恢复seos.ini文件。


---------------------



评论:

发表一条评论:
  • HTML语法: 禁用
About

samwan

Search

Categories
Archives
« 四月 2014
星期日星期一星期二星期三星期四星期五星期六
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
今天