From: zingaburga at hotmail dot com
Operating system: Debian 7 amd64
PHP version: 5.6.6
Package: Streams related
Bug Type: Bug
Bug description:Bus error from stream_copy_to_stream (file -> SSL stream) with invalid length
Description:
------------
It seems that a Bus error can be generated by stream_copy_to_stream,
when copying to a SSL stream if the given length exceeds the available
remaining data.
I've successfully replicated the problem on a few machines, using the
exact parameters below, all running Debian 7 x86-64, on both PHP 5.5 and
5.6, although it doesn't seem to occur _everywhere_.
I haven't experimented, but I suspect it may be something to do with
mmap and the range check.
From main/streams/plain_wrapper.c:
case PHP_STREAM_MMAP_MAP_RANGE:
do_fstat(data, 1);
if (range->length == 0 && range->offset > 0 && range->offset <
data->sb.st_size) {
range->length = data->sb.st_size - range->offset;
}
if (range->length == 0 || range->length > data->sb.st_size) {
range->length = data->sb.st_size;
}
if (range->offset >= data->sb.st_size) {
range->offset = data->sb.st_size;
range->length = 0;
}
It doesn't look like range->length is ever checked against
range->offset+data->sb.st_size, hence it's possible for
php_stdiop_set_option to claim that more memory was mapped than actually
was. This can cause invalid memory errors when the buffer is read.
And for reference's sake, it seems that sending the file over HTTP is
also problematic, though you won't get a crash:
Notice: stream_copy_to_stream(): send of 8192 bytes failed with errno=14
Bad address in /root/b.php on line 9
int(7340032)
bool(false)
Test script:
---------------
<?php
// create an TLS stream to localhost:443 (this means you need a server
listening there)
$context = stream_context_create();
stream_context_set_option($context, 'ssl', 'verify_peer', false);
$fw = stream_socket_client('tls://localhost:443', $null, $null, 5,
STREAM_CLIENT_CONNECT, $context);
fwrite($fw, "POST /null.php HTTP/1.1\r\nHost:
localhost\r\nContent-Length: 1073741824\r\n\r\n");
// the file './data' needs to be 8383276 bytes long, can be created via
'dd if=/dev/zero of=data count=1 bs=8383276'
$fr = fopen('./data', 'rb');
// copy
var_dump(stream_copy_to_stream($fr, $fw, 7340032));
var_dump(stream_copy_to_stream($fr, $fw, 1048576)); // causes Bus Error
as it overflows the file's size
fclose($fr);
fclose($fw);
Expected result:
----------------
int(7340032)
int(1043244)
Actual result:
--------------
int(7340032)
Program received signal SIGBUS, Bus error.
__memcpy_sse2_unaligned () at
../sysdeps/x86_64/multiarch/memcpy-sse2-unaligned.S:36
36 ../sysdeps/x86_64/multiarch/memcpy-sse2-unaligned.S: No such
file or directory.
----- BACKTRACE -----
#0 __memcpy_sse2_unaligned () at
../sysdeps/x86_64/multiarch/memcpy-sse2-unaligned.S:36
#1 0x00007ffff70e9c7c in memcpy (__len=8192, __src=0x7fffec514000,
__dest=<optimized out>)
at /usr/include/x86_64-linux-gnu/bits/string3.h:51
#2 do_ssl3_write (s=s@entry=0x1229b40, type=type@entry=23,
buf=buf@entry=0x7fffec514000 "", len=8192,
create_empty_fragment=create_empty_fragment@entry=0) at
s3_pkt.c:836
#3 0x00007ffff70e9e24 in ssl3_write_bytes (s=0x1229b40, type=23,
buf_=0x7fffec514000, len=<optimized out>)
at s3_pkt.c:646
#4 0x0000000000479878 in php_openssl_sockop_write
(stream=0x7ffff7fceb18, buf=0x7fffec514000 "",
count=<optimized out>) at
/usr/src/php5.6/nonzts/source/dotdeb-php5/ext/openssl/xp_ssl.c:1786
#5 0x000000000068d25e in _php_stream_write_buffer
(stream=0x7ffff7fceb18, buf=0x7fffec514000 "", count=8192)
at
/usr/src/php5.6/nonzts/source/dotdeb-php5/main/streams/streams.c:1133
#6 0x000000000068f8df in _php_stream_copy_to_stream_ex
(src=src@entry=0x7ffff7fcff10, dest=dest@entry=0x7ffff7fceb18,
maxlen=1048576, len=len@entry=0x7fffffffac98)
at
/usr/src/php5.6/nonzts/source/dotdeb-php5/main/streams/streams.c:1536
#7 0x000000000065015f in zif_stream_copy_to_stream (ht=<optimized out>,
return_value=0x7ffff7fcd768,
return_value_ptr=<optimized out>, this_ptr=<optimized out>,
return_value_used=<optimized out>)
at
/usr/src/php5.6/nonzts/source/dotdeb-php5/ext/standard/streamsfuncs.c:477
#8 0x00000000006c9919 in dtrace_execute_internal
(execute_data_ptr=<optimized out>, fci=<optimized out>,
return_value_used=<optimized out>) at
/usr/src/php5.6/nonzts/source/dotdeb-php5/Zend/zend_dtrace.c:97
#9 0x000000000077d1e1 in zend_do_fcall_common_helper_SPEC
(execute_data=0x7ffff7f9b268)
at
/usr/src/php5.6/nonzts/source/dotdeb-php5/Zend/zend_vm_execute.h:560
#10 0x0000000000743a88 in execute_ex (execute_data=0x7ffff7f9b268)
at
/usr/src/php5.6/nonzts/source/dotdeb-php5/Zend/zend_vm_execute.h:363
#11 0x00000000006c97ed in dtrace_execute_ex (execute_data=<optimized
out>)
at /usr/src/php5.6/nonzts/source/dotdeb-php5/Zend/zend_dtrace.c:73
#12 0x00000000006dc028 in zend_execute_scripts (type=type@entry=8,
retval=retval@entry=0x0,
file_count=file_count@entry=3) at
/usr/src/php5.6/nonzts/source/dotdeb-php5/Zend/zend.c:1341
#13 0x000000000067796c in php_execute_script
(primary_file=primary_file@entry=0x7fffffffd250)
at /usr/src/php5.6/nonzts/source/dotdeb-php5/main/main.c:2584
#14 0x0000000000780783 in do_cli (argc=2, argv=0xedd990)
at /usr/src/php5.6/nonzts/source/dotdeb-php5/sapi/cli/php_cli.c:994
#15 0x0000000000433b7f in main (argc=2, argv=0xedd990)
at
/usr/src/php5.6/nonzts/source/dotdeb-php5/sapi/cli/php_cli.c:1378
--
Edit bug report at https://bugs.php.net/bug.php?id=69100&edit=1
--
Try a snapshot (PHP 5.4): https://bugs.php.net/fix.php?id=69100&r=trysnapshot54
Try a snapshot (PHP 5.5): https://bugs.php.net/fix.php?id=69100&r=trysnapshot55
Try a snapshot (trunk): https://bugs.php.net/fix.php?id=69100&r=trysnapshottrunk
Fixed in SVN: https://bugs.php.net/fix.php?id=69100&r=fixed
Fixed in release: https://bugs.php.net/fix.php?id=69100&r=alreadyfixed
Need backtrace: https://bugs.php.net/fix.php?id=69100&r=needtrace
Need Reproduce Script: https://bugs.php.net/fix.php?id=69100&r=needscript
Try newer version: https://bugs.php.net/fix.php?id=69100&r=oldversion
Not developer issue: https://bugs.php.net/fix.php?id=69100&r=support
Expected behavior: https://bugs.php.net/fix.php?id=69100&r=notwrong
Not enough info: https://bugs.php.net/fix.php?id=69100&r=notenoughinfo
Submitted twice: https://bugs.php.net/fix.php?id=69100&r=submittedtwice
register_globals: https://bugs.php.net/fix.php?id=69100&r=globals
PHP 4 support discontinued: https://bugs.php.net/fix.php?id=69100&r=php4
Daylight Savings: https://bugs.php.net/fix.php?id=69100&r=dst
IIS Stability: https://bugs.php.net/fix.php?id=69100&r=isapi
Install GNU Sed: https://bugs.php.net/fix.php?id=69100&r=gnused
Floating point limitations: https://bugs.php.net/fix.php?id=69100&r=float
No Zend Extensions: https://bugs.php.net/fix.php?id=69100&r=nozend
MySQL Configuration Error: https://bugs.php.net/fix.php?id=69100&r=mysqlcfg