mirror of
https://github.com/php/php-src.git
synced 2024-11-23 09:54:15 +08: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
3
NEWS
3
NEWS
@ -122,6 +122,9 @@ PHP NEWS
|
||||
. Fixed bug with url_rewriter.hosts not used by output_add_rewrite_var().
|
||||
(haszi)
|
||||
|
||||
- PCNTL:
|
||||
. Added pcntl_setns for Linux. (David Carlier)
|
||||
|
||||
- PCRE:
|
||||
. Upgrade bundled pcre2lib to version 10.43. (nielsdos)
|
||||
. 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
|
||||
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:
|
||||
. Added the sodium_crypto_aead_aegis128l_*() and sodium_crypto_aead_aegis256l_*()
|
||||
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([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([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>])
|
||||
|
||||
|
@ -46,6 +46,10 @@
|
||||
#include <sched.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_PIDFD_OPEN
|
||||
#include <sys/syscall.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_FORKX
|
||||
#include <sys/fork.h>
|
||||
#endif
|
||||
@ -1402,6 +1406,76 @@ PHP_FUNCTION(pcntl_forkx)
|
||||
#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)
|
||||
{
|
||||
pcntl_signal_dispatch();
|
||||
|
@ -990,3 +990,7 @@ function pcntl_rfork(int $flags, int $signal = 0): int{}
|
||||
#ifdef HAVE_FORKX
|
||||
function pcntl_forkx(int $flags): int{}
|
||||
#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.
|
||||
* Stub hash: 3b03373d1bb68de779baaa62db14d98ca9018339 */
|
||||
* Stub hash: 614bd67bb4cfcdc68d37141ff9dfad0a49c318b5 */
|
||||
|
||||
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_pcntl_fork, 0, 0, IS_LONG, 0)
|
||||
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()
|
||||
#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_waitpid);
|
||||
ZEND_FUNCTION(pcntl_wait);
|
||||
@ -176,6 +183,9 @@ ZEND_FUNCTION(pcntl_rfork);
|
||||
#if defined(HAVE_FORKX)
|
||||
ZEND_FUNCTION(pcntl_forkx);
|
||||
#endif
|
||||
#if defined(HAVE_PIDFD_OPEN)
|
||||
ZEND_FUNCTION(pcntl_setns);
|
||||
#endif
|
||||
|
||||
static const zend_function_entry ext_functions[] = {
|
||||
ZEND_FE(pcntl_fork, arginfo_pcntl_fork)
|
||||
@ -222,6 +232,9 @@ static const zend_function_entry ext_functions[] = {
|
||||
#endif
|
||||
#if defined(HAVE_FORKX)
|
||||
ZEND_FE(pcntl_forkx, arginfo_pcntl_forkx)
|
||||
#endif
|
||||
#if defined(HAVE_PIDFD_OPEN)
|
||||
ZEND_FE(pcntl_setns, arginfo_pcntl_setns)
|
||||
#endif
|
||||
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…
Reference in New Issue
Block a user