root/drivers/misc/lkdtm/core.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. find_crashtype
  2. lkdtm_do_action
  3. lkdtm_register_cpoint
  4. lkdtm_kprobe_handler
  5. lkdtm_debugfs_entry
  6. lkdtm_debugfs_read
  7. lkdtm_debugfs_open
  8. direct_entry
  9. lkdtm_module_init
  10. lkdtm_module_exit

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * Linux Kernel Dump Test Module for testing kernel crashes conditions:
   4  * induces system failures at predefined crashpoints and under predefined
   5  * operational conditions in order to evaluate the reliability of kernel
   6  * sanity checking and crash dumps obtained using different dumping
   7  * solutions.
   8  *
   9  * Copyright (C) IBM Corporation, 2006
  10  *
  11  * Author: Ankita Garg <ankita@in.ibm.com>
  12  *
  13  * It is adapted from the Linux Kernel Dump Test Tool by
  14  * Fernando Luis Vazquez Cao <http://lkdtt.sourceforge.net>
  15  *
  16  * Debugfs support added by Simon Kagstrom <simon.kagstrom@netinsight.net>
  17  *
  18  * See Documentation/fault-injection/provoke-crashes.rst for instructions
  19  */
  20 #include "lkdtm.h"
  21 #include <linux/fs.h>
  22 #include <linux/module.h>
  23 #include <linux/buffer_head.h>
  24 #include <linux/kprobes.h>
  25 #include <linux/list.h>
  26 #include <linux/init.h>
  27 #include <linux/slab.h>
  28 #include <linux/debugfs.h>
  29 
  30 #define DEFAULT_COUNT 10
  31 
  32 static int lkdtm_debugfs_open(struct inode *inode, struct file *file);
  33 static ssize_t lkdtm_debugfs_read(struct file *f, char __user *user_buf,
  34                 size_t count, loff_t *off);
  35 static ssize_t direct_entry(struct file *f, const char __user *user_buf,
  36                             size_t count, loff_t *off);
  37 
  38 #ifdef CONFIG_KPROBES
  39 static int lkdtm_kprobe_handler(struct kprobe *kp, struct pt_regs *regs);
  40 static ssize_t lkdtm_debugfs_entry(struct file *f,
  41                                    const char __user *user_buf,
  42                                    size_t count, loff_t *off);
  43 # define CRASHPOINT_KPROBE(_symbol)                             \
  44                 .kprobe = {                                     \
  45                         .symbol_name = (_symbol),               \
  46                         .pre_handler = lkdtm_kprobe_handler,    \
  47                 },
  48 # define CRASHPOINT_WRITE(_symbol)                              \
  49                 (_symbol) ? lkdtm_debugfs_entry : direct_entry
  50 #else
  51 # define CRASHPOINT_KPROBE(_symbol)
  52 # define CRASHPOINT_WRITE(_symbol)              direct_entry
  53 #endif
  54 
  55 /* Crash points */
  56 struct crashpoint {
  57         const char *name;
  58         const struct file_operations fops;
  59         struct kprobe kprobe;
  60 };
  61 
  62 #define CRASHPOINT(_name, _symbol)                              \
  63         {                                                       \
  64                 .name = _name,                                  \
  65                 .fops = {                                       \
  66                         .read   = lkdtm_debugfs_read,           \
  67                         .llseek = generic_file_llseek,          \
  68                         .open   = lkdtm_debugfs_open,           \
  69                         .write  = CRASHPOINT_WRITE(_symbol)     \
  70                 },                                              \
  71                 CRASHPOINT_KPROBE(_symbol)                      \
  72         }
  73 
  74 /* Define the possible places where we can trigger a crash point. */
  75 static struct crashpoint crashpoints[] = {
  76         CRASHPOINT("DIRECT",             NULL),
  77 #ifdef CONFIG_KPROBES
  78         CRASHPOINT("INT_HARDWARE_ENTRY", "do_IRQ"),
  79         CRASHPOINT("INT_HW_IRQ_EN",      "handle_irq_event"),
  80         CRASHPOINT("INT_TASKLET_ENTRY",  "tasklet_action"),
  81         CRASHPOINT("FS_DEVRW",           "ll_rw_block"),
  82         CRASHPOINT("MEM_SWAPOUT",        "shrink_inactive_list"),
  83         CRASHPOINT("TIMERADD",           "hrtimer_start"),
  84         CRASHPOINT("SCSI_DISPATCH_CMD",  "scsi_dispatch_cmd"),
  85         CRASHPOINT("IDE_CORE_CP",        "generic_ide_ioctl"),
  86 #endif
  87 };
  88 
  89 
  90 /* Crash types. */
  91 struct crashtype {
  92         const char *name;
  93         void (*func)(void);
  94 };
  95 
  96 #define CRASHTYPE(_name)                        \
  97         {                                       \
  98                 .name = __stringify(_name),     \
  99                 .func = lkdtm_ ## _name,        \
 100         }
 101 
 102 /* Define the possible types of crashes that can be triggered. */
 103 static const struct crashtype crashtypes[] = {
 104         CRASHTYPE(PANIC),
 105         CRASHTYPE(BUG),
 106         CRASHTYPE(WARNING),
 107         CRASHTYPE(WARNING_MESSAGE),
 108         CRASHTYPE(EXCEPTION),
 109         CRASHTYPE(LOOP),
 110         CRASHTYPE(EXHAUST_STACK),
 111         CRASHTYPE(CORRUPT_STACK),
 112         CRASHTYPE(CORRUPT_STACK_STRONG),
 113         CRASHTYPE(CORRUPT_LIST_ADD),
 114         CRASHTYPE(CORRUPT_LIST_DEL),
 115         CRASHTYPE(CORRUPT_USER_DS),
 116         CRASHTYPE(STACK_GUARD_PAGE_LEADING),
 117         CRASHTYPE(STACK_GUARD_PAGE_TRAILING),
 118         CRASHTYPE(UNSET_SMEP),
 119         CRASHTYPE(UNALIGNED_LOAD_STORE_WRITE),
 120         CRASHTYPE(OVERWRITE_ALLOCATION),
 121         CRASHTYPE(WRITE_AFTER_FREE),
 122         CRASHTYPE(READ_AFTER_FREE),
 123         CRASHTYPE(WRITE_BUDDY_AFTER_FREE),
 124         CRASHTYPE(READ_BUDDY_AFTER_FREE),
 125         CRASHTYPE(SLAB_FREE_DOUBLE),
 126         CRASHTYPE(SLAB_FREE_CROSS),
 127         CRASHTYPE(SLAB_FREE_PAGE),
 128         CRASHTYPE(SOFTLOCKUP),
 129         CRASHTYPE(HARDLOCKUP),
 130         CRASHTYPE(SPINLOCKUP),
 131         CRASHTYPE(HUNG_TASK),
 132         CRASHTYPE(EXEC_DATA),
 133         CRASHTYPE(EXEC_STACK),
 134         CRASHTYPE(EXEC_KMALLOC),
 135         CRASHTYPE(EXEC_VMALLOC),
 136         CRASHTYPE(EXEC_RODATA),
 137         CRASHTYPE(EXEC_USERSPACE),
 138         CRASHTYPE(EXEC_NULL),
 139         CRASHTYPE(ACCESS_USERSPACE),
 140         CRASHTYPE(ACCESS_NULL),
 141         CRASHTYPE(WRITE_RO),
 142         CRASHTYPE(WRITE_RO_AFTER_INIT),
 143         CRASHTYPE(WRITE_KERN),
 144         CRASHTYPE(REFCOUNT_INC_OVERFLOW),
 145         CRASHTYPE(REFCOUNT_ADD_OVERFLOW),
 146         CRASHTYPE(REFCOUNT_INC_NOT_ZERO_OVERFLOW),
 147         CRASHTYPE(REFCOUNT_ADD_NOT_ZERO_OVERFLOW),
 148         CRASHTYPE(REFCOUNT_DEC_ZERO),
 149         CRASHTYPE(REFCOUNT_DEC_NEGATIVE),
 150         CRASHTYPE(REFCOUNT_DEC_AND_TEST_NEGATIVE),
 151         CRASHTYPE(REFCOUNT_SUB_AND_TEST_NEGATIVE),
 152         CRASHTYPE(REFCOUNT_INC_ZERO),
 153         CRASHTYPE(REFCOUNT_ADD_ZERO),
 154         CRASHTYPE(REFCOUNT_INC_SATURATED),
 155         CRASHTYPE(REFCOUNT_DEC_SATURATED),
 156         CRASHTYPE(REFCOUNT_ADD_SATURATED),
 157         CRASHTYPE(REFCOUNT_INC_NOT_ZERO_SATURATED),
 158         CRASHTYPE(REFCOUNT_ADD_NOT_ZERO_SATURATED),
 159         CRASHTYPE(REFCOUNT_DEC_AND_TEST_SATURATED),
 160         CRASHTYPE(REFCOUNT_SUB_AND_TEST_SATURATED),
 161         CRASHTYPE(REFCOUNT_TIMING),
 162         CRASHTYPE(ATOMIC_TIMING),
 163         CRASHTYPE(USERCOPY_HEAP_SIZE_TO),
 164         CRASHTYPE(USERCOPY_HEAP_SIZE_FROM),
 165         CRASHTYPE(USERCOPY_HEAP_WHITELIST_TO),
 166         CRASHTYPE(USERCOPY_HEAP_WHITELIST_FROM),
 167         CRASHTYPE(USERCOPY_STACK_FRAME_TO),
 168         CRASHTYPE(USERCOPY_STACK_FRAME_FROM),
 169         CRASHTYPE(USERCOPY_STACK_BEYOND),
 170         CRASHTYPE(USERCOPY_KERNEL),
 171         CRASHTYPE(USERCOPY_KERNEL_DS),
 172         CRASHTYPE(STACKLEAK_ERASING),
 173         CRASHTYPE(CFI_FORWARD_PROTO),
 174 };
 175 
 176 
 177 /* Global kprobe entry and crashtype. */
 178 static struct kprobe *lkdtm_kprobe;
 179 static struct crashpoint *lkdtm_crashpoint;
 180 static const struct crashtype *lkdtm_crashtype;
 181 
 182 /* Module parameters */
 183 static int recur_count = -1;
 184 module_param(recur_count, int, 0644);
 185 MODULE_PARM_DESC(recur_count, " Recursion level for the stack overflow test");
 186 
 187 static char* cpoint_name;
 188 module_param(cpoint_name, charp, 0444);
 189 MODULE_PARM_DESC(cpoint_name, " Crash Point, where kernel is to be crashed");
 190 
 191 static char* cpoint_type;
 192 module_param(cpoint_type, charp, 0444);
 193 MODULE_PARM_DESC(cpoint_type, " Crash Point Type, action to be taken on "\
 194                                 "hitting the crash point");
 195 
 196 static int cpoint_count = DEFAULT_COUNT;
 197 module_param(cpoint_count, int, 0644);
 198 MODULE_PARM_DESC(cpoint_count, " Crash Point Count, number of times the "\
 199                                 "crash point is to be hit to trigger action");
 200 
 201 
 202 /* Return the crashtype number or NULL if the name is invalid */
 203 static const struct crashtype *find_crashtype(const char *name)
 204 {
 205         int i;
 206 
 207         for (i = 0; i < ARRAY_SIZE(crashtypes); i++) {
 208                 if (!strcmp(name, crashtypes[i].name))
 209                         return &crashtypes[i];
 210         }
 211 
 212         return NULL;
 213 }
 214 
 215 /*
 216  * This is forced noinline just so it distinctly shows up in the stackdump
 217  * which makes validation of expected lkdtm crashes easier.
 218  */
 219 static noinline void lkdtm_do_action(const struct crashtype *crashtype)
 220 {
 221         if (WARN_ON(!crashtype || !crashtype->func))
 222                 return;
 223         crashtype->func();
 224 }
 225 
 226 static int lkdtm_register_cpoint(struct crashpoint *crashpoint,
 227                                  const struct crashtype *crashtype)
 228 {
 229         int ret;
 230 
 231         /* If this doesn't have a symbol, just call immediately. */
 232         if (!crashpoint->kprobe.symbol_name) {
 233                 lkdtm_do_action(crashtype);
 234                 return 0;
 235         }
 236 
 237         if (lkdtm_kprobe != NULL)
 238                 unregister_kprobe(lkdtm_kprobe);
 239 
 240         lkdtm_crashpoint = crashpoint;
 241         lkdtm_crashtype = crashtype;
 242         lkdtm_kprobe = &crashpoint->kprobe;
 243         ret = register_kprobe(lkdtm_kprobe);
 244         if (ret < 0) {
 245                 pr_info("Couldn't register kprobe %s\n",
 246                         crashpoint->kprobe.symbol_name);
 247                 lkdtm_kprobe = NULL;
 248                 lkdtm_crashpoint = NULL;
 249                 lkdtm_crashtype = NULL;
 250         }
 251 
 252         return ret;
 253 }
 254 
 255 #ifdef CONFIG_KPROBES
 256 /* Global crash counter and spinlock. */
 257 static int crash_count = DEFAULT_COUNT;
 258 static DEFINE_SPINLOCK(crash_count_lock);
 259 
 260 /* Called by kprobe entry points. */
 261 static int lkdtm_kprobe_handler(struct kprobe *kp, struct pt_regs *regs)
 262 {
 263         unsigned long flags;
 264         bool do_it = false;
 265 
 266         if (WARN_ON(!lkdtm_crashpoint || !lkdtm_crashtype))
 267                 return 0;
 268 
 269         spin_lock_irqsave(&crash_count_lock, flags);
 270         crash_count--;
 271         pr_info("Crash point %s of type %s hit, trigger in %d rounds\n",
 272                 lkdtm_crashpoint->name, lkdtm_crashtype->name, crash_count);
 273 
 274         if (crash_count == 0) {
 275                 do_it = true;
 276                 crash_count = cpoint_count;
 277         }
 278         spin_unlock_irqrestore(&crash_count_lock, flags);
 279 
 280         if (do_it)
 281                 lkdtm_do_action(lkdtm_crashtype);
 282 
 283         return 0;
 284 }
 285 
 286 static ssize_t lkdtm_debugfs_entry(struct file *f,
 287                                    const char __user *user_buf,
 288                                    size_t count, loff_t *off)
 289 {
 290         struct crashpoint *crashpoint = file_inode(f)->i_private;
 291         const struct crashtype *crashtype = NULL;
 292         char *buf;
 293         int err;
 294 
 295         if (count >= PAGE_SIZE)
 296                 return -EINVAL;
 297 
 298         buf = (char *)__get_free_page(GFP_KERNEL);
 299         if (!buf)
 300                 return -ENOMEM;
 301         if (copy_from_user(buf, user_buf, count)) {
 302                 free_page((unsigned long) buf);
 303                 return -EFAULT;
 304         }
 305         /* NULL-terminate and remove enter */
 306         buf[count] = '\0';
 307         strim(buf);
 308 
 309         crashtype = find_crashtype(buf);
 310         free_page((unsigned long)buf);
 311 
 312         if (!crashtype)
 313                 return -EINVAL;
 314 
 315         err = lkdtm_register_cpoint(crashpoint, crashtype);
 316         if (err < 0)
 317                 return err;
 318 
 319         *off += count;
 320 
 321         return count;
 322 }
 323 #endif
 324 
 325 /* Generic read callback that just prints out the available crash types */
 326 static ssize_t lkdtm_debugfs_read(struct file *f, char __user *user_buf,
 327                 size_t count, loff_t *off)
 328 {
 329         char *buf;
 330         int i, n, out;
 331 
 332         buf = (char *)__get_free_page(GFP_KERNEL);
 333         if (buf == NULL)
 334                 return -ENOMEM;
 335 
 336         n = scnprintf(buf, PAGE_SIZE, "Available crash types:\n");
 337         for (i = 0; i < ARRAY_SIZE(crashtypes); i++) {
 338                 n += scnprintf(buf + n, PAGE_SIZE - n, "%s\n",
 339                               crashtypes[i].name);
 340         }
 341         buf[n] = '\0';
 342 
 343         out = simple_read_from_buffer(user_buf, count, off,
 344                                       buf, n);
 345         free_page((unsigned long) buf);
 346 
 347         return out;
 348 }
 349 
 350 static int lkdtm_debugfs_open(struct inode *inode, struct file *file)
 351 {
 352         return 0;
 353 }
 354 
 355 /* Special entry to just crash directly. Available without KPROBEs */
 356 static ssize_t direct_entry(struct file *f, const char __user *user_buf,
 357                 size_t count, loff_t *off)
 358 {
 359         const struct crashtype *crashtype;
 360         char *buf;
 361 
 362         if (count >= PAGE_SIZE)
 363                 return -EINVAL;
 364         if (count < 1)
 365                 return -EINVAL;
 366 
 367         buf = (char *)__get_free_page(GFP_KERNEL);
 368         if (!buf)
 369                 return -ENOMEM;
 370         if (copy_from_user(buf, user_buf, count)) {
 371                 free_page((unsigned long) buf);
 372                 return -EFAULT;
 373         }
 374         /* NULL-terminate and remove enter */
 375         buf[count] = '\0';
 376         strim(buf);
 377 
 378         crashtype = find_crashtype(buf);
 379         free_page((unsigned long) buf);
 380         if (!crashtype)
 381                 return -EINVAL;
 382 
 383         pr_info("Performing direct entry %s\n", crashtype->name);
 384         lkdtm_do_action(crashtype);
 385         *off += count;
 386 
 387         return count;
 388 }
 389 
 390 static struct dentry *lkdtm_debugfs_root;
 391 
 392 static int __init lkdtm_module_init(void)
 393 {
 394         struct crashpoint *crashpoint = NULL;
 395         const struct crashtype *crashtype = NULL;
 396         int ret;
 397         int i;
 398 
 399         /* Neither or both of these need to be set */
 400         if ((cpoint_type || cpoint_name) && !(cpoint_type && cpoint_name)) {
 401                 pr_err("Need both cpoint_type and cpoint_name or neither\n");
 402                 return -EINVAL;
 403         }
 404 
 405         if (cpoint_type) {
 406                 crashtype = find_crashtype(cpoint_type);
 407                 if (!crashtype) {
 408                         pr_err("Unknown crashtype '%s'\n", cpoint_type);
 409                         return -EINVAL;
 410                 }
 411         }
 412 
 413         if (cpoint_name) {
 414                 for (i = 0; i < ARRAY_SIZE(crashpoints); i++) {
 415                         if (!strcmp(cpoint_name, crashpoints[i].name))
 416                                 crashpoint = &crashpoints[i];
 417                 }
 418 
 419                 /* Refuse unknown crashpoints. */
 420                 if (!crashpoint) {
 421                         pr_err("Invalid crashpoint %s\n", cpoint_name);
 422                         return -EINVAL;
 423                 }
 424         }
 425 
 426 #ifdef CONFIG_KPROBES
 427         /* Set crash count. */
 428         crash_count = cpoint_count;
 429 #endif
 430 
 431         /* Handle test-specific initialization. */
 432         lkdtm_bugs_init(&recur_count);
 433         lkdtm_perms_init();
 434         lkdtm_usercopy_init();
 435         lkdtm_heap_init();
 436 
 437         /* Register debugfs interface */
 438         lkdtm_debugfs_root = debugfs_create_dir("provoke-crash", NULL);
 439 
 440         /* Install debugfs trigger files. */
 441         for (i = 0; i < ARRAY_SIZE(crashpoints); i++) {
 442                 struct crashpoint *cur = &crashpoints[i];
 443 
 444                 debugfs_create_file(cur->name, 0644, lkdtm_debugfs_root, cur,
 445                                     &cur->fops);
 446         }
 447 
 448         /* Install crashpoint if one was selected. */
 449         if (crashpoint) {
 450                 ret = lkdtm_register_cpoint(crashpoint, crashtype);
 451                 if (ret < 0) {
 452                         pr_info("Invalid crashpoint %s\n", crashpoint->name);
 453                         goto out_err;
 454                 }
 455                 pr_info("Crash point %s of type %s registered\n",
 456                         crashpoint->name, cpoint_type);
 457         } else {
 458                 pr_info("No crash points registered, enable through debugfs\n");
 459         }
 460 
 461         return 0;
 462 
 463 out_err:
 464         debugfs_remove_recursive(lkdtm_debugfs_root);
 465         return ret;
 466 }
 467 
 468 static void __exit lkdtm_module_exit(void)
 469 {
 470         debugfs_remove_recursive(lkdtm_debugfs_root);
 471 
 472         /* Handle test-specific clean-up. */
 473         lkdtm_heap_exit();
 474         lkdtm_usercopy_exit();
 475 
 476         if (lkdtm_kprobe != NULL)
 477                 unregister_kprobe(lkdtm_kprobe);
 478 
 479         pr_info("Crash point unregistered\n");
 480 }
 481 
 482 module_init(lkdtm_module_init);
 483 module_exit(lkdtm_module_exit);
 484 
 485 MODULE_LICENSE("GPL");
 486 MODULE_DESCRIPTION("Kernel crash testing module");

/* [<][>][^][v][top][bottom][index][help] */