linux/drivers/misc/lkdtm_heap.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * This is for all the tests relating directly to heap memory, including
   4 * page allocation and slab allocations.
   5 */
   6#include "lkdtm.h"
   7#include <linux/slab.h>
   8#include <linux/sched.h>
   9
  10/*
  11 * This tries to stay within the next largest power-of-2 kmalloc cache
  12 * to avoid actually overwriting anything important if it's not detected
  13 * correctly.
  14 */
  15void lkdtm_OVERWRITE_ALLOCATION(void)
  16{
  17        size_t len = 1020;
  18        u32 *data = kmalloc(len, GFP_KERNEL);
  19
  20        data[1024 / sizeof(u32)] = 0x12345678;
  21        kfree(data);
  22}
  23
  24void lkdtm_WRITE_AFTER_FREE(void)
  25{
  26        int *base, *again;
  27        size_t len = 1024;
  28        /*
  29         * The slub allocator uses the first word to store the free
  30         * pointer in some configurations. Use the middle of the
  31         * allocation to avoid running into the freelist
  32         */
  33        size_t offset = (len / sizeof(*base)) / 2;
  34
  35        base = kmalloc(len, GFP_KERNEL);
  36        pr_info("Allocated memory %p-%p\n", base, &base[offset * 2]);
  37        pr_info("Attempting bad write to freed memory at %p\n",
  38                &base[offset]);
  39        kfree(base);
  40        base[offset] = 0x0abcdef0;
  41        /* Attempt to notice the overwrite. */
  42        again = kmalloc(len, GFP_KERNEL);
  43        kfree(again);
  44        if (again != base)
  45                pr_info("Hmm, didn't get the same memory range.\n");
  46}
  47
  48void lkdtm_READ_AFTER_FREE(void)
  49{
  50        int *base, *val, saw;
  51        size_t len = 1024;
  52        /*
  53         * The slub allocator uses the first word to store the free
  54         * pointer in some configurations. Use the middle of the
  55         * allocation to avoid running into the freelist
  56         */
  57        size_t offset = (len / sizeof(*base)) / 2;
  58
  59        base = kmalloc(len, GFP_KERNEL);
  60        if (!base) {
  61                pr_info("Unable to allocate base memory.\n");
  62                return;
  63        }
  64
  65        val = kmalloc(len, GFP_KERNEL);
  66        if (!val) {
  67                pr_info("Unable to allocate val memory.\n");
  68                kfree(base);
  69                return;
  70        }
  71
  72        *val = 0x12345678;
  73        base[offset] = *val;
  74        pr_info("Value in memory before free: %x\n", base[offset]);
  75
  76        kfree(base);
  77
  78        pr_info("Attempting bad read from freed memory\n");
  79        saw = base[offset];
  80        if (saw != *val) {
  81                /* Good! Poisoning happened, so declare a win. */
  82                pr_info("Memory correctly poisoned (%x)\n", saw);
  83                BUG();
  84        }
  85        pr_info("Memory was not poisoned\n");
  86
  87        kfree(val);
  88}
  89
  90void lkdtm_WRITE_BUDDY_AFTER_FREE(void)
  91{
  92        unsigned long p = __get_free_page(GFP_KERNEL);
  93        if (!p) {
  94                pr_info("Unable to allocate free page\n");
  95                return;
  96        }
  97
  98        pr_info("Writing to the buddy page before free\n");
  99        memset((void *)p, 0x3, PAGE_SIZE);
 100        free_page(p);
 101        schedule();
 102        pr_info("Attempting bad write to the buddy page after free\n");
 103        memset((void *)p, 0x78, PAGE_SIZE);
 104        /* Attempt to notice the overwrite. */
 105        p = __get_free_page(GFP_KERNEL);
 106        free_page(p);
 107        schedule();
 108}
 109
 110void lkdtm_READ_BUDDY_AFTER_FREE(void)
 111{
 112        unsigned long p = __get_free_page(GFP_KERNEL);
 113        int saw, *val;
 114        int *base;
 115
 116        if (!p) {
 117                pr_info("Unable to allocate free page\n");
 118                return;
 119        }
 120
 121        val = kmalloc(1024, GFP_KERNEL);
 122        if (!val) {
 123                pr_info("Unable to allocate val memory.\n");
 124                free_page(p);
 125                return;
 126        }
 127
 128        base = (int *)p;
 129
 130        *val = 0x12345678;
 131        base[0] = *val;
 132        pr_info("Value in memory before free: %x\n", base[0]);
 133        free_page(p);
 134        pr_info("Attempting to read from freed memory\n");
 135        saw = base[0];
 136        if (saw != *val) {
 137                /* Good! Poisoning happened, so declare a win. */
 138                pr_info("Memory correctly poisoned (%x)\n", saw);
 139                BUG();
 140        }
 141        pr_info("Buddy page was not poisoned\n");
 142
 143        kfree(val);
 144}
 145