php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #65000 use after free (double free) caused by emalloc in _zval_copy_ctor_func
Submitted: 2013-06-09 16:05 UTC Modified: 2013-06-28 06:59 UTC
From: shm@php.net Assigned:
Status: Open Package: Reproducible crash
PHP Version: 5.4.16 OS: Linux
Private report: No CVE-ID: None
Have you experienced this issue?
Rate the importance of this bug to you:

 [2013-06-09 16:05 UTC] shm@php.net
Description:
------------
$ ./php --version
PHP 5.4.16 (cli) (built: Jun  9 2013 17:56:24) (DEBUG)
Copyright (c) 1997-2013 The PHP Group
Zend Engine v2.4.0, Copyright (c) 1998-2013 Zend Technologies
---
(gdb) r ~shm/php1.php 
Starting program: /home/fuzzphp/php-5.4.16/sapi/cli/php ~shm/php1.php

Fatal error: Allowed memory size of 33554432 bytes exhausted at /home/fuzzphp/php-5.4.16/Zend/zend_vm_execute.h:27134 (tried to allocate 30000001 bytes) in /home/shm/php1.php on line 11

Program received signal SIGSEGV, Segmentation fault.
0x00000000008ebc07 in _zval_dtor_func (zvalue=0x7ffff7fdb4d8, __zend_filename=0xeac8e8 "/home/fuzzphp/php-5.4.16/Zend/zend_execute_API.c", __zend_lineno=438)
    at /home/fuzzphp/php-5.4.16/Zend/zend_variables.c:35
35                              CHECK_ZVAL_STRING_REL(zvalue);
(gdb) bt
#0  0x00000000008ebc07 in _zval_dtor_func (zvalue=0x7ffff7fdb4d8, __zend_filename=0xeac8e8 "/home/fuzzphp/php-5.4.16/Zend/zend_execute_API.c", __zend_lineno=438)
    at /home/fuzzphp/php-5.4.16/Zend/zend_variables.c:35
#1  0x00000000008da584 in _zval_dtor (zvalue=0x7ffff7fdb4d8, __zend_filename=0xeac8e8 "/home/fuzzphp/php-5.4.16/Zend/zend_execute_API.c", __zend_lineno=438)
    at /home/fuzzphp/php-5.4.16/Zend/zend_variables.h:35
#2  0x00000000008db528 in _zval_ptr_dtor (zval_ptr=0x7ffff7fdcb00, __zend_filename=0xeae170 "/home/fuzzphp/php-5.4.16/Zend/zend_variables.c", __zend_lineno=182)
    at /home/fuzzphp/php-5.4.16/Zend/zend_execute_API.c:438
#3  0x00000000008ec0c1 in _zval_ptr_dtor_wrapper (zval_ptr=0x7ffff7fdcb00) at /home/fuzzphp/php-5.4.16/Zend/zend_variables.c:182
#4  0x000000000090046a in zend_hash_apply_deleter (ht=0x116ad88, p=0x7ffff7fdcae8) at /home/fuzzphp/php-5.4.16/Zend/zend_hash.c:650
#5  0x00000000009005fb in zend_hash_graceful_reverse_destroy (ht=0x116ad88) at /home/fuzzphp/php-5.4.16/Zend/zend_hash.c:687
#6  0x00000000008daed3 in shutdown_executor () at /home/fuzzphp/php-5.4.16/Zend/zend_execute_API.c:247
#7  0x00000000008edf1e in zend_deactivate () at /home/fuzzphp/php-5.4.16/Zend/zend.c:938
#8  0x000000000086438f in php_request_shutdown (dummy=0x0) at /home/fuzzphp/php-5.4.16/main/main.c:1800
#9  0x0000000000990d12 in do_cli (argc=2, argv=0x7fffffffe628) at /home/fuzzphp/php-5.4.16/sapi/cli/php_cli.c:1171
#10 0x0000000000991418 in main (argc=2, argv=0x7fffffffe628) at /home/fuzzphp/php-5.4.16/sapi/cli/php_cli.c:1364
-----

It seems that _zval_copy_ctor_func can be used to trigger double free/use after free issue, in case when emalloc pointed here: http://lxr.php.net/xref/PHP_5_4/Zend/zend_variables.c#123 fails (estrndup calls emalloc internally). The interpreter runs destroy functions on error (memory exhastion) which lead to use value.str.val two times. Please see the test script for details.

I'm not sure how to fix the issue, so I left it for smarter than me. :-)


Test script:
---------------
<?php

ini_set('memory_limit', '32M');
$var5 = str_repeat("A",30000000);
$x = array($var5);

function crash_me(&$x) {
 die('failed :-(');
}

crash_me($var5);


Expected result:
----------------
no crash

Actual result:
--------------
SEGFAULT

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2013-06-10 18:54 UTC] stas@php.net
-Type: Security +Type: Bug -Package: *General Issues +Package: Reproducible crash
 [2013-06-11 12:50 UTC] laruence@php.net
here is the replay I wrote to security, just for the record:
   A fix could be, set the zval type to be NULL, then doing the
estrndup, then set it back to IS_STRING:

@@ -118,10 +118,12 @@ ZEND_API void _zval_copy_ctor_func(zval *zvalue
ZEND_FILE_LINE_DC)
  break;
  case IS_CONSTANT:
  case IS_STRING:
+    ZVAL_NULL(zvalue);
  CHECK_ZVAL_STRING_REL(zvalue);
  if (!IS_INTERNED(zvalue->value.str.val)) {
  zvalue->value.str.val = (char *) estrndup_rel(zvalue->value.str.val,
zvalue->value.str.l
en);
  }
+ Z_TYPE_P(zvalue) = IS_STRING;
  break;


 but it definitly will brings performance slow down...
 [2013-06-11 14:28 UTC] laruence@php.net
-Type: Bug +Type: Security -Private report: No +Private report: Yes
 [2013-06-11 14:29 UTC] laruence@php.net
-Type: Security +Type: Bug
 [2013-06-28 06:59 UTC] shm@php.net
Are you going to commit this patch?
 
PHP Copyright © 2001-2018 The PHP Group
All rights reserved.
Last updated: Sat Nov 17 02:01:25 2018 UTC