From nobody Sun May 24 21:37:38 2026 Received: from mail-yx1-f50.google.com (mail-yx1-f50.google.com [74.125.224.50]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 923003803F7 for ; Thu, 21 May 2026 02:59:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.224.50 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779332372; cv=none; b=C0WEem4xc4YQX3ohcNE0b+FujzrMbqW+AO8ayannn60j1YCY5vdGnN20S9564aSm3K5VPGx79XPy8wJyM4r3ZJhkuL4EtD1Qv17gqiYtWXp9yWYjO7HIe5ZIK+VnXfBoSqijEEgDfjezztea3QcxjncDzbiOXnlEPlIFjgWjl4Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779332372; c=relaxed/simple; bh=oHsfccn7DDbOn6VBM/zSWqYwTq+d7qUjU4CoIduHDQw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ZBPpO+pq+Dn50FF57BOMfivDg/0p+sNldb/fWLz3XkC3NxQ+TS+j1g1gshx0ZsOFqocLqWRze+mTZzNZ50lPqm/sGfl+qsvVs+d9RPt6v/5y9nQeaw1zZIdm0tBioLamjba+Rdx6hTCPWRG/miLn5MqlLgO0ncqjZvlgS1lwZoM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=northecho.dev; spf=none smtp.mailfrom=northecho.dev; dkim=pass (2048-bit key) header.d=northecho-dev.20251104.gappssmtp.com header.i=@northecho-dev.20251104.gappssmtp.com header.b=I/ycwK4T; arc=none smtp.client-ip=74.125.224.50 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=northecho.dev Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=northecho.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=northecho-dev.20251104.gappssmtp.com header.i=@northecho-dev.20251104.gappssmtp.com header.b="I/ycwK4T" Received: by mail-yx1-f50.google.com with SMTP id 956f58d0204a3-65e81d623bbso191843d50.2 for ; Wed, 20 May 2026 19:59:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=northecho-dev.20251104.gappssmtp.com; s=20251104; t=1779332370; x=1779937170; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=+XKb2Lqr4W3lw4U2X+TN89zQnTM+iU4ox03eiLP8Puw=; b=I/ycwK4TMG9SWoBWs7GGWmpyy/zMgqVJjV8Od4XM4lPIgfZjaXoP77LJx6QdLBYdWt jspYHPHHiWy175XjS0m0NYSroj62j1DADFlesGkVd87rJ8+iffHe7cJ4MCPE0dfNWitH EMtrDVqOXk3YS90Pc2S0isRAXcb8tXf8wE8bPRqQcmqqKTE5BkQFBAYsmYBjlRUPMeuJ BmnT1Z1BA2vYfJuBjG4HJNfaxJXfN7JoBYXN/3hxTaF6U3cEEzJZgSgYri2tydgCF0bR +lMbiSVinixoE6mCPLf0n2QtakJQ79NWeMWlFbs62ZWDCptG1gvHAz25ZLk/lcZvRCnK KGbA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1779332370; x=1779937170; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=+XKb2Lqr4W3lw4U2X+TN89zQnTM+iU4ox03eiLP8Puw=; b=bdp9OLMWxdtM6pMgMNcIlFzlsLVQbp+k9ed9PyBz4y1ANsJEfPxZUZtoSu4oWJbf/X xihgVtyuF6owl3TVt/kjk8NmO8nULZlNTOwQQ5rSm8te5yn8Jdm5eUvAUdI7bMAiVv4Y WbxvnnJ1BBFuvUJ/CtSi1PRi8yRFKfVKL3hCWtkbFms4mz7aJOdvBFTI+CDQPiKE8DtH chnP/TEEspDZZf3kMLjmYccA4BGbeGeT6r4yJKvqnLCHnIg63CsW78lbIar5eYtL+SfW mhlQBTAKNNtHedBHfOIaEzB+0z9mIzY+YfUhioqu/W+qUblaDss5nYFCUk/btA1ngYRF XwPg== X-Forwarded-Encrypted: i=1; AFNElJ+RlR9l6KIEbQb2prmDyrlJmYuw1L8OLoi7f+zN+SUe5nBL3R7D2AAvKnVyj0mRKE+lc6b7U0dIqSzFXYE=@vger.kernel.org X-Gm-Message-State: AOJu0Ywhww5TBQIgSW3PrvJDhZLmY79LIkUrywaJZ+2P3/kEx6Wp+fXR j9utsEA/nKzD1teQmmgufRLut0Tru814IsDLTWiAs1s8mcbXqVLGrV8xoJ8PYDDFgRi3 X-Gm-Gg: Acq92OFF6TNXTOpDtmRgGJPu7jUWaGVqblEzJK6V4GfrqquI0/B4FHBTRHqarUWDpev NQ7Pu9XtLdynURid3Vo2U1WWuRi5IOQG8f5pFAZWENDQ2S7qVNO2ghpqBFU5XQDVJAevutcXLgE YnGs23AExIfkRlUga67xt2RpO/iq+pJR3QR1Cqg425rP/WawOKM7Q8j5eIAYXBe3evxQ8WIP7Pi CTLylzQg5k0alyAfz6t+Tp9gv5SVlNkLPxQ5z7uHtjjR6czoMEmxQBsDQWJM8DBiLBEL0MujZzB 8Ce8aPmvIPJv5ILzY28WcKtKFvLHxwnYI4+Gbu1k0eGy6egcTkg212g7LQ7v358fuQ27UvW1pxd naF7tGymOAUeG/i4huTuBPCEQpILMOpp23iuxT7XLaMyjzhuXYK2vfQcv/gsQ3rFh+JFNQToOwe xJS7yyHjBofoUiOGJLo97Fetl23IlfBuhv6j1bRO8ozwK8HeiCtt3DUo2tHTmG4O1SQfCMFdPlj PqgZZuzu2Xq5zG7vbtZF3li5w== X-Received: by 2002:a05:690e:140d:b0:65c:6ffb:303a with SMTP id 956f58d0204a3-65eae2fdc85mr521328d50.8.1779332369665; Wed, 20 May 2026 19:59:29 -0700 (PDT) Received: from kelso.tail8e61da.ts.net (99-10-92-174.lightspeed.rlghnc.sbcglobal.net. [99.10.92.174]) by smtp.gmail.com with ESMTPSA id 956f58d0204a3-65e0d86c850sm10092743d50.1.2026.05.20.19.59.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 20 May 2026 19:59:29 -0700 (PDT) From: Christopher Lusk To: Jakub Kicinski Cc: John Fastabend , Sabrina Dubroca , "David S. Miller" , Eric Dumazet , Paolo Abeni , Simon Horman , Shuah Khan , Alexei Starovoitov , Daniel Borkmann , netdev@vger.kernel.org, bpf@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org, stable@vger.kernel.org Subject: [PATCH net v2 1/2] net: tls: preserve split open record on async encrypt Date: Wed, 20 May 2026 22:58:39 -0400 Message-ID: <20260521025840.976378-2-clusk@northecho.dev> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260521025840.976378-1-clusk@northecho.dev> References: <20260521025840.976378-1-clusk@northecho.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" When the BPF sk_msg verdict sets apply_bytes smaller than the current open record, tls_push_record() splits ctx->open_rec into the record being encrypted and a remainder record. The synchronous path reattaches the remainder to ctx->open_rec before continuing. If the selected AEAD provider completes asynchronously, tls_do_encryption() returns -EINPROGRESS after unhooking ctx->open_rec. tls_push_record() currently returns immediately in that case, before the split remainder is reattached. The remainder is no longer reachable through ctx->open_rec or ctx->tx_list, which can silently drop transmitted data and leak the unreachable tls_rec. Keep the split remainder rooted even when encryption of the first record is pending asynchronously, and continue the BPF verdict drain loop after an async record has been queued. If that loop then hits a later verdict error, wait for the pending async encryption before returning the error so zerocopy user pages cannot be released while cryptd still reads them. Fixes: d3b18ad31f93 ("tls: add bpf support to sk_msg handling") Cc: stable@vger.kernel.org # 4.20+ Signed-off-by: Christopher Lusk Assisted-by: Codex:gpt-5.5 Assisted-by: Claude:claude-opus-4-7 --- net/tls/tls_sw.c | 40 ++++++++++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c index 964ebc268..5b20be5b4 100644 --- a/net/tls/tls_sw.c +++ b/net/tls/tls_sw.c @@ -840,16 +840,19 @@ static int tls_push_record(struct sock *sk, int flags, rc =3D tls_do_encryption(sk, tls_ctx, ctx, req, msg_pl->sg.size + prot->tail_size, i); if (rc < 0) { - if (rc !=3D -EINPROGRESS) { - tls_err_abort(sk, -EBADMSG); - if (split) { - tls_ctx->pending_open_record_frags =3D true; - tls_merge_open_record(sk, rec, tmp, orig_end); - } + if (rc =3D=3D -EINPROGRESS) + goto split_done; + + tls_err_abort(sk, -EBADMSG); + if (split) { + tls_ctx->pending_open_record_frags =3D true; + tls_merge_open_record(sk, rec, tmp, orig_end); } ctx->async_capable =3D 1; return rc; - } else if (split) { + } +split_done: + if (split) { msg_pl =3D &tmp->msg_plaintext; msg_en =3D &tmp->msg_encrypted; sk_msg_trim(sk, msg_en, msg_pl->sg.size + prot->overhead_size); @@ -857,6 +860,11 @@ static int tls_push_record(struct sock *sk, int flags, ctx->open_rec =3D tmp; } =20 + if (rc < 0) { + ctx->async_capable =3D 1; + return rc; + } + return tls_tx_records(sk, flags); } =20 @@ -871,6 +879,8 @@ static int bpf_exec_tx_verdict(struct sk_msg *msg, stru= ct sock *sk, struct sock *sk_redir; struct tls_rec *rec; bool enospc, policy, redir_ingress; + bool async =3D false; + int async_err =3D 0; int err =3D 0, send; u32 delta =3D 0; =20 @@ -920,6 +930,10 @@ static int bpf_exec_tx_verdict(struct sk_msg *msg, str= uct sock *sk, switch (psock->eval) { case __SK_PASS: err =3D tls_push_record(sk, flags, record_type); + if (err =3D=3D -EINPROGRESS) { + async =3D true; + err =3D 0; + } if (err && err !=3D -EINPROGRESS && sk->sk_err =3D=3D EBADMSG) { *copied -=3D sk_msg_free(sk, msg); tls_free_open_rec(sk); @@ -988,8 +1002,18 @@ static int bpf_exec_tx_verdict(struct sk_msg *msg, st= ruct sock *sk, goto more_data; } out_err: + if (async && err && err !=3D -EINPROGRESS) { + async_err =3D tls_encrypt_async_wait(ctx); + if (test_and_clear_bit(BIT_TX_SCHEDULED, &ctx->tx_bitmask)) { + /* tx_lock is held; the worker will reschedule if needed. */ + cancel_delayed_work(&ctx->tx_work.work); + tls_tx_records(sk, flags); + } + if (async_err) + err =3D async_err; + } sk_psock_put(sk, psock); - return err; + return err ?: (async ? -EINPROGRESS : 0); } =20 static int tls_sw_push_pending_record(struct sock *sk, int flags) --=20 2.54.0 From nobody Sun May 24 21:37:38 2026 Received: from mail-yw1-f180.google.com (mail-yw1-f180.google.com [209.85.128.180]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 998E93815DD for ; Thu, 21 May 2026 02:59:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.180 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779332373; cv=none; b=nbLYYa4ELKyIpoV/C5umoGuFaEnocBP9GdY0V0M6BPWDUY4die4AxvQlnM4quAJG4rjWLwlKbNqwJTGtIH80/+bN2LYMo/eCb7w+NG2pmwEOqjhbezVzhVQMqRXJSCXkRRoOeUQvpDG21OoS3wvq37cUpbpRE3jqZGzj1ylQr7Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779332373; c=relaxed/simple; bh=QXGk+N7UKdb5UEa/p2m6D1TJ82lDDhUIOB4+GhpmpN8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=K6rx6TxTyImnSd3FNCls09EBg+3ZA11KccZAImuzI9Qj1O5Qf7Ru6j1tsY17sHvF8C88dWgIYAlbChyg9qE2r08k7dYqnhS/Nm9LKdsKMhBzqxAbfmWY+UEilIDPL1y24nX7mrVNod+4P1VGESP1UzG2f9aH/oC7IBo+gt+7CDw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=northecho.dev; spf=none smtp.mailfrom=northecho.dev; dkim=pass (2048-bit key) header.d=northecho-dev.20251104.gappssmtp.com header.i=@northecho-dev.20251104.gappssmtp.com header.b=afIBeJOe; arc=none smtp.client-ip=209.85.128.180 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=northecho.dev Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=northecho.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=northecho-dev.20251104.gappssmtp.com header.i=@northecho-dev.20251104.gappssmtp.com header.b="afIBeJOe" Received: by mail-yw1-f180.google.com with SMTP id 00721157ae682-7bdf6db2c70so11348207b3.3 for ; Wed, 20 May 2026 19:59:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=northecho-dev.20251104.gappssmtp.com; s=20251104; t=1779332371; x=1779937171; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=mKA+nc2M+9i0cbABiaxwn8cSkvOwNM/DV9gdI4m3CAA=; b=afIBeJOeskmJecIQ3YRoY3doQjgi9DV7RLSyaUKCL2fPbZ5ZtCDp8PVq666VPvyHH6 Yv+c7lRf7I0iXS8YFqKuEFWVVlvYKDycRSUwu+y5gBMz3PnScobQg2kVx1SRebRB2fnl lah57OWk/tw59HE96/3pz+Orr8bX9kXDmBjl8UhWq2LVk1/GunPB4qXhzsYF/QIC9Lp3 sEsOFD/JoPOYgZWsF+hYNLuQdOKw+IXzs8nFW1T/cent859Iec2MyGMfd8NfWzwk04a9 GSqiwOOQYXX7IXirTRhzuJMp8rq16XqTYnWkocXuLacDSwNLJCc9Di06b/hGBehvAa8l Dh6A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1779332371; x=1779937171; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=mKA+nc2M+9i0cbABiaxwn8cSkvOwNM/DV9gdI4m3CAA=; b=EXIBrf4Mzy3EgJOBwTe+hc+VhNM/vsVBgWav01rqP8WmdRKHDDCWLgagy88yj0ANha L07r9Hl/1zu9yPSq9G1UZqT+CJr+s4sMM0PpchwMQwgUbpBVoCWv7WFZpKrUGbhC1Vvl jYfe9e5WDnVc7iWfFGAyyKDcV2Tt/RdqLKTilLpNzj5Aaw4FwqFO/dbQHLKIKyj/H/NR j/uHNDVvyxxWPkA9Mw+4R7O70ilE1TYuVpIwZAAvyAlCnKMRQN2DOad9nh5knYYC3Nem 9/4RnGU8/Y8brkvqVO4hAaqG5CUZf++AN25CyEtH0ouayS14a8U4HebylDpy1XPSFySE Bz0Q== X-Forwarded-Encrypted: i=1; AFNElJ/V60ah9KR4DwV00xAmZAKNGGj1h8bR09xULmokR+xrdFQ85UHFjlUspPgX5BKX5YVnMRqzUwWZTvlCseA=@vger.kernel.org X-Gm-Message-State: AOJu0YxbhsGYpEHdi0gu2SGdtsYh6eLkCokYB4aqTBwdiIobfDwGmnGe 9j97FmD919a/OAI9tSMsGluko7+1HLfjUPWqpZbzOkrzEa8CvSUzR2UTJyO1esEM6hnt X-Gm-Gg: Acq92OHkNRLBcw6Mzo8PRR79S5DsAVvI1zRf9VGTF5A3AknwVNeWq+tpw0l38e4Pyu3 Ct7YXJib0Nr64KjkPxXMVCIdOfagdHnoOAg2Hl+DyWjMPyMKaYn7ovvZReMtUfMBzf6/8Y+7NM1 WPTrTj/9DnL3+rcjYEvcN2kLU6H52eogeGlQmPIEvzbecfVSzrzJgMsZbkob4fyDzT6Qw6o+FXg Tto/yak/DI84qnAp8xA1XgaU/NYWDDjFYb2jSRDiL2jWd1IzwIam02xTcAvRa5FGfMOhJoYcyUP 0LAOdiyMcAi3xJIPPEKBKTnfACd/nlgnKknig8ExUlMBnl2iWf0rkLkwwgtDKzIT0BwDpZZX047 in6hi+ajgbYHFAeEBuiB2ed5I+fMdAHIpCiUrDPoWZJi1MhB3mCpyYsqnM6SAGVYONYrWSuyYXZ bgBfor74718JTR+VdbWsFg9ahqXF8rHw8z0Yev0frMmPV0yKaPZvPPW5DlNbu4+yodIck7DS2rf KxIbXqiVqWlmjE= X-Received: by 2002:a05:690e:bca:b0:650:20d6:7098 with SMTP id 956f58d0204a3-65eae3c0194mr463771d50.4.1779332370609; Wed, 20 May 2026 19:59:30 -0700 (PDT) Received: from kelso.tail8e61da.ts.net (99-10-92-174.lightspeed.rlghnc.sbcglobal.net. [99.10.92.174]) by smtp.gmail.com with ESMTPSA id 956f58d0204a3-65e0d86c850sm10092743d50.1.2026.05.20.19.59.29 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 20 May 2026 19:59:30 -0700 (PDT) From: Christopher Lusk To: Jakub Kicinski Cc: John Fastabend , Sabrina Dubroca , "David S. Miller" , Eric Dumazet , Paolo Abeni , Simon Horman , Shuah Khan , Alexei Starovoitov , Daniel Borkmann , netdev@vger.kernel.org, bpf@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH net v2 2/2] selftests: net: add kTLS async split record regression Date: Wed, 20 May 2026 22:58:40 -0400 Message-ID: <20260521025840.976378-3-clusk@northecho.dev> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260521025840.976378-1-clusk@northecho.dev> References: <20260521025840.976378-1-clusk@northecho.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add a kTLS TX regression test for the BPF sk_msg apply_bytes split-record path. The test sends four 4096-byte writes through a sockmap verdict program that applies 512-byte verdict windows, then verifies that the peer receives the full TLS-protected stream. Run the case once with the synchronous provider and once after instantiating an async pcrypt gcm(aes) provider. Vulnerable kernels silently truncate the async run because the split open-record remainder is lost when encryption returns -EINPROGRESS. Validate the loaded BPF program fd before attaching it so setup failures are reported directly instead of being passed to bpf_prog_attach(). Signed-off-by: Christopher Lusk Assisted-by: Codex:gpt-5.5 Assisted-by: Claude:claude-opus-4-7 --- tools/testing/selftests/net/Makefile | 5 + .../selftests/net/ktls_async_split.bpf.c | 24 ++ .../testing/selftests/net/ktls_async_split.c | 393 ++++++++++++++++++ 3 files changed, 422 insertions(+) create mode 100644 tools/testing/selftests/net/ktls_async_split.bpf.c create mode 100644 tools/testing/selftests/net/ktls_async_split.c diff --git a/tools/testing/selftests/net/Makefile b/tools/testing/selftests= /net/Makefile index f3da38c54..0435327e9 100644 --- a/tools/testing/selftests/net/Makefile +++ b/tools/testing/selftests/net/Makefile @@ -179,6 +179,7 @@ TEST_GEN_PROGS :=3D \ epoll_busy_poll \ icmp_rfc4884 \ ipv6_fragmentation \ + ktls_async_split \ proc_net_pktgen \ reuseaddr_conflict \ reuseport_bpf \ @@ -236,3 +237,7 @@ $(OUTPUT)/bind_bhash: LDLIBS +=3D -lpthread $(OUTPUT)/io_uring_zerocopy_tx: CFLAGS +=3D -I../../../include/ =20 include bpf.mk + +$(OUTPUT)/ktls_async_split: CFLAGS +=3D -I../../../lib +$(OUTPUT)/ktls_async_split: LDLIBS +=3D $(BPFOBJ) -lelf -lz +$(OUTPUT)/ktls_async_split: $(BPFOBJ) diff --git a/tools/testing/selftests/net/ktls_async_split.bpf.c b/tools/tes= ting/selftests/net/ktls_async_split.bpf.c new file mode 100644 index 000000000..c7caafb73 --- /dev/null +++ b/tools/testing/selftests/net/ktls_async_split.bpf.c @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include +#include + +#ifndef SK_PASS +#define SK_PASS 1 +#endif + +char LICENSE[] SEC("license") =3D "GPL"; + +struct { + __uint(type, BPF_MAP_TYPE_SOCKMAP); + __uint(max_entries, 4); + __type(key, __u32); + __type(value, int); +} sock_map SEC(".maps"); + +SEC("sk_msg") +int apply_bytes_verdict(struct sk_msg_md *msg) +{ + bpf_msg_apply_bytes(msg, 512); + return SK_PASS; +} diff --git a/tools/testing/selftests/net/ktls_async_split.c b/tools/testing= /selftests/net/ktls_async_split.c new file mode 100644 index 000000000..5601ce4b5 --- /dev/null +++ b/tools/testing/selftests/net/ktls_async_split.c @@ -0,0 +1,393 @@ +// SPDX-License-Identifier: GPL-2.0 + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "kselftest.h" + +#ifndef SOL_TLS +#define SOL_TLS 282 +#endif + +#define EXPECTED_BYTES 17312 + +static void fill_seq(unsigned char *p, size_t n, unsigned char seed) +{ + size_t i; + + for (i =3D 0; i < n; i++) + p[i] =3D (unsigned char)(seed + i); +} + +static void bump_memlock(void) +{ + struct rlimit r =3D { RLIM_INFINITY, RLIM_INFINITY }; + + setrlimit(RLIMIT_MEMLOCK, &r); +} + +static int run_cmd(const char *cmd) +{ + int ret =3D system(cmd); + + if (ret =3D=3D -1) + return -1; + if (WIFEXITED(ret)) + return WEXITSTATUS(ret); + return 1; +} + +static int instantiate_aead(const char *name) +{ + struct sockaddr_alg sa =3D { + .salg_family =3D AF_ALG, + }; + int fd, ret; + + strncpy((char *)sa.salg_type, "aead", sizeof(sa.salg_type) - 1); + strncpy((char *)sa.salg_name, name, sizeof(sa.salg_name) - 1); + + fd =3D socket(AF_ALG, SOCK_SEQPACKET, 0); + if (fd < 0) + return -errno; + + ret =3D bind(fd, (struct sockaddr *)&sa, sizeof(sa)); + if (ret < 0) + ret =3D -errno; + + close(fd); + return ret; +} + +static bool have_async_pcrypt(void) +{ + FILE *f =3D fopen("/proc/crypto", "r"); + char line[256]; + bool in_driver =3D false; + bool async =3D false; + + if (!f) + return false; + + while (fgets(line, sizeof(line), f)) { + if (!strncmp(line, "driver", 6)) { + in_driver =3D strstr(line, "pcrypt(") && + strstr(line, "gcm"); + async =3D false; + continue; + } + if (in_driver && !strncmp(line, "async", 5)) { + async =3D strstr(line, "yes"); + if (async) { + fclose(f); + return true; + } + } + } + + fclose(f); + return false; +} + +static bool module_loaded(const char *name) +{ + FILE *f =3D fopen("/proc/modules", "r"); + char line[256], mod[128]; + + if (!f) + return false; + + while (fgets(line, sizeof(line), f)) { + if (sscanf(line, "%127s", mod) =3D=3D 1 && !strcmp(mod, name)) { + fclose(f); + return true; + } + } + + fclose(f); + return false; +} + +static int make_listener(unsigned short *port) +{ + struct sockaddr_in addr =3D { + .sin_family =3D AF_INET, + .sin_addr.s_addr =3D htonl(INADDR_LOOPBACK), + .sin_port =3D 0, + }; + socklen_t len =3D sizeof(addr); + int fd, one =3D 1; + + fd =3D socket(AF_INET, SOCK_STREAM, 0); + if (fd < 0) + return -errno; + + if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) < 0) + goto err; + if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) + goto err; + if (listen(fd, 1) < 0) + goto err; + if (getsockname(fd, (struct sockaddr *)&addr, &len) < 0) + goto err; + + *port =3D ntohs(addr.sin_port); + return fd; + +err: + close(fd); + return -errno; +} + +static int connect_client(unsigned short port) +{ + struct sockaddr_in addr =3D { + .sin_family =3D AF_INET, + .sin_addr.s_addr =3D htonl(INADDR_LOOPBACK), + .sin_port =3D htons(port), + }; + int fd; + + fd =3D socket(AF_INET, SOCK_STREAM, 0); + if (fd < 0) + return -errno; + if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { + close(fd); + return -errno; + } + + return fd; +} + +static int make_tcp_pair(int *client_fd, int *peer_fd) +{ + unsigned short port =3D 0; + int listen_fd, c, p; + + listen_fd =3D make_listener(&port); + if (listen_fd < 0) + return listen_fd; + + c =3D connect_client(port); + if (c < 0) { + close(listen_fd); + return c; + } + + p =3D accept(listen_fd, NULL, NULL); + close(listen_fd); + if (p < 0) { + close(c); + return -errno; + } + + *client_fd =3D c; + *peer_fd =3D p; + return 0; +} + +static int enable_ktls_tx(int fd) +{ + struct tls12_crypto_info_aes_gcm_128 info; + static const char ulp[] =3D "tls"; + + if (setsockopt(fd, IPPROTO_TCP, TCP_ULP, ulp, sizeof(ulp)) < 0) + return -errno; + + memset(&info, 0, sizeof(info)); + info.info.version =3D TLS_1_2_VERSION; + info.info.cipher_type =3D TLS_CIPHER_AES_GCM_128; + fill_seq(info.iv, sizeof(info.iv), 0x11); + fill_seq(info.key, sizeof(info.key), 0x22); + fill_seq(info.salt, sizeof(info.salt), 0x33); + fill_seq(info.rec_seq, sizeof(info.rec_seq), 0x44); + + if (setsockopt(fd, SOL_TLS, TLS_TX, &info, sizeof(info)) < 0) + return -errno; + + return 0; +} + +static int attach_bpf(const char *obj_path, int sock_fd, struct bpf_object= **obj_out) +{ + struct bpf_object *obj; + struct bpf_program *prog; + int map_fd, prog_fd; + __u32 key =3D 0; + + obj =3D bpf_object__open_file(obj_path, NULL); + if (libbpf_get_error(obj)) + return -EINVAL; + if (bpf_object__load(obj)) + return -EINVAL; + + prog =3D bpf_object__find_program_by_name(obj, "apply_bytes_verdict"); + if (!prog) + return -ENOENT; + prog_fd =3D bpf_program__fd(prog); + if (prog_fd < 0) + return prog_fd; + + map_fd =3D bpf_object__find_map_fd_by_name(obj, "sock_map"); + if (map_fd < 0) + return -ENOENT; + + if (bpf_prog_attach(prog_fd, map_fd, BPF_SK_MSG_VERDICT, 0)) + return -errno; + if (bpf_map_update_elem(map_fd, &key, &sock_fd, BPF_ANY)) + return -errno; + + *obj_out =3D obj; + return 0; +} + +static void server_loop(int fd, int out_fd) +{ + unsigned char buf[16384]; + int total =3D 0; + + for (;;) { + ssize_t n =3D read(fd, buf, sizeof(buf)); + + if (n < 0) { + if (errno =3D=3D EINTR) + continue; + _exit(1); + } + if (!n) + break; + total +=3D (int)n; + } + + (void)write(out_fd, &total, sizeof(total)); + close(fd); + close(out_fd); + _exit(0); +} + +static int run_case(const char *obj_path, int *server_read) +{ + struct bpf_object *obj =3D NULL; + unsigned char buf[4096]; + int client_fd =3D -1, peer_fd =3D -1, pipefd[2] =3D { -1, -1 }; + pid_t pid; + int status, ret, i; + ssize_t n, got; + + ret =3D make_tcp_pair(&client_fd, &peer_fd); + if (ret) + return ret; + if (pipe(pipefd)) { + close(client_fd); + close(peer_fd); + return -errno; + } + + pid =3D fork(); + if (pid < 0) { + close(client_fd); + close(peer_fd); + close(pipefd[0]); + close(pipefd[1]); + return -errno; + } + if (!pid) { + close(pipefd[0]); + server_loop(peer_fd, pipefd[1]); + } + + close(peer_fd); + close(pipefd[1]); + + ret =3D attach_bpf(obj_path, client_fd, &obj); + if (ret) + goto out; + ret =3D enable_ktls_tx(client_fd); + if (ret) + goto out; + + fill_seq(buf, sizeof(buf), 0x80); + for (i =3D 0; i < 4; i++) { + n =3D send(client_fd, buf, sizeof(buf), 0); + if (n !=3D sizeof(buf)) { + ret =3D n < 0 ? -errno : -EIO; + goto out; + } + } + + shutdown(client_fd, SHUT_WR); + got =3D read(pipefd[0], server_read, sizeof(*server_read)); + if (got !=3D sizeof(*server_read)) + ret =3D -EIO; + +out: + close(client_fd); + close(pipefd[0]); + if (obj) + bpf_object__close(obj); + if (waitpid(pid, &status, 0) < 0) + return -errno; + if (!ret && (!WIFEXITED(status) || WEXITSTATUS(status))) + ret =3D -EIO; + return ret; +} + +int main(int argc, char **argv) +{ + const char *obj_path =3D argc > 1 ? argv[1] : "./ktls_async_split.bpf.o"; + int sync_read =3D 0, async_read =3D 0, ret; + + ksft_print_header(); + ksft_set_plan(2); + bump_memlock(); + + if (run_cmd("modprobe tls >/dev/null 2>&1") && !module_loaded("tls")) + ksft_exit_skip("missing tls module\n"); + + /* Keep the first run on the synchronous provider. */ + run_cmd("modprobe -r pcrypt >/dev/null 2>&1"); + ret =3D run_case(obj_path, &sync_read); + if (ret) + ksft_exit_fail_msg("sync case failed: %s\n", strerror(-ret)); + if (sync_read !=3D EXPECTED_BYTES) + ksft_exit_fail_msg("sync case read %d, expected %d\n", + sync_read, EXPECTED_BYTES); + ksft_test_result_pass("sync provider transmits split record\n"); + + run_cmd("modprobe af_alg algif_aead pcrypt >/dev/null 2>&1"); + ret =3D instantiate_aead("pcrypt(generic-gcm-vaes-avx2)"); + if (ret) + ret =3D instantiate_aead("pcrypt(gcm(aes))"); + if (ret || !have_async_pcrypt()) + ksft_exit_skip("missing async pcrypt gcm(aes) provider\n"); + + ret =3D run_case(obj_path, &async_read); + if (ret) + ksft_exit_fail_msg("async case failed: %s\n", strerror(-ret)); + if (async_read !=3D EXPECTED_BYTES) + ksft_exit_fail_msg("async case read %d, expected %d\n", + async_read, EXPECTED_BYTES); + ksft_test_result_pass("async provider transmits split record\n"); + + ksft_finished(); +} --=20 2.54.0