我正在写一个Linux内核模块,在其中我实现了一个链表。 我知道在Linux内核中有一个列表API,但是当我实现它时,我不知道如何使用kmalloc()处理原始指针。 运行几个小时后,内核崩溃,崩溃日志中显示“常规保护错误”。 日志还显示,它是从我的functionsearch链接列表中发生。 显然searchfunction就像下面没有逻辑错误。
/* * Searches in a certain index of hash table for a data * returns NULL if not found else returns pointer of that element in the table */ struct queue_data * search_table(unsigned int hash_index, struct queue_data *new_data) { /* Taking a new queue pointer. Which will be pointing to the queue represented * by new_data at last. */ struct queue_data *ret; /* First initializing it with first queue on the list */ ret = table[hash_index].next; /* Iterating through the list to find the desired queue */ while(ret != NULL) { /* Checking if current queue matches our criteria */ if(ret->saddr == new_data->saddr && ret->daddr == new_data->daddr && ret->dest == new_data->dest && ret->ssrc == new_data->ssrc) { /* It matched. So I can return it */ return ret; } /* It didn't match so I need to go to next queue */ ret = ret->next; } /* No queue matched out criteria. Because if it matched it would have not * come this far. It would have returned before. * So I need to return a NULL. Now value of 'ret' is NULL. * I can return 'ret' */ return ret; }
从逻辑的angular度来看,插入function也是完美无缺的。 由于一般保护错误通常发生在发生无效内存访问时,我从来没有使用除kmalloc()
以外的内存分配。 现在我的问题是,如果我使用kmalloc分配的内存,那么有可能使用无效的内存,我应该检查使用之前?
崩溃日志的分数在这里:
[ffff8804130cb690] general_protection at ffffffff81661c85 [exception RIP: search_table+52] RIP: ffffffffa00bc854 RSP: ffff8804130cb748 RFLAGS: 00010286 RAX: d6d4575455d55555 RBX: ffff88040f46db00 RCX: 0000000000000018 RDX: 02b53202ab706c17 RSI: ffff8803fccaaa00 RDI: 00000000000c2568 RBP: ffff8804130cb748 R8: ffffffff8180cb80 R9: 000000000000016d R10: a3d70a3d70a3d70b R11: ffff8803fccaab58 R12: ffffc9001262cc38 R13: 000000000000079f R14: ffff8803fccaaa00 R15: ffffffffa00cbee8 ORIG_RAX: ffffffffffffffff CS: 0010 SS: 0018
插入时,我用kmalloc检查分配的内存:
/* Allocating and initializing a new queue. * If a queue corresponding to it already exists then it's data will * copied and this queue will be dropped. * Else this queue will be inserted to the hash table that manages the queues. */ new_data = (struct queue_data *)kmalloc(sizeof(struct queue_data), GFP_ATOMIC); if (!new_data) { //printk(KERN_ALERT "pkt_queue EXCEPTION: new_data\n"); return NULL; }
看看你发布的代码,我可以看到的一般保护错误的唯一可能的来源是这一行:
ret = table[hash_index].next;
你没有检查table
的大小,所以也许你正在访问超出界限的内存? 没有办法确定,不知道如何,在哪里声明了什么table
,以及如何初始化它。
查看你的评论之后,说hash_index
是一个unsigned int
,它是HASH_PRIME
宏模数的结果, 可能在某个时候,你遇到了可能的有符号无符号算术问题,所以尽管模数HASH_PRIME
,你实际上超出了界限。 也许补充:
if (hash_index >= HASH_PRIME) hash_index = HASH_PRIME-1;//or error
为了完整起见,正如我在评论中指出的那样,所使用的函数都使用内核的u32
类型。 事实证明,这是你的代码仍然访问错误的内存的原因。 (在手机上键入此更新…恨它)