Skip to content
This repository was archived by the owner on Oct 25, 2024. It is now read-only.

Commit 2700fba

Browse files
Taylor Brandstetterjianjunz
authored andcommitted
Prevent pointer from being sent in the clear over SCTP.
We were using the address of the SctpTransport object as the sconn_addr field in usrsctp, which is used to get access to the SctpTransport object in various callbacks. However, this address is sent in the clear in the SCTP cookie, which is undesirable. This change uses a monotonically increasing id instead, which is mapped back to a SctpTransport using a SctpTransportMap helper class. Bug: chromium:1076703 Change-Id: Iffb23fdbfa13625e921a9fd5500fe772b4d4015f Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/176422 Reviewed-by: Harald Alvestrand <[email protected]> Reviewed-by: Tommi <[email protected]> Commit-Queue: Taylor <[email protected]> Cr-Commit-Position: refs/heads/master@{#31449}
1 parent 46df1fc commit 2700fba

File tree

2 files changed

+82
-10
lines changed

2 files changed

+82
-10
lines changed

media/sctp/sctp_transport.cc

Lines changed: 77 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ enum PreservedErrno {
2222
#include <stdio.h>
2323

2424
#include <memory>
25+
#include <unordered_map>
2526

2627
#include "absl/algorithm/container.h"
2728
#include "absl/base/attributes.h"
@@ -39,6 +40,7 @@ enum PreservedErrno {
3940
#include "rtc_base/logging.h"
4041
#include "rtc_base/numerics/safe_conversions.h"
4142
#include "rtc_base/string_utils.h"
43+
#include "rtc_base/thread_annotations.h"
4244
#include "rtc_base/thread_checker.h"
4345
#include "rtc_base/trace_event.h"
4446
#include "usrsctplib/usrsctp.h"
@@ -72,6 +74,59 @@ enum PayloadProtocolIdentifier {
7274
PPID_TEXT_LAST = 51
7375
};
7476

77+
// Maps SCTP transport ID to SctpTransport object, necessary in send threshold
78+
// callback and outgoing packet callback.
79+
// TODO(crbug.com/1076703): Remove once the underlying problem is fixed or
80+
// workaround is provided in usrsctp.
81+
class SctpTransportMap {
82+
public:
83+
SctpTransportMap() = default;
84+
85+
// Assigns a new unused ID to the following transport.
86+
uintptr_t Register(cricket::SctpTransport* transport) {
87+
rtc::CritScope cs(&lock_);
88+
// usrsctp_connect fails with a value of 0...
89+
if (next_id_ == 0) {
90+
++next_id_;
91+
}
92+
// In case we've wrapped around and need to find an empty spot from a
93+
// removed transport. Assumes we'll never be full.
94+
while (map_.find(next_id_) != map_.end()) {
95+
++next_id_;
96+
if (next_id_ == 0) {
97+
++next_id_;
98+
}
99+
};
100+
map_[next_id_] = transport;
101+
return next_id_++;
102+
}
103+
104+
// Returns true if found.
105+
bool Deregister(uintptr_t id) {
106+
rtc::CritScope cs(&lock_);
107+
return map_.erase(id) > 0;
108+
}
109+
110+
cricket::SctpTransport* Retrieve(uintptr_t id) const {
111+
rtc::CritScope cs(&lock_);
112+
auto it = map_.find(id);
113+
if (it == map_.end()) {
114+
return nullptr;
115+
}
116+
return it->second;
117+
}
118+
119+
private:
120+
rtc::CriticalSection lock_;
121+
122+
uintptr_t next_id_ RTC_GUARDED_BY(lock_) = 0;
123+
std::unordered_map<uintptr_t, cricket::SctpTransport*> map_
124+
RTC_GUARDED_BY(lock_);
125+
};
126+
127+
// Should only be modified by UsrSctpWrapper.
128+
ABSL_CONST_INIT SctpTransportMap* g_transport_map_ = nullptr;
129+
75130
// Helper for logging SCTP messages.
76131
#if defined(__GNUC__)
77132
__attribute__((__format__(__printf__, 1, 2)))
@@ -242,9 +297,12 @@ class SctpTransport::UsrSctpWrapper {
242297
// Set the number of default outgoing streams. This is the number we'll
243298
// send in the SCTP INIT message.
244299
usrsctp_sysctl_set_sctp_nr_outgoing_streams_default(kMaxSctpStreams);
300+
301+
g_transport_map_ = new SctpTransportMap();
245302
}
246303

247304
static void UninitializeUsrSctp() {
305+
delete g_transport_map_;
248306
RTC_LOG(LS_INFO) << __FUNCTION__;
249307
// usrsctp_finish() may fail if it's called too soon after the transports
250308
// are
@@ -282,7 +340,14 @@ class SctpTransport::UsrSctpWrapper {
282340
size_t length,
283341
uint8_t tos,
284342
uint8_t set_df) {
285-
SctpTransport* transport = static_cast<SctpTransport*>(addr);
343+
SctpTransport* transport =
344+
g_transport_map_->Retrieve(reinterpret_cast<uintptr_t>(addr));
345+
if (!transport) {
346+
RTC_LOG(LS_ERROR)
347+
<< "OnSctpOutboundPacket: Failed to get transport for socket ID "
348+
<< addr;
349+
return EINVAL;
350+
}
286351
RTC_LOG(LS_VERBOSE) << "global OnSctpOutboundPacket():"
287352
"addr: "
288353
<< addr << "; length: " << length
@@ -392,14 +457,14 @@ class SctpTransport::UsrSctpWrapper {
392457
return nullptr;
393458
}
394459
// usrsctp_getladdrs() returns the addresses bound to this socket, which
395-
// contains the SctpTransport* as sconn_addr. Read the pointer,
460+
// contains the SctpTransport id as sconn_addr. Read the id,
396461
// then free the list of addresses once we have the pointer. We only open
397462
// AF_CONN sockets, and they should all have the sconn_addr set to the
398-
// pointer that created them, so [0] is as good as any other.
463+
// id of the transport that created them, so [0] is as good as any other.
399464
struct sockaddr_conn* sconn =
400465
reinterpret_cast<struct sockaddr_conn*>(&addrs[0]);
401-
SctpTransport* transport =
402-
reinterpret_cast<SctpTransport*>(sconn->sconn_addr);
466+
SctpTransport* transport = g_transport_map_->Retrieve(
467+
reinterpret_cast<uintptr_t>(sconn->sconn_addr));
403468
usrsctp_freeladdrs(addrs);
404469

405470
return transport;
@@ -779,9 +844,10 @@ bool SctpTransport::OpenSctpSocket() {
779844
UsrSctpWrapper::DecrementUsrSctpUsageCount();
780845
return false;
781846
}
782-
// Register this class as an address for usrsctp. This is used by SCTP to
847+
id_ = g_transport_map_->Register(this);
848+
// Register our id as an address for usrsctp. This is used by SCTP to
783849
// direct the packets received (by the created socket) to this class.
784-
usrsctp_register_address(this);
850+
usrsctp_register_address(reinterpret_cast<void*>(id_));
785851
return true;
786852
}
787853

@@ -872,7 +938,8 @@ void SctpTransport::CloseSctpSocket() {
872938
// discarded instead of being sent.
873939
usrsctp_close(sock_);
874940
sock_ = nullptr;
875-
usrsctp_deregister_address(this);
941+
usrsctp_deregister_address(reinterpret_cast<void*>(id_));
942+
RTC_CHECK(g_transport_map_->Deregister(id_));
876943
UsrSctpWrapper::DecrementUsrSctpUsageCount();
877944
ready_to_send_data_ = false;
878945
}
@@ -1003,7 +1070,7 @@ void SctpTransport::OnPacketRead(rtc::PacketTransportInternal* transport,
10031070
// will be will be given to the global OnSctpInboundData, and then,
10041071
// marshalled by the AsyncInvoker.
10051072
VerboseLogPacket(data, len, SCTP_DUMP_INBOUND);
1006-
usrsctp_conninput(this, data, len, 0);
1073+
usrsctp_conninput(reinterpret_cast<void*>(id_), data, len, 0);
10071074
} else {
10081075
// TODO(ldixon): Consider caching the packet for very slightly better
10091076
// reliability.
@@ -1033,7 +1100,7 @@ sockaddr_conn SctpTransport::GetSctpSockAddr(int port) {
10331100
#endif
10341101
// Note: conversion from int to uint16_t happens here.
10351102
sconn.sconn_port = rtc::HostToNetwork16(port);
1036-
sconn.sconn_addr = this;
1103+
sconn.sconn_addr = reinterpret_cast<void*>(id_);
10371104
return sconn;
10381105
}
10391106

media/sctp/sctp_transport.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
#include <errno.h>
1515

16+
#include <cstdint>
1617
#include <map>
1718
#include <memory>
1819
#include <set>
@@ -267,6 +268,10 @@ class SctpTransport : public SctpTransportInternal,
267268
absl::optional<int> max_outbound_streams_;
268269
absl::optional<int> max_inbound_streams_;
269270

271+
// Used for associating this transport with the underlying sctp socket in
272+
// various callbacks.
273+
uintptr_t id_ = 0;
274+
270275
RTC_DISALLOW_COPY_AND_ASSIGN(SctpTransport);
271276
};
272277

0 commit comments

Comments
 (0)