memory corruptor in .18rc1-git

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Three times in the last week, I've had a box running the -git-du-jour
spontaneously reboot.  It just happened again, this time I had a serial
console hooked up, but it rebooted before transferring much data.
The one thing it did spew however was "List corruption. prev->ne",
which came from the patch below which I had in my tree.
(The latter half is likely irrelevant, and came from chasing a different bug)

Things in common at all three times it happened..
reading email, and listening to oggs with rhythmbox.
Another ALSA bug maybe ?

I've up'd the speed of the serial console, in the hope that more chars
make it over the wire before reboot should this happen again.

		Dave


--- linux-2.6/include/linux/list.h~	2005-08-08 15:34:50.000000000 -0400
+++ linux-2.6/include/linux/list.h	2005-08-08 15:35:22.000000000 -0400
@@ -5,7 +5,9 @@
 
 #include <linux/stddef.h>
 #include <linux/prefetch.h>
+#include <linux/kernel.h>
 #include <asm/system.h>
+#include <asm/bug.h>
 
 /*
  * These are non-NULL pointers that will result in page faults
@@ -52,6 +52,16 @@ static inline void __list_add(struct lis
 			      struct list_head *prev,
 			      struct list_head *next)
 {
+	if (next->prev != prev) {
+		printk("List corruption. next->prev should be %p, but was %p\n",
+				prev, next->prev);
+		BUG();
+	}
+	if (prev->next != next) {
+		printk("List corruption. prev->next should be %p, but was %p\n",
+				next, prev->next);
+		BUG();
+	}
 	next->prev = new;
 	new->next = next;
 	new->prev = prev;
@@ -162,6 +162,16 @@ static inline void __list_del(struct lis
  */
 static inline void list_del(struct list_head *entry)
 {
+	if (entry->prev->next != entry) {
+		printk("List corruption. prev->next should be %p, but was %p\n",
+				entry, entry->prev->next);
+		BUG();
+	}
+	if (entry->next->prev != entry) {
+		printk("List corruption. next->prev should be %p, but was %p\n",
+				entry, entry->next->prev);
+		BUG();
+	}
 	__list_del(entry->prev, entry->next);
 	entry->next = LIST_POISON1;
 	entry->prev = LIST_POISON2;



It _may_ give more information about exactly which wait-queue (or rather, 
what the poll function that was related to that wait-queue) seems to be 
corrupted. 

		Linus

---
diff --git a/fs/select.c b/fs/select.c
index a8109ba..8cd6dc3 100644
--- a/fs/select.c
+++ b/fs/select.c
@@ -23,6 +23,7 @@ #include <linux/personality.h> /* for ST
 #include <linux/file.h>
 #include <linux/fs.h>
 #include <linux/rcupdate.h>
+#include <linux/kallsyms.h>
 
 #include <asm/uaccess.h>
 
@@ -65,7 +66,8 @@ EXPORT_SYMBOL(poll_initwait);
 
 static void free_poll_entry(struct poll_table_entry *entry)
 {
-	remove_wait_queue(entry->wait_address,&entry->wait);
+	if (remove_wait_queue(entry->wait_address,&entry->wait) < 0)
+		print_symbol("bad poll-entry for %s", (unsigned long) entry->filp->f_op->poll);
 	fput(entry->filp);
 }
 
diff --git a/include/linux/wait.h b/include/linux/wait.h
index d285182..4c1d74e 100644
--- a/include/linux/wait.h
+++ b/include/linux/wait.h
@@ -115,7 +115,7 @@ #define is_sync_wait(wait)	(!(wait) || (
 
 extern void FASTCALL(add_wait_queue(wait_queue_head_t *q, wait_queue_t * wait));
 extern void FASTCALL(add_wait_queue_exclusive(wait_queue_head_t *q, wait_queue_t * wait));
-extern void FASTCALL(remove_wait_queue(wait_queue_head_t *q, wait_queue_t * wait));
+extern int FASTCALL(remove_wait_queue(wait_queue_head_t *q, wait_queue_t * wait));
 
 static inline void __add_wait_queue(wait_queue_head_t *head, wait_queue_t *new)
 {
diff --git a/kernel/wait.c b/kernel/wait.c
index 791681c..5cdf169 100644
--- a/kernel/wait.c
+++ b/kernel/wait.c
@@ -33,13 +33,35 @@ void fastcall add_wait_queue_exclusive(w
 }
 EXPORT_SYMBOL(add_wait_queue_exclusive);
 
-void fastcall remove_wait_queue(wait_queue_head_t *q, wait_queue_t *wait)
+int fastcall remove_wait_queue(wait_queue_head_t *q, wait_queue_t *wait)
 {
 	unsigned long flags;
+	struct list_head *list;
+	int seen, retval;
 
 	spin_lock_irqsave(&q->lock, flags);
-	__remove_wait_queue(q, wait);
+	list = &q->task_list;
+	seen = 0;
+	retval = -1;
+
+	do {
+		struct list_head *next;
+		if (list == &wait->task_list)
+			seen++;
+		next = list->next;
+		if (next->prev != list) {
+			seen += 2;
+			break;
+		}
+		list = next;
+	} while (list != &q->task_list);
+
+	if (seen == 1) {
+		__remove_wait_queue(q, wait);
+		retval = 0;
+	}
 	spin_unlock_irqrestore(&q->lock, flags);
+	return retval;
 }
 EXPORT_SYMBOL(remove_wait_queue);
 

-- 
http://www.codemonkey.org.uk
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux