aboutsummaryrefslogtreecommitdiffstats
path: root/net/atm
diff options
context:
space:
mode:
authorKrzysztof Mazur <krzysiek@podlesie.net>2012-11-06 17:17:00 -0500
committerDavid Woodhouse <David.Woodhouse@intel.com>2012-11-27 19:37:05 -0500
commit3ac108006fd7f20cb8fc8ea2287f1497bcda00a1 (patch)
tree4931009972256abde839087b795c7b9b4926ae36 /net/atm
parente41faed9cde1acce657f75a0b19a1787e9850d3f (diff)
pppoatm: take ATM socket lock in pppoatm_send()
The pppoatm_send() does not take any lock that will prevent concurrent vcc_sendmsg(). This causes two problems: - there is no locking between checking the send queue size with atm_may_send() and incrementing sk_wmem_alloc, and the real queue size can be a little higher than sk_sndbuf - the vcc->sendmsg() can be called concurrently. I'm not sure if it's allowed. Some drivers (eni, nicstar, ...) seem to assume it will never happen. Now pppoatm_send() takes ATM socket lock, the same that is used in vcc_sendmsg() and other ATM socket functions. The pppoatm_send() is called with BH disabled, so bh_lock_sock() is used instead of lock_sock(). Signed-off-by: Krzysztof Mazur <krzysiek@podlesie.net> Cc: Chas Williams - CONTRACTOR <chas@cmf.nrl.navy.mil> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Diffstat (limited to 'net/atm')
-rw-r--r--net/atm/pppoatm.c19
1 files changed, 17 insertions, 2 deletions
diff --git a/net/atm/pppoatm.c b/net/atm/pppoatm.c
index b23c6723e87c..c4a57bca77bf 100644
--- a/net/atm/pppoatm.c
+++ b/net/atm/pppoatm.c
@@ -272,10 +272,19 @@ static inline int pppoatm_may_send(struct pppoatm_vcc *pvcc, int size)
272static int pppoatm_send(struct ppp_channel *chan, struct sk_buff *skb) 272static int pppoatm_send(struct ppp_channel *chan, struct sk_buff *skb)
273{ 273{
274 struct pppoatm_vcc *pvcc = chan_to_pvcc(chan); 274 struct pppoatm_vcc *pvcc = chan_to_pvcc(chan);
275 struct atm_vcc *vcc;
276 int ret;
277
275 ATM_SKB(skb)->vcc = pvcc->atmvcc; 278 ATM_SKB(skb)->vcc = pvcc->atmvcc;
276 pr_debug("(skb=0x%p, vcc=0x%p)\n", skb, pvcc->atmvcc); 279 pr_debug("(skb=0x%p, vcc=0x%p)\n", skb, pvcc->atmvcc);
277 if (skb->data[0] == '\0' && (pvcc->flags & SC_COMP_PROT)) 280 if (skb->data[0] == '\0' && (pvcc->flags & SC_COMP_PROT))
278 (void) skb_pull(skb, 1); 281 (void) skb_pull(skb, 1);
282
283 vcc = ATM_SKB(skb)->vcc;
284 bh_lock_sock(sk_atm(vcc));
285 if (sock_owned_by_user(sk_atm(vcc)))
286 goto nospace;
287
279 switch (pvcc->encaps) { /* LLC encapsulation needed */ 288 switch (pvcc->encaps) { /* LLC encapsulation needed */
280 case e_llc: 289 case e_llc:
281 if (skb_headroom(skb) < LLC_LEN) { 290 if (skb_headroom(skb) < LLC_LEN) {
@@ -288,8 +297,10 @@ static int pppoatm_send(struct ppp_channel *chan, struct sk_buff *skb)
288 } 297 }
289 consume_skb(skb); 298 consume_skb(skb);
290 skb = n; 299 skb = n;
291 if (skb == NULL) 300 if (skb == NULL) {
301 bh_unlock_sock(sk_atm(vcc));
292 return DROP_PACKET; 302 return DROP_PACKET;
303 }
293 } else if (!pppoatm_may_send(pvcc, skb->truesize)) 304 } else if (!pppoatm_may_send(pvcc, skb->truesize))
294 goto nospace; 305 goto nospace;
295 memcpy(skb_push(skb, LLC_LEN), pppllc, LLC_LEN); 306 memcpy(skb_push(skb, LLC_LEN), pppllc, LLC_LEN);
@@ -299,6 +310,7 @@ static int pppoatm_send(struct ppp_channel *chan, struct sk_buff *skb)
299 goto nospace; 310 goto nospace;
300 break; 311 break;
301 case e_autodetect: 312 case e_autodetect:
313 bh_unlock_sock(sk_atm(vcc));
302 pr_debug("Trying to send without setting encaps!\n"); 314 pr_debug("Trying to send without setting encaps!\n");
303 kfree_skb(skb); 315 kfree_skb(skb);
304 return 1; 316 return 1;
@@ -308,9 +320,12 @@ static int pppoatm_send(struct ppp_channel *chan, struct sk_buff *skb)
308 ATM_SKB(skb)->atm_options = ATM_SKB(skb)->vcc->atm_options; 320 ATM_SKB(skb)->atm_options = ATM_SKB(skb)->vcc->atm_options;
309 pr_debug("atm_skb(%p)->vcc(%p)->dev(%p)\n", 321 pr_debug("atm_skb(%p)->vcc(%p)->dev(%p)\n",
310 skb, ATM_SKB(skb)->vcc, ATM_SKB(skb)->vcc->dev); 322 skb, ATM_SKB(skb)->vcc, ATM_SKB(skb)->vcc->dev);
311 return ATM_SKB(skb)->vcc->send(ATM_SKB(skb)->vcc, skb) 323 ret = ATM_SKB(skb)->vcc->send(ATM_SKB(skb)->vcc, skb)
312 ? DROP_PACKET : 1; 324 ? DROP_PACKET : 1;
325 bh_unlock_sock(sk_atm(vcc));
326 return ret;
313nospace: 327nospace:
328 bh_unlock_sock(sk_atm(vcc));
314 /* 329 /*
315 * We don't have space to send this SKB now, but we might have 330 * We don't have space to send this SKB now, but we might have
316 * already applied SC_COMP_PROT compression, so may need to undo 331 * already applied SC_COMP_PROT compression, so may need to undo