Skip to content

Commit

Permalink
ieee802154: Fix sockaddr_ieee802154 implicit padding information leak.
Browse files Browse the repository at this point in the history
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.

Cc: [email protected]
Signed-off-by: Lennert Buytenhek <[email protected]>
Acked-by: Alexander Aring <[email protected]>
Signed-off-by: Marcel Holtmann <[email protected]>
  • Loading branch information
buytenh authored and holtmann committed Jun 4, 2015
1 parent 07bd77f commit 8a70cef
Showing 1 changed file with 6 additions and 0 deletions.
6 changes: 6 additions & 0 deletions net/ieee802154/socket.c
Original file line number Diff line number Diff line change
Expand Up @@ -731,6 +731,12 @@ static int dgram_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
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);
Expand Down

0 comments on commit 8a70cef

Please sign in to comment.