4 comments

  • ZiiS 40 minutes ago
    A good write up explaining how assumptions of network and security design have changed so much over the years. Also you have to give credit nowadays for not overly sensationalizing 'heebie-jeebies level 6'. I certainly continue reusing a connection I assumed was TLS after a cancel so was vulnerable to a DoS; but equally if the next statement was canceled I would switch to a new connection no harm no foul.
  • rlpb 3 hours ago
    TCP has an "urgent data" feature that might have been used for this kind of thing, used for Ctrl-C in telnet, etc. It can be used to bypass any pending send buffer and received by the server ahead of any unread data.
    • mike_hearn 2 hours ago
      Fun fact: Oracle implements cancellation this way.

      The downside is that sometimes connections are proxied in ways that lose these unusual packets. Looking at you, Docker...

    • ZiiS 50 minutes ago
      Unfortunately the can be many buffers between you and the server which "urgent data" doesn't skip by design. (the were also lots of implementation problems)
  • jtwaleson 4 hours ago
    From the title I was hoping for this being hacky on the server application side, like how it aborts and clears the memory for a running query.

    Still an interesting read. Just wondering, why can't the TCP connection of the query not be used to send a cancellation request? Why does it have the be out of band?

    • mike_hearn 2 hours ago
      Because Postgres is a very old codebase and was written in a style that assumes there are no threads, and thus there's nothing to listen for a cancellation packet whilst work is getting done. A lot of UNIXes had very poor support for threads for a long time and so this kind of multi-process architecture is common in old codebases.

      The TCP URG bit came out of this kind of problem. It triggers a SIGURG signal on UNIX which interrupts the process. Oracle works this way.

      These days you'd implement cancellation by having one thread handle inbound messages and another thread do the actual work with shared memory to implement a cooperative cancellation mechanic.

      But we should in general have sympathy here. Very little software and very few protocols properly implements any form of cancellation. HTTP hardly does for normal requests, and even if it did, how many web servers abort request processing if the connection drops?

      • johannes1234321 31 minutes ago
        It isn't really easy to do. A client may send tons of data over the connection, probably data which is calculated by the client as the client's buffer empties. If the server clears the buffers all the time to check for a cancellation it may have quite bad consequences.
    • toast0 4 hours ago
      I don't know much about postgres, but as I understand it, it's a pretty standard server application. Read a request from the client, work on the request, send the result, read the next request.

      Changing that to poll for a cancellation while working is a big change. Also, the server would need to buffer any pipelined requests while looking for a cancellation request. A second connection is not without wrinkles, but it avoids a lot of network complexity.

    • hlinnaka 1 hour ago
      Because then the cancellation request would get queued behind any other data that's in flight from the client to the server. In the worst case the TCP buffers are full, and the client cannot even send the request until the server processes some of the existing data that's in-flight.
      • adrian_b 1 minute ago
        As others have said, TCP allows sending urgent packets, precisely for solving this problem.

        At the receiver, a signal handler must be used, which will be invoked when an urgent packet is received.

    • CamouflagedKiwi 2 hours ago
      It's basically got a thread per connection, while it's working on a query that thread isn't listening to incoming traffic on the network socket any more.
    • bob1029 4 hours ago
      MSSQL uses a special message over an existing connection:

      https://learn.microsoft.com/en-us/openspecs/windows_protocol...

  • michalc 4 hours ago
    I think I can understand why this wasn’t addressed for so long: in the vast majority of cases if your db is exposed on a network level to untrusted sources, then you probably have far bigger problems?
    • hrmtst93837 1 hour ago
      That's the kind of hand-wave that turns into a CVE later. Network exposure is one thing, but weird signal handling in local tooling can still become a cross-session bug or a nasty security footgun on shared infra, terminals, or jump boxes.

      If you have shared psql sessions in tmux or on a jump box one bad cancel can trash someone else's work. 'Just firewall it' is how you end up owned by the intern with shell access.

    • pilif 2 hours ago
      it's also very tricky to do given the current architecture on the server side where one single-threaded process handles the connection and uses (for all intents and purposes) sync io.

      In such a scenario, listening (and acting) on cancellation requests on the same connection becomes very hard, so fixing this goes way beyond "just".