Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v4.10-rc1 546 lines 14 kB view raw
1/* 2 * Linux Kernel Dump Test Module for testing kernel crashes conditions: 3 * induces system failures at predefined crashpoints and under predefined 4 * operational conditions in order to evaluate the reliability of kernel 5 * sanity checking and crash dumps obtained using different dumping 6 * solutions. 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 21 * 22 * Copyright (C) IBM Corporation, 2006 23 * 24 * Author: Ankita Garg <ankita@in.ibm.com> 25 * 26 * It is adapted from the Linux Kernel Dump Test Tool by 27 * Fernando Luis Vazquez Cao <http://lkdtt.sourceforge.net> 28 * 29 * Debugfs support added by Simon Kagstrom <simon.kagstrom@netinsight.net> 30 * 31 * See Documentation/fault-injection/provoke-crashes.txt for instructions 32 */ 33#include "lkdtm.h" 34#include <linux/fs.h> 35#include <linux/module.h> 36#include <linux/buffer_head.h> 37#include <linux/kprobes.h> 38#include <linux/list.h> 39#include <linux/init.h> 40#include <linux/interrupt.h> 41#include <linux/hrtimer.h> 42#include <linux/slab.h> 43#include <scsi/scsi_cmnd.h> 44#include <linux/debugfs.h> 45 46#ifdef CONFIG_IDE 47#include <linux/ide.h> 48#endif 49 50#define DEFAULT_COUNT 10 51 52static int lkdtm_debugfs_open(struct inode *inode, struct file *file); 53static ssize_t lkdtm_debugfs_read(struct file *f, char __user *user_buf, 54 size_t count, loff_t *off); 55static ssize_t direct_entry(struct file *f, const char __user *user_buf, 56 size_t count, loff_t *off); 57 58#ifdef CONFIG_KPROBES 59static void lkdtm_handler(void); 60static ssize_t lkdtm_debugfs_entry(struct file *f, 61 const char __user *user_buf, 62 size_t count, loff_t *off); 63 64 65/* jprobe entry point handlers. */ 66static unsigned int jp_do_irq(unsigned int irq) 67{ 68 lkdtm_handler(); 69 jprobe_return(); 70 return 0; 71} 72 73static irqreturn_t jp_handle_irq_event(unsigned int irq, 74 struct irqaction *action) 75{ 76 lkdtm_handler(); 77 jprobe_return(); 78 return 0; 79} 80 81static void jp_tasklet_action(struct softirq_action *a) 82{ 83 lkdtm_handler(); 84 jprobe_return(); 85} 86 87static void jp_ll_rw_block(int rw, int nr, struct buffer_head *bhs[]) 88{ 89 lkdtm_handler(); 90 jprobe_return(); 91} 92 93struct scan_control; 94 95static unsigned long jp_shrink_inactive_list(unsigned long max_scan, 96 struct zone *zone, 97 struct scan_control *sc) 98{ 99 lkdtm_handler(); 100 jprobe_return(); 101 return 0; 102} 103 104static int jp_hrtimer_start(struct hrtimer *timer, ktime_t tim, 105 const enum hrtimer_mode mode) 106{ 107 lkdtm_handler(); 108 jprobe_return(); 109 return 0; 110} 111 112static int jp_scsi_dispatch_cmd(struct scsi_cmnd *cmd) 113{ 114 lkdtm_handler(); 115 jprobe_return(); 116 return 0; 117} 118 119# ifdef CONFIG_IDE 120static int jp_generic_ide_ioctl(ide_drive_t *drive, struct file *file, 121 struct block_device *bdev, unsigned int cmd, 122 unsigned long arg) 123{ 124 lkdtm_handler(); 125 jprobe_return(); 126 return 0; 127} 128# endif 129#endif 130 131/* Crash points */ 132struct crashpoint { 133 const char *name; 134 const struct file_operations fops; 135 struct jprobe jprobe; 136}; 137 138#define CRASHPOINT(_name, _write, _symbol, _entry) \ 139 { \ 140 .name = _name, \ 141 .fops = { \ 142 .read = lkdtm_debugfs_read, \ 143 .llseek = generic_file_llseek, \ 144 .open = lkdtm_debugfs_open, \ 145 .write = _write, \ 146 }, \ 147 .jprobe = { \ 148 .kp.symbol_name = _symbol, \ 149 .entry = (kprobe_opcode_t *)_entry, \ 150 }, \ 151 } 152 153/* Define the possible places where we can trigger a crash point. */ 154struct crashpoint crashpoints[] = { 155 CRASHPOINT("DIRECT", direct_entry, 156 NULL, NULL), 157#ifdef CONFIG_KPROBES 158 CRASHPOINT("INT_HARDWARE_ENTRY", lkdtm_debugfs_entry, 159 "do_IRQ", jp_do_irq), 160 CRASHPOINT("INT_HW_IRQ_EN", lkdtm_debugfs_entry, 161 "handle_IRQ_event", jp_handle_irq_event), 162 CRASHPOINT("INT_TASKLET_ENTRY", lkdtm_debugfs_entry, 163 "tasklet_action", jp_tasklet_action), 164 CRASHPOINT("FS_DEVRW", lkdtm_debugfs_entry, 165 "ll_rw_block", jp_ll_rw_block), 166 CRASHPOINT("MEM_SWAPOUT", lkdtm_debugfs_entry, 167 "shrink_inactive_list", jp_shrink_inactive_list), 168 CRASHPOINT("TIMERADD", lkdtm_debugfs_entry, 169 "hrtimer_start", jp_hrtimer_start), 170 CRASHPOINT("SCSI_DISPATCH_CMD", lkdtm_debugfs_entry, 171 "scsi_dispatch_cmd", jp_scsi_dispatch_cmd), 172# ifdef CONFIG_IDE 173 CRASHPOINT("IDE_CORE_CP", lkdtm_debugfs_entry, 174 "generic_ide_ioctl", jp_generic_ide_ioctl), 175# endif 176#endif 177}; 178 179 180/* Crash types. */ 181struct crashtype { 182 const char *name; 183 void (*func)(void); 184}; 185 186#define CRASHTYPE(_name) \ 187 { \ 188 .name = __stringify(_name), \ 189 .func = lkdtm_ ## _name, \ 190 } 191 192/* Define the possible types of crashes that can be triggered. */ 193struct crashtype crashtypes[] = { 194 CRASHTYPE(PANIC), 195 CRASHTYPE(BUG), 196 CRASHTYPE(WARNING), 197 CRASHTYPE(EXCEPTION), 198 CRASHTYPE(LOOP), 199 CRASHTYPE(OVERFLOW), 200 CRASHTYPE(CORRUPT_LIST_ADD), 201 CRASHTYPE(CORRUPT_LIST_DEL), 202 CRASHTYPE(CORRUPT_STACK), 203 CRASHTYPE(UNALIGNED_LOAD_STORE_WRITE), 204 CRASHTYPE(OVERWRITE_ALLOCATION), 205 CRASHTYPE(WRITE_AFTER_FREE), 206 CRASHTYPE(READ_AFTER_FREE), 207 CRASHTYPE(WRITE_BUDDY_AFTER_FREE), 208 CRASHTYPE(READ_BUDDY_AFTER_FREE), 209 CRASHTYPE(SOFTLOCKUP), 210 CRASHTYPE(HARDLOCKUP), 211 CRASHTYPE(SPINLOCKUP), 212 CRASHTYPE(HUNG_TASK), 213 CRASHTYPE(EXEC_DATA), 214 CRASHTYPE(EXEC_STACK), 215 CRASHTYPE(EXEC_KMALLOC), 216 CRASHTYPE(EXEC_VMALLOC), 217 CRASHTYPE(EXEC_RODATA), 218 CRASHTYPE(EXEC_USERSPACE), 219 CRASHTYPE(ACCESS_USERSPACE), 220 CRASHTYPE(WRITE_RO), 221 CRASHTYPE(WRITE_RO_AFTER_INIT), 222 CRASHTYPE(WRITE_KERN), 223 CRASHTYPE(ATOMIC_UNDERFLOW), 224 CRASHTYPE(ATOMIC_OVERFLOW), 225 CRASHTYPE(USERCOPY_HEAP_SIZE_TO), 226 CRASHTYPE(USERCOPY_HEAP_SIZE_FROM), 227 CRASHTYPE(USERCOPY_HEAP_FLAG_TO), 228 CRASHTYPE(USERCOPY_HEAP_FLAG_FROM), 229 CRASHTYPE(USERCOPY_STACK_FRAME_TO), 230 CRASHTYPE(USERCOPY_STACK_FRAME_FROM), 231 CRASHTYPE(USERCOPY_STACK_BEYOND), 232 CRASHTYPE(USERCOPY_KERNEL), 233}; 234 235 236/* Global jprobe entry and crashtype. */ 237static struct jprobe *lkdtm_jprobe; 238struct crashpoint *lkdtm_crashpoint; 239struct crashtype *lkdtm_crashtype; 240 241/* Module parameters */ 242static int recur_count = -1; 243module_param(recur_count, int, 0644); 244MODULE_PARM_DESC(recur_count, " Recursion level for the stack overflow test"); 245 246static char* cpoint_name; 247module_param(cpoint_name, charp, 0444); 248MODULE_PARM_DESC(cpoint_name, " Crash Point, where kernel is to be crashed"); 249 250static char* cpoint_type; 251module_param(cpoint_type, charp, 0444); 252MODULE_PARM_DESC(cpoint_type, " Crash Point Type, action to be taken on "\ 253 "hitting the crash point"); 254 255static int cpoint_count = DEFAULT_COUNT; 256module_param(cpoint_count, int, 0644); 257MODULE_PARM_DESC(cpoint_count, " Crash Point Count, number of times the "\ 258 "crash point is to be hit to trigger action"); 259 260 261/* Return the crashtype number or NULL if the name is invalid */ 262static struct crashtype *find_crashtype(const char *name) 263{ 264 int i; 265 266 for (i = 0; i < ARRAY_SIZE(crashtypes); i++) { 267 if (!strcmp(name, crashtypes[i].name)) 268 return &crashtypes[i]; 269 } 270 271 return NULL; 272} 273 274/* 275 * This is forced noinline just so it distinctly shows up in the stackdump 276 * which makes validation of expected lkdtm crashes easier. 277 */ 278static noinline void lkdtm_do_action(struct crashtype *crashtype) 279{ 280 BUG_ON(!crashtype || !crashtype->func); 281 crashtype->func(); 282} 283 284static int lkdtm_register_cpoint(struct crashpoint *crashpoint, 285 struct crashtype *crashtype) 286{ 287 int ret; 288 289 /* If this doesn't have a symbol, just call immediately. */ 290 if (!crashpoint->jprobe.kp.symbol_name) { 291 lkdtm_do_action(crashtype); 292 return 0; 293 } 294 295 if (lkdtm_jprobe != NULL) 296 unregister_jprobe(lkdtm_jprobe); 297 298 lkdtm_crashpoint = crashpoint; 299 lkdtm_crashtype = crashtype; 300 lkdtm_jprobe = &crashpoint->jprobe; 301 ret = register_jprobe(lkdtm_jprobe); 302 if (ret < 0) { 303 pr_info("Couldn't register jprobe %s\n", 304 crashpoint->jprobe.kp.symbol_name); 305 lkdtm_jprobe = NULL; 306 lkdtm_crashpoint = NULL; 307 lkdtm_crashtype = NULL; 308 } 309 310 return ret; 311} 312 313#ifdef CONFIG_KPROBES 314/* Global crash counter and spinlock. */ 315static int crash_count = DEFAULT_COUNT; 316static DEFINE_SPINLOCK(crash_count_lock); 317 318/* Called by jprobe entry points. */ 319static void lkdtm_handler(void) 320{ 321 unsigned long flags; 322 bool do_it = false; 323 324 BUG_ON(!lkdtm_crashpoint || !lkdtm_crashtype); 325 326 spin_lock_irqsave(&crash_count_lock, flags); 327 crash_count--; 328 pr_info("Crash point %s of type %s hit, trigger in %d rounds\n", 329 lkdtm_crashpoint->name, lkdtm_crashtype->name, crash_count); 330 331 if (crash_count == 0) { 332 do_it = true; 333 crash_count = cpoint_count; 334 } 335 spin_unlock_irqrestore(&crash_count_lock, flags); 336 337 if (do_it) 338 lkdtm_do_action(lkdtm_crashtype); 339} 340 341static ssize_t lkdtm_debugfs_entry(struct file *f, 342 const char __user *user_buf, 343 size_t count, loff_t *off) 344{ 345 struct crashpoint *crashpoint = file_inode(f)->i_private; 346 struct crashtype *crashtype = NULL; 347 char *buf; 348 int err; 349 350 if (count >= PAGE_SIZE) 351 return -EINVAL; 352 353 buf = (char *)__get_free_page(GFP_KERNEL); 354 if (!buf) 355 return -ENOMEM; 356 if (copy_from_user(buf, user_buf, count)) { 357 free_page((unsigned long) buf); 358 return -EFAULT; 359 } 360 /* NULL-terminate and remove enter */ 361 buf[count] = '\0'; 362 strim(buf); 363 364 crashtype = find_crashtype(buf); 365 free_page((unsigned long)buf); 366 367 if (!crashtype) 368 return -EINVAL; 369 370 err = lkdtm_register_cpoint(crashpoint, crashtype); 371 if (err < 0) 372 return err; 373 374 *off += count; 375 376 return count; 377} 378#endif 379 380/* Generic read callback that just prints out the available crash types */ 381static ssize_t lkdtm_debugfs_read(struct file *f, char __user *user_buf, 382 size_t count, loff_t *off) 383{ 384 char *buf; 385 int i, n, out; 386 387 buf = (char *)__get_free_page(GFP_KERNEL); 388 if (buf == NULL) 389 return -ENOMEM; 390 391 n = snprintf(buf, PAGE_SIZE, "Available crash types:\n"); 392 for (i = 0; i < ARRAY_SIZE(crashtypes); i++) { 393 n += snprintf(buf + n, PAGE_SIZE - n, "%s\n", 394 crashtypes[i].name); 395 } 396 buf[n] = '\0'; 397 398 out = simple_read_from_buffer(user_buf, count, off, 399 buf, n); 400 free_page((unsigned long) buf); 401 402 return out; 403} 404 405static int lkdtm_debugfs_open(struct inode *inode, struct file *file) 406{ 407 return 0; 408} 409 410/* Special entry to just crash directly. Available without KPROBEs */ 411static ssize_t direct_entry(struct file *f, const char __user *user_buf, 412 size_t count, loff_t *off) 413{ 414 struct crashtype *crashtype; 415 char *buf; 416 417 if (count >= PAGE_SIZE) 418 return -EINVAL; 419 if (count < 1) 420 return -EINVAL; 421 422 buf = (char *)__get_free_page(GFP_KERNEL); 423 if (!buf) 424 return -ENOMEM; 425 if (copy_from_user(buf, user_buf, count)) { 426 free_page((unsigned long) buf); 427 return -EFAULT; 428 } 429 /* NULL-terminate and remove enter */ 430 buf[count] = '\0'; 431 strim(buf); 432 433 crashtype = find_crashtype(buf); 434 free_page((unsigned long) buf); 435 if (!crashtype) 436 return -EINVAL; 437 438 pr_info("Performing direct entry %s\n", crashtype->name); 439 lkdtm_do_action(crashtype); 440 *off += count; 441 442 return count; 443} 444 445static struct dentry *lkdtm_debugfs_root; 446 447static int __init lkdtm_module_init(void) 448{ 449 struct crashpoint *crashpoint = NULL; 450 struct crashtype *crashtype = NULL; 451 int ret = -EINVAL; 452 int i; 453 454 /* Neither or both of these need to be set */ 455 if ((cpoint_type || cpoint_name) && !(cpoint_type && cpoint_name)) { 456 pr_err("Need both cpoint_type and cpoint_name or neither\n"); 457 return -EINVAL; 458 } 459 460 if (cpoint_type) { 461 crashtype = find_crashtype(cpoint_type); 462 if (!crashtype) { 463 pr_err("Unknown crashtype '%s'\n", cpoint_type); 464 return -EINVAL; 465 } 466 } 467 468 if (cpoint_name) { 469 for (i = 0; i < ARRAY_SIZE(crashpoints); i++) { 470 if (!strcmp(cpoint_name, crashpoints[i].name)) 471 crashpoint = &crashpoints[i]; 472 } 473 474 /* Refuse unknown crashpoints. */ 475 if (!crashpoint) { 476 pr_err("Invalid crashpoint %s\n", cpoint_name); 477 return -EINVAL; 478 } 479 } 480 481#ifdef CONFIG_KPROBES 482 /* Set crash count. */ 483 crash_count = cpoint_count; 484#endif 485 486 /* Handle test-specific initialization. */ 487 lkdtm_bugs_init(&recur_count); 488 lkdtm_perms_init(); 489 lkdtm_usercopy_init(); 490 491 /* Register debugfs interface */ 492 lkdtm_debugfs_root = debugfs_create_dir("provoke-crash", NULL); 493 if (!lkdtm_debugfs_root) { 494 pr_err("creating root dir failed\n"); 495 return -ENODEV; 496 } 497 498 /* Install debugfs trigger files. */ 499 for (i = 0; i < ARRAY_SIZE(crashpoints); i++) { 500 struct crashpoint *cur = &crashpoints[i]; 501 struct dentry *de; 502 503 de = debugfs_create_file(cur->name, 0644, lkdtm_debugfs_root, 504 cur, &cur->fops); 505 if (de == NULL) { 506 pr_err("could not create crashpoint %s\n", cur->name); 507 goto out_err; 508 } 509 } 510 511 /* Install crashpoint if one was selected. */ 512 if (crashpoint) { 513 ret = lkdtm_register_cpoint(crashpoint, crashtype); 514 if (ret < 0) { 515 pr_info("Invalid crashpoint %s\n", crashpoint->name); 516 goto out_err; 517 } 518 pr_info("Crash point %s of type %s registered\n", 519 crashpoint->name, cpoint_type); 520 } else { 521 pr_info("No crash points registered, enable through debugfs\n"); 522 } 523 524 return 0; 525 526out_err: 527 debugfs_remove_recursive(lkdtm_debugfs_root); 528 return ret; 529} 530 531static void __exit lkdtm_module_exit(void) 532{ 533 debugfs_remove_recursive(lkdtm_debugfs_root); 534 535 /* Handle test-specific clean-up. */ 536 lkdtm_usercopy_exit(); 537 538 unregister_jprobe(lkdtm_jprobe); 539 pr_info("Crash point unregistered\n"); 540} 541 542module_init(lkdtm_module_init); 543module_exit(lkdtm_module_exit); 544 545MODULE_LICENSE("GPL"); 546MODULE_DESCRIPTION("Kernel crash testing module");