isdn/capi: handle CAPI 2.0 message parser failures
[cascardo/linux.git] / drivers / isdn / gigaset / capi.c
index 47e2a91..ccec777 100644 (file)
@@ -647,7 +647,13 @@ int gigaset_isdn_icall(struct at_state_t *at_state)
                                        __func__);
                                break;
                        }
-                       capi_cmsg2message(&iif->hcmsg, __skb_put(skb, msgsize));
+                       if (capi_cmsg2message(&iif->hcmsg,
+                                             __skb_put(skb, msgsize))) {
+                               dev_err(cs->dev, "%s: message parser failure\n",
+                                       __func__);
+                               dev_kfree_skb_any(skb);
+                               break;
+                       }
                        dump_cmsg(DEBUG_CMD, __func__, &iif->hcmsg);
 
                        /* add to listeners on this B channel, update state */
@@ -693,7 +699,12 @@ static void send_disconnect_ind(struct bc_state *bcs,
                dev_err(cs->dev, "%s: out of memory\n", __func__);
                return;
        }
-       capi_cmsg2message(&iif->hcmsg, __skb_put(skb, CAPI_DISCONNECT_IND_LEN));
+       if (capi_cmsg2message(&iif->hcmsg,
+                             __skb_put(skb, CAPI_DISCONNECT_IND_LEN))) {
+               dev_err(cs->dev, "%s: message parser failure\n", __func__);
+               dev_kfree_skb_any(skb);
+               return;
+       }
        dump_cmsg(DEBUG_CMD, __func__, &iif->hcmsg);
        capi_ctr_handle_message(&iif->ctr, ap->id, skb);
 }
@@ -723,8 +734,12 @@ static void send_disconnect_b3_ind(struct bc_state *bcs,
                dev_err(cs->dev, "%s: out of memory\n", __func__);
                return;
        }
-       capi_cmsg2message(&iif->hcmsg,
-                         __skb_put(skb, CAPI_DISCONNECT_B3_IND_BASELEN));
+       if (capi_cmsg2message(&iif->hcmsg,
+                         __skb_put(skb, CAPI_DISCONNECT_B3_IND_BASELEN))) {
+               dev_err(cs->dev, "%s: message parser failure\n", __func__);
+               dev_kfree_skb_any(skb);
+               return;
+       }
        dump_cmsg(DEBUG_CMD, __func__, &iif->hcmsg);
        capi_ctr_handle_message(&iif->ctr, ap->id, skb);
 }
@@ -789,7 +804,11 @@ void gigaset_isdn_connD(struct bc_state *bcs)
                dev_err(cs->dev, "%s: out of memory\n", __func__);
                return;
        }
-       capi_cmsg2message(&iif->hcmsg, __skb_put(skb, msgsize));
+       if (capi_cmsg2message(&iif->hcmsg, __skb_put(skb, msgsize))) {
+               dev_err(cs->dev, "%s: message parser failure\n", __func__);
+               dev_kfree_skb_any(skb);
+               return;
+       }
        dump_cmsg(DEBUG_CMD, __func__, &iif->hcmsg);
        capi_ctr_handle_message(&iif->ctr, ap->id, skb);
 }
@@ -889,7 +908,11 @@ void gigaset_isdn_connB(struct bc_state *bcs)
                dev_err(cs->dev, "%s: out of memory\n", __func__);
                return;
        }
-       capi_cmsg2message(&iif->hcmsg, __skb_put(skb, msgsize));
+       if (capi_cmsg2message(&iif->hcmsg, __skb_put(skb, msgsize))) {
+               dev_err(cs->dev, "%s: message parser failure\n", __func__);
+               dev_kfree_skb_any(skb);
+               return;
+       }
        dump_cmsg(DEBUG_CMD, __func__, &iif->hcmsg);
        capi_ctr_handle_message(&iif->ctr, ap->id, skb);
 }
@@ -1096,13 +1119,19 @@ static void send_conf(struct gigaset_capi_ctr *iif,
                      struct sk_buff *skb,
                      u16 info)
 {
+       struct cardstate *cs = iif->ctr.driverdata;
+
        /*
         * _CONF replies always only have NCCI and Info parameters
         * so they'll fit into the _REQ message skb
         */
        capi_cmsg_answer(&iif->acmsg);
        iif->acmsg.Info = info;
-       capi_cmsg2message(&iif->acmsg, skb->data);
+       if (capi_cmsg2message(&iif->acmsg, skb->data)) {
+               dev_err(cs->dev, "%s: message parser failure\n", __func__);
+               dev_kfree_skb_any(skb);
+               return;
+       }
        __skb_trim(skb, CAPI_STDCONF_LEN);
        dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg);
        capi_ctr_handle_message(&iif->ctr, ap->id, skb);
