summaryrefslogtreecommitdiff
path: root/sapi
diff options
context:
space:
mode:
authorJakub Zelenka <bukka@php.net>2020-03-29 20:21:24 +0100
committerJakub Zelenka <bukka@php.net>2020-03-29 20:21:24 +0100
commit477efe935bf120255b9e034d934b81f7e75a075f (patch)
tree53520b65f431aec1bb636d2ae3842d7a610f80c2 /sapi
parent5fa17fbf94fa95705922313ac0d19e38ddabbad9 (diff)
parent0b4e80b8c1462a17ab758e600e2a5ddb39d80c06 (diff)
downloadphp-git-477efe935bf120255b9e034d934b81f7e75a075f.tar.gz
Merge branch 'PHP-7.4'
Diffstat (limited to 'sapi')
-rw-r--r--sapi/fpm/fpm/fpm_unix.c36
-rw-r--r--sapi/fpm/tests/socket-uds-numeric-ugid-nonroot.phpt62
-rw-r--r--sapi/fpm/tests/socket-uds-numeric-ugid.phpt58
-rw-r--r--sapi/fpm/tests/tester.inc56
-rw-r--r--sapi/fpm/www.conf.in3
5 files changed, 200 insertions, 15 deletions
diff --git a/sapi/fpm/fpm/fpm_unix.c b/sapi/fpm/fpm/fpm_unix.c
index 6490a7b5ba..1c28b1aa09 100644
--- a/sapi/fpm/fpm/fpm_unix.c
+++ b/sapi/fpm/fpm/fpm_unix.c
@@ -163,27 +163,35 @@ int fpm_unix_resolve_socket_premissions(struct fpm_worker_pool_s *wp) /* {{{ */
#endif
if (c->listen_owner && *c->listen_owner) {
- struct passwd *pwd;
+ if (strlen(c->listen_owner) == strspn(c->listen_owner, "0123456789")) {
+ wp->socket_uid = strtoul(c->listen_owner, 0, 10);
+ } else {
+ struct passwd *pwd;
- pwd = getpwnam(c->listen_owner);
- if (!pwd) {
- zlog(ZLOG_SYSERROR, "[pool %s] cannot get uid for user '%s'", wp->config->name, c->listen_owner);
- return -1;
- }
+ pwd = getpwnam(c->listen_owner);
+ if (!pwd) {
+ zlog(ZLOG_SYSERROR, "[pool %s] cannot get uid for user '%s'", wp->config->name, c->listen_owner);
+ return -1;
+ }
- wp->socket_uid = pwd->pw_uid;
- wp->socket_gid = pwd->pw_gid;
+ wp->socket_uid = pwd->pw_uid;
+ wp->socket_gid = pwd->pw_gid;
+ }
}
if (c->listen_group && *c->listen_group) {
- struct group *grp;
+ if (strlen(c->listen_group) == strspn(c->listen_group, "0123456789")) {
+ wp->socket_gid = strtoul(c->listen_group, 0, 10);
+ } else {
+ struct group *grp;
- grp = getgrnam(c->listen_group);
- if (!grp) {
- zlog(ZLOG_SYSERROR, "[pool %s] cannot get gid for group '%s'", wp->config->name, c->listen_group);
- return -1;
+ grp = getgrnam(c->listen_group);
+ if (!grp) {
+ zlog(ZLOG_SYSERROR, "[pool %s] cannot get gid for group '%s'", wp->config->name, c->listen_group);
+ return -1;
+ }
+ wp->socket_gid = grp->gr_gid;
}
- wp->socket_gid = grp->gr_gid;
}
return 0;
diff --git a/sapi/fpm/tests/socket-uds-numeric-ugid-nonroot.phpt b/sapi/fpm/tests/socket-uds-numeric-ugid-nonroot.phpt
new file mode 100644
index 0000000000..a4d352123c
--- /dev/null
+++ b/sapi/fpm/tests/socket-uds-numeric-ugid-nonroot.phpt
@@ -0,0 +1,62 @@
+--TEST--
+FPM: UNIX socket owner and group settings can be numeric
+--SKIPIF--
+<?php
+include "skipif.inc";
+FPM\Tester::skipIfPosixNotLoaded();
+?>
+--FILE--
+<?php
+
+require_once "tester.inc";
+
+$cfg = <<<EOT
+[global]
+error_log = {{FILE:LOG}}
+[unconfined]
+listen = {{ADDR:UDS}}
+listen.owner = {{UID}}
+listen.group = {{GID}}
+user = {{USER}}
+ping.path = /ping
+ping.response = pong
+pm = dynamic
+pm.max_children = 5
+pm.start_servers = 2
+pm.min_spare_servers = 1
+pm.max_spare_servers = 3
+EOT;
+
+$tester = new FPM\Tester($cfg);
+$tester->testConfig();
+$tester->start();
+$tester->expectLogNotice(
+ "'user' directive is ignored when FPM is not running as root",
+ 'unconfined'
+);
+$tester->expectLogStartNotices();
+$tester->ping('{{ADDR:UDS}}');
+$st = stat($tester->getListen('{{ADDR:UDS}}'));
+if ($st) {
+ $pw = posix_getpwuid($st['uid']);
+ $gr = posix_getgrgid($st['gid']);
+ $user = $pw ? $pw['name'] : 'UNKNOWN';
+ $group = $gr ? $gr['name'] : 'UNKNOWN';
+ echo "{$st['uid']}/{$user},{$st['gid']}/{$group}\n";
+} else {
+ echo "stat failed for " . $tester->getListen('{{ADDR:UDS}}');
+}
+$tester->terminate();
+$tester->expectLogTerminatingNotices();
+$tester->close();
+
+?>
+Done
+--EXPECTF--
+%d/%s,%d/%s
+Done
+--CLEAN--
+<?php
+require_once "tester.inc";
+FPM\Tester::clean();
+?>
diff --git a/sapi/fpm/tests/socket-uds-numeric-ugid.phpt b/sapi/fpm/tests/socket-uds-numeric-ugid.phpt
new file mode 100644
index 0000000000..d97ab2fc3f
--- /dev/null
+++ b/sapi/fpm/tests/socket-uds-numeric-ugid.phpt
@@ -0,0 +1,58 @@
+--TEST--
+FPM: UNIX socket owner and group settings can be numeric
+--SKIPIF--
+<?php
+include "skipif.inc";
+FPM\Tester::skipIfPosixNotLoaded();
+FPM\Tester::skipIfNotRoot();
+?>
+--FILE--
+<?php
+
+require_once "tester.inc";
+
+$cfg = <<<EOT
+[global]
+error_log = {{FILE:LOG}}
+[unconfined]
+listen = {{ADDR:UDS}}
+listen.owner = 1234
+listen.group = 1234
+user = 1234
+ping.path = /ping
+ping.response = pong
+pm = dynamic
+pm.max_children = 5
+pm.start_servers = 2
+pm.min_spare_servers = 1
+pm.max_spare_servers = 3
+EOT;
+
+$tester = new FPM\Tester($cfg);
+$tester->start();
+$tester->expectLogStartNotices();
+$tester->ping('{{ADDR:UDS}}');
+$st = stat($tester->getListen('{{ADDR:UDS}}'));
+if ($st) {
+ $pw = posix_getpwuid($st['uid']);
+ $gr = posix_getgrgid($st['gid']);
+ $user = $pw ? $pw['name'] : 'UNKNOWN';
+ $group = $gr ? $gr['name'] : 'UNKNOWN';
+ echo "{$st['uid']}/{$user},{$st['gid']}/{$group}\n";
+} else {
+ echo "stat failed for " . $tester->getListen('{{ADDR:UDS}}');
+}
+$tester->terminate();
+$tester->expectLogTerminatingNotices();
+$tester->close();
+
+?>
+Done
+--EXPECT--
+1234/UNKNOWN,1234/UNKNOWN
+Done
+--CLEAN--
+<?php
+require_once "tester.inc";
+FPM\Tester::clean();
+?>
diff --git a/sapi/fpm/tests/tester.inc b/sapi/fpm/tests/tester.inc
index 3424898074..e553e94f15 100644
--- a/sapi/fpm/tests/tester.inc
+++ b/sapi/fpm/tests/tester.inc
@@ -269,6 +269,26 @@ class Tester
}
/**
+ * Skip if not running as root.
+ */
+ static public function skipIfNotRoot()
+ {
+ if (getmyuid() != 0) {
+ die('skip not running as root');
+ }
+ }
+
+ /**
+ * Skip if posix extension not loaded.
+ */
+ static public function skipIfPosixNotLoaded()
+ {
+ if (!extension_loaded('posix')) {
+ die('skip posix extension not loaded');
+ }
+ }
+
+ /**
* Tester constructor.
*
* @param string|array $configTemplate
@@ -666,6 +686,38 @@ class Tester
}
/**
+ * @return string
+ */
+ public function getUser()
+ {
+ return get_current_user();
+ }
+
+ /**
+ * @return string
+ */
+ public function getGroup()
+ {
+ return get_current_group();
+ }
+
+ /**
+ * @return int
+ */
+ public function getUid()
+ {
+ return getmyuid();
+ }
+
+ /**
+ * @return int
+ */
+ public function getGid()
+ {
+ return getmygid();
+ }
+
+ /**
* Send signal to the supplied PID or the server PID.
*
* @param string $signal
@@ -761,6 +813,10 @@ class Tester
'ADDR:UDS' => ['getAddr', 'uds'],
'PORT' => ['getPort', 'ip'],
'INCLUDE:CONF' => self::CONF_DIR . '/*.conf',
+ 'USER' => ['getUser'],
+ 'GROUP' => ['getGroup'],
+ 'UID' => ['getUid'],
+ 'GID' => ['getGid'],
];
$aliases = [
'ADDR' => 'ADDR:IPv4',
diff --git a/sapi/fpm/www.conf.in b/sapi/fpm/www.conf.in
index 815618c65d..0bb4008ae1 100644
--- a/sapi/fpm/www.conf.in
+++ b/sapi/fpm/www.conf.in
@@ -41,7 +41,8 @@ listen = 127.0.0.1:9000
; Set permissions for unix socket, if one is used. In Linux, read/write
; permissions must be set in order to allow connections from a web server. Many
-; BSD-derived systems allow connections regardless of permissions.
+; BSD-derived systems allow connections regardless of permissions. The owner
+; and group can be specified either by name or by their numeric IDs.
; Default Values: user and group are set as the running user
; mode is set to 0660
;listen.owner = @php_fpm_user@