| From foo@baz Thu Apr 10 22:03:05 PDT 2014 |
| From: Dan Carpenter <dan.carpenter@oracle.com> |
| Date: Tue, 8 Apr 2014 12:23:09 +0300 |
| Subject: isdnloop: several buffer overflows |
| |
| From: Dan Carpenter <dan.carpenter@oracle.com> |
| |
| [ Upstream commit 7563487cbf865284dcd35e9ef5a95380da046737 ] |
| |
| There are three buffer overflows addressed in this patch. |
| |
| 1) In isdnloop_fake_err() we add an 'E' to a 60 character string and |
| then copy it into a 60 character buffer. I have made the destination |
| buffer 64 characters and I'm changed the sprintf() to a snprintf(). |
| |
| 2) In isdnloop_parse_cmd(), p points to a 6 characters into a 60 |
| character buffer so we have 54 characters. The ->eazlist[] is 11 |
| characters long. I have modified the code to return if the source |
| buffer is too long. |
| |
| 3) In isdnloop_command() the cbuf[] array was 60 characters long but the |
| max length of the string then can be up to 79 characters. I made the |
| cbuf array 80 characters long and changed the sprintf() to snprintf(). |
| I also removed the temporary "dial" buffer and changed it to use "p" |
| directly. |
| |
| Unfortunately, we pass the "cbuf" string from isdnloop_command() to |
| isdnloop_writecmd() which truncates anything over 60 characters to make |
| it fit in card->omsg[]. (It can accept values up to 255 characters so |
| long as there is a '\n' character every 60 characters). For now I have |
| just fixed the memory corruption bug and left the other problems in this |
| driver alone. |
| |
| Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/isdn/isdnloop/isdnloop.c | 17 +++++++++-------- |
| 1 file changed, 9 insertions(+), 8 deletions(-) |
| |
| --- a/drivers/isdn/isdnloop/isdnloop.c |
| +++ b/drivers/isdn/isdnloop/isdnloop.c |
| @@ -518,9 +518,9 @@ static isdnloop_stat isdnloop_cmd_table[ |
| static void |
| isdnloop_fake_err(isdnloop_card *card) |
| { |
| - char buf[60]; |
| + char buf[64]; |
| |
| - sprintf(buf, "E%s", card->omsg); |
| + snprintf(buf, sizeof(buf), "E%s", card->omsg); |
| isdnloop_fake(card, buf, -1); |
| isdnloop_fake(card, "NAK", -1); |
| } |
| @@ -903,6 +903,8 @@ isdnloop_parse_cmd(isdnloop_card *card) |
| case 7: |
| /* 0x;EAZ */ |
| p += 3; |
| + if (strlen(p) >= sizeof(card->eazlist[0])) |
| + break; |
| strcpy(card->eazlist[ch - 1], p); |
| break; |
| case 8: |
| @@ -1133,7 +1135,7 @@ isdnloop_command(isdn_ctrl *c, isdnloop_ |
| { |
| ulong a; |
| int i; |
| - char cbuf[60]; |
| + char cbuf[80]; |
| isdn_ctrl cmd; |
| isdnloop_cdef cdef; |
| |
| @@ -1198,7 +1200,6 @@ isdnloop_command(isdn_ctrl *c, isdnloop_ |
| break; |
| if ((c->arg & 255) < ISDNLOOP_BCH) { |
| char *p; |
| - char dial[50]; |
| char dcode[4]; |
| |
| a = c->arg; |
| @@ -1210,10 +1211,10 @@ isdnloop_command(isdn_ctrl *c, isdnloop_ |
| } else |
| /* Normal Dial */ |
| strcpy(dcode, "CAL"); |
| - strcpy(dial, p); |
| - sprintf(cbuf, "%02d;D%s_R%s,%02d,%02d,%s\n", (int) (a + 1), |
| - dcode, dial, c->parm.setup.si1, |
| - c->parm.setup.si2, c->parm.setup.eazmsn); |
| + snprintf(cbuf, sizeof(cbuf), |
| + "%02d;D%s_R%s,%02d,%02d,%s\n", (int) (a + 1), |
| + dcode, p, c->parm.setup.si1, |
| + c->parm.setup.si2, c->parm.setup.eazmsn); |
| i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card); |
| } |
| break; |