linux-mm.kvack.org archive mirror
 help / color / mirror / Atom feed
From: Linus Torvalds <torvalds@linux-foundation.org>
To: Eric Dumazet <eric.dumazet@gmail.com>
Cc: Michal Hocko <mhocko@suse.cz>, Ingo Molnar <mingo@elte.hu>,
	linux-mm@kvack.org, LKML <linux-kernel@vger.kernel.org>,
	Octavian Purdila <opurdila@ixiacom.com>,
	David Miller <davem@davemloft.net>
Subject: Re: BUG: Bad page map in process udevd (anon_vma: (null)) in 2.6.38-rc4
Date: Thu, 17 Feb 2011 12:18:04 -0800	[thread overview]
Message-ID: <AANLkTi=SHY9gF49zyoECNV3favjS8Q6-9eWnQwNKX2EM@mail.gmail.com> (raw)
In-Reply-To: <AANLkTikUF+gz8H3SkW4NhD8SOT5b4bxnpcJgsVU+G-bC@mail.gmail.com>

[-- Attachment #1: Type: text/plain, Size: 1289 bytes --]

On Thu, Feb 17, 2011 at 9:07 AM, Linus Torvalds
<torvalds@linux-foundation.org> wrote:
>
> [ Btw, that also shows another problem: "list_move()" doesn't trigger
> the debugging checks when it does the __list_del(). So
> CONFIG_DEBUG_LIST would never have caught the fact that the
> "list_move()" was done on a list-entry that didn't have valid list
> pointers any more. ]

Ok, so does this patch change things? IOW, if you enable
CONFIG_DEBUG_LIST, this patch should hopefully make the error case of
using "list_move()" on a stale and re-used entry trigger an error
printout.

NOTE! Even if the list is some stale entry on the stack, if nothing
has overwritten that stack entry, no amount of list debugging will
notice this. So you still need to hit the problem. But now the kernel
should print stuff out even if the page got re-allocated to something
else than a page table, so _if_ the problem is a list_move() or
similar, we don't need to hit quite the same very special case. If it
corrupts user space pages or some other random memory, it will still
complain (instead of just resulting in a SIGSEGV or whatever)

Of course, there is absolutely no guarantee that it's actually
"list_move()" at all.

And as usual, the patch is TOTALLY UNTESTED.

                                 Linus

[-- Attachment #2: patch.diff --]
[-- Type: text/x-patch, Size: 3431 bytes --]

 include/linux/list.h |   12 +++++++++---
 lib/list_debug.c     |   39 ++++++++++++++++++++++++++-------------
 2 files changed, 35 insertions(+), 16 deletions(-)

diff --git a/include/linux/list.h b/include/linux/list.h
index 9a5f8a7..3a54266 100644
--- a/include/linux/list.h
+++ b/include/linux/list.h
@@ -96,6 +96,11 @@ static inline void __list_del(struct list_head * prev, struct list_head * next)
  * in an undefined state.
  */
 #ifndef CONFIG_DEBUG_LIST
+static inline void __list_del_entry(struct list_head *entry)
+{
+	__list_del(entry->prev, entry->next);
+}
+
 static inline void list_del(struct list_head *entry)
 {
 	__list_del(entry->prev, entry->next);
@@ -103,6 +108,7 @@ static inline void list_del(struct list_head *entry)
 	entry->prev = LIST_POISON2;
 }
 #else
+extern void __list_del_entry(struct list_head *entry);
 extern void list_del(struct list_head *entry);
 #endif
 
@@ -135,7 +141,7 @@ static inline void list_replace_init(struct list_head *old,
  */
 static inline void list_del_init(struct list_head *entry)
 {
-	__list_del(entry->prev, entry->next);
+	__list_del_entry(entry);
 	INIT_LIST_HEAD(entry);
 }
 
@@ -146,7 +152,7 @@ static inline void list_del_init(struct list_head *entry)
  */
 static inline void list_move(struct list_head *list, struct list_head *head)
 {
-	__list_del(list->prev, list->next);
+	__list_del_entry(list);
 	list_add(list, head);
 }
 
@@ -158,7 +164,7 @@ static inline void list_move(struct list_head *list, struct list_head *head)
 static inline void list_move_tail(struct list_head *list,
 				  struct list_head *head)
 {
-	__list_del(list->prev, list->next);
+	__list_del_entry(list);
 	list_add_tail(list, head);
 }
 
diff --git a/lib/list_debug.c b/lib/list_debug.c
index 344c710..b8029a5 100644
--- a/lib/list_debug.c
+++ b/lib/list_debug.c
@@ -35,6 +35,31 @@ void __list_add(struct list_head *new,
 }
 EXPORT_SYMBOL(__list_add);
 
+void __list_del_entry(struct list_head *entry)
+{
+	struct list_head *prev, *next;
+
+	prev = entry->prev;
+	next = entry->next;
+
+	if (WARN(next == LIST_POISON1,
+		"list_del corruption, %p->next is LIST_POISON1 (%p)\n",
+		entry, LIST_POISON1) ||
+	    WARN(prev == LIST_POISON2,
+		"list_del corruption, %p->prev is LIST_POISON2 (%p)\n",
+		entry, LIST_POISON2) ||
+	    WARN(prev->next != entry,
+		"list_del corruption. prev->next should be %p, "
+		"but was %p\n", entry, prev->next) ||
+	    WARN(next->prev != entry,
+		"list_del corruption. next->prev should be %p, "
+		"but was %p\n", entry, next->prev))
+		return;
+
+	__list_del(prev, next);
+}
+EXPORT_SYMBOL(__list_del_entry);
+
 /**
  * list_del - deletes entry from list.
  * @entry: the element to delete from the list.
@@ -43,19 +68,7 @@ EXPORT_SYMBOL(__list_add);
  */
 void list_del(struct list_head *entry)
 {
-	WARN(entry->next == LIST_POISON1,
-		"list_del corruption, next is LIST_POISON1 (%p)\n",
-		LIST_POISON1);
-	WARN(entry->next != LIST_POISON1 && entry->prev == LIST_POISON2,
-		"list_del corruption, prev is LIST_POISON2 (%p)\n",
-		LIST_POISON2);
-	WARN(entry->prev->next != entry,
-		"list_del corruption. prev->next should be %p, "
-		"but was %p\n", entry, entry->prev->next);
-	WARN(entry->next->prev != entry,
-		"list_del corruption. next->prev should be %p, "
-		"but was %p\n", entry, entry->next->prev);
-	__list_del(entry->prev, entry->next);
+	__list_del_entry(entry);
 	entry->next = LIST_POISON1;
 	entry->prev = LIST_POISON2;
 }

  parent reply	other threads:[~2011-02-17 20:18 UTC|newest]

Thread overview: 53+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-02-16 18:52 Michal Hocko
2011-02-16 19:37 ` Ingo Molnar
2011-02-16 19:50   ` Linus Torvalds
2011-02-16 20:09     ` Linus Torvalds
2011-02-16 20:51       ` Linus Torvalds
2011-02-17  9:09       ` Michal Hocko
2011-02-17 16:13         ` Linus Torvalds
2011-02-17 16:26           ` Michal Hocko
2011-02-17 16:35           ` Ingo Molnar
2011-02-17 18:57             ` Eric W. Biederman
2011-02-17 19:11               ` Linus Torvalds
2011-02-17 19:31                 ` Eric W. Biederman
2011-02-18  3:16                 ` Eric W. Biederman
2011-02-18  4:30                   ` Linus Torvalds
2011-02-18  4:36                     ` David Miller
2011-02-18  6:25                       ` Eric Dumazet
2011-02-18  7:29                         ` Eric Dumazet
2011-02-18  8:54                           ` [PATCH 1/2] net: dont leave active on stack LIST_HEAD Eric Dumazet
2011-02-18 20:14                             ` David Miller
2011-02-18  4:38                     ` BUG: Bad page map in process udevd (anon_vma: (null)) in 2.6.38-rc4 Linus Torvalds
2011-02-18  4:40                       ` David Miller
2011-02-18  4:57                         ` Linus Torvalds
2011-02-18  8:29                           ` Eric W. Biederman
2011-02-18  5:20                     ` Eric W. Biederman
2011-02-18  8:41                       ` Eric Dumazet
2011-02-18  8:59                       ` [PATCH 2/2] net: deinit automatic LIST_HEAD Eric Dumazet
2011-02-18 20:14                         ` David Miller
2011-02-18 12:29                 ` BUG: Bad page map in process udevd (anon_vma: (null)) in 2.6.38-rc4 Michal Hocko
2011-02-18 16:26                   ` Michal Hocko
2011-02-18 16:39                     ` Linus Torvalds
2011-02-18 18:08                       ` Eric W. Biederman
2011-02-18 18:48                         ` Linus Torvalds
2011-02-18 19:01                           ` Arnaldo Carvalho de Melo
2011-02-18 19:11                             ` Arnaldo Carvalho de Melo
2011-02-18 20:38                               ` Eric W. Biederman
2011-02-19  8:35                                 ` [PATCH] tcp: fix inet_twsk_deschedule() Eric Dumazet
2011-02-20  2:59                                   ` David Miller
2011-02-18 19:13                             ` BUG: Bad page map in process udevd (anon_vma: (null)) in 2.6.38-rc4 Eric Dumazet
2011-02-18 19:56                       ` David Miller
2011-02-19  6:22                       ` Eric W. Biederman
2011-02-19 15:33                         ` Linus Torvalds
2011-02-20  2:01                           ` Eric W. Biederman
2011-02-20  6:15                             ` Linus Torvalds
2011-02-20  8:27                               ` Eric Dumazet
2011-02-20 19:53                               ` David Miller
2011-02-20 21:34                                 ` Eric W. Biederman
2011-02-18  8:54             ` Michal Hocko
2011-02-20 12:43             ` Ingo Molnar
2011-02-17 16:36           ` Eric Dumazet
2011-02-17 17:07             ` Linus Torvalds
2011-02-17 19:36               ` Eric Dumazet
2011-02-17 20:18               ` Linus Torvalds [this message]
2011-02-16 20:13     ` Ingo Molnar

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='AANLkTi=SHY9gF49zyoECNV3favjS8Q6-9eWnQwNKX2EM@mail.gmail.com' \
    --to=torvalds@linux-foundation.org \
    --cc=davem@davemloft.net \
    --cc=eric.dumazet@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=mhocko@suse.cz \
    --cc=mingo@elte.hu \
    --cc=opurdila@ixiacom.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox