]> git.ipfire.org Git - thirdparty/rspamd.git/commitdiff
[Fix] Fix TCP framing protocol endianness mismatch
authorVsevolod Stakhov <vsevolod@rspamd.com>
Wed, 8 Oct 2025 08:10:09 +0000 (09:10 +0100)
committerVsevolod Stakhov <vsevolod@rspamd.com>
Wed, 8 Oct 2025 08:10:09 +0000 (09:10 +0100)
The TCP framing protocol had an endianness mismatch for the 2-byte frame size header. The client was sending and expecting frame lengths in little-endian, while the server was sending and expecting them in network byte order (big-endian). This inconsistency corrupted frame lengths, leading to protocol errors and communication failures.

Changes:
* Server now uses GUINT16_TO_LE() instead of htons() for frame length encoding
* Server now uses GUINT16_FROM_LE() instead of ntohs() for frame length reading
* Server frame length parsing now reconstructs little-endian format
* Updated comment to reflect little-endian byte order consistency

All TCP frame lengths are now consistently transferred as little-endian numbers.

src/fuzzy_storage.c
src/plugins/fuzzy_check.c

index da2d920911cdb8120c5998f6a900b3f53360c9cd..d0edcca81aaac5ab5b9cd431f2b8ee06ca4242c8 100644 (file)
@@ -1052,7 +1052,7 @@ rspamd_fuzzy_tcp_enqueue_reply(struct fuzzy_session *session)
 
        /* Create reply queue element */
        reply_elt = g_malloc0(sizeof(*reply_elt));
-       reply_elt->rep.size_hdr = htons((uint16_t) len);
+       reply_elt->rep.size_hdr = GUINT16_TO_LE((uint16_t) len);
        memcpy(&reply_elt->rep.payload, data, len);
        reply_elt->written = 0;
 
@@ -2572,7 +2572,7 @@ rspamd_fuzzy_tcp_write_reply(struct fuzzy_tcp_session *session,
                                                         struct fuzzy_tcp_reply_queue_elt *reply)
 {
        gssize r;
-       gsize total_len = sizeof(reply->rep.size_hdr) + ntohs(reply->rep.size_hdr);
+       gsize total_len = sizeof(reply->rep.size_hdr) + GUINT16_FROM_LE(reply->rep.size_hdr);
        gsize remaining = total_len - reply->written;
        unsigned char *data = ((unsigned char *) &reply->rep) + reply->written;
 
@@ -2664,7 +2664,8 @@ rspamd_fuzzy_tcp_io(EV_P_ ev_io *w, int revents)
                                if (processed_offset < session->bytes_unprocessed) {
                                        uint16_t first_byte = session->cur_frame_state & 0xFF;
                                        uint16_t second_byte = session->input_buf[processed_offset];
-                                       session->cur_frame_state = 0xC000 | ((first_byte << 8) | second_byte);
+                                       /* Reconstruct in little-endian byte order */
+                                       session->cur_frame_state = 0xC000 | (first_byte | (second_byte << 8));
                                        processed_offset++;
                                }
                                else {
index ff9fc6dfbe12ba3c0eba3c3eef605478244ec815..743fdd37501b03bc9939b971d27f8514480f3cc4 100644 (file)
@@ -209,7 +209,7 @@ struct fuzzy_tcp_pending_command {
  * TCP write queue element - contains framed command ready to send
  */
 struct fuzzy_tcp_write_buf {
-       uint16_t size_hdr;   /* Frame size in network byte order */
+       uint16_t size_hdr;   /* Frame size in little-endian byte order */
        unsigned char *data; /* Command data (encrypted) */
        gsize total_len;     /* Total length: sizeof(size_hdr) + data_len */
        gsize bytes_written; /* How many bytes already written */