Received: by 2002:a05:7412:b795:b0:e2:908c:2ebd with SMTP id iv21csp32756rdb; Wed, 1 Nov 2023 16:00:48 -0700 (PDT) X-Google-Smtp-Source: AGHT+IGZe/u5w6JVGDrcLeiz6zTdyWLi08uJgZE2ItQITLME9rBaSj+LXe3WzwfCt5YcVraxipQc X-Received: by 2002:a05:6a21:3e14:b0:180:d01b:ba77 with SMTP id bk20-20020a056a213e1400b00180d01bba77mr8160193pzc.60.1698879648122; Wed, 01 Nov 2023 16:00:48 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1698879648; cv=none; d=google.com; s=arc-20160816; b=OtilHqa2aPOj/SXXp+kYqFFnMWuS7wtRFauw3W6PLq3vhb6pKZCYj46xWo6JWDQLUv Z+q+rtg1j0VXBg6jiq7SFnPgggVpL2rZn7yeDdAVZXupl8gEey4D5dU1HE5bm3AX4Q8M K13MCDdRGA9j7AJ5klC5PBeo0BwR7yQC5A2XFoEx+FnJbiquElGoRsx3fKTLZnl/D6xR ed5gy3pni/HwTHyfrpWa32V+3VJ3d5LuUSNHWYHtBPCgQYqc/AwSB8euBKr6WZvRzitK 18l85aVUr0UeXbRgl0imUbx1GL0OnDKyebqxsmcXEH9JIwjjhVYsT7/mIL6wAtsrJif3 Jtyw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:in-reply-to:from :content-language:references:cc:to:subject:mime-version:date :dkim-signature:message-id; bh=RMdmibva2yxlR7N89p7VT8Rue7TcGpAZ1h9dzWXsZhc=; fh=B0c1akj/WKCQ3XqxeY2+4h1y7OlzMG3in+FiLtYqBcg=; b=VNHOmb6AWNZ6i/N7D9N77vuF4TTaGYLlQ50wEHjccYrmirfRWHQMYR5t0N3ut+0Ht5 2s2rWTc38jcPP7A8/VHyKrU5lH7ZenNhirNHXHp8xOGFGmnfSbLwadTcgiiEGj1AkW/Q UUX7hoB5ajYrmb4IX0qlQBeEdzQ+quZ0IF6aOWthFPYoFzD7IoBp7+fpDBjp3fnILgl2 vMJSAkQFiMM4JanNbL1REWgr264n2XTwo5fwG3+hpVJvrW+Ei3ujCpdNyX4smqsJRYeI DmjzpQKZN7xqNzeZXYx7U0VKGKLdfCpz4eQnhZrXh3IM+MtSrzUxjVs5J8Pq+ocrhzAh l3nw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linux.dev header.s=key1 header.b=B92zGrBU; spf=pass (google.com: domain of linux-crypto-owner@vger.kernel.org designates 23.128.96.38 as permitted sender) smtp.mailfrom=linux-crypto-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linux.dev Return-Path: Received: from fry.vger.email (fry.vger.email. [23.128.96.38]) by mx.google.com with ESMTPS id b15-20020a056a00114f00b006b1fec25a82si2536951pfm.403.2023.11.01.16.00.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 01 Nov 2023 16:00:48 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-crypto-owner@vger.kernel.org designates 23.128.96.38 as permitted sender) client-ip=23.128.96.38; Authentication-Results: mx.google.com; dkim=pass header.i=@linux.dev header.s=key1 header.b=B92zGrBU; spf=pass (google.com: domain of linux-crypto-owner@vger.kernel.org designates 23.128.96.38 as permitted sender) smtp.mailfrom=linux-crypto-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linux.dev Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by fry.vger.email (Postfix) with ESMTP id A1CE080A28D3; Wed, 1 Nov 2023 16:00:40 -0700 (PDT) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.10 at fry.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232330AbjKAXAk (ORCPT + 99 others); Wed, 1 Nov 2023 19:00:40 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40608 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233267AbjKAXAj (ORCPT ); Wed, 1 Nov 2023 19:00:39 -0400 X-Greylist: delayed 566 seconds by postgrey-1.37 at lindbergh.monkeyblade.net; Wed, 01 Nov 2023 16:00:33 PDT Received: from out-189.mta1.migadu.com (out-189.mta1.migadu.com [95.215.58.189]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0C81A124 for ; Wed, 1 Nov 2023 16:00:32 -0700 (PDT) Message-ID: <91a6d5a7-7b18-48a2-9a74-7c00509467f8@linux.dev> DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1698879060; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=RMdmibva2yxlR7N89p7VT8Rue7TcGpAZ1h9dzWXsZhc=; b=B92zGrBUlEYHV8O3dCI+PMbzWhGwSt93mlEnToISwJMMAbwQEkOUUX/4SQJ/sV7m4sRA1j KYYeNgIwXeEuQocxwqdpy2mjBO+uol3P5ZWoXtYa790V4qI/OOp8AZP0hJFzNp3Zj2O0Tm jUta1W9ucqdv0FNi7c8+XXlyNOZSb6M= Date: Wed, 1 Nov 2023 22:50:54 +0000 MIME-Version: 1.0 Subject: Re: [PATCH bpf-next v3 1/2] bpf: add skcipher API support to TC/XDP programs To: Martin KaFai Lau , "David S. Miller" , Herbert Xu Cc: bpf@vger.kernel.org, netdev@vger.kernel.org, linux-crypto@vger.kernel.org, Jakub Kicinski , Andrii Nakryiko , Alexei Starovoitov , Mykola Lysenko , Vadim Fedorenko References: <20231031134900.1432945-1-vadfed@meta.com> Content-Language: en-US X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. From: Vadim Fedorenko In-Reply-To: Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit X-Migadu-Flow: FLOW_OUT X-Spam-Status: No, score=-0.9 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI, SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE,URIBL_BLOCKED autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on fry.vger.email Precedence: bulk List-ID: X-Mailing-List: linux-crypto@vger.kernel.org X-Greylist: Sender passed SPF test, not delayed by milter-greylist-4.6.4 (fry.vger.email [0.0.0.0]); Wed, 01 Nov 2023 16:00:40 -0700 (PDT) On 01/11/2023 21:49, Martin KaFai Lau wrote: > On 10/31/23 6:48 AM, Vadim Fedorenko wrote: >> --- /dev/null >> +++ b/kernel/bpf/crypto.c >> @@ -0,0 +1,280 @@ >> +// SPDX-License-Identifier: GPL-2.0-only >> +/* Copyright (c) 2023 Meta, Inc */ >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> + >> +/** >> + * struct bpf_crypto_skcipher_ctx - refcounted BPF sync skcipher >> context structure >> + * @tfm:    The pointer to crypto_sync_skcipher struct. >> + * @rcu:    The RCU head used to free the crypto context with RCU >> safety. >> + * @usage:    Object reference counter. When the refcount goes to 0, the >> + *        memory is released back to the BPF allocator, which provides >> + *        RCU safety. >> + */ >> +struct bpf_crypto_skcipher_ctx { >> +    struct crypto_sync_skcipher *tfm; >> +    struct rcu_head rcu; >> +    refcount_t usage; >> +}; >> + >> +__diag_push(); >> +__diag_ignore_all("-Wmissing-prototypes", >> +          "Global kfuncs as their definitions will be in BTF"); >> + >> +static void *__bpf_dynptr_data_ptr(const struct bpf_dynptr_kern *ptr) >> +{ >> +    enum bpf_dynptr_type type; >> + >> +    if (!ptr->data) >> +        return NULL; >> + >> +    type = bpf_dynptr_get_type(ptr); >> + >> +    switch (type) { >> +    case BPF_DYNPTR_TYPE_LOCAL: >> +    case BPF_DYNPTR_TYPE_RINGBUF: >> +        return ptr->data + ptr->offset; >> +    case BPF_DYNPTR_TYPE_SKB: >> +        return skb_pointer_if_linear(ptr->data, ptr->offset, >> __bpf_dynptr_size(ptr)); >> +    case BPF_DYNPTR_TYPE_XDP: >> +    { >> +        void *xdp_ptr = bpf_xdp_pointer(ptr->data, ptr->offset, >> __bpf_dynptr_size(ptr)); > > I suspect what it is doing here (for skb and xdp in particular) is very > similar to bpf_dynptr_slice. Please check if bpf_dynptr_slice(ptr, 0, > NULL, sz) will work. > Well, yes, it's simplified version of bpf_dynptr_slice. The problem is that bpf_dynptr_slice bpf_kfunc which cannot be used in another bpf_kfunc. Should I refactor the code to use it in both places? Like create __bpf_dynptr_slice() which will be internal part of bpf_kfunc? > >> +        if (!IS_ERR_OR_NULL(xdp_ptr)) >> +            return xdp_ptr; >> + >> +        return NULL; >> +    } >> +    default: >> +        WARN_ONCE(true, "unknown dynptr type %d\n", type); >> +        return NULL; >> +    } >> +} >> + >> +/** >> + * bpf_crypto_skcipher_ctx_create() - Create a mutable BPF crypto >> context. >> + * >> + * Allocates a crypto context that can be used, acquired, and >> released by >> + * a BPF program. The crypto context returned by this function must >> either >> + * be embedded in a map as a kptr, or freed with >> bpf_crypto_skcipher_ctx_release(). >> + * >> + * bpf_crypto_skcipher_ctx_create() allocates memory using the BPF >> memory >> + * allocator, and will not block. It may return NULL if no memory is >> available. >> + * @algo: bpf_dynptr which holds string representation of algorithm. >> + * @key:  bpf_dynptr which holds cipher key to do crypto. >> + */ >> +__bpf_kfunc struct bpf_crypto_skcipher_ctx * >> +bpf_crypto_skcipher_ctx_create(const struct bpf_dynptr_kern *palgo, > > Song's patch on __const_str should help on the palgo (which is a string) > also: > https://lore.kernel.org/bpf/20231024235551.2769174-4-song@kernel.org/ > Got it, I'll update it. >> +                   const struct bpf_dynptr_kern *pkey, int *err) >> +{ >> +    struct bpf_crypto_skcipher_ctx *ctx; >> +    char *algo; >> + >> +    if (__bpf_dynptr_size(palgo) > CRYPTO_MAX_ALG_NAME) { >> +        *err = -EINVAL; >> +        return NULL; >> +    } >> + >> +    algo = __bpf_dynptr_data_ptr(palgo); >> + >> +    if (!crypto_has_skcipher(algo, CRYPTO_ALG_TYPE_SKCIPHER, >> CRYPTO_ALG_TYPE_MASK)) { >> +        *err = -EOPNOTSUPP; >> +        return NULL; >> +    } >> + >> +    ctx = kmalloc(sizeof(*ctx), GFP_KERNEL); >> +    if (!ctx) { >> +        *err = -ENOMEM; >> +        return NULL; >> +    } >> + >> +    memset(ctx, 0, sizeof(*ctx)); > > nit. kzalloc() > >> + >> +    ctx->tfm = crypto_alloc_sync_skcipher(algo, 0, 0); >> +    if (IS_ERR(ctx->tfm)) { >> +        *err = PTR_ERR(ctx->tfm); >> +        ctx->tfm = NULL; >> +        goto err; >> +    } >> + >> +    *err = crypto_sync_skcipher_setkey(ctx->tfm, >> __bpf_dynptr_data_ptr(pkey), >> +                       __bpf_dynptr_size(pkey)); >> +    if (*err) >> +        goto err; >> + >> +    refcount_set(&ctx->usage, 1); >> + >> +    return ctx; >> +err: >> +    if (ctx->tfm) >> +        crypto_free_sync_skcipher(ctx->tfm); >> +    kfree(ctx); >> + >> +    return NULL; >> +} > > [ ... ] > >> +static int bpf_crypto_skcipher_crypt(struct crypto_sync_skcipher *tfm, >> +                     const struct bpf_dynptr_kern *src, >> +                     struct bpf_dynptr_kern *dst, >> +                     const struct bpf_dynptr_kern *iv, >> +                     bool decrypt) >> +{ >> +    struct skcipher_request *req = NULL; >> +    struct scatterlist sgin, sgout; >> +    int err; >> + >> +    if (crypto_sync_skcipher_get_flags(tfm) & CRYPTO_TFM_NEED_KEY) >> +        return -EINVAL; >> + >> +    if (__bpf_dynptr_is_rdonly(dst)) >> +        return -EINVAL; >> + >> +    if (!__bpf_dynptr_size(dst) || !__bpf_dynptr_size(src)) >> +        return -EINVAL; >> + >> +    if (__bpf_dynptr_size(iv) != crypto_sync_skcipher_ivsize(tfm)) >> +        return -EINVAL; >> + >> +    req = skcipher_request_alloc(&tfm->base, GFP_ATOMIC); > > Doing alloc per packet may kill performance. Is it possible to optimize > it somehow? What is the usual size of the req (e.g. the example in the > selftest)? > In ktls code aead_request is allocated every time encryption is invoked, see tls_decrypt_sg(), apparently per skb. Doesn't look like performance killer. For selftest it's only sizeof(struct skcipher_request). >> +    if (!req) >> +        return -ENOMEM; >> + >> +    sg_init_one(&sgin, __bpf_dynptr_data_ptr(src), >> __bpf_dynptr_size(src)); >> +    sg_init_one(&sgout, __bpf_dynptr_data_ptr(dst), >> __bpf_dynptr_size(dst)); >> + >> +    skcipher_request_set_crypt(req, &sgin, &sgout, >> __bpf_dynptr_size(src), >> +                   __bpf_dynptr_data_ptr(iv)); >> + >> +    err = decrypt ? crypto_skcipher_decrypt(req) : >> crypto_skcipher_encrypt(req); > > I am hitting this with the selftest in patch 2: > > [   39.806675] ============================= > [   39.807243] WARNING: suspicious RCU usage > [   39.807825] 6.6.0-rc7-02091-g17e023652cc1 #336 Tainted: G           O > [   39.808798] ----------------------------- > [   39.809368] kernel/sched/core.c:10149 Illegal context switch in > RCU-bh read-side critical section! > [   39.810589] > [   39.810589] other info that might help us debug this: > [   39.810589] > [   39.811696] > [   39.811696] rcu_scheduler_active = 2, debug_locks = 1 > [   39.812616] 2 locks held by test_progs/1769: > [   39.813249]  #0: ffffffff84dce140 (rcu_read_lock){....}-{1:3}, at: > ip6_finish_output2+0x625/0x1b70 > [   39.814539]  #1: ffffffff84dce1a0 (rcu_read_lock_bh){....}-{1:3}, at: > __dev_queue_xmit+0x1df/0x2c40 > [   39.815813] > [   39.815813] stack backtrace: > [   39.816441] CPU: 1 PID: 1769 Comm: test_progs Tainted: G           O > 6.6.0-rc7-02091-g17e023652cc1 #336 > [   39.817774] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), > BIOS rel-1.14.0-0-g155821a1990b-prebuilt.qemu.org 04/01/2014 > [   39.819312] Call Trace: > [   39.819655]  > [   39.819967]  dump_stack_lvl+0x130/0x1d0 > [   39.822669]  dump_stack+0x14/0x20 > [   39.823136]  lockdep_rcu_suspicious+0x220/0x350 > [   39.823777]  __might_resched+0xe0/0x660 > [   39.827915]  __might_sleep+0x89/0xf0 > [   39.828423]  skcipher_walk_virt+0x55/0x120 > [   39.828990]  crypto_ecb_decrypt+0x159/0x310 > [   39.833846]  crypto_skcipher_decrypt+0xa0/0xd0 > [   39.834481]  bpf_crypto_skcipher_crypt+0x29a/0x3c0 > [   39.837100]  bpf_crypto_skcipher_decrypt+0x56/0x70 > [   39.837770]  bpf_prog_fa576505ab32d186_decrypt_sanity+0x180/0x185 > [   39.838627]  cls_bpf_classify+0x3b6/0xf80 > [   39.839807]  tcf_classify+0x2f4/0x550 > That's odd. skcipher_walk_virt() checks for SKCIPHER_WALK_SLEEP which depends on CRYPTO_TFM_REQ_MAY_SLEEP of tfm, which shouldn't be set for crypto_alloc_sync_skcipher(). I think we need some crypto@ folks to jump in and explain. David, Herbert could you please take a look at the patchset to confirm that crypto API is used properly. >> + >> +    skcipher_request_free(req); >> + >> +    return err; >> +} >> + > >