Linux wireless drivers development
 help / color / mirror / Atom feed
* [PATCH] wext: verify buffer size for SIOCSIWENCODEEXT
@ 2009-05-13 10:04 Johannes Berg
  2009-05-13 22:00 ` [PATCH v2] " Johannes Berg
  0 siblings, 1 reply; 2+ messages in thread
From: Johannes Berg @ 2009-05-13 10:04 UTC (permalink / raw)
  To: John Linville; +Cc: linux-wireless

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>
---
 net/wireless/wext.c |    7 +++++++
 1 file changed, 7 insertions(+)

--- wireless-testing.orig/net/wireless/wext.c	2009-05-13 11:47:04.000000000 +0200
+++ wireless-testing/net/wireless/wext.c	2009-05-13 11:47:25.000000000 +0200
@@ -798,6 +798,13 @@ static int ioctl_standard_iw_point(struc
 			err = -EFAULT;
 			goto out;
 		}
+
+		if (cmd == SIOCSIWENCODEEXT) {
+			struct iw_encode_ext *ee = extra;
+
+			if (iwp->length < sizeof(*ee) + ee->key_len)
+				return -EFAULT;
+		}
 	}
 
 	err = handler(dev, info, (union iwreq_data *) iwp, extra);



^ permalink raw reply	[flat|nested] 2+ messages in thread

* [PATCH v2] wext: verify buffer size for SIOCSIWENCODEEXT
  2009-05-13 10:04 [PATCH] wext: verify buffer size for SIOCSIWENCODEEXT Johannes Berg
@ 2009-05-13 22:00 ` Johannes Berg
  0 siblings, 0 replies; 2+ messages in thread
From: Johannes Berg @ 2009-05-13 22:00 UTC (permalink / raw)
  To: John Linville; +Cc: linux-wireless

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>
---
Forgot a cast, not sure why that didn't show up in my other compile
test?!

 net/wireless/wext.c |    7 +++++++
 1 file changed, 7 insertions(+)

--- wireless-testing.orig/net/wireless/wext.c	2009-05-13 23:56:22.000000000 +0200
+++ wireless-testing/net/wireless/wext.c	2009-05-13 23:56:32.000000000 +0200
@@ -798,6 +798,13 @@ static int ioctl_standard_iw_point(struc
 			err = -EFAULT;
 			goto out;
 		}
+
+		if (cmd == SIOCSIWENCODEEXT) {
+			struct iw_encode_ext *ee = (void *) extra;
+
+			if (iwp->length < sizeof(*ee) + ee->key_len)
+				return -EFAULT;
+		}
 	}
 
 	err = handler(dev, info, (union iwreq_data *) iwp, extra);



^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2009-05-13 22:00 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-05-13 10:04 [PATCH] wext: verify buffer size for SIOCSIWENCODEEXT Johannes Berg
2009-05-13 22:00 ` [PATCH v2] " Johannes Berg

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox