]> git.ipfire.org Git - thirdparty/knot-dns.git/commitdiff
fixup! kxdpgun: allow various modes exploiting left-open connections
authorLibor Peltan <libor.peltan@nic.cz>
Fri, 12 Nov 2021 16:11:18 +0000 (17:11 +0100)
committerDaniel Salzman <daniel.salzman@nic.cz>
Wed, 16 Mar 2022 13:58:06 +0000 (14:58 +0100)
src/knot/server/xdp-handler.c
src/libknot/xdp/tcp.c
src/libknot/xdp/tcp.h
src/libknot/xdp/tcp_iobuf.c
src/libknot/xdp/tcp_iobuf.h
src/utils/kxdpgun/main.c
tests/libknot/test_xdp_tcp.c

index 6c0be11087ebd0cc26bbe6901a1875fb6f80c863..2e0ac166d6d0320e781b6320836d79fdca25d925 100644 (file)
@@ -222,7 +222,7 @@ static void handle_tcp(xdp_handle_ctx_t *ctx, knot_layer_t *layer,
                                        continue;
                                }
 
-                               (void)knot_tcp_reply_data(rl, ctx->tcp_table, ans->wire, ans->size);
+                               (void)knot_tcp_reply_data(rl, ctx->tcp_table, false, ans->wire, ans->size);
                                // ignore unprobable ENOMEM here
                        }
 
index 9b052b46a3e515ac324e9c98f51324e0f78da23d..900d49c2df8540707fc5f3bb76c456723302e7da 100644 (file)
@@ -434,12 +434,12 @@ int knot_tcp_recv(knot_tcp_relay_t *relays, knot_xdp_msg_t *msgs, uint32_t count
 
 _public_
 int knot_tcp_reply_data(knot_tcp_relay_t *relay, knot_tcp_table_t *tcp_table,
-                        uint8_t *data, size_t len)
+                        bool ignore_lastbyte, uint8_t *data, size_t len)
 {
        if (relay == NULL || tcp_table == NULL || relay->conn == NULL) {
                return KNOT_EINVAL;
        }
-       int ret = tcp_outbufs_add(&relay->conn->outbufs, data, len,
+       int ret = tcp_outbufs_add(&relay->conn->outbufs, data, len, ignore_lastbyte,
                                  relay->conn->mss, &tcp_table->outbufs_total);
 
        if (tcp_table->next_obuf == NULL && tcp_outbufs_usage(&relay->conn->outbufs) > 0) {
index a94a302368cd71b69c4da80a801ab768f89856ce..cefd96780e0ea9bdb86e9e602009a9a1d4a70c7b 100644 (file)
@@ -167,13 +167,14 @@ int knot_tcp_recv(knot_tcp_relay_t *relays, knot_xdp_msg_t *msgs, uint32_t count
  *
  * \param relay       Relay with active connection.
  * \param tcp_table   TCP table.
+ * \param ignore_lastbyte  Evil mode: drop last byte of the payload.
  * \param data        Data payload, possibly > MSS and > window.
  * \param len         Payload length, < 64k.
  *
  * \return KNOT_E*
  */
 int knot_tcp_reply_data(knot_tcp_relay_t *relay, knot_tcp_table_t *tcp_table,
-                        uint8_t *data, size_t len);
+                        bool ignore_lastbyte, uint8_t *data, size_t len);
 
 /*!
  * \brief Send TCP packets.
index fded5ff4336dbfb9d72462c9ffb72f2ed89a1cef..51701999f508aad611eced54d808a4f9ca5ae7e6 100644 (file)
@@ -177,7 +177,7 @@ int tcp_inbuf_update(struct iovec *buffer, struct iovec data,
 }
 
 int tcp_outbufs_add(struct tcp_outbufs *ob, uint8_t *data, size_t len,
-                    uint32_t mss, size_t *outbufs_total)
+                    bool ignore_lastbyte, uint32_t mss, size_t *outbufs_total)
 {
        if (len > UINT16_MAX) {
                return KNOT_ELIMIT;
@@ -195,6 +195,9 @@ int tcp_outbufs_add(struct tcp_outbufs *ob, uint8_t *data, size_t len,
                }
                *outbufs_total += sizeof(*newob) + newlen;
                newob->len = newlen;
+               if (ignore_lastbyte) {
+                       newob->len--;
+               }
                memcpy(newob->bytes, &prefix, prefix_len);
                memcpy(newob->bytes + prefix_len, data, newlen - prefix_len);
 
index b140dffe7fa5c1640fce73250016de33fe51f909..c3a7af038a3aa81422832cd44d206e63d695f731 100644 (file)
@@ -62,13 +62,14 @@ int tcp_inbuf_update(struct iovec *buffer, struct iovec data,
  * \param ob               Output buffers to be updated.
  * \param data             Payload to be sent.
  * \param len              Payload length.
+ * \param ignore_lastbyte  Evil mode: drop last byte of the payload.
  * \param mss              Connection outgoing MSS.
  * \param outbufs_total    In/out: total outbuf statistic to be updated.
  *
  * \return KNOT_E*
  */
 int tcp_outbufs_add(struct tcp_outbufs *ob, uint8_t *data, size_t len,
-                    uint32_t mss, size_t *outbufs_total);
+                    bool ignore_lastbyte, uint32_t mss, size_t *outbufs_total);
 
 /*!
  * \brief Remove+free acked data from output buffers.
index c1aba6e3f62924dcb238058605e0d00c8bdcac79..1c0fd48b9e8dcb33c8e8c748db44170b49065ebb 100644 (file)
@@ -445,10 +445,9 @@ void *xdp_gun_thread(void *_ctx)
                                                                break;
                                                        }
                                                        put_dns_payload(&payl, true, ctx, &payload_ptr);
-                                                       if (ctx->ignore1 & KXDPGUN_IGNORE_LASTBYTE) {
-                                                               payl.iov_len--;
-                                                       }
-                                                       ret = knot_tcp_reply_data(rl, tcp_table, payl.iov_base, payl.iov_len);
+                                                       ret = knot_tcp_reply_data(rl, tcp_table,
+                                                                                 (ctx->ignore1 & KXDPGUN_IGNORE_LASTBYTE),
+                                                                                 payl.iov_base, payl.iov_len);
                                                        if (ret != KNOT_EOK) {
                                                                errors++;
                                                        }
index a1427c2b541c30c842dff7a23dc9ffd076b30a7d..d0299af25e2e65bf6befe042066ee68f9563b183 100644 (file)
@@ -534,7 +534,7 @@ void test_obufs(void)
        rl.conn->window_size = 65536;
        send2_mss = TEST_MSS;
 
-       int ret = knot_tcp_reply_data(&rl, test_table, data, DATA_LEN), i = 0;
+       int ret = knot_tcp_reply_data(&rl, test_table, false, data, DATA_LEN), i = 0;
        is_int(KNOT_EOK, ret, "obufs: fill with data");
        for (struct tcp_outbuf *ob = rl.conn->outbufs.bufs; ob != NULL; ob = ob->next, i++) {
                if (ob->next == NULL) {