diff mbox

[RFC,2/2] nl80211: make eloop sockets non-blocking

Message ID 1382373298-9150-2-git-send-email-johannes@sipsolutions.net
State Superseded
Headers show

Commit Message

Johannes Berg Oct. 21, 2013, 4:34 p.m. UTC
From: Johannes Berg <johannes.berg@intel.com>

To avoid a problem where the beacon socket occasionally
blocks, mark any sockets on the eloop as non-blocking.
The previous patch reordered the code to never send a
command after a socket was put on the eloop, but now also
invalidate the nl handle pointer while it's on there.

Signed-hostap: Johannes Berg <johannes.berg@intel.com>
---
 src/drivers/driver_nl80211.c | 5 +++++
 1 file changed, 5 insertions(+)

Comments

Jouni Malinen Oct. 22, 2013, 9:36 p.m. UTC | #1
On Mon, Oct 21, 2013 at 06:34:58PM +0200, Johannes Berg wrote:
> To avoid a problem where the beacon socket occasionally
> blocks, mark any sockets on the eloop as non-blocking.
> The previous patch reordered the code to never send a
> command after a socket was put on the eloop, but now also
> invalidate the nl handle pointer while it's on there.

> diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
> +#define ELOOP_SOCKET_INVALID	0x8888888888888889ULL

This needs something like

+#if __WORDSIZE == 64
 #define ELOOP_SOCKET_INVALID   0x8888888888888889ULL
+#else
+#define ELOOP_SOCKET_INVALID   0x88888889UL
+#endif

to compile for 32-bit targets.

>  static void nl80211_register_eloop_read(struct nl_handle **handle,
> +	*handle = (void *)(((unsigned long)*handle) ^ ELOOP_SOCKET_INVALID);

And this invalidation does trigger an issue in the test_ibss_rsn case,
i.e., the wpa_supplicant controlling wlan0 crashes with this backtrace:

==11352== Invalid read of size 8
==11352==    at 0x513EE26: nl_send_auto (in /lib/libnl-3.so.200.3.0)
==11352==    by 0x537CEC: send_and_recv.isra.17 (driver_nl80211.c:579)
==11352==    by 0x537EBC: nl80211_register_frame (driver_nl80211.c:3771)
==11352==    by 0x544F31: do_process_drv_event (driver_nl80211.c:1863)
==11352==    by 0x54538A: process_global_event (driver_nl80211.c:2824)
==11352==    by 0x513F4A9: nl_recvmsgs (in /lib/libnl-3.so.200.3.0)
==11352==    by 0x437DFF: eloop_sock_table_dispatch_table (eloop.c:335)
==11352==    by 0x438CB7: eloop_run (eloop.c:352)
==11352==    by 0x526878: wpa_supplicant_run (wpa_supplicant.c:3446)
==11352==    by 0x42CCFC: main (main.c:320)
==11352==  Address 0x888888888f6e7929 is not stack'd, malloc'd or (recently) free'd


So I cannot apply this before that gets fixed. I'd assume patch 1/2 is
fine, though, and I do need it for my buildbot setup to be more stable.
Johannes Berg Oct. 26, 2013, 8:40 a.m. UTC | #2
On Wed, 2013-10-23 at 00:36 +0300, Jouni Malinen wrote:

> >  static void nl80211_register_eloop_read(struct nl_handle **handle,
> > +	*handle = (void *)(((unsigned long)*handle) ^ ELOOP_SOCKET_INVALID);
> 
> And this invalidation does trigger an issue in the test_ibss_rsn case,
> i.e., the wpa_supplicant controlling wlan0 crashes with this backtrace:

Yes, I see, the IBSS code is actually broken in that it does send
commands to the socket well after it has been registered for the eloop.
That could cause the problems we discussed, when an event is processed
in the loop that waits for the command to finish we could drop the event
and then block the eloop.

johannes
diff mbox

Patch

diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index c1050e3..b59db09 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -139,16 +139,21 @@  static void nl_destroy_handles(struct nl_handle **handle)
 	*handle = NULL;
 }
 
+#define ELOOP_SOCKET_INVALID	0x8888888888888889ULL
+
 static void nl80211_register_eloop_read(struct nl_handle **handle,
 					eloop_sock_handler handler,
 					void *eloop_data)
 {
+	nl_socket_set_nonblocking(*handle);
 	eloop_register_read_sock(nl_socket_get_fd(*handle), handler,
 				 eloop_data, *handle);
+	*handle = (void *)(((unsigned long)*handle) ^ ELOOP_SOCKET_INVALID);
 }
 
 static void nl80211_destroy_eloop_handle(struct nl_handle **handle)
 {
+	*handle = (void *)(((unsigned long)*handle) ^ ELOOP_SOCKET_INVALID);
 	eloop_unregister_read_sock(nl_socket_get_fd(*handle));
 	nl_destroy_handles(handle);
 }