diff options
author | Sjur Braendeland <sjur.brandeland@stericsson.com> | 2010-05-20 22:16:09 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-05-24 02:57:42 -0400 |
commit | 638e628a600a5c542d46dfb06771cf9c229ef5f3 (patch) | |
tree | 777d4d2b9aee8a1d4b0ce522bf3957023a9bfb7e | |
parent | 7aecf4944f2c05aafb73b4820e469c74b4ec8517 (diff) |
caif: Bugfix - handle mem-allocation failures
Discovered bugs when injecting slab allocation failures.
Add checks on all memory allocation.
Signed-off-by: Sjur Braendeland <sjur.brandeland@stericsson.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/caif/cfpkt_skbuff.c | 25 | ||||
-rw-r--r-- | net/caif/cfserl.c | 3 | ||||
-rw-r--r-- | net/caif/cfsrvl.c | 6 |
3 files changed, 25 insertions, 9 deletions
diff --git a/net/caif/cfpkt_skbuff.c b/net/caif/cfpkt_skbuff.c index 83fff2ff6658..a6fdf899741a 100644 --- a/net/caif/cfpkt_skbuff.c +++ b/net/caif/cfpkt_skbuff.c | |||
@@ -238,6 +238,7 @@ int cfpkt_add_head(struct cfpkt *pkt, const void *data2, u16 len) | |||
238 | struct sk_buff *lastskb; | 238 | struct sk_buff *lastskb; |
239 | u8 *to; | 239 | u8 *to; |
240 | const u8 *data = data2; | 240 | const u8 *data = data2; |
241 | int ret; | ||
241 | if (unlikely(is_erronous(pkt))) | 242 | if (unlikely(is_erronous(pkt))) |
242 | return -EPROTO; | 243 | return -EPROTO; |
243 | if (unlikely(skb_headroom(skb) < len)) { | 244 | if (unlikely(skb_headroom(skb) < len)) { |
@@ -246,9 +247,10 @@ int cfpkt_add_head(struct cfpkt *pkt, const void *data2, u16 len) | |||
246 | } | 247 | } |
247 | 248 | ||
248 | /* Make sure data is writable */ | 249 | /* Make sure data is writable */ |
249 | if (unlikely(skb_cow_data(skb, 0, &lastskb) < 0)) { | 250 | ret = skb_cow_data(skb, 0, &lastskb); |
251 | if (unlikely(ret < 0)) { | ||
250 | PKT_ERROR(pkt, "cfpkt_add_head: cow failed\n"); | 252 | PKT_ERROR(pkt, "cfpkt_add_head: cow failed\n"); |
251 | return -EPROTO; | 253 | return ret; |
252 | } | 254 | } |
253 | 255 | ||
254 | to = skb_push(skb, len); | 256 | to = skb_push(skb, len); |
@@ -316,6 +318,8 @@ EXPORT_SYMBOL(cfpkt_setlen); | |||
316 | struct cfpkt *cfpkt_create_uplink(const unsigned char *data, unsigned int len) | 318 | struct cfpkt *cfpkt_create_uplink(const unsigned char *data, unsigned int len) |
317 | { | 319 | { |
318 | struct cfpkt *pkt = cfpkt_create_pfx(len + PKT_POSTFIX, PKT_PREFIX); | 320 | struct cfpkt *pkt = cfpkt_create_pfx(len + PKT_POSTFIX, PKT_PREFIX); |
321 | if (!pkt) | ||
322 | return NULL; | ||
319 | if (unlikely(data != NULL)) | 323 | if (unlikely(data != NULL)) |
320 | cfpkt_add_body(pkt, data, len); | 324 | cfpkt_add_body(pkt, data, len); |
321 | return pkt; | 325 | return pkt; |
@@ -344,12 +348,13 @@ struct cfpkt *cfpkt_append(struct cfpkt *dstpkt, | |||
344 | 348 | ||
345 | if (dst->tail + neededtailspace > dst->end) { | 349 | if (dst->tail + neededtailspace > dst->end) { |
346 | /* Create a dumplicate of 'dst' with more tail space */ | 350 | /* Create a dumplicate of 'dst' with more tail space */ |
351 | struct cfpkt *tmppkt; | ||
347 | dstlen = skb_headlen(dst); | 352 | dstlen = skb_headlen(dst); |
348 | createlen = dstlen + neededtailspace; | 353 | createlen = dstlen + neededtailspace; |
349 | tmp = pkt_to_skb( | 354 | tmppkt = cfpkt_create(createlen + PKT_PREFIX + PKT_POSTFIX); |
350 | cfpkt_create(createlen + PKT_PREFIX + PKT_POSTFIX)); | 355 | if (tmppkt == NULL) |
351 | if (!tmp) | ||
352 | return NULL; | 356 | return NULL; |
357 | tmp = pkt_to_skb(tmppkt); | ||
353 | skb_set_tail_pointer(tmp, dstlen); | 358 | skb_set_tail_pointer(tmp, dstlen); |
354 | tmp->len = dstlen; | 359 | tmp->len = dstlen; |
355 | memcpy(tmp->data, dst->data, dstlen); | 360 | memcpy(tmp->data, dst->data, dstlen); |
@@ -368,6 +373,7 @@ struct cfpkt *cfpkt_split(struct cfpkt *pkt, u16 pos) | |||
368 | { | 373 | { |
369 | struct sk_buff *skb2; | 374 | struct sk_buff *skb2; |
370 | struct sk_buff *skb = pkt_to_skb(pkt); | 375 | struct sk_buff *skb = pkt_to_skb(pkt); |
376 | struct cfpkt *tmppkt; | ||
371 | u8 *split = skb->data + pos; | 377 | u8 *split = skb->data + pos; |
372 | u16 len2nd = skb_tail_pointer(skb) - split; | 378 | u16 len2nd = skb_tail_pointer(skb) - split; |
373 | 379 | ||
@@ -381,9 +387,12 @@ struct cfpkt *cfpkt_split(struct cfpkt *pkt, u16 pos) | |||
381 | } | 387 | } |
382 | 388 | ||
383 | /* Create a new packet for the second part of the data */ | 389 | /* Create a new packet for the second part of the data */ |
384 | skb2 = pkt_to_skb( | 390 | tmppkt = cfpkt_create_pfx(len2nd + PKT_PREFIX + PKT_POSTFIX, |
385 | cfpkt_create_pfx(len2nd + PKT_PREFIX + PKT_POSTFIX, | 391 | PKT_PREFIX); |
386 | PKT_PREFIX)); | 392 | if (tmppkt == NULL) |
393 | return NULL; | ||
394 | skb2 = pkt_to_skb(tmppkt); | ||
395 | |||
387 | 396 | ||
388 | if (skb2 == NULL) | 397 | if (skb2 == NULL) |
389 | return NULL; | 398 | return NULL; |
diff --git a/net/caif/cfserl.c b/net/caif/cfserl.c index 06029ea2da2f..cb4325a3dc83 100644 --- a/net/caif/cfserl.c +++ b/net/caif/cfserl.c | |||
@@ -67,6 +67,8 @@ static int cfserl_receive(struct cflayer *l, struct cfpkt *newpkt) | |||
67 | layr->incomplete_frm = | 67 | layr->incomplete_frm = |
68 | cfpkt_append(layr->incomplete_frm, newpkt, expectlen); | 68 | cfpkt_append(layr->incomplete_frm, newpkt, expectlen); |
69 | pkt = layr->incomplete_frm; | 69 | pkt = layr->incomplete_frm; |
70 | if (pkt == NULL) | ||
71 | return -ENOMEM; | ||
70 | } else { | 72 | } else { |
71 | pkt = newpkt; | 73 | pkt = newpkt; |
72 | } | 74 | } |
@@ -154,7 +156,6 @@ static int cfserl_receive(struct cflayer *l, struct cfpkt *newpkt) | |||
154 | if (layr->usestx) { | 156 | if (layr->usestx) { |
155 | if (tail_pkt != NULL) | 157 | if (tail_pkt != NULL) |
156 | pkt = cfpkt_append(pkt, tail_pkt, 0); | 158 | pkt = cfpkt_append(pkt, tail_pkt, 0); |
157 | |||
158 | /* Start search for next STX if frame failed */ | 159 | /* Start search for next STX if frame failed */ |
159 | continue; | 160 | continue; |
160 | } else { | 161 | } else { |
diff --git a/net/caif/cfsrvl.c b/net/caif/cfsrvl.c index aff31f34528f..6e5b7079a684 100644 --- a/net/caif/cfsrvl.c +++ b/net/caif/cfsrvl.c | |||
@@ -123,6 +123,12 @@ static int cfservl_modemcmd(struct cflayer *layr, enum caif_modemcmd ctrl) | |||
123 | struct caif_payload_info *info; | 123 | struct caif_payload_info *info; |
124 | u8 flow_off = SRVL_FLOW_OFF; | 124 | u8 flow_off = SRVL_FLOW_OFF; |
125 | pkt = cfpkt_create(SRVL_CTRL_PKT_SIZE); | 125 | pkt = cfpkt_create(SRVL_CTRL_PKT_SIZE); |
126 | if (!pkt) { | ||
127 | pr_warning("CAIF: %s(): Out of memory\n", | ||
128 | __func__); | ||
129 | return -ENOMEM; | ||
130 | } | ||
131 | |||
126 | if (cfpkt_add_head(pkt, &flow_off, 1) < 0) { | 132 | if (cfpkt_add_head(pkt, &flow_off, 1) < 0) { |
127 | pr_err("CAIF: %s(): Packet is erroneous!\n", | 133 | pr_err("CAIF: %s(): Packet is erroneous!\n", |
128 | __func__); | 134 | __func__); |