2

我正在编写一个 linux 内核模块,我在其中实现了一个链表。我知道 linux 内核中有一个列表 API,但是当我实现它时,我不知道它是如何实现的,它使用 kmalloc() 处理原始指针。运行几个小时后,内核崩溃,并且在崩溃日志中显示“General Protection Fault”。日志还显示它是从我的搜索链表功能中发生的。显然搜索功能如下所示,没有逻辑错误。

/*
 * 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;
}

很明显,插入函数在逻辑上也是完美无缺的。由于一般保护错误通常发生在发生无效内存访问并且我从未使用过由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;
    }
4

1 回答 1

3

查看您发布的代码,我可以看到的一般保护错误的唯一可能来源是这一行:

ret = table[hash_index].next;

您没有检查 的大小table,所以也许您正在访问越界内存?无法确定,不知道table声明的方式、位置和内容,以及如何初始化它。

在查看您的评论后,说hash_indexan是宏unsigned int的模数的结果,可能是在某些时候,您遇到可能的有符号无符号算术问题,因此,尽管模数为,您事实越界。也许添加:HASH_PRIMEHASH_PRIME

if (hash_index >= HASH_PRIME) hash_index = HASH_PRIME-1;//or error

只是为了完整起见:正如我在评论中指出的那样,您使用的函数都使用内核的u32类型。事实证明,这就是您的代码仍然访问错误内存的原因。(在手机上输入此更新......讨厌它)

于 2013-12-27T13:20:09.863 回答