Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incorrect error handling in httpGets2 #879

Open
xypron opened this issue Jan 31, 2024 · 13 comments
Open

Incorrect error handling in httpGets2 #879

xypron opened this issue Jan 31, 2024 · 13 comments
Assignees
Labels
bug Something isn't working priority-low
Milestone

Comments

@xypron
Copy link

xypron commented Jan 31, 2024

Describe the bug

cups-browsed runs into an infinite loop in httpGets.

To Reproduce

The issues was sometimes observed in cups-browsed on Ubuntu 24.04. See https://bugs.launchpad.net/ubuntu/+source/cups-browsed/+bug/2049315.

Expected behavior

httpGets2 should not enter an endless loop if a connection error occurs or the webserver provides invalid data.

System Information:

  • OS and its version: Ubuntu 24.04
  • Application cups-browsed
  • CUPS version 2.4.6

Additional context

Debugging showed negative values of http->used in httpGets.

Some error paths lead to negative numbers being added to http->used. The following diff should avoid this:

diff --git a/cups/http.c b/cups/http.c
index c154412b1..57db33ae3 100644
--- a/cups/http.c
+++ b/cups/http.c
@@ -1091,6 +1091,7 @@ httpGets2(http_t *http,                   // I - HTTP connection
            continue;
 
          http->error = WSAGetLastError();
+         return (NULL);
        }
        else if (WSAGetLastError() != http->error)
        {
@@ -1113,6 +1114,7 @@ httpGets2(http_t *http,                   // I - HTTP connection
            continue;
 
          http->error = errno;
+         return (NULL);
        }
        else if (errno != http->error)
        {
xypron added a commit to xypron/cups that referenced this issue Jan 31, 2024
Closes: OpenPrinting#879

In case of some errors httpGets2 waits for the next packet. In all cases of
errors it should return NULL.

Signed-off-by: Heinrich Schuchardt <[email protected]>
xypron added a commit to xypron/cups that referenced this issue Feb 1, 2024
Closes: OpenPrinting#879

In case of some errors httpGets2 waits for the next packet. In all other
cases of errors it should return NULL to avoid negative values of
http->used leading to ending up in an endless loop.

Signed-off-by: Heinrich Schuchardt <[email protected]>
@zdohnal
Copy link
Member

zdohnal commented Feb 16, 2024

The discussion happens on the PR, setting the correct label.

@michaelrsweet
Copy link
Member

[master c89dd90] Fix httpGets timeout handling (Issue #879)

[2.4.x cde48f0] Fix httpGets timeout handling (Issue #879)

@michaelrsweet michaelrsweet self-assigned this Apr 2, 2024
@michaelrsweet michaelrsweet added bug Something isn't working priority-low labels Apr 2, 2024
@michaelrsweet michaelrsweet added this to the v2.4.x milestone Apr 2, 2024
@tillkamppeter
Copy link
Member

Unfortunately, the fix for this bug is not actually working. In Ubuntu 24.04 the fix is applied but the bug still occurs. See

https://bugs.launchpad.net/ubuntu/+source/cups-browsed/+bug/2067918

and there expecially comment #10

https://bugs.launchpad.net/ubuntu/+source/cups-browsed/+bug/2067918/comments/10

@tillkamppeter tillkamppeter reopened this Sep 6, 2024
@tillkamppeter
Copy link
Member

Many users of Ubuntu 24.04 are still reporting this very same problem.

@jknockel
Copy link

jknockel commented Sep 9, 2024

Unfortunately, the fix for this bug is not actually working. In Ubuntu 24.04 the fix is applied but the bug still occurs.

Are you sure that the fix has been applied in Ubuntu 24.04? I looked at the source (via apt-get source) and did not see the changes applied.

@michaelrsweet
Copy link
Member

@tillkamppeter Can you respond to @jknockel ?

@tillkamppeter
Copy link
Member

Sorry for the late reply. I was very busy, had some days off, a conference, and now there was also the vulnerability.

I have checked now and the upstream introduction of the fix was in 2.4.8 and 24.04 has only 2.4.7, and I see no distro patch in 2.4.7 which backports the fix. Probably the fix was too late for the release of 24.04 LTS.

We need to somehow test it, in 24.10 (which has CUPS 2.4.10 which contains it) and perhaps also a 2.4.7 with backported fix in a PPA for 24.04, to check whether one could do an SRU.

@tillkamppeter
Copy link
Member

I got somebody reporting to still have the cups-browsed issue on Ubuntu 24.10 with CUPS 2.4.10:

https://bugs.launchpad.net/ubuntu/+source/cups-browsed/+bug/2049315/comments/29

As CUPS 2.4.10 contains the changes described in this issue report, it seems that the change does not fix the issue.

@tillkamppeter
Copy link
Member

For me it also looks like that the patch is without effect, as if the added return (NULL); in line 1245 (2.4.x branch) had not been there, the return (NULL); in line 1254 had been reached, so presence or absence of the patch had the same result. Am I right?

@michaelrsweet
Copy link
Member

@tillkamppeter According to the bug report, http->used is going negative, which should never happen. Are there any patches being applied to cups/http.c for the Debian/Ubuntu CUPS release?

@tillkamppeter
Copy link
Member

I have checked now and the Ubuntu package of CUPS does not apply any patches to cups/http.c. The relevant parts of the file are identical with the original (only difference is your _cupsSetError() one-liner change. due to the fact that Ubuntu uses 2.4.10 and not .11).

I also had a look through the code of cups/http.c. It is not possile with it to make http->used negative and with the data structure being opaque there is no direct access fot external programs which just use libcups. Looks rather like an uninitialized data structure used somewhere.

@tillkamppeter
Copy link
Member

It is easy to see when reviewing the code of httpGets() that if, when the function is called, http->used is negative, nothing of the code inside the outer while loop, while (lineptr < lineend), does anything: while (http->used == 0) {...] -> for (bufptr = http->buffer, bufend = http->buffer + http->used; lineptr < lineend && bufptr < bufend;) {...} (with http->used < 0 there is bufptr > bufend) -> http->used -= (int)(bufptr - http->buffer); if (http->used > 0) {...} (http->used does not get changed here) -> if (eol) {...} (for loop did not run, so no EOL found), So we have a perfect infinite loop not logging anything.

The code of cups-browsed (daemon/cups-browsed.c) creates the http variable always with httpConnect2(host, port, NULL, AF_UNSPEC, encryption, 1, 3000, NULL) which should create a valid http_t data structure or NULL, where in the latter case httpGets() returns right in the beginning.

So only thing which could cause http->used be negative is something like a buffer overflow, http being overwritten.

tillkamppeter added a commit to OpenPrinting/cups-browsed that referenced this issue Dec 18, 2024
Before, a HTTP connection to the local CUPS was opened and kept in a
global variable of http_t* during the whole session. Functions
connecting to the local CUPS just used this connection.

Later on multi-threading for time consuming actions like DNS-SD
resolving and creating CUPS queues got introduced.

Also the sub-threads for creating CUPS queues used the global HTTP
connection. This could have cause drace conditions messing up the
http_t data structure.

Most probably this has caused to the "used" field of the data
structure (number of bytes which are in use in the internal buffer,
must be >= 0) getting negative nad this making the httpGets() function
of libcups busy-looping, which caused cups-browsed taking 100% of one
or two CPU cores and requiring SIGKILL to get terminated.

Bug reports at Ubuntu:

  - cups-browsed running non-stop on two cores
    https://bugs.launchpad.net/bugs/2049315

  - cups-browsed high-cpu usage
    https://bugs.launchpad.net/bugs/2067918

  - cups-browsed delays shutdown for 90 s
    https://bugs.launchpad.net/bugs/2073504

Bug report on CUPS:

  - OpenPrinting/cups#879

This commit does away with the global connection. Each function which
had used the global HTTP connection to the local CUPS creates an HTTP
connection onits own now and closes it before returning.CUPS can
accept several HTTP connections in parallel, therefore it is no
problem if we have individual connections now and if they happen in
parallel due to the sub-threads.

Note that testing is needed to determine whether this change actually
fixes the bug. The probability is high, butdue to the fact that the
bug is not easily reproducable it will take some time.
@tillkamppeter
Copy link
Member

I have now modified cups-browsed to not use a global HTTP connection to the local CUPS any more but individual connections, to avoid any race conditions and mess-ups in the parallel threads:

OpenPrinting/cups-browsed@a8b645e4b3

This should fix the problem.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working priority-low
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants