aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/mesh_plink.c
diff options
context:
space:
mode:
authorThomas Pedersen <thomas@cozybit.com>2012-08-03 15:21:35 -0400
committerJohannes Berg <johannes.berg@intel.com>2012-08-03 15:34:29 -0400
commitf609a43dca2964a8a604ef554be92fa11c3b4c41 (patch)
treee046bde3df86b0278f23f78f6a7aa1cbb0f0bb47 /net/mac80211/mesh_plink.c
parente7570dfb635b0c89570852002c9f85dd1cf82ba1 (diff)
mac80211: skb leak in mesh_plink_frame_tx()
Although adding an IE is almost guaranteed to succeed since we already accounted for its length while allocating the skb, we should still free the skb in case of failure. Signed-off-by: Thomas Pedersen <thomas@cozybit.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211/mesh_plink.c')
-rw-r--r--net/mac80211/mesh_plink.c17
1 files changed, 11 insertions, 6 deletions
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index bad5126c8483..5fd1250f7866 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -224,6 +224,7 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
224 u8 *pos, ie_len = 4; 224 u8 *pos, ie_len = 4;
225 int hdr_len = offsetof(struct ieee80211_mgmt, u.action.u.self_prot) + 225 int hdr_len = offsetof(struct ieee80211_mgmt, u.action.u.self_prot) +
226 sizeof(mgmt->u.action.u.self_prot); 226 sizeof(mgmt->u.action.u.self_prot);
227 int err = -ENOMEM;
227 228
228 skb = dev_alloc_skb(local->tx_headroom + 229 skb = dev_alloc_skb(local->tx_headroom +
229 hdr_len + 230 hdr_len +
@@ -267,11 +268,11 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
267 mesh_add_rsn_ie(skb, sdata) || 268 mesh_add_rsn_ie(skb, sdata) ||
268 mesh_add_meshid_ie(skb, sdata) || 269 mesh_add_meshid_ie(skb, sdata) ||
269 mesh_add_meshconf_ie(skb, sdata)) 270 mesh_add_meshconf_ie(skb, sdata))
270 return -1; 271 goto free;
271 } else { /* WLAN_SP_MESH_PEERING_CLOSE */ 272 } else { /* WLAN_SP_MESH_PEERING_CLOSE */
272 info->flags |= IEEE80211_TX_CTL_NO_ACK; 273 info->flags |= IEEE80211_TX_CTL_NO_ACK;
273 if (mesh_add_meshid_ie(skb, sdata)) 274 if (mesh_add_meshid_ie(skb, sdata))
274 return -1; 275 goto free;
275 } 276 }
276 277
277 /* Add Mesh Peering Management element */ 278 /* Add Mesh Peering Management element */
@@ -290,11 +291,12 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
290 ie_len += 2; /* reason code */ 291 ie_len += 2; /* reason code */
291 break; 292 break;
292 default: 293 default:
293 return -EINVAL; 294 err = -EINVAL;
295 goto free;
294 } 296 }
295 297
296 if (WARN_ON(skb_tailroom(skb) < 2 + ie_len)) 298 if (WARN_ON(skb_tailroom(skb) < 2 + ie_len))
297 return -ENOMEM; 299 goto free;
298 300
299 pos = skb_put(skb, 2 + ie_len); 301 pos = skb_put(skb, 2 + ie_len);
300 *pos++ = WLAN_EID_PEER_MGMT; 302 *pos++ = WLAN_EID_PEER_MGMT;
@@ -315,14 +317,17 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
315 if (action != WLAN_SP_MESH_PEERING_CLOSE) { 317 if (action != WLAN_SP_MESH_PEERING_CLOSE) {
316 if (mesh_add_ht_cap_ie(skb, sdata) || 318 if (mesh_add_ht_cap_ie(skb, sdata) ||
317 mesh_add_ht_oper_ie(skb, sdata)) 319 mesh_add_ht_oper_ie(skb, sdata))
318 return -1; 320 goto free;
319 } 321 }
320 322
321 if (mesh_add_vendor_ies(skb, sdata)) 323 if (mesh_add_vendor_ies(skb, sdata))
322 return -1; 324 goto free;
323 325
324 ieee80211_tx_skb(sdata, skb); 326 ieee80211_tx_skb(sdata, skb);
325 return 0; 327 return 0;
328free:
329 kfree_skb(skb);
330 return err;
326} 331}
327 332
328/** 333/**