RHEL-129723 CVE-2025-58436 cups: Slow client communication leads to a possible DoS attack

Resolves: RHEL-129723
This commit is contained in:
Zdenek Dohnal 2025-12-04 14:24:57 +01:00
parent 8801af4d7f
commit cec3bbab49
4 changed files with 682 additions and 1 deletions

View File

@ -0,0 +1,26 @@
From 2dc021f33a3ea358c9f5c5c54643adc4c46a84a1 Mon Sep 17 00:00:00 2001
From: Michael R Sweet <msweet@msweet.org>
Date: Wed, 3 Dec 2025 07:25:30 -0500
Subject: [PATCH] Fix an infinite loop issue in GTK+ (Issue #1439)
---
CHANGES.md | 1 +
cups/http.c | 2 +-
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/cups/http.c b/cups/http.c
index 214e45158..31ed6ddc1 100644
--- a/cups/http.c
+++ b/cups/http.c
@@ -2779,7 +2779,7 @@ _httpUpdate(http_t *http, /* I - HTTP connection */
/* See whether our read buffer is full... */
DEBUG_printf(("2_httpUpdate: used=%d", http->used));
- if (http->used > 0 && !memchr(http->buffer, '\n', (size_t)http->used) && (size_t)http->used < sizeof(http->buffer))
+ if (http->used < sizeof(http->buffer))
{
/* No, try filling in more data... */
if ((bytes = http_read(http, http->buffer + http->used, sizeof(http->buffer) - (size_t)http->used, /*timeout*/0)) > 0)
--
2.52.0

View File

@ -0,0 +1,12 @@
diff -up cups-2.4.10/cups/http.c.use-usessl cups-2.4.10/cups/http.c
--- cups-2.4.10/cups/http.c.use-usessl 2024-06-18 13:11:05.000000000 +0200
+++ cups-2.4.10/cups/http.c 2025-12-04 14:23:30.019246588 +0100
@@ -3033,7 +3033,7 @@ _httpWait(http_t *http, /* I - HTTP co
*/
#ifdef HAVE_TLS
- if (http->tls && _httpTLSPending(http))
+ if (usessl && http->tls && _httpTLSPending(http))
{
DEBUG_puts("5_httpWait: Return 1 since there is pending TLS data.");
return (1);

629
cups-CVE-2025-58436.patch Normal file
View File

@ -0,0 +1,629 @@
From baec1278966eb8d7fcf12578f0835cba56d0e249 Mon Sep 17 00:00:00 2001
From: Zdenek Dohnal <zdohnal@redhat.com>
Date: Mon, 13 Oct 2025 10:16:48 +0200
Subject: [PATCH] Fix unresponsive cupsd process caused by a slow client
If client is very slow, it will slow cupsd process for other clients.
The fix is the best effort without turning scheduler cupsd into
multithreaded process which would be too complex and error-prone when
backporting to 2.4.x series.
The fix for unencrypted communication is to follow up on communication
only if there is the whole line on input, and the waiting time is
guarded by timeout.
Encrypted communication now starts after we have the whole client hello
packet, which conflicts with optional upgrade support to HTTPS via
methods other than method OPTIONS, so this optional support defined in
RFC 2817, section 3.1 is removed. Too slow or incomplete requests are
handled by connection timeout.
Fixes CVE-2025-58436
---
cups/http-private.h | 7 +-
cups/http.c | 80 +++++++++++++-------
cups/tls-openssl.c | 15 +++-
scheduler/client.c | 178 ++++++++++++++++++++++++++++----------------
scheduler/client.h | 3 +
scheduler/select.c | 12 +++
6 files changed, 198 insertions(+), 97 deletions(-)
diff --git a/cups/http-private.h b/cups/http-private.h
index d9854faed..2d9035032 100644
--- a/cups/http-private.h
+++ b/cups/http-private.h
@@ -121,6 +121,7 @@ extern "C" {
* Constants...
*/
+# define _HTTP_MAX_BUFFER 32768 /* Size of read buffer */
# define _HTTP_MAX_SBUFFER 65536 /* Size of (de)compression buffer */
# define _HTTP_RESOLVE_DEFAULT 0 /* Just resolve with default options */
# define _HTTP_RESOLVE_STDERR 1 /* Log resolve progress to stderr */
@@ -233,8 +234,8 @@ struct _http_s /**** HTTP connection structure ****/
http_encoding_t data_encoding; /* Chunked or not */
int _data_remaining;/* Number of bytes left (deprecated) */
int used; /* Number of bytes used in buffer */
- char buffer[HTTP_MAX_BUFFER];
- /* Buffer for incoming data */
+ char _buffer[HTTP_MAX_BUFFER];
+ /* Old read buffer (deprecated) */
int _auth_type; /* Authentication in use (deprecated) */
unsigned char _md5_state[88]; /* MD5 state (deprecated) */
char nonce[HTTP_MAX_VALUE];
@@ -308,6 +309,8 @@ struct _http_s /**** HTTP connection structure ****/
/* Allocated field values */
*default_fields[HTTP_FIELD_MAX];
/* Default field values, if any */
+ char buffer[_HTTP_MAX_BUFFER];
+ /* Read buffer */
};
# endif /* !_HTTP_NO_PRIVATE */
diff --git a/cups/http.c b/cups/http.c
index 7a42cb3d6..214e45158 100644
--- a/cups/http.c
+++ b/cups/http.c
@@ -53,7 +53,7 @@ static http_t *http_create(const char *host, int port,
static void http_debug_hex(const char *prefix, const char *buffer,
int bytes);
#endif /* DEBUG */
-static ssize_t http_read(http_t *http, char *buffer, size_t length);
+static ssize_t http_read(http_t *http, char *buffer, size_t length, int timeout);
static ssize_t http_read_buffered(http_t *http, char *buffer, size_t length);
static ssize_t http_read_chunk(http_t *http, char *buffer, size_t length);
static int http_send(http_t *http, http_state_t request,
@@ -1206,7 +1206,7 @@ httpGets(char *line, /* I - Line to read into */
return (NULL);
}
- bytes = http_read(http, http->buffer + http->used, (size_t)(HTTP_MAX_BUFFER - http->used));
+ bytes = http_read(http, http->buffer + http->used, (size_t)(_HTTP_MAX_BUFFER - http->used), http->wait_value);
DEBUG_printf(("4httpGets: read " CUPS_LLFMT " bytes.", CUPS_LLCAST bytes));
@@ -1726,24 +1726,13 @@ httpPeek(http_t *http, /* I - HTTP connection */
ssize_t buflen; /* Length of read for buffer */
- if (!http->blocking)
- {
- while (!httpWait(http, http->wait_value))
- {
- if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data))
- continue;
-
- return (0);
- }
- }
-
if ((size_t)http->data_remaining > sizeof(http->buffer))
buflen = sizeof(http->buffer);
else
buflen = (ssize_t)http->data_remaining;
DEBUG_printf(("2httpPeek: Reading %d bytes into buffer.", (int)buflen));
- bytes = http_read(http, http->buffer, (size_t)buflen);
+ bytes = http_read(http, http->buffer, (size_t)buflen, http->wait_value);
DEBUG_printf(("2httpPeek: Read " CUPS_LLFMT " bytes into buffer.",
CUPS_LLCAST bytes));
@@ -1764,9 +1753,9 @@ httpPeek(http_t *http, /* I - HTTP connection */
int zerr; /* Decompressor error */
z_stream stream; /* Copy of decompressor stream */
- if (http->used > 0 && ((z_stream *)http->stream)->avail_in < HTTP_MAX_BUFFER)
+ if (http->used > 0 && ((z_stream *)http->stream)->avail_in < _HTTP_MAX_BUFFER)
{
- size_t buflen = HTTP_MAX_BUFFER - ((z_stream *)http->stream)->avail_in;
+ size_t buflen = _HTTP_MAX_BUFFER - ((z_stream *)http->stream)->avail_in;
/* Number of bytes to copy */
if (((z_stream *)http->stream)->avail_in > 0 &&
@@ -2024,7 +2013,7 @@ httpRead2(http_t *http, /* I - HTTP connection */
if (bytes == 0)
{
- ssize_t buflen = HTTP_MAX_BUFFER - (ssize_t)((z_stream *)http->stream)->avail_in;
+ ssize_t buflen = _HTTP_MAX_BUFFER - (ssize_t)((z_stream *)http->stream)->avail_in;
/* Additional bytes for buffer */
if (buflen > 0)
@@ -2774,7 +2763,7 @@ int /* O - 1 to continue, 0 to stop */
_httpUpdate(http_t *http, /* I - HTTP connection */
http_status_t *status) /* O - Current HTTP status */
{
- char line[32768], /* Line from connection... */
+ char line[_HTTP_MAX_BUFFER], /* Line from connection... */
*value; /* Pointer to value on line */
http_field_t field; /* Field index */
int major, minor; /* HTTP version numbers */
@@ -2782,12 +2771,46 @@ _httpUpdate(http_t *http, /* I - HTTP connection */
DEBUG_printf(("_httpUpdate(http=%p, status=%p), state=%s", (void *)http, (void *)status, httpStateString(http->state)));
+ /* When doing non-blocking I/O, make sure we have a whole line... */
+ if (!http->blocking)
+ {
+ ssize_t bytes; /* Bytes "peeked" from connection */
+
+ /* See whether our read buffer is full... */
+ DEBUG_printf(("2_httpUpdate: used=%d", http->used));
+
+ if (http->used > 0 && !memchr(http->buffer, '\n', (size_t)http->used) && (size_t)http->used < sizeof(http->buffer))
+ {
+ /* No, try filling in more data... */
+ if ((bytes = http_read(http, http->buffer + http->used, sizeof(http->buffer) - (size_t)http->used, /*timeout*/0)) > 0)
+ {
+ DEBUG_printf(("2_httpUpdate: Read %d bytes.", (int)bytes));
+ http->used += (int)bytes;
+ }
+ }
+
+ /* Peek at the incoming data... */
+ if (!http->used || !memchr(http->buffer, '\n', (size_t)http->used))
+ {
+ /* Don't have a full line, tell the reader to try again when there is more data... */
+ DEBUG_puts("1_htttpUpdate: No newline in buffer yet.");
+ if ((size_t)http->used == sizeof(http->buffer))
+ *status = HTTP_STATUS_ERROR;
+ else
+ *status = HTTP_STATUS_CONTINUE;
+ return (0);
+ }
+
+ DEBUG_puts("2_httpUpdate: Found newline in buffer.");
+ }
+
/*
* Grab a single line from the connection...
*/
if (!httpGets(line, sizeof(line), http))
{
+ DEBUG_puts("1_httpUpdate: Error reading request line.");
*status = HTTP_STATUS_ERROR;
return (0);
}
@@ -4140,7 +4163,8 @@ http_debug_hex(const char *prefix, /* I - Prefix for line */
static ssize_t /* O - Number of bytes read or -1 on error */
http_read(http_t *http, /* I - HTTP connection */
char *buffer, /* I - Buffer */
- size_t length) /* I - Maximum bytes to read */
+ size_t length, /* I - Maximum bytes to read */
+ int timeout) /* I - Wait timeout */
{
ssize_t bytes; /* Bytes read */
@@ -4149,7 +4173,7 @@ http_read(http_t *http, /* I - HTTP connection */
if (!http->blocking || http->timeout_value > 0.0)
{
- while (!httpWait(http, http->wait_value))
+ while (!_httpWait(http, timeout, 1))
{
if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data))
continue;
@@ -4252,7 +4276,7 @@ http_read_buffered(http_t *http, /* I - HTTP connection */
else
bytes = (ssize_t)length;
- DEBUG_printf(("8http_read: Grabbing %d bytes from input buffer.",
+ DEBUG_printf(("8http_read_buffered: Grabbing %d bytes from input buffer.",
(int)bytes));
memcpy(buffer, http->buffer, (size_t)bytes);
@@ -4262,7 +4286,7 @@ http_read_buffered(http_t *http, /* I - HTTP connection */
memmove(http->buffer, http->buffer + bytes, (size_t)http->used);
}
else
- bytes = http_read(http, buffer, length);
+ bytes = http_read(http, buffer, length, http->wait_value);
return (bytes);
}
@@ -4603,15 +4627,15 @@ http_set_timeout(int fd, /* I - File descriptor */
static void
http_set_wait(http_t *http) /* I - HTTP connection */
{
- if (http->blocking)
- {
- http->wait_value = (int)(http->timeout_value * 1000);
+ http->wait_value = (int)(http->timeout_value * 1000);
- if (http->wait_value <= 0)
+ if (http->wait_value <= 0)
+ {
+ if (http->blocking)
http->wait_value = 60000;
+ else
+ http->wait_value = 1000;
}
- else
- http->wait_value = 10000;
}
diff --git a/cups/tls-openssl.c b/cups/tls-openssl.c
index 9fcbe0af3..f746f4cba 100644
--- a/cups/tls-openssl.c
+++ b/cups/tls-openssl.c
@@ -215,12 +215,14 @@ cupsMakeServerCredentials(
// Save them...
if ((bio = BIO_new_file(keyfile, "wb")) == NULL)
{
+ DEBUG_printf(("1cupsMakeServerCredentials: Unable to create private key file '%s': %s", keyfile, strerror(errno)));
_cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(errno), 0);
goto done;
}
if (!PEM_write_bio_PrivateKey(bio, pkey, NULL, NULL, 0, NULL, NULL))
{
+ DEBUG_puts("1cupsMakeServerCredentials: PEM_write_bio_PrivateKey failed.");
_cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Unable to write private key."), 1);
BIO_free(bio);
goto done;
@@ -230,12 +232,14 @@ cupsMakeServerCredentials(
if ((bio = BIO_new_file(crtfile, "wb")) == NULL)
{
+ DEBUG_printf(("1cupsMakeServerCredentials: Unable to create certificate file '%s': %s", crtfile, strerror(errno)));
_cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(errno), 0);
goto done;
}
if (!PEM_write_bio_X509(bio, cert))
{
+ DEBUG_puts("1cupsMakeServerCredentials: PEM_write_bio_X509 failed.");
_cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Unable to write X.509 certificate."), 1);
BIO_free(bio);
goto done;
@@ -1082,10 +1086,10 @@ _httpTLSStart(http_t *http) // I - Connection to server
if (!cupsMakeServerCredentials(tls_keypath, cn, 0, NULL, time(NULL) + 3650 * 86400))
{
- DEBUG_puts("4_httpTLSStart: cupsMakeServerCredentials failed.");
+ DEBUG_printf(("4_httpTLSStart: cupsMakeServerCredentials failed: %s", cupsLastErrorString()));
http->error = errno = EINVAL;
http->status = HTTP_STATUS_ERROR;
- _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Unable to create server credentials."), 1);
+// _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Unable to create server credentials."), 1);
SSL_CTX_free(context);
_cupsMutexUnlock(&tls_mutex);
@@ -1346,14 +1350,17 @@ http_bio_read(BIO *h, // I - BIO data
http = (http_t *)BIO_get_data(h);
- if (!http->blocking)
+ if (!http->blocking || http->timeout_value > 0.0)
{
/*
* Make sure we have data before we read...
*/
- if (!_httpWait(http, 10000, 0))
+ while (!_httpWait(http, http->wait_value, 0))
{
+ if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data))
+ continue;
+
#ifdef WIN32
http->error = WSAETIMEDOUT;
#else
diff --git a/scheduler/client.c b/scheduler/client.c
index f0349a6c9..9593c9138 100644
--- a/scheduler/client.c
+++ b/scheduler/client.c
@@ -34,11 +34,11 @@
static int check_if_modified(cupsd_client_t *con,
struct stat *filestats);
-static int compare_clients(cupsd_client_t *a, cupsd_client_t *b,
- void *data);
#ifdef HAVE_TLS
-static int cupsd_start_tls(cupsd_client_t *con, http_encryption_t e);
+static int check_start_tls(cupsd_client_t *con);
#endif /* HAVE_TLS */
+static int compare_clients(cupsd_client_t *a, cupsd_client_t *b,
+ void *data);
static char *get_file(cupsd_client_t *con, struct stat *filestats,
char *filename, size_t len);
static http_status_t install_cupsd_conf(cupsd_client_t *con);
@@ -367,14 +367,20 @@ cupsdAcceptClient(cupsd_listener_t *lis)/* I - Listener socket */
if (lis->encryption == HTTP_ENCRYPTION_ALWAYS)
{
/*
- * https connection; go secure...
+ * HTTPS connection, force TLS negotiation...
*/
- if (cupsd_start_tls(con, HTTP_ENCRYPTION_ALWAYS))
- cupsdCloseClient(con);
+ con->tls_start = time(NULL);
+ con->encryption = HTTP_ENCRYPTION_ALWAYS;
}
else
+ {
+ /*
+ * HTTP connection, but check for HTTPS negotiation on first data...
+ */
+
con->auto_ssl = 1;
+ }
#endif /* HAVE_TLS */
}
@@ -613,17 +619,46 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */
con->auto_ssl = 0;
- if (recv(httpGetFd(con->http), buf, 1, MSG_PEEK) == 1 &&
- (!buf[0] || !strchr("DGHOPT", buf[0])))
+ if (recv(httpGetFd(con->http), buf, 5, MSG_PEEK) == 5 && buf[0] == 0x16 && buf[1] == 3 && buf[2])
{
/*
- * Encrypt this connection...
+ * Client hello record, encrypt this connection...
*/
- cupsdLogClient(con, CUPSD_LOG_DEBUG2, "Saw first byte %02X, auto-negotiating SSL/TLS session.", buf[0] & 255);
+ cupsdLogClient(con, CUPSD_LOG_DEBUG2, "Saw client hello record, auto-negotiating TLS session.");
+ con->tls_start = time(NULL);
+ con->encryption = HTTP_ENCRYPTION_ALWAYS;
+ }
+ }
- if (cupsd_start_tls(con, HTTP_ENCRYPTION_ALWAYS))
- cupsdCloseClient(con);
+ if (con->tls_start)
+ {
+ /*
+ * Try negotiating TLS...
+ */
+
+ int tls_status = check_start_tls(con);
+
+ if (tls_status < 0)
+ {
+ /*
+ * TLS negotiation failed, close the connection.
+ */
+
+ cupsdCloseClient(con);
+ return;
+ }
+ else if (tls_status == 0)
+ {
+ /*
+ * Nothing to do yet...
+ */
+
+ if ((time(NULL) - con->tls_start) > 5)
+ {
+ // Timeout, close the connection...
+ cupsdCloseClient(con);
+ }
return;
}
@@ -787,9 +822,7 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */
* Parse incoming parameters until the status changes...
*/
- while ((status = httpUpdate(con->http)) == HTTP_STATUS_CONTINUE)
- if (!httpGetReady(con->http))
- break;
+ status = httpUpdate(con->http);
if (status != HTTP_STATUS_OK && status != HTTP_STATUS_CONTINUE)
{
@@ -951,11 +984,10 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */
return;
}
- if (cupsd_start_tls(con, HTTP_ENCRYPTION_REQUIRED))
- {
- cupsdCloseClient(con);
- return;
- }
+ con->tls_start = time(NULL);
+ con->tls_upgrade = 1;
+ con->encryption = HTTP_ENCRYPTION_REQUIRED;
+ return;
#else
if (!cupsdSendError(con, HTTP_STATUS_NOT_IMPLEMENTED, CUPSD_AUTH_NONE))
{
@@ -994,32 +1026,11 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */
if (!_cups_strcasecmp(httpGetField(con->http, HTTP_FIELD_CONNECTION),
"Upgrade") && !httpIsEncrypted(con->http))
{
-#ifdef HAVE_TLS
- /*
- * Do encryption stuff...
- */
-
- httpClearFields(con->http);
-
- if (!cupsdSendHeader(con, HTTP_STATUS_SWITCHING_PROTOCOLS, NULL,
- CUPSD_AUTH_NONE))
- {
- cupsdCloseClient(con);
- return;
- }
-
- if (cupsd_start_tls(con, HTTP_ENCRYPTION_REQUIRED))
- {
- cupsdCloseClient(con);
- return;
- }
-#else
if (!cupsdSendError(con, HTTP_STATUS_NOT_IMPLEMENTED, CUPSD_AUTH_NONE))
{
cupsdCloseClient(con);
return;
}
-#endif /* HAVE_TLS */
}
if ((status = cupsdIsAuthorized(con, NULL)) != HTTP_STATUS_OK)
@@ -2689,6 +2700,69 @@ check_if_modified(
}
+#ifdef HAVE_TLS
+/*
+ * 'check_start_tls()' - Start encryption on a connection.
+ */
+
+static int /* O - 0 to continue, 1 on success, -1 on error */
+check_start_tls(cupsd_client_t *con) /* I - Client connection */
+{
+ unsigned char chello[4096]; /* Client hello record */
+ ssize_t chello_bytes; /* Bytes read/peeked */
+ int chello_len; /* Length of record */
+
+
+ /*
+ * See if we have a good and complete client hello record...
+ */
+
+ if ((chello_bytes = recv(httpGetFd(con->http), (char *)chello, sizeof(chello), MSG_PEEK)) < 5)
+ return (0); /* Not enough bytes (yet) */
+
+ if (chello[0] != 0x016 || chello[1] != 3 || chello[2] == 0)
+ return (-1); /* Not a TLS Client Hello record */
+
+ chello_len = (chello[3] << 8) | chello[4];
+
+ if ((chello_len + 5) > chello_bytes)
+ return (0); /* Not enough bytes yet */
+
+ /*
+ * OK, we do, try negotiating...
+ */
+
+ con->tls_start = 0;
+
+ if (httpEncryption(con->http, con->encryption))
+ {
+ cupsdLogClient(con, CUPSD_LOG_ERROR, "Unable to encrypt connection: %s", cupsLastErrorString());
+ return (-1);
+ }
+
+ cupsdLogClient(con, CUPSD_LOG_DEBUG, "Connection now encrypted.");
+
+ if (con->tls_upgrade)
+ {
+ // Respond to the original OPTIONS command...
+ con->tls_upgrade = 0;
+
+ httpClearFields(con->http);
+ httpClearCookie(con->http);
+ httpSetField(con->http, HTTP_FIELD_CONTENT_LENGTH, "0");
+
+ if (!cupsdSendHeader(con, HTTP_STATUS_OK, NULL, CUPSD_AUTH_NONE))
+ {
+ cupsdCloseClient(con);
+ return (-1);
+ }
+ }
+
+ return (1);
+}
+#endif /* HAVE_TLS */
+
+
/*
* 'compare_clients()' - Compare two client connections.
*/
@@ -2709,28 +2783,6 @@ compare_clients(cupsd_client_t *a, /* I - First client */
}
-#ifdef HAVE_TLS
-/*
- * 'cupsd_start_tls()' - Start encryption on a connection.
- */
-
-static int /* O - 0 on success, -1 on error */
-cupsd_start_tls(cupsd_client_t *con, /* I - Client connection */
- http_encryption_t e) /* I - Encryption mode */
-{
- if (httpEncryption(con->http, e))
- {
- cupsdLogClient(con, CUPSD_LOG_ERROR, "Unable to encrypt connection: %s",
- cupsLastErrorString());
- return (-1);
- }
-
- cupsdLogClient(con, CUPSD_LOG_DEBUG, "Connection now encrypted.");
- return (0);
-}
-#endif /* HAVE_TLS */
-
-
/*
* 'get_file()' - Get a filename and state info.
*/
diff --git a/scheduler/client.h b/scheduler/client.h
index 9fe4e2ea6..2939ce997 100644
--- a/scheduler/client.h
+++ b/scheduler/client.h
@@ -53,6 +53,9 @@ struct cupsd_client_s
cups_lang_t *language; /* Language to use */
#ifdef HAVE_TLS
int auto_ssl; /* Automatic test for SSL/TLS */
+ time_t tls_start; /* Do TLS negotiation? */
+ int tls_upgrade; /* Doing TLS upgrade via OPTIONS? */
+ http_encryption_t encryption; /* Type of TLS negotiation */
#endif /* HAVE_TLS */
http_addr_t clientaddr; /* Client's server address */
char clientname[256];/* Client's server name for connection */
diff --git a/scheduler/select.c b/scheduler/select.c
index 2e64f2a7e..ac6205c51 100644
--- a/scheduler/select.c
+++ b/scheduler/select.c
@@ -408,6 +408,9 @@ cupsdDoSelect(long timeout) /* I - Timeout in seconds */
cupsd_in_select = 1;
+ // Prevent 100% CPU by releasing control before the kevent call...
+ usleep(1);
+
if (timeout >= 0 && timeout < 86400)
{
ktimeout.tv_sec = timeout;
@@ -452,6 +455,9 @@ cupsdDoSelect(long timeout) /* I - Timeout in seconds */
struct epoll_event *event; /* Current event */
+ // Prevent 100% CPU by releasing control before the epoll_wait call...
+ usleep(1);
+
if (timeout >= 0 && timeout < 86400)
nfds = epoll_wait(cupsd_epoll_fd, cupsd_epoll_events, MaxFDs,
timeout * 1000);
@@ -544,6 +550,9 @@ cupsdDoSelect(long timeout) /* I - Timeout in seconds */
}
}
+ // Prevent 100% CPU by releasing control before the poll call...
+ usleep(1);
+
if (timeout >= 0 && timeout < 86400)
nfds = poll(cupsd_pollfds, (nfds_t)count, timeout * 1000);
else
@@ -597,6 +606,9 @@ cupsdDoSelect(long timeout) /* I - Timeout in seconds */
cupsd_current_input = cupsd_global_input;
cupsd_current_output = cupsd_global_output;
+ // Prevent 100% CPU by releasing control before the select call...
+ usleep(1);
+
if (timeout >= 0 && timeout < 86400)
{
stimeout.tv_sec = timeout;
--
2.51.1

View File

@ -22,7 +22,7 @@ Summary: CUPS printing system
Name: cups
Epoch: 1
Version: 2.4.10
Release: 14%{?dist}
Release: 15%{?dist}
# backend/failover.c - BSD-3-Clause
# cups/md5* - Zlib
# scheduler/colorman.c - Apache-2.0 WITH LLVM-exception AND BSD-2-Clause
@ -112,6 +112,13 @@ Patch1015: CVE-2025-58364.patch
# RHEL-108945 The KONICA MINOLTA C352 is not distributed using cups-browsed and the included ppd file
# https://github.com/OpenPrinting/cups/commit/c0b8e481250445
Patch1016: 0001-Drop-non-keyword-characters-from-PPD-names-Issue-111.patch
# RHEL-129723 CVE-2025-58436 cups: Slow client communication leads to a possible DoS attack
# 0001-_httpWait-s-usessl-parameter-wasn-t-being-used.patch
# cups-CVE-2025-58436.patch
# 0001-Fix-an-infinite-loop-issue-in-GTK-Issue-1439.patch
Patch1017: 0001-_httpWait-s-usessl-parameter-wasn-t-being-used.patch
Patch1018: cups-CVE-2025-58436.patch
Patch1019: 0001-Fix-an-infinite-loop-issue-in-GTK-Issue-1439.patch
##### Patches removed because IMHO they aren't no longer needed
@ -377,6 +384,10 @@ to CUPS daemon. This solution will substitute printer drivers and raw queues in
%patch -P 1015 -p1 -b .cve-2025-58364
# drop nonIPP characters from keywords
%patch -P 1016 -p1 -b .drop-brackets
# RHEL-129723 CVE-2025-58436 cups: Slow client communication leads to a possible DoS attack
%patch -P 1017 -p1 -b .use-usessl
%patch -P 1018 -p1 -b .slow-client
%patch -P 1019 -p1 -b .gtk-infinite-loop
# Log to the system journal by default (bug #1078781, bug #1519331).
@ -848,6 +859,9 @@ rm -f %{cups_serverbin}/backend/smb
%{_mandir}/man7/ippeveps.7.gz
%changelog
* Thu Nov 27 2025 Zdenek Dohnal <zdohnal@redhat.com> - 1:2.4.10-15
- RHEL-129723 CVE-2025-58436 cups: Slow client communication leads to a possible DoS attack
* Tue Nov 18 2025 Zdenek Dohnal <zdohnal@redhat.com> - 1:2.4.10-14
- RHEL-122293 [image-mode] Missing /var/log/cups