Bug #79027 [NEW]: Heap corruption in accel_remap_huge_pages
| From: | chris at neadwerx dot com | Date: | Tue, 24 Dec 2019 14:18:08 +0000 |
| Subject: | Bug #79027 [NEW]: Heap corruption in accel_remap_huge_pages | ||
| Groups: | php.bugs | ||
| Request: | Send a blank email to php-bugs+get-224520@lists.php.net to get a copy of this message | ||
From: chris at neadwerx dot com
Operating system: Linux
PHP version: Irrelevant
Package: opcache
Bug Type: Bug
Bug description:Heap corruption in accel_remap_huge_pages
Description:
------------
Prerequisites:
- System has CPU flag PDPE1GB (basically sandy bridge era or better)
- System configured with hugepage size of 1GB
- PHP version > 7.0
- /etc/php.d/10-opcache.ini:opcache.huge_code_pages=1
Execution:
PHP has a 0.2% chance that execve() loads PHP in the upper 512 4 KiB
pages of a 1 GiB page. This causes zend_move_code_to_huge_pages to
select start address for the mmap allocation to be 1 GiB aligned
(ZEND_MM_ALIGNED_SIZE_EX for the start address - both 2MiB and 1GiB
alignment will be the same).
From mmap(2). This will result in a successful allocation of a full 1
GiB, resulting in a corrupted heap. PHP will receive a SIGSEGV when
returning from zend_remap_huge_pages and calling fclose on the file
pointer in zend_move_code_to_huge_pages()
Remediation:
- Modify zend_remap_huge_pages to call mmap with the MAP_HUGE_2MB flag
or
- Check system default hugepage size by opening /proc/meminfo and
reading in Hugepagesize setting - this isn't very portable but ensures
that the correct page size can be used, or the function can exit
gracefully.
Test script:
---------------
#!/usr/bin/perl -w
while(1)
{
system( 'php /some/php/file' ); # doesn't need to be a CLI call, can
be from apache
}
Expected result:
----------------
Nothing
Actual result:
--------------
0.2% chance of SIGSEGV
It was very difficult to get a useful trace for this, This is the best I
could come up with as GDB was being very uncooperative:
#0: 0x7f898aa80ff4 _IO_new_fclose /usr/lib64/libc-2.17.so (offset
0x6dff4)
#1: 0x562b420466c0 ??
#2: 0x200000 ??
#3: 0x7f8963303000 ??
#4: 0x7f8982e617f7 accel_move_code_to_huge_pages
/usr/lib64/php/modules/opcache.so (offset 0x107f7)
#5: 0x562b3ff78000 ??
#6: 0x562b403dc000 /usr/bin/php (offset 0x464000)
--
Edit bug report at https://bugs.php.net/bug.php?id=79027&edit=1
--
Fix committed: https://bugs.php.net/fix.php?id=79027&r=fixed
Fixed in release: https://bugs.php.net/fix.php?id=79027&r=alreadyfixed
Need backtrace: https://bugs.php.net/fix.php?id=79027&r=needtrace
Need Reproduce Script: https://bugs.php.net/fix.php?id=79027&r=needscript
Try newer version: https://bugs.php.net/fix.php?id=79027&r=oldversion
Not developer issue: https://bugs.php.net/fix.php?id=79027&r=support
Expected behavior: https://bugs.php.net/fix.php?id=79027&r=notwrong
Not enough info: https://bugs.php.net/fix.php?id=79027&r=notenoughinfo
Submitted twice: https://bugs.php.net/fix.php?id=79027&r=submittedtwice
register_globals: https://bugs.php.net/fix.php?id=79027&r=globals
PHP version support discontinued: https://bugs.php.net/fix.php?id=79027&r=phptooold
Daylight Savings: https://bugs.php.net/fix.php?id=79027&r=dst
IIS Stability: https://bugs.php.net/fix.php?id=79027&r=isapi
Install GNU Sed: https://bugs.php.net/fix.php?id=79027&r=gnused
Floating point limitations: https://bugs.php.net/fix.php?id=79027&r=float
No Zend Extensions: https://bugs.php.net/fix.php?id=79027&r=nozend
MySQL Configuration Error: https://bugs.php.net/fix.php?id=79027&r=mysqlcfg