Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.13.7.
  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");