Indirect Branch Tracking (IBT) is part of Intel's Control-Flow
Enforcement Technology (CET). IBT is hardware based, forward edge
Control-Flow-Integrity mechanism where any indirect CALL/JMP must target
an ENDBR instruction or suffer #CP.
This commit adds IBT support for fiber:
1. Add endbr32/64 in assembly
2. Inform compiler jump_fcontext may return via indirect branch
Furthermore:
gcc support CET since v8.1 and set it to default since gcc 11. That is,
the ELF header of sapi/cli/php has a property named IBT. However, such
property is lost since PHP8.1 because the assembly introduced by Fiber.
This commit also fixes this.
Closes GH-8339
Signed-off-by: Chen, Hu <hu1.chen@intel.com>
Co-authored-by: Christoph M. Becker <cmbecker69@gmx.de>
Even if the fiber function returns by reference, we must return
a value from Fiber::getReturn() to satisfy the function signature.
Fixes oss-fuzz #36417.
This prevents serialization and unserialization of a class and its
children in a way that does not depend on the zend_class_serialize_deny
and zend_class_unserialize_deny handlers that will be going away
in PHP 9 together with the Serializable interface.
In stubs, `@not-serializable` can be used to set this flag.
This patch only uses the new flag for a handful of Zend classes,
converting the remainder is left for later.
Closes GH-7249.
Fixes bug #81111.
Direct creation of GracefulExit allows the the special exception object to be transfered and thrown into a destroyed fiber using the same path as any other exception thrown into a fiber instead of needing to check for a flag.
Removes unnecessary copying of fiber return value to transfer value. This zval was not used as the return of start/resume/throw, instead being destroyed when the fiber was dead. Now the zval initialized to NULL when starting the fiber is maintained as the transfer value and is subsequently returned from start/resume/throw.
Add zend_fiber prefix to delegate_transfer_result().
Ensure status is set to INIT when initializing the fiber context in case memory is not zeroed.
Assert destination fiber context is not dead.
Update stack alloc failure messages.
getThis() -> ZEND_THIS
The variable size of zend_fiber_stack results in the offset of other fields to be variable, which causes compatiblity issues with extensions when php-src is compiled with ASan enabled. This solution was prefered over moving the stack field to be the last member, as inclusion of ZEND_FIBER_CONTEXT_FIELDS into other structs may still result in field offset errors.
The definition of zend_fiber_stack was removed from the header to hide it from the ABI.
Renamed prior_pointer and prior_size to asan_pointer and asan_size to reflect their current use.
Changed context flags type to uint8_t.
Renamed valgrind stack id field to valgrind_stack_id and fixed the type to unsigned int.
Allows flags besides ZEND_FIBER_FLAG_THREW to be set without causing this method to throw.
The method will not be called after a bailout, so the ZEND_FIBER_FLAG_BAILOUT case was removed.
- make_fcontext() never returns NULL.
- Show syscall error info in exception just like zend_alloc does (we also used php_win32_error_*() in Zend).
- MAP_ANON was marked as deprecated or compatibility macro on Linux, It would be better to use MAP_ANONYMOUS first.
- Makes the code consistent with the code of other modules in the kernel.
- adds some comments.
This additional internal fiber API creates and manipulates a Fiber object, allowing any internal function to start, resume, or suspend a fiber. The existing zend_fiber_context API allows custom C-based fiber creation using the bundled switching context, but does not interact with the PHP VM. This API behaves the same as calling Fiber object methods from user code, switching EGs, and triggering the fiber switch observer. In general, the Fiber object methods call these new API methods.
This removes switching to main for fatal errors in fibers in favor of catching any zend_bailout in a fiber and calling zend_bailout again after switching to the previous fiber or {main}.
Checking EG(current_exectue_data) throws into the previous fiber instead of triggering a fatal error during shutdown. A fatal error is triggered only if the throwing destroyed fiber was resumed from {main}.
Previously an exception thrown during fiber destruction resulted in a fatal error, but that exception should be able to be caught (unless we’ve entered shutdown, then still use a fatal error so the error is not hidden).
This is needed by both fibers and opcache (and GH-6903 also uses it),
so make it a common structure that can be used by any functionality
storing warnings/errors.