struct iw_point has a 32bit hole on 64bit arches.
struct iw_point { void __user *pointer; /* Pointer to the data (in user space) */ __u16 length; /* number of fields or size in bytes */ __u16 flags; /* Optional params */ };
Make sure to zero the structure to avoid dislosing 32bits of kernel data to user space.
Fixes: 87de87d5e47f ("wext: Dispatch and handle compat ioctls entirely in net/wireless/wext.c") Reported-by: syzbot+bfc7323743ca6dbcc3d3@syzkaller.appspotmail.com https://lore.kernel.org/netdev/695f83f3.050a0220.1c677c.0392.GAE@google.com/... Signed-off-by: Eric Dumazet edumazet@google.com Cc: stable@vger.kernel.org --- net/wireless/wext-core.c | 4 ++++ net/wireless/wext-priv.c | 4 ++++ 2 files changed, 8 insertions(+)
diff --git a/net/wireless/wext-core.c b/net/wireless/wext-core.c index c32a7c6903d53686bc5b51652a7c0574e7085659..7b8e94214b07224ffda4852d9e8a471a5fb18637 100644 --- a/net/wireless/wext-core.c +++ b/net/wireless/wext-core.c @@ -1101,6 +1101,10 @@ static int compat_standard_call(struct net_device *dev, return ioctl_standard_call(dev, iwr, cmd, info, handler);
iwp_compat = (struct compat_iw_point *) &iwr->u.data; + + /* struct iw_point has a 32bit hole on 64bit arches. */ + memset(&iwp, 0, sizeof(iwp)); + iwp.pointer = compat_ptr(iwp_compat->pointer); iwp.length = iwp_compat->length; iwp.flags = iwp_compat->flags; diff --git a/net/wireless/wext-priv.c b/net/wireless/wext-priv.c index 674d426a9d24f9aab7657d1e8ecf342e3be87438..37d1147019c2baba3e3792bb98f098294cba00ec 100644 --- a/net/wireless/wext-priv.c +++ b/net/wireless/wext-priv.c @@ -228,6 +228,10 @@ int compat_private_call(struct net_device *dev, struct iwreq *iwr, struct iw_point iwp;
iwp_compat = (struct compat_iw_point *) &iwr->u.data; + + /* struct iw_point has a 32bit hole on 64bit arches. */ + memset(&iwp, 0, sizeof(iwp)); + iwp.pointer = compat_ptr(iwp_compat->pointer); iwp.length = iwp_compat->length; iwp.flags = iwp_compat->flags;
On Thu, 2026-01-08 at 10:19 +0000, Eric Dumazet wrote:
struct iw_point has a 32bit hole on 64bit arches.
struct iw_point { void __user *pointer; /* Pointer to the data (in user space) */ __u16 length; /* number of fields or size in bytes */ __u16 flags; /* Optional params */ };
Make sure to zero the structure to avoid dislosing 32bits of kernel data to user space.
Heh, wow. Talk about old code.
Reported-by: syzbot+bfc7323743ca6dbcc3d3@syzkaller.appspotmail.com https://lore.kernel.org/netdev/695f83f3.050a0220.1c677c.0392.GAE@google.com/...
Was that intentionally without Link: or some other tag?
johannes
On Thu, Jan 8, 2026 at 11:29 AM Johannes Berg johannes@sipsolutions.net wrote:
On Thu, 2026-01-08 at 10:19 +0000, Eric Dumazet wrote:
struct iw_point has a 32bit hole on 64bit arches.
struct iw_point { void __user *pointer; /* Pointer to the data (in user space) */ __u16 length; /* number of fields or size in bytes */ __u16 flags; /* Optional params */ };
Make sure to zero the structure to avoid dislosing 32bits of kernel data to user space.
Heh, wow. Talk about old code.
Reported-by: syzbot+bfc7323743ca6dbcc3d3@syzkaller.appspotmail.com https://lore.kernel.org/netdev/695f83f3.050a0220.1c677c.0392.GAE@google.com/...
Was that intentionally without Link: or some other tag?
Somehow the Closes: prefix has been lost when I cooked the patch.
Closes: https://lore.kernel.org/netdev/695f83f3.050a0220.1c677c.0392.GAE@google.com/...
Let me know if you want a V2, thanks.
johannes
On Thu, 2026-01-08 at 11:32 +0100, Eric Dumazet wrote:
On Thu, Jan 8, 2026 at 11:29 AM Johannes Berg johannes@sipsolutions.net wrote:
On Thu, 2026-01-08 at 10:19 +0000, Eric Dumazet wrote:
struct iw_point has a 32bit hole on 64bit arches.
struct iw_point { void __user *pointer; /* Pointer to the data (in user space) */ __u16 length; /* number of fields or size in bytes */ __u16 flags; /* Optional params */ };
Make sure to zero the structure to avoid dislosing 32bits of kernel data to user space.
Heh, wow. Talk about old code.
Reported-by: syzbot+bfc7323743ca6dbcc3d3@syzkaller.appspotmail.com https://lore.kernel.org/netdev/695f83f3.050a0220.1c677c.0392.GAE@google.com/...
Was that intentionally without Link: or some other tag?
Somehow the Closes: prefix has been lost when I cooked the patch.
Closes: https://lore.kernel.org/netdev/695f83f3.050a0220.1c677c.0392.GAE@google.com/...
Let me know if you want a V2, thanks.
I'll add it, no worries.
johannes
Hi,
On Thu, Jan 8, 2026 at 12:28 PM Eric Dumazet edumazet@google.com wrote:
On Thu, Jan 8, 2026 at 11:29 AM Johannes Berg johannes@sipsolutions.net wrote:
On Thu, 2026-01-08 at 10:19 +0000, Eric Dumazet wrote:
struct iw_point has a 32bit hole on 64bit arches.
struct iw_point { void __user *pointer; /* Pointer to the data (in user space) */ __u16 length; /* number of fields or size in bytes */ __u16 flags; /* Optional params */ };
Make sure to zero the structure to avoid dislosing 32bits of kernel data
In case you do a V2: dislosing -> disclosing (I assume)
to user space.
Best regards, Jonas
On Thu, 2026-01-08 at 10:19 +0000, Eric Dumazet wrote:
https://lore.kernel.org/netdev/695f83f3.050a0220.1c677c.0392.GAE@google.com/...
That wasn't the easiest bit to follow (for me anyway), so for anyone else wanting to follow along, here's my interpretation of what happens:
+++ b/net/wireless/wext-core.c @@ -1101,6 +1101,10 @@ static int compat_standard_call(struct net_device *dev, return ioctl_standard_call(dev, iwr, cmd, info, handler); iwp_compat = (struct compat_iw_point *) &iwr->u.data;
- /* struct iw_point has a 32bit hole on 64bit arches. */
- memset(&iwp, 0, sizeof(iwp));
- iwp.pointer = compat_ptr(iwp_compat->pointer); iwp.length = iwp_compat->length; iwp.flags = iwp_compat->flags;
This all looks mostly fine locally, even for the compat code, i.e. for a 32-bit task on the 64-bit machine. The iwp is created here and is given to ioctl_standard_iw_point(), which crucially then for some requests (according to IW_DESCR_FLAG_EVENT) passes it to wireless_send_event().
This then can creates _two_ events, one for 32-bit tasks and one for 64- bit tasks, and the 64-bit one will have the "struct iw_point" starting from "length", excluding "pointer" but including the padding at the end... The layout is further described in the "The problem for 64/32 bit." comment in wext-core.c
I don't think this can happen for the compat_private_call() part since no events are generated there, but fixing it there as well is definitely better (and who knows what random drivers might do in priv ioctls.)
johannes
linux-stable-mirror@lists.linaro.org