Merge branch 'akpm' (patches from Andrew)
[linux-2.6-microblaze.git] / lib / test_kasan.c
index 8be9d4b..8835e07 100644 (file)
@@ -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)