backport_1076703.patch 7.3 KB

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