-
Notifications
You must be signed in to change notification settings - Fork 877
Description
Hi,
There's an invalid union access of sock->ssl->handshake.server in proceed_handshake() for client connections that may cause pointer corruption under certain conditions. The handshake union is written to using handshake.server in lib/common/socket.c:1103, without checking if this is a client or a server handshake.
ERR_clear_error();
if (SSL_is_server(sock->ssl->ossl)) {
ret = SSL_accept(sock->ssl->ossl);
} else {
ret = SSL_connect(sock->ssl->ossl);
}
switch (sock->ssl->handshake.server.async_resumption.state) {
case ASYNC_RESUMPTION_STATE_RECORD:
/* async resumption has not been triggered; proceed the state to complete */
sock->ssl->handshake.server.async_resumption.state = ASYNC_RESUMPTION_STATE_COMPLETE;
break;The switch statement in line 1103 checks handshake.server.async_resumption.state, which coincides with handshake.client.server_name's high bytes on big endian architectures. On Debian/s390x, if server_name is allocated on the heap, it will usually be around address 0x100000000 which when accessed as handshake.server.async_resumption.state will contain 1 (i.e. ASYNC_RESUMPTION_STATE_RECORD) and so the code will set it to ASYNC_RESUMPTION_STATE_COMPLETE (i.e. 0), effectively zeroing out the server_name pointer's top 32 bits. This causes reverse proxy tests to segfault during h2o's build on Debian/s390x. I guess it's hard to trigger it on other architectures, as it depends on endianness and also on the location of the heap in the virtual address space.
The code should be probably fixed to access handshake.server only for server sockets.
Apollon