Merge branch 'master' into bmx6_testing
[feed/routing.git] / batman-adv / patches / 0001-batman-adv-fix-potential-kernel-paging-errors-for-un.patch
1 From c98c3e521913b8dd5fee4d3b90dc9ed7a47e5bee Mon Sep 17 00:00:00 2001
2 From: =?UTF-8?q?Linus=20L=C3=BCssing?= <linus.luessing@web.de>
3 Date: Tue, 6 Aug 2013 20:21:15 +0200
4 Subject: [PATCH] batman-adv: fix potential kernel paging errors for unicast
5 transmissions
6 MIME-Version: 1.0
7 Content-Type: text/plain; charset=UTF-8
8 Content-Transfer-Encoding: 8bit
9
10 There are several functions which might reallocate skb data. Currently
11 some places keep reusing their old ethhdr pointer regardless of whether
12 they became invalid after such a reallocation or not. This potentially
13 leads to kernel paging errors.
14
15 This patch fixes these by refetching the ethdr pointer after the
16 potential reallocations.
17
18 Signed-off-by: Linus Lüssing <linus.luessing@web.de>
19 Signed-off-by: Marek Lindner <lindner_marek@yahoo.de>
20 ---
21 bridge_loop_avoidance.c | 2 ++
22 gateway_client.c | 13 ++++++++++++-
23 gateway_client.h | 3 +--
24 soft-interface.c | 9 ++++++++-
25 unicast.c | 13 ++++++++++---
26 5 files changed, 33 insertions(+), 7 deletions(-)
27
28 diff --git a/bridge_loop_avoidance.c b/bridge_loop_avoidance.c
29 index e14531f..264de88 100644
30 --- a/bridge_loop_avoidance.c
31 +++ b/bridge_loop_avoidance.c
32 @@ -1529,6 +1529,8 @@ out:
33 * in these cases, the skb is further handled by this function and
34 * returns 1, otherwise it returns 0 and the caller shall further
35 * process the skb.
36 + *
37 + * This call might reallocate skb data.
38 */
39 int batadv_bla_tx(struct batadv_priv *bat_priv, struct sk_buff *skb,
40 unsigned short vid)
41 diff --git a/gateway_client.c b/gateway_client.c
42 index f105219..7614af3 100644
43 --- a/gateway_client.c
44 +++ b/gateway_client.c
45 @@ -508,6 +508,7 @@ out:
46 return 0;
47 }
48
49 +/* this call might reallocate skb data */
50 static bool batadv_is_type_dhcprequest(struct sk_buff *skb, int header_len)
51 {
52 int ret = false;
53 @@ -568,6 +569,7 @@ out:
54 return ret;
55 }
56
57 +/* this call might reallocate skb data */
58 bool batadv_gw_is_dhcp_target(struct sk_buff *skb, unsigned int *header_len)
59 {
60 struct ethhdr *ethhdr;
61 @@ -619,6 +621,12 @@ bool batadv_gw_is_dhcp_target(struct sk_buff *skb, unsigned int *header_len)
62
63 if (!pskb_may_pull(skb, *header_len + sizeof(*udphdr)))
64 return false;
65 +
66 + /* skb->data might have been reallocated by pskb_may_pull() */
67 + ethhdr = (struct ethhdr *)skb->data;
68 + if (ntohs(ethhdr->h_proto) == ETH_P_8021Q)
69 + ethhdr = (struct ethhdr *)(skb->data + VLAN_HLEN);
70 +
71 udphdr = (struct udphdr *)(skb->data + *header_len);
72 *header_len += sizeof(*udphdr);
73
74 @@ -634,12 +642,14 @@ bool batadv_gw_is_dhcp_target(struct sk_buff *skb, unsigned int *header_len)
75 return true;
76 }
77
78 +/* this call might reallocate skb data */
79 bool batadv_gw_out_of_range(struct batadv_priv *bat_priv,
80 - struct sk_buff *skb, struct ethhdr *ethhdr)
81 + struct sk_buff *skb)
82 {
83 struct batadv_neigh_node *neigh_curr = NULL, *neigh_old = NULL;
84 struct batadv_orig_node *orig_dst_node = NULL;
85 struct batadv_gw_node *curr_gw = NULL;
86 + struct ethhdr *ethhdr;
87 bool ret, out_of_range = false;
88 unsigned int header_len = 0;
89 uint8_t curr_tq_avg;
90 @@ -648,6 +658,7 @@ bool batadv_gw_out_of_range(struct batadv_priv *bat_priv,
91 if (!ret)
92 goto out;
93
94 + ethhdr = (struct ethhdr *)skb->data;
95 orig_dst_node = batadv_transtable_search(bat_priv, ethhdr->h_source,
96 ethhdr->h_dest);
97 if (!orig_dst_node)
98 diff --git a/gateway_client.h b/gateway_client.h
99 index 039902d..1037d75 100644
100 --- a/gateway_client.h
101 +++ b/gateway_client.h
102 @@ -34,7 +34,6 @@ void batadv_gw_node_delete(struct batadv_priv *bat_priv,
103 void batadv_gw_node_purge(struct batadv_priv *bat_priv);
104 int batadv_gw_client_seq_print_text(struct seq_file *seq, void *offset);
105 bool batadv_gw_is_dhcp_target(struct sk_buff *skb, unsigned int *header_len);
106 -bool batadv_gw_out_of_range(struct batadv_priv *bat_priv,
107 - struct sk_buff *skb, struct ethhdr *ethhdr);
108 +bool batadv_gw_out_of_range(struct batadv_priv *bat_priv, struct sk_buff *skb);
109
110 #endif /* _NET_BATMAN_ADV_GATEWAY_CLIENT_H_ */
111 diff --git a/soft-interface.c b/soft-interface.c
112 index 700d0b4..0f04e1c 100644
113 --- a/soft-interface.c
114 +++ b/soft-interface.c
115 @@ -180,6 +180,9 @@ static int batadv_interface_tx(struct sk_buff *skb,
116 if (batadv_bla_tx(bat_priv, skb, vid))
117 goto dropped;
118
119 + /* skb->data might have been reallocated by batadv_bla_tx() */
120 + ethhdr = (struct ethhdr *)skb->data;
121 +
122 /* Register the client MAC in the transtable */
123 if (!is_multicast_ether_addr(ethhdr->h_source))
124 batadv_tt_local_add(soft_iface, ethhdr->h_source, skb->skb_iif);
125 @@ -220,6 +223,10 @@ static int batadv_interface_tx(struct sk_buff *skb,
126 default:
127 break;
128 }
129 +
130 + /* reminder: ethhdr might have become unusable from here on
131 + * (batadv_gw_is_dhcp_target() might have reallocated skb data)
132 + */
133 }
134
135 /* ethernet packet should be broadcasted */
136 @@ -266,7 +273,7 @@ static int batadv_interface_tx(struct sk_buff *skb,
137 /* unicast packet */
138 } else {
139 if (atomic_read(&bat_priv->gw_mode) != BATADV_GW_MODE_OFF) {
140 - ret = batadv_gw_out_of_range(bat_priv, skb, ethhdr);
141 + ret = batadv_gw_out_of_range(bat_priv, skb);
142 if (ret)
143 goto dropped;
144 }
145 diff --git a/unicast.c b/unicast.c
146 index dc8b5d4..688a041 100644
147 --- a/unicast.c
148 +++ b/unicast.c
149 @@ -326,7 +326,9 @@ static bool batadv_unicast_push_and_fill_skb(struct sk_buff *skb, int hdr_size,
150 * @skb: the skb containing the payload to encapsulate
151 * @orig_node: the destination node
152 *
153 - * Returns false if the payload could not be encapsulated or true otherwise
154 + * Returns false if the payload could not be encapsulated or true otherwise.
155 + *
156 + * This call might reallocate skb data.
157 */
158 static bool batadv_unicast_prepare_skb(struct sk_buff *skb,
159 struct batadv_orig_node *orig_node)
160 @@ -343,7 +345,9 @@ static bool batadv_unicast_prepare_skb(struct sk_buff *skb,
161 * @orig_node: the destination node
162 * @packet_subtype: the batman 4addr packet subtype to use
163 *
164 - * Returns false if the payload could not be encapsulated or true otherwise
165 + * Returns false if the payload could not be encapsulated or true otherwise.
166 + *
167 + * This call might reallocate skb data.
168 */
169 bool batadv_unicast_4addr_prepare_skb(struct batadv_priv *bat_priv,
170 struct sk_buff *skb,
171 @@ -401,7 +405,7 @@ int batadv_unicast_generic_send_skb(struct batadv_priv *bat_priv,
172 struct batadv_neigh_node *neigh_node;
173 int data_len = skb->len;
174 int ret = NET_RX_DROP;
175 - unsigned int dev_mtu;
176 + unsigned int dev_mtu, header_len;
177
178 /* get routing information */
179 if (is_multicast_ether_addr(ethhdr->h_dest)) {
180 @@ -429,10 +433,12 @@ find_router:
181 switch (packet_type) {
182 case BATADV_UNICAST:
183 batadv_unicast_prepare_skb(skb, orig_node);
184 + header_len = sizeof(struct batadv_unicast_packet);
185 break;
186 case BATADV_UNICAST_4ADDR:
187 batadv_unicast_4addr_prepare_skb(bat_priv, skb, orig_node,
188 packet_subtype);
189 + header_len = sizeof(struct batadv_unicast_4addr_packet);
190 break;
191 default:
192 /* this function supports UNICAST and UNICAST_4ADDR only. It
193 @@ -441,6 +447,7 @@ find_router:
194 goto out;
195 }
196
197 + ethhdr = (struct ethhdr *)(skb->data + header_len);
198 unicast_packet = (struct batadv_unicast_packet *)skb->data;
199
200 /* inform the destination node that we are still missing a correct route
201 --
202 1.7.10.4
203