Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(32)

Side by Side Diff: net/udp/udp_socket_libevent.cc

Issue 1053873003: Guard socket file descriptor in UDPSocketLibevent (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@close
Patch Set: Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/udp/udp_socket_libevent.h" 5 #include "net/udp/udp_socket_libevent.h"
6 6
7 #include <errno.h> 7 #include <errno.h>
8 #include <fcntl.h> 8 #include <fcntl.h>
9 #include <net/if.h> 9 #include <net/if.h>
10 #include <netdb.h> 10 #include <netdb.h>
(...skipping 10 matching lines...) Expand all
21 #include "base/rand_util.h" 21 #include "base/rand_util.h"
22 #include "net/base/io_buffer.h" 22 #include "net/base/io_buffer.h"
23 #include "net/base/ip_endpoint.h" 23 #include "net/base/ip_endpoint.h"
24 #include "net/base/net_errors.h" 24 #include "net/base/net_errors.h"
25 #include "net/base/net_util.h" 25 #include "net/base/net_util.h"
26 #include "net/base/network_activity_monitor.h" 26 #include "net/base/network_activity_monitor.h"
27 #include "net/log/net_log.h" 27 #include "net/log/net_log.h"
28 #include "net/socket/socket_descriptor.h" 28 #include "net/socket/socket_descriptor.h"
29 #include "net/udp/udp_net_log_parameters.h" 29 #include "net/udp/udp_net_log_parameters.h"
30 30
31 #if defined(OS_MACOSX) && !defined(OS_IOS)
32 // Needed temporarily to debug crbug.com/461246.
33 // TODO(sergeyu): Remove once the bug is resolved.
34 #include <dlfcn.h>
35 #include <pthread.h>
36 #endif // defined(OS_MACOSX) && !defined(OS_IOS)
31 37
32 namespace net { 38 namespace net {
33 39
34 namespace { 40 namespace {
35 41
36 const int kBindRetries = 10; 42 const int kBindRetries = 10;
37 const int kPortStart = 1024; 43 const int kPortStart = 1024;
38 const int kPortEnd = 65535; 44 const int kPortEnd = 65535;
39 45
40 #if defined(OS_MACOSX) 46 #if defined(OS_MACOSX)
(...skipping 10 matching lines...) Expand all
51 return MapSystemError(errno); 57 return MapSystemError(errno);
52 int rv = ioctl(socket, SIOCGIFADDR, &ifr); 58 int rv = ioctl(socket, SIOCGIFADDR, &ifr);
53 if (rv == -1) 59 if (rv == -1)
54 return MapSystemError(errno); 60 return MapSystemError(errno);
55 *address = reinterpret_cast<sockaddr_in*>(&ifr.ifr_addr)->sin_addr.s_addr; 61 *address = reinterpret_cast<sockaddr_in*>(&ifr.ifr_addr)->sin_addr.s_addr;
56 return OK; 62 return OK;
57 } 63 }
58 64
59 #endif // OS_MACOSX 65 #endif // OS_MACOSX
60 66
67 #if defined(OS_MACOSX) && !defined(OS_IOS)
68
69 // On OSX the file descriptor is guarded to detect the cause of
70 // crbug.com/461246. guarded API is supported only on newer versions of OSX,
71 // so the symbols need to be resolved dynamically.
72 // TODO(sergeyu): Removed this code once the bug is resolved.
73
74 typedef uint64_t guardid_t;
75
76 typedef int (*GuardedCloseNpFunction)(int fd, const guardid_t* guard);
77 typedef int (*ChangeFdguardNpFunction)(int fd,
78 const guardid_t* guard,
79 u_int flags,
80 const guardid_t* nguard,
81 u_int nflags,
82 int* fdflagsp);
83
84 GuardedCloseNpFunction g_guarded_close_np = nullptr;
85 ChangeFdguardNpFunction g_change_fdguard_np = nullptr;
86
87 pthread_once_t g_guarded_functions_once = PTHREAD_ONCE_INIT;
88
89 void InitGuardedFunctions() {
90 void* libsystem_handle =
91 dlopen("/usr/lib/libSystem.dylib", RTLD_LAZY | RTLD_LOCAL | RTLD_NOLOAD);
92 if (libsystem_handle) {
93 g_guarded_close_np = reinterpret_cast<GuardedCloseNpFunction>(
94 dlsym(libsystem_handle, "guarded_close_np"));
95 g_change_fdguard_np = reinterpret_cast<ChangeFdguardNpFunction>(
96 dlsym(libsystem_handle, "change_fdguard_np"));
97
98 // If for any reason only one of the functions is found, set both of them to
99 // nullptr.
100 if (!g_guarded_close_np || !g_change_fdguard_np) {
101 g_guarded_close_np = nullptr;
102 g_change_fdguard_np = nullptr;
103 }
104 }
105 }
106
107 int change_fdguard_np(int fd,
108 const guardid_t* guard,
109 u_int flags,
110 const guardid_t* nguard,
111 u_int nflags,
112 int* fdflagsp) {
113 CHECK_EQ(pthread_once(&g_guarded_functions_once, InitGuardedFunctions), 0);
114 // Older version of OSX may not support guarded API.
115 if (!g_change_fdguard_np)
116 return 0;
117 return g_change_fdguard_np(fd, guard, flags, nguard, nflags, fdflagsp);
118 }
119
120 int guarded_close_np(int fd, const guardid_t* guard) {
121 // Older version of OSX may not support guarded API.
122 if (!g_guarded_close_np)
123 return close(fd);
124
125 return g_guarded_close_np(fd, guard);
126 }
127
128 const unsigned int GUARD_CLOSE = 1u << 0;
129 const unsigned int GUARD_DUP = 1u << 1;
130
131 const guardid_t kSocketFdGuard = 0xD712BC0BC9A4EAD4;
132
133 #endif // defined(OS_MACOSX) && !defined(OS_IOS)
134
61 } // namespace 135 } // namespace
62 136
63 UDPSocketLibevent::UDPSocketLibevent( 137 UDPSocketLibevent::UDPSocketLibevent(
64 DatagramSocket::BindType bind_type, 138 DatagramSocket::BindType bind_type,
65 const RandIntCallback& rand_int_cb, 139 const RandIntCallback& rand_int_cb,
66 net::NetLog* net_log, 140 net::NetLog* net_log,
67 const net::NetLog::Source& source) 141 const net::NetLog::Source& source)
68 : socket_(kInvalidSocket), 142 : socket_(kInvalidSocket),
69 addr_family_(0), 143 addr_family_(0),
70 is_connected_(false), 144 is_connected_(false),
(...skipping 20 matching lines...) Expand all
91 } 165 }
92 166
93 int UDPSocketLibevent::Open(AddressFamily address_family) { 167 int UDPSocketLibevent::Open(AddressFamily address_family) {
94 DCHECK(CalledOnValidThread()); 168 DCHECK(CalledOnValidThread());
95 DCHECK_EQ(socket_, kInvalidSocket); 169 DCHECK_EQ(socket_, kInvalidSocket);
96 170
97 addr_family_ = ConvertAddressFamily(address_family); 171 addr_family_ = ConvertAddressFamily(address_family);
98 socket_ = CreatePlatformSocket(addr_family_, SOCK_DGRAM, 0); 172 socket_ = CreatePlatformSocket(addr_family_, SOCK_DGRAM, 0);
99 if (socket_ == kInvalidSocket) 173 if (socket_ == kInvalidSocket)
100 return MapSystemError(errno); 174 return MapSystemError(errno);
175 #if defined(OS_MACOSX) && !defined(OS_IOS)
176 PCHECK(change_fdguard_np(socket_, NULL, 0, &kSocketFdGuard,
177 GUARD_CLOSE | GUARD_DUP, NULL) == 0);
178 #endif // defined(OS_MACOSX) && !defined(OS_IOS)
101 if (SetNonBlocking(socket_)) { 179 if (SetNonBlocking(socket_)) {
102 const int err = MapSystemError(errno); 180 const int err = MapSystemError(errno);
103 Close(); 181 Close();
104 return err; 182 return err;
105 } 183 }
106 return OK; 184 return OK;
107 } 185 }
108 186
109 void UDPSocketLibevent::Close() { 187 void UDPSocketLibevent::Close() {
110 DCHECK(CalledOnValidThread()); 188 DCHECK(CalledOnValidThread());
111 189
112 if (socket_ == kInvalidSocket) 190 if (socket_ == kInvalidSocket)
113 return; 191 return;
114 192
115 // Zero out any pending read/write callback state. 193 // Zero out any pending read/write callback state.
116 read_buf_ = NULL; 194 read_buf_ = NULL;
117 read_buf_len_ = 0; 195 read_buf_len_ = 0;
118 read_callback_.Reset(); 196 read_callback_.Reset();
119 recv_from_address_ = NULL; 197 recv_from_address_ = NULL;
120 write_buf_ = NULL; 198 write_buf_ = NULL;
121 write_buf_len_ = 0; 199 write_buf_len_ = 0;
122 write_callback_.Reset(); 200 write_callback_.Reset();
123 send_to_address_.reset(); 201 send_to_address_.reset();
124 202
125 bool ok = read_socket_watcher_.StopWatchingFileDescriptor(); 203 bool ok = read_socket_watcher_.StopWatchingFileDescriptor();
126 DCHECK(ok); 204 DCHECK(ok);
127 ok = write_socket_watcher_.StopWatchingFileDescriptor(); 205 ok = write_socket_watcher_.StopWatchingFileDescriptor();
128 DCHECK(ok); 206 DCHECK(ok);
129 207
208 #if defined(OS_MACOSX) && !defined(OS_IOS)
209 PCHECK(IGNORE_EINTR(guarded_close_np(socket_, &kSocketFdGuard)) == 0);
210 #else
130 PCHECK(IGNORE_EINTR(close(socket_)) == 0); 211 PCHECK(IGNORE_EINTR(close(socket_)) == 0);
212 #endif // defined(OS_MACOSX) && !defined(OS_IOS)
131 213
132 socket_ = kInvalidSocket; 214 socket_ = kInvalidSocket;
133 addr_family_ = 0; 215 addr_family_ = 0;
134 is_connected_ = false; 216 is_connected_ = false;
135 } 217 }
136 218
137 int UDPSocketLibevent::GetPeerAddress(IPEndPoint* address) const { 219 int UDPSocketLibevent::GetPeerAddress(IPEndPoint* address) const {
138 DCHECK(CalledOnValidThread()); 220 DCHECK(CalledOnValidThread());
139 DCHECK(address); 221 DCHECK(address);
140 if (!is_connected()) 222 if (!is_connected())
(...skipping 603 matching lines...) Expand 10 before | Expand all | Expand 10 after
744 return MapSystemError(errno); 826 return MapSystemError(errno);
745 827
746 return OK; 828 return OK;
747 } 829 }
748 830
749 void UDPSocketLibevent::DetachFromThread() { 831 void UDPSocketLibevent::DetachFromThread() {
750 base::NonThreadSafe::DetachFromThread(); 832 base::NonThreadSafe::DetachFromThread();
751 } 833 }
752 834
753 } // namespace net 835 } // namespace net
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698