aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrent Cook <busterb@gmail.com>2023-07-06 20:32:34 +0300
committerBrent Cook <busterb@gmail.com>2023-07-06 20:32:34 +0300
commitafcd4be8a72abcae003f1760eea407cf3db5e14e (patch)
tree32bcab14ec9ad3fe2923575628356f7a75accbf0
parent4aa76421303aaddbae7da8cf76549d5c0f1419be (diff)
downloadportable-afcd4be8a72abcae003f1760eea407cf3db5e14e.tar.gz
portable-afcd4be8a72abcae003f1760eea407cf3db5e14e.tar.bz2
portable-afcd4be8a72abcae003f1760eea407cf3db5e14e.zip
change socket / file descriptor checks on windows
based on discussion in https://github.com/libressl/portable/issues/266 and https://bugs.python.org/issue23524 adjust the compat layer for Windows to use _get_osfhandle in combination with _set_thread_local_invalid_parameter_handler if applicable to more reliably determine if a handle is a socket, file, or closed socket. This prevents assertions when calling tls_close on an already-closed socket.
-rw-r--r--CMakeLists.txt2
-rw-r--r--crypto/compat/posix_win.c125
2 files changed, 102 insertions, 25 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index b8863c4..02699d0 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -121,7 +121,7 @@ if(WIN32)
121 if(NOT CMAKE_SYSTEM_NAME MATCHES "WindowsStore") 121 if(NOT CMAKE_SYSTEM_NAME MATCHES "WindowsStore")
122 add_definitions(-D_WIN32_WINNT=0x0600) 122 add_definitions(-D_WIN32_WINNT=0x0600)
123 endif() 123 endif()
124 set(PLATFORM_LIBS ${PLATFORM_LIBS} ws2_32 bcrypt) 124 set(PLATFORM_LIBS ${PLATFORM_LIBS} ws2_32 ntdll bcrypt)
125endif() 125endif()
126 126
127if(MSVC) 127if(MSVC)
diff --git a/crypto/compat/posix_win.c b/crypto/compat/posix_win.c
index 30c93cd..cea73e9 100644
--- a/crypto/compat/posix_win.c
+++ b/crypto/compat/posix_win.c
@@ -148,6 +148,61 @@ wsa_errno(int err)
148 return -1; 148 return -1;
149} 149}
150 150
151/*
152 * Employ a similar trick to cpython (pycore_fileutils.h) where the CRT report
153 * handler is disabled while checking if a descriptor is a socket or a file
154 */
155#if defined _MSC_VER && _MSC_VER >= 1900
156
157#include <crtdbg.h>
158#include <stdlib.h>
159
160typedef void (*_invalid_parameter_handler)(
161 const wchar_t * expression,
162 const wchar_t * function,
163 const wchar_t * file,
164 unsigned int line,
165 uintptr_t pReserved
166);
167
168extern _invalid_parameter_handler _set_thread_local_invalid_parameter_handler(
169 _invalid_parameter_handler pNew
170);
171
172static void noop_handler(const wchar_t *expression, const wchar_t *function,
173 const wchar_t *file, unsigned int line, uintptr_t pReserved)
174{
175 return;
176}
177
178#define BEGIN_SUPPRESS_IPH \
179 _invalid_parameter_handler old_handler = _set_thread_local_invalid_parameter_handler(noop_handler)
180#define END_SUPPRESS_IPH \
181 _set_thread_local_invalid_parameter_handler(old_handler)
182
183#else
184
185#define BEGIN_SUPPRESS_IPH
186#define END_SUPPRESS_IPH
187
188#endif
189
190static int
191is_socket(int fd)
192{
193 intptr_t hd;
194
195 BEGIN_SUPPRESS_IPH;
196 hd = _get_osfhandle(fd);
197 END_SUPPRESS_IPH;
198
199 if (hd == (intptr_t)INVALID_HANDLE_VALUE) {
200 return 1; /* fd is not file descriptor */
201 }
202
203 return 0;
204}
205
151int 206int
152posix_connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) 207posix_connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
153{ 208{
@@ -160,24 +215,31 @@ posix_connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
160int 215int
161posix_close(int fd) 216posix_close(int fd)
162{ 217{
163 if (closesocket(fd) == SOCKET_ERROR) { 218 int rc;
164 int err = WSAGetLastError(); 219
165 return (err == WSAENOTSOCK || err == WSAEBADF || 220 if (is_socket(fd)) {
166 err == WSANOTINITIALISED) ? 221 if ((rc = closesocket(fd)) == SOCKET_ERROR) {
167 close(fd) : wsa_errno(err); 222 int err = WSAGetLastError();
223 rc = wsa_errno(err);
224 }
225 } else {
226 rc = close(fd);
168 } 227 }
169 return 0; 228 return rc;
170} 229}
171 230
172ssize_t 231ssize_t
173posix_read(int fd, void *buf, size_t count) 232posix_read(int fd, void *buf, size_t count)
174{ 233{
175 ssize_t rc = recv(fd, buf, count, 0); 234 ssize_t rc;
176 if (rc == SOCKET_ERROR) { 235
177 int err = WSAGetLastError(); 236 if (is_socket(fd)) {
178 return (err == WSAENOTSOCK || err == WSAEBADF || 237 if ((rc = recv(fd, buf, count, 0)) == SOCKET_ERROR) {
179 err == WSANOTINITIALISED) ? 238 int err = WSAGetLastError();
180 read(fd, buf, count) : wsa_errno(err); 239 rc = wsa_errno(err);
240 }
241 } else {
242 rc = read(fd, buf, count);
181 } 243 }
182 return rc; 244 return rc;
183} 245}
@@ -185,12 +247,13 @@ posix_read(int fd, void *buf, size_t count)
185ssize_t 247ssize_t
186posix_write(int fd, const void *buf, size_t count) 248posix_write(int fd, const void *buf, size_t count)
187{ 249{
188 ssize_t rc = send(fd, buf, count, 0); 250 ssize_t rc;
189 if (rc == SOCKET_ERROR) { 251 if (is_socket(fd)) {
190 int err = WSAGetLastError(); 252 if ((rc = send(fd, buf, count, 0)) == SOCKET_ERROR) {
191 return (err == WSAENOTSOCK || err == WSAEBADF || 253 rc = wsa_errno(WSAGetLastError());
192 err == WSANOTINITIALISED) ? 254 }
193 write(fd, buf, count) : wsa_errno(err); 255 } else {
256 rc = write(fd, buf, count);
194 } 257 }
195 return rc; 258 return rc;
196} 259}
@@ -199,17 +262,32 @@ int
199posix_getsockopt(int sockfd, int level, int optname, 262posix_getsockopt(int sockfd, int level, int optname,
200 void *optval, socklen_t *optlen) 263 void *optval, socklen_t *optlen)
201{ 264{
202 int rc = getsockopt(sockfd, level, optname, (char *)optval, optlen); 265 int rc;
203 return rc == 0 ? 0 : wsa_errno(WSAGetLastError()); 266 if (is_socket(sockfd)) {
204 267 rc = getsockopt(sockfd, level, optname, (char *)optval, optlen);
268 if (rc == 0) {
269 rc = wsa_errno(WSAGetLastError());
270 }
271 } else {
272 rc = -1;
273 }
274 return rc;
205} 275}
206 276
207int 277int
208posix_setsockopt(int sockfd, int level, int optname, 278posix_setsockopt(int sockfd, int level, int optname,
209 const void *optval, socklen_t optlen) 279 const void *optval, socklen_t optlen)
210{ 280{
211 int rc = setsockopt(sockfd, level, optname, (char *)optval, optlen); 281 int rc;
212 return rc == 0 ? 0 : wsa_errno(WSAGetLastError()); 282 if (is_socket(sockfd)) {
283 rc = setsockopt(sockfd, level, optname, (char *)optval, optlen);
284 if (rc == 0) {
285 rc = wsa_errno(WSAGetLastError());
286 }
287 } else {
288 rc = -1;
289 }
290 return rc;
213} 291}
214 292
215uid_t getuid(void) 293uid_t getuid(void)
@@ -241,5 +319,4 @@ int gettimeofday(struct timeval * tp, struct timezone * tzp)
241 tp->tv_usec = (long)(system_time.wMilliseconds * 1000); 319 tp->tv_usec = (long)(system_time.wMilliseconds * 1000);
242 return 0; 320 return 0;
243} 321}
244
245#endif 322#endif