We found a problem regarding TCP connection alias in the following code at
tcp_main.c:
int tcpconn_finish_connect( struct tcp_connection* c,
union sockaddr_union* from)
{
:
:
/* remove all the aliases
except the first one and re-add them
* (there shouldn't be more
then the 3 default aliases at this
* stage) */
for (r=1; r<c->aliases;
r++){
a=&c->con_aliases[r];
tcpconn_listrm(tcpconn_aliases_hash[a->hash],
a, next, prev);
}
c->aliases=1;
As TCP_ALIAS_REPLACE flag is set for the default TCP options value, in the
function _tcpconn_add_alias_unsafe() a TCP connection alias can be moved
from connection A to connection B based on the TCP alias hash. In this
case, the number of aliases is incremented in the connection A, and
decremented from connection B. However, in the connection B the number of
aliases can reach zero (no alias). And the code above can be executed for
connection B setting the number of aliases to 1 unconditionally. When this
case happens, the connection B keeps an invalid alias (already excluded
from connection B by tcpconn_add_alias_unsafe() function called from
connection A). When the connection A is released, the aliases are also
released, and this memory area can be filled with different data. As
connection B has references to an invalid alias it can try to access
invalid areas, and can crash Kamailio. This access happens, for example,
when another alias is added to connection B.
To fix it we include a check before the code:
if (c->aliases>0) {
for (r=1;
r<c->aliases; r++){
a=&c->con_aliases[r];
tcpconn_listrm(tcpconn_aliases_hash[a->hash], a, next, prev);
memset(a,0xbb,sizeof(struct tcp_conn_alias));
}
c->aliases=1;
}
Please let us know if any comments.
Thanks
Jijo