core.c (12310B)
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#include <linux/utsname.h> 30 31#define DEFAULT_COUNT 10 32 33static int lkdtm_debugfs_open(struct inode *inode, struct file *file); 34static ssize_t lkdtm_debugfs_read(struct file *f, char __user *user_buf, 35 size_t count, loff_t *off); 36static ssize_t direct_entry(struct file *f, const char __user *user_buf, 37 size_t count, loff_t *off); 38 39#ifdef CONFIG_KPROBES 40static int lkdtm_kprobe_handler(struct kprobe *kp, struct pt_regs *regs); 41static ssize_t lkdtm_debugfs_entry(struct file *f, 42 const char __user *user_buf, 43 size_t count, loff_t *off); 44# define CRASHPOINT_KPROBE(_symbol) \ 45 .kprobe = { \ 46 .symbol_name = (_symbol), \ 47 .pre_handler = lkdtm_kprobe_handler, \ 48 }, 49# define CRASHPOINT_WRITE(_symbol) \ 50 (_symbol) ? lkdtm_debugfs_entry : direct_entry 51#else 52# define CRASHPOINT_KPROBE(_symbol) 53# define CRASHPOINT_WRITE(_symbol) direct_entry 54#endif 55 56/* Crash points */ 57struct crashpoint { 58 const char *name; 59 const struct file_operations fops; 60 struct kprobe kprobe; 61}; 62 63#define CRASHPOINT(_name, _symbol) \ 64 { \ 65 .name = _name, \ 66 .fops = { \ 67 .read = lkdtm_debugfs_read, \ 68 .llseek = generic_file_llseek, \ 69 .open = lkdtm_debugfs_open, \ 70 .write = CRASHPOINT_WRITE(_symbol) \ 71 }, \ 72 CRASHPOINT_KPROBE(_symbol) \ 73 } 74 75/* Define the possible places where we can trigger a crash point. */ 76static struct crashpoint crashpoints[] = { 77 CRASHPOINT("DIRECT", NULL), 78#ifdef CONFIG_KPROBES 79 CRASHPOINT("INT_HARDWARE_ENTRY", "do_IRQ"), 80 CRASHPOINT("INT_HW_IRQ_EN", "handle_irq_event"), 81 CRASHPOINT("INT_TASKLET_ENTRY", "tasklet_action"), 82 CRASHPOINT("FS_DEVRW", "ll_rw_block"), 83 CRASHPOINT("MEM_SWAPOUT", "shrink_inactive_list"), 84 CRASHPOINT("TIMERADD", "hrtimer_start"), 85 CRASHPOINT("SCSI_QUEUE_RQ", "scsi_queue_rq"), 86#endif 87}; 88 89/* List of possible types for crashes that can be triggered. */ 90static const struct crashtype_category *crashtype_categories[] = { 91 &bugs_crashtypes, 92 &heap_crashtypes, 93 &perms_crashtypes, 94 &refcount_crashtypes, 95 &usercopy_crashtypes, 96 &stackleak_crashtypes, 97 &cfi_crashtypes, 98 &fortify_crashtypes, 99#ifdef CONFIG_PPC_64S_HASH_MMU 100 &powerpc_crashtypes, 101#endif 102}; 103 104/* Global kprobe entry and crashtype. */ 105static struct kprobe *lkdtm_kprobe; 106static struct crashpoint *lkdtm_crashpoint; 107static const struct crashtype *lkdtm_crashtype; 108 109/* Module parameters */ 110static int recur_count = -1; 111module_param(recur_count, int, 0644); 112MODULE_PARM_DESC(recur_count, " Recursion level for the stack overflow test"); 113 114static char* cpoint_name; 115module_param(cpoint_name, charp, 0444); 116MODULE_PARM_DESC(cpoint_name, " Crash Point, where kernel is to be crashed"); 117 118static char* cpoint_type; 119module_param(cpoint_type, charp, 0444); 120MODULE_PARM_DESC(cpoint_type, " Crash Point Type, action to be taken on "\ 121 "hitting the crash point"); 122 123static int cpoint_count = DEFAULT_COUNT; 124module_param(cpoint_count, int, 0644); 125MODULE_PARM_DESC(cpoint_count, " Crash Point Count, number of times the "\ 126 "crash point is to be hit to trigger action"); 127 128/* 129 * For test debug reporting when CI systems provide terse summaries. 130 * TODO: Remove this once reasonable reporting exists in most CI systems: 131 * https://lore.kernel.org/lkml/CAHk-=wiFvfkoFixTapvvyPMN9pq5G-+Dys2eSyBa1vzDGAO5+A@mail.gmail.com 132 */ 133char *lkdtm_kernel_info; 134 135/* Return the crashtype number or NULL if the name is invalid */ 136static const struct crashtype *find_crashtype(const char *name) 137{ 138 int cat, idx; 139 140 for (cat = 0; cat < ARRAY_SIZE(crashtype_categories); cat++) { 141 for (idx = 0; idx < crashtype_categories[cat]->len; idx++) { 142 struct crashtype *crashtype; 143 144 crashtype = &crashtype_categories[cat]->crashtypes[idx]; 145 if (!strcmp(name, crashtype->name)) 146 return crashtype; 147 } 148 } 149 150 return NULL; 151} 152 153/* 154 * This is forced noinline just so it distinctly shows up in the stackdump 155 * which makes validation of expected lkdtm crashes easier. 156 */ 157static noinline void lkdtm_do_action(const struct crashtype *crashtype) 158{ 159 if (WARN_ON(!crashtype || !crashtype->func)) 160 return; 161 crashtype->func(); 162} 163 164static int lkdtm_register_cpoint(struct crashpoint *crashpoint, 165 const struct crashtype *crashtype) 166{ 167 int ret; 168 169 /* If this doesn't have a symbol, just call immediately. */ 170 if (!crashpoint->kprobe.symbol_name) { 171 lkdtm_do_action(crashtype); 172 return 0; 173 } 174 175 if (lkdtm_kprobe != NULL) 176 unregister_kprobe(lkdtm_kprobe); 177 178 lkdtm_crashpoint = crashpoint; 179 lkdtm_crashtype = crashtype; 180 lkdtm_kprobe = &crashpoint->kprobe; 181 ret = register_kprobe(lkdtm_kprobe); 182 if (ret < 0) { 183 pr_info("Couldn't register kprobe %s\n", 184 crashpoint->kprobe.symbol_name); 185 lkdtm_kprobe = NULL; 186 lkdtm_crashpoint = NULL; 187 lkdtm_crashtype = NULL; 188 } 189 190 return ret; 191} 192 193#ifdef CONFIG_KPROBES 194/* Global crash counter and spinlock. */ 195static int crash_count = DEFAULT_COUNT; 196static DEFINE_SPINLOCK(crash_count_lock); 197 198/* Called by kprobe entry points. */ 199static int lkdtm_kprobe_handler(struct kprobe *kp, struct pt_regs *regs) 200{ 201 unsigned long flags; 202 bool do_it = false; 203 204 if (WARN_ON(!lkdtm_crashpoint || !lkdtm_crashtype)) 205 return 0; 206 207 spin_lock_irqsave(&crash_count_lock, flags); 208 crash_count--; 209 pr_info("Crash point %s of type %s hit, trigger in %d rounds\n", 210 lkdtm_crashpoint->name, lkdtm_crashtype->name, crash_count); 211 212 if (crash_count == 0) { 213 do_it = true; 214 crash_count = cpoint_count; 215 } 216 spin_unlock_irqrestore(&crash_count_lock, flags); 217 218 if (do_it) 219 lkdtm_do_action(lkdtm_crashtype); 220 221 return 0; 222} 223 224static ssize_t lkdtm_debugfs_entry(struct file *f, 225 const char __user *user_buf, 226 size_t count, loff_t *off) 227{ 228 struct crashpoint *crashpoint = file_inode(f)->i_private; 229 const struct crashtype *crashtype = NULL; 230 char *buf; 231 int err; 232 233 if (count >= PAGE_SIZE) 234 return -EINVAL; 235 236 buf = (char *)__get_free_page(GFP_KERNEL); 237 if (!buf) 238 return -ENOMEM; 239 if (copy_from_user(buf, user_buf, count)) { 240 free_page((unsigned long) buf); 241 return -EFAULT; 242 } 243 /* NULL-terminate and remove enter */ 244 buf[count] = '\0'; 245 strim(buf); 246 247 crashtype = find_crashtype(buf); 248 free_page((unsigned long)buf); 249 250 if (!crashtype) 251 return -EINVAL; 252 253 err = lkdtm_register_cpoint(crashpoint, crashtype); 254 if (err < 0) 255 return err; 256 257 *off += count; 258 259 return count; 260} 261#endif 262 263/* Generic read callback that just prints out the available crash types */ 264static ssize_t lkdtm_debugfs_read(struct file *f, char __user *user_buf, 265 size_t count, loff_t *off) 266{ 267 int n, cat, idx; 268 ssize_t out; 269 char *buf; 270 271 buf = (char *)__get_free_page(GFP_KERNEL); 272 if (buf == NULL) 273 return -ENOMEM; 274 275 n = scnprintf(buf, PAGE_SIZE, "Available crash types:\n"); 276 277 for (cat = 0; cat < ARRAY_SIZE(crashtype_categories); cat++) { 278 for (idx = 0; idx < crashtype_categories[cat]->len; idx++) { 279 struct crashtype *crashtype; 280 281 crashtype = &crashtype_categories[cat]->crashtypes[idx]; 282 n += scnprintf(buf + n, PAGE_SIZE - n, "%s\n", 283 crashtype->name); 284 } 285 } 286 buf[n] = '\0'; 287 288 out = simple_read_from_buffer(user_buf, count, off, 289 buf, n); 290 free_page((unsigned long) buf); 291 292 return out; 293} 294 295static int lkdtm_debugfs_open(struct inode *inode, struct file *file) 296{ 297 return 0; 298} 299 300/* Special entry to just crash directly. Available without KPROBEs */ 301static ssize_t direct_entry(struct file *f, const char __user *user_buf, 302 size_t count, loff_t *off) 303{ 304 const struct crashtype *crashtype; 305 char *buf; 306 307 if (count >= PAGE_SIZE) 308 return -EINVAL; 309 if (count < 1) 310 return -EINVAL; 311 312 buf = (char *)__get_free_page(GFP_KERNEL); 313 if (!buf) 314 return -ENOMEM; 315 if (copy_from_user(buf, user_buf, count)) { 316 free_page((unsigned long) buf); 317 return -EFAULT; 318 } 319 /* NULL-terminate and remove enter */ 320 buf[count] = '\0'; 321 strim(buf); 322 323 crashtype = find_crashtype(buf); 324 free_page((unsigned long) buf); 325 if (!crashtype) 326 return -EINVAL; 327 328 pr_info("Performing direct entry %s\n", crashtype->name); 329 lkdtm_do_action(crashtype); 330 *off += count; 331 332 return count; 333} 334 335#ifndef MODULE 336/* 337 * To avoid needing to export parse_args(), just don't use this code 338 * when LKDTM is built as a module. 339 */ 340struct check_cmdline_args { 341 const char *param; 342 int value; 343}; 344 345static int lkdtm_parse_one(char *param, char *val, 346 const char *unused, void *arg) 347{ 348 struct check_cmdline_args *args = arg; 349 350 /* short circuit if we already found a value. */ 351 if (args->value != -ESRCH) 352 return 0; 353 if (strncmp(param, args->param, strlen(args->param)) == 0) { 354 bool bool_result; 355 int ret; 356 357 ret = kstrtobool(val, &bool_result); 358 if (ret == 0) 359 args->value = bool_result; 360 } 361 return 0; 362} 363 364int lkdtm_check_bool_cmdline(const char *param) 365{ 366 char *command_line; 367 struct check_cmdline_args args = { 368 .param = param, 369 .value = -ESRCH, 370 }; 371 372 command_line = kstrdup(saved_command_line, GFP_KERNEL); 373 if (!command_line) 374 return -ENOMEM; 375 376 parse_args("Setting sysctl args", command_line, 377 NULL, 0, -1, -1, &args, lkdtm_parse_one); 378 379 kfree(command_line); 380 381 return args.value; 382} 383#endif 384 385static struct dentry *lkdtm_debugfs_root; 386 387static int __init lkdtm_module_init(void) 388{ 389 struct crashpoint *crashpoint = NULL; 390 const struct crashtype *crashtype = NULL; 391 int ret; 392 int i; 393 394 /* Neither or both of these need to be set */ 395 if ((cpoint_type || cpoint_name) && !(cpoint_type && cpoint_name)) { 396 pr_err("Need both cpoint_type and cpoint_name or neither\n"); 397 return -EINVAL; 398 } 399 400 if (cpoint_type) { 401 crashtype = find_crashtype(cpoint_type); 402 if (!crashtype) { 403 pr_err("Unknown crashtype '%s'\n", cpoint_type); 404 return -EINVAL; 405 } 406 } 407 408 if (cpoint_name) { 409 for (i = 0; i < ARRAY_SIZE(crashpoints); i++) { 410 if (!strcmp(cpoint_name, crashpoints[i].name)) 411 crashpoint = &crashpoints[i]; 412 } 413 414 /* Refuse unknown crashpoints. */ 415 if (!crashpoint) { 416 pr_err("Invalid crashpoint %s\n", cpoint_name); 417 return -EINVAL; 418 } 419 } 420 421#ifdef CONFIG_KPROBES 422 /* Set crash count. */ 423 crash_count = cpoint_count; 424#endif 425 426 /* Common initialization. */ 427 lkdtm_kernel_info = kasprintf(GFP_KERNEL, "kernel (%s %s)", 428 init_uts_ns.name.release, 429 init_uts_ns.name.machine); 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 463out_err: 464 debugfs_remove_recursive(lkdtm_debugfs_root); 465 return ret; 466} 467 468static 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 kfree(lkdtm_kernel_info); 480 481 pr_info("Crash point unregistered\n"); 482} 483 484module_init(lkdtm_module_init); 485module_exit(lkdtm_module_exit); 486 487MODULE_LICENSE("GPL"); 488MODULE_DESCRIPTION("Kernel crash testing module");