[Ubuntu12.04] strace를 이용한 리눅스 프로그램 system call 추적하기 Develop Tip

일반적인 리눅스 (우분투 12.04 LTS에서 테스트 했습니다)에서
리눅스의 PAM 모듈을 이용하여  로그인을 테스트 해 볼 수 있습니다.

$ sudo pip install pam
파이썬 pam 모듈을 설치합니다.

$ python -c "import pam;print pam.authenticate('user','pass','passwd')"
True

위와 같이 간단한 파이썬 명령으로 로그인 정보가 user / pass 라는 사용자인 경우,
정상 로그인 테스트를 해 볼 수 있습니다.

그런데 필요에 따라 이 명령에서 어떤 pam 모듈을 어떻게 이용되는지
구체적으로 확인해 볼 필요가 있었습니다.
어떤 방법이 있을까 생각하다가 오래 전에 유닉스 시스템 콜을 추적해 볼 수 있는 strace
명령을 이용해 보기로 하였습니다.

$ sudo apt-get install strace
명령으로 설치하여야 합니다.

$ ldd /usr/bin/strace
    linux-vdso.so.1 =>  (0x00007fff2027b000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f38c66ee000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f38c6abc000)

ldd로 확인해 보니 라이브러리 읜존도는 그리 높지 않습니다.

이제 아래와 같은 명령으로 파이썬 프로그램을 재구동시켜 봅니다.

$ strace python -c "import pam;print pam.authenticate('user','pass','passwd')" 2> foo.out

strace의 결과는 stderr로 나오므로 해당 명령의 stderr 결과를 foo.out 에 저장합니다.

이제 ,
$ less foo.out
을 하면,

execve("/usr/bin/python", ["python", "-c", "import pam;print pam.authenticat"...], [/* 51 vars */]) = 0
brk(0)                                  = 0x114c000
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fd248a30000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/usr/local/lib/tls/x86_64/libpthread.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
...

와 같은 리눅스 시스템  함수 명령 시퀀스가 출력됩니다.
음... execve 로 해당 명령을 수행하고,
ld.so.nohwcap 파일이 있는가 access 시스템 호출을 한 다음, mmap 등을 호출하네요...

이제 pam만 검사하기 위하여
/pam
검색을 해 봅니다.

stat("pam", 0x7fff57e68410)             = -1 ENOENT (No such file or directory)
open("pam.so", O_RDONLY)                = -1 ENOENT (No such file or directory)
...
우선 현재 디렉터리에서 pam.so 를 열려고 시도하였으나 실패,

stat("/opt/F3/NFW2/lib/python2.7/pam", 0x7fff57e68410) = -1 ENOENT (No such file or directory)
open("/opt/F3/NFW2/lib/python2.7/pam.so", O_RDONLY) = -1 ENOENT (No such file or directory)
...
그 다음 다른 sys.path 디렉터리를 시도하다가...

open("/lib/x86_64-linux-gnu/libpam.so.0", O_RDONLY|O_CLOEXEC) = 4
라고 libpam.so.0 을 찾았고,

stat("/etc/pam.d", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
open("/etc/pam.d/passwd", O_RDONLY)     = 3

/etc/pam.d/passwd 파일을 읽은 다음,

open("/etc/pam.d/common-password", O_RDONLY) = 4
read(4, "#\n# /etc/pam.d/common-password -"..., 4096) = 1480

/etc/pam.d/common-password 를 읽습니다.

open("/lib/x86_64-linux-gnu/security/pam_unix.so", O_RDONLY|O_CLOEXEC) = 5
read(5, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\360'\0\0\0\0\0\0"..., 832) = 832
...
close(5)

그리고 나서 pam_unix.so 파일도 읽었습니다.

open("/lib/x86_64-linux-gnu/security/pam_deny.so", O_RDONLY|O_CLOEXEC) = 5
read(5, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\0\5\0\0\0\0\0\0"..., 832) = 832
...
close(5)

pam_deny.so 파일을 읽고,

open("/lib/x86_64-linux-gnu/security/pam_permit.so", O_RDONLY|O_CLOEXEC) = 5
read(5, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\320\5\0\0\0\0\0\0"..., 832) = 832
...
close(5)

pam_permit.so 를 읽었습니다.

open("/lib/security/pam_gnome_keyring.so", O_RDONLY|O_CLOEXEC) = 5
read(5, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\340\32\0\0\0\0\0\0"..., 832) = 832
...
close(5)

그 다음에는 pam_gnome_keyring.so 을 읽었습니다.

그리고 후에,
/etc/pam.d/other 와 /etc/pam.d/common-auth를 읽었습니다.

open("/lib/x86_64-linux-gnu/security/pam_cap.so", O_RDONLY|O_CLOEXEC) = 5
read(5, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\20\f\0\0\0\0\0\0"..., 832) = 832
...
close(5)

pam_cap.so 를 읽었네요.


그 다음에는

/etc/pam.d/common-account 와
/etc/pam.d/common-password,
/etc/pam.d/common-session 을 순차적으로 읽으면서

/lib/x86_64-linux-gnu/security/pam_umask.so 공유 라이브러리를 참조했습니다.

그리고는

/lib/security/pam_ck_connector.so 를 참조하는 것으로 pam 참조를 모두 마쳤습니다.

휴우...


노가다 지만 이렇게 하여 참조하는 pam 파일 및 공유 라이브러리를 유추해 볼 수 있습니다.

결론은,
/etc/pam.d/에 있는 파일들,
/etc/pam.d/passwd
/etc/pam.d/common-password
/etc/pam.d/common-account
/etc/pam.d/common-password
/etc/pam.d/common-session


/lib/x86_64-linux-gnu/에 있는 공유 라이브러리 파일들과
/lib/x86_64-linux-gnu/libpam.so.0
/lib/x86_64-linux-gnu/security/pam_unix.so
/lib/x86_64-linux-gnu/security/pam_deny.so
/lib/x86_64-linux-gnu/security/pam_permit.so
/lib/x86_64-linux-gnu/security/pam_cap.so
/lib/x86_64-linux-gnu/security/pam_umask.so

/lib/security/에 있는 pam* 공유 라이브러리 등을 이용하는군요.
/lib/security/pam_ck_connector.so
/lib/security/pam_gnome_keyring.so


어느 분께는 도움이 되셨기를...

덧글

댓글 입력 영역

구글애드텍스트