wext: verify buffer size for SIOCSIWENCODEEXT
authorJohannes Berg <johannes@sipsolutions.net>
Wed, 13 May 2009 10:04:30 +0000 (12:04 +0200)
committerJohn W. Linville <linville@tuxdriver.com>
Wed, 20 May 2009 18:07:50 +0000 (14:07 -0400)
commit88f16db7a2fa63b9242e8a0fbc40d51722f2e2f9
treeea9ffbf2e1e595070c599486bfc5e9db394b46d5
parent2b611cb6eed04062d0a9861c82248e02c844ba3f
wext: verify buffer size for SIOCSIWENCODEEXT

Another design flaw in wireless extensions (is anybody
surprised?) in the way it handles the iw_encode_ext
structure: The structure is part of the 'extra' memory
but contains the key length explicitly, instead of it
just being the length of the extra buffer - size of
the struct and using the explicit key length only for
the get operation (which only writes it).

Therefore, we have this layout:

extra: +-------------------------+
       | struct iw_encode_ext  { |
       |     ...                 |
       |     u16 key_len;        |
       |     u8 key[0];          |
       | };                      |
       +-------------------------+
       | key material            |
       +-------------------------+

Now, all drivers I checked use ext->key_len without
checking that both key_len and the struct fit into the
extra buffer that has been copied from userspace. This
leads to a buffer overrun while reading that buffer,
depending on the driver it may be possible to specify
arbitrary key_len or it may need to be a proper length
for the key algorithm specified.

Thankfully, this is only exploitable by root, but root
can actually cause a segfault or use kernel memory as
a key (which you can even get back with siocgiwencode
or siocgiwencodeext from the key buffer).

Fix this by verifying that key_len fits into the buffer
along with struct iw_encode_ext.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
net/wireless/wext.c