Skip to content

Commit

Permalink
mISDN: Fix null pointer dereference at mISDN_FsmNew
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Druidos authored and kkeil committed Aug 28, 2017
1 parent ce6d8fb commit a460993
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 9 deletions.
5 changes: 4 additions & 1 deletion drivers/isdn/mISDN/fsm.c
Expand Up @@ -26,14 +26,16 @@

#define FSM_TIMER_DEBUG 0

void
int
mISDN_FsmNew(struct Fsm *fsm,
struct FsmNode *fnlist, int fncount)
{
int i;

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) ||
Expand All @@ -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);

Expand Down
2 changes: 1 addition & 1 deletion drivers/isdn/mISDN/fsm.h
Expand Up @@ -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);
Expand Down
3 changes: 1 addition & 2 deletions drivers/isdn/mISDN/layer1.c
Expand Up @@ -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
Expand Down
15 changes: 13 additions & 2 deletions drivers/isdn/mISDN/layer2.c
Expand Up @@ -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
Expand Down
20 changes: 17 additions & 3 deletions drivers/isdn/mISDN/tei.c
Expand Up @@ -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)
Expand Down

0 comments on commit a460993

Please sign in to comment.