Skip to content

Allow numeric [UG]ID in FPM listen.{owner,group} - #5148

Closed
andrenth wants to merge 1 commit into
php:masterfrom
andrenth:numeric-fpm-socket-owner-and-group
Closed

andrenth wants to merge 1 commit into
php:masterfrom
andrenth:numeric-fpm-socket-owner-and-group

Conversation

@andrenth

@andrenth andrenth commented Feb 4, 2020

Copy link
Copy Markdown
Contributor

This patch allows FPM pool configuration settings listen.owner and listen.group to accept numeric IDs as well as user and group names. This makes them mirror the behavior of the user and group settings.

This feature was requested on bug #77062 in the bug tracker

@andrenth

Copy link
Copy Markdown
Contributor Author

So, there were CI failures but they seem unrelated to the PR.

This patch is useful for users with remote user databases (e.g. LDAP), where there's an inherent race between user creation and FPM pool creation. When the pool is created before the user has been created, FPM dies on reload due to the nonexistent user, taking down all pools. Accepting numeric IDs would prevent this from happening.

@nikic

nikic commented Feb 21, 2020

Copy link
Copy Markdown
Member

Looks fine to me, but let's let @bukka have a look as well.

@nikic nikic added the Feature label Feb 21, 2020

@bukka bukka left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that it makes sense in general.

It might be also possible to add some basic tests. It will be probably reliable only for the current user and some non existent user for errors. That should be enough to verify that uid and gid is accepted.

Comment thread sapi/fpm/fpm/fpm_unix.c Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please verify that the uid exists using getpwuid and fail if it doesn't.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The motivation for this patch is to allow the code to work even when UID and GID don't correspond to a valid used (yet). The use case is for situations where creating the user might take longer than creating the pool when using remote authentication, like when using LDAP, and using the numeric IDs would allow FPM to successfully be reloaded when the pool is created, even if the user does not yet exist.

The patch mirrors the code for the user and group settings, which also do not fail if the IDs are not found.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok that makes sense.

Comment thread sapi/fpm/fpm/fpm_unix.c Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please verify that the gid exists using getgrgid and fail if it doesn't.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please see my comment w.r.t listen_owner above.

@bukka

bukka commented Mar 1, 2020

Copy link
Copy Markdown
Member

So the only missing bit is a test. Otherwise it looks good.

@andrenth

andrenth commented Mar 2, 2020

Copy link
Copy Markdown
Contributor Author

I've added a simple test file.

@andrenth

andrenth commented Mar 2, 2020 •

Copy link
Copy Markdown
Contributor Author

I believe the tests failed because they're not run as root. Is there a way to skip a test case unless it's running as root?

Edit: I've added a commit for that, thought I'm not sure it's the best way.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just tested this to run under root and it actually fails to start for me. Might be my local issue but was wondering if the test actually works for you when you run it under root?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Btw for me this line fails if run under root even with setting TEST_FPM_RUN_AS_ROOT=1:

$this->masterProcess = proc_open($cmd, $desc, $pipes);

Interestingly I tested starting that with passthru and it actually starts FPM so something weird with proc_open. Might need to debug it.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does work for me:

$ sudo -i
# cd /home/andre/git/forks/php-src
# TEST_FPM_RUN_AS_ROOT=1 ./sapi/cli/php run-tests.php sapi/fpm/tests/socket-uds-numeric-user-and-group-id.phpt

=====================================================================
PHP         : /home/andre/git/forks/php-src/sapi/cli/php 
PHP_SAPI    : cli
PHP_VERSION : 8.0.0-dev
ZEND_VERSION: 4.0.0-dev
PHP_OS      : Linux - Linux andre 4.15.0-88-generic #88-Ubuntu SMP Tue Feb 11 20:11:34 UTC 2020 x86_64
INI actual  : /home/andre/git/forks/php-src
More .INIs  :   
---------------------------------------------------------------------
PHP         : /home/andre/git/forks/php-src/sapi/phpdbg/phpdbg 
PHP_SAPI    : phpdbg
PHP_VERSION : 8.0.0-dev
ZEND_VERSION: 4.0.0-dev
PHP_OS      : Linux - Linux andre 4.15.0-88-generic #88-Ubuntu SMP Tue Feb 11 20:11:34 UTC 2020 x86_64
INI actual  : /home/andre/git/forks/php-src
More .INIs  : 
---------------------------------------------------------------------
CWD         : /home/andre/git/forks/php-src
Extra dirs  : 
VALGRIND    : Not used
=====================================================================
Running selected tests.
PASS FPM: UNIX socket owner and group settings can be numeric [sapi/fpm/tests/socket-uds-numeric-user-and-group-id.phpt] 
=====================================================================
Number of tests :    1                 1
Tests skipped   :    0 (  0.0%) --------
Tests warned    :    0 (  0.0%) (  0.0%)
Tests failed    :    0 (  0.0%) (  0.0%)
Tests passed    :    1 (100.0%) (100.0%)
---------------------------------------------------------------------
Time taken      :    0 seconds
=====================================================================

