]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MAJOR: ring: tcp forward on ring can break the reader counter.
authorEmeric Brun <ebrun@haproxy.com>
Wed, 2 Dec 2020 16:02:09 +0000 (17:02 +0100)
committerWilly Tarreau <w@1wt.eu>
Wed, 2 Dec 2020 19:17:19 +0000 (20:17 +0100)
If the session is not established, the applet handler could leave
with the applet detached from the ring. At next call, the attach
counter will be decreased again causing unpredectable behavior.

This patch should be backported on branches >=2.2

src/sink.c

index 4995270e49702f7e8e3455800a6672f4fc4c9552..a7f689780745fbccd44ac2140dda3073d425810e 100644 (file)
@@ -348,18 +348,18 @@ static void sink_forward_io_handler(struct appctx *appctx)
                ofs += ring->ofs;
        }
 
-       /* we were already there, adjust the offset to be relative to
-        * the buffer's head and remove us from the counter.
-        */
-       ofs -= ring->ofs;
-       BUG_ON(ofs >= buf->size);
-       HA_ATOMIC_SUB(b_peek(buf, ofs), 1);
-
        /* in this loop, ofs always points to the counter byte that precedes
         * the message so that we can take our reference there if we have to
         * stop before the end (ret=0).
         */
        if (si_opposite(si)->state == SI_ST_EST) {
+               /* we were already there, adjust the offset to be relative to
+                * the buffer's head and remove us from the counter.
+                */
+               ofs -= ring->ofs;
+               BUG_ON(ofs >= buf->size);
+               HA_ATOMIC_SUB(b_peek(buf, ofs), 1);
+
                ret = 1;
                while (ofs + 1 < b_data(buf)) {
                        cnt = 1;
@@ -488,18 +488,18 @@ static void sink_forward_oc_io_handler(struct appctx *appctx)
                ofs += ring->ofs;
        }
 
-       /* we were already there, adjust the offset to be relative to
-        * the buffer's head and remove us from the counter.
-        */
-       ofs -= ring->ofs;
-       BUG_ON(ofs >= buf->size);
-       HA_ATOMIC_SUB(b_peek(buf, ofs), 1);
-
        /* in this loop, ofs always points to the counter byte that precedes
         * the message so that we can take our reference there if we have to
         * stop before the end (ret=0).
         */
        if (si_opposite(si)->state == SI_ST_EST) {
+               /* we were already there, adjust the offset to be relative to
+                * the buffer's head and remove us from the counter.
+                */
+               ofs -= ring->ofs;
+               BUG_ON(ofs >= buf->size);
+               HA_ATOMIC_SUB(b_peek(buf, ofs), 1);
+
                ret = 1;
                while (ofs + 1 < b_data(buf)) {
                        cnt = 1;