@@ -1124,7 +1153,11 @@ static void do_facility_req(struct gigaset_capi_ctr *iif,
        static u8 confparam[10];        /* max. 9 octets + length byte */
 
        /* decode message */
-       capi_message2cmsg(cmsg, skb->data);
+       if (capi_message2cmsg(cmsg, skb->data)) {
+               dev_err(cs->dev, "%s: message parser failure\n", __func__);
+               dev_kfree_skb_any(skb);
+               return;
+       }
        dump_cmsg(DEBUG_CMD, __func__, cmsg);
 
        /*
@@ -1223,6 +1256,7 @@ static void do_facility_req(struct gigaset_capi_ctr *iif,
        }
 
        /* send FACILITY_CONF with given Info and confirmation parameter */
+       dev_kfree_skb_any(skb);
        capi_cmsg_answer(cmsg);
        cmsg->Info = info;
        cmsg->FacilityConfirmationParameter = confparam;
@@ -1232,7 +1266,11 @@ static void do_facility_req(struct gigaset_capi_ctr *iif,
                dev_err(cs->dev, "%s: out of memory\n", __func__);
                return;
        }
-       capi_cmsg2message(cmsg, __skb_put(cskb, msgsize));
+       if (capi_cmsg2message(cmsg, __skb_put(cskb, msgsize))) {
+               dev_err(cs->dev, "%s: message parser failure\n", __func__);
+               dev_kfree_skb_any(cskb);
+               return;
+       }
        dump_cmsg(DEBUG_CMD, __func__, cmsg);
        capi_ctr_handle_message(&iif->ctr, ap->id, cskb);
 }
@@ -1246,8 +1284,14 @@ static void do_listen_req(struct gigaset_capi_ctr *iif,
                          struct gigaset_capi_appl *ap,
                          struct sk_buff *skb)
 {
+       struct cardstate *cs = iif->ctr.driverdata;
+
        /* decode message */
-       capi_message2cmsg(&iif->acmsg, skb->data);
+       if (capi_message2cmsg(&iif->acmsg, skb->data)) {
+               dev_err(cs->dev, "%s: message parser failure\n", __func__);
+               dev_kfree_skb_any(skb);
+               return;
+       }
        dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg);
 
        /* store listening parameters */
@@ -1264,8 +1308,14 @@ static void do_alert_req(struct gigaset_capi_ctr *iif,
                         struct gigaset_capi_appl *ap,
                         struct sk_buff *skb)
 {
+       struct cardstate *cs = iif->ctr.driverdata;
+
        /* decode message */
-       capi_message2cmsg(&iif->acmsg, skb->data);
+       if (capi_message2cmsg(&iif->acmsg, skb->data)) {
+               dev_err(cs->dev, "%s: message parser failure\n", __func__);
+               dev_kfree_skb_any(skb);
+               return;
+       }
        dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg);
        send_conf(iif, ap, skb, CapiAlertAlreadySent);
 }
