Bug #79027 [PATCH]: Heap corruption in accel_remap_huge_pages

From: Date: Tue, 31 Dec 2019 12:37:51 +0000
Subject: Bug #79027 [PATCH]: Heap corruption in accel_remap_huge_pages
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-224635@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=79027&edit=1 ID: 79027 Patch added by: chris@neadwerx.com Reported by: chris at neadwerx dot com Summary: Heap corruption in accel_remap_huge_pages Status: Open Type: Bug Package: opcache Operating System: Linux PHP Version: Irrelevant Block user comment: N Private report: N New Comment: The following patch has been added/updated: Patch Name: PHP7_huge_2mb_flag.patch Revision: 1577795871 URL: https://bugs.php.net/patch-display.php?bug=79027&patch=PHP7_huge_2mb_flag.patch&revision=1577795871 Previous Comments: ------------------------------------------------------------------------ [2019-12-24 14:18:07] chris at neadwerx dot com 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 this bug report at https://bugs.php.net/bug.php?id=79027&edit=1

« previous php.bugs (#224635) next »