From 75548207631eeaf679c60c5b11c72669d20774cd Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Mon, 21 Nov 2022 21:03:44 +0000 Subject: [PATCH] Fix bug #80669: FPM numeric user fails to set groups --- sapi/fpm/fpm/fpm_unix.c | 7 ++- sapi/fpm/fpm/fpm_worker_pool.c | 3 ++ sapi/fpm/fpm/fpm_worker_pool.h | 1 + sapi/fpm/tests/bug80669-uid-user-groups.phpt | 52 ++++++++++++++++++++ sapi/fpm/tests/response.inc | 10 ++-- sapi/fpm/tests/tester.inc | 15 +++++- 6 files changed, 80 insertions(+), 8 deletions(-) create mode 100644 sapi/fpm/tests/bug80669-uid-user-groups.phpt diff --git a/sapi/fpm/fpm/fpm_unix.c b/sapi/fpm/fpm/fpm_unix.c index ed5b66294fb0e..3349499fada2f 100644 --- a/sapi/fpm/fpm/fpm_unix.c +++ b/sapi/fpm/fpm/fpm_unix.c @@ -269,6 +269,11 @@ static int fpm_unix_conf_wp(struct fpm_worker_pool_s *wp) /* {{{ */ if (wp->config->user && *wp->config->user) { if (strlen(wp->config->user) == strspn(wp->config->user, "0123456789")) { wp->set_uid = strtoul(wp->config->user, 0, 10); + pwd = getpwuid(wp->set_uid); + if (pwd) { + wp->set_gid = pwd->pw_gid; + wp->set_user = strdup(pwd->pw_name); + } } else { struct passwd *pwd; @@ -392,7 +397,7 @@ int fpm_unix_init_child(struct fpm_worker_pool_s *wp) /* {{{ */ } } if (wp->set_uid) { - if (0 > initgroups(wp->config->user, wp->set_gid)) { + if (0 > initgroups(wp->set_user ? wp->set_user : wp->config->user, wp->set_gid)) { zlog(ZLOG_SYSERROR, "[pool %s] failed to initgroups(%s, %d)", wp->config->name, wp->config->user, wp->set_gid); return -1; } diff --git a/sapi/fpm/fpm/fpm_worker_pool.c b/sapi/fpm/fpm/fpm_worker_pool.c index 974238de296d4..6016b5867f5c6 100644 --- a/sapi/fpm/fpm/fpm_worker_pool.c +++ b/sapi/fpm/fpm/fpm_worker_pool.c @@ -34,6 +34,9 @@ void fpm_worker_pool_free(struct fpm_worker_pool_s *wp) /* {{{ */ if (wp->user) { free(wp->user); } + if (wp->set_user) { + free(wp->set_user); + } if (wp->home) { free(wp->home); } diff --git a/sapi/fpm/fpm/fpm_worker_pool.h b/sapi/fpm/fpm/fpm_worker_pool.h index 809f53a0545b5..efb8640cd32f0 100644 --- a/sapi/fpm/fpm/fpm_worker_pool.h +++ b/sapi/fpm/fpm/fpm_worker_pool.h @@ -24,6 +24,7 @@ struct fpm_worker_pool_s { enum fpm_address_domain listen_address_domain; int listening_socket; int set_uid, set_gid; /* config uid and gid */ + char *set_user; /* config user name */ int socket_uid, socket_gid, socket_mode; /* runtime */ diff --git a/sapi/fpm/tests/bug80669-uid-user-groups.phpt b/sapi/fpm/tests/bug80669-uid-user-groups.phpt new file mode 100644 index 0000000000000..9a69473004778 --- /dev/null +++ b/sapi/fpm/tests/bug80669-uid-user-groups.phpt @@ -0,0 +1,52 @@ +--TEST-- +FPM: Process user setting ignored when FPM is not running as root +--SKIPIF-- + +--FILE-- +start(); +$tester->expectLogStartNotices(); +$tester->request()->expectBody((string) $gid); +$tester->terminate(); +$tester->expectLogTerminatingNotices(); +$tester->close(); + +?> +Done +--EXPECT-- +Done +--CLEAN-- + diff --git a/sapi/fpm/tests/response.inc b/sapi/fpm/tests/response.inc index 9112da6ed7756..dd74e42990b08 100644 --- a/sapi/fpm/tests/response.inc +++ b/sapi/fpm/tests/response.inc @@ -71,11 +71,11 @@ class Response $body = implode("\n", $body); } - if ( - $this->checkIfValid() && - $this->checkDefaultHeaders($contentType) && - $body !== $this->rawBody - ) { + if (!$this->checkIfValid()) { + $this->error('Response is invalid'); + } elseif (!$this->checkDefaultHeaders($contentType)) { + $this->error('Response default headers not found'); + } elseif ($body !== $this->rawBody) { if ($multiLine) { $this->error( "==> The expected body:\n$body\n" . diff --git a/sapi/fpm/tests/tester.inc b/sapi/fpm/tests/tester.inc index ae60114f78f18..ef26bc9807d5e 100644 --- a/sapi/fpm/tests/tester.inc +++ b/sapi/fpm/tests/tester.inc @@ -294,7 +294,7 @@ class Tester */ static public function skipIfNotRoot() { - if (getmyuid() != 0) { + if (exec('whoami') !== 'root') { die('skip not running as root'); } } @@ -304,7 +304,7 @@ class Tester */ static public function skipIfRoot() { - if (getmyuid() == 0) { + if (exec('whoami') === 'root') { die('skip running as root'); } } @@ -319,6 +319,17 @@ class Tester } } + /** + * Skip if posix extension not loaded. + */ + static public function skipIfUserDoesNotExist($userName) + { + self::skipIfPosixNotLoaded(); + if (posix_getpwnam($userName) === false) { + die("skip user $userName does not exist"); + } + } + /** * Tester constructor. *