@@ -1290,7 +1340,11 @@ static void do_connect_req(struct gigaset_capi_ctr *iif,
        u16 info;
 
        /* decode message */
-       capi_message2cmsg(cmsg, skb->data);
+       if (capi_message2cmsg(cmsg, skb->data)) {
+               dev_err(cs->dev, "%s: message parser failure\n", __func__);
+               dev_kfree_skb_any(skb);
+               return;
+       }
        dump_cmsg(DEBUG_CMD, __func__, cmsg);
 
        /* get free B channel & construct PLCI */
@@ -1577,7 +1631,11 @@ static void do_connect_resp(struct gigaset_capi_ctr *iif,
        int channel;
 
        /* decode message */
-       capi_message2cmsg(cmsg, skb->data);
+       if (capi_message2cmsg(cmsg, skb->data)) {
+               dev_err(cs->dev, "%s: message parser failure\n", __func__);
+               dev_kfree_skb_any(skb);
+               return;
+       }
        dump_cmsg(DEBUG_CMD, __func__, cmsg);
        dev_kfree_skb_any(skb);
 
@@ -1743,7 +1801,11 @@ static void do_connect_b3_req(struct gigaset_capi_ctr *iif,
        int channel;
 
        /* decode message */
-       capi_message2cmsg(cmsg, skb->data);
+       if (capi_message2cmsg(cmsg, skb->data)) {
+               dev_err(cs->dev, "%s: message parser failure\n", __func__);
+               dev_kfree_skb_any(skb);
+               return;
+       }
        dump_cmsg(DEBUG_CMD, __func__, cmsg);
 
        /* extract and check channel number from PLCI */
@@ -1788,7 +1850,11 @@ static void do_connect_b3_resp(struct gigaset_capi_ctr *iif,
        u8 command;
 
        /* decode message */
-       capi_message2cmsg(cmsg, skb->data);
+       if (capi_message2cmsg(cmsg, skb->data)) {
+               dev_err(cs->dev, "%s: message parser failure\n", __func__);
+               dev_kfree_skb_any(skb);
+               return;
+       }
        dump_cmsg(DEBUG_CMD, __func__, cmsg);
 
        /* extract and check channel number and NCCI */
@@ -1828,7 +1894,11 @@ static void do_connect_b3_resp(struct gigaset_capi_ctr *iif,
        capi_cmsg_header(cmsg, ap->id, command, CAPI_IND,
                         ap->nextMessageNumber++, cmsg->adr.adrNCCI);
        __skb_trim(skb, msgsize);
-       capi_cmsg2message(cmsg, skb->data);
+       if (capi_cmsg2message(cmsg, skb->data)) {
+               dev_err(cs->dev, "%s: message parser failure\n", __func__);
+               dev_kfree_skb_any(skb);
+               return;
+       }
        dump_cmsg(DEBUG_CMD, __func__, cmsg);
        capi_ctr_handle_message(&iif->ctr, ap->id, skb);
 }
@@ -1850,7 +1920,11 @@ static void do_disconnect_req(struct gigaset_capi_ctr *iif,
        int channel;
 
        /* decode message */
-       capi_message2cmsg(cmsg, skb->data);
+       if (capi_message2cmsg(cmsg, skb->data)) {
+               dev_err(cs->dev, "%s: message parser failure\n", __func__);
+               dev_kfree_skb_any(skb);
+               return;
+       }
        dump_cmsg(DEBUG_CMD, __func__, cmsg);
 
        /* extract and check channel number from PLCI */
@@ -1906,8 +1980,14 @@ static void do_disconnect_req(struct gigaset_capi_ctr *iif,
                        kfree(b3cmsg);
                        return;
                }
-               capi_cmsg2message(b3cmsg,
-                                 __skb_put(b3skb, CAPI_DISCONNECT_B3_IND_BASELEN));
+               if (capi_cmsg2message(b3cmsg,
+                                     __skb_put(b3skb, CAPI_DISCONNECT_B3_IND_BASELEN))) {
+                       dev_err(cs->dev, "%s: message parser failure\n",
+                               __func__);
+                       kfree(b3cmsg);
+                       dev_kfree_skb_any(b3skb);
+                       return;
+               }
                dump_cmsg(DEBUG_CMD, __func__, b3cmsg);
                kfree(b3cmsg);
                capi_ctr_handle_message(&iif->ctr, ap->id, b3skb);
@@ -1938,7 +2018,11 @@ static void do_disconnect_b3_req(struct gigaset_capi_ctr *iif,
        int channel;
 
        /* decode message */
-       capi_message2cmsg(cmsg, skb->data);
+       if (capi_message2cmsg(cmsg, skb->data)) {
+               dev_err(cs->dev, "%s: message parser failure\n", __func__);
+               dev_kfree_skb_any(skb);
+               return;
+       }
        dump_cmsg(DEBUG_CMD, __func__, cmsg);
 
        /* extract and check channel number and NCCI */
@@ -2055,8 +2139,14 @@ static void do_reset_b3_req(struct gigaset_capi_ctr *iif,
                            struct gigaset_capi_appl *ap,
                            struct sk_buff *skb)
 {
+       struct cardstate *cs = iif->ctr.driverdata;
+
        /* decode message */
-       capi_message2cmsg(&iif->acmsg, skb->data);
+       if (capi_message2cmsg(&iif->acmsg, skb->data)) {
+               dev_err(cs->dev, "%s: message parser failure\n", __func__);
+               dev_kfree_skb_any(skb);
+               return;
+       }
        dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg);
        send_conf(iif, ap, skb,
                  CapiResetProcedureNotSupportedByCurrentProtocol);
@@ -2069,8 +2159,14 @@ static void do_unsupported(struct gigaset_capi_ctr *iif,
                           struct gigaset_capi_appl *ap,
                           struct sk_buff *skb)
 {
+       struct cardstate *cs = iif->ctr.driverdata;
+
        /* decode message */
-       capi_message2cmsg(&iif->acmsg, skb->data);
+       if (capi_message2cmsg(&iif->acmsg, skb->data)) {
+               dev_err(cs->dev, "%s: message parser failure\n", __func__);
+               dev_kfree_skb_any(skb);
+               return;
+       }
        dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg);
        send_conf(iif, ap, skb, CapiMessageNotSupportedInCurrentState);
 }
@@ -2082,8 +2178,14 @@ static void do_nothing(struct gigaset_capi_ctr *iif,
                       struct gigaset_capi_appl *ap,
                       struct sk_buff *skb)
 {
+       struct cardstate *cs = iif->ctr.driverdata;
+
        /* decode message */
-       capi_message2cmsg(&iif->acmsg, skb->data);
+       if (capi_message2cmsg(&iif->acmsg, skb->data)) {
+               dev_err(cs->dev, "%s: message parser failure\n", __func__);
+               dev_kfree_skb_any(skb);
+               return;
+       }
        dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg);
        dev_kfree_skb_any(skb);
 }