[PATCH 11/18] utils: Keep the last NOTE message as context for backtraces

Benjamin Berg benjamin at sipsolutions.net
Thu Oct 30 01:24:42 PDT 2025


From: Benjamin Berg <benjamin.berg at intel.com>

When storing a backtrace, keep the string that was last used in a NOTE
message as context information. Keep all past strings in a list so that
they will remain available.

With this, we are able to show in leak reports which test did the
allocation. This is useful to more quickly solve issues as it can be
hard to find the triggering test otherwise.

Signed-off-by: Benjamin Berg <benjamin.berg at intel.com>
---
 hostapd/ctrl_iface.c        |  2 ++
 src/utils/trace.c           | 34 +++++++++++++++++++++++++++++++++-
 src/utils/trace.h           | 25 ++++++++++++++++++++-----
 wpa_supplicant/ctrl_iface.c |  2 ++
 4 files changed, 57 insertions(+), 6 deletions(-)

diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
index d7e5c6071c..4fa824b4a6 100644
--- a/hostapd/ctrl_iface.c
+++ b/hostapd/ctrl_iface.c
@@ -30,6 +30,7 @@
 #include "utils/common.h"
 #include "utils/eloop.h"
 #include "utils/module_tests.h"
+#include "utils/trace.h"
 #include "common/version.h"
 #include "common/ieee802_11_defs.h"
 #include "common/ctrl_iface_common.h"
@@ -3893,6 +3894,7 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
 		wpa_debug_stop_log();
 	} else if (os_strncmp(buf, "NOTE ", 5) == 0) {
 		wpa_printf(MSG_INFO, "NOTE: %s", buf + 5);
+		wpa_trace_set_context(buf + 5);
 	} else if (os_strcmp(buf, "STATUS") == 0) {
 		reply_len = hostapd_ctrl_iface_status(hapd, reply,
 						      reply_size);
diff --git a/src/utils/trace.c b/src/utils/trace.c
index 1ec226515c..1d7ab0597d 100644
--- a/src/utils/trace.c
+++ b/src/utils/trace.c
@@ -17,6 +17,8 @@
 
 #ifdef WPA_TRACE
 
+const char *current_btrace_ctx;
+
 static struct dl_list active_references =
 { &active_references, &active_references };
 
@@ -346,7 +348,8 @@ size_t wpa_trace_calling_func(const char *buf[], size_t len)
 
 #endif /* WPA_TRACE_BFD */
 
-void wpa_trace_dump_func(const char *title, void **btrace, int btrace_num)
+void wpa_trace_dump_func(const char *title, void **btrace, int btrace_num,
+			 const char *btrace_ctx)
 {
 	char **sym;
 	int i;
@@ -378,6 +381,9 @@ void wpa_trace_dump_func(const char *title, void **btrace, int btrace_num)
 			state = TRACE_TAIL;
 	}
 	free(sym);
+	if (btrace_ctx)
+		wpa_printf(MSG_INFO, "WPA_TRACE: External context: %s",
+			   btrace_ctx);
 	wpa_printf(MSG_INFO, "WPA_TRACE: %s - END", title);
 }
 
@@ -423,4 +429,30 @@ void wpa_trace_deinit(void)
 #endif /* WPA_TRACE_BFD */
 }
 
+struct btrace_ctx_entry {
+	struct dl_list list;
+	char ctx[];
+};
+static struct dl_list old_btrace_ctxs = DL_LIST_HEAD_INIT(old_btrace_ctxs);
+
+void wpa_trace_set_context(const char *ctx)
+{
+#ifdef WPA_TRACE_BFD
+	/*
+	 * Old values might still be referenced, keep them in a list so that
+	 * they are not freed and so that a reference exists for the sanitizer.
+	 */
+	if (ctx) {
+		struct btrace_ctx_entry *entry;
+
+		entry = malloc(sizeof(*entry) + os_strlen(ctx) + 1);
+		strcpy(entry->ctx, ctx);
+		dl_list_add(&old_btrace_ctxs, &entry->list);
+
+		current_btrace_ctx = entry->ctx;
+	} else
+		current_btrace_ctx = NULL;
+#endif /* WPA_TRACE_BFD */
+}
+
 #endif /* WPA_TRACE */
