From nobody Mon Jun 8 04:20:41 2026 Received: from mail-wr1-f51.google.com (mail-wr1-f51.google.com [209.85.221.51]) (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 906336FC5 for ; Sun, 7 Jun 2026 22:12:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.51 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780870357; cv=none; b=qTJwPg2tGPgk+9ndKxRxsi4axYISib3rXOHcN6Xsn8N1mhQLSmVEMKtSGisJq22grRswK3Xk36cVuDlDcotJWJFHJv9+IdMWdECc/Cgl54y5wC3JH8mbi2nxI5VqfW2ptSnZSuLqwOMMLp8WlVq9hXYdWiS9Dy59oRN16YJKaU4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780870357; c=relaxed/simple; bh=5Gv6HcYygMyhQXidp/OGzdRjg6V3YrRWUke26jM9Qo8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=UXA1tu3gJ30F+//66I7KJyBxnu9iDdS2qIT3v52z4zAL3MJ6y3Eho1MTwiU/1RkQuDdnQvLykMQgYQSbozRgFmNgtiadnUu++BN9HUelKXOCUdExhnhW030UH6RQWl2UZQNk3N+nMKW7cEPAQE1ORVBv768TrrC39Q39Yz6KtWA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=S8J9waPf; arc=none smtp.client-ip=209.85.221.51 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="S8J9waPf" Received: by mail-wr1-f51.google.com with SMTP id ffacd0b85a97d-45eedcdaeaaso2555329f8f.3 for ; Sun, 07 Jun 2026 15:12:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1780870354; x=1781475154; 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=8p4WQWA5RgafOeFKzM54X4fmRTN6X6fnEzGbViwwnSU=; b=S8J9waPf8qbd6fg67qwDXWwHhU+kYPalU+8XPaOzZv1n+pDlZklBa9Sy/TInlAwrZz LWc4oUrAKY814hr4r8lN2FIUJaAVaWIaNaq5E5zSb/dBovY4ec8k/Fn9GIzlUEem9unw mDOBfXCRwLS061ZgCbsUIY8ZSun7TKXenB+TX1dhKIXZJkW6l+pWl8wqmmWXi1x2pgT5 pvLBhJ+D5pCymwArbSwlQKoXGNW6Z58ukxexbTVVGGJ1fT3v2a6C58utD3wR41MqeNi/ fvYVDqvI0DrGdzz0QezrpGUVjSWjxbFJRiSUX1bICKbaDVIsAt2Obh06AJxUHa9VUiXz Z7Ow== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1780870354; x=1781475154; 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=8p4WQWA5RgafOeFKzM54X4fmRTN6X6fnEzGbViwwnSU=; b=jmz2F29ermteB2FeysbEtzqFxwL5YcRdqk46r4xU5fhDXrfF5niV+pSceC3yP3gk0K ggJXzIlllb3jIh0Bjv3AIEE70tMANhL4HGxwwYoJK7rbuK2NxJrg0o2xr4dFD27vJZp3 MNYjro1jlBKFQXmn9QvsBwyoQFYsfDxk2/WUgvaOP3sAtU7ccVHX279fdJafm/ZZzwWH tOLNE4bNKQyb0bp6GCh8xYxtjn1lOgKZmXF9LSP5xhzuq/jNh2TjO+6S7wqKEo5S2zc3 kePyqIeWjGjf9RQOUtkM0cD3sN+YeMxcqzs278/zxj6HwHE3JV3HLlqPfgeoQtKW061j VpWA== X-Forwarded-Encrypted: i=1; AFNElJ9tDwUO6dAaHcK5b62JUQXrlEpCZs2yHolbziEtjA6CZRWgu6UWjU9sgCmFiGeGZXQeF2axM91+zDPdj4s=@vger.kernel.org X-Gm-Message-State: AOJu0Yz1JMfiKlVNaL4Kecg9dtc9pVXm+iyTyxqkiHfnCzEJllhF0Lhm 9h3bu1zHjiavK2lY8GdkWkngMubG7VMTomZACO4CNv0HhVJ7qwWNnYyq X-Gm-Gg: Acq92OGCDpSiTw613ub4gZT/H7x5Q6HdTtowPZ59gZrse4LL1wnDWPkyRCM3ZGULyS8 wWgvLVyIo8aG5+SVzt8nhLZanyv4QySkkwOkQk8zkw6N4R9dsL6Y4teyl5PhcfSnRMZ4g6K3fq3 hghIJjE4MQ1ydj2b8szA+ZEwBGLCzidkfisUfFlBss1buCyiv6jBOoVLTmtSNeeFcmOTgZg6OZ2 Ub37gaOZYwWi0IWEt8Jm09z2wexdQQt4USA2/uGZMs61GdFul2HmJjyMBsvulKDFKUc31cW2g2A JsicyfJK6Cl1F5ibUTFG/6O0DF3HsP7UZDcP8GS4HJNoutHDjaZjfrD0qd/ExmOBjXJnjQnnctk rcwi26GjKzCsonYGDHIXLlZ8kqMiaYQz1arFbUzxXekKMG6wig12FvplzOJMUeHY0zdQiOygk3R E7ySk5w3VumeFdVCStNzmCzZCridofRIYqk1t52DlhXBBViJIXLZ4= X-Received: by 2002:adf:e006:0:20b0:441:1e8e:d8fd with SMTP id ffacd0b85a97d-46030658bc5mr14810105f8f.29.1780870353903; Sun, 07 Jun 2026 15:12:33 -0700 (PDT) Received: from localhost ([217.199.144.50]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-4601f2ec711sm45291686f8f.12.2026.06.07.15.12.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 07 Jun 2026 15:12:33 -0700 (PDT) From: Nyakundi Emmanuel To: axboe@kernel.dk Cc: federico.brasili@gmail.com, io-uring@vger.kernel.org, linux-kernel@vger.kernel.org, Nyakundi Emmanuel Subject: [PATCH] test/recv-bundle-pbuf-len-poison: add regression test for pbuf len corruption Date: Mon, 8 Jun 2026 01:10:47 +0300 Message-ID: <20260607221114.135950-1-nyariboemmanuel8@gmail.com> X-Mailer: git-send-email 2.54.0 In-Reply-To: <1fd2ea63-c128-4641-9565-dbafd97de612@kernel.dk> References: <1fd2ea63-c128-4641-9565-dbafd97de612@kernel.dk> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable A failed IORING_RECVSEND_BUNDLE receive on a non-INC provided-buffer ring can persistently corrupt the buffer descriptor length. When the receive fails with -EAGAIN, the kernel writes the requested length into buf->len during buffer selection but never restores it on failure. A later unrelated IORING_OP_READ using the same buffer group then consumes the corrupted length, returning fewer bytes than expected. This test reproduces the issue as reported by Federico Brasili. Reported-by: Federico Brasili Link: https://lore.kernel.org/io-uring/CAAEr8jbY60noGj1fw_k91UJRBkyiRVoS6= =3DnLhZ7Svwidjn4CAA@mail.gmail.com/ Signed-off-by: Nyakundi Emmanuel --- test/recv-bundle-pbuf-len-poison.c | 146 +++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 test/recv-bundle-pbuf-len-poison.c diff --git a/test/recv-bundle-pbuf-len-poison.c b/test/recv-bundle-pbuf-len= -poison.c new file mode 100644 index 00000000..90fafff4 --- /dev/null +++ b/test/recv-bundle-pbuf-len-poison.c @@ -0,0 +1,146 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Regression test for io_uring provided-buffer ring length corruption. + * + * A failed IORING_RECVSEND_BUNDLE receive on a non-INC provided-buffer + * ring can persistently shrink the user-visible buffer descriptor length. + * The modified length is not rolled back when the receive fails with + * -EAGAIN, and a later unrelated IORING_OP_READ from a pipe consumes + * the corrupted length. + * + * Reported-by: Federico Brasili + */ +#include +#include +#include +#include +#include +#include + +#include "liburing.h" +#include "helpers.h" + +#define BGID 8 +#define BUF_SIZE 4096 +#define NR_BUFS 2 + +static int test(void) +{ + struct io_uring_buf_ring *br; + struct io_uring_cqe *cqe; + struct io_uring_sqe *sqe; + struct io_uring ring; + struct io_uring_buf *buf_entry; + int sockfd, pipefds[2], ret; + void *buf; + char pipe_data[BUF_SIZE]; + + ret =3D io_uring_queue_init(8, &ring, 0); + if (ret) { + fprintf(stderr, "queue init failed: %d\n", ret); + return T_EXIT_FAIL; + } + + if (posix_memalign(&buf, 4096, BUF_SIZE * NR_BUFS)) + return T_EXIT_FAIL; + + /* set up non-INC provided buffer ring with 2 buffers of BUF_SIZE */ + br =3D io_uring_setup_buf_ring(&ring, NR_BUFS, BGID, 0, &ret); + if (!br) { + if (ret =3D=3D -EINVAL) + return T_EXIT_SKIP; + fprintf(stderr, "buf ring setup failed: %d\n", ret); + return T_EXIT_FAIL; + } + + io_uring_buf_ring_add(br, buf, BUF_SIZE, 0, NR_BUFS - 1, 0); + io_uring_buf_ring_add(br, buf + BUF_SIZE, BUF_SIZE, 1, NR_BUFS - 1, 1); + io_uring_buf_ring_advance(br, NR_BUFS); + + /* create an empty SOCK_DGRAM socket to trigger -EAGAIN */ + sockfd =3D socket(AF_UNIX, SOCK_DGRAM, 0); + if (sockfd < 0) { + perror("socket"); + return T_EXIT_FAIL; + } + + /* submit RECV_BUNDLE on empty socket =E2=80=94 expects -EAGAIN */ + sqe =3D io_uring_get_sqe(&ring); + io_uring_prep_recv(sqe, sockfd, NULL, 1, MSG_DONTWAIT); + sqe->ioprio |=3D IORING_RECVSEND_BUNDLE; + sqe->flags |=3D IOSQE_BUFFER_SELECT; + sqe->buf_group =3D BGID; + sqe->user_data =3D 0x1111; + io_uring_submit(&ring); + + ret =3D io_uring_wait_cqe(&ring, &cqe); + if (ret) { + fprintf(stderr, "wait cqe failed: %d\n", ret); + return T_EXIT_FAIL; + } + if (cqe->res !=3D -EAGAIN) { + fprintf(stderr, "expected -EAGAIN, got %d\n", cqe->res); + io_uring_cqe_seen(&ring, cqe); + return T_EXIT_FAIL; + } + io_uring_cqe_seen(&ring, cqe); + + /* check entry0.len =E2=80=94 must still be BUF_SIZE after failed RECV */ + buf_entry =3D &br->bufs[0]; + if (buf_entry->len !=3D BUF_SIZE) { + fprintf(stderr, + "FAIL: entry0.len corrupted after -EAGAIN RECV_BUNDLE: " + "got %u, expected %u\n", + buf_entry->len, BUF_SIZE); + return T_EXIT_FAIL; + } + + /* now do a pipe READ using the same buffer group */ + if (pipe(pipefds)) { + perror("pipe"); + return T_EXIT_FAIL; + } + + memset(pipe_data, 'A', BUF_SIZE); + if (write(pipefds[1], pipe_data, BUF_SIZE) !=3D BUF_SIZE) { + fprintf(stderr, "pipe write failed\n"); + return T_EXIT_FAIL; + } + + sqe =3D io_uring_get_sqe(&ring); + io_uring_prep_read(sqe, pipefds[0], NULL, BUF_SIZE, 0); + sqe->flags |=3D IOSQE_BUFFER_SELECT; + sqe->buf_group =3D BGID; + sqe->user_data =3D 0x6666; + io_uring_submit(&ring); + + ret =3D io_uring_wait_cqe(&ring, &cqe); + if (ret) { + fprintf(stderr, "wait read cqe failed: %d\n", ret); + return T_EXIT_FAIL; + } + if (cqe->res !=3D BUF_SIZE) { + fprintf(stderr, + "FAIL: READ got %d bytes, expected %d =E2=80=94 " + "pbuf len was poisoned by failed RECV_BUNDLE\n", + cqe->res, BUF_SIZE); + io_uring_cqe_seen(&ring, cqe); + return T_EXIT_FAIL; + } + io_uring_cqe_seen(&ring, cqe); + + close(sockfd); + close(pipefds[0]); + close(pipefds[1]); + io_uring_queue_exit(&ring); + free(buf); + return T_EXIT_PASS; +} + +int main(int argc, char *argv[]) +{ + if (argc > 1) + return T_EXIT_SKIP; + + return test(); +} --=20 2.54.0