drop patches applied upstream

This commit is contained in:
Fabian Grünbichler 2017-06-07 10:35:40 +02:00
parent f18d724f8c
commit 674abe87c8
7 changed files with 0 additions and 729 deletions

View File

@ -1,42 +0,0 @@
From e18cf144f49054fa79d43689accdd2766618953d Mon Sep 17 00:00:00 2001
From: Wei Yongjun <weiyongjun1@huawei.com>
Date: Mon, 24 Apr 2017 16:26:00 +0200
Subject: [PATCH 1/2] net_sched: nla_memdup_cookie() can be static
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1682368
Fixes the following sparse warning:
net/sched/act_api.c:532:5: warning:
symbol 'nla_memdup_cookie' was not declared. Should it be static?
Signed-off-by: Wei Yongjun <weiyongjun1@huawei.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
(cherry picked from commit 6f2e3f7d9785dacb358b48b44950182b5c13e4bc)
Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
Acked-by: Kamal Mostafa <kamal@canonical.com>
Acked-by: Seth Forshee <seth.forshee@canonical.com>
Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
---
net/sched/act_api.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index 501c42d..e336f30 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -532,7 +532,7 @@ int tcf_action_dump(struct sk_buff *skb, struct list_head *actions,
return err;
}
-int nla_memdup_cookie(struct tc_action *a, struct nlattr **tb)
+static int nla_memdup_cookie(struct tc_action *a, struct nlattr **tb)
{
a->act_cookie = kzalloc(sizeof(*a->act_cookie), GFP_KERNEL);
if (!a->act_cookie)
--
2.1.4

View File

@ -1,142 +0,0 @@
From 3fe083491bf6c688d34c6e300f14d775a5b8a443 Mon Sep 17 00:00:00 2001
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
Date: Mon, 24 Apr 2017 16:26:00 +0200
Subject: [PATCH 2/2] net sched actions: allocate act cookie early
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1682368
Policing filters do not use the TCA_ACT_* enum and the tb[]
nlattr array in tcf_action_init_1() doesn't get filled for
them so we should not try to look for a TCA_ACT_COOKIE
attribute in the then uninitialized array.
The error handling in cookie allocation then calls
tcf_hash_release() leading to invalid memory access later
on.
Additionally, if cookie allocation fails after an already
existing non-policing filter has successfully been changed,
tcf_action_release() should not be called, also we would
have to roll back the changes in the error handling, so
instead we now allocate the cookie early and assign it on
success at the end.
CVE-2017-7979
Fixes: 1045ba77a596 ("net sched actions: Add support for user cookies")
Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
(cherry picked from commit e0535ce58b92d7baf0b33284a6c4f8f0338f943e)
Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
Acked-by: Kamal Mostafa <kamal@canonical.com>
Acked-by: Seth Forshee <seth.forshee@canonical.com>
Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
---
net/sched/act_api.c | 55 +++++++++++++++++++++++++++++++----------------------
1 file changed, 32 insertions(+), 23 deletions(-)
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index e336f30..bdbc7a9 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -532,20 +532,20 @@ int tcf_action_dump(struct sk_buff *skb, struct list_head *actions,
return err;
}
-static int nla_memdup_cookie(struct tc_action *a, struct nlattr **tb)
+static struct tc_cookie *nla_memdup_cookie(struct nlattr **tb)
{
- a->act_cookie = kzalloc(sizeof(*a->act_cookie), GFP_KERNEL);
- if (!a->act_cookie)
- return -ENOMEM;
+ struct tc_cookie *c = kzalloc(sizeof(*c), GFP_KERNEL);
+ if (!c)
+ return NULL;
- a->act_cookie->data = nla_memdup(tb[TCA_ACT_COOKIE], GFP_KERNEL);
- if (!a->act_cookie->data) {
- kfree(a->act_cookie);
- return -ENOMEM;
+ c->data = nla_memdup(tb[TCA_ACT_COOKIE], GFP_KERNEL);
+ if (!c->data) {
+ kfree(c);
+ return NULL;
}
- a->act_cookie->len = nla_len(tb[TCA_ACT_COOKIE]);
+ c->len = nla_len(tb[TCA_ACT_COOKIE]);
- return 0;
+ return c;
}
struct tc_action *tcf_action_init_1(struct net *net, struct nlattr *nla,
@@ -554,6 +554,7 @@ struct tc_action *tcf_action_init_1(struct net *net, struct nlattr *nla,
{
struct tc_action *a;
struct tc_action_ops *a_o;
+ struct tc_cookie *cookie = NULL;
char act_name[IFNAMSIZ];
struct nlattr *tb[TCA_ACT_MAX + 1];
struct nlattr *kind;
@@ -569,6 +570,18 @@ struct tc_action *tcf_action_init_1(struct net *net, struct nlattr *nla,
goto err_out;
if (nla_strlcpy(act_name, kind, IFNAMSIZ) >= IFNAMSIZ)
goto err_out;
+ if (tb[TCA_ACT_COOKIE]) {
+ int cklen = nla_len(tb[TCA_ACT_COOKIE]);
+
+ if (cklen > TC_COOKIE_MAX_SIZE)
+ goto err_out;
+
+ cookie = nla_memdup_cookie(tb);
+ if (!cookie) {
+ err = -ENOMEM;
+ goto err_out;
+ }
+ }
} else {
err = -EINVAL;
if (strlcpy(act_name, name, IFNAMSIZ) >= IFNAMSIZ)
@@ -607,20 +620,12 @@ struct tc_action *tcf_action_init_1(struct net *net, struct nlattr *nla,
if (err < 0)
goto err_mod;
- if (tb[TCA_ACT_COOKIE]) {
- int cklen = nla_len(tb[TCA_ACT_COOKIE]);
-
- if (cklen > TC_COOKIE_MAX_SIZE) {
- err = -EINVAL;
- tcf_hash_release(a, bind);
- goto err_mod;
- }
-
- if (nla_memdup_cookie(a, tb) < 0) {
- err = -ENOMEM;
- tcf_hash_release(a, bind);
- goto err_mod;
+ if (name == NULL && tb[TCA_ACT_COOKIE]) {
+ if (a->act_cookie) {
+ kfree(a->act_cookie->data);
+ kfree(a->act_cookie);
}
+ a->act_cookie = cookie;
}
/* module count goes up only when brand new policy is created
@@ -635,6 +640,10 @@ struct tc_action *tcf_action_init_1(struct net *net, struct nlattr *nla,
err_mod:
module_put(a_o->owner);
err_out:
+ if (cookie) {
+ kfree(cookie->data);
+ kfree(cookie);
+ }
return ERR_PTR(err);
}
--
2.1.4

View File

@ -234,12 +234,6 @@ ${KERNEL_SRC}/README ${KERNEL_CFG_ORG}: ${KERNEL_SRC_SUBMODULE} | submodules
cd ${KERNEL_SRC}; patch -p1 < ../kvm-dynamic-halt-polling-disable-default.patch cd ${KERNEL_SRC}; patch -p1 < ../kvm-dynamic-halt-polling-disable-default.patch
cd ${KERNEL_SRC}; patch -p1 < ../cgroup-cpuset-add-cpuset.remap_cpus.patch cd ${KERNEL_SRC}; patch -p1 < ../cgroup-cpuset-add-cpuset.remap_cpus.patch
cd ${KERNEL_SRC}; patch -p1 < ../openvswitch-Set-internal-device-max-mtu-to-ETH_MAX_M.patch cd ${KERNEL_SRC}; patch -p1 < ../openvswitch-Set-internal-device-max-mtu-to-ETH_MAX_M.patch
cd ${KERNEL_SRC}; patch -p1 < ../CVE-2017-7979-0001-net_sched-nla_memdup_cookie-can-be-static.patch
cd ${KERNEL_SRC}; patch -p1 < ../CVE-2017-7979-0002-net-sched-actions-allocate-act-cookie-early.patch
cd ${KERNEL_SRC}; patch -p1 < ../swapops-0001-Revert-mm-ksm-handle-protnone-saved-writes-when-maki.patch
cd ${KERNEL_SRC}; patch -p1 < ../swapops-0002-Revert-mm-ksm-convert-write_protect_page-to-use-page.patch
cd ${KERNEL_SRC}; patch -p1 < ../swapops-0003-Revert-mm-introduce-page_vma_mapped_walk.patch
cd ${KERNEL_SRC}; patch -p1 < ../swapops-0004-mm-ksm-handle-protnone-saved-writes-when-making-page.patch
cd ${KERNEL_SRC}; patch -p1 < ../0001-netfilter-nft_set_rbtree-handle-re-addition-element-.patch # DoS from within (unpriv) containers cd ${KERNEL_SRC}; patch -p1 < ../0001-netfilter-nft_set_rbtree-handle-re-addition-element-.patch # DoS from within (unpriv) containers
sed -i ${KERNEL_SRC}/Makefile -e 's/^EXTRAVERSION.*$$/EXTRAVERSION=${EXTRAVERSION}/' sed -i ${KERNEL_SRC}/Makefile -e 's/^EXTRAVERSION.*$$/EXTRAVERSION=${EXTRAVERSION}/'
touch $@ touch $@

View File

@ -1,70 +0,0 @@
From b4cf3c107f8f1d2da2b606e9d08e241be7000d65 Mon Sep 17 00:00:00 2001
From: Seth Forshee <seth.forshee@canonical.com>
Date: Wed, 3 May 2017 08:34:47 -0500
Subject: [PATCH 1/4] Revert "mm/ksm: handle protnone saved writes when making
page write protect"
This reverts commit c228a1037cd6bd0064472ea282e3730a342d6fca.
Signed-off-by: Seth Forshee <seth.forshee@canonical.com>
---
include/asm-generic/pgtable.h | 8 --------
mm/ksm.c | 9 ++-------
2 files changed, 2 insertions(+), 15 deletions(-)
diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h
index 8c8ba48bef0b..b6f3a8a4b738 100644
--- a/include/asm-generic/pgtable.h
+++ b/include/asm-generic/pgtable.h
@@ -200,10 +200,6 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addres
#define pte_mk_savedwrite pte_mkwrite
#endif
-#ifndef pte_clear_savedwrite
-#define pte_clear_savedwrite pte_wrprotect
-#endif
-
#ifndef pmd_savedwrite
#define pmd_savedwrite pmd_write
#endif
@@ -212,10 +208,6 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addres
#define pmd_mk_savedwrite pmd_mkwrite
#endif
-#ifndef pmd_clear_savedwrite
-#define pmd_clear_savedwrite pmd_wrprotect
-#endif
-
#ifndef __HAVE_ARCH_PMDP_SET_WRPROTECT
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
static inline void pmdp_set_wrprotect(struct mm_struct *mm,
diff --git a/mm/ksm.c b/mm/ksm.c
index abc05187168a..9dd2e58fb6dc 100644
--- a/mm/ksm.c
+++ b/mm/ksm.c
@@ -880,8 +880,7 @@ static int write_protect_page(struct vm_area_struct *vma, struct page *page,
if (WARN_ONCE(!pvmw.pte, "Unexpected PMD mapping?"))
goto out_unlock;
- if (pte_write(*pvmw.pte) || pte_dirty(*pvmw.pte) ||
- (pte_protnone(*pvmw.pte) && pte_savedwrite(*pvmw.pte))) {
+ if (pte_write(*pvmw.pte) || pte_dirty(*pvmw.pte)) {
pte_t entry;
swapped = PageSwapCache(page);
@@ -906,11 +905,7 @@ static int write_protect_page(struct vm_area_struct *vma, struct page *page,
}
if (pte_dirty(entry))
set_page_dirty(page);
-
- if (pte_protnone(entry))
- entry = pte_mkclean(pte_clear_savedwrite(entry));
- else
- entry = pte_mkclean(pte_wrprotect(entry));
+ entry = pte_mkclean(pte_wrprotect(entry));
set_pte_at_notify(mm, pvmw.address, pvmw.pte, entry);
}
*orig_pte = *pvmw.pte;
--
2.7.4

View File

@ -1,98 +0,0 @@
From 40e1fa51bc8aa3df1d3a23711b5de62d8251bff5 Mon Sep 17 00:00:00 2001
From: Seth Forshee <seth.forshee@canonical.com>
Date: Wed, 3 May 2017 08:34:52 -0500
Subject: [PATCH 2/4] Revert "mm, ksm: convert write_protect_page() to use
page_vma_mapped_walk()"
This reverts commit 3000e033152a70fa139765b4dbb5baec46b1cc1b.
Signed-off-by: Seth Forshee <seth.forshee@canonical.com>
---
mm/ksm.c | 34 ++++++++++++++++------------------
1 file changed, 16 insertions(+), 18 deletions(-)
diff --git a/mm/ksm.c b/mm/ksm.c
index 9dd2e58fb6dc..fed4afd8293b 100644
--- a/mm/ksm.c
+++ b/mm/ksm.c
@@ -856,35 +856,33 @@ static int write_protect_page(struct vm_area_struct *vma, struct page *page,
pte_t *orig_pte)
{
struct mm_struct *mm = vma->vm_mm;
- struct page_vma_mapped_walk pvmw = {
- .page = page,
- .vma = vma,
- };
+ unsigned long addr;
+ pte_t *ptep;
+ spinlock_t *ptl;
int swapped;
int err = -EFAULT;
unsigned long mmun_start; /* For mmu_notifiers */
unsigned long mmun_end; /* For mmu_notifiers */
- pvmw.address = page_address_in_vma(page, vma);
- if (pvmw.address == -EFAULT)
+ addr = page_address_in_vma(page, vma);
+ if (addr == -EFAULT)
goto out;
BUG_ON(PageTransCompound(page));
- mmun_start = pvmw.address;
- mmun_end = pvmw.address + PAGE_SIZE;
+ mmun_start = addr;
+ mmun_end = addr + PAGE_SIZE;
mmu_notifier_invalidate_range_start(mm, mmun_start, mmun_end);
- if (!page_vma_mapped_walk(&pvmw))
+ ptep = page_check_address(page, mm, addr, &ptl, 0);
+ if (!ptep)
goto out_mn;
- if (WARN_ONCE(!pvmw.pte, "Unexpected PMD mapping?"))
- goto out_unlock;
- if (pte_write(*pvmw.pte) || pte_dirty(*pvmw.pte)) {
+ if (pte_write(*ptep) || pte_dirty(*ptep)) {
pte_t entry;
swapped = PageSwapCache(page);
- flush_cache_page(vma, pvmw.address, page_to_pfn(page));
+ flush_cache_page(vma, addr, page_to_pfn(page));
/*
* Ok this is tricky, when get_user_pages_fast() run it doesn't
* take any lock, therefore the check that we are going to make
@@ -894,25 +892,25 @@ static int write_protect_page(struct vm_area_struct *vma, struct page *page,
* this assure us that no O_DIRECT can happen after the check
* or in the middle of the check.
*/
- entry = ptep_clear_flush_notify(vma, pvmw.address, pvmw.pte);
+ entry = ptep_clear_flush_notify(vma, addr, ptep);
/*
* Check that no O_DIRECT or similar I/O is in progress on the
* page
*/
if (page_mapcount(page) + 1 + swapped != page_count(page)) {
- set_pte_at(mm, pvmw.address, pvmw.pte, entry);
+ set_pte_at(mm, addr, ptep, entry);
goto out_unlock;
}
if (pte_dirty(entry))
set_page_dirty(page);
entry = pte_mkclean(pte_wrprotect(entry));
- set_pte_at_notify(mm, pvmw.address, pvmw.pte, entry);
+ set_pte_at_notify(mm, addr, ptep, entry);
}
- *orig_pte = *pvmw.pte;
+ *orig_pte = *ptep;
err = 0;
out_unlock:
- page_vma_mapped_walk_done(&pvmw);
+ pte_unmap_unlock(ptep, ptl);
out_mn:
mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end);
out:
--
2.7.4

View File

@ -1,294 +0,0 @@
From 47a3e75a6d3db759a5fce3e922f144af0d6f1d38 Mon Sep 17 00:00:00 2001
From: Seth Forshee <seth.forshee@canonical.com>
Date: Wed, 3 May 2017 08:34:56 -0500
Subject: [PATCH 3/4] Revert "mm: introduce page_vma_mapped_walk()"
This reverts commit 6e2a092a48d38cfc0f06bdb523014acbfeba7b2e.
Signed-off-by: Seth Forshee <seth.forshee@canonical.com>
---
include/linux/rmap.h | 26 -------
mm/Makefile | 6 +-
mm/huge_memory.c | 9 +--
mm/page_vma_mapped.c | 188 ---------------------------------------------------
4 files changed, 5 insertions(+), 224 deletions(-)
delete mode 100644 mm/page_vma_mapped.c
diff --git a/include/linux/rmap.h b/include/linux/rmap.h
index b76343610653..15321fb1df6b 100644
--- a/include/linux/rmap.h
+++ b/include/linux/rmap.h
@@ -9,7 +9,6 @@
#include <linux/mm.h>
#include <linux/rwsem.h>
#include <linux/memcontrol.h>
-#include <linux/highmem.h>
/*
* The anon_vma heads a list of private "related" vmas, to scan if
@@ -233,31 +232,6 @@ static inline bool page_check_address_transhuge(struct page *page,
}
#endif
-/* Avoid racy checks */
-#define PVMW_SYNC (1 << 0)
-/* Look for migarion entries rather than present PTEs */
-#define PVMW_MIGRATION (1 << 1)
-
-struct page_vma_mapped_walk {
- struct page *page;
- struct vm_area_struct *vma;
- unsigned long address;
- pmd_t *pmd;
- pte_t *pte;
- spinlock_t *ptl;
- unsigned int flags;
-};
-
-static inline void page_vma_mapped_walk_done(struct page_vma_mapped_walk *pvmw)
-{
- if (pvmw->pte)
- pte_unmap(pvmw->pte);
- if (pvmw->ptl)
- spin_unlock(pvmw->ptl);
-}
-
-bool page_vma_mapped_walk(struct page_vma_mapped_walk *pvmw);
-
/*
* Used by swapoff to help locate where page is expected in vma.
*/
diff --git a/mm/Makefile b/mm/Makefile
index 474fa3431059..14fa1c83b504 100644
--- a/mm/Makefile
+++ b/mm/Makefile
@@ -23,10 +23,8 @@ KCOV_INSTRUMENT_vmstat.o := n
mmu-y := nommu.o
mmu-$(CONFIG_MMU) := gup.o highmem.o memory.o mincore.o \
- mlock.o mmap.o mprotect.o mremap.o msync.o \
- page_vma_mapped.o pagewalk.o pgtable-generic.o \
- rmap.o vmalloc.o
-
+ mlock.o mmap.o mprotect.o mremap.o msync.o rmap.o \
+ vmalloc.o pagewalk.o pgtable-generic.o
ifdef CONFIG_CROSS_MEMORY_ATTACH
mmu-$(CONFIG_MMU) += process_vm_access.o
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index 87303c6bacf4..e6de801fa477 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -1878,12 +1878,9 @@ static void freeze_page(struct page *page)
static void unfreeze_page(struct page *page)
{
int i;
- if (PageTransHuge(page)) {
- remove_migration_ptes(page, page, true);
- } else {
- for (i = 0; i < HPAGE_PMD_NR; i++)
- remove_migration_ptes(page + i, page + i, true);
- }
+
+ for (i = 0; i < HPAGE_PMD_NR; i++)
+ remove_migration_ptes(page + i, page + i, true);
}
static void __split_huge_page_tail(struct page *head, int tail,
diff --git a/mm/page_vma_mapped.c b/mm/page_vma_mapped.c
deleted file mode 100644
index dc1a54826cf2..000000000000
--- a/mm/page_vma_mapped.c
+++ /dev/null
@@ -1,188 +0,0 @@
-#include <linux/mm.h>
-#include <linux/rmap.h>
-#include <linux/hugetlb.h>
-#include <linux/swap.h>
-#include <linux/swapops.h>
-
-#include "internal.h"
-
-static inline bool check_pmd(struct page_vma_mapped_walk *pvmw)
-{
- pmd_t pmde;
- /*
- * Make sure we don't re-load pmd between present and !trans_huge check.
- * We need a consistent view.
- */
- pmde = READ_ONCE(*pvmw->pmd);
- return pmd_present(pmde) && !pmd_trans_huge(pmde);
-}
-
-static inline bool not_found(struct page_vma_mapped_walk *pvmw)
-{
- page_vma_mapped_walk_done(pvmw);
- return false;
-}
-
-static bool map_pte(struct page_vma_mapped_walk *pvmw)
-{
- pvmw->pte = pte_offset_map(pvmw->pmd, pvmw->address);
- if (!(pvmw->flags & PVMW_SYNC)) {
- if (pvmw->flags & PVMW_MIGRATION) {
- if (!is_swap_pte(*pvmw->pte))
- return false;
- } else {
- if (!pte_present(*pvmw->pte))
- return false;
- }
- }
- pvmw->ptl = pte_lockptr(pvmw->vma->vm_mm, pvmw->pmd);
- spin_lock(pvmw->ptl);
- return true;
-}
-
-static bool check_pte(struct page_vma_mapped_walk *pvmw)
-{
- if (pvmw->flags & PVMW_MIGRATION) {
-#ifdef CONFIG_MIGRATION
- swp_entry_t entry;
- if (!is_swap_pte(*pvmw->pte))
- return false;
- entry = pte_to_swp_entry(*pvmw->pte);
- if (!is_migration_entry(entry))
- return false;
- if (migration_entry_to_page(entry) - pvmw->page >=
- hpage_nr_pages(pvmw->page)) {
- return false;
- }
- if (migration_entry_to_page(entry) < pvmw->page)
- return false;
-#else
- WARN_ON_ONCE(1);
-#endif
- } else {
- if (!pte_present(*pvmw->pte))
- return false;
-
- /* THP can be referenced by any subpage */
- if (pte_page(*pvmw->pte) - pvmw->page >=
- hpage_nr_pages(pvmw->page)) {
- return false;
- }
- if (pte_page(*pvmw->pte) < pvmw->page)
- return false;
- }
-
- return true;
-}
-
-/**
- * page_vma_mapped_walk - check if @pvmw->page is mapped in @pvmw->vma at
- * @pvmw->address
- * @pvmw: pointer to struct page_vma_mapped_walk. page, vma, address and flags
- * must be set. pmd, pte and ptl must be NULL.
- *
- * Returns true if the page is mapped in the vma. @pvmw->pmd and @pvmw->pte point
- * to relevant page table entries. @pvmw->ptl is locked. @pvmw->address is
- * adjusted if needed (for PTE-mapped THPs).
- *
- * If @pvmw->pmd is set but @pvmw->pte is not, you have found PMD-mapped page
- * (usually THP). For PTE-mapped THP, you should run page_vma_mapped_walk() in
- * a loop to find all PTEs that map the THP.
- *
- * For HugeTLB pages, @pvmw->pte is set to the relevant page table entry
- * regardless of which page table level the page is mapped at. @pvmw->pmd is
- * NULL.
- *
- * Retruns false if there are no more page table entries for the page in
- * the vma. @pvmw->ptl is unlocked and @pvmw->pte is unmapped.
- *
- * If you need to stop the walk before page_vma_mapped_walk() returned false,
- * use page_vma_mapped_walk_done(). It will do the housekeeping.
- */
-bool page_vma_mapped_walk(struct page_vma_mapped_walk *pvmw)
-{
- struct mm_struct *mm = pvmw->vma->vm_mm;
- struct page *page = pvmw->page;
- pgd_t *pgd;
- pud_t *pud;
-
- /* The only possible pmd mapping has been handled on last iteration */
- if (pvmw->pmd && !pvmw->pte)
- return not_found(pvmw);
-
- /* Only for THP, seek to next pte entry makes sense */
- if (pvmw->pte) {
- if (!PageTransHuge(pvmw->page) || PageHuge(pvmw->page))
- return not_found(pvmw);
- goto next_pte;
- }
-
- if (unlikely(PageHuge(pvmw->page))) {
- /* when pud is not present, pte will be NULL */
- pvmw->pte = huge_pte_offset(mm, pvmw->address);
- if (!pvmw->pte)
- return false;
-
- pvmw->ptl = huge_pte_lockptr(page_hstate(page), mm, pvmw->pte);
- spin_lock(pvmw->ptl);
- if (!check_pte(pvmw))
- return not_found(pvmw);
- return true;
- }
-restart:
- pgd = pgd_offset(mm, pvmw->address);
- if (!pgd_present(*pgd))
- return false;
- pud = pud_offset(pgd, pvmw->address);
- if (!pud_present(*pud))
- return false;
- pvmw->pmd = pmd_offset(pud, pvmw->address);
- if (pmd_trans_huge(*pvmw->pmd)) {
- pvmw->ptl = pmd_lock(mm, pvmw->pmd);
- if (!pmd_present(*pvmw->pmd))
- return not_found(pvmw);
- if (likely(pmd_trans_huge(*pvmw->pmd))) {
- if (pvmw->flags & PVMW_MIGRATION)
- return not_found(pvmw);
- if (pmd_page(*pvmw->pmd) != page)
- return not_found(pvmw);
- return true;
- } else {
- /* THP pmd was split under us: handle on pte level */
- spin_unlock(pvmw->ptl);
- pvmw->ptl = NULL;
- }
- } else {
- if (!check_pmd(pvmw))
- return false;
- }
- if (!map_pte(pvmw))
- goto next_pte;
- while (1) {
- if (check_pte(pvmw))
- return true;
-next_pte: do {
- pvmw->address += PAGE_SIZE;
- if (pvmw->address >=
- __vma_address(pvmw->page, pvmw->vma) +
- hpage_nr_pages(pvmw->page) * PAGE_SIZE)
- return not_found(pvmw);
- /* Did we cross page table boundary? */
- if (pvmw->address % PMD_SIZE == 0) {
- pte_unmap(pvmw->pte);
- if (pvmw->ptl) {
- spin_unlock(pvmw->ptl);
- pvmw->ptl = NULL;
- }
- goto restart;
- } else {
- pvmw->pte++;
- }
- } while (pte_none(*pvmw->pte));
-
- if (!pvmw->ptl) {
- pvmw->ptl = pte_lockptr(mm, pvmw->pmd);
- spin_lock(pvmw->ptl);
- }
- }
-}
--
2.7.4

View File

@ -1,77 +0,0 @@
From 361de9fb44163c4e693022786af380a2b2298c6d Mon Sep 17 00:00:00 2001
From: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com>
Date: Fri, 24 Feb 2017 14:59:19 -0800
Subject: [PATCH 4/4] mm/ksm: handle protnone saved writes when making page
write protect
Without this KSM will consider the page write protected, but a numa
fault can later mark the page writable. This can result in memory
corruption.
Link: http://lkml.kernel.org/r/1487498625-10891-3-git-send-email-aneesh.kumar@linux.vnet.ibm.com
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
(backported from commit 595cd8f256d24face93b2722927ec9c980419c26)
Signed-off-by: Seth Forshee <seth.forshee@canonical.com>
---
include/asm-generic/pgtable.h | 8 ++++++++
mm/ksm.c | 9 +++++++--
2 files changed, 15 insertions(+), 2 deletions(-)
diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h
index b6f3a8a4b738..8c8ba48bef0b 100644
--- a/include/asm-generic/pgtable.h
+++ b/include/asm-generic/pgtable.h
@@ -200,6 +200,10 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addres
#define pte_mk_savedwrite pte_mkwrite
#endif
+#ifndef pte_clear_savedwrite
+#define pte_clear_savedwrite pte_wrprotect
+#endif
+
#ifndef pmd_savedwrite
#define pmd_savedwrite pmd_write
#endif
@@ -208,6 +212,10 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addres
#define pmd_mk_savedwrite pmd_mkwrite
#endif
+#ifndef pmd_clear_savedwrite
+#define pmd_clear_savedwrite pmd_wrprotect
+#endif
+
#ifndef __HAVE_ARCH_PMDP_SET_WRPROTECT
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
static inline void pmdp_set_wrprotect(struct mm_struct *mm,
diff --git a/mm/ksm.c b/mm/ksm.c
index fed4afd8293b..099dfa45d596 100644
--- a/mm/ksm.c
+++ b/mm/ksm.c
@@ -878,7 +878,8 @@ static int write_protect_page(struct vm_area_struct *vma, struct page *page,
if (!ptep)
goto out_mn;
- if (pte_write(*ptep) || pte_dirty(*ptep)) {
+ if (pte_write(*ptep) || pte_dirty(*ptep) ||
+ (pte_protnone(*ptep) && pte_savedwrite(*ptep))) {
pte_t entry;
swapped = PageSwapCache(page);
@@ -903,7 +904,11 @@ static int write_protect_page(struct vm_area_struct *vma, struct page *page,
}
if (pte_dirty(entry))
set_page_dirty(page);
- entry = pte_mkclean(pte_wrprotect(entry));
+
+ if (pte_protnone(entry))
+ entry = pte_mkclean(pte_clear_savedwrite(entry));
+ else
+ entry = pte_mkclean(pte_wrprotect(entry));
set_pte_at_notify(mm, addr, ptep, entry);
}
*orig_pte = *ptep;
--
2.7.4