Files
Linux_Drivers/04-Debug/01-Panic/test_ps.c
2024-11-16 15:18:22 +08:00

168 lines
4.4 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/vmalloc.h>
#include <linux/rcupdate.h>
#include <linux/kthread.h>
#include <linux/mutex.h>
static unsigned int test_type;
module_param(test_type, uint, 0400);
MODULE_PARM_DESC(test_type, "set to 1 to try to OOM (default 0)");
static int trigger_oops(void)
{
int *ptr = (int *)0; // 强制类型转换0地址为指针并尝试读取
printk(KERN_ALERT "Dereferenced NULL pointer value: %d\n", *ptr);
return 0;
}
static int trigger_oob(void) {
char *buffer;
int *out_of_bounds;
printk(KERN_INFO "Out-of-bounds memory access test module loaded\n");
// Allocate a small buffer
// buffer = kmalloc(256, GFP_KERNEL);
buffer = vmalloc(PAGE_SIZE * 2);
if (!buffer) {
printk(KERN_ERR "Failed to allocate memory\n");
return -ENOMEM;
}
// Attempt to access memory out of bounds
out_of_bounds = (int *)(buffer + PAGE_SIZE * 3); // Move pointer to the end of the buffer
*out_of_bounds = 0; // This should cause an out-of-bounds write
printk(KERN_INFO "Out-of-bounds Ofst[%lu] memory access performed\n", 256 + PAGE_SIZE);
kfree(buffer);
return 0;
}
static int trigger_oom(void)
{
void *memory = NULL;
size_t memory_size = 0;
printk(KERN_INFO "oom_trigger: Initializing the oom_trigger LKM\n");
memory_size = 100*1024*1024;
while (1) { // 尝试分配大块内存
memory = vmalloc(memory_size);
if (!memory) {
printk(KERN_ALERT "oom_trigger: Memory allocation failed\n");
break;
}
// 仅为防止编译器优化,实际不访问分配的内存
memset(memory, 0, memory_size);
}
return 0;
}
static int test_data = 0;
static struct rcu_head test_rcu_head;
static void bad_rcu_callback(struct rcu_head *head)
{
// 违规操作在RCU回调函数中睡眠这可能导致RCU grace period过长
msleep(1000);
// 违规操作修改被RCU保护的数据结构
test_data++; // 不应在RCU回调中修改全局变量
pr_info("Bad RCU callback executed\n");
}
static void trigger_rcu(void)
{
pr_info("RCU error module loaded\n");
call_rcu(&test_rcu_head, bad_rcu_callback);
}
static int is_ready_thread1, is_ready_thread2;
static struct task_struct *thread1;
static struct task_struct *thread2;
static DEFINE_MUTEX(mutex_a);
static DEFINE_MUTEX(mutex_b);
static int thread_func(void *data)
{
char *name = (char *) data;
if (!strcmp(name, "Thread1")) {
printk(KERN_INFO "%s: Acquiring mutex A...\n", name);
mutex_lock(&mutex_a);
is_ready_thread1 = 1;
while (!is_ready_thread2);
printk(KERN_INFO "%s: Got mutex A. Now trying to acquire mutex B...\n", name);
mutex_lock(&mutex_b); // This will block, causing deadlock
printk(KERN_INFO "%s: Got mutex B.\n", name);
} else {
printk(KERN_INFO "%s: Acquiring mutex B...\n", name);
mutex_lock(&mutex_b);
is_ready_thread2 = 1;
while (!is_ready_thread1);
printk(KERN_INFO "%s: Got mutex B. Now trying to acquire mutex A...\n", name);
mutex_lock(&mutex_a); // This will block, causing deadlock
printk(KERN_INFO "%s: Got mutex A.\n", name);
}
return 0;
}
static int trigger_deadlock(void)
{
thread1 = kthread_run(thread_func, (void *) "Thread1", "thread1");
if (IS_ERR(thread1)) {
printk(KERN_ERR "Failed to create thread1\n");
return PTR_ERR(thread1);
}
thread2 = kthread_run(thread_func, (void *) "Thread2", "thread2");
if (IS_ERR(thread2)) {
printk(KERN_ERR "Failed to create thread2\n");
kthread_stop(thread1);
return PTR_ERR(thread2);
}
return 0;
}
static int trigger_init(void) {
if (test_type == 0)
trigger_oops();
else if (test_type == 1)
trigger_oom();
else if (test_type == 2)
trigger_rcu();
else if (test_type == 3)
trigger_deadlock();
else if (test_type == 4)
trigger_oob();
return 0; // 加载模块不应该有返回值但这里返回0避免编译警告。
}
static void __exit trigger_exit(void) {
if (test_type == 3) {
kthread_stop(thread1);
kthread_stop(thread2);
printk(KERN_INFO "Deadlock trigger exit.\n");
}
}
module_init(trigger_init);
module_exit(trigger_exit);
MODULE_LICENSE("GPL");