mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Andrew Morton <akpm@linux-foundation.org>
To: Simon Kagstrom <simon.kagstrom@netinsight.net>
Cc: ebiederm@xmission.com (Eric W. Biederman),
	ankita@in.ibm.com, dedekind1@gmail.com,
	"Américo Wang" <xiyou.wangcong@gmail.com>,
	linux-kernel@vger.kernel.org,
	"David Woodhouse" <dwmw2@infradead.org>,
	"Ingo Molnar" <mingo@elte.hu>,
	mohan@in.ibm.com
Subject: Re: [PATCH] lkdtm: Add debugfs access and loosen KPROBE ties
Date: Wed, 3 Feb 2010 14:55:03 -0800	[thread overview]
Message-ID: <20100203145503.b7f7c5d7.akpm@linux-foundation.org> (raw)
In-Reply-To: <20100203095224.55522f4c@marrow.netinsight.se>

On Wed, 3 Feb 2010 09:52:24 +0100
Simon Kagstrom <simon.kagstrom@netinsight.net> wrote:

> This patch adds a debugfs interface and additional failure modes to
> LKDTM to provide similar functionality to the provoke-crash driver
> submitted here:
> 
>   http://lwn.net/Articles/371208/
> 
> Crashes can now be induced either through module parameters (as before)
> or through the debugfs interface as in provoke-crash.
> 
> The patch also provides a new "direct" interface, where KPROBES are not
> used, i.e., the crash is invoked directly upon write to the debugfs
> file. When built without KPROBES configured, only this mode is available.
> 
> Signed-off-by: Simon Kagstrom <simon.kagstrom@netinsight.net>
> ---
> I reused the debugfs directory name from provoke-crash since I think the
> name is more descriptive than "lkdtm".
> 
> I also put some documentation in Documentation/fault-injection. While I
> know that the fault-injection framework isn't used for this driver, I
> think the name make sense (that's where I'd look for functionality like
> this).
> 
>
> ...
>
> +static void lkdtm_do_action(enum ctype which)
>  {
> -	printk(KERN_INFO "lkdtm : Crash point %s of type %s hit\n",
> -					 cpoint_name, cpoint_type);
> +	switch (which) {
> +	case PANIC:
> +		panic("dumptest");
> +		break;
> +	case BUG:
> +		BUG();
> +		break;
> +	case EXCEPTION:
> +		*((int *) 0) = 0;
> +		break;
> +	case LOOP:
> +		for (;;);

Please feed the patch through scripts/checkpatch.pl and contemplate the
resulting report.

> +		break;
> +	case OVERFLOW:
> +		(void) recursive_loop(0);
> +		break;
> +	case CORRUPT_STACK:
> +	{
> +		volatile u32 data[8];
> +		volatile u32 *p = data;
> +
> +		p[12] = 0x12345678;
> +	} break;

Like this:

	case CORRUPT_STACK: {
		volatile u32 data[8];
		volatile u32 *p = data;

		p[12] = 0x12345678;
		break;
	}

> +	case UNALIGNED_LOAD_STORE_WRITE:
> +	{
> +		static u8 data[5] __attribute__((aligned(4))) = {1,2,3,4,5};
> +		u32 *p;
> +		u32 val = 0x12345678;
> +
> +		p = (u32*)(data + 1);
> +		if (*p == 0)
> +			val = 0x87654321;
> +		*p = val;
> +	} break;
> +	case OVERWRITE_ALLOCATION:
> +	{
> +		size_t len = 1020;
> +		u32 *data = kmalloc(len, GFP_KERNEL);
> +
> +		data[1024 / sizeof(u32)] = 0x12345678;
> +		kfree(data);
> +	} break;
> +	case WRITE_AFTER_FREE:
> +	{
> +		size_t len = 1024;
> +		u32 *data = kmalloc(len, GFP_KERNEL);
> +
> +		kfree(data);
> +		schedule();
> +		memset(data, 0x78, len);
> +	} break;
> +	case NONE:
> +	default:
> +		break;
> +	}
> +
> +}
> +
>
> ...
>
> +static ssize_t do_register_entry(enum cname which, struct file *f,
> +		const char __user *user_buf, size_t count, loff_t *off)
> +{
> +	char *buf;
> +	int err;
> +
> +	if (count >= PAGE_SIZE)
> +		return -EINVAL;
> +
> +	buf = (char *)__get_free_page(GFP_TEMPORARY);

Someone ought to write

static inline void *__get_free_page_ptr(gfp_t flags)
{
	return (void *)__get_free_page(flags);
}

and then delete 100000000 typecasts.



The use of GFP_TEMPORARY is incorrect.  This page is not reclaimable.

> +	if (!buf)
> +		return -ENOMEM;
> +	if (copy_from_user(buf, user_buf, count)) {
> +		free_page((unsigned long) buf);
> +		return -EFAULT;
> +	}
> +	/* NULL-terminate and remove enter */
> +	buf[count] = '\0';
> +	if (buf[count - 1] == '\r' || buf[count - 1] == '\n')
> +		buf[count - 1] = '\0';

Use strim().

> +	cptype = parse_cp_type(buf, count);
> +	free_page((unsigned long) buf);

Write free_page_ptr() and delete another 100000000.

> +
> +	if (cptype == NONE)
> +		return -EINVAL;
> +
> +	err = lkdtm_register_cpoint(which);
> +	if (err < 0)
> +		return err;
> +
> +	*off += count;
> +
> +	return count;
> +}
> +
>
> ...
>
> +/* Special entry to just crash directly. Available without KPROBEs */
> +static ssize_t direct_entry(struct file *f, const char __user *user_buf,
> +		size_t count, loff_t *off)
> +{
> +	enum ctype type;
> +	char *buf;
> +
> +	if (count >= PAGE_SIZE)
> +		return -EINVAL;
> +	if (count < 1)
> +		return -EINVAL;
> +
> +	buf = (char *)__get_free_page(GFP_TEMPORARY);

GFP_KERNEL

> +	if (!buf)
> +		return -ENOMEM;
> +	if (copy_from_user(buf, user_buf, count)) {
> +		free_page((unsigned long) buf);
> +		return -EFAULT;
> +	}
> +	/* NULL-terminate and remove enter */
> +	buf[count] = '\0';
> +	if (buf[count - 1] == '\r' || buf[count - 1] == '\n')
> +		buf[count - 1] = '\0';

strim().

> +	type = parse_cp_type(buf, count);
> +	free_page((unsigned long) buf);
> +	if (type == NONE)
> +		return -EINVAL;
> +
> +	printk(KERN_INFO "lkdtm : Performing direct entry %s\n",
> +			cp_type_to_str(type));
> +	lkdtm_do_action(type);
> +	*off += count;
> +
> +	return count;
> +}
> +
> +struct crash_entry
> +{

struct crash_entry {

> +	const char *name;
> +	struct file_operations fops;
> +};
> +
> +static struct crash_entry crash_entries[] = {

const, perhaps.

> +	{"DIRECT",		{.read = lkdtm_debugfs_read,
> +			.open = lkdtm_debugfs_open, .write = direct_entry}},
> +	{"INT_HARDWARE_ENTRY",	{.read = lkdtm_debugfs_read,
> +			.open = lkdtm_debugfs_open, .write = int_hardware_entry}},
> +	{"INT_HW_IRQ_EN",	{.read = lkdtm_debugfs_read,
> +			.open = lkdtm_debugfs_open, .write = int_hw_irq_en}},
> +	{"INT_TASKLET_ENTRY",	{.read = lkdtm_debugfs_read,
> +			.open = lkdtm_debugfs_open, .write = int_tasklet_entry}},
> +	{"FS_DEVRW",		{.read = lkdtm_debugfs_read,
> +			.open = lkdtm_debugfs_open, .write = fs_devrw_entry}},
> +	{"MEM_SWAPOUT",		{.read = lkdtm_debugfs_read,
> +			.open = lkdtm_debugfs_open, .write = mem_swapout_entry}},
> +	{"TIMERADD",		{.read = lkdtm_debugfs_read,
> +			.open = lkdtm_debugfs_open, .write = timeradd_entry}},
> +	{"SCSI_DISPATCH_CMD",	{.read = lkdtm_debugfs_read,
> +			.open = lkdtm_debugfs_open, .write = scsi_dispatch_cmd_entry}},
> +	{"IDE_CORE_CP",		{.read = lkdtm_debugfs_read,
> +			.open = lkdtm_debugfs_open, .write = ide_core_cp_entry}},
> +};
> +
> +static struct dentry *lkdtm_debugfs_root;
> +
> +static int __init lkdtm_module_init(void)
> +{
> +	int ret = -EINVAL;
> +	int n_debugfs_entries = 1; /* Assume only the direct entry */
> +	int i;
> +
> +	/* Register debugfs interface */
> +	lkdtm_debugfs_root = debugfs_create_dir("provoke-crash", NULL);
> +	if (!lkdtm_debugfs_root) {
> +		printk(KERN_ERR "lkdtm: creating root dir failed\n");
> +		return -ENODEV;
> +	}
> +
> +#if defined(CONFIG_KPROBES)

#ifdef will suffice

> +	n_debugfs_entries = ARRAY_SIZE(crash_entries);
> +#endif
> +
> +	for (i = 0; i < n_debugfs_entries; i++) {

Sometimes you do

	for (i = ..., i < ...; i++)

and sometimes

	for (i = ..., i < ...; ++i)

The former is more typical.

> +		struct crash_entry *cur = &crash_entries[i];
> +		struct dentry *de;
> +
> +		de = debugfs_create_file(cur->name, 0644, lkdtm_debugfs_root,
> +				NULL, &cur->fops);
> +		if (de == NULL) {
> +			printk(KERN_ERR "lkdtm: could not create %s\n",
> +					cur->name);
> +			goto out_err;
> +		}
> +	}
> +
> +	if (lkdtm_parse_commandline() == -EINVAL) {
> +		printk(KERN_INFO "lkdtm : Invalid command\n");
> +		goto out_err;
>  	}
>  
> -	printk(KERN_INFO "lkdtm : Crash point %s of type %s registered\n",
> -						cpoint_name, cpoint_type);
> +	if (cpoint != INVALID && cptype != NONE)
> +	{

	if (cpoint != INVALID && cptype != NONE) {

> +		ret = lkdtm_register_cpoint(cpoint);
> +		if (ret < 0)
> +		{

ditto

> +			printk(KERN_INFO "lkdtm : Invalid crash point %d\n", cpoint);
> +			goto out_err;
> +		}
> +		printk(KERN_INFO "lkdtm : Crash point %s of type %s registered\n",
> +				cpoint_name, cpoint_type);

Please do s/lkdtm :/lkdtm:/ in all printks.

> +	}
> +	else

	} else {

> +		printk(KERN_INFO "lkdtm : No crash points registered, enable through debugfs\n");
> +

	}

>  	return 0;
> +
> +out_err:
> +	debugfs_remove_recursive(lkdtm_debugfs_root);
> +	return ret;
>  }
>  
>  static void __exit lkdtm_module_exit(void)
>  {
> -        unregister_jprobe(&lkdtm);
> -        printk(KERN_INFO "lkdtm : Crash point unregistered\n");
> +	debugfs_remove_recursive(lkdtm_debugfs_root);
> +
> +	unregister_jprobe(&lkdtm);
> +	printk(KERN_INFO "lkdtm : Crash point unregistered\n");

A colon does not terminate a sentence, so "lkdtm: crash point
unregistered" would be better (applies to whole patch).

>  }
>  
>  module_init(lkdtm_module_init);
> diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
> index 8c82a1d..67b1799 100644
> --- a/lib/Kconfig.debug
> +++ b/lib/Kconfig.debug
> @@ -840,8 +840,7 @@ config DEBUG_FORCE_WEAK_PER_CPU
>  
>  config LKDTM
>  	tristate "Linux Kernel Dump Test Tool Module"
> -	depends on DEBUG_KERNEL
> -	depends on KPROBES
> +	depends on DEBUG_FS
>  	depends on BLOCK
>  	default n
>  	help
> @@ -852,7 +851,7 @@ config LKDTM
>  	called lkdtm.
>  
>  	Documentation on how to use the module can be found in
> -	drivers/misc/lkdtm.c
> +	Documentation/fault-injection/provoke-crashes.txt
>  
>  config FAULT_INJECTION
>  	bool "Fault-injection framework"
> -- 
> 1.6.0.4

  reply	other threads:[~2010-02-03 22:56 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-01-26  9:56 [PATCH] Provide ways of crashing the kernel through debugfs Simon Kagstrom
2010-01-26 10:08 ` Américo Wang
2010-01-26 10:18   ` Simon Kagstrom
2010-01-27  2:53     ` Américo Wang
2010-01-27  7:09       ` Simon Kagstrom
2010-01-28 14:38       ` Artem Bityutskiy
2010-01-29  6:13         ` Simon Kagstrom
2010-01-29 10:33           ` Andrew Morton
2010-02-02  4:16             ` Eric W. Biederman
2010-02-02  8:16               ` Simon Kagstrom
2010-02-03  8:52               ` [PATCH] lkdtm: Add debugfs access and loosen KPROBE ties Simon Kagstrom
2010-02-03 22:55                 ` Andrew Morton [this message]
2010-02-04  9:06                   ` [PATCH v2] " Simon Kagstrom

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20100203145503.b7f7c5d7.akpm@linux-foundation.org \
    --to=akpm@linux-foundation.org \
    --cc=ankita@in.ibm.com \
    --cc=dedekind1@gmail.com \
    --cc=dwmw2@infradead.org \
    --cc=ebiederm@xmission.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@elte.hu \
    --cc=mohan@in.ibm.com \
    --cc=simon.kagstrom@netinsight.net \
    --cc=xiyou.wangcong@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

Powered by JetHome