From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-lf1-f68.google.com (mail-lf1-f68.google.com [209.85.167.68]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by dev.tarantool.org (Postfix) with ESMTPS id 1DC0544643B for ; Thu, 17 Sep 2020 16:52:02 +0300 (MSK) Received: by mail-lf1-f68.google.com with SMTP id y17so2263634lfa.8 for ; Thu, 17 Sep 2020 06:52:02 -0700 (PDT) From: Cyrill Gorcunov Date: Thu, 17 Sep 2020 16:51:21 +0300 Message-Id: <20200917135121.60380-4-gorcunov@gmail.com> In-Reply-To: <20200917135121.60380-1-gorcunov@gmail.com> References: <20200917135121.60380-1-gorcunov@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Subject: [Tarantool-patches] [PATCH 3/3] lua/pwd: workaround the systemd bug List-Id: Tarantool development patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: tml Cc: Alexander Turenko 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 | 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 --- 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