Merge pull request #624 from ecsv/batadv-for-18.06
[feed/routing.git] / batman-adv / patches / 0036-batman-adv-Avoid-free-alloc-race-when-handling-OGM2-.patch
1 From: Sven Eckelmann <sven@narfation.org>
2 Date: Thu, 3 Oct 2019 17:02:01 +0200
3 Subject: batman-adv: Avoid free/alloc race when handling OGM2 buffer
4
5 A B.A.T.M.A.N. V virtual interface has an OGM2 packet buffer which is
6 initialized using data from the RTNL lock protected netdevice notifier and
7 other rtnetlink related hooks. It is sent regularly via various slave
8 interfaces of the batadv virtual interface and in this process also
9 modified (realloced) to integrate additional state information via TVLV
10 containers.
11
12 It must be avoided that the worker item is executed without a common lock
13 with the netdevice notifier/rtnetlink helpers. Otherwise it can either
14 happen that half modified data is sent out or the functions modifying the
15 OGM2 buffer try to access already freed memory regions.
16
17 Fixes: 632835348e65 ("batman-adv: OGMv2 - add basic infrastructure")
18 Signed-off-by: Sven Eckelmann <sven@narfation.org>
19
20 Origin: upstream, https://git.open-mesh.org/batman-adv.git/commit/14ee24576213ff02272b7f8d975c7c61d5448aa2
21
22 diff --git a/net/batman-adv/bat_v_ogm.c b/net/batman-adv/bat_v_ogm.c
23 index d241ccc0ca0278173853512c8aa4bfb8b041f996..a9f949501ff3c354d38e3ad333901310391f27d8 100644
24 --- a/net/batman-adv/bat_v_ogm.c
25 +++ b/net/batman-adv/bat_v_ogm.c
26 @@ -33,6 +33,7 @@
27 #include <linux/random.h>
28 #include <linux/rculist.h>
29 #include <linux/rcupdate.h>
30 +#include <linux/rtnetlink.h>
31 #include <linux/skbuff.h>
32 #include <linux/slab.h>
33 #include <linux/stddef.h>
34 @@ -128,14 +129,12 @@ static void batadv_v_ogm_send_to_if(struct sk_buff *skb,
35 }
36
37 /**
38 - * batadv_v_ogm_send() - periodic worker broadcasting the own OGM
39 - * @work: work queue item
40 + * batadv_v_ogm_send_softif() - periodic worker broadcasting the own OGM
41 + * @bat_priv: the bat priv with all the soft interface information
42 */
43 -static void batadv_v_ogm_send(struct work_struct *work)
44 +static void batadv_v_ogm_send_softif(struct batadv_priv *bat_priv)
45 {
46 struct batadv_hard_iface *hard_iface;
47 - struct batadv_priv_bat_v *bat_v;
48 - struct batadv_priv *bat_priv;
49 struct batadv_ogm2_packet *ogm_packet;
50 struct sk_buff *skb, *skb_tmp;
51 unsigned char *ogm_buff;
52 @@ -143,8 +142,7 @@ static void batadv_v_ogm_send(struct work_struct *work)
53 u16 tvlv_len = 0;
54 int ret;
55
56 - bat_v = container_of(work, struct batadv_priv_bat_v, ogm_wq.work);
57 - bat_priv = container_of(bat_v, struct batadv_priv, bat_v);
58 + ASSERT_RTNL();
59
60 if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_DEACTIVATING)
61 goto out;
62 @@ -235,6 +233,22 @@ static void batadv_v_ogm_send(struct work_struct *work)
63 return;
64 }
65
66 +/**
67 + * batadv_v_ogm_send() - periodic worker broadcasting the own OGM
68 + * @work: work queue item
69 + */
70 +static void batadv_v_ogm_send(struct work_struct *work)
71 +{
72 + struct batadv_priv_bat_v *bat_v;
73 + struct batadv_priv *bat_priv;
74 +
75 + rtnl_lock();
76 + bat_v = container_of(work, struct batadv_priv_bat_v, ogm_wq.work);
77 + bat_priv = container_of(bat_v, struct batadv_priv, bat_v);
78 + batadv_v_ogm_send_softif(bat_priv);
79 + rtnl_unlock();
80 +}
81 +
82 /**
83 * batadv_v_ogm_iface_enable() - prepare an interface for B.A.T.M.A.N. V
84 * @hard_iface: the interface to prepare
85 @@ -261,6 +275,8 @@ void batadv_v_ogm_primary_iface_set(struct batadv_hard_iface *primary_iface)
86 struct batadv_priv *bat_priv = netdev_priv(primary_iface->soft_iface);
87 struct batadv_ogm2_packet *ogm_packet;
88
89 + ASSERT_RTNL();
90 +
91 if (!bat_priv->bat_v.ogm_buff)
92 return;
93
94 @@ -869,6 +885,8 @@ int batadv_v_ogm_init(struct batadv_priv *bat_priv)
95 unsigned char *ogm_buff;
96 u32 random_seqno;
97
98 + ASSERT_RTNL();
99 +
100 bat_priv->bat_v.ogm_buff_len = BATADV_OGM2_HLEN;
101 ogm_buff = kzalloc(bat_priv->bat_v.ogm_buff_len, GFP_ATOMIC);
102 if (!ogm_buff)
103 diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
104 index 86f37db7dd01592aff95ada5ba5441667971e1bc..3392198ff146ba77d320104663e97ab21559d556 100644
105 --- a/net/batman-adv/types.h
106 +++ b/net/batman-adv/types.h
107 @@ -1479,10 +1479,10 @@ struct batadv_softif_vlan {
108 * struct batadv_priv_bat_v - B.A.T.M.A.N. V per soft-interface private data
109 */
110 struct batadv_priv_bat_v {
111 - /** @ogm_buff: buffer holding the OGM packet */
112 + /** @ogm_buff: buffer holding the OGM packet. rtnl protected */
113 unsigned char *ogm_buff;
114
115 - /** @ogm_buff_len: length of the OGM packet buffer */
116 + /** @ogm_buff_len: length of the OGM packet buffer. rtnl protected */
117 int ogm_buff_len;
118
119 /** @ogm_seqno: OGM sequence number - used to identify each OGM */