mirror of
https://github.com/php/php-src.git
synced 2025-08-16 05:58:45 +02:00
ext/pcntl: adding pcntl_setns for Linux >= 5.3
allows a given process to join an existing Linux namespace, relatively complementary to the existing pcntl_unshare. Close GH-13878
This commit is contained in:
parent
e08a5dce8f
commit
ae4978a139
8 changed files with 145 additions and 2 deletions
3
NEWS
3
NEWS
|
@ -122,6 +122,9 @@ PHP NEWS
|
||||||
. Fixed bug with url_rewriter.hosts not used by output_add_rewrite_var().
|
. Fixed bug with url_rewriter.hosts not used by output_add_rewrite_var().
|
||||||
(haszi)
|
(haszi)
|
||||||
|
|
||||||
|
- PCNTL:
|
||||||
|
. Added pcntl_setns for Linux. (David Carlier)
|
||||||
|
|
||||||
- PCRE:
|
- PCRE:
|
||||||
. Upgrade bundled pcre2lib to version 10.43. (nielsdos)
|
. Upgrade bundled pcre2lib to version 10.43. (nielsdos)
|
||||||
. Add "/r" modifier. (Ayesh)
|
. Add "/r" modifier. (Ayesh)
|
||||||
|
|
|
@ -442,6 +442,10 @@ PHP 8.4 UPGRADE NOTES
|
||||||
. If JIT is enabled, PHP will now exit with a fatal error on startup in case
|
. If JIT is enabled, PHP will now exit with a fatal error on startup in case
|
||||||
of JIT startup initialization issues.
|
of JIT startup initialization issues.
|
||||||
|
|
||||||
|
- PCNTL:
|
||||||
|
. Added pcntl_setns allowing a process to be reassociated with a namespace in order
|
||||||
|
to share resources with other processes within this context.
|
||||||
|
|
||||||
- Sodium:
|
- Sodium:
|
||||||
. Added the sodium_crypto_aead_aegis128l_*() and sodium_crypto_aead_aegis256l_*()
|
. Added the sodium_crypto_aead_aegis128l_*() and sodium_crypto_aead_aegis256l_*()
|
||||||
functions to support the AEGIS family of authenticated encryption algorithms,
|
functions to support the AEGIS family of authenticated encryption algorithms,
|
||||||
|
|
|
@ -7,7 +7,7 @@ if test "$PHP_PCNTL" != "no"; then
|
||||||
AC_CHECK_FUNCS([fork], [], [AC_MSG_ERROR([pcntl: fork() not supported by this platform])])
|
AC_CHECK_FUNCS([fork], [], [AC_MSG_ERROR([pcntl: fork() not supported by this platform])])
|
||||||
AC_CHECK_FUNCS([waitpid], [], [AC_MSG_ERROR([pcntl: waitpid() not supported by this platform])])
|
AC_CHECK_FUNCS([waitpid], [], [AC_MSG_ERROR([pcntl: waitpid() not supported by this platform])])
|
||||||
AC_CHECK_FUNCS([sigaction], [], [AC_MSG_ERROR([pcntl: sigaction() not supported by this platform])])
|
AC_CHECK_FUNCS([sigaction], [], [AC_MSG_ERROR([pcntl: sigaction() not supported by this platform])])
|
||||||
AC_CHECK_FUNCS([getpriority setpriority wait3 wait4 sigwaitinfo sigtimedwait unshare rfork forkx])
|
AC_CHECK_FUNCS([getpriority setpriority wait3 wait4 sigwaitinfo sigtimedwait unshare rfork forkx pidfd_open])
|
||||||
|
|
||||||
AC_CHECK_TYPE([siginfo_t],[PCNTL_CFLAGS="-DHAVE_STRUCT_SIGINFO_T"],,[#include <signal.h>])
|
AC_CHECK_TYPE([siginfo_t],[PCNTL_CFLAGS="-DHAVE_STRUCT_SIGINFO_T"],,[#include <signal.h>])
|
||||||
|
|
||||||
|
|
|
@ -46,6 +46,10 @@
|
||||||
#include <sched.h>
|
#include <sched.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_PIDFD_OPEN
|
||||||
|
#include <sys/syscall.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_FORKX
|
#ifdef HAVE_FORKX
|
||||||
#include <sys/fork.h>
|
#include <sys/fork.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -1402,6 +1406,76 @@ PHP_FUNCTION(pcntl_forkx)
|
||||||
#endif
|
#endif
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
|
#ifdef HAVE_PIDFD_OPEN
|
||||||
|
// The `pidfd_open` syscall is available since 5.3
|
||||||
|
// and `setns` since 3.0.
|
||||||
|
PHP_FUNCTION(pcntl_setns)
|
||||||
|
{
|
||||||
|
zend_long pid, nstype = CLONE_NEWNET;
|
||||||
|
bool pid_is_null = 1;
|
||||||
|
int fd, ret;
|
||||||
|
|
||||||
|
ZEND_PARSE_PARAMETERS_START(0, 2)
|
||||||
|
Z_PARAM_OPTIONAL
|
||||||
|
Z_PARAM_LONG_OR_NULL(pid, pid_is_null)
|
||||||
|
Z_PARAM_LONG(nstype)
|
||||||
|
ZEND_PARSE_PARAMETERS_END();
|
||||||
|
|
||||||
|
pid = pid_is_null ? getpid() : pid;
|
||||||
|
fd = syscall(SYS_pidfd_open, pid, 0);
|
||||||
|
if (errno) {
|
||||||
|
PCNTL_G(last_error) = errno;
|
||||||
|
switch (errno) {
|
||||||
|
case EINVAL:
|
||||||
|
case ESRCH:
|
||||||
|
zend_argument_value_error(1, "is not a valid process (%d)", pid);
|
||||||
|
RETURN_THROWS();
|
||||||
|
|
||||||
|
case ENFILE:
|
||||||
|
php_error_docref(NULL, E_WARNING, "Error %d: File descriptors per-process limit reached", errno);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ENODEV:
|
||||||
|
php_error_docref(NULL, E_WARNING, "Error %d: Anonymous inode fs unsupported", errno);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ENOMEM:
|
||||||
|
php_error_docref(NULL, E_WARNING, "Error %d: Insufficient memory for pidfd_open", errno);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
php_error_docref(NULL, E_WARNING, "Error %d", errno);
|
||||||
|
}
|
||||||
|
RETURN_FALSE;
|
||||||
|
}
|
||||||
|
ret = setns(fd, (int)nstype);
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
if (ret == -1) {
|
||||||
|
PCNTL_G(last_error) = errno;
|
||||||
|
switch (errno) {
|
||||||
|
case ESRCH:
|
||||||
|
zend_argument_value_error(1, "process no longer available (%d)", pid);
|
||||||
|
RETURN_THROWS();
|
||||||
|
|
||||||
|
case EINVAL:
|
||||||
|
zend_argument_value_error(2, "is an invalid nstype (%d)", nstype);
|
||||||
|
RETURN_THROWS();
|
||||||
|
|
||||||
|
case EPERM:
|
||||||
|
php_error_docref(NULL, E_WARNING, "Error %d: No required capability for this process", errno);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
php_error_docref(NULL, E_WARNING, "Error %d", errno);
|
||||||
|
}
|
||||||
|
RETURN_FALSE;
|
||||||
|
} else {
|
||||||
|
RETURN_TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void pcntl_interrupt_function(zend_execute_data *execute_data)
|
static void pcntl_interrupt_function(zend_execute_data *execute_data)
|
||||||
{
|
{
|
||||||
pcntl_signal_dispatch();
|
pcntl_signal_dispatch();
|
||||||
|
|
|
@ -990,3 +990,7 @@ function pcntl_rfork(int $flags, int $signal = 0): int{}
|
||||||
#ifdef HAVE_FORKX
|
#ifdef HAVE_FORKX
|
||||||
function pcntl_forkx(int $flags): int{}
|
function pcntl_forkx(int $flags): int{}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_PIDFD_OPEN
|
||||||
|
function pcntl_setns(int $process_id = null, int $nstype = CLONE_NEWNET): bool {}
|
||||||
|
#endif
|
||||||
|
|
15
ext/pcntl/pcntl_arginfo.h
generated
15
ext/pcntl/pcntl_arginfo.h
generated
|
@ -1,5 +1,5 @@
|
||||||
/* This is a generated file, edit the .stub.php file instead.
|
/* This is a generated file, edit the .stub.php file instead.
|
||||||
* Stub hash: 3b03373d1bb68de779baaa62db14d98ca9018339 */
|
* Stub hash: 614bd67bb4cfcdc68d37141ff9dfad0a49c318b5 */
|
||||||
|
|
||||||
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_pcntl_fork, 0, 0, IS_LONG, 0)
|
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_pcntl_fork, 0, 0, IS_LONG, 0)
|
||||||
ZEND_END_ARG_INFO()
|
ZEND_END_ARG_INFO()
|
||||||
|
@ -132,6 +132,13 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_pcntl_forkx, 0, 1, IS_LONG, 0)
|
||||||
ZEND_END_ARG_INFO()
|
ZEND_END_ARG_INFO()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(HAVE_PIDFD_OPEN)
|
||||||
|
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_pcntl_setns, 0, 0, _IS_BOOL, 0)
|
||||||
|
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, process_id, IS_LONG, 0, "null")
|
||||||
|
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, nstype, IS_LONG, 0, "CLONE_NEWNET")
|
||||||
|
ZEND_END_ARG_INFO()
|
||||||
|
#endif
|
||||||
|
|
||||||
ZEND_FUNCTION(pcntl_fork);
|
ZEND_FUNCTION(pcntl_fork);
|
||||||
ZEND_FUNCTION(pcntl_waitpid);
|
ZEND_FUNCTION(pcntl_waitpid);
|
||||||
ZEND_FUNCTION(pcntl_wait);
|
ZEND_FUNCTION(pcntl_wait);
|
||||||
|
@ -176,6 +183,9 @@ ZEND_FUNCTION(pcntl_rfork);
|
||||||
#if defined(HAVE_FORKX)
|
#if defined(HAVE_FORKX)
|
||||||
ZEND_FUNCTION(pcntl_forkx);
|
ZEND_FUNCTION(pcntl_forkx);
|
||||||
#endif
|
#endif
|
||||||
|
#if defined(HAVE_PIDFD_OPEN)
|
||||||
|
ZEND_FUNCTION(pcntl_setns);
|
||||||
|
#endif
|
||||||
|
|
||||||
static const zend_function_entry ext_functions[] = {
|
static const zend_function_entry ext_functions[] = {
|
||||||
ZEND_FE(pcntl_fork, arginfo_pcntl_fork)
|
ZEND_FE(pcntl_fork, arginfo_pcntl_fork)
|
||||||
|
@ -222,6 +232,9 @@ static const zend_function_entry ext_functions[] = {
|
||||||
#endif
|
#endif
|
||||||
#if defined(HAVE_FORKX)
|
#if defined(HAVE_FORKX)
|
||||||
ZEND_FE(pcntl_forkx, arginfo_pcntl_forkx)
|
ZEND_FE(pcntl_forkx, arginfo_pcntl_forkx)
|
||||||
|
#endif
|
||||||
|
#if defined(HAVE_PIDFD_OPEN)
|
||||||
|
ZEND_FE(pcntl_setns, arginfo_pcntl_setns)
|
||||||
#endif
|
#endif
|
||||||
ZEND_FE_END
|
ZEND_FE_END
|
||||||
};
|
};
|
||||||
|
|
24
ext/pcntl/tests/pcntl_setns_basic.phpt
Normal file
24
ext/pcntl/tests/pcntl_setns_basic.phpt
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
--TEST--
|
||||||
|
pcntl_setns()
|
||||||
|
--EXTENSIONS--
|
||||||
|
pcntl
|
||||||
|
posix
|
||||||
|
--SKIPIF--
|
||||||
|
<?php
|
||||||
|
if (!function_exists("pcntl_setns")) die("skip pcntl_setns is not available");
|
||||||
|
if (getenv('SKIP_ASAN')) die('skip Timeouts under ASAN');
|
||||||
|
?>
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
$pid = pcntl_fork();
|
||||||
|
if ($pid == -1) die("pcntl_fork failed");
|
||||||
|
if ($pid != 0) {
|
||||||
|
try {
|
||||||
|
pcntl_setns($pid, 0);
|
||||||
|
} catch (\ValueError $e) {
|
||||||
|
echo $e->getMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
pcntl_setns(): Argument #2 ($nstype) is an invalid nstype (%d)
|
21
ext/pcntl/tests/pcntl_setns_newpid.phpt
Normal file
21
ext/pcntl/tests/pcntl_setns_newpid.phpt
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
--TEST--
|
||||||
|
pcntl_setns()
|
||||||
|
--EXTENSIONS--
|
||||||
|
pcntl
|
||||||
|
posix
|
||||||
|
--SKIPIF--
|
||||||
|
<?php
|
||||||
|
if (!function_exists("pcntl_setns")) die("skip pcntl_setns is not available");
|
||||||
|
if (posix_getuid() !== 0) die('skip Test needs root user');
|
||||||
|
if (getenv('SKIP_ASAN')) die('skip Timeouts under ASAN');
|
||||||
|
?>
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
$pid = pcntl_fork();
|
||||||
|
if ($pid == -1) die("pcntl_fork failed");
|
||||||
|
if ($pid != 0) {
|
||||||
|
var_dump(pcntl_setns($pid, CLONE_NEWPID));
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
bool(true)
|
Loading…
Add table
Add a link
Reference in a new issue