[patch 16/18] remap_file_pages protection support: avoid truncating COW PTEs

From: blaisorblade
Date: Fri Aug 26 2005 - 12:05:23 EST



From: Paolo 'Blaisorblade' Giarrusso <blaisorblade@xxxxxxxx>, Ingo Molnar <mingo@xxxxxxx>

This patch may or may not be wanted. I took this from the original Ingo's
patch and improved it, but probably we want to keep this bug. However, I'm not
sure of what Ingo wanted to do.

If on a private writable mapping we call remap_file_pages() without
altering the file offset or the protections, after writing on the page to
create a COW mapping, with this patch we refuse reinstalling the old page, as
we should.

However, I'm not sure there's a point for an app to do this.

It is possible that we return an error even if the present page is already the
same one; however, that shouldn't be a big problem. In fact, the main purpose
of supporting private VMAs in remap_file_pages is allowing mmap(MAP_PRIVATE |
MAP_POPULATE) to work, and for that case existing mappings have already been
cleared and this patch is unneeded.

Note that this patch *needs* testing on each existing arch - I already got
subtle failures on i386 and not on UML on this patch (I had forgot to test
pte_present(), and pte_file() returned true, because _PAGE_DIRTY and
_PAGE_FILE share the same slot).

Setting CONFIG_DEBUG_PRIVATE in the test-program provides a mean to test this.

Signed-off-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade@xxxxxxxx>
---

linux-2.6.git-paolo/mm/fremap.c | 19 +++++++++++++++++++
1 files changed, 19 insertions(+)

diff -puN mm/fremap.c~rfp-notrunc-priv-mappings mm/fremap.c
--- linux-2.6.git/mm/fremap.c~rfp-notrunc-priv-mappings 2005-08-24 20:57:34.000000000 +0200
+++ linux-2.6.git-paolo/mm/fremap.c 2005-08-24 20:57:34.000000000 +0200
@@ -94,6 +94,16 @@ int install_page(struct mm_struct *mm, s
if (!page->mapping || page->index >= size)
goto err_unlock;

+ /*
+ * On private (and thus uniform) mapping, we don't want to truncate COW
+ * page, so we can only override pte_none or pte_file PTEs, not swap or
+ * present ones.
+ */
+ err = -EEXIST;
+ if (unlikely(!(vma->vm_flags & VM_SHARED)) && (pte_present(*pte) ||
+ (!pte_none(*pte) && !pte_file(*pte))))
+ goto err_unlock;
+
zap_pte(mm, vma, addr, pte);

inc_mm_counter(mm,rss);
@@ -155,6 +165,15 @@ int install_file_pte(struct mm_struct *m
err = 0;
if (uniform && pte_none(*pte))
goto err_unlock;
+ /*
+ * On private (and thus uniform) mapping, we don't want to truncate COW
+ * page, so we can only override pte_none or pte_file PTEs, not swap or
+ * present ones.
+ */
+ err = -EEXIST;
+ if (unlikely(!(vma->vm_flags & VM_SHARED)) && (pte_present(*pte) ||
+ (!pte_none(*pte) && !pte_file(*pte))))
+ goto err_unlock;

err = 0;
zap_pte(mm, vma, addr, pte);
_
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/