Commit 9fdfb15a authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull networking fixes from Paolo Abeni:
 "Quite unusually, this does not contains any fix coming from subtrees
  (nf, ebpf, wifi, etc).

  Current release - regressions:

   - bcmasp: fix possible OOB write in bcmasp_netfilt_get_all_active()

  Previous releases - regressions:

   - ipv4: fix one memleak in __inet_del_ifa()

   - tcp: fix bind() regressions for v4-mapped-v6 addresses.

   - tls: do not free tls_rec on async operation in
     bpf_exec_tx_verdict()

   - dsa: fixes for SJA1105 FDB regressions

   - veth: update XDP feature set when bringing up device

   - igb: fix hangup when enabling SR-IOV

  Previous releases - always broken:

   - kcm: fix memory leak in error path of kcm_sendmsg()

   - smc: fix data corruption in smcr_port_add

   - microchip: fix possible memory leak for vcap_dup_rule()"

* tag 'net-6.6-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net: (37 commits)
  kcm: Fix error handling for SOCK_DGRAM in kcm_sendmsg().
  net: renesas: rswitch: Add spin lock protection for irq {un}mask
  net: renesas: rswitch: Fix unmasking irq condition
  igb: clean up in all error paths when enabling SR-IOV
  ixgbe: fix timestamp configuration code
  selftest: tcp: Add v4-mapped-v6 cases in bind_wildcard.c.
  selftest: tcp: Move expected_errno into each test case in bind_wildcard.c.
  selftest: tcp: Fix address length in bind_wildcard.c.
  tcp: Fix bind() regression for v4-mapped-v6 non-wildcard address.
  tcp: Fix bind() regression for v4-mapped-v6 wildcard address.
  tcp: Factorise sk_family-independent comparison in inet_bind2_bucket_match(_addr_any).
  ipv6: fix ip6_sock_set_addr_preferences() typo
  veth: Update XDP feature set when bringing up device
  net: macb: fix sleep inside spinlock
  net/tls: do not free tls_rec on async operation in bpf_exec_tx_verdict()
  net: ethernet: mtk_eth_soc: fix pse_port configuration for MT7988
  net: ethernet: mtk_eth_soc: fix uninitialized variable
  kcm: Fix memory leak in error path of kcm_sendmsg()
  r8152: check budget for r8152_poll()
  net: dsa: sja1105: block FDB accesses that are concurrent with a switch reset
  ...
