为什么 getpwuid 在我的系统上调用 connect?
Why is getpwuid calling connect on my system?
在 Fedora 21 上考虑以下 Linux 命令:
[0:12:57][/tmp/nss]$ echo 'main() { getpwuid(1000); }' > test.c
[0:12:59][/tmp/nss]$ gcc -ggdb test.c
[0:13:01][/tmp/nss]$ gdb ./a.out -ex 'break main' -ex 'r' -ex 'break connect' -ex 'c' -ex 'bt' -ex 'quit'
GNU gdb (GDB) Fedora 7.8.2-38.fc21
Copyright (C) 2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
warning: ~/.gdbinit.local: No such file or directory
Reading symbols from ./a.out...done.
Breakpoint 1 at 0x40054a: file test.c, line 1.
Starting program: /tmp/nss/a.out
-----------------------------------------------------------------------------------------------------------------------[regs]
RAX: 0x0000000000400546 RBX: 0x0000000000000000 RBP: 0x00007FFFFFFFDB70 RSP: 0x00007FFFFFFFDB70 o d I t s Z a P c
RDI: 0x0000000000000001 RSI: 0x00007FFFFFFFDC58 RDX: 0x00007FFFFFFFDC68 RCX: 0x0000000000400560 RIP: 0x000000000040054A
R8 : 0x0000003F3E1B8E80 R9 : 0x0000003F3E1B8E80 R10: 0x0000003F3E1B76A0 R11: 0x0000003F3DE1FEF0 R12: 0x0000000000400450
R13: 0x00007FFFFFFFDC50 R14: 0x0000000000000000 R15: 0x0000000000000000
CS: 0033 DS: 0000 ES: 0000 FS: 0000 GS: 0000 SS: 002B
-----------------------------------------------------------------------------------------------------------------------[code]
=> 0x40054a <main+4>: mov edi,0x3e8
0x40054f <main+9>: mov eax,0x0
0x400554 <main+14>: call 0x400420 <getpwuid@plt>
0x400559 <main+19>: pop rbp
0x40055a <main+20>: ret
0x40055b: nop DWORD PTR [rax+rax*1+0x0]
0x400560 <__libc_csu_init>: push r15
0x400562 <__libc_csu_init+2>: push r14
-----------------------------------------------------------------------------------------------------------------------------
Breakpoint 1, main () at test.c:1
1 main() { getpwuid(1000); }
Breakpoint 2 at 0x3f3df00f70: file ../sysdeps/unix/syscall-template.S, line 81.
Continuing.
-----------------------------------------------------------------------------------------------------------------------[regs]
RAX: 0x0000000000000020 RBX: 0x0000000000000003 RBP: 0x00007FFFFFFFD790 RSP: 0x00007FFFFFFFD688 o d I t s z a p C
RDI: 0x0000000000000003 RSI: 0x00007FFFFFFFD6F0 RDX: 0x000000000000006E RCX: 0x6F732F6463736E2F RIP: 0x0000003F3DF00F70
R8 : 0x00001FFFFFFFF5A4 R9 : 0x0000000000000001 R10: 0x0000000000000000 R11: 0x0000000000000202 R12: 0x0000000000000013
R13: 0x00007FFFFFFFD690 R14: 0x0000000000000007 R15: 0x00001FFFFFFFF5A4
CS: 0033 DS: 0000 ES: 0000 FS: 0000 GS: 0000 SS: 002B
-----------------------------------------------------------------------------------------------------------------------[code]
=> 0x3f3df00f70 <connect>: cmp DWORD PTR [rip+0x2bbd7d],0x0 # 0x3f3e1bccf4 <__libc_multiple_threads>
0x3f3df00f77 <connect+7>: jne 0x3f3df00f89 <connect+25>
0x3f3df00f79 <__connect_nocancel>: mov eax,0x2a
0x3f3df00f7e <__connect_nocancel+5>: syscall
0x3f3df00f80 <__connect_nocancel+7>: cmp rax,0xfffffffffffff001
0x3f3df00f86 <__connect_nocancel+13>: jae 0x3f3df00fb9 <connect+73>
0x3f3df00f88 <__connect_nocancel+15>: ret
0x3f3df00f89 <connect+25>: sub rsp,0x8
-----------------------------------------------------------------------------------------------------------------------------
Breakpoint 2, connect () at ../sysdeps/unix/syscall-template.S:81
81 T_PSEUDO (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS)
#0 connect () at ../sysdeps/unix/syscall-template.S:81
#1 0x0000003f3df37663 in open_socket (type=type@entry=GETFDPW, key=key@entry=0x3f3df86853 "passwd", keylen=keylen@entry=0x7) at nscd_helper.c:207
#2 0x0000003f3df37d1d in __nscd_get_mapping (type=type@entry=GETFDPW, key=key@entry=0x3f3df86853 "passwd", mappedp=mappedp@entry=0x3f3e1bc618 <map_handle+8>) at nscd_helper.c:293
#3 0x0000003f3df38277 in __nscd_get_map_ref (type=type@entry=GETFDPW, name=name@entry=0x3f3df86853 "passwd", mapptr=mapptr@entry=0x3f3e1bc610 <map_handle>, gc_cyclep=gc_cyclep@entry=0x7fffffffd9fc) at nscd_helper.c:443
#4 0x0000003f3df34758 in nscd_getpw_r (key=0x7fffffffda87 "1000", keylen=keylen@entry=0x5, type=type@entry=GETPWBYUID, resultbuf=resultbuf@entry=0x3f3e1ba160 <resbuf.9883>, buffer=buffer@entry=0x602010 "", buflen=buflen@entry=0x400, result=0x7fffffffdb38) at nscd_getpw_r.c:95
#5 0x0000003f3df34bd9 in __nscd_getpwuid_r (uid=uid@entry=0x3e8, resultbuf=resultbuf@entry=0x3f3e1ba160 <resbuf.9883>, buffer=buffer@entry=0x602010 "", buflen=buflen@entry=0x400, result=result@entry=0x7fffffffdb38) at nscd_getpw_r.c:63
#6 0x0000003f3dec3610 in __getpwuid_r (uid=uid@entry=0x3e8, resbuf=resbuf@entry=0x3f3e1ba160 <resbuf.9883>, buffer=0x602010 "", buflen=buflen@entry=0x400, result=result@entry=0x7fffffffdb38) at ../nss/getXXbyYY_r.c:196
#7 0x0000003f3dec2ebe in getpwuid (uid=0x3e8) at ../nss/getXXbyYY.c:116
#8 0x0000000000400559 in main () at test.c:1
[0:13:04][/tmp/nss]$ cat /etc/nsswitch.conf
#
# /etc/nsswitch.conf
#
# An example Name Service Switch config file. This file should be
# sorted with the most-used services at the beginning.
#
# The entry '[NOTFOUND=return]' means that the search for an
# entry should stop if the search in the previous entry turned
# up nothing. Note that if the search failed due to some other reason
# (like no NIS server responding) then the search continues with the
# next entry.
#
# Valid entries include:
#
# nisplus Use NIS+ (NIS version 3)
# nis Use NIS (NIS version 2), also called YP
# dns Use DNS (Domain Name Service)
# files Use the local files
# db Use the local database (.db) files
# compat Use NIS on compat mode
# hesiod Use Hesiod for user lookups
# [NOTFOUND=return] Stop searching if not found so far
#
# To use db, put the "db" in front of "files" for entries you want to be
# looked up first in the databases
#
# Example:
#passwd: db files nisplus nis
#shadow: db files nisplus nis
#group: db files nisplus nis
passwd: files
shadow: files
group: files
#initgroups: files
#hosts: db files nisplus nis dns
hosts: files dns mdns4_minimal myhostname
# Example - obey only what nisplus tells us...
#services: nisplus [NOTFOUND=return] files
#networks: nisplus [NOTFOUND=return] files
#protocols: nisplus [NOTFOUND=return] files
#rpc: nisplus [NOTFOUND=return] files
#ethers: nisplus [NOTFOUND=return] files
#netmasks: nisplus [NOTFOUND=return] files
bootparams: nisplus [NOTFOUND=return] files
ethers: files
netmasks: files
networks: files
protocols: files
rpc: files
services: files
netgroup: files
publickey: nisplus
automount: files
aliases: files nisplus
为什么在 /etc/passwd
上进行简单查找就可以在此处调用 connect
?
nscd
就是"name service cache daemon"。客户端通过套接字连接到它(使用堆栈跟踪中的 nscd*
函数),它缓存名称查找结果。将所有工作卸载到这个守护进程中而不是在每个客户端中使用特殊外壳是有意义的。
在 Fedora 21 上考虑以下 Linux 命令:
[0:12:57][/tmp/nss]$ echo 'main() { getpwuid(1000); }' > test.c
[0:12:59][/tmp/nss]$ gcc -ggdb test.c
[0:13:01][/tmp/nss]$ gdb ./a.out -ex 'break main' -ex 'r' -ex 'break connect' -ex 'c' -ex 'bt' -ex 'quit'
GNU gdb (GDB) Fedora 7.8.2-38.fc21
Copyright (C) 2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
warning: ~/.gdbinit.local: No such file or directory
Reading symbols from ./a.out...done.
Breakpoint 1 at 0x40054a: file test.c, line 1.
Starting program: /tmp/nss/a.out
-----------------------------------------------------------------------------------------------------------------------[regs]
RAX: 0x0000000000400546 RBX: 0x0000000000000000 RBP: 0x00007FFFFFFFDB70 RSP: 0x00007FFFFFFFDB70 o d I t s Z a P c
RDI: 0x0000000000000001 RSI: 0x00007FFFFFFFDC58 RDX: 0x00007FFFFFFFDC68 RCX: 0x0000000000400560 RIP: 0x000000000040054A
R8 : 0x0000003F3E1B8E80 R9 : 0x0000003F3E1B8E80 R10: 0x0000003F3E1B76A0 R11: 0x0000003F3DE1FEF0 R12: 0x0000000000400450
R13: 0x00007FFFFFFFDC50 R14: 0x0000000000000000 R15: 0x0000000000000000
CS: 0033 DS: 0000 ES: 0000 FS: 0000 GS: 0000 SS: 002B
-----------------------------------------------------------------------------------------------------------------------[code]
=> 0x40054a <main+4>: mov edi,0x3e8
0x40054f <main+9>: mov eax,0x0
0x400554 <main+14>: call 0x400420 <getpwuid@plt>
0x400559 <main+19>: pop rbp
0x40055a <main+20>: ret
0x40055b: nop DWORD PTR [rax+rax*1+0x0]
0x400560 <__libc_csu_init>: push r15
0x400562 <__libc_csu_init+2>: push r14
-----------------------------------------------------------------------------------------------------------------------------
Breakpoint 1, main () at test.c:1
1 main() { getpwuid(1000); }
Breakpoint 2 at 0x3f3df00f70: file ../sysdeps/unix/syscall-template.S, line 81.
Continuing.
-----------------------------------------------------------------------------------------------------------------------[regs]
RAX: 0x0000000000000020 RBX: 0x0000000000000003 RBP: 0x00007FFFFFFFD790 RSP: 0x00007FFFFFFFD688 o d I t s z a p C
RDI: 0x0000000000000003 RSI: 0x00007FFFFFFFD6F0 RDX: 0x000000000000006E RCX: 0x6F732F6463736E2F RIP: 0x0000003F3DF00F70
R8 : 0x00001FFFFFFFF5A4 R9 : 0x0000000000000001 R10: 0x0000000000000000 R11: 0x0000000000000202 R12: 0x0000000000000013
R13: 0x00007FFFFFFFD690 R14: 0x0000000000000007 R15: 0x00001FFFFFFFF5A4
CS: 0033 DS: 0000 ES: 0000 FS: 0000 GS: 0000 SS: 002B
-----------------------------------------------------------------------------------------------------------------------[code]
=> 0x3f3df00f70 <connect>: cmp DWORD PTR [rip+0x2bbd7d],0x0 # 0x3f3e1bccf4 <__libc_multiple_threads>
0x3f3df00f77 <connect+7>: jne 0x3f3df00f89 <connect+25>
0x3f3df00f79 <__connect_nocancel>: mov eax,0x2a
0x3f3df00f7e <__connect_nocancel+5>: syscall
0x3f3df00f80 <__connect_nocancel+7>: cmp rax,0xfffffffffffff001
0x3f3df00f86 <__connect_nocancel+13>: jae 0x3f3df00fb9 <connect+73>
0x3f3df00f88 <__connect_nocancel+15>: ret
0x3f3df00f89 <connect+25>: sub rsp,0x8
-----------------------------------------------------------------------------------------------------------------------------
Breakpoint 2, connect () at ../sysdeps/unix/syscall-template.S:81
81 T_PSEUDO (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS)
#0 connect () at ../sysdeps/unix/syscall-template.S:81
#1 0x0000003f3df37663 in open_socket (type=type@entry=GETFDPW, key=key@entry=0x3f3df86853 "passwd", keylen=keylen@entry=0x7) at nscd_helper.c:207
#2 0x0000003f3df37d1d in __nscd_get_mapping (type=type@entry=GETFDPW, key=key@entry=0x3f3df86853 "passwd", mappedp=mappedp@entry=0x3f3e1bc618 <map_handle+8>) at nscd_helper.c:293
#3 0x0000003f3df38277 in __nscd_get_map_ref (type=type@entry=GETFDPW, name=name@entry=0x3f3df86853 "passwd", mapptr=mapptr@entry=0x3f3e1bc610 <map_handle>, gc_cyclep=gc_cyclep@entry=0x7fffffffd9fc) at nscd_helper.c:443
#4 0x0000003f3df34758 in nscd_getpw_r (key=0x7fffffffda87 "1000", keylen=keylen@entry=0x5, type=type@entry=GETPWBYUID, resultbuf=resultbuf@entry=0x3f3e1ba160 <resbuf.9883>, buffer=buffer@entry=0x602010 "", buflen=buflen@entry=0x400, result=0x7fffffffdb38) at nscd_getpw_r.c:95
#5 0x0000003f3df34bd9 in __nscd_getpwuid_r (uid=uid@entry=0x3e8, resultbuf=resultbuf@entry=0x3f3e1ba160 <resbuf.9883>, buffer=buffer@entry=0x602010 "", buflen=buflen@entry=0x400, result=result@entry=0x7fffffffdb38) at nscd_getpw_r.c:63
#6 0x0000003f3dec3610 in __getpwuid_r (uid=uid@entry=0x3e8, resbuf=resbuf@entry=0x3f3e1ba160 <resbuf.9883>, buffer=0x602010 "", buflen=buflen@entry=0x400, result=result@entry=0x7fffffffdb38) at ../nss/getXXbyYY_r.c:196
#7 0x0000003f3dec2ebe in getpwuid (uid=0x3e8) at ../nss/getXXbyYY.c:116
#8 0x0000000000400559 in main () at test.c:1
[0:13:04][/tmp/nss]$ cat /etc/nsswitch.conf
#
# /etc/nsswitch.conf
#
# An example Name Service Switch config file. This file should be
# sorted with the most-used services at the beginning.
#
# The entry '[NOTFOUND=return]' means that the search for an
# entry should stop if the search in the previous entry turned
# up nothing. Note that if the search failed due to some other reason
# (like no NIS server responding) then the search continues with the
# next entry.
#
# Valid entries include:
#
# nisplus Use NIS+ (NIS version 3)
# nis Use NIS (NIS version 2), also called YP
# dns Use DNS (Domain Name Service)
# files Use the local files
# db Use the local database (.db) files
# compat Use NIS on compat mode
# hesiod Use Hesiod for user lookups
# [NOTFOUND=return] Stop searching if not found so far
#
# To use db, put the "db" in front of "files" for entries you want to be
# looked up first in the databases
#
# Example:
#passwd: db files nisplus nis
#shadow: db files nisplus nis
#group: db files nisplus nis
passwd: files
shadow: files
group: files
#initgroups: files
#hosts: db files nisplus nis dns
hosts: files dns mdns4_minimal myhostname
# Example - obey only what nisplus tells us...
#services: nisplus [NOTFOUND=return] files
#networks: nisplus [NOTFOUND=return] files
#protocols: nisplus [NOTFOUND=return] files
#rpc: nisplus [NOTFOUND=return] files
#ethers: nisplus [NOTFOUND=return] files
#netmasks: nisplus [NOTFOUND=return] files
bootparams: nisplus [NOTFOUND=return] files
ethers: files
netmasks: files
networks: files
protocols: files
rpc: files
services: files
netgroup: files
publickey: nisplus
automount: files
aliases: files nisplus
为什么在 /etc/passwd
上进行简单查找就可以在此处调用 connect
?
nscd
就是"name service cache daemon"。客户端通过套接字连接到它(使用堆栈跟踪中的 nscd*
函数),它缓存名称查找结果。将所有工作卸载到这个守护进程中而不是在每个客户端中使用特殊外壳是有意义的。