KUNIT_EXPECT_KASAN_FAIL(test, *(volatile char *)p);
 }
 
-/* Check that ksize() makes the whole object accessible. */
+/* Check that ksize() does NOT unpoison whole object. */
 static void ksize_unpoisons_memory(struct kunit *test)
 {
        char *ptr;
-       size_t size = 123, real_size;
+       size_t size = 128 - KASAN_GRANULE_SIZE - 5;
+       size_t real_size;
 
        ptr = kmalloc(size, GFP_KERNEL);
        KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr);
+
        real_size = ksize(ptr);
+       KUNIT_EXPECT_GT(test, real_size, size);
 
        OPTIMIZER_HIDE_VAR(ptr);
 
-       /* This access shouldn't trigger a KASAN report. */
-       ptr[size] = 'x';
+       /* These accesses shouldn't trigger a KASAN report. */
+       ptr[0] = 'x';
+       ptr[size - 1] = 'x';
 
-       /* This one must. */
-       KUNIT_EXPECT_KASAN_FAIL(test, ((volatile char *)ptr)[real_size]);
+       /* These must trigger a KASAN report. */
+       if (IS_ENABLED(CONFIG_KASAN_GENERIC))
+               KUNIT_EXPECT_KASAN_FAIL(test, ((volatile char *)ptr)[size]);
+       KUNIT_EXPECT_KASAN_FAIL(test, ((volatile char *)ptr)[size + 5]);
+       KUNIT_EXPECT_KASAN_FAIL(test, ((volatile char *)ptr)[real_size - 1]);
 
        kfree(ptr);
 }
 
        void *ret;
        size_t ks;
 
-       /* Don't use instrumented ksize to allow precise KASAN poisoning. */
+       /* Check for double-free before calling ksize. */
        if (likely(!ZERO_OR_NULL_PTR(p))) {
                if (!kasan_check_byte(p))
                        return NULL;
-               ks = kfence_ksize(p) ?: __ksize(p);
+               ks = ksize(p);
        } else
                ks = 0;
 
        void *mem = (void *)p;
 
        ks = ksize(mem);
-       if (ks)
+       if (ks) {
+               kasan_unpoison_range(mem, ks);
                memzero_explicit(mem, ks);
+       }
        kfree(mem);
 }
 EXPORT_SYMBOL(kfree_sensitive);
  */
 size_t ksize(const void *objp)
 {
-       size_t size;
-
        /*
-        * We need to first check that the pointer to the object is valid, and
-        * only then unpoison the memory. The report printed from ksize() is
-        * more useful, then when it's printed later when the behaviour could
-        * be undefined due to a potential use-after-free or double-free.
+        * We need to first check that the pointer to the object is valid.
+        * The KASAN report printed from ksize() is more useful, then when
+        * it's printed later when the behaviour could be undefined due to
+        * a potential use-after-free or double-free.
         *
         * We use kasan_check_byte(), which is supported for the hardware
         * tag-based KASAN mode, unlike kasan_check_read/write().
        if (unlikely(ZERO_OR_NULL_PTR(objp)) || !kasan_check_byte(objp))
                return 0;
 
-       size = kfence_ksize(objp) ?: __ksize(objp);
-       /*
-        * We assume that ksize callers could use whole allocated area,
-        * so we need to unpoison this area.
-        */
-       kasan_unpoison_range(objp, size);
-       return size;
+       return kfence_ksize(objp) ?: __ksize(objp);
 }
 EXPORT_SYMBOL(ksize);