Merge branch 'akpm' (patches from Andrew)
Merge misc updates from Andrew Morton: - large KASAN update to use arm's "software tag-based mode" - a few misc things - sh updates - ocfs2 updates - just about all of MM * emailed patches from Andrew Morton <akpm@linux-foundation.org>: (167 commits) kernel/fork.c: mark 'stack_vm_area' with __maybe_unused memcg, oom: notify on oom killer invocation from the charge path mm, swap: fix swapoff with KSM pages include/linux/gfp.h: fix typo mm/hmm: fix memremap.h, move dev_page_fault_t callback to hmm hugetlbfs: Use i_mmap_rwsem to fix page fault/truncate race hugetlbfs: use i_mmap_rwsem for more pmd sharing synchronization memory_hotplug: add missing newlines to debugging output mm: remove __hugepage_set_anon_rmap() include/linux/vmstat.h: remove unused page state adjustment macro mm/page_alloc.c: allow error injection mm: migrate: drop unused argument of migrate_page_move_mapping() blkdev: avoid migration stalls for blkdev pages mm: migrate: provide buffer_migrate_page_norefs() mm: migrate: move migrate_page_lock_buffers() mm: migrate: lock buffers before migrate_page_move_mapping() mm: migration: factor out code to compute expected number of page references mm, page_alloc: enable pcpu_drain with zone capability kmemleak: add config to select auto scan mm/page_alloc.c: don't call kasan_free_pages() at deferred mem init ...
This commit is contained in:
@@ -40,6 +40,7 @@
|
||||
#include <asm/daifflags.h>
|
||||
#include <asm/debug-monitors.h>
|
||||
#include <asm/esr.h>
|
||||
#include <asm/kasan.h>
|
||||
#include <asm/sysreg.h>
|
||||
#include <asm/system_misc.h>
|
||||
#include <asm/pgtable.h>
|
||||
@@ -132,6 +133,18 @@ static void mem_abort_decode(unsigned int esr)
|
||||
data_abort_decode(esr);
|
||||
}
|
||||
|
||||
static inline bool is_ttbr0_addr(unsigned long addr)
|
||||
{
|
||||
/* entry assembly clears tags for TTBR0 addrs */
|
||||
return addr < TASK_SIZE;
|
||||
}
|
||||
|
||||
static inline bool is_ttbr1_addr(unsigned long addr)
|
||||
{
|
||||
/* TTBR1 addresses may have a tag if KASAN_SW_TAGS is in use */
|
||||
return arch_kasan_reset_tag(addr) >= VA_START;
|
||||
}
|
||||
|
||||
/*
|
||||
* Dump out the page tables associated with 'addr' in the currently active mm.
|
||||
*/
|
||||
@@ -141,7 +154,7 @@ void show_pte(unsigned long addr)
|
||||
pgd_t *pgdp;
|
||||
pgd_t pgd;
|
||||
|
||||
if (addr < TASK_SIZE) {
|
||||
if (is_ttbr0_addr(addr)) {
|
||||
/* TTBR0 */
|
||||
mm = current->active_mm;
|
||||
if (mm == &init_mm) {
|
||||
@@ -149,7 +162,7 @@ void show_pte(unsigned long addr)
|
||||
addr);
|
||||
return;
|
||||
}
|
||||
} else if (addr >= VA_START) {
|
||||
} else if (is_ttbr1_addr(addr)) {
|
||||
/* TTBR1 */
|
||||
mm = &init_mm;
|
||||
} else {
|
||||
@@ -254,7 +267,7 @@ static inline bool is_el1_permission_fault(unsigned long addr, unsigned int esr,
|
||||
if (fsc_type == ESR_ELx_FSC_PERM)
|
||||
return true;
|
||||
|
||||
if (addr < TASK_SIZE && system_uses_ttbr0_pan())
|
||||
if (is_ttbr0_addr(addr) && system_uses_ttbr0_pan())
|
||||
return fsc_type == ESR_ELx_FSC_FAULT &&
|
||||
(regs->pstate & PSR_PAN_BIT);
|
||||
|
||||
@@ -319,7 +332,7 @@ static void set_thread_esr(unsigned long address, unsigned int esr)
|
||||
* type", so we ignore this wrinkle and just return the translation
|
||||
* fault.)
|
||||
*/
|
||||
if (current->thread.fault_address >= TASK_SIZE) {
|
||||
if (!is_ttbr0_addr(current->thread.fault_address)) {
|
||||
switch (ESR_ELx_EC(esr)) {
|
||||
case ESR_ELx_EC_DABT_LOW:
|
||||
/*
|
||||
@@ -455,7 +468,7 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr,
|
||||
mm_flags |= FAULT_FLAG_WRITE;
|
||||
}
|
||||
|
||||
if (addr < TASK_SIZE && is_el1_permission_fault(addr, esr, regs)) {
|
||||
if (is_ttbr0_addr(addr) && is_el1_permission_fault(addr, esr, regs)) {
|
||||
/* regs->orig_addr_limit may be 0 if we entered from EL0 */
|
||||
if (regs->orig_addr_limit == KERNEL_DS)
|
||||
die_kernel_fault("access to user memory with fs=KERNEL_DS",
|
||||
@@ -603,7 +616,7 @@ static int __kprobes do_translation_fault(unsigned long addr,
|
||||
unsigned int esr,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
if (addr < TASK_SIZE)
|
||||
if (is_ttbr0_addr(addr))
|
||||
return do_page_fault(addr, esr, regs);
|
||||
|
||||
do_bad_area(addr, esr, regs);
|
||||
@@ -758,7 +771,7 @@ asmlinkage void __exception do_el0_ia_bp_hardening(unsigned long addr,
|
||||
* re-enabled IRQs. If the address is a kernel address, apply
|
||||
* BP hardening prior to enabling IRQs and pre-emption.
|
||||
*/
|
||||
if (addr > TASK_SIZE)
|
||||
if (!is_ttbr0_addr(addr))
|
||||
arm64_apply_bp_hardening();
|
||||
|
||||
local_daif_restore(DAIF_PROCCTX);
|
||||
@@ -771,7 +784,7 @@ asmlinkage void __exception do_sp_pc_abort(unsigned long addr,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
if (user_mode(regs)) {
|
||||
if (instruction_pointer(regs) > TASK_SIZE)
|
||||
if (!is_ttbr0_addr(instruction_pointer(regs)))
|
||||
arm64_apply_bp_hardening();
|
||||
local_daif_restore(DAIF_PROCCTX);
|
||||
}
|
||||
@@ -825,7 +838,7 @@ asmlinkage int __exception do_debug_exception(unsigned long addr,
|
||||
if (interrupts_enabled(regs))
|
||||
trace_hardirqs_off();
|
||||
|
||||
if (user_mode(regs) && instruction_pointer(regs) > TASK_SIZE)
|
||||
if (user_mode(regs) && !is_ttbr0_addr(instruction_pointer(regs)))
|
||||
arm64_apply_bp_hardening();
|
||||
|
||||
if (!inf->fn(addr, esr, regs)) {
|
||||
|
@@ -39,7 +39,15 @@ static phys_addr_t __init kasan_alloc_zeroed_page(int node)
|
||||
{
|
||||
void *p = memblock_alloc_try_nid(PAGE_SIZE, PAGE_SIZE,
|
||||
__pa(MAX_DMA_ADDRESS),
|
||||
MEMBLOCK_ALLOC_ACCESSIBLE, node);
|
||||
MEMBLOCK_ALLOC_KASAN, node);
|
||||
return __pa(p);
|
||||
}
|
||||
|
||||
static phys_addr_t __init kasan_alloc_raw_page(int node)
|
||||
{
|
||||
void *p = memblock_alloc_try_nid_raw(PAGE_SIZE, PAGE_SIZE,
|
||||
__pa(MAX_DMA_ADDRESS),
|
||||
MEMBLOCK_ALLOC_KASAN, node);
|
||||
return __pa(p);
|
||||
}
|
||||
|
||||
@@ -47,8 +55,9 @@ static pte_t *__init kasan_pte_offset(pmd_t *pmdp, unsigned long addr, int node,
|
||||
bool early)
|
||||
{
|
||||
if (pmd_none(READ_ONCE(*pmdp))) {
|
||||
phys_addr_t pte_phys = early ? __pa_symbol(kasan_zero_pte)
|
||||
: kasan_alloc_zeroed_page(node);
|
||||
phys_addr_t pte_phys = early ?
|
||||
__pa_symbol(kasan_early_shadow_pte)
|
||||
: kasan_alloc_zeroed_page(node);
|
||||
__pmd_populate(pmdp, pte_phys, PMD_TYPE_TABLE);
|
||||
}
|
||||
|
||||
@@ -60,8 +69,9 @@ static pmd_t *__init kasan_pmd_offset(pud_t *pudp, unsigned long addr, int node,
|
||||
bool early)
|
||||
{
|
||||
if (pud_none(READ_ONCE(*pudp))) {
|
||||
phys_addr_t pmd_phys = early ? __pa_symbol(kasan_zero_pmd)
|
||||
: kasan_alloc_zeroed_page(node);
|
||||
phys_addr_t pmd_phys = early ?
|
||||
__pa_symbol(kasan_early_shadow_pmd)
|
||||
: kasan_alloc_zeroed_page(node);
|
||||
__pud_populate(pudp, pmd_phys, PMD_TYPE_TABLE);
|
||||
}
|
||||
|
||||
@@ -72,8 +82,9 @@ static pud_t *__init kasan_pud_offset(pgd_t *pgdp, unsigned long addr, int node,
|
||||
bool early)
|
||||
{
|
||||
if (pgd_none(READ_ONCE(*pgdp))) {
|
||||
phys_addr_t pud_phys = early ? __pa_symbol(kasan_zero_pud)
|
||||
: kasan_alloc_zeroed_page(node);
|
||||
phys_addr_t pud_phys = early ?
|
||||
__pa_symbol(kasan_early_shadow_pud)
|
||||
: kasan_alloc_zeroed_page(node);
|
||||
__pgd_populate(pgdp, pud_phys, PMD_TYPE_TABLE);
|
||||
}
|
||||
|
||||
@@ -87,8 +98,11 @@ static void __init kasan_pte_populate(pmd_t *pmdp, unsigned long addr,
|
||||
pte_t *ptep = kasan_pte_offset(pmdp, addr, node, early);
|
||||
|
||||
do {
|
||||
phys_addr_t page_phys = early ? __pa_symbol(kasan_zero_page)
|
||||
: kasan_alloc_zeroed_page(node);
|
||||
phys_addr_t page_phys = early ?
|
||||
__pa_symbol(kasan_early_shadow_page)
|
||||
: kasan_alloc_raw_page(node);
|
||||
if (!early)
|
||||
memset(__va(page_phys), KASAN_SHADOW_INIT, PAGE_SIZE);
|
||||
next = addr + PAGE_SIZE;
|
||||
set_pte(ptep, pfn_pte(__phys_to_pfn(page_phys), PAGE_KERNEL));
|
||||
} while (ptep++, addr = next, addr != end && pte_none(READ_ONCE(*ptep)));
|
||||
@@ -205,14 +219,14 @@ void __init kasan_init(void)
|
||||
kasan_map_populate(kimg_shadow_start, kimg_shadow_end,
|
||||
early_pfn_to_nid(virt_to_pfn(lm_alias(_text))));
|
||||
|
||||
kasan_populate_zero_shadow((void *)KASAN_SHADOW_START,
|
||||
(void *)mod_shadow_start);
|
||||
kasan_populate_zero_shadow((void *)kimg_shadow_end,
|
||||
kasan_mem_to_shadow((void *)PAGE_OFFSET));
|
||||
kasan_populate_early_shadow((void *)KASAN_SHADOW_START,
|
||||
(void *)mod_shadow_start);
|
||||
kasan_populate_early_shadow((void *)kimg_shadow_end,
|
||||
kasan_mem_to_shadow((void *)PAGE_OFFSET));
|
||||
|
||||
if (kimg_shadow_start > mod_shadow_end)
|
||||
kasan_populate_zero_shadow((void *)mod_shadow_end,
|
||||
(void *)kimg_shadow_start);
|
||||
kasan_populate_early_shadow((void *)mod_shadow_end,
|
||||
(void *)kimg_shadow_start);
|
||||
|
||||
for_each_memblock(memory, reg) {
|
||||
void *start = (void *)__phys_to_virt(reg->base);
|
||||
@@ -227,16 +241,19 @@ void __init kasan_init(void)
|
||||
}
|
||||
|
||||
/*
|
||||
* KAsan may reuse the contents of kasan_zero_pte directly, so we
|
||||
* should make sure that it maps the zero page read-only.
|
||||
* KAsan may reuse the contents of kasan_early_shadow_pte directly,
|
||||
* so we should make sure that it maps the zero page read-only.
|
||||
*/
|
||||
for (i = 0; i < PTRS_PER_PTE; i++)
|
||||
set_pte(&kasan_zero_pte[i],
|
||||
pfn_pte(sym_to_pfn(kasan_zero_page), PAGE_KERNEL_RO));
|
||||
set_pte(&kasan_early_shadow_pte[i],
|
||||
pfn_pte(sym_to_pfn(kasan_early_shadow_page),
|
||||
PAGE_KERNEL_RO));
|
||||
|
||||
memset(kasan_zero_page, 0, PAGE_SIZE);
|
||||
memset(kasan_early_shadow_page, KASAN_SHADOW_INIT, PAGE_SIZE);
|
||||
cpu_replace_ttbr1(lm_alias(swapper_pg_dir));
|
||||
|
||||
kasan_init_tags();
|
||||
|
||||
/* At this point kasan is fully initialized. Enable error messages */
|
||||
init_task.kasan_depth = 0;
|
||||
pr_info("KernelAddressSanitizer initialized\n");
|
||||
|
@@ -1003,10 +1003,8 @@ int pmd_free_pte_page(pmd_t *pmdp, unsigned long addr)
|
||||
|
||||
pmd = READ_ONCE(*pmdp);
|
||||
|
||||
if (!pmd_present(pmd))
|
||||
return 1;
|
||||
if (!pmd_table(pmd)) {
|
||||
VM_WARN_ON(!pmd_table(pmd));
|
||||
VM_WARN_ON(1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1026,10 +1024,8 @@ int pud_free_pmd_page(pud_t *pudp, unsigned long addr)
|
||||
|
||||
pud = READ_ONCE(*pudp);
|
||||
|
||||
if (!pud_present(pud))
|
||||
return 1;
|
||||
if (!pud_table(pud)) {
|
||||
VM_WARN_ON(!pud_table(pud));
|
||||
VM_WARN_ON(1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1047,6 +1043,11 @@ int pud_free_pmd_page(pud_t *pudp, unsigned long addr)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int p4d_free_pud_page(p4d_t *p4d, unsigned long addr)
|
||||
{
|
||||
return 0; /* Don't attempt a block mapping */
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MEMORY_HOTPLUG
|
||||
int arch_add_memory(int nid, u64 start, u64 size, struct vmem_altmap *altmap,
|
||||
bool want_memblock)
|
||||
|
@@ -47,6 +47,12 @@
|
||||
/* PTWs cacheable, inner/outer WBWA */
|
||||
#define TCR_CACHE_FLAGS TCR_IRGN_WBWA | TCR_ORGN_WBWA
|
||||
|
||||
#ifdef CONFIG_KASAN_SW_TAGS
|
||||
#define TCR_KASAN_FLAGS TCR_TBI1
|
||||
#else
|
||||
#define TCR_KASAN_FLAGS 0
|
||||
#endif
|
||||
|
||||
#define MAIR(attr, mt) ((attr) << ((mt) * 8))
|
||||
|
||||
/*
|
||||
@@ -449,7 +455,7 @@ ENTRY(__cpu_setup)
|
||||
*/
|
||||
ldr x10, =TCR_TxSZ(VA_BITS) | TCR_CACHE_FLAGS | TCR_SMP_FLAGS | \
|
||||
TCR_TG_FLAGS | TCR_KASLR_FLAGS | TCR_ASID16 | \
|
||||
TCR_TBI0 | TCR_A1
|
||||
TCR_TBI0 | TCR_A1 | TCR_KASAN_FLAGS
|
||||
|
||||
#ifdef CONFIG_ARM64_USER_VA_BITS_52
|
||||
ldr_l x9, vabits_user
|
||||
|
Reference in New Issue
Block a user