Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753472Ab1C1F2T (ORCPT ); Mon, 28 Mar 2011 01:28:19 -0400 Received: from mx1.redhat.com ([209.132.183.28]:20846 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752587Ab1C1F2R (ORCPT ); Mon, 28 Mar 2011 01:28:17 -0400 From: Amerigo Wang To: linux-kernel@vger.kernel.org Cc: WANG Cong , Linus Torvalds , Al Viro , WANG Cong , Andrew Morton , Eric B Munson , David Rientjes , Dave Hansen , Mel Gorman , linux-fsdevel@vger.kernel.org Subject: [Patch V2] proc: check error pointer returned by m_start() Date: Mon, 28 Mar 2011 13:26:33 +0800 Message-Id: <1301289993-24248-1-git-send-email-amwang@redhat.com> In-Reply-To: References: Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 2370 Lines: 72 From: WANG Cong V2: move the check into m_stop() as suggested by Linus, also, most ->show() implementations assume the second parameter 'v' is not NULL, this fixes them too. Anca reported a bug: [15117.080119] BUG: unable to handle kernel paging request at fffffffffffffff3 [15117.080152] IP: [] vma_stop+0x19/0x40 Linus did the initial analysis, and found this was caused by commit ec6fd8a4355c ("report errors in /proc/*/*map* sanely"), which replaces NULL with various ERR_PTR() cases. This is true, that commit changed the return value of m_start(), which will return an error pointer on failure, but Al forgot to check the error pointer in m_stop() which will be called when m_start() fails. This patches fixes it. Reported-by: Anca Emanuel Tested-by: Anca Emanuel Cc: Linus Torvalds Cc: Al Viro Signed-off-by: WANG Cong Signed-off-by: WANG Cong --- diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 7c708a4..8e59169 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -124,8 +124,10 @@ static void *m_start(struct seq_file *m, loff_t *pos) return ERR_PTR(-ESRCH); mm = mm_for_maps(priv->task); - if (!mm || IS_ERR(mm)) + if (IS_ERR_OR_NULL(mm)) { + put_task_struct(priv->task); return mm; + } down_read(&mm->mmap_sem); tail_vma = get_gate_vma(priv->task->mm); @@ -182,6 +184,8 @@ static void m_stop(struct seq_file *m, void *v) struct proc_maps_private *priv = m->private; struct vm_area_struct *vma = v; + if (IS_ERR_OR_NULL(v)) + return; vma_stop(priv, vma); if (priv->task) put_task_struct(priv->task); diff --git a/fs/seq_file.c b/fs/seq_file.c index 05d6b0e..e17d5e6 100644 --- a/fs/seq_file.c +++ b/fs/seq_file.c @@ -83,7 +83,7 @@ static int traverse(struct seq_file *m, loff_t offset) p = m->op->start(m, &index); while (p) { error = PTR_ERR(p); - if (IS_ERR(p)) + if (IS_ERR_OR_NULL(p)) break; error = m->op->show(m, p); if (error < 0) -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/