In CUPS versions 2.4.16 and prior, a local unprivileged
user can coerce cupsd into authenticating to an attacker-
controlled localhost IPP service with a reusable
Authorization: Local token. That token is sufficient to
drive /admin/ requests on localhost. By combining
CUPS-Create-Local-Printer with printer-is-shared=true,
an attacker can persist a file:///... queue even though
the normal FileDevice policy rejects such URIs. Printing
to that queue allows arbitrary root file overwrite. A
proof-of-concept demonstrates dropping a sudoers fragment
to achieve root command execution.

Apply upstream fix to prevent misuse of Local authorization
tokens and block unauthorized file:/// queues.

Signed-off-by: Abhishek Bachiphale <[email protected]>
---
 meta/recipes-extended/cups/cups.inc           |   1 +
 .../cups/cups/CVE-2026-34990.patch            | 348 ++++++++++++++++++
 2 files changed, 349 insertions(+)
 create mode 100644 meta/recipes-extended/cups/cups/CVE-2026-34990.patch

diff --git a/meta/recipes-extended/cups/cups.inc 
b/meta/recipes-extended/cups/cups.inc
index f23411f44b..42107774e4 100644
--- a/meta/recipes-extended/cups/cups.inc
+++ b/meta/recipes-extended/cups/cups.inc
@@ -18,6 +18,7 @@ SRC_URI = 
"${GITHUB_BASE_URI}/download/v${PV}/cups-${PV}-source.tar.gz \
            file://CVE-2026-34978.patch \
            file://CVE-2026-34979.patch \
            file://CVE-2026-34980.patch \
+           file://CVE-2026-34990.patch \
            "
 
 GITHUB_BASE_URI = "https://github.com/OpenPrinting/cups/releases";
diff --git a/meta/recipes-extended/cups/cups/CVE-2026-34990.patch 
b/meta/recipes-extended/cups/cups/CVE-2026-34990.patch
new file mode 100644
index 0000000000..3f7781c19e
--- /dev/null
+++ b/meta/recipes-extended/cups/cups/CVE-2026-34990.patch
@@ -0,0 +1,348 @@
+From e052dc44da9d12adfbebc51de4975fbadb2ce356 Mon Sep 17 00:00:00 2001
+From: Michael R Sweet <[email protected]>
+Date: Tue, 31 Mar 2026 15:55:50 -0400
+Subject: [PATCH] Don't allow local certificates over the loopback interface,
+ drop support for writing to plain files.
+
+OpenPrinting CUPS is an open source printing system for Linux and other
+Unix-like operating systems. In versions 2.4.16 and prior, a local
+unprivileged user can coerce cupsd into authenticating to an
+attacker-controlled localhost IPP service with a reusable Authorization:
+Local ... token. That token is enough to drive /admin/ requests on
+localhost, and the attacker can combine CUPS-Create-Local-Printer with
+printer-is-shared=true to persist a file: ///... queue even though the
+normal FileDevice policy rejects such URIs. Printing to that queue gives
+an arbitrary root file overwrite; the PoC below uses that primitive to
+drop a sudoers fragment and demonstrate root command execution.
+
+CVE: CVE-2026-34990
+
+Upstream-Status: Backport [ 
https://github.com/OpenPrinting/cups/commit/e052dc44da9d12adfbebc51de4975fbadb2ce356
 ]
