Commit e34f1753 authored by Michal Kubecek's avatar Michal Kubecek Committed by David S. Miller
Browse files

ethtool: limit bitset size



Syzbot reported that ethnl_compact_sanity_checks() can be tricked into
reading past the end of ETHTOOL_A_BITSET_VALUE and ETHTOOL_A_BITSET_MASK
attributes and even the message by passing a value between (u32)(-31)
and (u32)(-1) as ETHTOOL_A_BITSET_SIZE.

The problem is that DIV_ROUND_UP(attr_nbits, 32) is 0 for such values so
that zero length ETHTOOL_A_BITSET_VALUE will pass the length check but
ethnl_bitmap32_not_zero() check would try to access up to 512 MB of
attribute "payload".

Prevent this overflow byt limiting the bitset size. Technically, compact
bitset format would allow bitset sizes up to almost 2^18 (so that the
nest size does not exceed U16_MAX) but bitsets used by ethtool are much
shorter. S16_MAX, the largest value which can be directly used as an
upper limit in policy, should be a reasonable compromise.

Fixes: 10b518d4 ("ethtool: netlink bitset handling")
Reported-by: default avatar <syzbot+7fd4ed5b4234ab1fdccd@syzkaller.appspotmail.com>
Reported-by: default avatar <syzbot+709b7a64d57978247e44@syzkaller.appspotmail.com>
Reported-by: default avatar <syzbot+983cb8fb2d17a7af549d@syzkaller.appspotmail.com>
Signed-off-by: default avatarMichal Kubecek <mkubecek@suse.cz>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 6e11d157
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -305,7 +305,8 @@ nla_put_failure:
static const struct nla_policy bitset_policy[ETHTOOL_A_BITSET_MAX + 1] = {
	[ETHTOOL_A_BITSET_UNSPEC]	= { .type = NLA_REJECT },
	[ETHTOOL_A_BITSET_NOMASK]	= { .type = NLA_FLAG },
	[ETHTOOL_A_BITSET_SIZE]		= { .type = NLA_U32 },
	[ETHTOOL_A_BITSET_SIZE]		= NLA_POLICY_MAX(NLA_U32,
							 ETHNL_MAX_BITSET_SIZE),
	[ETHTOOL_A_BITSET_BITS]		= { .type = NLA_NESTED },
	[ETHTOOL_A_BITSET_VALUE]	= { .type = NLA_BINARY },
	[ETHTOOL_A_BITSET_MASK]		= { .type = NLA_BINARY },
+2 −0
Original line number Diff line number Diff line
@@ -3,6 +3,8 @@
#ifndef _NET_ETHTOOL_BITSET_H
#define _NET_ETHTOOL_BITSET_H

#define ETHNL_MAX_BITSET_SIZE S16_MAX

typedef const char (*const ethnl_string_array_t)[ETH_GSTRING_LEN];

int ethnl_bitset_is_compact(const struct nlattr *bitset, bool *compact);