From 38f0b0364dec820974e81871da5ec7dcccdbe842 Mon Sep 17 00:00:00 2001
From: ulfvonbelow <strilen@tilde.club>
Date: Sun, 29 Jan 2023 06:38:07 -0600
Subject: [PATCH] NAMESTORE: fix overread in handle_record_store.

A RecordStoreMessage looks like this:

| header | key | recordset |

A StoreActivity's rs field is supposed to point to the record
set. handle_record_store tries to make a copy of this record set, but it does
it by allocating enough memory for both key and recordset, then copying
sizeof(key) + sizeof(recordset) bytes into it *starting from recordset*. This
causes memcpy to read past the end of recordset by sizeof(key) bytes. There's
still enough room in the allocated region for it, though, so it's only an
overread.
---
 src/namestore/gnunet-service-namestore.c | 17 +++++++++++------
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/src/namestore/gnunet-service-namestore.c b/src/namestore/gnunet-service-namestore.c
index d25287c9f..ed06b1dc5 100644
--- a/src/namestore/gnunet-service-namestore.c
+++ b/src/namestore/gnunet-service-namestore.c
@@ -1735,11 +1735,19 @@ handle_record_store (void *cls, const struct RecordStoreMessage *rp_msg)
   ssize_t read;
   size_t key_len;
   size_t kb_read;
+  size_t rp_msg_len;
+  size_t rs_len;
+  size_t rs_off;
+  size_t body_len;
   struct StoreActivity *sa;
   struct RecordSet *rs;
   enum GNUNET_ErrorCode res;
 
   key_len = ntohs (rp_msg->key_len);
+  rp_msg_len = ntohs (rp_msg->gns_header.header.size);
+  body_len = rp_msg_len - sizeof (*rp_msg);
+  rs_off = sizeof (*rp_msg) + key_len;
+  rs_len = rp_msg_len - rs_off;
   if ((GNUNET_SYSERR ==
        GNUNET_IDENTITY_read_private_key_from_buffer (&rp_msg[1],
                                                      key_len,
@@ -1756,7 +1764,7 @@ handle_record_store (void *cls, const struct RecordStoreMessage *rp_msg)
               "Received NAMESTORE_RECORD_STORE message\n");
   rid = ntohl (rp_msg->gns_header.r_id);
   rd_set_count = ntohs (rp_msg->rd_set_count);
-  buf = (const char *) &rp_msg[1] + key_len;
+  buf = (const char *) rp_msg + rs_off;
   for (int i = 0; i < rd_set_count; i++)
   {
     rs = (struct RecordSet *) buf;
@@ -1770,15 +1778,12 @@ handle_record_store (void *cls, const struct RecordStoreMessage *rp_msg)
     }
     buf += read;
   }
-  sa = GNUNET_malloc (sizeof(struct StoreActivity)
-                      + ntohs (rp_msg->gns_header.header.size)
-                      - sizeof (*rp_msg));
+  sa = GNUNET_malloc (sizeof(struct StoreActivity) + rs_len);
   GNUNET_CONTAINER_DLL_insert (sa_head, sa_tail, sa);
   sa->nc = nc;
   sa->rs = (struct RecordSet *) &sa[1];
   sa->rd_set_count = rd_set_count;
-  GNUNET_memcpy (&sa[1], (char *) &rp_msg[1] + key_len,
-                 ntohs (rp_msg->gns_header.header.size) - sizeof (*rp_msg));
+  GNUNET_memcpy (&sa[1], (char *) rp_msg + rs_off, rs_len);
   sa->rid = rid;
   sa->rd_set_pos = 0;
   sa->private_key = zone;
-- 
2.38.1

