Skip to content

Commit

Permalink
net: partially revert dynamic lockdep key changes
Browse files Browse the repository at this point in the history
This patch reverts the folowing commits:

commit 064ff66
"bonding: add missing netdev_update_lockdep_key()"

commit 53d3749
"net: avoid updating qdisc_xmit_lock_key in netdev_update_lockdep_key()"

commit 1f26c0d
"net: fix kernel-doc warning in <linux/netdevice.h>"

commit ab92d68
"net: core: add generic lockdep keys"

but keeps the addr_list_lock_key because we still lock
addr_list_lock nestedly on stack devices, unlikely xmit_lock
this is safe because we don't take addr_list_lock on any fast
path.

Reported-and-tested-by: syzbot+aaa6fa4949cc5d9b7b25@syzkaller.appspotmail.com
Cc: Dmitry Vyukov <dvyukov@google.com>
Cc: Taehee Yoo <ap420073@gmail.com>
Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
Acked-by: Taehee Yoo <ap420073@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
congwang authored and davem330 committed May 4, 2020
1 parent ea84c84 commit 1a33e10
Show file tree
Hide file tree
Showing 22 changed files with 294 additions and 33 deletions.
1 change: 1 addition & 0 deletions drivers/net/bonding/bond_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -4898,6 +4898,7 @@ static int bond_init(struct net_device *bond_dev)
spin_lock_init(&bond->stats_lock);
lockdep_register_key(&bond->stats_lock_key);
lockdep_set_class(&bond->stats_lock, &bond->stats_lock_key);
netdev_lockdep_set_classes(bond_dev);

list_add_tail(&bond->bond_list, &bn->dev_list);

Expand Down
16 changes: 16 additions & 0 deletions drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,20 @@ static void nfp_repr_clean(struct nfp_repr *repr)
nfp_port_free(repr->port);
}

static struct lock_class_key nfp_repr_netdev_xmit_lock_key;

static void nfp_repr_set_lockdep_class_one(struct net_device *dev,
struct netdev_queue *txq,
void *_unused)
{
lockdep_set_class(&txq->_xmit_lock, &nfp_repr_netdev_xmit_lock_key);
}

static void nfp_repr_set_lockdep_class(struct net_device *dev)
{
netdev_for_each_tx_queue(dev, nfp_repr_set_lockdep_class_one, NULL);
}

