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