Merge branch 'akpm' (patches from Andrew)
Merge misc updates from Andrew Morton: "173 patches. Subsystems affected by this series: ia64, ocfs2, block, and mm (debug, pagecache, gup, swap, shmem, memcg, selftests, pagemap, mremap, bootmem, sparsemem, vmalloc, kasan, pagealloc, memory-failure, hugetlb, userfaultfd, vmscan, compaction, mempolicy, memblock, oom-kill, migration, ksm, percpu, vmstat, and madvise)" * emailed patches from Andrew Morton <akpm@linux-foundation.org>: (173 commits) mm/madvise: add MADV_WILLNEED to process_madvise() mm/vmstat: remove unneeded return value mm/vmstat: simplify the array size calculation mm/vmstat: correct some wrong comments mm/percpu,c: remove obsolete comments of pcpu_chunk_populated() selftests: vm: add COW time test for KSM pages selftests: vm: add KSM merging time test mm: KSM: fix data type selftests: vm: add KSM merging across nodes test selftests: vm: add KSM zero page merging test selftests: vm: add KSM unmerge test selftests: vm: add KSM merge test mm/migrate: correct kernel-doc notation mm: wire up syscall process_mrelease mm: introduce process_mrelease system call memblock: make memblock_find_in_range method private mm/mempolicy.c: use in_task() in mempolicy_slab_node() mm/mempolicy: unify the create() func for bind/interleave/prefer-many policies mm/mempolicy: advertise new MPOL_PREFERRED_MANY mm/hugetlb: add support for mempolicy MPOL_PREFERRED_MANY ...
This commit is contained in:
+2
-3
@@ -918,9 +918,8 @@ void sg_miter_stop(struct sg_mapping_iter *miter)
|
||||
miter->__offset += miter->consumed;
|
||||
miter->__remaining -= miter->consumed;
|
||||
|
||||
if ((miter->__flags & SG_MITER_TO_SG) &&
|
||||
!PageSlab(miter->page))
|
||||
flush_kernel_dcache_page(miter->page);
|
||||
if (miter->__flags & SG_MITER_TO_SG)
|
||||
flush_dcache_page(miter->page);
|
||||
|
||||
if (miter->__flags & SG_MITER_ATOMIC) {
|
||||
WARN_ON_ONCE(preemptible());
|
||||
|
||||
+57
-23
@@ -120,12 +120,28 @@ static void kasan_test_exit(struct kunit *test)
|
||||
static void kmalloc_oob_right(struct kunit *test)
|
||||
{
|
||||
char *ptr;
|
||||
size_t size = 123;
|
||||
size_t size = 128 - KASAN_GRANULE_SIZE - 5;
|
||||
|
||||
ptr = kmalloc(size, GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr);
|
||||
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, ptr[size + OOB_TAG_OFF] = 'x');
|
||||
/*
|
||||
* An unaligned access past the requested kmalloc size.
|
||||
* Only generic KASAN can precisely detect these.
|
||||
*/
|
||||
if (IS_ENABLED(CONFIG_KASAN_GENERIC))
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, ptr[size] = 'x');
|
||||
|
||||
/*
|
||||
* An aligned access into the first out-of-bounds granule that falls
|
||||
* within the aligned kmalloc object.
|
||||
*/
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, ptr[size + 5] = 'y');
|
||||
|
||||
/* Out-of-bounds access past the aligned kmalloc object. */
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, ptr[0] =
|
||||
ptr[size + KASAN_GRANULE_SIZE + 5]);
|
||||
|
||||
kfree(ptr);
|
||||
}
|
||||
|
||||
@@ -149,7 +165,7 @@ static void kmalloc_node_oob_right(struct kunit *test)
|
||||
ptr = kmalloc_node(size, GFP_KERNEL, 0);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr);
|
||||
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, ptr[size] = 0);
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, ptr[0] = ptr[size]);
|
||||
kfree(ptr);
|
||||
}
|
||||
|
||||
@@ -185,7 +201,7 @@ static void kmalloc_pagealloc_uaf(struct kunit *test)
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr);
|
||||
kfree(ptr);
|
||||
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, ptr[0] = 0);
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, ((volatile char *)ptr)[0]);
|
||||
}
|
||||
|
||||
static void kmalloc_pagealloc_invalid_free(struct kunit *test)
|
||||
@@ -219,7 +235,7 @@ static void pagealloc_oob_right(struct kunit *test)
|
||||
ptr = page_address(pages);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr);
|
||||
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, ptr[size] = 0);
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, ptr[0] = ptr[size]);
|
||||
free_pages((unsigned long)ptr, order);
|
||||
}
|
||||
|
||||
@@ -234,7 +250,7 @@ static void pagealloc_uaf(struct kunit *test)
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr);
|
||||
free_pages((unsigned long)ptr, order);
|
||||
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, ptr[0] = 0);
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, ((volatile char *)ptr)[0]);
|
||||
}
|
||||
|
||||
static void kmalloc_large_oob_right(struct kunit *test)
|
||||
@@ -410,64 +426,70 @@ static void kmalloc_uaf_16(struct kunit *test)
|
||||
kfree(ptr1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Note: in the memset tests below, the written range touches both valid and
|
||||
* invalid memory. This makes sure that the instrumentation does not only check
|
||||
* the starting address but the whole range.
|
||||
*/
|
||||
|
||||
static void kmalloc_oob_memset_2(struct kunit *test)
|
||||
{
|
||||
char *ptr;
|
||||
size_t size = 8;
|
||||
size_t size = 128 - KASAN_GRANULE_SIZE;
|
||||
|
||||
ptr = kmalloc(size, GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr);
|
||||
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, memset(ptr + 7 + OOB_TAG_OFF, 0, 2));
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, memset(ptr + size - 1, 0, 2));
|
||||
kfree(ptr);
|
||||
}
|
||||
|
||||
static void kmalloc_oob_memset_4(struct kunit *test)
|
||||
{
|
||||
char *ptr;
|
||||
size_t size = 8;
|
||||
size_t size = 128 - KASAN_GRANULE_SIZE;
|
||||
|
||||
ptr = kmalloc(size, GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr);
|
||||
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, memset(ptr + 5 + OOB_TAG_OFF, 0, 4));
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, memset(ptr + size - 3, 0, 4));
|
||||
kfree(ptr);
|
||||
}
|
||||
|
||||
|
||||
static void kmalloc_oob_memset_8(struct kunit *test)
|
||||
{
|
||||
char *ptr;
|
||||
size_t size = 8;
|
||||
size_t size = 128 - KASAN_GRANULE_SIZE;
|
||||
|
||||
ptr = kmalloc(size, GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr);
|
||||
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, memset(ptr + 1 + OOB_TAG_OFF, 0, 8));
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, memset(ptr + size - 7, 0, 8));
|
||||
kfree(ptr);
|
||||
}
|
||||
|
||||
static void kmalloc_oob_memset_16(struct kunit *test)
|
||||
{
|
||||
char *ptr;
|
||||
size_t size = 16;
|
||||
size_t size = 128 - KASAN_GRANULE_SIZE;
|
||||
|
||||
ptr = kmalloc(size, GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr);
|
||||
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, memset(ptr + 1 + OOB_TAG_OFF, 0, 16));
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, memset(ptr + size - 15, 0, 16));
|
||||
kfree(ptr);
|
||||
}
|
||||
|
||||
static void kmalloc_oob_in_memset(struct kunit *test)
|
||||
{
|
||||
char *ptr;
|
||||
size_t size = 666;
|
||||
size_t size = 128 - KASAN_GRANULE_SIZE;
|
||||
|
||||
ptr = kmalloc(size, GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr);
|
||||
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, memset(ptr, 0, size + 5 + OOB_TAG_OFF));
|
||||
KUNIT_EXPECT_KASAN_FAIL(test,
|
||||
memset(ptr, 0, size + KASAN_GRANULE_SIZE));
|
||||
kfree(ptr);
|
||||
}
|
||||
|
||||
@@ -477,11 +499,17 @@ static void kmalloc_memmove_invalid_size(struct kunit *test)
|
||||
size_t size = 64;
|
||||
volatile size_t invalid_size = -2;
|
||||
|
||||
/*
|
||||
* Hardware tag-based mode doesn't check memmove for negative size.
|
||||
* As a result, this test introduces a side-effect memory corruption,
|
||||
* which can result in a crash.
|
||||
*/
|
||||
KASAN_TEST_NEEDS_CONFIG_OFF(test, CONFIG_KASAN_HW_TAGS);
|
||||
|
||||
ptr = kmalloc(size, GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr);
|
||||
|
||||
memset((char *)ptr, 0, 64);
|
||||
|
||||
KUNIT_EXPECT_KASAN_FAIL(test,
|
||||
memmove((char *)ptr, (char *)ptr + 4, invalid_size));
|
||||
kfree(ptr);
|
||||
@@ -496,7 +524,7 @@ static void kmalloc_uaf(struct kunit *test)
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr);
|
||||
|
||||
kfree(ptr);
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, *(ptr + 8) = 'x');
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, ((volatile char *)ptr)[8]);
|
||||
}
|
||||
|
||||
static void kmalloc_uaf_memset(struct kunit *test)
|
||||
@@ -504,6 +532,12 @@ static void kmalloc_uaf_memset(struct kunit *test)
|
||||
char *ptr;
|
||||
size_t size = 33;
|
||||
|
||||
/*
|
||||
* Only generic KASAN uses quarantine, which is required to avoid a
|
||||
* kernel memory corruption this test causes.
|
||||
*/
|
||||
KASAN_TEST_NEEDS_CONFIG_ON(test, CONFIG_KASAN_GENERIC);
|
||||
|
||||
ptr = kmalloc(size, GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr);
|
||||
|
||||
@@ -535,7 +569,7 @@ again:
|
||||
goto again;
|
||||
}
|
||||
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, ptr1[40] = 'x');
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, ((volatile char *)ptr1)[40]);
|
||||
KUNIT_EXPECT_PTR_NE(test, ptr1, ptr2);
|
||||
|
||||
kfree(ptr2);
|
||||
@@ -682,7 +716,7 @@ static void ksize_unpoisons_memory(struct kunit *test)
|
||||
ptr[size] = 'x';
|
||||
|
||||
/* This one must. */
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, ptr[real_size] = 'y');
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, ((volatile char *)ptr)[real_size]);
|
||||
|
||||
kfree(ptr);
|
||||
}
|
||||
@@ -701,8 +735,8 @@ static void ksize_uaf(struct kunit *test)
|
||||
kfree(ptr);
|
||||
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, ksize(ptr));
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, kasan_int_result = *ptr);
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, kasan_int_result = *(ptr + size));
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, ((volatile char *)ptr)[0]);
|
||||
KUNIT_EXPECT_KASAN_FAIL(test, ((volatile char *)ptr)[size]);
|
||||
}
|
||||
|
||||
static void kasan_stack_oob(struct kunit *test)
|
||||
|
||||
+9
-11
@@ -15,13 +15,11 @@
|
||||
|
||||
#include "../mm/kasan/kasan.h"
|
||||
|
||||
#define OOB_TAG_OFF (IS_ENABLED(CONFIG_KASAN_GENERIC) ? 0 : KASAN_GRANULE_SIZE)
|
||||
|
||||
static noinline void __init copy_user_test(void)
|
||||
{
|
||||
char *kmem;
|
||||
char __user *usermem;
|
||||
size_t size = 10;
|
||||
size_t size = 128 - KASAN_GRANULE_SIZE;
|
||||
int __maybe_unused unused;
|
||||
|
||||
kmem = kmalloc(size, GFP_KERNEL);
|
||||
@@ -38,25 +36,25 @@ static noinline void __init copy_user_test(void)
|
||||
}
|
||||
|
||||
pr_info("out-of-bounds in copy_from_user()\n");
|
||||
unused = copy_from_user(kmem, usermem, size + 1 + OOB_TAG_OFF);
|
||||
unused = copy_from_user(kmem, usermem, size + 1);
|
||||
|
||||
pr_info("out-of-bounds in copy_to_user()\n");
|
||||
unused = copy_to_user(usermem, kmem, size + 1 + OOB_TAG_OFF);
|
||||
unused = copy_to_user(usermem, kmem, size + 1);
|
||||
|
||||
pr_info("out-of-bounds in __copy_from_user()\n");
|
||||
unused = __copy_from_user(kmem, usermem, size + 1 + OOB_TAG_OFF);
|
||||
unused = __copy_from_user(kmem, usermem, size + 1);
|
||||
|
||||
pr_info("out-of-bounds in __copy_to_user()\n");
|
||||
unused = __copy_to_user(usermem, kmem, size + 1 + OOB_TAG_OFF);
|
||||
unused = __copy_to_user(usermem, kmem, size + 1);
|
||||
|
||||
pr_info("out-of-bounds in __copy_from_user_inatomic()\n");
|
||||
unused = __copy_from_user_inatomic(kmem, usermem, size + 1 + OOB_TAG_OFF);
|
||||
unused = __copy_from_user_inatomic(kmem, usermem, size + 1);
|
||||
|
||||
pr_info("out-of-bounds in __copy_to_user_inatomic()\n");
|
||||
unused = __copy_to_user_inatomic(usermem, kmem, size + 1 + OOB_TAG_OFF);
|
||||
unused = __copy_to_user_inatomic(usermem, kmem, size + 1);
|
||||
|
||||
pr_info("out-of-bounds in strncpy_from_user()\n");
|
||||
unused = strncpy_from_user(kmem, usermem, size + 1 + OOB_TAG_OFF);
|
||||
unused = strncpy_from_user(kmem, usermem, size + 1);
|
||||
|
||||
vm_munmap((unsigned long)usermem, PAGE_SIZE);
|
||||
kfree(kmem);
|
||||
@@ -73,7 +71,7 @@ static noinline void __init kasan_rcu_reclaim(struct rcu_head *rp)
|
||||
struct kasan_rcu_info, rcu);
|
||||
|
||||
kfree(fp);
|
||||
fp->i = 1;
|
||||
((volatile struct kasan_rcu_info *)fp)->i;
|
||||
}
|
||||
|
||||
static noinline void __init kasan_rcu_uaf(void)
|
||||
|
||||
+4
-1
@@ -35,6 +35,9 @@ __param(int, test_repeat_count, 1,
|
||||
__param(int, test_loop_count, 1000000,
|
||||
"Set test loop counter");
|
||||
|
||||
__param(int, nr_pages, 0,
|
||||
"Set number of pages for fix_size_alloc_test(default: 1)");
|
||||
|
||||
__param(int, run_test_mask, INT_MAX,
|
||||
"Set tests specified in the mask.\n\n"
|
||||
"\t\tid: 1, name: fix_size_alloc_test\n"
|
||||
@@ -262,7 +265,7 @@ static int fix_size_alloc_test(void)
|
||||
int i;
|
||||
|
||||
for (i = 0; i < test_loop_count; i++) {
|
||||
ptr = vmalloc(3 * PAGE_SIZE);
|
||||
ptr = vmalloc((nr_pages > 0 ? nr_pages:1) * PAGE_SIZE);
|
||||
|
||||
if (!ptr)
|
||||
return -1;
|
||||
|
||||
Reference in New Issue
Block a user