Protect _transportPtr, which can be accessed by different threads in the case of external transport. This change avoid the potential use-after-free, e.g. the case in the reported bug.

BUG=2508
RISK=P1
TEST=try bots
R=henrika@webrtc.org, xians@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/2425004

git-svn-id: http://webrtc.googlecode.com/svn/trunk@5000 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
wu@webrtc.org 2013-10-18 21:10:51 +00:00
parent 3c5d2b43ec
commit fb648da2b9

View File

@ -121,6 +121,8 @@ Channel::SendPacket(int channel, const void *data, int len)
WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId), WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
"Channel::SendPacket(channel=%d, len=%d)", channel, len); "Channel::SendPacket(channel=%d, len=%d)", channel, len);
CriticalSectionScoped cs(&_callbackCritSect);
if (_transportPtr == NULL) if (_transportPtr == NULL)
{ {
WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,_channelId), WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,_channelId),
@ -158,8 +160,6 @@ Channel::SendPacket(int channel, const void *data, int len)
// SRTP or External encryption // SRTP or External encryption
if (_encrypting) if (_encrypting)
{ {
CriticalSectionScoped cs(&_callbackCritSect);
if (_encryptionPtr) if (_encryptionPtr)
{ {
if (!_encryptionRTPBufferPtr) if (!_encryptionRTPBufferPtr)
@ -192,39 +192,18 @@ Channel::SendPacket(int channel, const void *data, int len)
} }
} }
// Packet transmission using WebRtc socket transport int n = _transportPtr->SendPacket(channel, bufferToSendPtr,
if (!_externalTransport) bufferLength);
{ if (n < 0) {
int n = _transportPtr->SendPacket(channel, bufferToSendPtr, std::string transport_name =
bufferLength); _externalTransport ? "external transport" : "WebRtc sockets";
if (n < 0) WEBRTC_TRACE(kTraceError, kTraceVoice,
{ VoEId(_instanceId,_channelId),
WEBRTC_TRACE(kTraceError, kTraceVoice, "Channel::SendPacket() RTP transmission using %s failed",
VoEId(_instanceId,_channelId), transport_name.c_str());
"Channel::SendPacket() RTP transmission using WebRtc" return -1;
" sockets failed");
return -1;
}
return n;
}
// Packet transmission using external transport transport
{
CriticalSectionScoped cs(&_callbackCritSect);
int n = _transportPtr->SendPacket(channel,
bufferToSendPtr,
bufferLength);
if (n < 0)
{
WEBRTC_TRACE(kTraceError, kTraceVoice,
VoEId(_instanceId,_channelId),
"Channel::SendPacket() RTP transmission using external"
" transport failed");
return -1;
}
return n;
} }
return n;
} }
int int
@ -236,16 +215,14 @@ Channel::SendRTCPPacket(int channel, const void *data, int len)
WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId), WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
"Channel::SendRTCPPacket(channel=%d, len=%d)", channel, len); "Channel::SendRTCPPacket(channel=%d, len=%d)", channel, len);
CriticalSectionScoped cs(&_callbackCritSect);
if (_transportPtr == NULL)
{ {
CriticalSectionScoped cs(&_callbackCritSect); WEBRTC_TRACE(kTraceError, kTraceVoice,
if (_transportPtr == NULL) VoEId(_instanceId,_channelId),
{ "Channel::SendRTCPPacket() failed to send RTCP packet"
WEBRTC_TRACE(kTraceError, kTraceVoice, " due to invalid transport object");
VoEId(_instanceId,_channelId), return -1;
"Channel::SendRTCPPacket() failed to send RTCP packet"
" due to invalid transport object");
return -1;
}
} }
uint8_t* bufferToSendPtr = (uint8_t*)data; uint8_t* bufferToSendPtr = (uint8_t*)data;
@ -262,8 +239,6 @@ Channel::SendRTCPPacket(int channel, const void *data, int len)
// SRTP or External encryption // SRTP or External encryption
if (_encrypting) if (_encrypting)
{ {
CriticalSectionScoped cs(&_callbackCritSect);
if (_encryptionPtr) if (_encryptionPtr)
{ {
if (!_encryptionRTCPBufferPtr) if (!_encryptionRTCPBufferPtr)
@ -294,45 +269,19 @@ Channel::SendRTCPPacket(int channel, const void *data, int len)
} }
} }
// Packet transmission using WebRtc socket transport int n = _transportPtr->SendRTCPPacket(channel,
if (!_externalTransport) bufferToSendPtr,
{ bufferLength);
int n = _transportPtr->SendRTCPPacket(channel, if (n < 0) {
bufferToSendPtr, std::string transport_name =
bufferLength); _externalTransport ? "external transport" : "WebRtc sockets";
if (n < 0) WEBRTC_TRACE(kTraceInfo, kTraceVoice,
{ VoEId(_instanceId,_channelId),
WEBRTC_TRACE(kTraceInfo, kTraceVoice, "Channel::SendRTCPPacket() transmission using %s failed",
VoEId(_instanceId,_channelId), transport_name.c_str());
"Channel::SendRTCPPacket() transmission using WebRtc" return -1;
" sockets failed");
return -1;
}
return n;
} }
return n;
// Packet transmission using external transport transport
{
CriticalSectionScoped cs(&_callbackCritSect);
if (_transportPtr == NULL)
{
return -1;
}
int n = _transportPtr->SendRTCPPacket(channel,
bufferToSendPtr,
bufferLength);
if (n < 0)
{
WEBRTC_TRACE(kTraceInfo, kTraceVoice,
VoEId(_instanceId,_channelId),
"Channel::SendRTCPPacket() transmission using external"
" transport failed");
return -1;
}
return n;
}
return len;
} }
void void
@ -5071,6 +5020,7 @@ Channel::GetDeadOrAliveCounters(int& countDead, int& countAlive) const
int32_t int32_t
Channel::SendPacketRaw(const void *data, int len, bool RTCP) Channel::SendPacketRaw(const void *data, int len, bool RTCP)
{ {
CriticalSectionScoped cs(&_callbackCritSect);
if (_transportPtr == NULL) if (_transportPtr == NULL)
{ {
return -1; return -1;