bug in nl80211_deliver_pending_events()

e9hack e9hack at gmail.com
Mon Dec 1 10:54:54 PST 2025


If nl80211_deliver_pending_events() is called with an empty global
pending events list a page fault does occur. The code to copy the
content of the global pending event list to the local list does not
cover this behaviour. The code puts global->pending_events as an entry
into the local pending events list instead of generating an empty
list. The first retrieved event is a pointer to
global->pending_events. event->handler, event->msg and event->data are
null. The call of event->handler(event->msg, event->data) results in a
page fault. The following patch solves the issue:

--- driver_nl80211.c.save    2025-11-30 21:17:12.628389679 +0100
+++ driver_nl80211.c    2025-12-01 16:08:08.342872411 +0100
@@ -536,24 +536,28 @@ static void nl80211_remove_pending_event
 static void nl80211_deliver_pending_events(void *eloop_ctx, void *data)
 {
     struct nl80211_global *global = eloop_ctx;
-    struct dl_list pending_events;

-    wpa_printf(MSG_DEBUG, "nl80211: Delivering pending events");
+    if (!dl_list_empty(&global->pending_events)) {
+        struct dl_list pending_events;

-    global->pending_events.next->prev = &pending_events;
-    global->pending_events.prev->next = &pending_events;
-    pending_events.next = global->pending_events.next;
-    pending_events.prev = global->pending_events.prev;
-    dl_list_init(&global->pending_events);
-
-    while (!dl_list_empty(&pending_events)) {
-        struct nl80211_pending_event *event =
-            dl_list_first(&pending_events,
-                      struct nl80211_pending_event, list);
-
-        event->handler(event->msg, event->data);
-        nl80211_remove_pending_event(event);
-    }
+        wpa_printf(MSG_DEBUG, "nl80211: Delivering pending events");
+
+        global->pending_events.next->prev = &pending_events;
+        global->pending_events.prev->next = &pending_events;
+        pending_events.next = global->pending_events.next;
+        pending_events.prev = global->pending_events.prev;
+        dl_list_init(&global->pending_events);
+
+        while (!dl_list_empty(&pending_events)) {
+            struct nl80211_pending_event *event =
+                dl_list_first(&pending_events,
+                          struct nl80211_pending_event, list);
+
+            event->handler(event->msg, event->data);
+            nl80211_remove_pending_event(event);
+        }
+    } else
+        wpa_printf(MSG_INFO, "%s() was called with an empty pending
events list", __func__);
 }

Regards,
Hartmut



More information about the Hostap mailing list