[Tarantool-patches] [PATCH 3/3] lua/pwd: workaround the systemd bug
Cyrill Gorcunov
gorcunov at gmail.com
Thu Sep 17 16:51:21 MSK 2020
There is a bug in systemd-209 source code: it returns
ENOENT when no more entries in a password database left.
Later the issue been fixed but we still meet the systems
where it hits. The problem affects getpwent/getgrent calls
only thus we can expect them to return the buggy error code
to skip.
Notes:
1) See systemd's commit where issue been fixed
| commit 06202b9e659e5cc72aeecc5200155b7c012fccbc
| Author: Yu Watanabe <watanabe.yu+github at gmail.com>
| Date: Sun Jul 15 23:00:00 2018 +0900
|
| nss: do not modify errno when NSS_STATUS_NOTFOUND or NSS_STATUS_SUCCESS
2) Another option is to call getpwall on Tarantool startup
unconditionally where we could simply ignore any errors. This
is a very bad choise since traversig a password database might
introduce significant lags if backend does some network activiy
or have expired caches. Thus drop getpwall() unconditional call
run it iif a user does an explicit request.
Fixes #5034
Signed-off-by: Cyrill Gorcunov <gorcunov at gmail.com>
---
src/lua/pwd.lua | 52 +++++++++++++++++++++++++++++++++++++------------
1 file changed, 40 insertions(+), 12 deletions(-)
diff --git a/src/lua/pwd.lua b/src/lua/pwd.lua
index 31cfbd8bf..907eb5a8e 100644
--- a/src/lua/pwd.lua
+++ b/src/lua/pwd.lua
@@ -196,6 +196,44 @@ local function getpw(uid)
return pwtotable(pw, gr)
end
+--
+-- systemd v209 sets errno is set to ENOENT in
+-- _nss_systemd_getpwent_r and _nss_systemd_getgrent_r
+-- when there are no more entries to enumerate.
+--
+-- This is a bug which has been fixed later in
+-- systemd code but we have to deal with buggy
+-- systems thus ignore such error if appears.
+--
+-- See the reference for details
+-- https://github.com/systemd/systemd/issues/9585
+--
+-- This issue affects getpwent/getgrent calls only
+-- thus provide own wrappings to keep workaround
+-- in one place and do not affect any other calls
+-- where ENOENT might become a valid error case.
+--
+-- Initially we observed this issue on Fedora 29
+-- when a password database is traversed for the
+-- first time.
+local function getpwent()
+ errno(0)
+ local pw = ffi.C.getpwent()
+ if pw == nil and errno() == errno.ENOENT then
+ errno(0)
+ end
+ return pw
+end
+
+local function getgrent()
+ errno(0)
+ local gr = ffi.C.getgrent()
+ if gr == nil and errno() == errno.ENOENT then
+ errno(0)
+ end
+ return gr
+end
+
local function getpwall()
ffi.C.setpwent()
local pws = {}
@@ -203,8 +241,7 @@ local function getpwall()
-- of a getpwent() current entry to a first one on CentOS 6
-- and FreeBSD 12.
while true do
- errno(0)
- local pw = ffi.C.getpwent()
+ local pw = getpwent()
if pw == nil then
pwgrcheck('getpwall', pw)
break
@@ -223,8 +260,7 @@ local function getgrall()
-- of a getgrent() current entry to a first one on CentOS 6
-- and FreeBSD 12.
while true do
- errno(0)
- local gr = ffi.C.getgrent()
+ local gr = getgrent()
if gr == nil then
pwgrcheck('getgrall', gr)
break
@@ -237,14 +273,6 @@ end
-- }}}
--- Workaround pwd.getpwall() issue on Fedora 29: successful
--- getgrent() call that should normally return NULL and preserve
--- errno, set it to ENOENT due to systemd-nss issue [1] when a
--- password database is traversed first time.
---
--- [1]: https://github.com/systemd/systemd/issues/9585
-pcall(getpwall)
-
return {
getpw = getpw,
getgr = getgr,
--
2.26.2
More information about the Tarantool-patches
mailing list