Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c70d6815 authored by Bert Kenward's avatar Bert Kenward Committed by David S. Miller
Browse files

sfc: don't read beyond unicast address list



If we have more than 32 unicast MAC addresses assigned to an interface
we will read beyond the end of the address table in the driver when
adding filters. The next 256 entries store multicast addresses, so we
will end up attempting to insert duplicate filters, which is mostly
harmless. If we add more than 288 unicast addresses we will then read
past the multicast address table, which is likely to be more exciting.

Fixes: 12fb0da4 ("sfc: clean fallbacks between promisc/normal in efx_ef10_filter_sync_rx_mode")
Signed-off-by: default avatarBert Kenward <bkenward@solarflare.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 07b8a7cf
Loading
Loading
Loading
Loading
+3 −5
Original line number Original line Diff line number Diff line
@@ -5034,12 +5034,9 @@ static void efx_ef10_filter_uc_addr_list(struct efx_nic *efx)
	struct efx_ef10_filter_table *table = efx->filter_state;
	struct efx_ef10_filter_table *table = efx->filter_state;
	struct net_device *net_dev = efx->net_dev;
	struct net_device *net_dev = efx->net_dev;
	struct netdev_hw_addr *uc;
	struct netdev_hw_addr *uc;
	int addr_count;
	unsigned int i;
	unsigned int i;


	addr_count = netdev_uc_count(net_dev);
	table->uc_promisc = !!(net_dev->flags & IFF_PROMISC);
	table->uc_promisc = !!(net_dev->flags & IFF_PROMISC);
	table->dev_uc_count = 1 + addr_count;
	ether_addr_copy(table->dev_uc_list[0].addr, net_dev->dev_addr);
	ether_addr_copy(table->dev_uc_list[0].addr, net_dev->dev_addr);
	i = 1;
	i = 1;
	netdev_for_each_uc_addr(uc, net_dev) {
	netdev_for_each_uc_addr(uc, net_dev) {
@@ -5050,6 +5047,8 @@ static void efx_ef10_filter_uc_addr_list(struct efx_nic *efx)
		ether_addr_copy(table->dev_uc_list[i].addr, uc->addr);
		ether_addr_copy(table->dev_uc_list[i].addr, uc->addr);
		i++;
		i++;
	}
	}

	table->dev_uc_count = i;
}
}


static void efx_ef10_filter_mc_addr_list(struct efx_nic *efx)
static void efx_ef10_filter_mc_addr_list(struct efx_nic *efx)
@@ -5057,12 +5056,11 @@ static void efx_ef10_filter_mc_addr_list(struct efx_nic *efx)
	struct efx_ef10_filter_table *table = efx->filter_state;
	struct efx_ef10_filter_table *table = efx->filter_state;
	struct net_device *net_dev = efx->net_dev;
	struct net_device *net_dev = efx->net_dev;
	struct netdev_hw_addr *mc;
	struct netdev_hw_addr *mc;
	unsigned int i, addr_count;
	unsigned int i;


	table->mc_overflow = false;
	table->mc_overflow = false;
	table->mc_promisc = !!(net_dev->flags & (IFF_PROMISC | IFF_ALLMULTI));
	table->mc_promisc = !!(net_dev->flags & (IFF_PROMISC | IFF_ALLMULTI));


	addr_count = netdev_mc_count(net_dev);
	i = 0;
	i = 0;
	netdev_for_each_mc_addr(mc, net_dev) {
	netdev_for_each_mc_addr(mc, net_dev) {
		if (i >= EFX_EF10_FILTER_DEV_MC_MAX) {
		if (i >= EFX_EF10_FILTER_DEV_MC_MAX) {