+
+Signed-off-by: Abhishek Bachiphale <[email protected]>
+---
+ cups/auth.c                    | 30 ++++++----------------
+ scheduler/auth.c               |  6 ++---
+ scheduler/client.c             |  4 +--
+ scheduler/ipp.c                |  6 ++---
+ scheduler/job.c                | 46 ++++++++++++++++++----------------
+ test/4.2-cups-printer-ops.test |  6 ++---
+ test/5.1-lpadmin.sh            | 14 +++++------
+ 7 files changed, 52 insertions(+), 62 deletions(-)
+
+diff --git a/cups/auth.c b/cups/auth.c
+index 5cb419458f..14661c7bef 100644
+--- a/cups/auth.c
++++ b/cups/auth.c
+@@ -1,7 +1,7 @@
+ /*
+  * Authentication functions for CUPS.
+  *
+- * Copyright © 2020-2024 by OpenPrinting.
++ * Copyright © 2020-2026 by OpenPrinting.
+  * Copyright © 2007-2019 by Apple Inc.
+  * Copyright © 1997-2007 by Easy Software Products.
+  *
+@@ -92,7 +92,6 @@ static void  cups_gss_printf(OM_uint32 major_status, 
OM_uint32 minor_status,
+ #    define   cups_gss_printf(major, minor, message)
+ #  endif /* DEBUG */
+ #endif /* HAVE_GSSAPI */
+-static int    cups_is_local_connection(http_t *http);
+ static int    cups_local_auth(http_t *http);
+ 
+ 
+@@ -948,14 +947,6 @@ cups_gss_printf(OM_uint32  major_status,/* I - Major 
status code */
+ #  endif /* DEBUG */
+ #endif /* HAVE_GSSAPI */
+ 
+-static int                            /* O - 0 if not a local connection */
+-                                      /*     1  if local connection */
+-cups_is_local_connection(http_t *http)        /* I - HTTP connection to 
server */
+-{
+-  if (!httpAddrLocalhost(http->hostaddr) && _cups_strcasecmp(http->hostname, 
"localhost") != 0)
+-    return 0;
+-  return 1;
+-}
+ 
+ /*
+  * 'cups_local_auth()' - Get the local authorization certificate if
+@@ -967,13 +958,7 @@ static int                                /* O - 0 if 
available */
+                                       /*    -1 error */
+ cups_local_auth(http_t *http)         /* I - HTTP connection to server */
+ {
+-#if defined(_WIN32) || defined(__EMX__)
+- /*
+-  * Currently _WIN32 and OS-2 do not support the CUPS server...
+-  */
+-
+-  return (1);
+-#else
++#if !_WIN32 && !__EMX__ && defined(AF_LOCAL)
+   int                 pid;            /* Current process ID */
+   FILE                        *fp;            /* Certificate file */
+   char                        trc[16],        /* Try Root Certificate 
parameter */
+@@ -998,7 +983,7 @@ cups_local_auth(http_t *http)              /* I - HTTP 
connection to server */
+   * See if we are accessing localhost...
+   */
+ 
+-  if (!cups_is_local_connection(http))
++  if (httpAddrFamily(httpGetAddress(http)) != AF_LOCAL)
+   {
+     DEBUG_puts("8cups_local_auth: Not a local connection!");
+     return (1);
+@@ -1072,15 +1057,14 @@ cups_local_auth(http_t *http)          /* I - HTTP 
connection to server */
+   }
+ #  endif /* HAVE_AUTHORIZATION_H */
+ 
+-#  if defined(SO_PEERCRED) && defined(AF_LOCAL)
++#  ifdef SO_PEERCRED
+  /*
+   * See if we can authenticate using the peer credentials provided over a
+   * domain socket; if so, specify "PeerCred username" as the authentication
+   * information...
+   */
+ 
+-  if (http->hostaddr->addr.sa_family == AF_LOCAL &&
+-      !getenv("GATEWAY_INTERFACE") && /* Not via CGI programs... */
++  if (!getenv("GATEWAY_INTERFACE") && /* Not via CGI programs... */
+       cups_auth_find(www_auth, "PeerCred"))
+   {
+    /*
+@@ -1104,7 +1088,7 @@ cups_local_auth(http_t *http)            /* I - HTTP 
connection to server */
+       return (0);
+     }
+   }
+-#  endif /* SO_PEERCRED && AF_LOCAL */
++#  endif /* SO_PEERCRED */
+ 
+   if ((schemedata = cups_auth_find(www_auth, "Local")) == NULL)
+     return (1);
+@@ -1164,7 +1148,7 @@ cups_local_auth(http_t *http)            /* I - HTTP 
connection to server */
+       return (0);
+     }
+   }
++#endif /* !_WIN32 && !__EMX__ && AF_LOCAL */
+ 
+   return (1);
+-#endif /* _WIN32 || __EMX__ */
+ }
+diff --git a/scheduler/auth.c b/scheduler/auth.c
+index 471de0492f..3e7041e220 100644
+--- a/scheduler/auth.c
++++ b/scheduler/auth.c
+@@ -318,7 +318,7 @@ cupsdAuthorize(cupsd_client_t *con)        /* I - Client 
connection */
+   }
+ #ifdef HAVE_AUTHORIZATION_H
+   else if (!strncmp(authorization, "AuthRef ", 8) &&
+-           httpAddrLocalhost(httpGetAddress(con->http)))
++           httpAddrFamily(httpGetAddress(con->http)) == AF_LOCAL)
+   {
+     OSStatus          status;         /* Status */
+     char              authdata[HTTP_MAX_VALUE];
+@@ -399,7 +399,7 @@ cupsdAuthorize(cupsd_client_t *con)        /* I - Client 
connection */
+ #endif /* HAVE_AUTHORIZATION_H */
+ #if defined(SO_PEERCRED) && defined(AF_LOCAL)
+   else if (PeerCred != CUPSD_PEERCRED_OFF && !strncmp(authorization, 
"PeerCred ", 9) &&
+-           con->http->hostaddr->addr.sa_family == AF_LOCAL && con->best)
++           httpAddrFamily(httpGetAddress(con->http)) == AF_LOCAL && con->best)
+   {
+    /*
+     * Use peer credentials from domain socket connection...
+@@ -489,7 +489,7 @@ cupsdAuthorize(cupsd_client_t *con)        /* I - Client 
connection */
+   }
+ #endif /* SO_PEERCRED && AF_LOCAL */
+   else if (!strncmp(authorization, "Local", 5) &&
+-         httpAddrLocalhost(httpGetAddress(con->http)))
++         httpAddrFamily(httpGetAddress(con->http)) == AF_LOCAL)
+   {
+    /*
+     * Get Local certificate authentication data...
+diff --git a/scheduler/client.c b/scheduler/client.c
+index 51be34f448..ab35bb7566 100644
+--- a/scheduler/client.c
++++ b/scheduler/client.c
+@@ -2188,7 +2188,7 @@ cupsdSendHeader(
+       strlcpy(auth_str, "Negotiate", sizeof(auth_str));
+     }
+ 
+-    if (con->best && !con->is_browser && 
!_cups_strcasecmp(httpGetHostname(con->http, NULL, 0), "localhost"))
++    if (con->best && !con->is_browser && 
httpAddrFamily(httpGetAddress(con->http)) == AF_LOCAL)
+     {
+      /*
+       * Add a "trc" (try root certification) parameter for local
+@@ -2208,7 +2208,7 @@ cupsdSendHeader(
+       auth_size = sizeof(auth_str) - (size_t)(auth_key - auth_str);
+ 
+ #if defined(SO_PEERCRED) && defined(AF_LOCAL)
+-      if (PeerCred != CUPSD_PEERCRED_OFF && 
httpAddrFamily(httpGetAddress(con->http)) == AF_LOCAL)
++      if (PeerCred != CUPSD_PEERCRED_OFF)
+       {
+         strlcpy(auth_key, ", PeerCred", auth_size);
+         auth_key += 10;
+diff --git a/scheduler/ipp.c b/scheduler/ipp.c
+index cb228b87c8..9a280e7525 100644
+--- a/scheduler/ipp.c
++++ b/scheduler/ipp.c
+@@ -5625,7 +5625,7 @@ create_local_printer(
+   * Require local access to create a local printer...
+   */
+ 
+-  if (!httpAddrLocalhost(httpGetAddress(con->http)))
++  if (httpAddrFamily(httpGetAddress(con->http)) != AF_LOCAL)
+   {
+     send_ipp_status(con, IPP_STATUS_ERROR_FORBIDDEN, _("Only local users can 
create a local printer."));
+     return;
+@@ -5685,9 +5685,9 @@ create_local_printer(
+ 
+   ptr = ippGetString(device_uri, 0, NULL);
+ 
+-  if (!ptr || !ptr[0])
++  if (!ptr || !ptr[0] || (strncmp(ptr, "ipp://", 6) && strncmp(ptr, 
"ipps://", 7)))
+   {
+-    send_ipp_status(con, IPP_STATUS_ERROR_BAD_REQUEST, _("Attribute \"%s\" 
has empty value."), "device-uri");
++    send_ipp_status(con, IPP_STATUS_ERROR_NOT_POSSIBLE, _("Bad device-uri 
\"%s\"."), ptr);
+ 
+     return;
+   }
+diff --git a/scheduler/job.c b/scheduler/job.c
+index 0494d7196d..6599bfcf48 100644
+--- a/scheduler/job.c
++++ b/scheduler/job.c
+@@ -1163,35 +1163,39 @@ cupsdContinueJob(cupsd_job_t *job)     /* I - Job */
+       }
+       else
+       {
++        char  scheme[32],             /* URI scheme */
++              userpass[32],           /* URI username:password */
++              host[256],              /* URI hostname */
++              resource[1024];         /* URI resource path (filename) */
++        int   port;                   /* URI port number */
++
++          httpSeparateURI(HTTP_URI_CODING_ALL, job->printer->device_uri, 
scheme, sizeof(scheme), userpass, sizeof(userpass), host, sizeof(host), &port, 
resource, sizeof(resource));
++
+         job->print_pipes[0] = -1;
+-        if (!strcmp(job->printer->device_uri, "file:/dev/null") ||
+-            !strcmp(job->printer->device_uri, "file:///dev/null"))
+-          job->print_pipes[1] = -1;
+-        else
++        job->print_pipes[1] = -1;
++
++        if (strcmp(resource, "/dev/null"))
+         {
+-          if (!strncmp(job->printer->device_uri, "file:/dev/", 10))
+-            job->print_pipes[1] = open(job->printer->device_uri + 5,
+-                                       O_WRONLY | O_EXCL);
+-          else if (!strncmp(job->printer->device_uri, "file:///dev/", 12))
+-            job->print_pipes[1] = open(job->printer->device_uri + 7,
+-                                       O_WRONLY | O_EXCL);
+-          else if (!strncmp(job->printer->device_uri, "file:///", 8))
+-            job->print_pipes[1] = open(job->printer->device_uri + 7,
+-                                       O_WRONLY | O_CREAT | O_TRUNC, 0600);
+-          else
+-            job->print_pipes[1] = open(job->printer->device_uri + 5,
+-                                       O_WRONLY | O_CREAT | O_TRUNC, 0600);
++          if (!FileDevice)
++          {
++            abort_message = "Stopping job because file: output is disabled.";
+ 
+-          if (job->print_pipes[1] < 0)
++              goto abort_job;
++          }
++          else if ((job->print_pipes[1] = open(resource, O_WRONLY | O_EXCL)) 
< 0)
+           {
+-            abort_message = "Stopping job because the scheduler could not "
+-                            "open the output file.";
++            abort_message = "Stopping job because the scheduler could not 
open the output file.";
+ 
+               goto abort_job;
+           }
++          else
++          {
++           /*
++            * Close this file on execute...
++            */
+ 
+-          fcntl(job->print_pipes[1], F_SETFD,
+-                fcntl(job->print_pipes[1], F_GETFD) | FD_CLOEXEC);
++            fcntl(job->print_pipes[1], F_SETFD, fcntl(job->print_pipes[1], 
F_GETFD) | FD_CLOEXEC);
++          }
+           }
+       }
+       }
+diff --git a/test/4.2-cups-printer-ops.test b/test/4.2-cups-printer-ops.test
+index 1a011e011a..945a9bbd71 100644
+--- a/test/4.2-cups-printer-ops.test
++++ b/test/4.2-cups-printer-ops.test
+@@ -1,7 +1,7 @@
+ #
+ # Verify that the CUPS printer operations work.
+ #
+-# Copyright © 2020-2024 by OpenPrinting.
++# Copyright © 2020-2026 by OpenPrinting.
+ # Copyright © 2007-2019 by Apple Inc.
+ # Copyright © 2001-2006 by Easy Software Products. All rights reserved.
+ #
+@@ -180,7 +180,7 @@
+       ATTR uri printer-uri $method://$hostname:$port/printers/Test2
+ 
+       GROUP printer
+-      ATTR uri device-uri file:/tmp/Test2
++      ATTR uri device-uri file:///dev/null
+       ATTR enum printer-state 3
+       ATTR boolean printer-is-accepting-jobs true
+ 
+@@ -206,7 +206,7 @@
+       ATTR uri printer-uri $method://$hostname:$port/printers/Test1
+ 
+       GROUP printer
+-      ATTR uri device-uri file:/tmp/Test1
++      ATTR uri device-uri file:///dev/null
+       ATTR enum printer-state 3
+       ATTR boolean printer-is-accepting-jobs true
+       ATTR text printer-info "Test Printer 1"
+diff --git a/test/5.1-lpadmin.sh b/test/5.1-lpadmin.sh
+index aa398000a1..36f2822275 100644
+--- a/test/5.1-lpadmin.sh
++++ b/test/5.1-lpadmin.sh
+@@ -2,7 +2,7 @@
+ #
+ # Test the lpadmin command.
+ #
+-# Copyright © 2020-2024 by OpenPrinting.
++# Copyright © 2020-2026 by OpenPrinting.
+ # Copyright © 2007-2018 by Apple Inc.
+ # Copyright © 1997-2005 by Easy Software Products, all rights reserved.
+ #
+@@ -12,8 +12,8 @@
+ 
+ echo "Add Printer Test"
+ echo ""
+-echo "    lpadmin -p Test3 -v file:/dev/null -E -m 
drv:///sample.drv/deskjet.ppd"
+-$runcups $VALGRIND ../systemv/lpadmin -p Test3 -v file:/dev/null -E -m 
drv:///sample.drv/deskjet.ppd 2>&1
++echo "    lpadmin -p Test3 -v file:///dev/null -E -m 
drv:///sample.drv/deskjet.ppd"
++$runcups $VALGRIND ../systemv/lpadmin -p Test3 -v file:///dev/null -E -m 
drv:///sample.drv/deskjet.ppd 2>&1
+ if test $? != 0; then
+       echo "    FAILED"
+       exit 1
+@@ -29,8 +29,8 @@ echo ""
+ 
+ echo "Modify Printer Test"
+ echo ""
+-echo "    lpadmin -p Test3 -v file:/tmp/Test3 -o PageSize=A4"
+-$runcups $VALGRIND ../systemv/lpadmin -p Test3 -v file:/tmp/Test3 -o 
PageSize=A4 2>&1
++echo "    lpadmin -p Test3 -v file:///dev/null -o PageSize=A4"
++$runcups $VALGRIND ../systemv/lpadmin -p Test3 -v file:///dev/null -o 
PageSize=A4 2>&1
+ if test $? != 0; then
+       echo "    FAILED"
+       exit 1
+@@ -65,8 +65,8 @@ echo ""
+ 
+ echo "Add a printer for cupSNMP/IPPSupplies test"
+ echo ""
+-echo "    lpadmin -p Test4 -E -v file:/dev/null -m 
drv:///sample.drv/zebra.ppd"
+-$runcups $VALGRIND ../systemv/lpadmin -p Test4 -E -v file:/dev/null -m 
drv:///sample.drv/zebra.ppd 2>&1
++echo "    lpadmin -p Test4 -E -v file:///dev/null -m 
drv:///sample.drv/zebra.ppd"
++$runcups $VALGRIND ../systemv/lpadmin -p Test4 -E -v file:///dev/null -m 
drv:///sample.drv/zebra.ppd 2>&1
+ if test $? != 0; then
+       echo "    FAILED"
+       exit 1
-- 
2.40.0

-=-=-=-=-=-=-=-=-=-=-=-
Links: You receive all messages sent to this group.
View/Reply Online (#237992): 
https://lists.openembedded.org/g/openembedded-core/message/237992
Mute This Topic: https://lists.openembedded.org/mt/119600014/21656
Group Owner: [email protected]
Unsubscribe: https://lists.openembedded.org/g/openembedded-core/unsub 
[[email protected]]
-=-=-=-=-=-=-=-=-=-=-=-

Reply via email to