使用crypto_alloc_hash进行'BUG:使用atomic进行调度'

时间:2015-11-19 12:30:20

标签: c linux-kernel cryptoapi crypt

我正在尝试使用Linux内核的加密库来计算HMAC值,给定密钥和消息。想法是计算HMAC并在iperf会话期间将其插入TCP选项(此部分不相关)。 这是我编写的使用加密库的函数,它需要两个8字节的键(要组合)和组成消息的可变字节数:

void crypto_hmac_sha1(u8 *key_1, u8 *key_2, u32 *hash_out, int arg_num, ...)
{
    struct crypto_ashash *shash;
    struct shash_desc *desc = NULL;
    const char hmac_alg[] = "hmac(sha1)";
    u8 key[16];
    int i;
    int ret;
    int length;
    u8 *msg;
    va_list list;

    /* Initialize result placeholder */
    memset(hash_out, 0, sizeof(hash_out));

    for (i = 0; i < 8; i++)
        key[i] ^= key_1[i];
    for (i = 0; i < 8; i++)
        key[i + 8] ^= key_2[i];

    printk("A1\n");
    shash = crypto_alloc_ahash(hmac_alg, 0, 0);
    printk("A2\n");
    desc = kzalloc(sizeof(*desc) + crypto_shash_descsize(shash), GFP_KERNEL);
    if (!desc)
        goto out;

    desc->tfm = shash;
    desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP;

    ret = crypto_shash_setkey(shash, key, 16);
    if (ret < 0)
        goto out;

    crypto_shash_init(desc);

    for (i = 0; i < arg_num; i++) {
        length = va_arg(list, int);
        msg = va_arg(list, u8 *);
        ret = crypto_shash_update(desc, msg, length);
        if (ret < 0)
            goto out;
    }

    ret = crypto_shash_final(desc, hash_out);
out:
    kfree(desc);
}

错误如下(由于crypto_alloc_ahash尝试获取信号量并且在当前上下文中不允许这样的事实):

BUG: scheduling while atomic: iperf/769/0x00000100
CPU: 0 PID: 769 Comm: iperf Not tainted 4.1.0-gdee0521-dirty #143
Received SIGSEGV in SIGSEGV handler, aborting stack trace!

修正建议?

1 个答案:

答案 0 :(得分:1)

不熟悉crypto库:如果crypto_hmac_sha1的并发执行数有上限,则可以使用预分配哈希算法结构池。鉴于似乎不允许调度/休眠,这样的约束不应该很难找到:硬件线程的数量将会这样做。

此外,如果不允许调度,CRYPTO_TFM_REQ_MAY_SLEEP似乎是可疑的。