Merge r429273 for AST-2014-019

git-svn-id: https://origsvn.digium.com/svn/asterisk/tags/13.1.0-rc2@429317 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Asterisk Autobuilder
2014-12-10 14:41:05 +00:00
parent b44043c493
commit f040fdbd76
4 changed files with 45 additions and 13 deletions

View File

@@ -1,3 +1,25 @@
2014-12-10 Asterisk Development Team <asteriskteam@digium.com>
* Asterisk 13.1.0-rc2 Released.
* AST-2014-019: Fix crash when receiving a WebSocket packet with a
payload length of zero.
Frames with a payload length of 0 were incorrectly handled in
res_http_websocket. Provided a frame with a payload had been
received prior it was possible for a double free to occur. The
realloc operation would succeed (thus freeing the payload) but be
treated as an error. When the session was then torn down the payload
would be freed again causing a crash. The read function now takes
this into account.
This change also fixes assumptions made by users of
res_http_websocket. There is no guarantee that a frame received from
it will be NULL terminated.
ASTERISK-24472 #close
Reported by: Badalian Vyacheslav
2014-12-08 Asterisk Development Team <asteriskteam@digium.com> 2014-12-08 Asterisk Development Team <asteriskteam@digium.com>
* Asterisk 13.1.0-rc1 Released. * Asterisk 13.1.0-rc1 Released.

View File

@@ -2644,12 +2644,16 @@ static void sip_websocket_callback(struct ast_websocket *session, struct ast_var
if (opcode == AST_WEBSOCKET_OPCODE_TEXT || opcode == AST_WEBSOCKET_OPCODE_BINARY) { if (opcode == AST_WEBSOCKET_OPCODE_TEXT || opcode == AST_WEBSOCKET_OPCODE_BINARY) {
struct sip_request req = { 0, }; struct sip_request req = { 0, };
char data[payload_len + 1];
if (!(req.data = ast_str_create(payload_len + 1))) { if (!(req.data = ast_str_create(payload_len + 1))) {
goto end; goto end;
} }
if (ast_str_set(&req.data, -1, "%s", payload) == AST_DYNSTR_BUILD_FAILED) { strncpy(data, payload, payload_len);
data[payload_len] = '\0';
if (ast_str_set(&req.data, -1, "%s", data) == AST_DYNSTR_BUILD_FAILED) {
deinit_req(&req); deinit_req(&req);
goto end; goto end;
} }

View File

@@ -513,14 +513,6 @@ int AST_OPTIONAL_API_NAME(ast_websocket_read)(struct ast_websocket *session, cha
} }
} }
if (!(new_payload = ast_realloc(session->payload, (session->payload_len + *payload_len)))) {
ast_log(LOG_WARNING, "Failed allocation: %p, %zu, %"PRIu64"\n",
session->payload, session->payload_len, *payload_len);
*payload_len = 0;
ast_websocket_close(session, 1009);
return 0;
}
/* Per the RFC for PING we need to send back an opcode with the application data as received */ /* Per the RFC for PING we need to send back an opcode with the application data as received */
if ((*opcode == AST_WEBSOCKET_OPCODE_PING) && (ast_websocket_write(session, AST_WEBSOCKET_OPCODE_PONG, *payload, *payload_len))) { if ((*opcode == AST_WEBSOCKET_OPCODE_PING) && (ast_websocket_write(session, AST_WEBSOCKET_OPCODE_PONG, *payload, *payload_len))) {
*payload_len = 0; *payload_len = 0;
@@ -528,9 +520,22 @@ int AST_OPTIONAL_API_NAME(ast_websocket_read)(struct ast_websocket *session, cha
return 0; return 0;
} }
session->payload = new_payload; if (*payload_len) {
memcpy((session->payload + session->payload_len), (*payload), (*payload_len)); if (!(new_payload = ast_realloc(session->payload, (session->payload_len + *payload_len)))) {
session->payload_len += *payload_len; ast_log(LOG_WARNING, "Failed allocation: %p, %zu, %"PRIu64"\n",
session->payload, session->payload_len, *payload_len);
*payload_len = 0;
ast_websocket_close(session, 1009);
return 0;
}
session->payload = new_payload;
memcpy((session->payload + session->payload_len), (*payload), (*payload_len));
session->payload_len += *payload_len;
} else if (!session->payload_len && session->payload) {
ast_free(session->payload);
session->payload = NULL;
}
if (!fin && session->reconstruct && (session->payload_len < session->reconstruct)) { if (!fin && session->reconstruct && (session->payload_len < session->reconstruct)) {
/* If this is not a final message we need to defer returning it until later */ /* If this is not a final message we need to defer returning it until later */

View File

@@ -200,7 +200,8 @@ static int transport_read(void *data)
pj_gettimeofday(&rdata->pkt_info.timestamp); pj_gettimeofday(&rdata->pkt_info.timestamp);
pj_memcpy(rdata->pkt_info.packet, read_data->payload, sizeof(rdata->pkt_info.packet)); pj_memcpy(rdata->pkt_info.packet, read_data->payload,
PJSIP_MAX_PKT_LEN < read_data->payload_len ? PJSIP_MAX_PKT_LEN : read_data->payload_len);
rdata->pkt_info.len = read_data->payload_len; rdata->pkt_info.len = read_data->payload_len;
rdata->pkt_info.zero = 0; rdata->pkt_info.zero = 0;