内核模块NULL指针解引用及copy_to_user数据回传问题
内核模块my_read函数问题修复方案
核心问题分析
- 空指针错误:
kmalloc存在分配失败返回NULL的可能,直接使用未检查的buffer会触发memcpy() - unable to handle kernel NULL pointer dereference错误。 - 数据无法传递/Buffer为空:
- 需确认
print_log是否正确将temp->data写入buffer(比如是否保证buffer空间充足、是否正确添加字符串终止符); - 原代码每次
copy_to_user都覆盖用户态buff的起始位置,且最终返回0,用户态只能拿到最后一次写入的内容(甚至可能因覆盖丢失全部有效数据)。
- 需确认
- 无法分段回传超长数据:未利用
loff_t *offp记录读取进度,导致单次read无法分段返回数据,用户态无法分次获取全部内容。
修复后的代码实现
#include <linux/slab.h> #include <linux/uaccess.h> #include <linux/fs.h> #define BUFFER_SIZE 1024 ssize_t my_read(struct file *filp, char __user *buff, size_t length, loff_t *offp) { struct log_list *temp; char *buffer = NULL; ssize_t total_written = 0; ssize_t curr_len; loff_t current_off = *offp; int entry_count = 0; // 分配内核缓冲区并检查是否成功 buffer = kmalloc(BUFFER_SIZE, GFP_KERNEL); if (!buffer) { return -ENOMEM; } temp = log_list_head->next; // 跳过已读取过的链表节点 while (temp != NULL && entry_count < current_off) { entry_count++; temp = temp->next; } while (temp != NULL && total_written < length) { // 重置buffer避免残留数据干扰 memset(buffer, 0, BUFFER_SIZE); // 将链表节点数据转换为字符串 print_log(temp->data, buffer); curr_len = strlen(buffer); if (curr_len == 0) { entry_count++; temp = temp->next; continue; } // 限制单次拷贝长度不超过用户请求的剩余空间 if (total_written + curr_len > length) { curr_len = length - total_written; } // 拷贝数据到用户态,检查是否成功 if (copy_to_user(buff + total_written, buffer, curr_len)) { kfree(buffer); return -EFAULT; } total_written += curr_len; entry_count++; temp = temp->next; } // 更新偏移量,记录已读取的节点数 *offp = entry_count; kfree(buffer); // 返回实际写入用户态的字节数,0表示读取完毕 return total_written; }
关键修复点说明
- 空指针防护:添加
kmalloc结果检查,分配失败直接返回-ENOMEM错误码。 - 读取进度跟踪:利用
offp记录已读取的链表节点数,下次read时从上次结束的节点继续,实现分段读取超长数据。 - 避免数据覆盖:每次拷贝到用户态buff的
total_written偏移位置,确保数据不会被覆盖。 - 合法性校验:检查
copy_to_user的返回值,拷贝失败返回-EFAULT;限制单次拷贝长度不超过用户请求的length。 - Buffer重置:每次调用
print_log前清空buffer,避免旧数据残留导致计算错误。
额外注意事项
- 需确保
print_log函数正确添加字符串终止符\0,否则strlen会计算错误甚至触发内存越界。 - 如果单条日志长度超过
BUFFER_SIZE,需修改print_log支持分段输出,或增大内核buffer的大小。 - 若存在多线程修改链表的场景,需添加自旋锁或互斥锁保护链表访问,避免并发问题。
内容的提问来源于stack exchange,提问作者Its me
相关产品推荐
相关产品推荐

