Comment 54 for bug 585938

Revision history for this message
gcc (chris+ubuntu-qwirx) wrote :

OK, I think I understand the problem. The table of iw_priv args and functions should alternate SET and GET functions, but Realtek just added them all in order.

net/wireless/wext.c uses IW_IS_SET on the command number to determine whether it's a GET or SET command, and this just checks the last bit. So it's essential that GET commands have an odd command number. Otherwise ioctl_private_iw_point won't allocate a memory buffer to pass into the handler.

r8192_wx_get_adhoc_peers is an iwpriv ioctl that behaves as a GET ioctl, it expects a writable buffer from the wireless extensions system (wext.c) and it writes all over it. However it lives in a SET slot (SIOCIWFIRSTPRIV + 0xc is even) so the kernel hasn't allocated any memory to it (extra_size = 0), although kzalloc did apparently return a valid pointer or this would have been a null pointer reference. Anyway at this point the driver will scribble over random kernel memory and cause a panic soon after.

It's not clear to me why reducing the buffer size works for some people. Perhaps the pointer returned by kzalloc happens to be a memory location big enough to write 1024 bytes to, for them but not for me?

The fix appears to be to correct the allocation of iwpriv ioctl numbers in the driver. I'm going to try my hand at writing a patch for this. Newer kernels (3.2.0) appear to have a completely different driver model based on nl80211 instead of wext, so I can't just backport a patch.

It would also probably be helpful in debugging other drivers if wext.c (1) checked that (apparent) SET ioctls don't expect a GET buffer, and GET ioctls don't expect a SET buffer, or return an error if they do, and (2) set the data pointer to 0 instead of calling kzalloc for 0 bytes.