1

mac80211 模块上的 rmmod(随着我在 ieee80211_init() 中的更改)正在崩溃。我对 ieee80211_exit() 没有任何更改。但是,在 ieee80211_exit() 上观察到用于释放网格表 tbl 的崩溃。为什么我对 init 函数的更改会导致 exit 函数出现问题?没有我的更改,卸载模块没有问题。

如果我注释掉调用 hmac_sha512() 的语句,则 rmmod 会成功。如果我将此代码集成到像 Hello 这样的自定义模块中,那么 rmmod 就没有问题。如果是同步问题,那么 Hello 模块怎么没有问题呢?我在下面粘贴了函数、hmac_sha512() 和其他相关函数的代码。我也尝试过同步 API。即使在那时,同样的问题也是可以重现的。

深入研究了 mac80211 功能,发现问题是由网格表取消分配引起的。在解除分配之前,必须通过 ieee80211s_start() 分配 Mesh 表,以便获得解除分配的 ieee80211s_stop()。已将日志放入代码中以检查谁在从 mac80211 分配网格表;根据日志,mac80211 中没有人(包括 HMAC 代码)分配网格表。

如果我从 ieee80211_exit() 中注释掉以下行,则 rmmod 可以正常工作:

 

/*

If(mesh_allocated)
    ieee80211_stop;

*/

请提供一些解决此问题的指示。

#define HMAC_SHA512_SIZE 64

struct hmac_sha512_result {
    struct completion completion;
    int err;
};

static void hmac_sha512_complete(struct crypto_async_request *req, int err) {
    struct hmac_sha512_result *r=req->data;
    if(err==-EINPROGRESS)
        return;
    r->err=err;
    complete(&r->completion);
}

int hmac_sha512(const unsigned char *key, // key 
                         const unsigned char *data_in, // data in
                        unsigned char *hash_out, size_t outlen) {  // hash buffer and length

    int rc=0;
    struct crypto_ahash *tfm;
    struct scatterlist sg;
    struct ahash_request *req;
    struct hmac_sha512_result tresult;
    void *hash_buf;
        size_t klen = strlen(key);
        size_t dlen = strlen(data_in); 

        int len = HMAC_SHA512_SIZE;
        char hash_tmp[HMAC_SHA512_SIZE];
    char *hash_res = hash_tmp;

        printk(KERN_INFO "hmac_sha512: HMAC key is %s ", key);

    /* Set hash output to 0 initially */
    memset(hash_out, 0, outlen);

    init_completion(&tresult.completion);
    tfm=crypto_alloc_ahash("hmac(sha512)",0,0);
    if(IS_ERR(tfm)) {
        printk(KERN_ERR "hmac_sha512: crypto_alloc_ahash failed.\n");
        rc=PTR_ERR(tfm);
        goto err_tfm;
    }
    if(!(req=ahash_request_alloc(tfm,GFP_KERNEL))) {
        printk(KERN_ERR "hmac_sha512: failed to allocate request for hmac(sha512)\n");
        rc=-ENOMEM;
        goto err_req;
    }
    if(crypto_ahash_digestsize(tfm)>len) {
        printk(KERN_ERR "hmac_sha512: tfm size > result buffer.\n");
        rc=-EINVAL;
        goto err_req;
    }
    ahash_request_set_callback(req,CRYPTO_TFM_REQ_MAY_BACKLOG,
                    hmac_sha512_complete,&tresult);

    if(!(hash_buf=kzalloc(dlen,GFP_KERNEL))) {
        printk(KERN_ERR "hmac_sha512: failed to kzalloc hash_buf");
        rc=-ENOMEM;
        goto err_hash_buf;
    }
    memcpy(hash_buf,data_in,dlen);
    sg_init_one(&sg,hash_buf,dlen);

    crypto_ahash_clear_flags(tfm,-0);
    if((rc=crypto_ahash_setkey(tfm,key,klen))){
        printk(KERN_ERR "hmac_sha512: crypto_ahash_setkey failed\n");
        goto err_setkey;
    }
    ahash_request_set_crypt(req,&sg,hash_res,dlen);
    rc=crypto_ahash_digest(req);
    switch(rc) {
        case 0:
            while (len--) {
                snprintf(hash_out, outlen, "%02x", (*hash_res++ & 0x0FF));
                hash_out += 2;
            }

                break;
        case -EINPROGRESS:
        case -EBUSY:
            rc=wait_for_completion_interruptible(&tresult.completion);
            if(!rc && !(rc=tresult.err)) {
                INIT_COMPLETION(tresult.completion);
                break;
            } else {
                printk(KERN_ERR "hmac_sha512: wait_for_completion_interruptible failed\n");
                goto out;
            }
        default:
            goto out;
    }

    out:
    err_setkey:
        kfree(hash_buf);
    err_hash_buf:
        ahash_request_free(req);
    err_req:
        crypto_free_ahash(tfm);
    err_tfm:
        return rc;
}
4

0 回答 0