summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShaun Ruffell <sruffell@digium.com>2012-08-16 21:38:57 +0000
committerShaun Ruffell <sruffell@digium.com>2012-08-16 21:38:57 +0000
commit6d1833f02ff672a1c0e8a342b6cb5f58d5049aed (patch)
tree64133a7554356050e062cc0a42aaa3f32dc4fbf0
parentee9b357640eeda5fc175bfbe1369748332493c99 (diff)
wcte12xp: Fix stack corruption when checking T1 RBS states.
This fixes an (embarrassing) error in t1_check_sigbits in the previous commit where I was writing pass the end of an array on the stack. Now instead of using an array on the stack, of which all elements were not used, the pending commands are now stored on a list. I also removed the automatic free of commands from __t1_getresults and now the function that allocated the command now frees them. I believe this will be less error-prone going forward. Signed-off-by: Shaun Ruffell <sruffell@digium.com> Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com> Origin: http://svnview.digium.com/svn/dahdi?view=rev&rev=10700 git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.6@10707 a0bf4364-ded3-4de4-8d8a-66a801d63aff
-rw-r--r--drivers/dahdi/wcte12xp/base.c112
1 files changed, 85 insertions, 27 deletions
diff --git a/drivers/dahdi/wcte12xp/base.c b/drivers/dahdi/wcte12xp/base.c
index f0fa949..6a34095 100644
--- a/drivers/dahdi/wcte12xp/base.c
+++ b/drivers/dahdi/wcte12xp/base.c
@@ -688,18 +688,20 @@ static int __t1_getresult(struct t1 *wc, struct command *cmd)
}
}
ret = cmd->data;
- free_cmd(wc, cmd);
return ret;
}
static int t1_getreg(struct t1 *wc, int addr)
{
+ int res;
struct command *cmd = NULL;
cmd = get_free_cmd(wc);
if (!cmd)
return -ENOMEM;
__t1_getreg(wc, addr, cmd);
- return __t1_getresult(wc, cmd);
+ res = __t1_getresult(wc, cmd);
+ free_cmd(wc, cmd);
+ return res;
}
static void t1_setleds(struct t1 *wc, int leds)
@@ -1195,27 +1197,45 @@ static int t1xxp_rbsbits(struct dahdi_chan *chan, int bits)
static void t1_check_sigbits(struct t1 *wc)
{
- struct command *cmds[15] = {NULL,};
+ struct command_container {
+ struct command *cmd;
+ struct list_head node;
+ unsigned int index;
+ };
+ struct command_container *cont;
+ LIST_HEAD(commands);
int a,i,rxs;
if (!(test_bit(DAHDI_FLAGBIT_RUNNING, &wc->span.flags)))
return;
+
if (dahdi_is_e1_span(&wc->span)) {
/* Send out all the commands first. */
for (i = 0; i < 15; i++) {
if (!(wc->span.chans[i+16]->sig & DAHDI_SIG_CLEAR) ||
!(wc->span.chans[i]->sig & DAHDI_SIG_CLEAR)) {
- cmds[i] = get_free_cmd(wc);
- __t1_getreg(wc, 0x71 + i, cmds[i]);
+ cont = kzalloc(sizeof(*cont), GFP_KERNEL);
+ if (!cont) {
+ WARN_ON_ONCE(1);
+ goto done;
+ }
+ cont->cmd = get_free_cmd(wc);
+ if (!cont->cmd) {
+ WARN_ON_ONCE(1);
+ goto done;
+ }
+ cont->index = i;
+ list_add_tail(&cont->node, &commands);
+ __t1_getreg(wc, 0x71 + i, cont->cmd);
}
}
/* Now check the results */
- for (i = 14; i >= 0; --i) {
- struct command *cmd = cmds[i];
- if (!cmd)
- continue;
- a = __t1_getresult(wc, cmd);
+ list_for_each_entry_reverse(cont, &commands, node) {
+ i = cont->index;
+ a = __t1_getresult(wc, cont->cmd);
+ free_cmd(wc, cont->cmd);
+ cont->cmd = NULL;
if (a > -1) {
/* Get high channel in low bits */
rxs = (a & 0xf);
@@ -1234,18 +1254,28 @@ static void t1_check_sigbits(struct t1 *wc)
}
} else if (wc->span.lineconfig & DAHDI_CONFIG_D4) {
/* First we'll send out the commands */
- for (i = 0; i < 24; i+=4) {
- cmds[i] = get_free_cmd(wc);
- if (!cmds[i]) {
- WARN_ON(1);
- return;
+ for (i = 0; i < 24; i += 4) {
+ cont = kzalloc(sizeof(*cont), GFP_KERNEL);
+ if (!cont) {
+ WARN_ON_ONCE(1);
+ goto done;
+ }
+ cont->cmd = get_free_cmd(wc);
+ if (!cont->cmd) {
+ WARN_ON_ONCE(1);
+ goto done;
}
- __t1_getreg(wc, 0x70 + (i>>2), cmds[i]);
+ cont->index = i;
+ list_add_tail(&cont->node, &commands);
+ __t1_getreg(wc, 0x70 + (i>>2), cont->cmd);
}
/* Now we'll check the results */
- for (i = 20; i >= 0; i -= 4) {
- a = __t1_getresult(wc, cmds[i]);
+ list_for_each_entry_reverse(cont, &commands, node) {
+ i = cont->index;
+ a = __t1_getresult(wc, cont->cmd);
+ free_cmd(wc, cont->cmd);
+ cont->cmd = NULL;
if (a > -1) {
/* Get high channel in low bits */
rxs = (a & 0x3) << 2;
@@ -1276,17 +1306,27 @@ static void t1_check_sigbits(struct t1 *wc)
}
} else {
/* First send out the commands. */
- for (i = 0; i < 24; i+=2) {
- cmds[i] = get_free_cmd(wc);
- if (!cmds[i]) {
- WARN_ON(1);
- return;
+ for (i = 0; i < 24; i += 2) {
+ cont = kzalloc(sizeof(*cont), GFP_KERNEL);
+ if (!cont) {
+ WARN_ON_ONCE(1);
+ goto done;
}
- __t1_getreg(wc, 0x70 + (i>>1), cmds[i]);
+ cont->cmd = get_free_cmd(wc);
+ if (!cont->cmd) {
+ WARN_ON_ONCE(1);
+ goto done;
+ }
+ cont->index = i;
+ list_add_tail(&cont->node, &commands);
+ __t1_getreg(wc, 0x70 + (i>>1), cont->cmd);
}
- /* Now check the results. */
- for (i = 22; i >= 0; i -= 2) {
- a = __t1_getresult(wc, cmds[i]);
+
+ list_for_each_entry_reverse(cont, &commands, node) {
+ i = cont->index;
+ a = __t1_getresult(wc, cont->cmd);
+ free_cmd(wc, cont->cmd);
+ cont->cmd = NULL;
if (a > -1) {
/* Get high channel in low bits */
rxs = (a & 0xf);
@@ -1304,6 +1344,21 @@ static void t1_check_sigbits(struct t1 *wc)
}
}
}
+done:
+ while (!list_empty(&commands)) {
+ cont = container_of(commands.next,
+ struct command_container, node);
+ if (unlikely(cont->cmd)) {
+ /* We do not care about the result, let's just wait for
+ * the rest of the system to finish with it. */
+ __t1_getresult(wc, cont->cmd);
+ free_cmd(wc, cont->cmd);
+ cont->cmd = NULL;
+ }
+ list_del(&cont->node);
+ kfree(cont);
+ }
+ return;
}
struct maint_work_struct {
@@ -2114,6 +2169,9 @@ static void t1_check_alarms(struct t1 *wc)
fmr4 = __t1_getresult(wc, cmds[1]);
c = __t1_getresult(wc, cmds[0]);
+ for (x=0; x < ARRAY_SIZE(cmds); ++x)
+ free_cmd(wc, cmds[x]);
+
/* Assume no alarms */
alarms = 0;