]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
mISDN: Fix null pointer dereference at mISDN_FsmNew
authorAnton Vasilyev <vasilyev@ispras.ru>
Fri, 11 Aug 2017 12:57:22 +0000 (15:57 +0300)
committerDavid S. Miller <davem@davemloft.net>
Fri, 11 Aug 2017 21:56:23 +0000 (14:56 -0700)
If mISDN_FsmNew() fails to allocate memory for jumpmatrix
then null pointer dereference will occur on any write to
jumpmatrix.

The patch adds check on successful allocation and
corresponding error handling.

Found by Linux Driver Verification project (linuxtesting.org).

Signed-off-by: Anton Vasilyev <vasilyev@ispras.ru>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/isdn/mISDN/fsm.c
drivers/isdn/mISDN/fsm.h
drivers/isdn/mISDN/layer1.c
drivers/isdn/mISDN/layer2.c
drivers/isdn/mISDN/tei.c

index 78fc5d5e90514353b258658da350a85c408b89db..92e6570b11435e7e4dade7aa433231008c82b294 100644 (file)
@@ -26,7 +26,7 @@
 
 #define FSM_TIMER_DEBUG 0
 
-void
+int
 mISDN_FsmNew(struct Fsm *fsm,
             struct FsmNode *fnlist, int fncount)
 {
@@ -34,6 +34,8 @@ mISDN_FsmNew(struct Fsm *fsm,
 
        fsm->jumpmatrix = kzalloc(sizeof(FSMFNPTR) * fsm->state_count *
                                  fsm->event_count, GFP_KERNEL);
+       if (fsm->jumpmatrix == NULL)
+               return -ENOMEM;
 
        for (i = 0; i < fncount; i++)
                if ((fnlist[i].state >= fsm->state_count) ||
@@ -45,6 +47,7 @@ mISDN_FsmNew(struct Fsm *fsm,
                } else
                        fsm->jumpmatrix[fsm->state_count * fnlist[i].event +
                                        fnlist[i].state] = (FSMFNPTR) fnlist[i].routine;
+       return 0;
 }
 EXPORT_SYMBOL(mISDN_FsmNew);
 
index 928f5be192c1fd4a5c8197160efb9dad21e1141d..e1def84902212e1637cf96f0c9cefb8c3950edbd 100644 (file)
@@ -55,7 +55,7 @@ struct FsmTimer {
        void *arg;
 };
 
-extern void mISDN_FsmNew(struct Fsm *, struct FsmNode *, int);
+extern int mISDN_FsmNew(struct Fsm *, struct FsmNode *, int);
 extern void mISDN_FsmFree(struct Fsm *);
 extern int mISDN_FsmEvent(struct FsmInst *, int , void *);
 extern void mISDN_FsmChangeState(struct FsmInst *, int);
index bebc57b72138e721aa5a290482ae46e748aac2d2..3192b0eb39445435d7b38c0f914bded7c93b2fac 100644 (file)
@@ -414,8 +414,7 @@ l1_init(u_int *deb)
        l1fsm_s.event_count = L1_EVENT_COUNT;
        l1fsm_s.strEvent = strL1Event;
        l1fsm_s.strState = strL1SState;
-       mISDN_FsmNew(&l1fsm_s, L1SFnList, ARRAY_SIZE(L1SFnList));
-       return 0;
+       return mISDN_FsmNew(&l1fsm_s, L1SFnList, ARRAY_SIZE(L1SFnList));
 }
 
 void
index 7243a6746f8b099d79d3221def6dcfcf138a6f51..9ff0903a0e89fb2f4f7373e1ef4d1d1663934b36 100644 (file)
@@ -2247,15 +2247,26 @@ static struct Bprotocol X75SLP = {
 int
 Isdnl2_Init(u_int *deb)
 {
+       int res;
        debug = deb;
        mISDN_register_Bprotocol(&X75SLP);
        l2fsm.state_count = L2_STATE_COUNT;
        l2fsm.event_count = L2_EVENT_COUNT;
        l2fsm.strEvent = strL2Event;
        l2fsm.strState = strL2State;
-       mISDN_FsmNew(&l2fsm, L2FnList, ARRAY_SIZE(L2FnList));
-       TEIInit(deb);
+       res = mISDN_FsmNew(&l2fsm, L2FnList, ARRAY_SIZE(L2FnList));
+       if (res)
+               goto error;
+       res = TEIInit(deb);
+       if (res)
+               goto error_fsm;
        return 0;
+
+error_fsm:
+       mISDN_FsmFree(&l2fsm);
+error:
+       mISDN_unregister_Bprotocol(&X75SLP);
+       return res;
 }
 
 void
index 908127efccf8ceb94ef2ab1ed7df4b17b26ce5b9..12d9e5f4beb1f81c5aa5e5af81bc9aca61c21668 100644 (file)
@@ -1387,23 +1387,37 @@ create_teimanager(struct mISDNdevice *dev)
 
 int TEIInit(u_int *deb)
 {
+       int res;
        debug = deb;
        teifsmu.state_count = TEI_STATE_COUNT;
        teifsmu.event_count = TEI_EVENT_COUNT;
        teifsmu.strEvent = strTeiEvent;
        teifsmu.strState = strTeiState;
-       mISDN_FsmNew(&teifsmu, TeiFnListUser, ARRAY_SIZE(TeiFnListUser));
+       res = mISDN_FsmNew(&teifsmu, TeiFnListUser, ARRAY_SIZE(TeiFnListUser));
+       if (res)
+               goto error;
        teifsmn.state_count = TEI_STATE_COUNT;
        teifsmn.event_count = TEI_EVENT_COUNT;
        teifsmn.strEvent = strTeiEvent;
        teifsmn.strState = strTeiState;
-       mISDN_FsmNew(&teifsmn, TeiFnListNet, ARRAY_SIZE(TeiFnListNet));
+       res = mISDN_FsmNew(&teifsmn, TeiFnListNet, ARRAY_SIZE(TeiFnListNet));
+       if (res)
+               goto error_smn;
        deactfsm.state_count =  DEACT_STATE_COUNT;
        deactfsm.event_count = DEACT_EVENT_COUNT;
        deactfsm.strEvent = strDeactEvent;
        deactfsm.strState = strDeactState;
-       mISDN_FsmNew(&deactfsm, DeactFnList, ARRAY_SIZE(DeactFnList));
+       res = mISDN_FsmNew(&deactfsm, DeactFnList, ARRAY_SIZE(DeactFnList));
+       if (res)
+               goto error_deact;
        return 0;
+
+error_deact:
+       mISDN_FsmFree(&teifsmn);
+error_smn:
+       mISDN_FsmFree(&teifsmu);
+error:
+       return res;
 }
 
 void TEIFree(void)