Commit 664f1b85 authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

Merge branch 'with-a-mutex'

Eric Dumazet says:

====================
net: atm: protect dev_lec[] with a mutex

Based on an initial syzbot report.

First patch is adding lec_mutex to address the report.

Second patch protects /proc/net/atm/lec operations.

We probably should delete this driver, it seems quite broken.
====================

Link: https://patch.msgid.link/20250618140844.1686882-1-edumazet@google.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents e7ea5f5b d03b79f4
Loading
Loading
Loading
Loading
+10 −2
Original line number Diff line number Diff line
@@ -124,6 +124,7 @@ static unsigned char bus_mac[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };

/* Device structures */
static struct net_device *dev_lec[MAX_LEC_ITF];
static DEFINE_MUTEX(lec_mutex);

#if IS_ENABLED(CONFIG_BRIDGE)
static void lec_handle_bridge(struct sk_buff *skb, struct net_device *dev)
@@ -685,6 +686,7 @@ static int lec_vcc_attach(struct atm_vcc *vcc, void __user *arg)
	int bytes_left;
	struct atmlec_ioc ioc_data;

	lockdep_assert_held(&lec_mutex);
	/* Lecd must be up in this case */
	bytes_left = copy_from_user(&ioc_data, arg, sizeof(struct atmlec_ioc));
	if (bytes_left != 0)
@@ -710,6 +712,7 @@ static int lec_vcc_attach(struct atm_vcc *vcc, void __user *arg)

static int lec_mcast_attach(struct atm_vcc *vcc, int arg)
{
	lockdep_assert_held(&lec_mutex);
	if (arg < 0 || arg >= MAX_LEC_ITF)
		return -EINVAL;
	arg = array_index_nospec(arg, MAX_LEC_ITF);
@@ -725,6 +728,7 @@ static int lecd_attach(struct atm_vcc *vcc, int arg)
	int i;
	struct lec_priv *priv;

	lockdep_assert_held(&lec_mutex);
	if (arg < 0)
		arg = 0;
	if (arg >= MAX_LEC_ITF)
@@ -742,6 +746,7 @@ static int lecd_attach(struct atm_vcc *vcc, int arg)
		snprintf(dev_lec[i]->name, IFNAMSIZ, "lec%d", i);
		if (register_netdev(dev_lec[i])) {
			free_netdev(dev_lec[i]);
			dev_lec[i] = NULL;
			return -EINVAL;
		}

@@ -904,7 +909,6 @@ static void *lec_itf_walk(struct lec_state *state, loff_t *l)
	v = (dev && netdev_priv(dev)) ?
		lec_priv_walk(state, l, netdev_priv(dev)) : NULL;
	if (!v && dev) {
		dev_put(dev);
		/* Partial state reset for the next time we get called */
		dev = NULL;
	}
@@ -928,6 +932,7 @@ static void *lec_seq_start(struct seq_file *seq, loff_t *pos)
{
	struct lec_state *state = seq->private;

	mutex_lock(&lec_mutex);
	state->itf = 0;
	state->dev = NULL;
	state->locked = NULL;
@@ -945,8 +950,9 @@ static void lec_seq_stop(struct seq_file *seq, void *v)
	if (state->dev) {
		spin_unlock_irqrestore(&state->locked->lec_arp_lock,
				       state->flags);
		dev_put(state->dev);
		state->dev = NULL;
	}
	mutex_unlock(&lec_mutex);
}

static void *lec_seq_next(struct seq_file *seq, void *v, loff_t *pos)
@@ -1003,6 +1009,7 @@ static int lane_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
		return -ENOIOCTLCMD;
	}

	mutex_lock(&lec_mutex);
	switch (cmd) {
	case ATMLEC_CTRL:
		err = lecd_attach(vcc, (int)arg);
@@ -1017,6 +1024,7 @@ static int lane_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
		break;
	}

	mutex_unlock(&lec_mutex);
	return err;
}