[svn-commits] rmeyerriecks: linux/trunk r10700 - /linux/trunk/drivers/dahdi/wcte12xp/base.c

SVN commits to the Digium repositories svn-commits at lists.digium.com
Wed Jul 11 11:13:25 CDT 2012


Author: rmeyerriecks
Date: Wed Jul 11 11:13:22 2012
New Revision: 10700

URL: http://svnview.digium.com/svn/dahdi?view=rev&rev=10700
Log:
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 at digium.com>
Signed-off-by: Russ Meyerriecks <rmeyerriecks at digium.com>

Modified:
    linux/trunk/drivers/dahdi/wcte12xp/base.c

Modified: linux/trunk/drivers/dahdi/wcte12xp/base.c
URL: http://svnview.digium.com/svn/dahdi/linux/trunk/drivers/dahdi/wcte12xp/base.c?view=diff&rev=10700&r1=10699&r2=10700
==============================================================================
--- linux/trunk/drivers/dahdi/wcte12xp/base.c (original)
+++ linux/trunk/drivers/dahdi/wcte12xp/base.c Wed Jul 11 11:13:22 2012
@@ -688,18 +688,20 @@
 		}
 	}
 	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 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 @@
 		}
 	} 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;
 			}
-			__t1_getreg(wc, 0x70 + (i>>2), 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>>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 @@
 		}
 	} 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]);
-		}
-		/* Now check the results. */
-		for (i = 22; i >= 0; i -= 2) {
-			a = __t1_getresult(wc, 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);
+		}
+
+		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 @@
 			}
 		}
 	}
+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 {
@@ -2118,6 +2173,9 @@
 	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;
 




More information about the svn-commits mailing list