| From 85e72aa5384b1a614563ad63257ded0e91d1a620 Mon Sep 17 00:00:00 2001 |
| From: Will Deacon <will.deacon@arm.com> |
| Date: Fri, 20 Jan 2012 14:34:09 -0800 |
| Subject: proc: clear_refs: do not clear reserved pages |
| |
| From: Will Deacon <will.deacon@arm.com> |
| |
| commit 85e72aa5384b1a614563ad63257ded0e91d1a620 upstream. |
| |
| /proc/pid/clear_refs is used to clear the Referenced and YOUNG bits for |
| pages and corresponding page table entries of the task with PID pid, which |
| includes any special mappings inserted into the page tables in order to |
| provide things like vDSOs and user helper functions. |
| |
| On ARM this causes a problem because the vectors page is mapped as a |
| global mapping and since ec706dab ("ARM: add a vma entry for the user |
| accessible vector page"), a VMA is also inserted into each task for this |
| page to aid unwinding through signals and syscall restarts. Since the |
| vectors page is required for handling faults, clearing the YOUNG bit (and |
| subsequently writing a faulting pte) means that we lose the vectors page |
| *globally* and cannot fault it back in. This results in a system deadlock |
| on the next exception. |
| |
| To see this problem in action, just run: |
| |
| $ echo 1 > /proc/self/clear_refs |
| |
| on an ARM platform (as any user) and watch your system hang. I think this |
| has been the case since 2.6.37 |
| |
| This patch avoids clearing the aforementioned bits for reserved pages, |
| therefore leaving the vectors page intact on ARM. Since reserved pages |
| are not candidates for swap, this change should not have any impact on the |
| usefulness of clear_refs. |
| |
| Signed-off-by: Will Deacon <will.deacon@arm.com> |
| Reported-by: Moussa Ba <moussaba@micron.com> |
| Acked-by: Hugh Dickins <hughd@google.com> |
| Cc: David Rientjes <rientjes@google.com> |
| Cc: Russell King <rmk@arm.linux.org.uk> |
| Acked-by: Nicolas Pitre <nico@linaro.org> |
| Cc: Matt Mackall <mpm@selenic.com> |
| Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
| Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| |
| --- |
| fs/proc/task_mmu.c | 3 +++ |
| 1 file changed, 3 insertions(+) |
| |
| --- a/fs/proc/task_mmu.c |
| +++ b/fs/proc/task_mmu.c |
| @@ -518,6 +518,9 @@ static int clear_refs_pte_range(pmd_t *p |
| if (!page) |
| continue; |
| |
| + if (PageReserved(page)) |
| + continue; |
| + |
| /* Clear accessed and referenced bits. */ |
| ptep_test_and_clear_young(vma, addr, pte); |
| ClearPageReferenced(page); |