Skip to content

Commit 96357ef

Browse files
authored
chore: cherry-pick fix from chromium issue 1076703 (electron#24561)
1 parent 31101c7 commit 96357ef

File tree

2 files changed

+201
-0
lines changed

2 files changed

+201
-0
lines changed

patches/webrtc/.patches

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
fix_vector_allocation_for_raw_data_handling.patch
22
acm_corrected_temporary_buffer_size.patch
3+
backport_1076703.patch
Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2+
From: Cheng Zhao <zcbenz@gmail.com>
3+
Date: Thu, 4 Oct 2018 14:57:02 -0700
4+
Subject: fix: prevent pointer from being sent in the clear over SCTP
5+
6+
[1076703] [High] [CVE-2020-6514]: Security: WebRTC: usrsctp is called with pointer as network address
7+
Backport https://webrtc.googlesource.com/src/+/963cc1ef1336b52ca27742beb28bfbc211ed54d0
8+
9+
diff --git a/media/sctp/sctp_transport.cc b/media/sctp/sctp_transport.cc
10+
index 5b631ffcae51726fb739d034a6530cb7be989ade..3f1e3233654bb7ae9285d066c92167f240e1126c 100644
11+
--- a/media/sctp/sctp_transport.cc
12+
+++ b/media/sctp/sctp_transport.cc
13+
@@ -22,6 +22,7 @@ enum PreservedErrno {
14+
#include <stdio.h>
15+
16+
#include <memory>
17+
+#include <unordered_map>
18+
19+
#include "absl/algorithm/container.h"
20+
#include "absl/types/optional.h"
21+
@@ -38,6 +39,7 @@ enum PreservedErrno {
22+
#include "rtc_base/logging.h"
23+
#include "rtc_base/numerics/safe_conversions.h"
24+
#include "rtc_base/string_utils.h"
25+
+#include "rtc_base/thread_annotations.h"
26+
#include "rtc_base/thread_checker.h"
27+
#include "rtc_base/trace_event.h"
28+
#include "usrsctplib/usrsctp.h"
29+
@@ -71,6 +73,59 @@ enum PayloadProtocolIdentifier {
30+
PPID_TEXT_LAST = 51
31+
};
32+
33+
+// Maps SCTP transport ID to SctpTransport object, necessary in send threshold
34+
+// callback and outgoing packet callback.
35+
+// TODO(crbug.com/1076703): Remove once the underlying problem is fixed or
36+
+// workaround is provided in usrsctp.
37+
+class SctpTransportMap {
38+
+ public:
39+
+ SctpTransportMap() = default;
40+
+
41+
+ // Assigns a new unused ID to the following transport.
42+
+ uintptr_t Register(cricket::SctpTransport* transport) {
43+
+ rtc::CritScope cs(&lock_);
44+
+ // usrsctp_connect fails with a value of 0...
45+
+ if (next_id_ == 0) {
46+
+ ++next_id_;
47+
+ }
48+
+ // In case we've wrapped around and need to find an empty spot from a
49+
+ // removed transport. Assumes we'll never be full.
50+
+ while (map_.find(next_id_) != map_.end()) {
51+
+ ++next_id_;
52+
+ if (next_id_ == 0) {
53+
+ ++next_id_;
54+
+ }
55+
+ };
56+
+ map_[next_id_] = transport;
57+
+ return next_id_++;
58+
+ }
59+
+
60+
+ // Returns true if found.
61+
+ bool Deregister(uintptr_t id) {
62+
+ rtc::CritScope cs(&lock_);
63+
+ return map_.erase(id) > 0;
64+
+ }
65+
+
66+
+ cricket::SctpTransport* Retrieve(uintptr_t id) const {
67+
+ rtc::CritScope cs(&lock_);
68+
+ auto it = map_.find(id);
69+
+ if (it == map_.end()) {
70+
+ return nullptr;
71+
+ }
72+
+ return it->second;
73+
+ }
74+
+
75+
+ private:
76+
+ rtc::CriticalSection lock_;
77+
+
78+
+ uintptr_t next_id_ RTC_GUARDED_BY(lock_) = 0;
79+
+ std::unordered_map<uintptr_t, cricket::SctpTransport*> map_
80+
+ RTC_GUARDED_BY(lock_);
81+
+};
82+
+
83+
+// Should only be modified by UsrSctpWrapper.
84+
+ABSL_CONST_INIT SctpTransportMap* g_transport_map_ = nullptr;
85+
+
86+
// Helper for logging SCTP messages.
87+
#if defined(__GNUC__)
88+
__attribute__((__format__(__printf__, 1, 2)))
89+
@@ -241,9 +296,12 @@ class SctpTransport::UsrSctpWrapper {
90+
// Set the number of default outgoing streams. This is the number we'll
91+
// send in the SCTP INIT message.
92+
usrsctp_sysctl_set_sctp_nr_outgoing_streams_default(kMaxSctpStreams);
93+
+
94+
+ g_transport_map_ = new SctpTransportMap();
95+
}
96+
97+
static void UninitializeUsrSctp() {
98+
+ delete g_transport_map_;
99+
RTC_LOG(LS_INFO) << __FUNCTION__;
100+
// usrsctp_finish() may fail if it's called too soon after the transports
101+
// are
102+
@@ -281,7 +339,14 @@ class SctpTransport::UsrSctpWrapper {
103+
size_t length,
104+
uint8_t tos,
105+
uint8_t set_df) {
106+
- SctpTransport* transport = static_cast<SctpTransport*>(addr);
107+
+ SctpTransport* transport =
108+
+ g_transport_map_->Retrieve(reinterpret_cast<uintptr_t>(addr));
109+
+ if (!transport) {
110+
+ RTC_LOG(LS_ERROR)
111+
+ << "OnSctpOutboundPacket: Failed to get transport for socket ID "
112+
+ << addr;
113+
+ return EINVAL;
114+
+ }
115+
RTC_LOG(LS_VERBOSE) << "global OnSctpOutboundPacket():"
116+
<< "addr: " << addr << "; length: " << length
117+
<< "; tos: " << rtc::ToHex(tos)
118+
@@ -390,14 +455,14 @@ class SctpTransport::UsrSctpWrapper {
119+
return nullptr;
120+
}
121+
// usrsctp_getladdrs() returns the addresses bound to this socket, which
122+
- // contains the SctpTransport* as sconn_addr. Read the pointer,
123+
+ // contains the SctpTransport id as sconn_addr. Read the id,
124+
// then free the list of addresses once we have the pointer. We only open
125+
// AF_CONN sockets, and they should all have the sconn_addr set to the
126+
- // pointer that created them, so [0] is as good as any other.
127+
+ // id of the transport that created them, so [0] is as good as any other.
128+
struct sockaddr_conn* sconn =
129+
reinterpret_cast<struct sockaddr_conn*>(&addrs[0]);
130+
- SctpTransport* transport =
131+
- reinterpret_cast<SctpTransport*>(sconn->sconn_addr);
132+
+ SctpTransport* transport = g_transport_map_->Retrieve(
133+
+ reinterpret_cast<uintptr_t>(sconn->sconn_addr));
134+
usrsctp_freeladdrs(addrs);
135+
136+
return transport;
137+
@@ -751,9 +816,10 @@ bool SctpTransport::OpenSctpSocket() {
138+
UsrSctpWrapper::DecrementUsrSctpUsageCount();
139+
return false;
140+
}
141+
- // Register this class as an address for usrsctp. This is used by SCTP to
142+
+ id_ = g_transport_map_->Register(this);
143+
+ // Register our id as an address for usrsctp. This is used by SCTP to
144+
// direct the packets received (by the created socket) to this class.
145+
- usrsctp_register_address(this);
146+
+ usrsctp_register_address(reinterpret_cast<void*>(id_));
147+
return true;
148+
}
149+
150+
@@ -840,7 +906,8 @@ void SctpTransport::CloseSctpSocket() {
151+
// discarded instead of being sent.
152+
usrsctp_close(sock_);
153+
sock_ = nullptr;
154+
- usrsctp_deregister_address(this);
155+
+ usrsctp_deregister_address(reinterpret_cast<void*>(id_));
156+
+ RTC_CHECK(g_transport_map_->Deregister(id_));
157+
UsrSctpWrapper::DecrementUsrSctpUsageCount();
158+
ready_to_send_data_ = false;
159+
}
160+
@@ -969,7 +1036,7 @@ void SctpTransport::OnPacketRead(rtc::PacketTransportInternal* transport,
161+
// will be will be given to the global OnSctpInboundData, and then,
162+
// marshalled by the AsyncInvoker.
163+
VerboseLogPacket(data, len, SCTP_DUMP_INBOUND);
164+
- usrsctp_conninput(this, data, len, 0);
165+
+ usrsctp_conninput(reinterpret_cast<void*>(id_), data, len, 0);
166+
} else {
167+
// TODO(ldixon): Consider caching the packet for very slightly better
168+
// reliability.
169+
@@ -995,7 +1062,7 @@ sockaddr_conn SctpTransport::GetSctpSockAddr(int port) {
170+
#endif
171+
// Note: conversion from int to uint16_t happens here.
172+
sconn.sconn_port = rtc::HostToNetwork16(port);
173+
- sconn.sconn_addr = this;
174+
+ sconn.sconn_addr = reinterpret_cast<void*>(id_);
175+
return sconn;
176+
}
177+
178+
diff --git a/media/sctp/sctp_transport.h b/media/sctp/sctp_transport.h
179+
index 7337f0103309bbd00d57e805449585ec48720c75..63d8a036deed2057cb367b01418bf1229f851dcb 100644
180+
--- a/media/sctp/sctp_transport.h
181+
+++ b/media/sctp/sctp_transport.h
182+
@@ -13,6 +13,7 @@
183+
184+
#include <errno.h>
185+
186+
+#include <cstdint>
187+
#include <map>
188+
#include <memory>
189+
#include <set>
190+
@@ -266,6 +267,10 @@ class SctpTransport : public SctpTransportInternal,
191+
absl::optional<int> max_outbound_streams_;
192+
absl::optional<int> max_inbound_streams_;
193+
194+
+ // Used for associating this transport with the underlying sctp socket in
195+
+ // various callbacks.
196+
+ uintptr_t id_ = 0;
197+
+
198+
RTC_DISALLOW_COPY_AND_ASSIGN(SctpTransport);
199+
};
200+

0 commit comments

Comments
 (0)