| From | Greg Kroah-Hartman <> | Subject | [PATCH 4.1 023/267] ieee802154: Fix sockaddr_ieee802154 implicit padding information leak. | Date | Fri, 31 Jul 2015 12:37:54 -0700 |
| |
4.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lennert Buytenhek <buytenh@wantstofly.org>
commit 8a70cefa3037d62e7c0b6068a66675def1a330c9 upstream.
The AF_IEEE802154 sockaddr looks like this:
struct sockaddr_ieee802154 { sa_family_t family; /* AF_IEEE802154 */ struct ieee802154_addr_sa addr; };
struct ieee802154_addr_sa { int addr_type; u16 pan_id; union { u8 hwaddr[IEEE802154_ADDR_LEN]; u16 short_addr; }; };
On most architectures there will be implicit structure padding here, in two different places:
* In struct sockaddr_ieee802154, two bytes of padding between 'family' (unsigned short) and 'addr', so that 'addr' starts on a four byte boundary.
* In struct ieee802154_addr_sa, two bytes at the end of the structure, to make the structure 16 bytes.
When calling recvmsg(2) on a PF_IEEE802154 SOCK_DGRAM socket, the ieee802154 stack constructs a struct sockaddr_ieee802154 on the kernel stack without clearing these padding fields, and, depending on the addr_type, between four and ten bytes of uncleared kernel stack will be copied to userspace.
We can't just insert two 'u16 __pad's in the right places and zero those before copying an address to userspace, as not all architectures insert this implicit padding -- from a quick test it seems that avr32, cris and m68k don't insert this padding, while every other architecture that I have cross compilers for does insert this padding.
The easiest way to plug the leak is to just memset the whole struct sockaddr_ieee802154 before filling in the fields we want to fill in, and that's what this patch does.
Signed-off-by: Lennert Buytenhek <buytenh@wantstofly.org> Acked-by: Alexander Aring <alex.aring@gmail.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
--- net/ieee802154/socket.c | 6 ++++++ 1 file changed, 6 insertions(+)
--- a/net/ieee802154/socket.c +++ b/net/ieee802154/socket.c @@ -739,6 +739,12 @@ static int dgram_recvmsg(struct sock *sk sock_recv_ts_and_drops(msg, sk, skb); if (saddr) { + /* Clear the implicit padding in struct sockaddr_ieee802154 + * (16 bits between 'family' and 'addr') and in struct + * ieee802154_addr_sa (16 bits at the end of the structure). + */ + memset(saddr, 0, sizeof(*saddr)); + saddr->family = AF_IEEE802154; ieee802154_addr_to_sa(&saddr->addr, &mac_cb(skb)->source); *addr_len = sizeof(*saddr);
|