0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020 #include "lkdtm.h"
0021 #include <linux/fs.h>
0022 #include <linux/module.h>
0023 #include <linux/buffer_head.h>
0024 #include <linux/kprobes.h>
0025 #include <linux/list.h>
0026 #include <linux/init.h>
0027 #include <linux/slab.h>
0028 #include <linux/debugfs.h>
0029 #include <linux/utsname.h>
0030
0031 #define DEFAULT_COUNT 10
0032
0033 static int lkdtm_debugfs_open(struct inode *inode, struct file *file);
0034 static ssize_t lkdtm_debugfs_read(struct file *f, char __user *user_buf,
0035 size_t count, loff_t *off);
0036 static ssize_t direct_entry(struct file *f, const char __user *user_buf,
0037 size_t count, loff_t *off);
0038
0039 #ifdef CONFIG_KPROBES
0040 static int lkdtm_kprobe_handler(struct kprobe *kp, struct pt_regs *regs);
0041 static ssize_t lkdtm_debugfs_entry(struct file *f,
0042 const char __user *user_buf,
0043 size_t count, loff_t *off);
0044 # define CRASHPOINT_KPROBE(_symbol) \
0045 .kprobe = { \
0046 .symbol_name = (_symbol), \
0047 .pre_handler = lkdtm_kprobe_handler, \
0048 },
0049 # define CRASHPOINT_WRITE(_symbol) \
0050 (_symbol) ? lkdtm_debugfs_entry : direct_entry
0051 #else
0052 # define CRASHPOINT_KPROBE(_symbol)
0053 # define CRASHPOINT_WRITE(_symbol) direct_entry
0054 #endif
0055
0056
0057 struct crashpoint {
0058 const char *name;
0059 const struct file_operations fops;
0060 struct kprobe kprobe;
0061 };
0062
0063 #define CRASHPOINT(_name, _symbol) \
0064 { \
0065 .name = _name, \
0066 .fops = { \
0067 .read = lkdtm_debugfs_read, \
0068 .llseek = generic_file_llseek, \
0069 .open = lkdtm_debugfs_open, \
0070 .write = CRASHPOINT_WRITE(_symbol) \
0071 }, \
0072 CRASHPOINT_KPROBE(_symbol) \
0073 }
0074
0075
0076 static struct crashpoint crashpoints[] = {
0077 CRASHPOINT("DIRECT", NULL),
0078 #ifdef CONFIG_KPROBES
0079 CRASHPOINT("INT_HARDWARE_ENTRY", "do_IRQ"),
0080 CRASHPOINT("INT_HW_IRQ_EN", "handle_irq_event"),
0081 CRASHPOINT("INT_TASKLET_ENTRY", "tasklet_action"),
0082 CRASHPOINT("FS_DEVRW", "ll_rw_block"),
0083 CRASHPOINT("MEM_SWAPOUT", "shrink_inactive_list"),
0084 CRASHPOINT("TIMERADD", "hrtimer_start"),
0085 CRASHPOINT("SCSI_QUEUE_RQ", "scsi_queue_rq"),
0086 #endif
0087 };
0088
0089
0090 static const struct crashtype_category *crashtype_categories[] = {
0091 &bugs_crashtypes,
0092 &heap_crashtypes,
0093 &perms_crashtypes,
0094 &refcount_crashtypes,
0095 &usercopy_crashtypes,
0096 &stackleak_crashtypes,
0097 &cfi_crashtypes,
0098 &fortify_crashtypes,
0099 #ifdef CONFIG_PPC_64S_HASH_MMU
0100 &powerpc_crashtypes,
0101 #endif
0102 };
0103
0104
0105 static struct kprobe *lkdtm_kprobe;
0106 static struct crashpoint *lkdtm_crashpoint;
0107 static const struct crashtype *lkdtm_crashtype;
0108
0109
0110 static int recur_count = -1;
0111 module_param(recur_count, int, 0644);
0112 MODULE_PARM_DESC(recur_count, " Recursion level for the stack overflow test");
0113
0114 static char* cpoint_name;
0115 module_param(cpoint_name, charp, 0444);
0116 MODULE_PARM_DESC(cpoint_name, " Crash Point, where kernel is to be crashed");
0117
0118 static char* cpoint_type;
0119 module_param(cpoint_type, charp, 0444);
0120 MODULE_PARM_DESC(cpoint_type, " Crash Point Type, action to be taken on "\
0121 "hitting the crash point");
0122
0123 static int cpoint_count = DEFAULT_COUNT;
0124 module_param(cpoint_count, int, 0644);
0125 MODULE_PARM_DESC(cpoint_count, " Crash Point Count, number of times the "\
0126 "crash point is to be hit to trigger action");
0127
0128
0129
0130
0131
0132
0133 char *lkdtm_kernel_info;
0134
0135
0136 static const struct crashtype *find_crashtype(const char *name)
0137 {
0138 int cat, idx;
0139
0140 for (cat = 0; cat < ARRAY_SIZE(crashtype_categories); cat++) {
0141 for (idx = 0; idx < crashtype_categories[cat]->len; idx++) {
0142 struct crashtype *crashtype;
0143
0144 crashtype = &crashtype_categories[cat]->crashtypes[idx];
0145 if (!strcmp(name, crashtype->name))
0146 return crashtype;
0147 }
0148 }
0149
0150 return NULL;
0151 }
0152
0153
0154
0155
0156
0157 static noinline void lkdtm_do_action(const struct crashtype *crashtype)
0158 {
0159 if (WARN_ON(!crashtype || !crashtype->func))
0160 return;
0161 crashtype->func();
0162 }
0163
0164 static int lkdtm_register_cpoint(struct crashpoint *crashpoint,
0165 const struct crashtype *crashtype)
0166 {
0167 int ret;
0168
0169
0170 if (!crashpoint->kprobe.symbol_name) {
0171 lkdtm_do_action(crashtype);
0172 return 0;
0173 }
0174
0175 if (lkdtm_kprobe != NULL)
0176 unregister_kprobe(lkdtm_kprobe);
0177
0178 lkdtm_crashpoint = crashpoint;
0179 lkdtm_crashtype = crashtype;
0180 lkdtm_kprobe = &crashpoint->kprobe;
0181 ret = register_kprobe(lkdtm_kprobe);
0182 if (ret < 0) {
0183 pr_info("Couldn't register kprobe %s\n",
0184 crashpoint->kprobe.symbol_name);
0185 lkdtm_kprobe = NULL;
0186 lkdtm_crashpoint = NULL;
0187 lkdtm_crashtype = NULL;
0188 }
0189
0190 return ret;
0191 }
0192
0193 #ifdef CONFIG_KPROBES
0194
0195 static int crash_count = DEFAULT_COUNT;
0196 static DEFINE_SPINLOCK(crash_count_lock);
0197
0198
0199 static int lkdtm_kprobe_handler(struct kprobe *kp, struct pt_regs *regs)
0200 {
0201 unsigned long flags;
0202 bool do_it = false;
0203
0204 if (WARN_ON(!lkdtm_crashpoint || !lkdtm_crashtype))
0205 return 0;
0206
0207 spin_lock_irqsave(&crash_count_lock, flags);
0208 crash_count--;
0209 pr_info("Crash point %s of type %s hit, trigger in %d rounds\n",
0210 lkdtm_crashpoint->name, lkdtm_crashtype->name, crash_count);
0211
0212 if (crash_count == 0) {
0213 do_it = true;
0214 crash_count = cpoint_count;
0215 }
0216 spin_unlock_irqrestore(&crash_count_lock, flags);
0217
0218 if (do_it)
0219 lkdtm_do_action(lkdtm_crashtype);
0220
0221 return 0;
0222 }
0223
0224 static ssize_t lkdtm_debugfs_entry(struct file *f,
0225 const char __user *user_buf,
0226 size_t count, loff_t *off)
0227 {
0228 struct crashpoint *crashpoint = file_inode(f)->i_private;
0229 const struct crashtype *crashtype = NULL;
0230 char *buf;
0231 int err;
0232
0233 if (count >= PAGE_SIZE)
0234 return -EINVAL;
0235
0236 buf = (char *)__get_free_page(GFP_KERNEL);
0237 if (!buf)
0238 return -ENOMEM;
0239 if (copy_from_user(buf, user_buf, count)) {
0240 free_page((unsigned long) buf);
0241 return -EFAULT;
0242 }
0243
0244 buf[count] = '\0';
0245 strim(buf);
0246
0247 crashtype = find_crashtype(buf);
0248 free_page((unsigned long)buf);
0249
0250 if (!crashtype)
0251 return -EINVAL;
0252
0253 err = lkdtm_register_cpoint(crashpoint, crashtype);
0254 if (err < 0)
0255 return err;
0256
0257 *off += count;
0258
0259 return count;
0260 }
0261 #endif
0262
0263
0264 static ssize_t lkdtm_debugfs_read(struct file *f, char __user *user_buf,
0265 size_t count, loff_t *off)
0266 {
0267 int n, cat, idx;
0268 ssize_t out;
0269 char *buf;
0270
0271 buf = (char *)__get_free_page(GFP_KERNEL);
0272 if (buf == NULL)
0273 return -ENOMEM;
0274
0275 n = scnprintf(buf, PAGE_SIZE, "Available crash types:\n");
0276
0277 for (cat = 0; cat < ARRAY_SIZE(crashtype_categories); cat++) {
0278 for (idx = 0; idx < crashtype_categories[cat]->len; idx++) {
0279 struct crashtype *crashtype;
0280
0281 crashtype = &crashtype_categories[cat]->crashtypes[idx];
0282 n += scnprintf(buf + n, PAGE_SIZE - n, "%s\n",
0283 crashtype->name);
0284 }
0285 }
0286 buf[n] = '\0';
0287
0288 out = simple_read_from_buffer(user_buf, count, off,
0289 buf, n);
0290 free_page((unsigned long) buf);
0291
0292 return out;
0293 }
0294
0295 static int lkdtm_debugfs_open(struct inode *inode, struct file *file)
0296 {
0297 return 0;
0298 }
0299
0300
0301 static ssize_t direct_entry(struct file *f, const char __user *user_buf,
0302 size_t count, loff_t *off)
0303 {
0304 const struct crashtype *crashtype;
0305 char *buf;
0306
0307 if (count >= PAGE_SIZE)
0308 return -EINVAL;
0309 if (count < 1)
0310 return -EINVAL;
0311
0312 buf = (char *)__get_free_page(GFP_KERNEL);
0313 if (!buf)
0314 return -ENOMEM;
0315 if (copy_from_user(buf, user_buf, count)) {
0316 free_page((unsigned long) buf);
0317 return -EFAULT;
0318 }
0319
0320 buf[count] = '\0';
0321 strim(buf);
0322
0323 crashtype = find_crashtype(buf);
0324 free_page((unsigned long) buf);
0325 if (!crashtype)
0326 return -EINVAL;
0327
0328 pr_info("Performing direct entry %s\n", crashtype->name);
0329 lkdtm_do_action(crashtype);
0330 *off += count;
0331
0332 return count;
0333 }
0334
0335 #ifndef MODULE
0336
0337
0338
0339
0340 struct check_cmdline_args {
0341 const char *param;
0342 int value;
0343 };
0344
0345 static int lkdtm_parse_one(char *param, char *val,
0346 const char *unused, void *arg)
0347 {
0348 struct check_cmdline_args *args = arg;
0349
0350
0351 if (args->value != -ESRCH)
0352 return 0;
0353 if (strncmp(param, args->param, strlen(args->param)) == 0) {
0354 bool bool_result;
0355 int ret;
0356
0357 ret = kstrtobool(val, &bool_result);
0358 if (ret == 0)
0359 args->value = bool_result;
0360 }
0361 return 0;
0362 }
0363
0364 int lkdtm_check_bool_cmdline(const char *param)
0365 {
0366 char *command_line;
0367 struct check_cmdline_args args = {
0368 .param = param,
0369 .value = -ESRCH,
0370 };
0371
0372 command_line = kstrdup(saved_command_line, GFP_KERNEL);
0373 if (!command_line)
0374 return -ENOMEM;
0375
0376 parse_args("Setting sysctl args", command_line,
0377 NULL, 0, -1, -1, &args, lkdtm_parse_one);
0378
0379 kfree(command_line);
0380
0381 return args.value;
0382 }
0383 #endif
0384
0385 static struct dentry *lkdtm_debugfs_root;
0386
0387 static int __init lkdtm_module_init(void)
0388 {
0389 struct crashpoint *crashpoint = NULL;
0390 const struct crashtype *crashtype = NULL;
0391 int ret;
0392 int i;
0393
0394
0395 if ((cpoint_type || cpoint_name) && !(cpoint_type && cpoint_name)) {
0396 pr_err("Need both cpoint_type and cpoint_name or neither\n");
0397 return -EINVAL;
0398 }
0399
0400 if (cpoint_type) {
0401 crashtype = find_crashtype(cpoint_type);
0402 if (!crashtype) {
0403 pr_err("Unknown crashtype '%s'\n", cpoint_type);
0404 return -EINVAL;
0405 }
0406 }
0407
0408 if (cpoint_name) {
0409 for (i = 0; i < ARRAY_SIZE(crashpoints); i++) {
0410 if (!strcmp(cpoint_name, crashpoints[i].name))
0411 crashpoint = &crashpoints[i];
0412 }
0413
0414
0415 if (!crashpoint) {
0416 pr_err("Invalid crashpoint %s\n", cpoint_name);
0417 return -EINVAL;
0418 }
0419 }
0420
0421 #ifdef CONFIG_KPROBES
0422
0423 crash_count = cpoint_count;
0424 #endif
0425
0426
0427 lkdtm_kernel_info = kasprintf(GFP_KERNEL, "kernel (%s %s)",
0428 init_uts_ns.name.release,
0429 init_uts_ns.name.machine);
0430
0431
0432 lkdtm_bugs_init(&recur_count);
0433 lkdtm_perms_init();
0434 lkdtm_usercopy_init();
0435 lkdtm_heap_init();
0436
0437
0438 lkdtm_debugfs_root = debugfs_create_dir("provoke-crash", NULL);
0439
0440
0441 for (i = 0; i < ARRAY_SIZE(crashpoints); i++) {
0442 struct crashpoint *cur = &crashpoints[i];
0443
0444 debugfs_create_file(cur->name, 0644, lkdtm_debugfs_root, cur,
0445 &cur->fops);
0446 }
0447
0448
0449 if (crashpoint) {
0450 ret = lkdtm_register_cpoint(crashpoint, crashtype);
0451 if (ret < 0) {
0452 pr_info("Invalid crashpoint %s\n", crashpoint->name);
0453 goto out_err;
0454 }
0455 pr_info("Crash point %s of type %s registered\n",
0456 crashpoint->name, cpoint_type);
0457 } else {
0458 pr_info("No crash points registered, enable through debugfs\n");
0459 }
0460
0461 return 0;
0462
0463 out_err:
0464 debugfs_remove_recursive(lkdtm_debugfs_root);
0465 return ret;
0466 }
0467
0468 static void __exit lkdtm_module_exit(void)
0469 {
0470 debugfs_remove_recursive(lkdtm_debugfs_root);
0471
0472
0473 lkdtm_heap_exit();
0474 lkdtm_usercopy_exit();
0475
0476 if (lkdtm_kprobe != NULL)
0477 unregister_kprobe(lkdtm_kprobe);
0478
0479 kfree(lkdtm_kernel_info);
0480
0481 pr_info("Crash point unregistered\n");
0482 }
0483
0484 module_init(lkdtm_module_init);
0485 module_exit(lkdtm_module_exit);
0486
0487 MODULE_LICENSE("GPL");
0488 MODULE_DESCRIPTION("Kernel crash testing module");