From 1c9d817a99834e84fac3157e5df6f39bcb161a4d Mon Sep 17 00:00:00 2001
From: Alexander Turenko <alexander.turenko@tarantool.org>
Date: Fri, 23 Aug 2019 02:58:28 +0300
Subject: [PATCH] lua: pwd: fix passwd and group traversal

CentOS 6 and FreeBSD 12 implementations of getpwuid() rewind
setpwent()-{getpwent()}-endpwent() loop to a start that leads to a hang
during pwd.getpwall() invoke. The same is true for a getgrgid() call
during setgrent()-{getgrent()}-endgrent() loop.

The commit modifies pwd module to avoid getpwuid() calls during passwd
database traversal and to avoid getgrgid() calls when traversing groups.

The commit also fixes the important regression on CentOS 6 after
f5d8331e833d6a29dc7a869e681e03fb8e03a5f8 ('lua: workaround
pwd.getpwall() issue on Fedora 29'): tarantool hungs during startup due
to added getpwall() call. This made tarantool unusable on CentOS 6 at
all.

Aside of that the commit fixes another pwd.getgrall() problem: the
function gaves password entries instead of group entries.

Fixes #4428.
Fixes #4447.
Part of #4271.

(cherry picked from commit 7753d350ffccad4344485bfd6b9ce66fec813bea)
---
 src/lua/pwd.lua           | 15 +++++----------
 test/app-tap/pwd.skipcond |  8 --------
 2 files changed, 5 insertions(+), 18 deletions(-)
 delete mode 100644 test/app-tap/pwd.skipcond

diff --git a/src/lua/pwd.lua b/src/lua/pwd.lua
index b6de1562f8..ab0229a724 100644
--- a/src/lua/pwd.lua
+++ b/src/lua/pwd.lua
@@ -112,7 +112,7 @@ local function getgr(gid)
     if gid == nil then
         gid = tonumber(ffi.C.getgid())
     end
-    local gr = _getgr(gid)
+    local gr = type(gid) == 'cdata' and gid or _getgr(gid)
     if gr == nil then
         if errno() ~= 0 then
             error(pwgr_errstr:format('gr', errno(), errno.strerror()))
@@ -141,7 +141,7 @@ local function getpw(uid)
     if uid == nil then
         uid = tonumber(ffi.C.getuid())
     end
-    local pw = _getpw(uid)
+    local pw = type(uid) == 'cdata' and uid or _getpw(uid)
     if pw == nil then
         if errno() ~= 0 then
             error(pwgr_errstr:format('pw', errno(), errno.strerror()))
@@ -170,7 +170,7 @@ local function getpwall()
             end
             break
         end
-        table.insert(pws, getpw(pw.pw_uid))
+        table.insert(pws, getpw(pw))
     end
     ffi.C.endpwent()
     return pws
@@ -188,7 +188,7 @@ local function getgrall()
             end
             break
         end
-        table.insert(grs, getpw(gr.gr_gid))
+        table.insert(grs, getgr(gr))
     end
     ffi.C.endgrent()
     return grs
@@ -200,12 +200,7 @@ end
 -- password database is traversed first time.
 --
 -- [1]: https://github.com/systemd/systemd/issues/9585
---
--- It is disabled on FreeBSD due to gh-4428: getpwall() hangs on
--- FreeBSD 12.
-if jit.os ~= 'BSD' then
-    pcall(getpwall)
-end
+pcall(getpwall)
 
 return {
     getpw = getpw,
diff --git a/test/app-tap/pwd.skipcond b/test/app-tap/pwd.skipcond
deleted file mode 100644
index 7950a5d93b..0000000000
--- a/test/app-tap/pwd.skipcond
+++ /dev/null
@@ -1,8 +0,0 @@
-import platform
-
-# Disabled on FreeBSD due to fail #4271:
-#   Data segment size exceeds process limit
-if platform.system() == 'FreeBSD':
-    self.skip = 1
-
-# vim: set ft=python:
-- 
GitLab