Here are two batman-adv bugfixes:
* Fix free/alloc race for OGM and OGMv2, by Sven Eckelmann (2 patches) -----BEGIN PGP SIGNATURE----- iQJKBAABCgA0FiEE1ilQI7G+y+fdhnrfoSvjmEKSnqEFAl2yvoAWHHN3QHNpbW9u d3VuZGVybGljaC5kZQAKCRChK+OYQpKeoVosEAC7Ei09QJKa2Wh6by4c8OQKvloK ecei39e0FjMUx4/XETSR/kdHrRFwzMPvIhqe+DUCski7p5x9sHWrkJwIWWirGrDf mAsF8mhA1E0pfsQmQRqu4h/UbDyLLhsbfEf95B75Uf6Nq2cIG0Ko7rb2ao3DR7c2 YwvSjzT+zwlS8Q6Hj1YsJKSS3BEk5NQ9r9soD9WhwWmYynn9TxTWy8o9z3lBCXtV j+mOm0qNebxsDKhr7jbfujjIaepmTOQJHwqPzm1Vo/v6CMEdJzd6j8vbsxCUyXvI /Cg3V+8INEGmRmCDT96paO5kYkHptr8i467Raj3DAdwlh3BuoMo382i3D3GOXgEK VtieWhuOplAJrbc+GFifvFSAA75+B8rZ/IV8CDFIbWHhEjZ/fdtyl1panqQkKSqw n5m/nAyKmfTZ9CH0kZ/zKU8EKPaMNh0BUTbjhU/8Zn0lDI+loBs024K5a00TWtD8 GnjCGKi87HhtCn/3hxasbaVEyJIrMvPlzyYRylzFfSml55GCBuA8i8l/7ql0QKCe xq78J08x/n3RjAj+aguLQ1v4Vz/EgOvzj4RdfHS2CGSI9m37z7wz5oFTKcqi4tX+ 4Phpl7onRnMDx6AiZHMGxwrti/AdFO3YZmOiIh/IEBjUBhmABuj6Eq40thl/8Hkv DfoOTKf98HhmaW6d/g== =usWf -----END PGP SIGNATURE----- Merge tag 'batadv-net-for-davem-20191025' of git://git.open-mesh.org/linux-merge Simon Wunderlich says: ==================== Here are two batman-adv bugfixes: * Fix free/alloc race for OGM and OGMv2, by Sven Eckelmann (2 patches) ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
55793d2a43
|
@ -22,6 +22,8 @@
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/kref.h>
|
#include <linux/kref.h>
|
||||||
#include <linux/list.h>
|
#include <linux/list.h>
|
||||||
|
#include <linux/lockdep.h>
|
||||||
|
#include <linux/mutex.h>
|
||||||
#include <linux/netdevice.h>
|
#include <linux/netdevice.h>
|
||||||
#include <linux/netlink.h>
|
#include <linux/netlink.h>
|
||||||
#include <linux/pkt_sched.h>
|
#include <linux/pkt_sched.h>
|
||||||
|
@ -193,14 +195,18 @@ static int batadv_iv_ogm_iface_enable(struct batadv_hard_iface *hard_iface)
|
||||||
unsigned char *ogm_buff;
|
unsigned char *ogm_buff;
|
||||||
u32 random_seqno;
|
u32 random_seqno;
|
||||||
|
|
||||||
|
mutex_lock(&hard_iface->bat_iv.ogm_buff_mutex);
|
||||||
|
|
||||||
/* randomize initial seqno to avoid collision */
|
/* randomize initial seqno to avoid collision */
|
||||||
get_random_bytes(&random_seqno, sizeof(random_seqno));
|
get_random_bytes(&random_seqno, sizeof(random_seqno));
|
||||||
atomic_set(&hard_iface->bat_iv.ogm_seqno, random_seqno);
|
atomic_set(&hard_iface->bat_iv.ogm_seqno, random_seqno);
|
||||||
|
|
||||||
hard_iface->bat_iv.ogm_buff_len = BATADV_OGM_HLEN;
|
hard_iface->bat_iv.ogm_buff_len = BATADV_OGM_HLEN;
|
||||||
ogm_buff = kmalloc(hard_iface->bat_iv.ogm_buff_len, GFP_ATOMIC);
|
ogm_buff = kmalloc(hard_iface->bat_iv.ogm_buff_len, GFP_ATOMIC);
|
||||||
if (!ogm_buff)
|
if (!ogm_buff) {
|
||||||
|
mutex_unlock(&hard_iface->bat_iv.ogm_buff_mutex);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
hard_iface->bat_iv.ogm_buff = ogm_buff;
|
hard_iface->bat_iv.ogm_buff = ogm_buff;
|
||||||
|
|
||||||
|
@ -212,35 +218,59 @@ static int batadv_iv_ogm_iface_enable(struct batadv_hard_iface *hard_iface)
|
||||||
batadv_ogm_packet->reserved = 0;
|
batadv_ogm_packet->reserved = 0;
|
||||||
batadv_ogm_packet->tq = BATADV_TQ_MAX_VALUE;
|
batadv_ogm_packet->tq = BATADV_TQ_MAX_VALUE;
|
||||||
|
|
||||||
|
mutex_unlock(&hard_iface->bat_iv.ogm_buff_mutex);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void batadv_iv_ogm_iface_disable(struct batadv_hard_iface *hard_iface)
|
static void batadv_iv_ogm_iface_disable(struct batadv_hard_iface *hard_iface)
|
||||||
{
|
{
|
||||||
|
mutex_lock(&hard_iface->bat_iv.ogm_buff_mutex);
|
||||||
|
|
||||||
kfree(hard_iface->bat_iv.ogm_buff);
|
kfree(hard_iface->bat_iv.ogm_buff);
|
||||||
hard_iface->bat_iv.ogm_buff = NULL;
|
hard_iface->bat_iv.ogm_buff = NULL;
|
||||||
|
|
||||||
|
mutex_unlock(&hard_iface->bat_iv.ogm_buff_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void batadv_iv_ogm_iface_update_mac(struct batadv_hard_iface *hard_iface)
|
static void batadv_iv_ogm_iface_update_mac(struct batadv_hard_iface *hard_iface)
|
||||||
{
|
{
|
||||||
struct batadv_ogm_packet *batadv_ogm_packet;
|
struct batadv_ogm_packet *batadv_ogm_packet;
|
||||||
unsigned char *ogm_buff = hard_iface->bat_iv.ogm_buff;
|
void *ogm_buff;
|
||||||
|
|
||||||
batadv_ogm_packet = (struct batadv_ogm_packet *)ogm_buff;
|
mutex_lock(&hard_iface->bat_iv.ogm_buff_mutex);
|
||||||
|
|
||||||
|
ogm_buff = hard_iface->bat_iv.ogm_buff;
|
||||||
|
if (!ogm_buff)
|
||||||
|
goto unlock;
|
||||||
|
|
||||||
|
batadv_ogm_packet = ogm_buff;
|
||||||
ether_addr_copy(batadv_ogm_packet->orig,
|
ether_addr_copy(batadv_ogm_packet->orig,
|
||||||
hard_iface->net_dev->dev_addr);
|
hard_iface->net_dev->dev_addr);
|
||||||
ether_addr_copy(batadv_ogm_packet->prev_sender,
|
ether_addr_copy(batadv_ogm_packet->prev_sender,
|
||||||
hard_iface->net_dev->dev_addr);
|
hard_iface->net_dev->dev_addr);
|
||||||
|
|
||||||
|
unlock:
|
||||||
|
mutex_unlock(&hard_iface->bat_iv.ogm_buff_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
batadv_iv_ogm_primary_iface_set(struct batadv_hard_iface *hard_iface)
|
batadv_iv_ogm_primary_iface_set(struct batadv_hard_iface *hard_iface)
|
||||||
{
|
{
|
||||||
struct batadv_ogm_packet *batadv_ogm_packet;
|
struct batadv_ogm_packet *batadv_ogm_packet;
|
||||||
unsigned char *ogm_buff = hard_iface->bat_iv.ogm_buff;
|
void *ogm_buff;
|
||||||
|
|
||||||
batadv_ogm_packet = (struct batadv_ogm_packet *)ogm_buff;
|
mutex_lock(&hard_iface->bat_iv.ogm_buff_mutex);
|
||||||
|
|
||||||
|
ogm_buff = hard_iface->bat_iv.ogm_buff;
|
||||||
|
if (!ogm_buff)
|
||||||
|
goto unlock;
|
||||||
|
|
||||||
|
batadv_ogm_packet = ogm_buff;
|
||||||
batadv_ogm_packet->ttl = BATADV_TTL;
|
batadv_ogm_packet->ttl = BATADV_TTL;
|
||||||
|
|
||||||
|
unlock:
|
||||||
|
mutex_unlock(&hard_iface->bat_iv.ogm_buff_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* when do we schedule our own ogm to be sent */
|
/* when do we schedule our own ogm to be sent */
|
||||||
|
@ -742,7 +772,11 @@ batadv_iv_ogm_slide_own_bcast_window(struct batadv_hard_iface *hard_iface)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface)
|
/**
|
||||||
|
* batadv_iv_ogm_schedule_buff() - schedule submission of hardif ogm buffer
|
||||||
|
* @hard_iface: interface whose ogm buffer should be transmitted
|
||||||
|
*/
|
||||||
|
static void batadv_iv_ogm_schedule_buff(struct batadv_hard_iface *hard_iface)
|
||||||
{
|
{
|
||||||
struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
|
struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
|
||||||
unsigned char **ogm_buff = &hard_iface->bat_iv.ogm_buff;
|
unsigned char **ogm_buff = &hard_iface->bat_iv.ogm_buff;
|
||||||
|
@ -753,9 +787,7 @@ static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface)
|
||||||
u16 tvlv_len = 0;
|
u16 tvlv_len = 0;
|
||||||
unsigned long send_time;
|
unsigned long send_time;
|
||||||
|
|
||||||
if (hard_iface->if_status == BATADV_IF_NOT_IN_USE ||
|
lockdep_assert_held(&hard_iface->bat_iv.ogm_buff_mutex);
|
||||||
hard_iface->if_status == BATADV_IF_TO_BE_REMOVED)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* the interface gets activated here to avoid race conditions between
|
/* the interface gets activated here to avoid race conditions between
|
||||||
* the moment of activating the interface in
|
* the moment of activating the interface in
|
||||||
|
@ -823,6 +855,17 @@ out:
|
||||||
batadv_hardif_put(primary_if);
|
batadv_hardif_put(primary_if);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface)
|
||||||
|
{
|
||||||
|
if (hard_iface->if_status == BATADV_IF_NOT_IN_USE ||
|
||||||
|
hard_iface->if_status == BATADV_IF_TO_BE_REMOVED)
|
||||||
|
return;
|
||||||
|
|
||||||
|
mutex_lock(&hard_iface->bat_iv.ogm_buff_mutex);
|
||||||
|
batadv_iv_ogm_schedule_buff(hard_iface);
|
||||||
|
mutex_unlock(&hard_iface->bat_iv.ogm_buff_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* batadv_iv_orig_ifinfo_sum() - Get bcast_own sum for originator over iterface
|
* batadv_iv_orig_ifinfo_sum() - Get bcast_own sum for originator over iterface
|
||||||
* @orig_node: originator which reproadcasted the OGMs directly
|
* @orig_node: originator which reproadcasted the OGMs directly
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include <linux/kref.h>
|
#include <linux/kref.h>
|
||||||
#include <linux/list.h>
|
#include <linux/list.h>
|
||||||
#include <linux/lockdep.h>
|
#include <linux/lockdep.h>
|
||||||
|
#include <linux/mutex.h>
|
||||||
#include <linux/netdevice.h>
|
#include <linux/netdevice.h>
|
||||||
#include <linux/random.h>
|
#include <linux/random.h>
|
||||||
#include <linux/rculist.h>
|
#include <linux/rculist.h>
|
||||||
|
@ -256,14 +257,12 @@ static void batadv_v_ogm_queue_on_if(struct sk_buff *skb,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* batadv_v_ogm_send() - periodic worker broadcasting the own OGM
|
* batadv_v_ogm_send_softif() - periodic worker broadcasting the own OGM
|
||||||
* @work: work queue item
|
* @bat_priv: the bat priv with all the soft interface information
|
||||||
*/
|
*/
|
||||||
static void batadv_v_ogm_send(struct work_struct *work)
|
static void batadv_v_ogm_send_softif(struct batadv_priv *bat_priv)
|
||||||
{
|
{
|
||||||
struct batadv_hard_iface *hard_iface;
|
struct batadv_hard_iface *hard_iface;
|
||||||
struct batadv_priv_bat_v *bat_v;
|
|
||||||
struct batadv_priv *bat_priv;
|
|
||||||
struct batadv_ogm2_packet *ogm_packet;
|
struct batadv_ogm2_packet *ogm_packet;
|
||||||
struct sk_buff *skb, *skb_tmp;
|
struct sk_buff *skb, *skb_tmp;
|
||||||
unsigned char *ogm_buff;
|
unsigned char *ogm_buff;
|
||||||
|
@ -271,8 +270,7 @@ static void batadv_v_ogm_send(struct work_struct *work)
|
||||||
u16 tvlv_len = 0;
|
u16 tvlv_len = 0;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
bat_v = container_of(work, struct batadv_priv_bat_v, ogm_wq.work);
|
lockdep_assert_held(&bat_priv->bat_v.ogm_buff_mutex);
|
||||||
bat_priv = container_of(bat_v, struct batadv_priv, bat_v);
|
|
||||||
|
|
||||||
if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_DEACTIVATING)
|
if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_DEACTIVATING)
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -363,6 +361,23 @@ out:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* batadv_v_ogm_send() - periodic worker broadcasting the own OGM
|
||||||
|
* @work: work queue item
|
||||||
|
*/
|
||||||
|
static void batadv_v_ogm_send(struct work_struct *work)
|
||||||
|
{
|
||||||
|
struct batadv_priv_bat_v *bat_v;
|
||||||
|
struct batadv_priv *bat_priv;
|
||||||
|
|
||||||
|
bat_v = container_of(work, struct batadv_priv_bat_v, ogm_wq.work);
|
||||||
|
bat_priv = container_of(bat_v, struct batadv_priv, bat_v);
|
||||||
|
|
||||||
|
mutex_lock(&bat_priv->bat_v.ogm_buff_mutex);
|
||||||
|
batadv_v_ogm_send_softif(bat_priv);
|
||||||
|
mutex_unlock(&bat_priv->bat_v.ogm_buff_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* batadv_v_ogm_aggr_work() - OGM queue periodic task per interface
|
* batadv_v_ogm_aggr_work() - OGM queue periodic task per interface
|
||||||
* @work: work queue item
|
* @work: work queue item
|
||||||
|
@ -424,11 +439,15 @@ void batadv_v_ogm_primary_iface_set(struct batadv_hard_iface *primary_iface)
|
||||||
struct batadv_priv *bat_priv = netdev_priv(primary_iface->soft_iface);
|
struct batadv_priv *bat_priv = netdev_priv(primary_iface->soft_iface);
|
||||||
struct batadv_ogm2_packet *ogm_packet;
|
struct batadv_ogm2_packet *ogm_packet;
|
||||||
|
|
||||||
|
mutex_lock(&bat_priv->bat_v.ogm_buff_mutex);
|
||||||
if (!bat_priv->bat_v.ogm_buff)
|
if (!bat_priv->bat_v.ogm_buff)
|
||||||
return;
|
goto unlock;
|
||||||
|
|
||||||
ogm_packet = (struct batadv_ogm2_packet *)bat_priv->bat_v.ogm_buff;
|
ogm_packet = (struct batadv_ogm2_packet *)bat_priv->bat_v.ogm_buff;
|
||||||
ether_addr_copy(ogm_packet->orig, primary_iface->net_dev->dev_addr);
|
ether_addr_copy(ogm_packet->orig, primary_iface->net_dev->dev_addr);
|
||||||
|
|
||||||
|
unlock:
|
||||||
|
mutex_unlock(&bat_priv->bat_v.ogm_buff_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1050,6 +1069,8 @@ int batadv_v_ogm_init(struct batadv_priv *bat_priv)
|
||||||
atomic_set(&bat_priv->bat_v.ogm_seqno, random_seqno);
|
atomic_set(&bat_priv->bat_v.ogm_seqno, random_seqno);
|
||||||
INIT_DELAYED_WORK(&bat_priv->bat_v.ogm_wq, batadv_v_ogm_send);
|
INIT_DELAYED_WORK(&bat_priv->bat_v.ogm_wq, batadv_v_ogm_send);
|
||||||
|
|
||||||
|
mutex_init(&bat_priv->bat_v.ogm_buff_mutex);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1061,7 +1082,11 @@ void batadv_v_ogm_free(struct batadv_priv *bat_priv)
|
||||||
{
|
{
|
||||||
cancel_delayed_work_sync(&bat_priv->bat_v.ogm_wq);
|
cancel_delayed_work_sync(&bat_priv->bat_v.ogm_wq);
|
||||||
|
|
||||||
|
mutex_lock(&bat_priv->bat_v.ogm_buff_mutex);
|
||||||
|
|
||||||
kfree(bat_priv->bat_v.ogm_buff);
|
kfree(bat_priv->bat_v.ogm_buff);
|
||||||
bat_priv->bat_v.ogm_buff = NULL;
|
bat_priv->bat_v.ogm_buff = NULL;
|
||||||
bat_priv->bat_v.ogm_buff_len = 0;
|
bat_priv->bat_v.ogm_buff_len = 0;
|
||||||
|
|
||||||
|
mutex_unlock(&bat_priv->bat_v.ogm_buff_mutex);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include <linux/kref.h>
|
#include <linux/kref.h>
|
||||||
#include <linux/limits.h>
|
#include <linux/limits.h>
|
||||||
#include <linux/list.h>
|
#include <linux/list.h>
|
||||||
|
#include <linux/mutex.h>
|
||||||
#include <linux/netdevice.h>
|
#include <linux/netdevice.h>
|
||||||
#include <linux/printk.h>
|
#include <linux/printk.h>
|
||||||
#include <linux/rculist.h>
|
#include <linux/rculist.h>
|
||||||
|
@ -929,6 +930,7 @@ batadv_hardif_add_interface(struct net_device *net_dev)
|
||||||
INIT_LIST_HEAD(&hard_iface->list);
|
INIT_LIST_HEAD(&hard_iface->list);
|
||||||
INIT_HLIST_HEAD(&hard_iface->neigh_list);
|
INIT_HLIST_HEAD(&hard_iface->neigh_list);
|
||||||
|
|
||||||
|
mutex_init(&hard_iface->bat_iv.ogm_buff_mutex);
|
||||||
spin_lock_init(&hard_iface->neigh_list_lock);
|
spin_lock_init(&hard_iface->neigh_list_lock);
|
||||||
kref_init(&hard_iface->refcount);
|
kref_init(&hard_iface->refcount);
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include <linux/if.h>
|
#include <linux/if.h>
|
||||||
#include <linux/if_ether.h>
|
#include <linux/if_ether.h>
|
||||||
#include <linux/kref.h>
|
#include <linux/kref.h>
|
||||||
|
#include <linux/mutex.h>
|
||||||
#include <linux/netdevice.h>
|
#include <linux/netdevice.h>
|
||||||
#include <linux/netlink.h>
|
#include <linux/netlink.h>
|
||||||
#include <linux/sched.h> /* for linux/wait.h */
|
#include <linux/sched.h> /* for linux/wait.h */
|
||||||
|
@ -81,6 +82,9 @@ struct batadv_hard_iface_bat_iv {
|
||||||
|
|
||||||
/** @ogm_seqno: OGM sequence number - used to identify each OGM */
|
/** @ogm_seqno: OGM sequence number - used to identify each OGM */
|
||||||
atomic_t ogm_seqno;
|
atomic_t ogm_seqno;
|
||||||
|
|
||||||
|
/** @ogm_buff_mutex: lock protecting ogm_buff and ogm_buff_len */
|
||||||
|
struct mutex ogm_buff_mutex;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1539,6 +1543,9 @@ struct batadv_priv_bat_v {
|
||||||
/** @ogm_seqno: OGM sequence number - used to identify each OGM */
|
/** @ogm_seqno: OGM sequence number - used to identify each OGM */
|
||||||
atomic_t ogm_seqno;
|
atomic_t ogm_seqno;
|
||||||
|
|
||||||
|
/** @ogm_buff_mutex: lock protecting ogm_buff and ogm_buff_len */
|
||||||
|
struct mutex ogm_buff_mutex;
|
||||||
|
|
||||||
/** @ogm_wq: workqueue used to schedule OGM transmissions */
|
/** @ogm_wq: workqueue used to schedule OGM transmissions */
|
||||||
struct delayed_work ogm_wq;
|
struct delayed_work ogm_wq;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue