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

Commit fa804301 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'hsr-bug-fixes'



Cong Wang says:

====================
hsr: a few bug fixes

This patchset contains 3 bug fixes for hsr triggered by a syzbot
reproducer, please check each patch for details.
====================

Signed-off-by: default avatarCong Wang <xiyou.wangcong@gmail.com>
parents 114b5b35 edf070a0
Loading
Loading
Loading
Loading
+16 −13
Original line number Diff line number Diff line
@@ -227,9 +227,13 @@ static int hsr_dev_xmit(struct sk_buff *skb, struct net_device *dev)
	struct hsr_port *master;

	master = hsr_port_get_hsr(hsr, HSR_PT_MASTER);
	if (master) {
		skb->dev = master->dev;
		hsr_forward_skb(skb, master);

	} else {
		atomic_long_inc(&dev->tx_dropped);
		dev_kfree_skb_any(skb);
	}
	return NETDEV_TX_OK;
}

@@ -344,27 +348,26 @@ static void hsr_announce(struct timer_list *t)
	rcu_read_unlock();
}

/* According to comments in the declaration of struct net_device, this function
 * is "Called from unregister, can be used to call free_netdev". Ok then...
 */
static void hsr_dev_destroy(struct net_device *hsr_dev)
void hsr_dev_destroy(struct net_device *hsr_dev)
{
	struct hsr_priv *hsr;
	struct hsr_port *port;
	struct hsr_port *tmp;

	hsr = netdev_priv(hsr_dev);

	hsr_debugfs_term(hsr);

	rtnl_lock();
	hsr_for_each_port(hsr, port)
	list_for_each_entry_safe(port, tmp, &hsr->ports, port_list)
		hsr_del_port(port);
	rtnl_unlock();

	del_timer_sync(&hsr->prune_timer);
	del_timer_sync(&hsr->announce_timer);

	synchronize_rcu();

	hsr_del_self_node(&hsr->self_node_db);
	hsr_del_nodes(&hsr->node_db);
}

static const struct net_device_ops hsr_device_ops = {
@@ -391,7 +394,6 @@ void hsr_dev_setup(struct net_device *dev)
	dev->priv_flags |= IFF_NO_QUEUE;

	dev->needs_free_netdev = true;
	dev->priv_destructor = hsr_dev_destroy;

	dev->hw_features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA |
			   NETIF_F_GSO_MASK | NETIF_F_HW_CSUM |
@@ -428,6 +430,7 @@ int hsr_dev_finalize(struct net_device *hsr_dev, struct net_device *slave[2],
{
	struct hsr_priv *hsr;
	struct hsr_port *port;
	struct hsr_port *tmp;
	int res;

	hsr = netdev_priv(hsr_dev);
@@ -492,10 +495,10 @@ int hsr_dev_finalize(struct net_device *hsr_dev, struct net_device *slave[2],
	return 0;

fail:
	hsr_for_each_port(hsr, port)
	list_for_each_entry_safe(port, tmp, &hsr->ports, port_list)
		hsr_del_port(port);
err_add_port:
	hsr_del_node(&hsr->self_node_db);
	hsr_del_self_node(&hsr->self_node_db);

	return res;
}
+1 −0
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@
void hsr_dev_setup(struct net_device *dev);
int hsr_dev_finalize(struct net_device *hsr_dev, struct net_device *slave[2],
		     unsigned char multicast_spec, u8 protocol_version);
void hsr_dev_destroy(struct net_device *hsr_dev);
void hsr_check_carrier_and_operstate(struct hsr_priv *hsr);
bool is_hsr_master(struct net_device *dev);
int hsr_get_max_mtu(struct hsr_priv *hsr);
+10 −1
Original line number Diff line number Diff line
@@ -104,7 +104,7 @@ int hsr_create_self_node(struct list_head *self_node_db,
	return 0;
}

void hsr_del_node(struct list_head *self_node_db)
void hsr_del_self_node(struct list_head *self_node_db)
{
	struct hsr_node *node;

@@ -117,6 +117,15 @@ void hsr_del_node(struct list_head *self_node_db)
	}
}

void hsr_del_nodes(struct list_head *node_db)
{
	struct hsr_node *node;
	struct hsr_node *tmp;

	list_for_each_entry_safe(node, tmp, node_db, mac_list)
		kfree(node);
}

/* Allocate an hsr_node and add it to node_db. 'addr' is the node's address_A;
 * seq_out is used to initialize filtering of outgoing duplicate frames
 * originating from the newly added node.
+2 −1
Original line number Diff line number Diff line
@@ -12,7 +12,8 @@

struct hsr_node;

void hsr_del_node(struct list_head *self_node_db);
void hsr_del_self_node(struct list_head *self_node_db);
void hsr_del_nodes(struct list_head *node_db);
struct hsr_node *hsr_add_node(struct list_head *node_db, unsigned char addr[],
			      u16 seq_out);
struct hsr_node *hsr_get_node(struct hsr_port *port, struct sk_buff *skb,
+7 −0
Original line number Diff line number Diff line
@@ -69,6 +69,12 @@ static int hsr_newlink(struct net *src_net, struct net_device *dev,
	return hsr_dev_finalize(dev, link, multicast_spec, hsr_version);
}

static void hsr_dellink(struct net_device *hsr_dev, struct list_head *head)
{
	hsr_dev_destroy(hsr_dev);
	unregister_netdevice_queue(hsr_dev, head);
}

static int hsr_fill_info(struct sk_buff *skb, const struct net_device *dev)
{
	struct hsr_priv *hsr;
@@ -113,6 +119,7 @@ static struct rtnl_link_ops hsr_link_ops __read_mostly = {
	.priv_size	= sizeof(struct hsr_priv),
	.setup		= hsr_dev_setup,
	.newlink	= hsr_newlink,
	.dellink	= hsr_dellink,
	.fill_info	= hsr_fill_info,
};

Loading