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