From: Greg Kroah-Hartman Date: Tue, 17 Mar 2020 10:19:59 +0000 (+0100) Subject: 4.19-stable patches X-Git-Tag: v4.19.111~1 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=230c61152d062fdd35d6b0eee3d784908f562538;p=thirdparty%2Fkernel%2Fstable-queue.git 4.19-stable patches added patches: batman-adv-avoid-free-alloc-race-when-handling-ogm2-buffer.patch --- diff --git a/queue-4.19/batman-adv-avoid-free-alloc-race-when-handling-ogm2-buffer.patch b/queue-4.19/batman-adv-avoid-free-alloc-race-when-handling-ogm2-buffer.patch new file mode 100644 index 00000000000..267f53deb90 --- /dev/null +++ b/queue-4.19/batman-adv-avoid-free-alloc-race-when-handling-ogm2-buffer.patch @@ -0,0 +1,151 @@ +From a8d23cbbf6c9f515ed678204ad2962be7c336344 Mon Sep 17 00:00:00 2001 +From: Sven Eckelmann +Date: Thu, 3 Oct 2019 17:02:01 +0200 +Subject: batman-adv: Avoid free/alloc race when handling OGM2 buffer + +From: Sven Eckelmann + +commit a8d23cbbf6c9f515ed678204ad2962be7c336344 upstream. + +A B.A.T.M.A.N. V virtual interface has an OGM2 packet buffer which is +initialized using data from the netdevice notifier and other rtnetlink +related hooks. It is sent regularly via various slave interfaces of the +batadv virtual interface and in this process also modified (realloced) to +integrate additional state information via TVLV containers. + +It must be avoided that the worker item is executed without a common lock +with the netdevice notifier/rtnetlink helpers. Otherwise it can either +happen that half modified data is sent out or the functions modifying the +OGM2 buffer try to access already freed memory regions. + +Fixes: 0da0035942d4 ("batman-adv: OGMv2 - add basic infrastructure") +Signed-off-by: Sven Eckelmann +Signed-off-by: Simon Wunderlich +Signed-off-by: Greg Kroah-Hartman + +--- + net/batman-adv/bat_v_ogm.c | 42 ++++++++++++++++++++++++++++++++++-------- + net/batman-adv/types.h | 4 ++++ + 2 files changed, 38 insertions(+), 8 deletions(-) + +--- a/net/batman-adv/bat_v_ogm.c ++++ b/net/batman-adv/bat_v_ogm.c +@@ -29,6 +29,8 @@ + #include + #include + #include ++#include ++#include + #include + #include + #include +@@ -128,14 +130,12 @@ static void batadv_v_ogm_send_to_if(stru + } + + /** +- * batadv_v_ogm_send() - periodic worker broadcasting the own OGM +- * @work: work queue item ++ * batadv_v_ogm_send_softif() - periodic worker broadcasting the own OGM ++ * @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_priv_bat_v *bat_v; +- struct batadv_priv *bat_priv; + struct batadv_ogm2_packet *ogm_packet; + struct sk_buff *skb, *skb_tmp; + unsigned char *ogm_buff; +@@ -143,8 +143,7 @@ static void batadv_v_ogm_send(struct wor + u16 tvlv_len = 0; + int ret; + +- bat_v = container_of(work, struct batadv_priv_bat_v, ogm_wq.work); +- bat_priv = container_of(bat_v, struct batadv_priv, bat_v); ++ lockdep_assert_held(&bat_priv->bat_v.ogm_buff_mutex); + + if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_DEACTIVATING) + goto out; +@@ -236,6 +235,23 @@ out: + } + + /** ++ * 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_iface_enable() - prepare an interface for B.A.T.M.A.N. V + * @hard_iface: the interface to prepare + * +@@ -261,11 +277,15 @@ void batadv_v_ogm_primary_iface_set(stru + struct batadv_priv *bat_priv = netdev_priv(primary_iface->soft_iface); + struct batadv_ogm2_packet *ogm_packet; + ++ mutex_lock(&bat_priv->bat_v.ogm_buff_mutex); + if (!bat_priv->bat_v.ogm_buff) +- return; ++ goto unlock; + + ogm_packet = (struct batadv_ogm2_packet *)bat_priv->bat_v.ogm_buff; + ether_addr_copy(ogm_packet->orig, primary_iface->net_dev->dev_addr); ++ ++unlock: ++ mutex_unlock(&bat_priv->bat_v.ogm_buff_mutex); + } + + /** +@@ -887,6 +907,8 @@ int batadv_v_ogm_init(struct batadv_priv + atomic_set(&bat_priv->bat_v.ogm_seqno, random_seqno); + INIT_DELAYED_WORK(&bat_priv->bat_v.ogm_wq, batadv_v_ogm_send); + ++ mutex_init(&bat_priv->bat_v.ogm_buff_mutex); ++ + return 0; + } + +@@ -898,7 +920,11 @@ void batadv_v_ogm_free(struct batadv_pri + { + 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); + bat_priv->bat_v.ogm_buff = NULL; + bat_priv->bat_v.ogm_buff_len = 0; ++ ++ mutex_unlock(&bat_priv->bat_v.ogm_buff_mutex); + } +--- a/net/batman-adv/types.h ++++ b/net/batman-adv/types.h +@@ -28,6 +28,7 @@ + #include + #include + #include ++#include + #include + #include + #include /* for linux/wait.h */ +@@ -1493,6 +1494,9 @@ struct batadv_priv_bat_v { + /** @ogm_seqno: OGM sequence number - used to identify each OGM */ + 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 */ + struct delayed_work ogm_wq; + }; diff --git a/queue-4.19/series b/queue-4.19/series index 1ee8c47f59e..452ec76cd43 100644 --- a/queue-4.19/series +++ b/queue-4.19/series @@ -86,3 +86,4 @@ ipv6-restrict-ipv6_addrform-operation.patch net-smc-check-for-valid-ib_client_data.patch net-smc-cancel-event-worker-during-device-removal.patch efi-add-a-sanity-check-to-efivar_store_raw.patch +batman-adv-avoid-free-alloc-race-when-handling-ogm2-buffer.patch