parents aed8aee1 a22730b1
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -266,6 +266,8 @@ struct sja1105_private {
	 * the switch doesn't confuse them with one another.
	 */
	struct mutex mgmt_lock;
	/* Serializes accesses to the FDB */
	struct mutex fdb_lock;
	/* PTP two-step TX timestamp ID, and its serialization lock */
	spinlock_t ts_id_lock;
	u8 ts_id;
+44 −49
Original line number Diff line number Diff line
@@ -1175,18 +1175,15 @@ const struct sja1105_dynamic_table_ops sja1110_dyn_ops[BLK_IDX_MAX_DYN] = {

static int
sja1105_dynamic_config_poll_valid(struct sja1105_private *priv,
				  struct sja1105_dyn_cmd *cmd,
				  const struct sja1105_dynamic_table_ops *ops)
				  const struct sja1105_dynamic_table_ops *ops,
				  void *entry, bool check_valident,
				  bool check_errors)
{
	u8 packed_buf[SJA1105_MAX_DYN_CMD_SIZE] = {};
	struct sja1105_dyn_cmd cmd = {};
	int rc;

	/* We don't _need_ to read the full entry, just the command area which
	 * is a fixed SJA1105_SIZE_DYN_CMD. But our cmd_packing() API expects a
	 * buffer that contains the full entry too. Additionally, our API
	 * doesn't really know how many bytes into the buffer does the command
	 * area really begin. So just read back the whole entry.
	 */
	/* Read back the whole entry + command structure. */
	rc = sja1105_xfer_buf(priv, SPI_READ, ops->addr, packed_buf,
			      ops->packed_size);
	if (rc)
@@ -1195,11 +1192,25 @@ sja1105_dynamic_config_poll_valid(struct sja1105_private *priv,
	/* Unpack the command structure, and return it to the caller in case it
	 * needs to perform further checks on it (VALIDENT).
	 */
	memset(cmd, 0, sizeof(*cmd));
	ops->cmd_packing(packed_buf, cmd, UNPACK);
	ops->cmd_packing(packed_buf, &cmd, UNPACK);

	/* Hardware hasn't cleared VALID => still working on it */
	return cmd->valid ? -EAGAIN : 0;
	if (cmd.valid)
		return -EAGAIN;

	if (check_valident && !cmd.valident && !(ops->access & OP_VALID_ANYWAY))
		return -ENOENT;

	if (check_errors && cmd.errors)
		return -EINVAL;

	/* Don't dereference possibly NULL pointer - maybe caller
	 * only wanted to see whether the entry existed or not.
	 */
	if (entry)
		ops->entry_packing(packed_buf, entry, UNPACK);

	return 0;
}

/* Poll the dynamic config entry's control area until the hardware has
@@ -1208,16 +1219,19 @@ sja1105_dynamic_config_poll_valid(struct sja1105_private *priv,
 */
static int
sja1105_dynamic_config_wait_complete(struct sja1105_private *priv,
				     struct sja1105_dyn_cmd *cmd,
				     const struct sja1105_dynamic_table_ops *ops)
				     const struct sja1105_dynamic_table_ops *ops,
				     void *entry, bool check_valident,
				     bool check_errors)
{
	int rc;
	int err, rc;

	return read_poll_timeout(sja1105_dynamic_config_poll_valid,
	err = read_poll_timeout(sja1105_dynamic_config_poll_valid,
				rc, rc != -EAGAIN,
				SJA1105_DYNAMIC_CONFIG_SLEEP_US,
				SJA1105_DYNAMIC_CONFIG_TIMEOUT_US,
				 false, priv, cmd, ops);
				false, priv, ops, entry, check_valident,
				check_errors);
	return err < 0 ? err : rc;
}

/* Provides read access to the settings through the dynamic interface
@@ -1286,25 +1300,14 @@ int sja1105_dynamic_config_read(struct sja1105_private *priv,
	mutex_lock(&priv->dynamic_config_lock);
	rc = sja1105_xfer_buf(priv, SPI_WRITE, ops->addr, packed_buf,
			      ops->packed_size);
	if (rc < 0) {
		mutex_unlock(&priv->dynamic_config_lock);
		return rc;
	}

	rc = sja1105_dynamic_config_wait_complete(priv, &cmd, ops);
	mutex_unlock(&priv->dynamic_config_lock);
	if (rc < 0)
		return rc;
		goto out;

	if (!cmd.valident && !(ops->access & OP_VALID_ANYWAY))
		return -ENOENT;
	rc = sja1105_dynamic_config_wait_complete(priv, ops, entry, true, false);
out:
	mutex_unlock(&priv->dynamic_config_lock);

	/* Don't dereference possibly NULL pointer - maybe caller
	 * only wanted to see whether the entry existed or not.
	 */
	if (entry)
		ops->entry_packing(packed_buf, entry, UNPACK);
	return 0;
	return rc;
}

int sja1105_dynamic_config_write(struct sja1105_private *priv,
@@ -1356,22 +1359,14 @@ int sja1105_dynamic_config_write(struct sja1105_private *priv,
	mutex_lock(&priv->dynamic_config_lock);
	rc = sja1105_xfer_buf(priv, SPI_WRITE, ops->addr, packed_buf,
			      ops->packed_size);
	if (rc < 0) {
		mutex_unlock(&priv->dynamic_config_lock);
		return rc;
	}

	rc = sja1105_dynamic_config_wait_complete(priv, &cmd, ops);
	mutex_unlock(&priv->dynamic_config_lock);
	if (rc < 0)
		return rc;
		goto out;

	cmd = (struct sja1105_dyn_cmd) {0};
	ops->cmd_packing(packed_buf, &cmd, UNPACK);
	if (cmd.errors)
		return -EINVAL;
	rc = sja1105_dynamic_config_wait_complete(priv, ops, NULL, false, true);
out:
	mutex_unlock(&priv->dynamic_config_lock);

	return 0;
	return rc;
}

static u8 sja1105_crc8_add(u8 crc, u8 byte, u8 poly)
+51 −18
Original line number Diff line number Diff line
@@ -1798,6 +1798,7 @@ static int sja1105_fdb_add(struct dsa_switch *ds, int port,
			   struct dsa_db db)
{
	struct sja1105_private *priv = ds->priv;
	int rc;

	if (!vid) {
		switch (db.type) {
@@ -1812,10 +1813,14 @@ static int sja1105_fdb_add(struct dsa_switch *ds, int port,
		}
	}

	return priv->info->fdb_add_cmd(ds, port, addr, vid);
	mutex_lock(&priv->fdb_lock);
	rc = priv->info->fdb_add_cmd(ds, port, addr, vid);
	mutex_unlock(&priv->fdb_lock);

	return rc;
}

static int sja1105_fdb_del(struct dsa_switch *ds, int port,
static int __sja1105_fdb_del(struct dsa_switch *ds, int port,
			     const unsigned char *addr, u16 vid,
			     struct dsa_db db)
{
@@ -1837,6 +1842,20 @@ static int sja1105_fdb_del(struct dsa_switch *ds, int port,
	return priv->info->fdb_del_cmd(ds, port, addr, vid);
}

static int sja1105_fdb_del(struct dsa_switch *ds, int port,
			   const unsigned char *addr, u16 vid,
			   struct dsa_db db)
{
	struct sja1105_private *priv = ds->priv;
	int rc;

	mutex_lock(&priv->fdb_lock);
	rc = __sja1105_fdb_del(ds, port, addr, vid, db);
	mutex_unlock(&priv->fdb_lock);

	return rc;
}

static int sja1105_fdb_dump(struct dsa_switch *ds, int port,
			    dsa_fdb_dump_cb_t *cb, void *data)
{
@@ -1868,13 +1887,14 @@ static int sja1105_fdb_dump(struct dsa_switch *ds, int port,
		if (!(l2_lookup.destports & BIT(port)))
			continue;

		/* We need to hide the FDB entry for unknown multicast */
		if (l2_lookup.macaddr == SJA1105_UNKNOWN_MULTICAST &&
		    l2_lookup.mask_macaddr == SJA1105_UNKNOWN_MULTICAST)
			continue;

		u64_to_ether_addr(l2_lookup.macaddr, macaddr);

		/* Hardware FDB is shared for fdb and mdb, "bridge fdb show"
		 * only wants to see unicast
		 */
		if (is_multicast_ether_addr(macaddr))
			continue;

		/* We need to hide the dsa_8021q VLANs from the user. */
		if (vid_is_dsa_8021q(l2_lookup.vlanid))
			l2_lookup.vlanid = 0;
@@ -1898,6 +1918,8 @@ static void sja1105_fast_age(struct dsa_switch *ds, int port)
	};
	int i;

	mutex_lock(&priv->fdb_lock);

	for (i = 0; i < SJA1105_MAX_L2_LOOKUP_COUNT; i++) {
		struct sja1105_l2_lookup_entry l2_lookup = {0};
		u8 macaddr[ETH_ALEN];
@@ -1911,7 +1933,7 @@ static void sja1105_fast_age(struct dsa_switch *ds, int port)
		if (rc) {
			dev_err(ds->dev, "Failed to read FDB: %pe\n",
				ERR_PTR(rc));
			return;
			break;
		}

		if (!(l2_lookup.destports & BIT(port)))
@@ -1923,14 +1945,16 @@ static void sja1105_fast_age(struct dsa_switch *ds, int port)

		u64_to_ether_addr(l2_lookup.macaddr, macaddr);

		rc = sja1105_fdb_del(ds, port, macaddr, l2_lookup.vlanid, db);
		rc = __sja1105_fdb_del(ds, port, macaddr, l2_lookup.vlanid, db);
		if (rc) {
			dev_err(ds->dev,
				"Failed to delete FDB entry %pM vid %lld: %pe\n",
				macaddr, l2_lookup.vlanid, ERR_PTR(rc));
			return;
			break;
		}
	}

	mutex_unlock(&priv->fdb_lock);
}

static int sja1105_mdb_add(struct dsa_switch *ds, int port,
@@ -2273,6 +2297,7 @@ int sja1105_static_config_reload(struct sja1105_private *priv,
	int rc, i;
	s64 now;

	mutex_lock(&priv->fdb_lock);
	mutex_lock(&priv->mgmt_lock);

	mac = priv->static_config.tables[BLK_IDX_MAC_CONFIG].entries;
@@ -2385,6 +2410,7 @@ int sja1105_static_config_reload(struct sja1105_private *priv,
		goto out;
out:
	mutex_unlock(&priv->mgmt_lock);
	mutex_unlock(&priv->fdb_lock);

	return rc;
}
@@ -2954,7 +2980,9 @@ static int sja1105_port_mcast_flood(struct sja1105_private *priv, int to,
{
	struct sja1105_l2_lookup_entry *l2_lookup;
	struct sja1105_table *table;
	int match;
	int match, rc;

	mutex_lock(&priv->fdb_lock);

	table = &priv->static_config.tables[BLK_IDX_L2_LOOKUP];
	l2_lookup = table->entries;
@@ -2967,7 +2995,8 @@ static int sja1105_port_mcast_flood(struct sja1105_private *priv, int to,
	if (match == table->entry_count) {
		NL_SET_ERR_MSG_MOD(extack,
				   "Could not find FDB entry for unknown multicast");
		return -ENOSPC;
		rc = -ENOSPC;
		goto out;
	}

	if (flags.val & BR_MCAST_FLOOD)
@@ -2975,10 +3004,13 @@ static int sja1105_port_mcast_flood(struct sja1105_private *priv, int to,
	else
		l2_lookup[match].destports &= ~BIT(to);

	return sja1105_dynamic_config_write(priv, BLK_IDX_L2_LOOKUP,
	rc = sja1105_dynamic_config_write(priv, BLK_IDX_L2_LOOKUP,
					  l2_lookup[match].index,
					    &l2_lookup[match],
					    true);
					  &l2_lookup[match], true);
out:
	mutex_unlock(&priv->fdb_lock);

	return rc;
}

static int sja1105_port_pre_bridge_flags(struct dsa_switch *ds, int port,
@@ -3348,6 +3380,7 @@ static int sja1105_probe(struct spi_device *spi)
	mutex_init(&priv->ptp_data.lock);
	mutex_init(&priv->dynamic_config_lock);
	mutex_init(&priv->mgmt_lock);
	mutex_init(&priv->fdb_lock);
	spin_lock_init(&priv->ts_id_lock);

	rc = sja1105_parse_dt(priv);
+1 −1
Original line number Diff line number Diff line
@@ -1385,7 +1385,7 @@ static int adin1110_fdb_add(struct adin1110_port_priv *port_priv,
		return -ENOMEM;

	other_port = priv->ports[!port_priv->nr];
	port_rules = adin1110_port_rules(port_priv, false, true);
	port_rules = adin1110_port_rules(other_port, false, true);
	eth_broadcast_addr(mask);

	return adin1110_write_mac_address(other_port, mac_nr, (u8 *)fdb->addr,
+8 −2
Original line number Diff line number Diff line
@@ -528,13 +528,16 @@ void bcmasp_netfilt_suspend(struct bcmasp_intf *intf)
				  ASP_RX_FILTER_BLK_CTRL);
}

void bcmasp_netfilt_get_all_active(struct bcmasp_intf *intf, u32 *rule_locs,
int bcmasp_netfilt_get_all_active(struct bcmasp_intf *intf, u32 *rule_locs,
				  u32 *rule_cnt)
{
	struct bcmasp_priv *priv = intf->parent;
	int j = 0, i;

	for (i = 0; i < NUM_NET_FILTERS; i++) {
		if (j == *rule_cnt)
			return -EMSGSIZE;

		if (!priv->net_filters[i].claimed ||
		    priv->net_filters[i].port != intf->port)
			continue;
@@ -548,6 +551,8 @@ void bcmasp_netfilt_get_all_active(struct bcmasp_intf *intf, u32 *rule_locs,
	}

	*rule_cnt = j;

	return 0;
}

int bcmasp_netfilt_get_active(struct bcmasp_intf *intf)
@@ -1300,6 +1305,7 @@ static int bcmasp_probe(struct platform_device *pdev)
		if (!intf) {
			dev_err(dev, "Cannot create eth interface %d\n", i);
			bcmasp_remove_intfs(priv);
			of_node_put(intf_node);
			goto of_put_exit;
		}
		list_add_tail(&intf->list, &priv->intfs);
Loading