wakeup_write: make sure the eventfd write sends eight bytes

The eventfd manpage says:

  A write(2) fails with the error EINVAL if the size of the supplied
  buffer is less than 8 bytes

When doing x32 on a 64-bit system, pointers are still four bytes so this
code must not use the size of a pointer but the size of a 64-bit type.

Fixes #16237
Reported-by: Jan Engelhardt
Closes #16239
This commit is contained in:
Daniel Stenberg 2025-02-07 14:57:36 +01:00
parent c012c6062e
commit c2aa504ab9
No known key found for this signature in database
GPG Key ID: 5CC908FDB71E12C2
2 changed files with 9 additions and 27 deletions

View File

@ -282,14 +282,6 @@ CURL_STDCALL getaddrinfo_thread(void *arg)
struct thread_data *td = tsd->td; struct thread_data *td = tsd->td;
char service[12]; char service[12];
int rc; int rc;
#ifndef CURL_DISABLE_SOCKETPAIR
#ifdef USE_EVENTFD
const void *buf;
const uint64_t val = 1;
#else
char buf[1];
#endif
#endif
msnprintf(service, sizeof(service), "%d", tsd->port); msnprintf(service, sizeof(service), "%d", tsd->port);
@ -315,9 +307,9 @@ CURL_STDCALL getaddrinfo_thread(void *arg)
#ifndef CURL_DISABLE_SOCKETPAIR #ifndef CURL_DISABLE_SOCKETPAIR
if(tsd->sock_pair[1] != CURL_SOCKET_BAD) { if(tsd->sock_pair[1] != CURL_SOCKET_BAD) {
#ifdef USE_EVENTFD #ifdef USE_EVENTFD
buf = &val; const uint64_t buf[1] = { 1 };
#else #else
buf[0] = 1; const char buf[1] = { 1 };
#endif #endif
/* DNS has been resolved, signal client task */ /* DNS has been resolved, signal client task */
if(wakeup_write(tsd->sock_pair[1], buf, sizeof(buf)) < 0) { if(wakeup_write(tsd->sock_pair[1], buf, sizeof(buf)) < 0) {

View File

@ -1538,15 +1538,6 @@ CURLMcode curl_multi_wakeup(CURLM *m)
Curl_multi struct that are constant */ Curl_multi struct that are constant */
struct Curl_multi *multi = m; struct Curl_multi *multi = m;
#if defined(ENABLE_WAKEUP) && !defined(USE_WINSOCK)
#ifdef USE_EVENTFD
const void *buf;
const uint64_t val = 1;
#else
char buf[1];
#endif
#endif
/* GOOD_MULTI_HANDLE can be safely called */ /* GOOD_MULTI_HANDLE can be safely called */
if(!GOOD_MULTI_HANDLE(multi)) if(!GOOD_MULTI_HANDLE(multi))
return CURLM_BAD_HANDLE; return CURLM_BAD_HANDLE;
@ -1560,15 +1551,14 @@ CURLMcode curl_multi_wakeup(CURLM *m)
making it safe to access from another thread after the init part making it safe to access from another thread after the init part
and before cleanup */ and before cleanup */
if(multi->wakeup_pair[1] != CURL_SOCKET_BAD) { if(multi->wakeup_pair[1] != CURL_SOCKET_BAD) {
#ifdef USE_EVENTFD
buf = &val;
/* eventfd has a stringent rule of requiring the 8-byte buffer when
calling write(2) on it, which makes the sizeof(buf) below fine since
this is only used on 64-bit systems and then the pointer is 64-bit */
#else
buf[0] = 1;
#endif
while(1) { while(1) {
#ifdef USE_EVENTFD
/* eventfd has a stringent rule of requiring the 8-byte buffer when
calling write(2) on it */
const uint64_t buf[1] = { 1 };
#else
const char buf[1] = { 1 };
#endif
/* swrite() is not thread-safe in general, because concurrent calls /* swrite() is not thread-safe in general, because concurrent calls
can have their messages interleaved, but in this case the content can have their messages interleaved, but in this case the content
of the messages does not matter, which makes it ok to call. of the messages does not matter, which makes it ok to call.