]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
- Fix CVE-2026-52863, Memory corruption could lead to crash and
authorW.C.A. Wijngaards <wouter@nlnetlabs.nl>
Wed, 22 Jul 2026 08:16:03 +0000 (10:16 +0200)
committerW.C.A. Wijngaards <wouter@nlnetlabs.nl>
Wed, 22 Jul 2026 08:16:03 +0000 (10:16 +0200)
  denial of service. Thanks to Qifan Zhang, Palo Alto Networks,
  for the report.

services/mesh.c
services/mesh.h
testcode/unitmain.c

index f06c1cb9d6181780cce7849fba4c4af181094abb..cd78d1c2913bdcd67214914e679a1287e6c0e33b 100644 (file)
@@ -933,8 +933,7 @@ cfg_region_strlist_copy(struct regional* region, struct config_strlist* list)
        return result;
 }
 
-/** Copy the client info to the query region. */
-static struct respip_client_info*
+struct respip_client_info*
 mesh_copy_client_info(struct regional* region, struct respip_client_info* cinfo)
 {
        size_t i;
@@ -979,6 +978,11 @@ mesh_copy_client_info(struct regional* region, struct respip_client_info* cinfo)
                        cinfo->view->name);
                if(!client_info->view_name)
                        return NULL;
+       } else if(cinfo->view_name) {
+               client_info->view_name = regional_strdup(region,
+                       cinfo->view_name);
+               if(!client_info->view_name)
+                       return NULL;
        }
        return client_info;
 }
index 352260e26eeace9c751b3fad5233ea9077363dcd..6ea63d098916f9f57f8ac7641fcc262e5dd406c9 100644 (file)
@@ -738,4 +738,8 @@ void mesh_respond_serve_expired(struct mesh_state* mstate);
 void mesh_remove_callback(struct mesh_area* mesh, struct query_info* qinfo,
        uint16_t qflags, mesh_cb_func_type cb, void* cb_arg);
 
+/** Copy the client info to the query region. */
+struct respip_client_info* mesh_copy_client_info(struct regional* region,
+       struct respip_client_info* cinfo);
+
 #endif /* SERVICES_MESH_H */
index 4bc756a0705fbb6c6759b05b0c427639ac2f81ea..62f37375f756fc1a2ebbd47eec715dc6ca9619d4 100644 (file)
@@ -1282,6 +1282,61 @@ static void localzone_test(void)
        localzone_parents_test();
 }
 
+#include "services/mesh.h"
+/** mesh unit tests */
+static void mesh_test(void)
+{
+       struct regional* r2, *r3;
+       struct respip_client_info* c1, *c2, *c3;
+       unit_show_func("services/mesh.c", "mesh_copy_client_info");
+       r2 = regional_create();
+       r3 = regional_create();
+       if(!r2 || !r3) fatal_exit("out of memory");
+
+       c1 = calloc(1, sizeof(*c1));
+       if(!c1) fatal_exit("out of memory");
+       c1->view = calloc(1, sizeof(*c1->view));
+       if(!c1->view) fatal_exit("out of memory");
+       c1->view->name = strdup("view1");
+       if(!c1->view->name) fatal_exit("out of memory");
+
+       c2 = mesh_copy_client_info(r2, c1);
+       if(!c2) fatal_exit("out of memory");
+       c3 = mesh_copy_client_info(r3, c2);
+       if(!c3) fatal_exit("out of memory");
+
+       unit_assert(strcmp(c1->view->name, c2->view_name) == 0);
+       unit_assert(strcmp(c1->view->name, c3->view_name) == 0);
+
+       /* make sure that the c3 view_name is in the r3 region. */
+       unit_assert(r3->next == NULL);  /* only the first chunk present atm */
+       if(strlen(c3->view_name) >= r3->large_object_size) {
+               char* a = r3->large_list;
+               int found = 0;
+               while(a) {
+                       if(strcmp(c3->view_name,
+                               a + /* ALIGNEMENT */ sizeof(uint64_t)) == 0) {
+                               found = 1;
+                               break;
+                       }
+                       a = *(char**)a;
+               }
+               unit_assert(found == 1);
+       } else {
+               /* The allocation is expected in the r3 region first chunk */
+               unit_assert((uint8_t*)c3->view_name < ((uint8_t*)r3)+r3->first_size);
+       }
+
+       regional_destroy(r2);
+       /* ASAN should complain for the freed access below */
+       unit_assert(strcmp(c1->view->name, c3->view_name) == 0);
+
+       regional_destroy(r3);
+       free(c1->view->name);
+       free(c1->view);
+       free(c1);
+}
+
 void unit_show_func(const char* file, const char* func)
 {
        printf("test %s:%s\n", file, func);
@@ -1356,6 +1411,7 @@ main(int argc, char* argv[])
        msgparse_test();
        edns_ede_answer_encode_test();
        localzone_test();
+       mesh_test();
 #ifdef CLIENT_SUBNET
        ecs_test();
 #endif /* CLIENT_SUBNET */