Skip to content

Commit

Permalink
Merge branch 'akpm' (patches from Andrew)
Browse files Browse the repository at this point in the history
Merge fixes from Andrew Morton:
 "6 fixes"

* emailed patches from Andrew Morton <akpm@linux-foundation.org>:
  lib/Kconfig.debug: fix some messed up configurations
  mm: vmscan: protect shrinker idr replace with CONFIG_MEMCG
  kasan: don't assume percpu shadow allocations will succeed
  kasan: use apply_to_existing_page_range() for releasing vmalloc shadow
  mm/memory.c: add apply_to_existing_page_range() helper
  kasan: fix crashes on access to memory mapped by vm_map_ram()
  • Loading branch information
Linus Torvalds committed Dec 19, 2019
2 parents 5f096c0 + 045f6d7 commit 7e0165b
Show file tree
Hide file tree
Showing 7 changed files with 258 additions and 163 deletions.
15 changes: 9 additions & 6 deletions include/linux/kasan.h
Original file line number Diff line number Diff line change
Expand Up @@ -205,20 +205,23 @@ static inline void *kasan_reset_tag(const void *addr)
#endif /* CONFIG_KASAN_SW_TAGS */

#ifdef CONFIG_KASAN_VMALLOC
int kasan_populate_vmalloc(unsigned long requested_size,
struct vm_struct *area);
void kasan_poison_vmalloc(void *start, unsigned long size);
int kasan_populate_vmalloc(unsigned long addr, unsigned long size);
void kasan_poison_vmalloc(const void *start, unsigned long size);
void kasan_unpoison_vmalloc(const void *start, unsigned long size);
void kasan_release_vmalloc(unsigned long start, unsigned long end,
unsigned long free_region_start,
unsigned long free_region_end);
#else
static inline int kasan_populate_vmalloc(unsigned long requested_size,
struct vm_struct *area)
static inline int kasan_populate_vmalloc(unsigned long start,
unsigned long size)
{
return 0;
}

