import UBI cups-2.4.10-12.el10_1.2

This commit is contained in:
eabdullin 2026-01-12 17:11:13 +00:00
parent 36a99cbcd4
commit 7c658d8816
7 changed files with 1231 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,460 @@
From db8d560262c22a21ee1e55dfd62fa98d9359bcb0 Mon Sep 17 00:00:00 2001
From: Zdenek Dohnal <zdohnal@redhat.com>
Date: Fri, 21 Nov 2025 07:36:36 +0100
Subject: [PATCH] Fix various issues in cupsd
Various issues were found by @SilverPlate3, recognized as CVE-2025-61915:
- out of bound write when handling IPv6 addresses,
- cupsd crash caused by null dereference when ErrorPolicy value is empty,
On the top of that, Mike Sweet noticed vulnerability via domain socket,
exploitable locally if attacker has access to domain socket and knows username
of user within a group which is present in CUPS system groups:
- rewrite of cupsd.conf via PeerCred authorization via domain socket
The last vulnerability is fixed by introducing PeerCred directive for cups-files.conf,
which controls whether PeerCred is enabled/disabled for user in CUPS system groups.
Fixes CVE-2025-61915
---
conf/cups-files.conf.in | 3 ++
config-scripts/cups-defaults.m4 | 9 +++++
config.h.in | 7 ++++
configure | 22 ++++++++++
doc/help/man-cups-files.conf.html | 9 ++++-
man/cups-files.conf.5 | 17 ++++++--
scheduler/auth.c | 8 +++-
scheduler/auth.h | 7 ++++
scheduler/client.c | 2 +-
scheduler/conf.c | 60 ++++++++++++++++++++++++----
test/run-stp-tests.sh | 2 +-
vcnet/config.h | 7 ++++
xcode/CUPS.xcodeproj/project.pbxproj | 2 -
xcode/config.h | 7 ++++
14 files changed, 145 insertions(+), 17 deletions(-)
diff --git a/conf/cups-files.conf.in b/conf/cups-files.conf.in
index f96f745ae..6db139297 100644
--- a/conf/cups-files.conf.in
+++ b/conf/cups-files.conf.in
@@ -22,6 +22,9 @@
SystemGroup @CUPS_SYSTEM_GROUPS@
@CUPS_SYSTEM_AUTHKEY@
+# Are Unix domain socket peer credentials used for authorization?
+PeerCred @CUPS_PEER_CRED@
+
# User that is substituted for unauthenticated (remote) root accesses...
#RemoteRoot remroot
diff --git a/config-scripts/cups-defaults.m4 b/config-scripts/cups-defaults.m4
index 999a8849d..fc9ba4a02 100644
--- a/config-scripts/cups-defaults.m4
+++ b/config-scripts/cups-defaults.m4
@@ -95,6 +95,15 @@ AC_ARG_WITH([log_level], AS_HELP_STRING([--with-log-level], [set default LogLeve
AC_SUBST([CUPS_LOG_LEVEL])
AC_DEFINE_UNQUOTED([CUPS_DEFAULT_LOG_LEVEL], ["$CUPS_LOG_LEVEL"], [Default LogLevel value.])
+dnl Default PeerCred
+AC_ARG_WITH([peer_cred], AS_HELP_STRING([--with-peer-cred], [set default PeerCred value (on/off/root-only), default=on]), [
+ CUPS_PEER_CRED="$withval"
+], [
+ CUPS_PEER_CRED="on"
+])
+AC_SUBST([CUPS_PEER_CRED])
+AC_DEFINE_UNQUOTED([CUPS_DEFAULT_PEER_CRED], ["$CUPS_PEER_CRED"], [Default PeerCred value.])
+
dnl Default AccessLogLevel
AC_ARG_WITH(access_log_level, [ --with-access-log-level set default AccessLogLevel value, default=none],
CUPS_ACCESS_LOG_LEVEL="$withval",
diff --git a/config.h.in b/config.h.in
index 207df66a7..37c279088 100644
--- a/config.h.in
+++ b/config.h.in
@@ -86,6 +86,13 @@
#define CUPS_DEFAULT_ERROR_POLICY "stop-printer"
+/*
+ * Default PeerCred value...
+ */
+
+#define CUPS_DEFAULT_PEER_CRED "on"
+
+
/*
* Default MaxCopies value...
*/
diff --git a/configure b/configure
index a38ebded9..1721634ba 100755
--- a/configure
+++ b/configure
@@ -670,6 +670,7 @@ CUPS_BROWSING
CUPS_SYNC_ON_CLOSE
CUPS_PAGE_LOG_FORMAT
CUPS_ACCESS_LOG_LEVEL
+CUPS_PEER_CRED
CUPS_LOG_LEVEL
CUPS_FATAL_ERRORS
CUPS_ERROR_POLICY
@@ -919,6 +920,7 @@ with_max_log_size
with_error_policy
with_fatal_errors
with_log_level
+with_peer_cred
with_access_log_level
enable_page_logging
enable_sync_on_close
@@ -1652,6 +1654,8 @@ Optional Packages:
--with-error-policy set default ErrorPolicy value, default=stop-printer
--with-fatal-errors set default FatalErrors value, default=config
--with-log-level set default LogLevel value, default=warn
+ --with-peer-cred set default PeerCred value (on/off/root-only),
+ default=on
--with-access-log-level set default AccessLogLevel value, default=none
--with-local-protocols set default BrowseLocalProtocols, default=""
--with-cups-user set default user for CUPS
@@ -11651,6 +11655,24 @@ printf "%s\n" "#define CUPS_DEFAULT_LOG_LEVEL \"$CUPS_LOG_LEVEL\"" >>confdefs.h
+# Check whether --with-peer_cred was given.
+if test ${with_peer_cred+y}
+then :
+ withval=$with_peer_cred;
+ CUPS_PEER_CRED="$withval"
+
+else $as_nop
+
+ CUPS_PEER_CRED="on"
+
+fi
+
+
+
+printf "%s\n" "#define CUPS_DEFAULT_PEER_CRED \"$CUPS_PEER_CRED\"" >>confdefs.h
+
+
+
# Check whether --with-access_log_level was given.
if test ${with_access_log_level+y}
then :
diff --git a/doc/help/man-cups-files.conf.html b/doc/help/man-cups-files.conf.html
index 440f033d5..5a9ddefeb 100644
--- a/doc/help/man-cups-files.conf.html
+++ b/doc/help/man-cups-files.conf.html
@@ -119,6 +119,13 @@ The default is "/var/log/cups/page_log".
<dt><a name="PassEnv"></a><b>PassEnv </b><i>variable </i>[ ... <i>variable </i>]
<dd style="margin-left: 5.0em">Passes the specified environment variable(s) to child processes.
Note: the standard CUPS filter and backend environment variables cannot be overridden using this directive.
+<dt><a name="PeerCred"></a><b>PeerCred off</b>
+<dd style="margin-left: 5.0em"><dt><b>PeerCred on</b>
+<dd style="margin-left: 5.0em"><dt><b>PeerCred root-only</b>
+<dd style="margin-left: 5.0em">Specifies whether peer credentials are used for authorization when communicating over the UNIX domain socket.
+When <b>on</b>, the peer credentials of any user are accepted for authorization.
+The value <b>off</b> disables the use of peer credentials entirely, while the value <b>root-only</b> allows peer credentials only for the root user.
+Note: for security reasons, the <b>on</b> setting is reduced to <b>root-only</b> for authorization of PUT requests.
<dt><a name="RemoteRoot"></a><b>RemoteRoot </b><i>username</i>
<dd style="margin-left: 5.0em">Specifies the username that is associated with unauthenticated accesses by clients claiming to be the root user.
The default is "remroot".
diff --git a/man/cups-files.conf.5 b/man/cups-files.conf.5
index ec16c9e13..18ce2be00 100644
--- a/man/cups-files.conf.5
+++ b/man/cups-files.conf.5
@@ -166,6 +166,17 @@ The default is "/var/log/cups/page_log".
\fBPassEnv \fIvariable \fR[ ... \fIvariable \fR]
Passes the specified environment variable(s) to child processes.
Note: the standard CUPS filter and backend environment variables cannot be overridden using this directive.
+.\"#PeerCred
+.TP 5
+\fBPeerCred off\fR
+.TP 5
+\fBPeerCred on\fR
+.TP 5
+\fBPeerCred root-only\fR
+Specifies whether peer credentials are used for authorization when communicating over the UNIX domain socket.
+When \fBon\fR, the peer credentials of any user are accepted for authorization.
+The value \fBoff\fR disables the use of peer credentials entirely, while the value \fBroot-only\fR allows peer credentials only for the root user.
+Note: for security reasons, the \fBon\fR setting is reduced to \fBroot-only\fR for authorization of PUT requests.
.\"#RemoteRoot
.TP 5
\fBRemoteRoot \fIusername\fR
@@ -289,4 +300,4 @@ command is used instead.
.BR subscriptions.conf (5),
CUPS Online Help (http://localhost:631/help)
.SH COPYRIGHT
-Copyright \[co] 2020-2024 by OpenPrinting.
+Copyright \[co] 2020-2025 by OpenPrinting.
diff --git a/scheduler/auth.c b/scheduler/auth.c
index 3c9aa72aa..bd0d28a0e 100644
--- a/scheduler/auth.c
+++ b/scheduler/auth.c
@@ -398,7 +398,7 @@ cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */
}
#endif /* HAVE_AUTHORIZATION_H */
#if defined(SO_PEERCRED) && defined(AF_LOCAL)
- else if (!strncmp(authorization, "PeerCred ", 9) &&
+ else if (PeerCred != CUPSD_PEERCRED_OFF && !strncmp(authorization, "PeerCred ", 9) &&
con->http->hostaddr->addr.sa_family == AF_LOCAL && con->best)
{
/*
@@ -441,6 +441,12 @@ cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */
}
#endif /* HAVE_AUTHORIZATION_H */
+ if ((PeerCred == CUPSD_PEERCRED_ROOTONLY || httpGetState(con->http) == HTTP_STATE_PUT_RECV) && strcmp(authorization + 9, "root"))
+ {
+ cupsdLogClient(con, CUPSD_LOG_INFO, "User \"%s\" is not allowed to use peer credentials.", authorization + 9);
+ return;
+ }
+
if ((pwd = getpwnam(authorization + 9)) == NULL)
{
cupsdLogClient(con, CUPSD_LOG_ERROR, "User \"%s\" does not exist.", authorization + 9);
diff --git a/scheduler/auth.h b/scheduler/auth.h
index ee98e92c7..fdf71213f 100644
--- a/scheduler/auth.h
+++ b/scheduler/auth.h
@@ -50,6 +50,10 @@
#define CUPSD_AUTH_LIMIT_ALL 127 /* Limit all requests */
#define CUPSD_AUTH_LIMIT_IPP 128 /* Limit IPP requests */
+#define CUPSD_PEERCRED_OFF 0 /* Don't allow PeerCred authorization */
+#define CUPSD_PEERCRED_ON 1 /* Allow PeerCred authorization for all users */
+#define CUPSD_PEERCRED_ROOTONLY 2 /* Allow PeerCred authorization for root user */
+
#define IPP_ANY_OPERATION (ipp_op_t)0
/* Any IPP operation */
#define IPP_BAD_OPERATION (ipp_op_t)-1
@@ -105,6 +109,9 @@ typedef struct
VAR cups_array_t *Locations VALUE(NULL);
/* Authorization locations */
+VAR int PeerCred VALUE(CUPSD_PEERCRED_ON);
+ /* Allow PeerCred authorization? */
+
#ifdef HAVE_TLS
VAR http_encryption_t DefaultEncryption VALUE(HTTP_ENCRYPT_REQUIRED);
/* Default encryption for authentication */
diff --git a/scheduler/client.c b/scheduler/client.c
index 9593c9138..d961c15db 100644
--- a/scheduler/client.c
+++ b/scheduler/client.c
@@ -2208,7 +2208,7 @@ cupsdSendHeader(
auth_size = sizeof(auth_str) - (size_t)(auth_key - auth_str);
#if defined(SO_PEERCRED) && defined(AF_LOCAL)
- if (httpAddrFamily(httpGetAddress(con->http)) == AF_LOCAL)
+ if (PeerCred != CUPSD_PEERCRED_OFF && httpAddrFamily(httpGetAddress(con->http)) == AF_LOCAL)
{
strlcpy(auth_key, ", PeerCred", auth_size);
auth_key += 10;
diff --git a/scheduler/conf.c b/scheduler/conf.c
index db4104ec5..7d6da0252 100644
--- a/scheduler/conf.c
+++ b/scheduler/conf.c
@@ -47,6 +47,7 @@ typedef enum
{
CUPSD_VARTYPE_INTEGER, /* Integer option */
CUPSD_VARTYPE_TIME, /* Time interval option */
+ CUPSD_VARTYPE_NULLSTRING, /* String option or NULL/empty string */
CUPSD_VARTYPE_STRING, /* String option */
CUPSD_VARTYPE_BOOLEAN, /* Boolean option */
CUPSD_VARTYPE_PATHNAME, /* File/directory name option */
@@ -69,7 +70,7 @@ static const cupsd_var_t cupsd_vars[] =
{
{ "AutoPurgeJobs", &JobAutoPurge, CUPSD_VARTYPE_BOOLEAN },
#ifdef HAVE_DNSSD
- { "BrowseDNSSDSubTypes", &DNSSDSubTypes, CUPSD_VARTYPE_STRING },
+ { "BrowseDNSSDSubTypes", &DNSSDSubTypes, CUPSD_VARTYPE_NULLSTRING },
#endif /* HAVE_DNSSD */
{ "BrowseWebIF", &BrowseWebIF, CUPSD_VARTYPE_BOOLEAN },
{ "Browsing", &Browsing, CUPSD_VARTYPE_BOOLEAN },
@@ -120,7 +121,7 @@ static const cupsd_var_t cupsd_vars[] =
{ "MaxSubscriptionsPerPrinter",&MaxSubscriptionsPerPrinter, CUPSD_VARTYPE_INTEGER },
{ "MaxSubscriptionsPerUser", &MaxSubscriptionsPerUser, CUPSD_VARTYPE_INTEGER },
{ "MultipleOperationTimeout", &MultipleOperationTimeout, CUPSD_VARTYPE_TIME },
- { "PageLogFormat", &PageLogFormat, CUPSD_VARTYPE_STRING },
+ { "PageLogFormat", &PageLogFormat, CUPSD_VARTYPE_NULLSTRING },
{ "PreserveJobFiles", &JobFiles, CUPSD_VARTYPE_TIME },
{ "PreserveJobHistory", &JobHistory, CUPSD_VARTYPE_TIME },
{ "ReloadTimeout", &ReloadTimeout, CUPSD_VARTYPE_TIME },
@@ -791,6 +792,13 @@ cupsdReadConfiguration(void)
IdleExitTimeout = 60;
#endif /* HAVE_ONDEMAND */
+ if (!strcmp(CUPS_DEFAULT_PEER_CRED, "off"))
+ PeerCred = CUPSD_PEERCRED_OFF;
+ else if (!strcmp(CUPS_DEFAULT_PEER_CRED, "root-only"))
+ PeerCred = CUPSD_PEERCRED_ROOTONLY;
+ else
+ PeerCred = CUPSD_PEERCRED_ON;
+
/*
* Setup environment variables...
*/
@@ -1842,7 +1850,7 @@ get_addr_and_mask(const char *value, /* I - String from config file */
family = AF_INET6;
- for (i = 0, ptr = value + 1; *ptr && i < 8; i ++)
+ for (i = 0, ptr = value + 1; *ptr && i >= 0 && i < 8; i ++)
{
if (*ptr == ']')
break;
@@ -1988,7 +1996,7 @@ get_addr_and_mask(const char *value, /* I - String from config file */
#ifdef AF_INET6
if (family == AF_INET6)
{
- if (i > 128)
+ if (i < 0 || i > 128)
return (0);
i = 128 - i;
@@ -2022,7 +2030,7 @@ get_addr_and_mask(const char *value, /* I - String from config file */
else
#endif /* AF_INET6 */
{
- if (i > 32)
+ if (i < 0 || i > 32)
return (0);
mask[0] = 0xffffffff;
@@ -2932,7 +2940,17 @@ parse_variable(
cupsdSetString((char **)var->ptr, temp);
break;
+ case CUPSD_VARTYPE_NULLSTRING :
+ cupsdSetString((char **)var->ptr, value);
+ break;
+
case CUPSD_VARTYPE_STRING :
+ if (!value)
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR, "Missing value for %s on line %d of %s.", line, linenum, filename);
+ return (0);
+ }
+
cupsdSetString((char **)var->ptr, value);
break;
}
@@ -3449,9 +3467,10 @@ read_cupsd_conf(cups_file_t *fp) /* I - File to read from */
line, value ? " " : "", value ? value : "", linenum,
ConfigurationFile, CupsFilesFile);
}
- else
- parse_variable(ConfigurationFile, linenum, line, value,
- sizeof(cupsd_vars) / sizeof(cupsd_vars[0]), cupsd_vars);
+ else if (!parse_variable(ConfigurationFile, linenum, line, value,
+ sizeof(cupsd_vars) / sizeof(cupsd_vars[0]), cupsd_vars) &&
+ (FatalErrors & CUPSD_FATAL_CONFIG))
+ return (0);
}
return (1);
@@ -3610,6 +3629,31 @@ read_cups_files_conf(cups_file_t *fp) /* I - File to read from */
break;
}
}
+ else if (!_cups_strcasecmp(line, "PeerCred") && value)
+ {
+ /*
+ * PeerCred {off,on,root-only}
+ */
+
+ if (!_cups_strcasecmp(value, "off"))
+ {
+ PeerCred = CUPSD_PEERCRED_OFF;
+ }
+ else if (!_cups_strcasecmp(value, "on"))
+ {
+ PeerCred = CUPSD_PEERCRED_ON;
+ }
+ else if (!_cups_strcasecmp(value, "root-only"))
+ {
+ PeerCred = CUPSD_PEERCRED_ROOTONLY;
+ }
+ else
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR, "Unknown PeerCred \"%s\" on line %d of %s.", value, linenum, CupsFilesFile);
+ if (FatalErrors & CUPSD_FATAL_CONFIG)
+ return (0);
+ }
+ }
else if (!_cups_strcasecmp(line, "PrintcapFormat") && value)
{
/*
diff --git a/test/run-stp-tests.sh b/test/run-stp-tests.sh
index 1c447edd7..8d677db71 100755
--- a/test/run-stp-tests.sh
+++ b/test/run-stp-tests.sh
@@ -512,7 +512,7 @@ fi
cat >$BASE/cups-files.conf <<EOF
FileDevice yes
-Printcap
+Printcap $BASE/printcap
User $user
ServerRoot $BASE
StateDir $BASE
diff --git a/vcnet/config.h b/vcnet/config.h
index dbc6f05d5..317c956a6 100644
--- a/vcnet/config.h
+++ b/vcnet/config.h
@@ -169,6 +169,13 @@ typedef unsigned long useconds_t;
#define CUPS_DEFAULT_ERROR_POLICY "stop-printer"
+/*
+ * Default PeerCred value...
+ */
+
+#define CUPS_DEFAULT_PEER_CRED "on"
+
+
/*
* Default MaxCopies value...
*/
diff --git a/xcode/CUPS.xcodeproj/project.pbxproj b/xcode/CUPS.xcodeproj/project.pbxproj
index 597946440..54ac652a1 100644
--- a/xcode/CUPS.xcodeproj/project.pbxproj
+++ b/xcode/CUPS.xcodeproj/project.pbxproj
@@ -3433,7 +3433,6 @@
72220FB313330BCE00FCA411 /* mime.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = mime.c; path = ../scheduler/mime.c; sourceTree = "<group>"; };
72220FB413330BCE00FCA411 /* mime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = mime.h; path = ../scheduler/mime.h; sourceTree = "<group>"; };
72220FB513330BCE00FCA411 /* type.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = type.c; path = ../scheduler/type.c; sourceTree = "<group>"; };
- 7226369B18AE6D19004ED309 /* org.cups.cups-lpd.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "org.cups.cups-lpd.plist"; path = "../scheduler/org.cups.cups-lpd.plist"; sourceTree = SOURCE_ROOT; };
7226369C18AE6D19004ED309 /* org.cups.cupsd.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = org.cups.cupsd.plist; path = ../scheduler/org.cups.cupsd.plist; sourceTree = SOURCE_ROOT; };
7226369D18AE73BB004ED309 /* config.h.in */ = {isa = PBXFileReference; lastKnownFileType = text; name = config.h.in; path = ../config.h.in; sourceTree = "<group>"; };
722A24EE2178D00C000CAB20 /* debug-internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "debug-internal.h"; path = "../cups/debug-internal.h"; sourceTree = "<group>"; };
@@ -5055,7 +5054,6 @@
isa = PBXGroup;
children = (
72E65BDC18DC852700097E89 /* Makefile */,
- 7226369B18AE6D19004ED309 /* org.cups.cups-lpd.plist */,
72E65BD518DC818400097E89 /* org.cups.cups-lpd.plist.in */,
7226369C18AE6D19004ED309 /* org.cups.cupsd.plist */,
72220F6913330B0C00FCA411 /* auth.c */,
diff --git a/xcode/config.h b/xcode/config.h
index e0ddd09dc..caec083ca 100644
--- a/xcode/config.h
+++ b/xcode/config.h
@@ -88,6 +88,13 @@
#define CUPS_DEFAULT_ERROR_POLICY "stop-printer"
+/*
+ * Default PeerCred value...
+ */
+
+#define CUPS_DEFAULT_PEER_CRED "on"
+
+
/*
* Default MaxCopies value...
*/
--
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);

View File

@ -0,0 +1,43 @@
From 277d3b1c49895f070bbf4b73cada011d71fbf9f3 Mon Sep 17 00:00:00 2001
From: Zdenek Dohnal <zdohnal@redhat.com>
Date: Thu, 4 Dec 2025 09:04:37 +0100
Subject: [PATCH] conf.c: Fix stopping scheduler on unknown directive
Change the return value to do not trigger stopping the scheduler in case
of unknown directive, because stopping the scheduler on config errors
should only happen in case of syntax errors.
---
scheduler/conf.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/scheduler/conf.c b/scheduler/conf.c
index 7d6da0252..0e7be0ef4 100644
--- a/scheduler/conf.c
+++ b/scheduler/conf.c
@@ -2708,16 +2708,16 @@ parse_variable(
{
/*
* Unknown directive! Output an error message and continue...
+ *
+ * Return value 1 is on purpose - we ignore unknown directives to log
+ * error, but do not stop the scheduler in case error in configuration
+ * is set to be fatal.
*/
- if (!value)
- cupsdLogMessage(CUPSD_LOG_ERROR, "Missing value for %s on line %d of %s.",
- line, linenum, filename);
- else
- cupsdLogMessage(CUPSD_LOG_ERROR, "Unknown directive %s on line %d of %s.",
- line, linenum, filename);
+ cupsdLogMessage(CUPSD_LOG_ERROR, "Unknown directive %s on line %d of %s.",
+ line, linenum, filename);
- return (0);
+ return (1);
}
switch (var->type)
--
2.52.0

View File

@ -0,0 +1,29 @@
From c1d2c631267f28131dd31df5b895b8bfb3005b0d Mon Sep 17 00:00:00 2001
From: Zdenek Dohnal <zdohnal@redhat.com>
Date: Thu, 11 Dec 2025 15:12:55 +0100
Subject: [PATCH] scheduler: Fix possible use_after_free in `cupsdReadClient()`
If `cupsdSendHeader()` fails, we free the connection and return -1, but
in that case we try to free the connection again in `cupsdReadClient()`.
---
scheduler/client.c | 3 ---
1 file changed, 3 deletions(-)
diff --git a/scheduler/client.c b/scheduler/client.c
index f6166091e..63844d531 100644
--- a/scheduler/client.c
+++ b/scheduler/client.c
@@ -2761,10 +2761,7 @@ check_start_tls(cupsd_client_t *con) /* I - Client connection */
httpSetField(con->http, HTTP_FIELD_CONTENT_LENGTH, "0");
if (!cupsdSendHeader(con, HTTP_STATUS_OK, NULL, CUPSD_AUTH_NONE))
- {
- cupsdCloseClient(con);
return (-1);
- }
}
return (1);
--
2.52.0

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: 12%{?dist}
Release: 12%{?dist}.2
# backend/failover.c - BSD-3-Clause
# cups/md5* - Zlib
# scheduler/colorman.c - Apache-2.0 WITH LLVM-exception AND BSD-2-Clause
@ -109,6 +109,21 @@ Patch1013: 0001-Add-NoSystem-SSLOptions-value.patch
Patch1014: CVE-2025-58060.patch
# RHEL-113073 CVE-2025-58364 cups: Null Pointer Dereference in CUPS ipp_read_io() Leading to Remote DoS
Patch1015: CVE-2025-58364.patch
# RHEL-129721 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
Patch1016: 0001-_httpWait-s-usessl-parameter-wasn-t-being-used.patch
Patch1017: cups-CVE-2025-58436.patch
Patch1018: 0001-Fix-an-infinite-loop-issue-in-GTK-Issue-1439.patch
# RHEL-129715 CVE-2025-61915 cups: Local denial-of-service via cupsd.conf update and related issues
# 0001-Fix-various-issues-in-cupsd.patch
# 0001-conf.c-Fix-stopping-scheduler-on-unknown-directive.patch
Patch1019: 0001-Fix-various-issues-in-cupsd.patch
Patch1020: 0001-conf.c-Fix-stopping-scheduler-on-unknown-directive.patch
# fix use-after-free reported after fix for CVE-2025-58436
# https://github.com/OpenPrinting/cups/pull/1454
Patch1021: 0001-scheduler-Fix-possible-use_after_free-in-cupsdReadCl.patch
##### Patches removed because IMHO they aren't no longer needed
@ -370,6 +385,15 @@ to CUPS daemon. This solution will substitute printer drivers and raw queues in
%patch -P 1014 -p1 -b .cve-2025-58060
# RHEL-113073 CVE-2025-58364 cups: Null Pointer Dereference in CUPS ipp_read_io() Leading to Remote DoS
%patch -P 1015 -p1 -b .cve-2025-58364
# RHEL-129721 CVE-2025-58436 cups: Slow client communication leads to a possible DoS attack
%patch -P 1016 -p1 -b .use-usessl
%patch -P 1017 -p1 -b .slow-client
%patch -P 1018 -p1 -b .gtk-infinite-loop
# RHEL-129715 CVE-2025-61915 cups: Local denial-of-service via cupsd.conf update and related issues
%patch -P 1019 -p1 -b .config-issues
%patch -P 1020 -p1 -b .ignore-unknown
# fix use-after-free reported after fix for CVE-2025-58436
%patch -P 1021 -p1 -b .osh-use-after-free
# Log to the system journal by default (bug #1078781, bug #1519331).
@ -839,6 +863,13 @@ rm -f %{cups_serverbin}/backend/smb
%{_mandir}/man7/ippeveps.7.gz
%changelog
* Fri Dec 12 2025 Zdenek Dohnal <zdohnal@redhat.com> - 1:2.4.10-12.2
- fix use-after-free reported by OSH
* Fri Dec 05 2025 Zdenek Dohnal <zdohnal@redhat.com> - 1:2.4.10-12.1
- RHEL-129721 CVE-2025-58436 cups: Slow client communication leads to a possible DoS attack
- RHEL-129715 CVE-2025-61915 cups: Local denial-of-service via cupsd.conf update and related issues
* Thu Sep 11 2025 Zdenek Dohnal <zdohnal@redhat.com> - 1:2.4.10-12
- RHEL-112419 CVE-2025-58060 cups: Authentication Bypass in CUPS Authorization Handling
- RHEL-113073 CVE-2025-58364 cups: Null Pointer Dereference in CUPS ipp_read_io() Leading to Remote DoS