diff --git a/src/utils/trace.h b/src/utils/trace.h
index d1636de077..f35234e7d3 100644
--- a/src/utils/trace.h
+++ b/src/utils/trace.h
@@ -16,7 +16,12 @@
 
 #include "list.h"
 
-#define WPA_TRACE_INFO void *btrace[WPA_TRACE_LEN]; int btrace_num;
+extern const char *current_btrace_ctx;
+
+#define WPA_TRACE_INFO			\
+	void *btrace[WPA_TRACE_LEN];	\
+	int btrace_num;			\
+	const char *btrace_ctx;
 
 struct wpa_trace_ref {
 	struct dl_list list;
@@ -26,10 +31,15 @@ struct wpa_trace_ref {
 #define WPA_TRACE_REF(name) struct wpa_trace_ref wpa_trace_ref_##name
 
 #define wpa_trace_dump(title, ptr) \
-	wpa_trace_dump_func((title), (ptr)->btrace, (ptr)->btrace_num)
-void wpa_trace_dump_func(const char *title, void **btrace, int btrace_num);
-#define wpa_trace_record(ptr) \
-	(ptr)->btrace_num = backtrace((ptr)->btrace, WPA_TRACE_LEN)
+	wpa_trace_dump_func((title), (ptr)->btrace, (ptr)->btrace_num,	\
+			    (ptr)->btrace_ctx)
+void wpa_trace_dump_func(const char *title, void **btrace, int btrace_num,
+			 const char *btrace_ctx);
+#define wpa_trace_record(ptr)						\
+	do {								\
+		(ptr)->btrace_num = backtrace((ptr)->btrace, WPA_TRACE_LEN); \
+		(ptr)->btrace_ctx = current_btrace_ctx;			\
+	} while (0)
 void wpa_trace_show(const char *title);
 #define wpa_trace_add_ref(ptr, name, addr) \
 	wpa_trace_add_ref_func(&(ptr)->wpa_trace_ref_##name, (addr))
@@ -41,6 +51,7 @@ void wpa_trace_add_ref_func(struct wpa_trace_ref *ref, const void *addr);
 	} while (0)
 void wpa_trace_check_ref(const void *addr);
 size_t wpa_trace_calling_func(const char *buf[], size_t len);
+void wpa_trace_set_context(const char *ctx);
 
 #else /* WPA_TRACE */
 
@@ -53,6 +64,10 @@ size_t wpa_trace_calling_func(const char *buf[], size_t len);
 #define wpa_trace_remove_ref(ptr, name, addr) do { } while (0)
 #define wpa_trace_check_ref(addr) do { } while (0)
 
+static inline void wpa_trace_set_context(const char *ctx)
+{
+}
+
 #endif /* WPA_TRACE */
 
 
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index 050ed16240..4f4e1832af 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -15,6 +15,7 @@
 #include "utils/eloop.h"
 #include "utils/uuid.h"
 #include "utils/module_tests.h"
+#include "utils/trace.h"
 #include "common/version.h"
 #include "common/ieee802_11_defs.h"
 #include "common/ieee802_11_common.h"
@@ -13198,6 +13199,7 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
 			reply_len = -1;
 	} else if (os_strncmp(buf, "NOTE ", 5) == 0) {
 		wpa_printf(MSG_INFO, "NOTE: %s", buf + 5);
+		wpa_trace_set_context(buf + 5);
 	} else if (os_strcmp(buf, "MIB") == 0) {
 		reply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size);
 		if (reply_len >= 0) {
-- 
2.51.0




More information about the Hostap mailing list