mirror of
git://sourceware.org/git/glibc.git
synced 2024-11-21 01:12:26 +08:00
03d2730b44
Robin Hack discovered Samba would enter an infinite loop processing certain quota-related requests. We eventually tracked this down to a glibc issue. Running a (simplified) test case under strace shows that /etc/passwd is continuously opened and closed: … open("/etc/passwd", O_RDONLY|O_CLOEXEC) = 3 lseek(3, 0, SEEK_CUR) = 0 read(3, "root❌0:0:root:/root:/bin/bash\n"..., 4096) = 2717 lseek(3, 2717, SEEK_SET) = 2717 close(3) = 0 open("/etc/passwd", O_RDONLY|O_CLOEXEC) = 3 lseek(3, 0, SEEK_CUR) = 0 lseek(3, 0, SEEK_SET) = 0 read(3, "root❌0:0:root:/root:/bin/bash\n"..., 4096) = 2717 lseek(3, 2717, SEEK_SET) = 2717 close(3) = 0 open("/etc/passwd", O_RDONLY|O_CLOEXEC) = 3 lseek(3, 0, SEEK_CUR) = 0 … The lookup function implementation in nss/nss_files/files-XXX.c:DB_LOOKUP has code to prevent that. It is supposed skip closing the input file if it was already open. /* Reset file pointer to beginning or open file. */ \ status = internal_setent (keep_stream); \ \ if (status == NSS_STATUS_SUCCESS) \ { \ /* Tell getent function that we have repositioned the file pointer. */ \ last_use = getby; \ \ while ((status = internal_getent (result, buffer, buflen, errnop \ H_ERRNO_ARG EXTRA_ARGS_VALUE)) \ == NSS_STATUS_SUCCESS) \ { break_if_match } \ \ if (! keep_stream) \ internal_endent (); \ } \ keep_stream is initialized from the stayopen flag in internal_setent. internal_setent is called from the set*ent implementation as: status = internal_setent (stayopen); However, for non-host database, this flag is always 0, per the STAYOPEN magic in nss/getXXent_r.c. Thus, the fix is this: - status = internal_setent (stayopen); + status = internal_setent (1); This is not a behavioral change even for the hosts database (where the application can specify the stayopen flag) because with a call to sethostent(0), the file handle is still not closed in the implementation of gethostent. |
||
---|---|---|
.. | ||
nss_db | ||
nss_files | ||
alias-lookup.c | ||
bug-erange.c | ||
databases.def | ||
db-Makefile | ||
Depend | ||
digits_dots.c | ||
ethers-lookup.c | ||
function.def | ||
getent.c | ||
getnssent_r.c | ||
getnssent.c | ||
getXXbyYY_r.c | ||
getXXbyYY.c | ||
getXXent_r.c | ||
getXXent.c | ||
grp-lookup.c | ||
hosts-lookup.c | ||
key-lookup.c | ||
makedb.c | ||
Makefile | ||
netgrp-lookup.c | ||
network-lookup.c | ||
nss_test1.c | ||
nss.h | ||
nsswitch.c | ||
nsswitch.conf | ||
nsswitch.h | ||
proto-lookup.c | ||
pwd-lookup.c | ||
rpc-lookup.c | ||
service-lookup.c | ||
sgrp-lookup.c | ||
spwd-lookup.c | ||
test-digits-dots.c | ||
test-netdb.c | ||
tst-nss-getpwent.c | ||
tst-nss-static.c | ||
tst-nss-test1.c | ||
Versions | ||
XXX-lookup.c |