static inline void kasan_poison_vmalloc(void *start, unsigned long size) {}
static inline void kasan_poison_vmalloc(const void *start, unsigned long size)
{ }
static inline void kasan_unpoison_vmalloc(const void *start, unsigned long size)
{ }
static inline void kasan_release_vmalloc(unsigned long start,
unsigned long end,
unsigned long free_region_start,
Expand Down
3 changes: 3 additions & 0 deletions include/linux/mm.h
Original file line number Diff line number Diff line change
Expand Up @@ -2621,6 +2621,9 @@ static inline int vm_fault_to_errno(vm_fault_t vm_fault, int foll_flags)
typedef int (*pte_fn_t)(pte_t *pte, unsigned long addr, void *data);
extern int apply_to_page_range(struct mm_struct *mm, unsigned long address,
unsigned long size, pte_fn_t fn, void *data);
extern int apply_to_existing_page_range(struct mm_struct *mm,
unsigned long address, unsigned long size,
pte_fn_t fn, void *data);

#ifdef CONFIG_PAGE_POISONING
extern bool page_poisoning_enabled(void);
Expand Down
100 changes: 51 additions & 49 deletions lib/Kconfig.debug
Original file line number Diff line number Diff line change
Expand Up @@ -1483,6 +1483,55 @@ config PROVIDE_OHCI1394_DMA_INIT

See Documentation/debugging-via-ohci1394.txt for more information.

source "samples/Kconfig"

config ARCH_HAS_DEVMEM_IS_ALLOWED
bool

config STRICT_DEVMEM
bool "Filter access to /dev/mem"
depends on MMU && DEVMEM
depends on ARCH_HAS_DEVMEM_IS_ALLOWED
default y if PPC || X86 || ARM64
help
If this option is disabled, you allow userspace (root) access to all
of memory, including kernel and userspace memory. Accidental
access to this is obviously disastrous, but specific access can
be used by people debugging the kernel. Note that with PAT support
enabled, even in this case there are restrictions on /dev/mem
use due to the cache aliasing requirements.

If this option is switched on, and IO_STRICT_DEVMEM=n, the /dev/mem
file only allows userspace access to PCI space and the BIOS code and
data regions. This is sufficient for dosemu and X and all common
users of /dev/mem.

If in doubt, say Y.

config IO_STRICT_DEVMEM
bool "Filter I/O access to /dev/mem"
depends on STRICT_DEVMEM
help
If this option is disabled, you allow userspace (root) access to all
io-memory regardless of whether a driver is actively using that
range. Accidental access to this is obviously disastrous, but
specific access can be used by people debugging kernel drivers.

If this option is switched on, the /dev/mem file only allows
userspace access to *idle* io-memory ranges (see /proc/iomem) This
may break traditional users of /dev/mem (dosemu, legacy X, etc...)
if the driver using a given range cannot be disabled.

If in doubt, say Y.

menu "$(SRCARCH) Debugging"

source "arch/$(SRCARCH)/Kconfig.debug"

endmenu

menu "Kernel Testing and Coverage"

source "lib/kunit/Kconfig"

config NOTIFIER_ERROR_INJECTION
Expand Down Expand Up @@ -1643,10 +1692,6 @@ config FAULT_INJECTION_STACKTRACE_FILTER
help
Provide stacktrace filter for fault-injection capabilities

endmenu # "Kernel Testing and Coverage"

menu "Kernel Testing and Coverage"

config ARCH_HAS_KCOV
bool
help
Expand Down Expand Up @@ -2130,52 +2175,7 @@ config MEMTEST
memtest=17, mean do 17 test patterns.
If you are unsure how to answer this question, answer N.

source "samples/Kconfig"

config ARCH_HAS_DEVMEM_IS_ALLOWED
bool

config STRICT_DEVMEM
bool "Filter access to /dev/mem"
depends on MMU && DEVMEM
depends on ARCH_HAS_DEVMEM_IS_ALLOWED
default y if PPC || X86 || ARM64
---help---
If this option is disabled, you allow userspace (root) access to all
of memory, including kernel and userspace memory. Accidental
access to this is obviously disastrous, but specific access can
be used by people debugging the kernel. Note that with PAT support
enabled, even in this case there are restrictions on /dev/mem
use due to the cache aliasing requirements.

If this option is switched on, and IO_STRICT_DEVMEM=n, the /dev/mem
file only allows userspace access to PCI space and the BIOS code and
data regions. This is sufficient for dosemu and X and all common
users of /dev/mem.

If in doubt, say Y.

config IO_STRICT_DEVMEM
bool "Filter I/O access to /dev/mem"
depends on STRICT_DEVMEM
---help---
If this option is disabled, you allow userspace (root) access to all
io-memory regardless of whether a driver is actively using that
range. Accidental access to this is obviously disastrous, but
specific access can be used by people debugging kernel drivers.

If this option is switched on, the /dev/mem file only allows
userspace access to *idle* io-memory ranges (see /proc/iomem) This
may break traditional users of /dev/mem (dosemu, legacy X, etc...)
if the driver using a given range cannot be disabled.

If in doubt, say Y.

menu "$(SRCARCH) Debugging"

source "arch/$(SRCARCH)/Kconfig.debug"

endmenu

config HYPERV_TESTING
bool "Microsoft Hyper-V driver testing"
Expand All @@ -2184,4 +2184,6 @@ config HYPERV_TESTING
help
Select this option to enable Hyper-V vmbus testing.

endmenu # "Kernel Testing and Coverage"

endmenu # Kernel hacking
36 changes: 24 additions & 12 deletions mm/kasan/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -778,15 +778,17 @@ static int kasan_populate_vmalloc_pte(pte_t *ptep, unsigned long addr,
return 0;
}

int kasan_populate_vmalloc(unsigned long requested_size, struct vm_struct *area)
int kasan_populate_vmalloc(unsigned long addr, unsigned long size)
{
unsigned long shadow_start, shadow_end;
int ret;

shadow_start = (unsigned long)kasan_mem_to_shadow(area->addr);
if (!is_vmalloc_or_module_addr((void *)addr))
return 0;

shadow_start = (unsigned long)kasan_mem_to_shadow((void *)addr);
shadow_start = ALIGN_DOWN(shadow_start, PAGE_SIZE);
shadow_end = (unsigned long)kasan_mem_to_shadow(area->addr +
area->size);
shadow_end = (unsigned long)kasan_mem_to_shadow((void *)addr + size);
shadow_end = ALIGN(shadow_end, PAGE_SIZE);

ret = apply_to_page_range(&init_mm, shadow_start,
Expand All @@ -797,10 +799,6 @@ int kasan_populate_vmalloc(unsigned long requested_size, struct vm_struct *area)

flush_cache_vmap(shadow_start, shadow_end);

kasan_unpoison_shadow(area->addr, requested_size);

area->flags |= VM_KASAN;

/*
* We need to be careful about inter-cpu effects here. Consider:
*
Expand Down Expand Up @@ -843,12 +841,23 @@ int kasan_populate_vmalloc(unsigned long requested_size, struct vm_struct *area)
* Poison the shadow for a vmalloc region. Called as part of the
* freeing process at the time the region is freed.
*/
void kasan_poison_vmalloc(void *start, unsigned long size)
void kasan_poison_vmalloc(const void *start, unsigned long size)
{
if (!is_vmalloc_or_module_addr(start))
return;

size = round_up(size, KASAN_SHADOW_SCALE_SIZE);
kasan_poison_shadow(start, size, KASAN_VMALLOC_INVALID);
}

void kasan_unpoison_vmalloc(const void *start, unsigned long size)
{
if (!is_vmalloc_or_module_addr(start))
return;

kasan_unpoison_shadow(start, size);
}

static int kasan_depopulate_vmalloc_pte(pte_t *ptep, unsigned long addr,
void *unused)
{
Expand Down Expand Up @@ -948,6 +957,7 @@ void kasan_release_vmalloc(unsigned long start, unsigned long end,
{
void *shadow_start, *shadow_end;
unsigned long region_start, region_end;
unsigned long size;

region_start = ALIGN(start, PAGE_SIZE * KASAN_SHADOW_SCALE_SIZE);
region_end = ALIGN_DOWN(end, PAGE_SIZE * KASAN_SHADOW_SCALE_SIZE);
Expand All @@ -970,9 +980,11 @@ void kasan_release_vmalloc(unsigned long start, unsigned long end,
shadow_end = kasan_mem_to_shadow((void *)region_end);

if (shadow_end > shadow_start) {
apply_to_page_range(&init_mm, (unsigned long)shadow_start,
(unsigned long)(shadow_end - shadow_start),
kasan_depopulate_vmalloc_pte, NULL);
size = shadow_end - shadow_start;
apply_to_existing_page_range(&init_mm,
(unsigned long)shadow_start,
size, kasan_depopulate_vmalloc_pte,
NULL);
flush_tlb_kernel_range((unsigned long)shadow_start,
(unsigned long)shadow_end);
}
Expand Down
Loading

0 comments on commit 7e0165b

Please sign in to comment.