linux/lib/test_kasan.c
<<
>>
Prefs
   1/*
   2 *
   3 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
   4 * Author: Andrey Ryabinin <a.ryabinin@samsung.com>
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License version 2 as
   8 * published by the Free Software Foundation.
   9 *
  10 */
  11
  12#define pr_fmt(fmt) "kasan test: %s " fmt, __func__
  13
  14#include <linux/kernel.h>
  15#include <linux/printk.h>
  16#include <linux/slab.h>
  17#include <linux/string.h>
  18#include <linux/module.h>
  19
  20static noinline void __init kmalloc_oob_right(void)
  21{
  22        char *ptr;
  23        size_t size = 123;
  24
  25        pr_info("out-of-bounds to right\n");
  26        ptr = kmalloc(size, GFP_KERNEL);
  27        if (!ptr) {
  28                pr_err("Allocation failed\n");
  29                return;
  30        }
  31
  32        ptr[size] = 'x';
  33        kfree(ptr);
  34}
  35
  36static noinline void __init kmalloc_oob_left(void)
  37{
  38        char *ptr;
  39        size_t size = 15;
  40
  41        pr_info("out-of-bounds to left\n");
  42        ptr = kmalloc(size, GFP_KERNEL);
  43        if (!ptr) {
  44                pr_err("Allocation failed\n");
  45                return;
  46        }
  47
  48        *ptr = *(ptr - 1);
  49        kfree(ptr);
  50}
  51
  52static noinline void __init kmalloc_node_oob_right(void)
  53{
  54        char *ptr;
  55        size_t size = 4096;
  56
  57        pr_info("kmalloc_node(): out-of-bounds to right\n");
  58        ptr = kmalloc_node(size, GFP_KERNEL, 0);
  59        if (!ptr) {
  60                pr_err("Allocation failed\n");
  61                return;
  62        }
  63
  64        ptr[size] = 0;
  65        kfree(ptr);
  66}
  67
  68static noinline void __init kmalloc_large_oob_right(void)
  69{
  70        char *ptr;
  71        size_t size = KMALLOC_MAX_CACHE_SIZE + 10;
  72
  73        pr_info("kmalloc large allocation: out-of-bounds to right\n");
  74        ptr = kmalloc(size, GFP_KERNEL);
  75        if (!ptr) {
  76                pr_err("Allocation failed\n");
  77                return;
  78        }
  79
  80        ptr[size] = 0;
  81        kfree(ptr);
  82}
  83
  84static noinline void __init kmalloc_oob_krealloc_more(void)
  85{
  86        char *ptr1, *ptr2;
  87        size_t size1 = 17;
  88        size_t size2 = 19;
  89
  90        pr_info("out-of-bounds after krealloc more\n");
  91        ptr1 = kmalloc(size1, GFP_KERNEL);
  92        ptr2 = krealloc(ptr1, size2, GFP_KERNEL);
  93        if (!ptr1 || !ptr2) {
  94                pr_err("Allocation failed\n");
  95                kfree(ptr1);
  96                return;
  97        }
  98
  99        ptr2[size2] = 'x';
 100        kfree(ptr2);
 101}
 102
 103static noinline void __init kmalloc_oob_krealloc_less(void)
 104{
 105        char *ptr1, *ptr2;
 106        size_t size1 = 17;
 107        size_t size2 = 15;
 108
 109        pr_info("out-of-bounds after krealloc less\n");
 110        ptr1 = kmalloc(size1, GFP_KERNEL);
 111        ptr2 = krealloc(ptr1, size2, GFP_KERNEL);
 112        if (!ptr1 || !ptr2) {
 113                pr_err("Allocation failed\n");
 114                kfree(ptr1);
 115                return;
 116        }
 117        ptr2[size2] = 'x';
 118        kfree(ptr2);
 119}
 120
 121static noinline void __init kmalloc_oob_16(void)
 122{
 123        struct {
 124                u64 words[2];
 125        } *ptr1, *ptr2;
 126
 127        pr_info("kmalloc out-of-bounds for 16-bytes access\n");
 128        ptr1 = kmalloc(sizeof(*ptr1) - 3, GFP_KERNEL);
 129        ptr2 = kmalloc(sizeof(*ptr2), GFP_KERNEL);
 130        if (!ptr1 || !ptr2) {
 131                pr_err("Allocation failed\n");
 132                kfree(ptr1);
 133                kfree(ptr2);
 134                return;
 135        }
 136        *ptr1 = *ptr2;
 137        kfree(ptr1);
 138        kfree(ptr2);
 139}
 140
 141static noinline void __init kmalloc_oob_memset_2(void)
 142{
 143        char *ptr;
 144        size_t size = 8;
 145
 146        pr_info("out-of-bounds in memset2\n");
 147        ptr = kmalloc(size, GFP_KERNEL);
 148        if (!ptr) {
 149                pr_err("Allocation failed\n");
 150                return;
 151        }
 152
 153        memset(ptr+7, 0, 2);
 154        kfree(ptr);
 155}
 156
 157static noinline void __init kmalloc_oob_memset_4(void)
 158{
 159        char *ptr;
 160        size_t size = 8;
 161
 162        pr_info("out-of-bounds in memset4\n");
 163        ptr = kmalloc(size, GFP_KERNEL);
 164        if (!ptr) {
 165                pr_err("Allocation failed\n");
 166                return;
 167        }
 168
 169        memset(ptr+5, 0, 4);
 170        kfree(ptr);
 171}
 172
 173
 174static noinline void __init kmalloc_oob_memset_8(void)
 175{
 176        char *ptr;
 177        size_t size = 8;
 178
 179        pr_info("out-of-bounds in memset8\n");
 180        ptr = kmalloc(size, GFP_KERNEL);
 181        if (!ptr) {
 182                pr_err("Allocation failed\n");
 183                return;
 184        }
 185
 186        memset(ptr+1, 0, 8);
 187        kfree(ptr);
 188}
 189
 190static noinline void __init kmalloc_oob_memset_16(void)
 191{
 192        char *ptr;
 193        size_t size = 16;
 194
 195        pr_info("out-of-bounds in memset16\n");
 196        ptr = kmalloc(size, GFP_KERNEL);
 197        if (!ptr) {
 198                pr_err("Allocation failed\n");
 199                return;
 200        }
 201
 202        memset(ptr+1, 0, 16);
 203        kfree(ptr);
 204}
 205
 206static noinline void __init kmalloc_oob_in_memset(void)
 207{
 208        char *ptr;
 209        size_t size = 666;
 210
 211        pr_info("out-of-bounds in memset\n");
 212        ptr = kmalloc(size, GFP_KERNEL);
 213        if (!ptr) {
 214                pr_err("Allocation failed\n");
 215                return;
 216        }
 217
 218        memset(ptr, 0, size+5);
 219        kfree(ptr);
 220}
 221
 222static noinline void __init kmalloc_uaf(void)
 223{
 224        char *ptr;
 225        size_t size = 10;
 226
 227        pr_info("use-after-free\n");
 228        ptr = kmalloc(size, GFP_KERNEL);
 229        if (!ptr) {
 230                pr_err("Allocation failed\n");
 231                return;
 232        }
 233
 234        kfree(ptr);
 235        *(ptr + 8) = 'x';
 236}
 237
 238static noinline void __init kmalloc_uaf_memset(void)
 239{
 240        char *ptr;
 241        size_t size = 33;
 242
 243        pr_info("use-after-free in memset\n");
 244        ptr = kmalloc(size, GFP_KERNEL);
 245        if (!ptr) {
 246                pr_err("Allocation failed\n");
 247                return;
 248        }
 249
 250        kfree(ptr);
 251        memset(ptr, 0, size);
 252}
 253
 254static noinline void __init kmalloc_uaf2(void)
 255{
 256        char *ptr1, *ptr2;
 257        size_t size = 43;
 258
 259        pr_info("use-after-free after another kmalloc\n");
 260        ptr1 = kmalloc(size, GFP_KERNEL);
 261        if (!ptr1) {
 262                pr_err("Allocation failed\n");
 263                return;
 264        }
 265
 266        kfree(ptr1);
 267        ptr2 = kmalloc(size, GFP_KERNEL);
 268        if (!ptr2) {
 269                pr_err("Allocation failed\n");
 270                return;
 271        }
 272
 273        ptr1[40] = 'x';
 274        kfree(ptr2);
 275}
 276
 277static noinline void __init kmem_cache_oob(void)
 278{
 279        char *p;
 280        size_t size = 200;
 281        struct kmem_cache *cache = kmem_cache_create("test_cache",
 282                                                size, 0,
 283                                                0, NULL);
 284        if (!cache) {
 285                pr_err("Cache allocation failed\n");
 286                return;
 287        }
 288        pr_info("out-of-bounds in kmem_cache_alloc\n");
 289        p = kmem_cache_alloc(cache, GFP_KERNEL);
 290        if (!p) {
 291                pr_err("Allocation failed\n");
 292                kmem_cache_destroy(cache);
 293                return;
 294        }
 295
 296        *p = p[size];
 297        kmem_cache_free(cache, p);
 298        kmem_cache_destroy(cache);
 299}
 300
 301static char global_array[10];
 302
 303static noinline void __init kasan_global_oob(void)
 304{
 305        volatile int i = 3;
 306        char *p = &global_array[ARRAY_SIZE(global_array) + i];
 307
 308        pr_info("out-of-bounds global variable\n");
 309        *(volatile char *)p;
 310}
 311
 312static noinline void __init kasan_stack_oob(void)
 313{
 314        char stack_array[10];
 315        volatile int i = 0;
 316        char *p = &stack_array[ARRAY_SIZE(stack_array) + i];
 317
 318        pr_info("out-of-bounds on stack\n");
 319        *(volatile char *)p;
 320}
 321
 322static int __init kmalloc_tests_init(void)
 323{
 324        kmalloc_oob_right();
 325        kmalloc_oob_left();
 326        kmalloc_node_oob_right();
 327        kmalloc_large_oob_right();
 328        kmalloc_oob_krealloc_more();
 329        kmalloc_oob_krealloc_less();
 330        kmalloc_oob_16();
 331        kmalloc_oob_in_memset();
 332        kmalloc_oob_memset_2();
 333        kmalloc_oob_memset_4();
 334        kmalloc_oob_memset_8();
 335        kmalloc_oob_memset_16();
 336        kmalloc_uaf();
 337        kmalloc_uaf_memset();
 338        kmalloc_uaf2();
 339        kmem_cache_oob();
 340        kasan_stack_oob();
 341        kasan_global_oob();
 342        return -EAGAIN;
 343}
 344
 345module_init(kmalloc_tests_init);
 346MODULE_LICENSE("GPL");
 347