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
next prev parent 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