caif: Bugfix - handle mem-allocation failures
Sjur Braendeland [Fri, 21 May 2010 02:16:09 +0000 (02:16 +0000)]
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>

net/caif/cfpkt_skbuff.c
net/caif/cfserl.c
net/caif/cfsrvl.c

index 83fff2f..a6fdf89 100644 (file)
@@ -238,6 +238,7 @@ int cfpkt_add_head(struct cfpkt *pkt, const void *data2, u16 len)
        struct sk_buff *lastskb;
        u8 *to;
        const u8 *data = data2;
+       int ret;
        if (unlikely(is_erronous(pkt)))
                return -EPROTO;
        if (unlikely(skb_headroom(skb) < len)) {
@@ -246,9 +247,10 @@ int cfpkt_add_head(struct cfpkt *pkt, const void *data2, u16 len)
        }
 
        /* Make sure data is writable */
-       if (unlikely(skb_cow_data(skb, 0, &lastskb) < 0)) {
+       ret = skb_cow_data(skb, 0, &lastskb);
+       if (unlikely(ret < 0)) {
                PKT_ERROR(pkt, "cfpkt_add_head: cow failed\n");
-               return -EPROTO;
+               return ret;
        }
 
        to = skb_push(skb, len);
@@ -316,6 +318,8 @@ EXPORT_SYMBOL(cfpkt_setlen);
 struct cfpkt *cfpkt_create_uplink(const unsigned char *data, unsigned int len)
 {
        struct cfpkt *pkt = cfpkt_create_pfx(len + PKT_POSTFIX, PKT_PREFIX);
+       if (!pkt)
+               return NULL;
        if (unlikely(data != NULL))
                cfpkt_add_body(pkt, data, len);
        return pkt;
@@ -344,12 +348,13 @@ struct cfpkt *cfpkt_append(struct cfpkt *dstpkt,
 
        if (dst->tail + neededtailspace > dst->end) {
                /* Create a dumplicate of 'dst' with more tail space */
+               struct cfpkt *tmppkt;
                dstlen = skb_headlen(dst);
                createlen = dstlen + neededtailspace;
-               tmp = pkt_to_skb(
-                       cfpkt_create(createlen + PKT_PREFIX + PKT_POSTFIX));
-               if (!tmp)
+               tmppkt = cfpkt_create(createlen + PKT_PREFIX + PKT_POSTFIX);
+               if (tmppkt == NULL)
                        return NULL;
+               tmp = pkt_to_skb(tmppkt);
                skb_set_tail_pointer(tmp, dstlen);
                tmp->len = dstlen;
                memcpy(tmp->data, dst->data, dstlen);
@@ -368,6 +373,7 @@ struct cfpkt *cfpkt_split(struct cfpkt *pkt, u16 pos)
 {
        struct sk_buff *skb2;
        struct sk_buff *skb = pkt_to_skb(pkt);
+       struct cfpkt *tmppkt;
        u8 *split = skb->data + pos;
        u16 len2nd = skb_tail_pointer(skb) - split;
 
@@ -381,9 +387,12 @@ struct cfpkt *cfpkt_split(struct cfpkt *pkt, u16 pos)
        }
 
        /* Create a new packet for the second part of the data */
-       skb2 = pkt_to_skb(
-               cfpkt_create_pfx(len2nd + PKT_PREFIX + PKT_POSTFIX,
-                                PKT_PREFIX));
+       tmppkt = cfpkt_create_pfx(len2nd + PKT_PREFIX + PKT_POSTFIX,
+                                 PKT_PREFIX);
+       if (tmppkt == NULL)
+               return NULL;
+       skb2 = pkt_to_skb(tmppkt);
+
 
        if (skb2 == NULL)
                return NULL;
index 06029ea..cb4325a 100644 (file)
@@ -67,6 +67,8 @@ static int cfserl_receive(struct cflayer *l, struct cfpkt *newpkt)
                layr->incomplete_frm =
                    cfpkt_append(layr->incomplete_frm, newpkt, expectlen);
                pkt = layr->incomplete_frm;
+               if (pkt == NULL)
+                       return -ENOMEM;
        } else {
                pkt = newpkt;
        }
@@ -154,7 +156,6 @@ static int cfserl_receive(struct cflayer *l, struct cfpkt *newpkt)
                        if (layr->usestx) {
                                if (tail_pkt != NULL)
                                        pkt = cfpkt_append(pkt, tail_pkt, 0);
-
                                /* Start search for next STX if frame failed */
                                continue;
                        } else {
index aff31f3..6e5b707 100644 (file)
@@ -123,6 +123,12 @@ static int cfservl_modemcmd(struct cflayer *layr, enum caif_modemcmd ctrl)
                        struct caif_payload_info *info;
                        u8 flow_off = SRVL_FLOW_OFF;
                        pkt = cfpkt_create(SRVL_CTRL_PKT_SIZE);
+                       if (!pkt) {
+                               pr_warning("CAIF: %s(): Out of memory\n",
+                                       __func__);
+                               return -ENOMEM;
+                       }
+
                        if (cfpkt_add_head(pkt, &flow_off, 1) < 0) {
                                pr_err("CAIF: %s(): Packet is erroneous!\n",
                                        __func__);