]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
more .25 patches
authorGreg Kroah-Hartman <gregkh@suse.de>
Sun, 22 Jun 2008 05:54:32 +0000 (22:54 -0700)
committerGreg Kroah-Hartman <gregkh@suse.de>
Sun, 22 Jun 2008 05:54:32 +0000 (22:54 -0700)
queue-2.6.25/reinstate-zero_page-optimization-in-get_user_pages-and-fix-xip.patch [new file with mode: 0644]
queue-2.6.25/sctp-make-sure-n-sizeof-does-not-overflow.patch [new file with mode: 0644]
queue-2.6.25/series [new file with mode: 0644]

diff --git a/queue-2.6.25/reinstate-zero_page-optimization-in-get_user_pages-and-fix-xip.patch b/queue-2.6.25/reinstate-zero_page-optimization-in-get_user_pages-and-fix-xip.patch
new file mode 100644 (file)
index 0000000..9425d06
--- /dev/null
@@ -0,0 +1,139 @@
+From 89f5b7da2a6bad2e84670422ab8192382a5aeb9f Mon Sep 17 00:00:00 2001
+From: Linus Torvalds <torvalds@linux-foundation.org>
+Date: Fri, 20 Jun 2008 11:18:25 -0700
+Subject: [PATCH] Reinstate ZERO_PAGE optimization in 'get_user_pages()' and fix XIP
+
+From: Linus Torvalds <torvalds@linux-foundation.org>
+
+commit 89f5b7da2a6bad2e84670422ab8192382a5aeb9f upstream
+
+KAMEZAWA Hiroyuki and Oleg Nesterov point out that since the commit
+557ed1fa2620dc119adb86b34c614e152a629a80 ("remove ZERO_PAGE") removed
+the ZERO_PAGE from the VM mappings, any users of get_user_pages() will
+generally now populate the VM with real empty pages needlessly.
+
+We used to get the ZERO_PAGE when we did the "handle_mm_fault()", but
+since fault handling no longer uses ZERO_PAGE for new anonymous pages,
+we now need to handle that special case in follow_page() instead.
+
+In particular, the removal of ZERO_PAGE effectively removed the core
+file writing optimization where we would skip writing pages that had not
+been populated at all, and increased memory pressure a lot by allocating
+all those useless newly zeroed pages.
+
+This reinstates the optimization by making the unmapped PTE case the
+same as for a non-existent page table, which already did this correctly.
+
+While at it, this also fixes the XIP case for follow_page(), where the
+caller could not differentiate between the case of a page that simply
+could not be used (because it had no "struct page" associated with it)
+and a page that just wasn't mapped.
+
+We do that by simply returning an error pointer for pages that could not
+be turned into a "struct page *".  The error is arbitrarily picked to be
+EFAULT, since that was what get_user_pages() already used for the
+equivalent IO-mapped page case.
+
+[ Also removed an impossible test for pte_offset_map_lock() failing:
+  that's not how that function works ]
+
+Acked-by: Oleg Nesterov <oleg@tv-sign.ru>
+Acked-by: Nick Piggin <npiggin@suse.de>
+Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
+Cc: Hugh Dickins <hugh@veritas.com>
+Cc: Andrew Morton <akpm@linux-foundation.org>
+Cc: Ingo Molnar <mingo@elte.hu>
+Cc: Roland McGrath <roland@redhat.com>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ arch/powerpc/kernel/vdso.c |    2 +-
+ mm/memory.c                |   17 +++++++++++++----
+ mm/migrate.c               |   10 ++++++++++
+ 3 files changed, 24 insertions(+), 5 deletions(-)
+
+--- a/arch/powerpc/kernel/vdso.c
++++ b/arch/powerpc/kernel/vdso.c
+@@ -141,7 +141,7 @@ static void dump_one_vdso_page(struct pa
+       printk("kpg: %p (c:%d,f:%08lx)", __va(page_to_pfn(pg) << PAGE_SHIFT),
+              page_count(pg),
+              pg->flags);
+-      if (upg/* && pg != upg*/) {
++      if (upg && !IS_ERR(upg) /* && pg != upg*/) {
+               printk(" upg: %p (c:%d,f:%08lx)", __va(page_to_pfn(upg)
+                                                      << PAGE_SHIFT),
+                      page_count(upg),
+--- a/mm/memory.c
++++ b/mm/memory.c
+@@ -943,17 +943,15 @@ struct page *follow_page(struct vm_area_
+       }
+       ptep = pte_offset_map_lock(mm, pmd, address, &ptl);
+-      if (!ptep)
+-              goto out;
+       pte = *ptep;
+       if (!pte_present(pte))
+-              goto unlock;
++              goto no_page;
+       if ((flags & FOLL_WRITE) && !pte_write(pte))
+               goto unlock;
+       page = vm_normal_page(vma, address, pte);
+       if (unlikely(!page))
+-              goto unlock;
++              goto bad_page;
+       if (flags & FOLL_GET)
+               get_page(page);
+@@ -968,6 +966,15 @@ unlock:
+ out:
+       return page;
++bad_page:
++      pte_unmap_unlock(ptep, ptl);
++      return ERR_PTR(-EFAULT);
++
++no_page:
++      pte_unmap_unlock(ptep, ptl);
++      if (!pte_none(pte))
++              return page;
++      /* Fall through to ZERO_PAGE handling */
+ no_page_table:
+       /*
+        * When core dumping an enormous anonymous area that nobody
+@@ -1104,6 +1111,8 @@ int get_user_pages(struct task_struct *t
+                               cond_resched();
+                       }
++                      if (IS_ERR(page))
++                              return i ? i : PTR_ERR(page);
+                       if (pages) {
+                               pages[i] = page;
+--- a/mm/migrate.c
++++ b/mm/migrate.c
+@@ -858,6 +858,11 @@ static int do_move_pages(struct mm_struc
+                       goto set_status;
+               page = follow_page(vma, pp->addr, FOLL_GET);
++
++              err = PTR_ERR(page);
++              if (IS_ERR(page))
++                      goto set_status;
++
+               err = -ENOENT;
+               if (!page)
+                       goto set_status;
+@@ -921,6 +926,11 @@ static int do_pages_stat(struct mm_struc
+                       goto set_status;
+               page = follow_page(vma, pm->addr, 0);
++
++              err = PTR_ERR(page);
++              if (IS_ERR(page))
++                      goto set_status;
++
+               err = -ENOENT;
+               /* Use PageReserved to check for zero page */
+               if (!page || PageReserved(page))
diff --git a/queue-2.6.25/sctp-make-sure-n-sizeof-does-not-overflow.patch b/queue-2.6.25/sctp-make-sure-n-sizeof-does-not-overflow.patch
new file mode 100644 (file)
index 0000000..f6d2b81
--- /dev/null
@@ -0,0 +1,35 @@
+From 735ce972fbc8a65fb17788debd7bbe7b4383cc62 Mon Sep 17 00:00:00 2001
+From: David S. Miller <davem@davemloft.net>
+Date: Fri, 20 Jun 2008 22:04:34 -0700
+Subject: sctp: Make sure N * sizeof(union sctp_addr) does not overflow.
+
+From: David S. Miller <davem@davemloft.net>
+
+commit 735ce972fbc8a65fb17788debd7bbe7b4383cc62 upstream
+
+As noticed by Gabriel Campana, the kmalloc() length arg
+passed in by sctp_getsockopt_local_addrs_old() can overflow
+if ->addr_num is large enough.
+
+Therefore, enforce an appropriate limit.
+
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ net/sctp/socket.c |    4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/net/sctp/socket.c
++++ b/net/sctp/socket.c
+@@ -4421,7 +4421,9 @@ static int sctp_getsockopt_local_addrs_o
+       if (copy_from_user(&getaddrs, optval, len))
+               return -EFAULT;
+-      if (getaddrs.addr_num <= 0) return -EINVAL;
++      if (getaddrs.addr_num <= 0 ||
++          getaddrs.addr_num >= (INT_MAX / sizeof(union sctp_addr)))
++              return -EINVAL;
+       /*
+        *  For UDP-style sockets, id specifies the association to query.
+        *  If the id field is set to the value '0' then the locally bound
diff --git a/queue-2.6.25/series b/queue-2.6.25/series
new file mode 100644 (file)
index 0000000..1f4d6bc
--- /dev/null
@@ -0,0 +1,2 @@
+reinstate-zero_page-optimization-in-get_user_pages-and-fix-xip.patch
+sctp-make-sure-n-sizeof-does-not-overflow.patch