int nfp_repr_init(struct nfp_app *app, struct net_device *netdev,
u32 cmsg_port_id, struct nfp_port *port,
struct net_device *pf_netdev)
Expand All @@ -308,6 +322,8 @@ int nfp_repr_init(struct nfp_app *app, struct net_device *netdev,
u32 repr_cap = nn->tlv_caps.repr_cap;
int err;

nfp_repr_set_lockdep_class(netdev);

repr->port = port;
repr->dst = metadata_dst_alloc(0, METADATA_HW_PORT_MUX, GFP_KERNEL);
if (!repr->dst)
Expand Down
20 changes: 20 additions & 0 deletions drivers/net/hamradio/bpqether.c
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,25 @@ struct bpqdev {

static LIST_HEAD(bpq_devices);

/*
* bpqether network devices are paired with ethernet devices below them, so
* form a special "super class" of normal ethernet devices; split their locks
* off into a separate class since they always nest.
*/
static struct lock_class_key bpq_netdev_xmit_lock_key;

static void bpq_set_lockdep_class_one(struct net_device *dev,
struct netdev_queue *txq,
void *_unused)
{
lockdep_set_class(&txq->_xmit_lock, &bpq_netdev_xmit_lock_key);
}

static void bpq_set_lockdep_class(struct net_device *dev)
{
netdev_for_each_tx_queue(dev, bpq_set_lockdep_class_one, NULL);
}

/* ------------------------------------------------------------------------ */


Expand Down Expand Up @@ -477,6 +496,7 @@ static int bpq_new_device(struct net_device *edev)
err = register_netdevice(ndev);
if (err)
goto error;
bpq_set_lockdep_class(ndev);

/* List protected by RTNL */
list_add_rcu(&bpq->bpq_list, &bpq_devices);
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/hyperv/netvsc_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -2456,6 +2456,8 @@ static int netvsc_probe(struct hv_device *dev,
NETIF_F_HW_VLAN_CTAG_RX;
net->vlan_features = net->features;

netdev_lockdep_set_classes(net);

/* MTU range: 68 - 1500 or 65521 */
net->min_mtu = NETVSC_MTU_MIN;
if (nvdev->nvsp_version >= NVSP_PROTOCOL_VERSION_2)
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/ipvlan/ipvlan_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,8 @@ static int ipvlan_init(struct net_device *dev)
dev->gso_max_segs = phy_dev->gso_max_segs;
dev->hard_header_len = phy_dev->hard_header_len;

netdev_lockdep_set_classes(dev);

ipvlan->pcpu_stats = netdev_alloc_pcpu_stats(struct ipvl_pcpu_stats);
if (!ipvlan->pcpu_stats)
return -ENOMEM;
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/macsec.c
Original file line number Diff line number Diff line change
Expand Up @@ -4047,6 +4047,8 @@ static int macsec_newlink(struct net *net, struct net_device *dev,
if (err < 0)
return err;

netdev_lockdep_set_classes(dev);

err = netdev_upper_dev_link(real_dev, dev, extack);
if (err < 0)
goto unregister;
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/macvlan.c
Original file line number Diff line number Diff line change
Expand Up @@ -890,6 +890,8 @@ static int macvlan_init(struct net_device *dev)
dev->gso_max_segs = lowerdev->gso_max_segs;
dev->hard_header_len = lowerdev->hard_header_len;

netdev_lockdep_set_classes(dev);

vlan->pcpu_stats = netdev_alloc_pcpu_stats(struct vlan_pcpu_stats);
if (!vlan->pcpu_stats)
return -ENOMEM;
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/ppp/ppp_generic.c
Original file line number Diff line number Diff line change
Expand Up @@ -1410,6 +1410,8 @@ static int ppp_dev_init(struct net_device *dev)
{
struct ppp *ppp;

netdev_lockdep_set_classes(dev);

ppp = netdev_priv(dev);
/* Let the netdevice take a reference on the ppp file. This ensures
* that ppp_destroy_interface() won't run before the device gets
Expand Down
1 change: 1 addition & 0 deletions drivers/net/team/team.c
Original file line number Diff line number Diff line change
Expand Up @@ -1647,6 +1647,7 @@ static int team_init(struct net_device *dev)

lockdep_register_key(&team->team_lock_key);
__mutex_init(&team->lock, "team->team_lock_key", &team->team_lock_key);
netdev_lockdep_set_classes(dev);

return 0;

Expand Down
1 change: 1 addition & 0 deletions drivers/net/vrf.c
Original file line number Diff line number Diff line change
Expand Up @@ -867,6 +867,7 @@ static int vrf_dev_init(struct net_device *dev)

/* similarly, oper state is irrelevant; set to up to avoid confusion */
dev->operstate = IF_OPER_UP;
netdev_lockdep_set_classes(dev);
return 0;

out_rth:
Expand Down
22 changes: 22 additions & 0 deletions drivers/net/wireless/intersil/hostap/hostap_hw.c
Original file line number Diff line number Diff line change
Expand Up @@ -3041,6 +3041,27 @@ static void prism2_clear_set_tim_queue(local_info_t *local)
}
}


/*
* HostAP uses two layers of net devices, where the inner
* layer gets called all the time from the outer layer.
* This is a natural nesting, which needs a split lock type.
*/
static struct lock_class_key hostap_netdev_xmit_lock_key;

static void prism2_set_lockdep_class_one(struct net_device *dev,
struct netdev_queue *txq,
void *_unused)
{
lockdep_set_class(&txq->_xmit_lock,
&hostap_netdev_xmit_lock_key);
}

static void prism2_set_lockdep_class(struct net_device *dev)
{
netdev_for_each_tx_queue(dev, prism2_set_lockdep_class_one, NULL);
}

static struct net_device *
prism2_init_local_data(struct prism2_helper_functions *funcs, int card_idx,
struct device *sdev)
Expand Down Expand Up @@ -3199,6 +3220,7 @@ while (0)
if (ret >= 0)
ret = register_netdevice(dev);

prism2_set_lockdep_class(dev);
rtnl_unlock();
if (ret < 0) {
printk(KERN_WARNING "%s: register netdevice failed!\n",
Expand Down
27 changes: 19 additions & 8 deletions include/linux/netdevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -1805,13 +1805,11 @@ enum netdev_priv_flags {
* @phydev: Physical device may attach itself
* for hardware timestamping
* @sfp_bus: attached &struct sfp_bus structure.
* @qdisc_tx_busylock_key: lockdep class annotating Qdisc->busylock
* spinlock
* @qdisc_running_key: lockdep class annotating Qdisc->running seqcount
* @qdisc_xmit_lock_key: lockdep class annotating
* netdev_queue->_xmit_lock spinlock
*
* @addr_list_lock_key: lockdep class annotating
* net_device->addr_list_lock spinlock
* @qdisc_tx_busylock: lockdep class annotating Qdisc->busylock spinlock
* @qdisc_running_key: lockdep class annotating Qdisc->running seqcount
*
* @proto_down: protocol port state information can be sent to the
* switch driver and used to set the phys state of the
Expand Down Expand Up @@ -2112,10 +2110,9 @@ struct net_device {
#endif
struct phy_device *phydev;
struct sfp_bus *sfp_bus;
struct lock_class_key qdisc_tx_busylock_key;
struct lock_class_key qdisc_running_key;
struct lock_class_key qdisc_xmit_lock_key;
struct lock_class_key addr_list_lock_key;
struct lock_class_key *qdisc_tx_busylock;
struct lock_class_key *qdisc_running_key;
bool proto_down;
unsigned wol_enabled:1;

Expand Down Expand Up @@ -2200,6 +2197,20 @@ static inline void netdev_for_each_tx_queue(struct net_device *dev,
f(dev, &dev->_tx[i], arg);
}

#define netdev_lockdep_set_classes(dev) \
{ \
static struct lock_class_key qdisc_tx_busylock_key; \
static struct lock_class_key qdisc_running_key; \
static struct lock_class_key qdisc_xmit_lock_key; \
unsigned int i; \
\
(dev)->qdisc_tx_busylock = &qdisc_tx_busylock_key; \
(dev)->qdisc_running_key = &qdisc_running_key; \
for (i = 0; i < (dev)->num_tx_queues; i++) \
lockdep_set_class(&(dev)->_tx[i]._xmit_lock, \
&qdisc_xmit_lock_key); \
}

u16 netdev_pick_tx(struct net_device *dev, struct sk_buff *skb,
struct net_device *sb_dev);
struct netdev_queue *netdev_core_pick_tx(struct net_device *dev,
Expand Down
21 changes: 21 additions & 0 deletions net/8021q/vlan_dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,25 @@ static void vlan_dev_set_rx_mode(struct net_device *vlan_dev)
dev_uc_sync(vlan_dev_priv(vlan_dev)->real_dev, vlan_dev);
}

/*
* vlan network devices have devices nesting below it, and are a special
* "super class" of normal network devices; split their locks off into a
* separate class since they always nest.
*/
static struct lock_class_key vlan_netdev_xmit_lock_key;

static void vlan_dev_set_lockdep_one(struct net_device *dev,
struct netdev_queue *txq,
void *unused)
{
lockdep_set_class(&txq->_xmit_lock, &vlan_netdev_xmit_lock_key);
}

static void vlan_dev_set_lockdep_class(struct net_device *dev)
{
netdev_for_each_tx_queue(dev, vlan_dev_set_lockdep_one, NULL);
}

static const struct header_ops vlan_header_ops = {
.create = vlan_dev_hard_header,
.parse = eth_header_parse,
Expand Down Expand Up @@ -579,6 +598,8 @@ static int vlan_dev_init(struct net_device *dev)

SET_NETDEV_DEVTYPE(dev, &vlan_type);

vlan_dev_set_lockdep_class(dev);

vlan->vlan_pcpu_stats = netdev_alloc_pcpu_stats(struct vlan_pcpu_stats);
if (!vlan->vlan_pcpu_stats)
return -ENOMEM;
Expand Down
30 changes: 30 additions & 0 deletions net/batman-adv/soft-interface.c
Original file line number Diff line number Diff line change
Expand Up @@ -739,6 +739,34 @@ static int batadv_interface_kill_vid(struct net_device *dev, __be16 proto,
return 0;
}

/* batman-adv network devices have devices nesting below it and are a special
* "super class" of normal network devices; split their locks off into a
* separate class since they always nest.
*/
static struct lock_class_key batadv_netdev_xmit_lock_key;

/**
* batadv_set_lockdep_class_one() - Set lockdep class for a single tx queue
* @dev: device which owns the tx queue
* @txq: tx queue to modify
* @_unused: always NULL
*/
static void batadv_set_lockdep_class_one(struct net_device *dev,
struct netdev_queue *txq,
void *_unused)
{
lockdep_set_class(&txq->_xmit_lock, &batadv_netdev_xmit_lock_key);
}

/**
* batadv_set_lockdep_class() - Set txq and addr_list lockdep class
* @dev: network device to modify
*/
static void batadv_set_lockdep_class(struct net_device *dev)
{
netdev_for_each_tx_queue(dev, batadv_set_lockdep_class_one, NULL);
}

/**
* batadv_softif_init_late() - late stage initialization of soft interface
* @dev: registered network device to modify
Expand All @@ -752,6 +780,8 @@ static int batadv_softif_init_late(struct net_device *dev)
int ret;
size_t cnt_len = sizeof(u64) * BATADV_CNT_NUM;

batadv_set_lockdep_class(dev);

bat_priv = netdev_priv(dev);
bat_priv->soft_iface = dev;

Expand Down
8 changes: 8 additions & 0 deletions net/bluetooth/6lowpan.c
Original file line number Diff line number Diff line change
Expand Up @@ -571,7 +571,15 @@ static netdev_tx_t bt_xmit(struct sk_buff *skb, struct net_device *netdev)
return err < 0 ? NET_XMIT_DROP : err;
}

static int bt_dev_init(struct net_device *dev)
{
netdev_lockdep_set_classes(dev);

return 0;
}

static const struct net_device_ops netdev_ops = {
.ndo_init = bt_dev_init,
.ndo_start_xmit = bt_xmit,
};

Expand Down
Loading

0 comments on commit 1a33e10

Please sign in to comment.