The test calls the stat command to check the owner and group of the created sockets. Could it be a PATH issue, or maybe your environment doesn't have this command?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably something local then. Don't worry about it then!

Comment thread sapi/fpm/tests/tester.inc Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't seem correct as it's just for the actual script owner but we should care about the EUID so it should be more something like this:

        if (
            (extension_loaded('posix_geteuid') && posix_geteuid() !== 0) ||
            (exec('id -u', $output, $rv) !== "0")
        ) {
            die('skip not running as root');
        }

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I didn't know that's what getmyuid did. However the test still works as intended because when the test is run as root, the PHP script generated from the phpt file will be owned by root, and so getmyuid will return 0.

I can add a commit to replace the test as you suggested, but in skipif.inc there's a similar check that also uses getmyuid:

// Running as root is not allowed without TEST_FPM_RUN_AS_ROOT env
if (!getmyuid() && !getenv('TEST_FPM_RUN_AS_ROOT')) {
    die('skip Refusing to run as root');
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah yeah it should be enough then. I sometimes test things just by running php on the phpt file (without the framework) so that's why it didn't work for me but that's not requirement for the test to work so feel free to leave it as it is.

@bukka

bukka commented Mar 8, 2020

Copy link
Copy Markdown
Member

That root test looks like a good idea and it would be also good to have root tests for other things so well done on starting that! The only thing about those tests is that we won't be currently able to run them in CI. I think it would be idea to also have a test that we can run in CI. It could be basically the same as the current one, just it would use posix_geteuid return value in the config. It will at least test that numbers are accepted and should hopefully work. It will probably also require skip if posix extension is not loaded.

@andrenth

andrenth commented Mar 8, 2020 •

Copy link
Copy Markdown
Contributor Author

I've added a test that works as you suggested. I couldn't find a way to use PHP code or template variables in the EXPECT section of the test, so I went with EXPECTF.

@andrenth

andrenth commented Mar 9, 2020

Copy link
Copy Markdown
Contributor Author

So, the test does work locally, but it's failing in the CI environment:

ERROR: [pool unconfined] failed to chown() the socket '/home/vsts/work/1/s/sapi/fpm/tests/socket-uds-numeric-user-and-group-id-nonroot.9004.sock': Operation not permitted (1)

I don't know enough about the CI environment to understand why this happens. Do the tests run as a different user than the one who owns the test files?

@bukka

bukka commented Mar 11, 2020

Copy link
Copy Markdown
Member

it might be that Azure pipeline might be using seccomp or something maybe. Might make sense to skip just in there maybe as it works in Travis.

@nikic is it possible to skip Azure pipelines easily?

Comment thread sapi/fpm/tests/tester.inc Resolved
@nikic

nikic commented Mar 11, 2020

Copy link
Copy Markdown
Member

Looks like that did it. There's still a failure on macos though

fsockopen(): socket path exceeded the maximum allowed length of 104 bytes and was truncated in /Users/runner/runners/2.165.0/work/1/s/sapi/fpm/tests/fcgi.inc on line 280

@andrenth

Copy link
Copy Markdown
Contributor Author

I think renaming the test files to something shorter will fix that.

@bukka

bukka commented Mar 15, 2020

Copy link
Copy Markdown
Member

@andrenth It all looks good, just one small thing. Please can you update www.conf.in to somehow state that uid and gid are supported. Currently the description in there (

; 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.
) is a bit vague so it might be worth to extend it a little a bit or maybe just adding a note about what is accepted.

@andrenth

Copy link
Copy Markdown
Contributor Author

I've added a short note that those settings accept either names or numeric IDs. If you'd like me to extend the explanation a bit more, let me know.

@bukka

bukka commented Mar 15, 2020

Copy link
Copy Markdown
Member

Yeah I think it's good enough. Can you please squash all your commits and push force it?

@andrenth
andrenth force-pushed the numeric-fpm-socket-owner-and-group branch from 64d0e8a to ac56ce1 Compare March 15, 2020 20:01
@andrenth

Copy link
Copy Markdown
Contributor Author

Done.

@bukka

bukka commented Mar 29, 2020

Copy link
Copy Markdown
Member

Merged to 7.4 as 0b4e80b

@bukka bukka closed this Mar 29, 2020
@andrenth

Copy link
Copy Markdown
Contributor Author

Thank you!

@hakuno

hakuno commented Apr 16, 2020

Copy link
Copy Markdown

Nice patch!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants