From nobody Mon Sep 28 18:36:44 2026 Received: from mail-pg1-f176.google.com (mail-pg1-f176.google.com [209.85.215.176]) (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 C16B83BD65A for ; Wed, 19 Aug 2026 02:33:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.176 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787106807; cv=none; b=cto76dtP1KrtjY/3cP8jnMqcKTjS/WYNNK4Z9WhKQlNhOaRrvwfY/PZJKARe0nRvxnUfmfHG8K/08a53QybWYNjSiVFI8Qmh/0QTbroCtwlJ87Mnjfki5nQsTWjKll2hl3bymU5v3dur5hs8DBjYyVhY1Ew3arIO8fWtjXNTGP4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787106807; c=relaxed/simple; bh=ZuphiXNWb/uj/JB4yhd4PdsT5Aa34PaTeZB5VmeK4IQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=E/dz93V1gi8yw/Q+XpZBqdsLuw2/IumJq2sC063bm2ctRTEvRTBk1ZjXGwdhGRIX+z4pHP3mrgUwfEwFaNxN7yShc63bLoNo94+0CR+5PwslJ17bkM7oniMzGs1hykJvqzuUMQCVOH4bKyU9K8XTAYS1DMPIhcBNrNXfG2r/Tg0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=isslab.korea.ac.kr; spf=none smtp.mailfrom=isslab.korea.ac.kr; dkim=pass (2048-bit key) header.d=isslab-korea-ac-kr.20251104.gappssmtp.com header.i=@isslab-korea-ac-kr.20251104.gappssmtp.com header.b=YJtjBkjh; arc=none smtp.client-ip=209.85.215.176 Authentication-Results: smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=isslab.korea.ac.kr Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=isslab.korea.ac.kr Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=isslab-korea-ac-kr.20251104.gappssmtp.com header.i=@isslab-korea-ac-kr.20251104.gappssmtp.com header.b="YJtjBkjh" Received: by mail-pg1-f176.google.com with SMTP id 41be03b00d2f7-ca80d708489so268922a12.1 for ; Tue, 18 Aug 2026 19:33:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=isslab-korea-ac-kr.20251104.gappssmtp.com; s=20251104; t=1787106805; x=1787711605; 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:content-type; bh=MRyhD/De8I3XwFwEvg80m/qAYnxN4OiKijosBqahdgU=; b=YJtjBkjhF6tZ7VqSFQD7rYmpfwO50J2utmx1g9Lq80rpW+vCRayAolf35lb7M1ZEdv TCUyPEuyk1VegyifTgI5c+KEWz8lA7gQ6l1fYpymfOYgXMd1vNzXSMfq4jgmGMEFwTUp iHGiKyX4ML0aZFQ61qt3kjOoOpCm2147j+oXJEsjNdd6aGSSTYWzpqYnpWwPq1gslws2 8FDmxRXrOz2FeF0R3+X4PI9vTggMRdLreCFuIp2HRXssOAZpdK60X2DhNtUmbzqjrFbw flXI50P/Sj/8yYh8NO+159dAkA85Q03FF5t8Lcssie4+abRZ7UlBWCEd4mYYN5Pzur5i 4qlg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1787106805; x=1787711605; 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:content-type; bh=MRyhD/De8I3XwFwEvg80m/qAYnxN4OiKijosBqahdgU=; b=qb+aO9vmzyY4YNiTqd1XY+vkHsw0PD8tSNK8de9oZkH7pwa5vPOY45AFXFzSYFcf6x P8ULhIDsJ7Hp1InZ87SDKaQ8xfZJnYpq8MoUbt8ChjFYU2LpNLilLoRe8mdwrYKTxNUz tRYeR03EXAxPrex4T86pNjGsNIDSu0rkSYJSd/UYbcYswuuKVrUX/0wB+RTTlQdOYrDK RKw5S9Jn/8BAZtpdq5q8MXzEY6ftvVXxbN51wsSzqQw3G9ft1DuFGDIQz6NB+TVXVapk 7v6UBV/R5rjQe6KX7G5dmWbBt96liGXAo0t4rHtzwyWAgv1giWCxecWto9G3YOklYe7l H2Wg== X-Forwarded-Encrypted: i=1; AHgh+RrLkJpML1m5p2FREfhLFUmW0V5ZyEbGrejG9gmbpNUphY0vXkns2Jg+9e1UrURHQHLAiNJL9tV2PCJNTu8=@vger.kernel.org X-Gm-Message-State: AOJu0Yz75UHDUE/1pcRcazVf/wc8ZUYtjGo/egJtMElQ1CM6h/N58jWc oCfcI8L+GtnexPwytE6bC8+O4F+WQ9yo9kMLYv8oCSkDyqILF336WODSNJyQV5ewWrw= X-Gm-Gg: AR+sD112m+vZ1FgDxiDcoa8Eq88J/t5JMGNJyzEpiEm7/NOYVpbO3FAak2++mPr/Oop /TjYq6tjrBByXaKDmU2OsHzdMw8J4jU8J7EXpvtWnriViZB1fRsvRb09WG++ZY+7ONQbnEt2ATM LwTfhfBIYkkrmUuSzpBIIZ/dO0zjCLWIkteJgEYQckWKGa8zJUAvKnNm4lTlohOiWNpor/jfZvd Uv6W5ZYJrn7uJAcUYW4u1kEXBT/7EbQyeVJIBhg3X7h6EOAY51asOSq34tagy45OYPI2tZ1woNC kh+WodtskU6nuzKy5qcll7oNVVpv/NLHjPfhz5kheTDQnDaVNIgWxrqEtbuZQqr4FKxglyYURtd B868fhM9o0AV8nAH3ViIgunvVUKi0T+FNAHnDI5tpABR6T/vNBm9HAAC5Jnldx/PWLiEOpuHKrJ ZzL59AiQoL/xrGjWsFZtlbWutYl4dw1RQewxSmQtp6vIHiZ57XMg7VZ/M3vkImsPujhv4z X-Received: by 2002:a17:90b:3a45:b0:387:d9cc:7dc3 with SMTP id 98e67ed59e1d1-3957fa83eeamr2551747a91.21.1787106804865; Tue, 18 Aug 2026 19:33:24 -0700 (PDT) Received: from yhlee-960QFG.. ([125.131.91.97]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-3957f9aaa12sm786281a91.5.2026.08.18.19.33.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Aug 2026 19:33:24 -0700 (PDT) From: Yehyeong Lee To: alibuda@linux.alibaba.com, dust.li@linux.alibaba.com, sidraya@linux.ibm.com, wenjia@linux.ibm.com, kuba@kernel.org, davem@davemloft.net, edumazet@google.com, pabeni@redhat.com Cc: leitao@debian.org, horms@kernel.org, mjambigi@linux.ibm.com, tonylu@linux.alibaba.com, guwen@linux.alibaba.com, guangguan.wang@linux.alibaba.com, kees@kernel.org, gustavoars@kernel.org, netdev@vger.kernel.org, linux-rdma@vger.kernel.org, linux-s390@vger.kernel.org, linux-hardening@vger.kernel.org, linux-kernel@vger.kernel.org, Yehyeong Lee , stable@vger.kernel.org Subject: [PATCH net v7 1/3] net/smc: fix use-after-free of the LLC qentry in smc_llc_srv_add_link() Date: Wed, 19 Aug 2026 11:33:04 +0900 Message-ID: <20260819023306.644849-2-yhlee@isslab.korea.ac.kr> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260819023306.644849-1-yhlee@isslab.korea.ac.kr> References: <20260819023306.644849-1-yhlee@isslab.korea.ac.kr> 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" smc_llc_srv_add_link() keeps add_llc pointing into the queue entry: add_llc =3D &qentry->msg.add_link; smc_llc.c:1482 ... smc_llc_save_add_link_info(link_new, add_llc); smc_llc.c:1494 smc_llc_flow_qentry_del(&lgr->llc_flow_lcl); smc_llc.c:1495 ... u8 *llc_msg =3D smc_link_shared_v2_rxbuf(link) ? (u8 *)lgr->wr_rx_buf_v2 : (u8 *)add_llc; smc_llc.c:1504 smc_llc_save_add_link_rkeys(link, link_new, llc_msg); smc_llc.c:1506 smc_llc_flow_qentry_del() kfree()s the entry, so on a link without a shared v2 receive buffer the pointer handed to smc_llc_save_add_link_rkeys() is already freed. Before the Fixes: commit that branch always used lgr->wr_rx_buf_v2 and add_llc was not used after the free. Reproduced on an unpatched tree over rxe, with KASAN, kasan_multi_shot and a link forced to max_recv_sge =3D=3D 1: the entry is freed and read by the same call, and the freeing frame is smc_llc_srv_add_link() itself. [ 2.523161] BUG: KASAN: slab-use-after-free in smc_llc_save_add_link_r= keys+0x333/0x350 [ 2.523499] Read of size 2 at addr ffff8880052194de by task kworker/0:= 1/11 [ 2.523789]=20 [ 2.523862] CPU: 0 UID: 0 PID: 11 Comm: kworker/0:1 Not tainted 7.2.0-= rc5-p0-g2c9dd296545d #35 PREEMPT(lazy)=20 [ 2.523865] Hardware name: QEMU Ubuntu 24.04 PC v2 (i440FX + PIIX, arc= h_caps fix, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014 [ 2.523866] Workqueue: smc_hs_wq smc_listen_work [ 2.523869] Call Trace: [ 2.523870] [ 2.523871] dump_stack_lvl+0x53/0x70 [ 2.523872] print_report+0xd0/0x630 [ 2.523874] ? __pfx__raw_spin_lock_irqsave+0x10/0x10 [ 2.523876] ? smc_llc_save_add_link_rkeys+0x333/0x350 [ 2.523878] kasan_report+0xce/0x100 [ 2.523879] ? smc_llc_save_add_link_rkeys+0x333/0x350 [ 2.523881] smc_llc_save_add_link_rkeys+0x333/0x350 [ 2.523883] ? smcr_buf_reg_lgr+0x2a4/0x660 [ 2.523885] smc_llc_srv_add_link+0xaa2/0x1e50 [ 2.523888] ? _printk+0xba/0xf0 [ 2.523897] ? __pfx_smc_llc_srv_add_link+0x10/0x10 [ 2.523899] ? down_write+0xb0/0x130 [ 2.523903] ? __pfx_down_write+0x10/0x10 [ 2.523905] smc_listen_work+0x489e/0x4d00 [ 2.523907] ? kmem_cache_free+0x1c6/0x3a0 [ 2.523911] ? __pfx_smc_listen_work+0x10/0x10 [ 2.523913] ? release_sock+0x148/0x1d0 [ 2.523915] ? smc_tcp_listen_work+0xb4f/0xfc0 [ 2.523917] ? _raw_spin_lock_irq+0x80/0xe0 [ 2.523918] ? __pfx__raw_spin_lock_irq+0x10/0x10 [ 2.523920] process_one_work+0x633/0x1030 [ 2.523922] ? assign_work+0x11d/0x370 [ 2.523924] worker_thread+0x45b/0xd10 [ 2.523926] ? __pfx_worker_thread+0x10/0x10 [ 2.523928] ? __pfx_worker_thread+0x10/0x10 [ 2.523929] kthread+0x2c6/0x3b0 [ 2.523931] ? recalc_sigpending+0x15c/0x1e0 [ 2.523934] ? __pfx_kthread+0x10/0x10 [ 2.523935] ret_from_fork+0x36e/0x5a0 [ 2.523937] ? __pfx_ret_from_fork+0x10/0x10 [ 2.523938] ? __switch_to+0x572/0xdd0 [ 2.523943] ? __pfx_kthread+0x10/0x10 [ 2.523944] ret_from_fork_asm+0x1a/0x30 [ 2.523947] [ 2.523948]=20 [ 2.531253] Allocated by task 48: [ 2.531399] kasan_save_stack+0x33/0x60 [ 2.531570] kasan_save_track+0x14/0x30 [ 2.531737] __kasan_kmalloc+0x8f/0xa0 [ 2.531905] __kmalloc_cache_noprof+0x158/0x370 [ 2.532100] smc_llc_enqueue+0x72/0x560 [ 2.532268] smc_wr_rx_tasklet_fn+0x474/0xa80 [ 2.532491] tasklet_action_common+0x20f/0x8a0 [ 2.532714] handle_softirqs+0x18e/0x590 [ 2.532886] do_softirq+0x3b/0x60 [ 2.533036] __local_bh_enable_ip+0x61/0x70 [ 2.533221] __alloc_skb+0x732/0x890 [ 2.533384] rxe_init_packet+0x16b/0x4f0 [ 2.533567] prepare_ack_packet+0xb8/0x830 [ 2.533760] rxe_receiver+0x495/0x96e0 [ 2.533933] do_work+0x144/0x470 [ 2.534078] process_one_work+0x633/0x1030 [ 2.534257] worker_thread+0x45b/0xd10 [ 2.534424] kthread+0x2c6/0x3b0 [ 2.534569] ret_from_fork+0x36e/0x5a0 [ 2.534737] ret_from_fork_asm+0x1a/0x30 [ 2.534907]=20 [ 2.534980] Freed by task 11: [ 2.535112] kasan_save_stack+0x33/0x60 [ 2.535279] kasan_save_track+0x14/0x30 [ 2.535444] kasan_save_free_info+0x3b/0x60 [ 2.535625] __kasan_slab_free+0x43/0x70 [ 2.535798] kfree+0x121/0x380 [ 2.535935] smc_llc_srv_add_link+0x9a8/0x1e50 [ 2.536128] smc_listen_work+0x489e/0x4d00 [ 2.536305] process_one_work+0x633/0x1030 [ 2.536482] worker_thread+0x45b/0xd10 [ 2.536652] kthread+0x2c6/0x3b0 [ 2.536794] ret_from_fork+0x36e/0x5a0 [ 2.536958] ret_from_fork_asm+0x1a/0x30 [ 2.537133]=20 [ 2.537205] The buggy address belongs to the object at ffff888005219480 [ 2.537205] which belongs to the cache kmalloc-96 of size 96 [ 2.537719] The buggy address is located 94 bytes inside of [ 2.537719] freed 96-byte region [ffff888005219480, ffff8880052194e0) [ 2.538216]=20 [ 2.538289] The buggy address belongs to the physical page: [ 2.538524] page: refcount:0 mapcount:0 mapping:0000000000000000 index= :0x0 pfn:0x5219 [ 2.538857] flags: 0x100000000000000(node=3D0|zone=3D1) [ 2.539066] page_type: f5(slab) [ 2.539210] raw: 0100000000000000 ffff888001041280 dead000000000122 00= 00000000000000 [ 2.539534] raw: 0000000000000000 0000000000200020 00000000f5000000 00= 00000000000000 [ 2.539863] page dumped because: kasan: bad access detected [ 2.540098]=20 [ 2.540170] Memory state around the buggy address: [ 2.540379] ffff888005219380: fc fc fc fc fc fc fc fc fc fc fc fc fc = fc fc fc [ 2.540684] ffff888005219400: fc fc fc fc fc fc fc fc fc fc fc fc fc = fc fc fc [ 2.540988] >ffff888005219480: fa fb fb fb fb fb fb fb fb fb fb fb fc = fc fc fc [ 2.541291] ^ [ 2.541548] ffff888005219500: 00 00 00 00 00 00 00 00 00 fc fc fc fc = fc fc fc [ 2.541857] ffff888005219580: 00 00 00 00 00 00 00 00 00 fc fc fc fc = fc fc fc The offset is past the 72-byte queue entry because the out-of-bounds read fixed by the next patch is on the same line; what this patch removes is the free at smc_llc_srv_add_link+0x9a8 happening before the read at +0xaa2. Detach the entry instead of freeing it there, and free it at the single exit label. The reject path has to detach as well, otherwise it would be freed twice. This changes only the lifetime of the entry. The same read still runs past its end until the next two patches bound it, so a backport wants all three. Fixes: 27ef6a9981fe ("net/smc: support SMC-R V2 for rdma devices with max_r= ecv_sge equals to 1") Cc: stable@vger.kernel.org Reviewed-by: Sidraya Jayagond Signed-off-by: Yehyeong Lee Reviewed-by: Breno Leitao --- Changes since v5: return through the existing exit label. Changes since v6: collected Sidraya's Reviewed-by; removed the extra spaces after sentence-ending punctuation. No functional change. net/smc/smc_llc.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/net/smc/smc_llc.c b/net/smc/smc_llc.c index 954b2ff1815c..055a03eee5b5 100644 --- a/net/smc/smc_llc.c +++ b/net/smc/smc_llc.c @@ -1481,7 +1481,7 @@ int smc_llc_srv_add_link(struct smc_link *link, } add_llc =3D &qentry->msg.add_link; if (add_llc->hd.flags & SMC_LLC_FLAG_ADD_LNK_REJ) { - smc_llc_flow_qentry_del(&lgr->llc_flow_lcl); + smc_llc_flow_qentry_clr(&lgr->llc_flow_lcl); rc =3D -ENOLINK; goto out_err; } @@ -1492,7 +1492,8 @@ int smc_llc_srv_add_link(struct smc_link *link, lgr_new_t =3D SMC_LGR_ASYMMETRIC_PEER; } smc_llc_save_add_link_info(link_new, add_llc); - smc_llc_flow_qentry_del(&lgr->llc_flow_lcl); + /* add_llc still points into qentry, so only detach it here */ + smc_llc_flow_qentry_clr(&lgr->llc_flow_lcl); =20 rc =3D smc_ib_ready_link(link_new); if (rc) @@ -1512,14 +1513,14 @@ int smc_llc_srv_add_link(struct smc_link *link, rc =3D smc_llc_srv_conf_link(link, link_new, lgr_new_t); if (rc) goto out_err; - kfree(ini); - return 0; + goto out; out_err: if (link_new) { link_new->state =3D SMC_LNK_INACTIVE; smcr_link_clear(link_new, false); } out: + kfree(qentry); kfree(ini); if (send_req_add_link_resp) smc_llc_send_req_add_link_response(req_qentry); --=20 2.43.0 From nobody Mon Sep 28 18:36:44 2026 Received: from mail-pj1-f41.google.com (mail-pj1-f41.google.com [209.85.216.41]) (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 400853C062A for ; Wed, 19 Aug 2026 02:33:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.41 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787106814; cv=none; b=M9JvQsqdpD/PUbr6VagEzEaYR03Z6K07IHApVeaL4kSfG9KlzdUzumxo/+XXZ0dFQlJehs+NG/iimYDOfqeAJ2L1aPdHLzPJgT4XR5Wz4LjRRPxa2pN77cvEAJxq6VnNJga5c4XTOv9IwZL93ZpSZetZjEymn2QXxUfkE4ZInWk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787106814; c=relaxed/simple; bh=NvUKtwCwLfTUlAPaeeoxkGpCIrYBqVMKcCKXISoLcZ4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=VGgQ5H+IcQmODDCh30Kqn/v7PcxIWwz3gTtRqhEj08PW4TFU05MTxcpXGp4CHqUU89iWArYSDuzbWo1ckz4Vx31WAQji3MvLC/4ClGKNf/IAOc1//C/64EUtotAYk+1REIiEp9g8JCw5vn+AFscFLMhlZtgsMOGUlj/9Ddi41pk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=isslab.korea.ac.kr; spf=none smtp.mailfrom=isslab.korea.ac.kr; dkim=pass (2048-bit key) header.d=isslab-korea-ac-kr.20251104.gappssmtp.com header.i=@isslab-korea-ac-kr.20251104.gappssmtp.com header.b=em5o3Ujn; arc=none smtp.client-ip=209.85.216.41 Authentication-Results: smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=isslab.korea.ac.kr Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=isslab.korea.ac.kr Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=isslab-korea-ac-kr.20251104.gappssmtp.com header.i=@isslab-korea-ac-kr.20251104.gappssmtp.com header.b="em5o3Ujn" Received: by mail-pj1-f41.google.com with SMTP id 98e67ed59e1d1-38dcbade417so669298a91.1 for ; Tue, 18 Aug 2026 19:33:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=isslab-korea-ac-kr.20251104.gappssmtp.com; s=20251104; t=1787106811; x=1787711611; 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:content-type; bh=tbeC9QALWzzC4pxWLz9RtusejQaR6vKots2JJ46k/0I=; b=em5o3Ujn38tApQIgrPOFgD6H9wXqLe8L/R/jx7tsNzf8fdRXaErg9rOGh9OPTJpIdi Jnia/mR5IzZh4Rzfm4vNxUnEccMC18YxuhRG5Kj1NBfl4E9exdsJZHJHDWH7y13pngxx cKEArI66rqQ6Q6OxmHPZsMmzwLcpe85/DlF717avVxogIyz0slcpFILGdg2xfWUFJE5P 0f3C35TJTEByL0H+kclZd54Yyz/quesn5aBsozUtgT5tL1IDRvYwBbnZF960PGs1m9yC 1Ht1wcKgrupxZbY9icS41AYpDxjmx9EHCTmJBA4JwOXvU8p6nvZJ6rqwG+hwTUMXPadK MrSQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1787106811; x=1787711611; 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:content-type; bh=tbeC9QALWzzC4pxWLz9RtusejQaR6vKots2JJ46k/0I=; b=LS2IzCfvIgq7RE0BUtqEcHtN1OzoXOXN0C2wI3sbjFOyiCkpzbGVVYldVVL/nDz1as YMPZUX9gq01sq9XHor8PSdWqXtg9vEla7kdYWlhbsSaSHuh5g0Oy45bgGF7kwQVUncYY 79DImR8WwHhQyUxA3RbYXeSj+5hh3EdViL3SzbqjV7VBtwrvX3wOw+4fKnML8UuWko0V QSrf7+4oj5hporBPsQRhMw6Agx9fNEpSToocFYOPGyiatejydArZxseBjbGfd72OW3im JMoC8diqExSi1Ej/TmgIgFRHon2Tw55X6S4rMuDgDbyw3aAouTpWSNW/SRSX1AiaRXJ2 umBA== X-Forwarded-Encrypted: i=1; AHgh+RrabbHUAjV9HQDnsFvQlTs0afp+4L+kPCiOvL/FlM2Wf1hks3X3Ttyr2KT671cPz+qSaqrJuSQSpdm7TA8=@vger.kernel.org X-Gm-Message-State: AOJu0Yz50fVvYajVeUet7RemuGjgqJoxSWaahE8b9Ble4NEbEikvVK9x zsjldeRbPHD/QoXz8aWmvekg1pSpMg7QkoWoetYNQFPlqh9+YYimh8dwg2HhWSbEP8Q= X-Gm-Gg: AR+sD12AKmN4yppryAub1Z8lrQDp4AyueCnO6H2/zJAf9J1Bu2Iyv42ULmVwCMEqxDT 56Q39wJ1OnMnhzWsuHdtD/P76JCGcQlsx4QqIxQDIIQHYaFUOPgIa2gQC06JzR/HAVupEKKsERS Bc45EIJycn0Gfqr/p1xXUFDiARVYH8FdKkLFdQyU1q9aea5ptwpg6fy4p8oztcnVSOSad203LU0 L4m9YSxBYxlw6yQV1klkfP5iknEf48b+lkeKZRYm7WCv99NsgN032tzA/IeJmcMeafhyJu2h2Go JN5n2pH0VQE+7oE0/dffzTfv5OwiS50YenUxTYcxyyTc4dYU3kv9MUNG76N1ir3sxO+If1/WY+S LLufmnNCJmWj0nFn7r8jTZOYysNubOiUP4zHslCNvxvnTv1fLJgrXIcKn9TshJgn3aeyxpcHzQ2 Jtbb9A1D1DI+GS961qwuB+yumfs+bg9+C5RzUp+URjeWQjT3+kn7SJpgq1EwGqceE07lPL X-Received: by 2002:a17:90b:4c8c:b0:38d:fda6:4873 with SMTP id 98e67ed59e1d1-3958108a4bbmr2251257a91.10.1787106810789; Tue, 18 Aug 2026 19:33:30 -0700 (PDT) Received: from yhlee-960QFG.. ([125.131.91.97]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-3957f9aaa12sm786281a91.5.2026.08.18.19.33.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Aug 2026 19:33:30 -0700 (PDT) From: Yehyeong Lee To: alibuda@linux.alibaba.com, dust.li@linux.alibaba.com, sidraya@linux.ibm.com, wenjia@linux.ibm.com, kuba@kernel.org, davem@davemloft.net, edumazet@google.com, pabeni@redhat.com Cc: leitao@debian.org, horms@kernel.org, mjambigi@linux.ibm.com, tonylu@linux.alibaba.com, guwen@linux.alibaba.com, guangguan.wang@linux.alibaba.com, kees@kernel.org, gustavoars@kernel.org, netdev@vger.kernel.org, linux-rdma@vger.kernel.org, linux-s390@vger.kernel.org, linux-hardening@vger.kernel.org, linux-kernel@vger.kernel.org, Yehyeong Lee , stable@vger.kernel.org Subject: [PATCH net v7 2/3] net/smc: bound the peer rkey counts in SMC-Rv2 LLC messages Date: Wed, 19 Aug 2026 11:33:05 +0900 Message-ID: <20260819023306.644849-3-yhlee@isslab.korea.ac.kr> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260819023306.644849-1-yhlee@isslab.korea.ac.kr> References: <20260819023306.644849-1-yhlee@isslab.korea.ac.kr> 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" On a link whose device has max_recv_sge =3D=3D 1 there is no shared v2 rece= ive buffer, and smc_llc_save_add_link_rkeys() takes the v2 extension from 44 bytes past the start of the queue entry's inline message: ext =3D (struct smc_llc_msg_add_link_v2_ext *)(llc_msg + SMC_WR_TX_SIZE); The entry is a 72-byte allocation and the extension starts at offset 68, so ext->num_rkeys at offset 94 is already past it. This happens on every SMC-Rv2 link addition, whatever the peer sends: [ 2.490065] BUG: KASAN: slab-out-of-bounds in smc_llc_save_add_link_rk= eys+0x333/0x350 [ 2.490431] Read of size 2 at addr ffff8880056406de by task smctest/106 [ 2.490709]=20 [ 2.490792] CPU: 0 UID: 0 PID: 106 Comm: smctest Not tainted 7.2.0-rc5= -p1-g77a5d9d9c99f #32 PREEMPT(lazy)=20 [ 2.490795] Hardware name: QEMU Ubuntu 24.04 PC v2 (i440FX + PIIX, arc= h_caps fix, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014 [ 2.490798] Call Trace: [ 2.490803] [ 2.490805] dump_stack_lvl+0x53/0x70 [ 2.490810] print_report+0xd0/0x630 [ 2.490828] ? __pfx__raw_spin_lock_irqsave+0x10/0x10 [ 2.490832] ? smc_llc_save_add_link_rkeys+0x333/0x350 [ 2.490834] kasan_report+0xce/0x100 [ 2.490836] ? smc_llc_save_add_link_rkeys+0x333/0x350 [ 2.490837] smc_llc_save_add_link_rkeys+0x333/0x350 [ 2.490839] ? smcr_buf_map_lgr+0x1bf/0x2b0 [ 2.490844] smc_llc_cli_add_link+0xca7/0x1e80 [ 2.490848] ? smc_llc_wait+0x355/0x810 [ 2.490850] ? __pfx_smc_llc_wait+0x10/0x10 [ 2.490851] ? __pfx_smc_llc_cli_add_link+0x10/0x10 [ 2.490853] ? __pfx_autoremove_wake_function+0x10/0x10 [ 2.490863] __smc_connect+0x3f5c/0x4980 [ 2.490873] ? __pfx_kernel_connect+0x10/0x10 [ 2.490888] ? __pfx___smc_connect+0x10/0x10 [ 2.490891] ? release_sock+0x148/0x1d0 [ 2.490894] smc_connect+0x42c/0x580 [ 2.490896] __sys_connect+0xfc/0x130 [ 2.490898] ? __pfx___sys_connect+0x10/0x10 [ 2.490900] ? handle_mm_fault+0x1a1/0x430 [ 2.490908] __x64_sys_connect+0x6d/0xb0 [ 2.490909] ? fpregs_assert_state_consistent+0x56/0xe0 [ 2.490917] do_syscall_64+0xf9/0x540 [ 2.490921] entry_SYSCALL_64_after_hwframe+0x77/0x7f [ 2.490924] RIP: 0033:0x421bb4 [ 2.490927] Code: ff f7 d8 64 89 01 48 83 c8 ff c3 66 2e 0f 1f 84 00 0= 0 00 00 00 90 f3 0f 1e fa 80 3d ad 34 09 00 00 74 13 b8 2a 00 00 00 0f 05 <= 48> 3d 00 f0 ff ff 77 4c c3 0f 1f 00 55 48 89 e5 48 83 ec 10 89 55 [ 2.490929] RSP: 002b:00007ffd473b01a8 EFLAGS: 00000202 ORIG_RAX: 0000= 00000000002a [ 2.490935] RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 000000000= 0421bb4 [ 2.490936] RDX: 0000000000000010 RSI: 00007ffd473b01d0 RDI: 000000000= 0000003 [ 2.490937] RBP: 0000000000003930 R08: 0000000000000004 R09: 000000000= 0000000 [ 2.490938] R10: 00007ffd473b0f98 R11: 0000000000000202 R12: 000000000= 0000006 [ 2.490939] R13: 00007ffd473b0f87 R14: 0000000000000003 R15: 00007ffd4= 73b0f90 [ 2.490940] [ 2.490941]=20 [ 2.499545] Allocated by task 44: [ 2.499693] kasan_save_stack+0x33/0x60 [ 2.499860] kasan_save_track+0x14/0x30 [ 2.500026] __kasan_kmalloc+0x8f/0xa0 [ 2.500190] __kmalloc_cache_noprof+0x158/0x370 [ 2.500393] smc_llc_enqueue+0x72/0x560 [ 2.500559] smc_wr_rx_tasklet_fn+0x474/0xa80 [ 2.500747] tasklet_action_common+0x20f/0x8a0 [ 2.500945] handle_softirqs+0x18e/0x590 [ 2.501115] do_softirq+0x3b/0x60 [ 2.501266] __local_bh_enable_ip+0x61/0x70 [ 2.501446] __alloc_skb+0x732/0x890 [ 2.501604] rxe_init_packet+0x16b/0x4f0 [ 2.501783] prepare_ack_packet+0xb8/0x830 [ 2.501962] rxe_receiver+0x495/0x96e0 [ 2.502125] do_work+0x144/0x470 [ 2.502269] process_one_work+0x633/0x1030 [ 2.502450] worker_thread+0x45b/0xd10 [ 2.502617] kthread+0x2c6/0x3b0 [ 2.502762] ret_from_fork+0x36e/0x5a0 [ 2.502925] ret_from_fork_asm+0x1a/0x30 [ 2.503103]=20 [ 2.503177] The buggy address belongs to the object at ffff888005640680 [ 2.503177] which belongs to the cache kmalloc-96 of size 96 [ 2.503692] The buggy address is located 22 bytes to the right of [ 2.503692] allocated 72-byte region [ffff888005640680, ffff888005640= 6c8) [ 2.504227]=20 [ 2.504300] The buggy address belongs to the physical page: [ 2.504535] page: refcount:0 mapcount:0 mapping:0000000000000000 index= :0x0 pfn:0x5640 [ 2.504865] flags: 0x100000000000000(node=3D0|zone=3D1) [ 2.505076] page_type: f5(slab) [ 2.505221] raw: 0100000000000000 ffff888001041280 dead000000000122 00= 00000000000000 [ 2.505544] raw: 0000000000000000 0000000000200020 00000000f5000000 00= 00000000000000 [ 2.505867] page dumped because: kasan: bad access detected [ 2.506102]=20 [ 2.506176] Memory state around the buggy address: [ 2.506380] ffff888005640580: 00 00 00 00 00 00 00 00 00 fc fc fc fc = fc fc fc [ 2.506683] ffff888005640600: 00 00 00 00 00 00 00 00 00 fc fc fc fc = fc fc fc [ 2.506987] >ffff888005640680: 00 00 00 00 00 00 00 00 00 fc fc fc fc = fc fc fc [ 2.507291] ^ [ 2.507548] ffff888005640700: 00 00 00 00 00 00 00 00 00 fc fc fc fc = fc fc fc [ 2.507850] ffff888005640780: 00 00 00 00 00 00 00 00 00 fc fc fc fc = fc fc fc Whatever that read finds then bounds the ext->rt[] loop, so a peer that declares 255 rkeys reads much further. smc_llc_rmt_delete_rkey() has the same shape for llcv2->rkey[]. Bound both loops by the buffer they read from, and skip the extension altogether when there is no shared v2 receive buffer. The extension does arrive on the link, but smc_llc_enqueue() copies only sizeof(union smc_llc_msg) into the queue entry, so what that code read past the 44 inline bytes was heap and not peer data. Fixes: 27ef6a9981fe ("net/smc: support SMC-R V2 for rdma devices with max_r= ecv_sge equals to 1") Cc: stable@vger.kernel.org Reviewed-by: Sidraya Jayagond Signed-off-by: Yehyeong Lee --- v4 -> v5: corrected the reason given for skipping the extension. It does arrive on the link; what is not there is the copy in the queue entry. No functional change. Measured over rxe with KASAN and max_recv_sge forced to 1, five test cells (plain 1-rkey delete, delete declaring 255, plain ADD_LINK v2, ADD_LINK declaring 255, and an SMC-Rv1 link group). Without this patch four of the five report; with it none do. With kasan_multi_shot the unpatched kernel reports 491 times in a single ADD_LINK run, the patched one not at all. Changes since v5: none. Changes since v6: collected Sidraya's Reviewed-by; removed the extra spaces after sentence-ending punctuation. No functional change. net/smc/smc_llc.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/net/smc/smc_llc.c b/net/smc/smc_llc.c index 055a03eee5b5..748d65186f68 100644 --- a/net/smc/smc_llc.c +++ b/net/smc/smc_llc.c @@ -1000,13 +1000,21 @@ static void smc_llc_save_add_link_rkeys(struct smc_= link *link, struct smc_link *link_new, u8 *llc_msg) { + const u32 rt_off =3D offsetof(struct smc_llc_msg_add_link_v2_ext, rt); struct smc_llc_msg_add_link_v2_ext *ext; struct smc_link_group *lgr =3D link->lgr; int max, i; =20 + /* Without a shared v2 receive buffer the extension is not copied + * into the queue entry, so not even ext->num_rkeys is there. + */ + if (!smc_link_shared_v2_rxbuf(link)) + return; ext =3D (struct smc_llc_msg_add_link_v2_ext *)(llc_msg + SMC_WR_TX_SIZE); max =3D min_t(u8, ext->num_rkeys, SMC_LLC_RKEYS_PER_MSG_V2); + max =3D min_t(u32, max, (SMC_WR_BUF_V2_SIZE - SMC_WR_TX_SIZE - rt_off) / + sizeof(ext->rt[0])); down_write(&lgr->rmbs_lock); for (i =3D 0; i < max; i++) { smc_rtoken_set(lgr, link->link_idx, link_new->link_idx, @@ -1811,17 +1819,25 @@ static void smc_llc_rmt_delete_rkey(struct smc_link= _group *lgr) link =3D qentry->link; =20 if (lgr->smc_version =3D=3D SMC_V2) { + const u32 rkey_off =3D + offsetof(struct smc_llc_msg_delete_rkey_v2, rkey); struct smc_llc_msg_delete_rkey_v2 *llcv2; + u32 buf_len; =20 if (smc_link_shared_v2_rxbuf(link)) { memcpy(lgr->wr_rx_buf_v2, llc, sizeof(*llc)); llcv2 =3D (struct smc_llc_msg_delete_rkey_v2 *)lgr->wr_rx_buf_v2; + buf_len =3D SMC_WR_BUF_V2_SIZE; } else { llcv2 =3D (struct smc_llc_msg_delete_rkey_v2 *)llc; + buf_len =3D sizeof(qentry->msg); } llcv2->num_inval_rkeys =3D 0; =20 max =3D min_t(u8, llcv2->num_rkeys, SMC_LLC_RKEYS_PER_MSG_V2); + /* bound by the buffer llcv2 points at */ + max =3D min_t(u32, max, (buf_len - rkey_off) / + sizeof(llcv2->rkey[0])); for (i =3D 0; i < max; i++) { if (smc_rtoken_delete(link, llcv2->rkey[i])) llcv2->num_inval_rkeys++; --=20 2.43.0 From nobody Mon Sep 28 18:36:44 2026 Received: from mail-pj1-f41.google.com (mail-pj1-f41.google.com [209.85.216.41]) (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 D50C02765DF for ; Wed, 19 Aug 2026 02:33:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.41 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787106820; cv=none; b=KIxyvV6o5v2ANU6VoTGZrPdbcEvtduMSdufhsgrcPEDJqkqTFVQfxYgNIEW1lEwdI7+YpaGaXgX1aicI6M+TkoATMCFrTbLDPht4a8B6E4RnZv6TgCnQtlR5ZPlpSVBf5/0EScHNyvkErDgcEtETaK6c76ocxlejSyT821c2/t4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787106820; c=relaxed/simple; bh=Iuarn4oLLGMAYXYIV7PHiY1UhbpceFCrWtAO6O1P5aI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=HqGU3dPdm6RHKT/DDNMHqDpJiewZaPukqm6iFVvrzYieQSrctGUmBSBp0b02Db66mm1brgyM2+M0s5/x1CWrdlZvmtlk/JyC+g/Pao178pylkRRQSMkX300IoNSOmcqzvOt/RLq6iZj0BVqrluBSW97hY6p5zodjo4U1Yb9JJ34= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=isslab.korea.ac.kr; spf=none smtp.mailfrom=isslab.korea.ac.kr; dkim=pass (2048-bit key) header.d=isslab-korea-ac-kr.20251104.gappssmtp.com header.i=@isslab-korea-ac-kr.20251104.gappssmtp.com header.b=m0Gdap07; arc=none smtp.client-ip=209.85.216.41 Authentication-Results: smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=isslab.korea.ac.kr Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=isslab.korea.ac.kr Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=isslab-korea-ac-kr.20251104.gappssmtp.com header.i=@isslab-korea-ac-kr.20251104.gappssmtp.com header.b="m0Gdap07" Received: by mail-pj1-f41.google.com with SMTP id 98e67ed59e1d1-38e347638adso686681a91.0 for ; Tue, 18 Aug 2026 19:33:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=isslab-korea-ac-kr.20251104.gappssmtp.com; s=20251104; t=1787106817; x=1787711617; 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:content-type; bh=xRPyHCi0h1GBGhDDK1sqVcFWzJLHUXUdR+otM3wSwgg=; b=m0Gdap07AW7ZkWK8oEOhIPuwiQeJ76OwSTuTA23IAhEVoYbAROy7wz1E3hxM5rq7HK aSUiWOGu5RmSuUmUON9GHf/VWq1KDV/J08nZhR98T2oApXXU0RjQoDddngZtP8FF+9Fr LtBj3dF17DRoOSRhXt6gM1Nq9LqvzjwDt8TiY9m2AsSBH+Wv1fqCI6h6ML86YoKVWkax 6bBZp6AMrbMf7Upi+DqMSu3ZPbWvR3bHZHVfnFTU1OsYT+FalgVaJihG/z7S65f0ifzJ wtwo6ANELEbaG7c/93SpCkLpxZJQvldueFkFeKMbSrKAZdIStKPNwnLYNB/C99TyM00Q GnzA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1787106817; x=1787711617; 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:content-type; bh=xRPyHCi0h1GBGhDDK1sqVcFWzJLHUXUdR+otM3wSwgg=; b=sL86mFjBkM3tnDnzV5lcn1UZAmbIb6M6/SSY8qxzjH0pSoZ3vcqTatrf8+sogms6S+ 1cjiZxLvOC/GpLadjto3Xt6uoP3nzxKb4z3BcJrM61DMf0w1aCSZD6n0nK+0GTE48JZJ iI/8PgytiRuLyFHaUa5MgzvF0774AD/MARTu06t2IrJ6HkTTMYcpQjz4HPgKSRv1ZfO3 kgZq4Z0vdVu5gkxnFKNGghC5gjsu0cU2TSk43PILOV91clkcSJk3uWTbuF4gzcm7L0SB UHZxw6Ii0yyPQ6gn8WpyxKpvNKFwzGgSjl6jazDJuMwdWqJEIpnw0ywmKzu0iqIq411e tiXA== X-Forwarded-Encrypted: i=1; AHgh+RqC9rjqAMRcex4JiiqAeqtW96awLcuueT9MAmntG8PPBSwZ3iGcPgK0y4ImVMoAqipCovOKkDB0Wcau/M0=@vger.kernel.org X-Gm-Message-State: AOJu0Yx6sxJgOFT8fJvHQaqyt58RZ3kdbRvc64nnxlTBS/8XJYf9s3zm gypN/+5ryl6N5rvwbw7HBfLixi5N/X7uyf6QJ9Oz7ua3p9Rbu9elYL1Yocsz+UFQ3rw= X-Gm-Gg: AR+sD10ZuxhPsDf0x/ULbw5oWHjJHR3L/OmCJpfJFIlzDBzMCZjuFsj2H4WPE2ARgqD EKB8aGnsMugz8F8x1a1+j/HtWt5Z9qesWxJcnu88dialLvA09fx23LEv3M1k9jjQnNicj1VUvK3 l9qZP2XN65hKz1Gw9fUP4W2Fz5q7LamCGBbhLVxQF4g+rFbh9lEGijmZ0USEE9trXyMC1Gs2RKB yyAG8zLfFztJLRklSvciFpwh+R+XYcjw9ij2hAI2J8ML34vN7qTQwNC6c6uumBxZx3oEokbkGlj t0YZ+U/1eeJwCSV+RbABlrVyYvq2kZd3U9b8tDqkjqKJvTa+zbjHFKIMpIQ+jATUP85t6unY81W eOu7SyrlDGbl1L4ZjBpdwxGwkQdb0qSStKwbbrm8eKNtUeLmm795j2JD8wkH+bdhPNtY4FQsOYH P1Vua6mxYbTWWwI9v/5cP3qzCEyKjCR2g6CdPRfAwv1CoyU2P4+9NZUvQocF69b64jSS2X X-Received: by 2002:a17:90b:3fcf:b0:38e:9045:bac0 with SMTP id 98e67ed59e1d1-39580ab840amr2698288a91.5.1787106816590; Tue, 18 Aug 2026 19:33:36 -0700 (PDT) Received: from yhlee-960QFG.. ([125.131.91.97]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-3957f9aaa12sm786281a91.5.2026.08.18.19.33.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Aug 2026 19:33:36 -0700 (PDT) From: Yehyeong Lee To: alibuda@linux.alibaba.com, dust.li@linux.alibaba.com, sidraya@linux.ibm.com, wenjia@linux.ibm.com, kuba@kernel.org, davem@davemloft.net, edumazet@google.com, pabeni@redhat.com Cc: leitao@debian.org, horms@kernel.org, mjambigi@linux.ibm.com, tonylu@linux.alibaba.com, guwen@linux.alibaba.com, guangguan.wang@linux.alibaba.com, kees@kernel.org, gustavoars@kernel.org, netdev@vger.kernel.org, linux-rdma@vger.kernel.org, linux-s390@vger.kernel.org, linux-hardening@vger.kernel.org, linux-kernel@vger.kernel.org, Yehyeong Lee , stable@vger.kernel.org Subject: [PATCH net v7 3/3] net/smc: carry oversized SMC-Rv2 LLC messages in the queue entry Date: Wed, 19 Aug 2026 11:33:06 +0900 Message-ID: <20260819023306.644849-4-yhlee@isslab.korea.ac.kr> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260819023306.644849-1-yhlee@isslab.korea.ac.kr> References: <20260819023306.644849-1-yhlee@isslab.korea.ac.kr> 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" smc_llc_rmt_delete_rkey() and smc_llc_save_add_link_rkeys() read the part of a v2 message that does not fit into the 44-byte union smc_llc_msg, and both bound themselves by the size of the buffer it landed in, not by what arrived. On a link with a shared v2 receive buffer a 44-byte DELETE_RKEY_V2 declaring 255 rkeys reaches rkey[9..254] in whatever an earlier message left in lgr->wr_rx_buf_v2, and passes each of them to smc_rtoken_delete(). One of those 255 matched a registered rtoken and deleted it. An ADD_LINK on such a link installs up to 255 rtokens from the same bytes. Copy the tail into the queue entry, so its length is the length of the message that arrived, and declare the rkeys that fit inline as a member of the union instead of reaching them through a cast. The same DELETE_RKEY_V2 now processes the 9 rkeys it carries. The copy is limited to the longest tail the two functions can read, so the peer does not pick the size of the entry. The bound the previous patch placed on links without a shared v2 receive buffer is no longer needed. Fixes: 27ef6a9981fe ("net/smc: support SMC-R V2 for rdma devices with max_r= ecv_sge equals to 1") Cc: stable@vger.kernel.org Suggested-by: D. Wythe Reviewed-by: Sidraya Jayagond Signed-off-by: Yehyeong Lee --- Changes since v5: added the Fixes: and Cc: stable tags; asserted that the t= wo DELETE_RKEY_V2 layouts agree on offsetof(rkey); limited the copied tail to what the two readers can use; corrected the comment in smc_wr_init_sge(). Measured over rxe with KASAN: a DELETE_RKEY_V2 carrying 12 rkeys over a link with a shared v2 receive buffer round-trips all 12 values, the last three coming from the copied tail; 8, 9 and 10 rkeys and a 44-byte message declar= ing 10 give 8, 9, 10 and 9 processed rkeys respectively. kmemleak reports nothi= ng over the link-addition path, and does report the queue entry when the free added by patch 1 is removed again. Five runs per cell with and without the new limit: a 44-byte DELETE_RKEY_V2 declaring 255 rkeys reports 9 processed on a link with and without a shared v2 receive buffer, an ADD_LINK v2 extension installs the 6 rtokens the peer sent, and no KASAN report appears. The only message the limit changes in that lab is a REQ_ADD_LINK, which copied 16 bytes that have no reader and now copies none. On the unpatched kernel the same DELETE_RKEY_V2 reports 254 and 255, and the ADD_LINK installs 255 rtokens per call. Changes since v6: collected Sidraya's Reviewed-by; removed the extra spaces after sentence-ending punctuation. No functional change. net/smc/smc_llc.c | 125 ++++++++++++++++++++++++++++++++-------------- net/smc/smc_wr.c | 6 +-- 2 files changed, 91 insertions(+), 40 deletions(-) diff --git a/net/smc/smc_llc.c b/net/smc/smc_llc.c index 748d65186f68..393aa0af18d1 100644 --- a/net/smc/smc_llc.c +++ b/net/smc/smc_llc.c @@ -157,6 +157,7 @@ struct smc_llc_msg_confirm_rkey { /* type 0x06 */ }; =20 #define SMC_LLC_DEL_RKEY_MAX 8 +#define SMC_LLC_DEL_RKEY_V2_INLINE 9 #define SMC_LLC_FLAG_RKEY_RETRY 0x10 #define SMC_LLC_FLAG_RKEY_NEG 0x20 =20 @@ -177,6 +178,15 @@ struct smc_llc_msg_delete_rkey_v2 { /* type 0x29 */ __be32 rkey[]; }; =20 +/* the leading rkeys of a DELETE_RKEY_V2 fit into union smc_llc_msg */ +struct smc_llc_msg_delete_rkey_v2_inline { /* type 0x29 */ + struct smc_llc_hdr hd; + u8 num_rkeys; + u8 num_inval_rkeys; + u8 reserved[2]; + __be32 rkey[SMC_LLC_DEL_RKEY_V2_INLINE]; +}; + union smc_llc_msg { struct smc_llc_msg_confirm_link confirm_link; struct smc_llc_msg_add_link add_link; @@ -186,6 +196,7 @@ union smc_llc_msg { =20 struct smc_llc_msg_confirm_rkey confirm_rkey; struct smc_llc_msg_delete_rkey delete_rkey; + struct smc_llc_msg_delete_rkey_v2_inline delete_rkey_v2; =20 struct smc_llc_msg_test_link test_link; struct { @@ -194,15 +205,25 @@ union smc_llc_msg { } raw; }; =20 +static_assert(SMC_LLC_DEL_RKEY_V2_INLINE =3D=3D + (sizeof(union smc_llc_msg) - + offsetof(struct smc_llc_msg_delete_rkey_v2, rkey)) / + sizeof(__be32)); +static_assert(offsetof(struct smc_llc_msg_delete_rkey_v2_inline, rkey) =3D= =3D + offsetof(struct smc_llc_msg_delete_rkey_v2, rkey)); + #define SMC_LLC_FLAG_RESP 0x80 =20 struct smc_llc_qentry { struct list_head list; struct smc_link *link; + u16 body_len; union smc_llc_msg msg; + u8 body[] __counted_by(body_len); }; =20 -static void smc_llc_enqueue(struct smc_link *link, union smc_llc_msg *llc); +static void smc_llc_enqueue(struct smc_link *link, union smc_llc_msg *llc, + u32 byte_len); =20 struct smc_llc_qentry *smc_llc_flow_qentry_clr(struct smc_llc_flow *flow) { @@ -998,22 +1019,19 @@ static int smc_llc_cli_conf_link(struct smc_link *li= nk, =20 static void smc_llc_save_add_link_rkeys(struct smc_link *link, struct smc_link *link_new, - u8 *llc_msg) + struct smc_llc_qentry *qentry) { const u32 rt_off =3D offsetof(struct smc_llc_msg_add_link_v2_ext, rt); struct smc_llc_msg_add_link_v2_ext *ext; struct smc_link_group *lgr =3D link->lgr; int max, i; =20 - /* Without a shared v2 receive buffer the extension is not copied - * into the queue entry, so not even ext->num_rkeys is there. - */ - if (!smc_link_shared_v2_rxbuf(link)) + /* the rkey count itself is only there if enough bytes arrived */ + if (qentry->body_len < rt_off) return; - ext =3D (struct smc_llc_msg_add_link_v2_ext *)(llc_msg + - SMC_WR_TX_SIZE); + ext =3D (struct smc_llc_msg_add_link_v2_ext *)qentry->body; max =3D min_t(u8, ext->num_rkeys, SMC_LLC_RKEYS_PER_MSG_V2); - max =3D min_t(u32, max, (SMC_WR_BUF_V2_SIZE - SMC_WR_TX_SIZE - rt_off) / + max =3D min_t(u32, max, (qentry->body_len - rt_off) / sizeof(ext->rt[0])); down_write(&lgr->rmbs_lock); for (i =3D 0; i < max; i++) { @@ -1107,9 +1125,7 @@ int smc_llc_cli_add_link(struct smc_link *link, struc= t smc_llc_qentry *qentry) if (rc) goto out_clear_lnk; if (lgr->smc_version =3D=3D SMC_V2) { - u8 *llc_msg =3D smc_link_shared_v2_rxbuf(link) ? - (u8 *)lgr->wr_rx_buf_v2 : (u8 *)llc; - smc_llc_save_add_link_rkeys(link, lnk_new, llc_msg); + smc_llc_save_add_link_rkeys(link, lnk_new, qentry); } else { rc =3D smc_llc_cli_rkey_exchange(link, lnk_new); if (rc) { @@ -1510,9 +1526,7 @@ int smc_llc_srv_add_link(struct smc_link *link, if (rc) goto out_err; if (lgr->smc_version =3D=3D SMC_V2) { - u8 *llc_msg =3D smc_link_shared_v2_rxbuf(link) ? - (u8 *)lgr->wr_rx_buf_v2 : (u8 *)add_llc; - smc_llc_save_add_link_rkeys(link, link_new, llc_msg); + smc_llc_save_add_link_rkeys(link, link_new, qentry); } else { rc =3D smc_llc_srv_rkey_exchange(link, link_new); if (rc) @@ -1561,7 +1575,8 @@ void smc_llc_add_link_local(struct smc_link *link) add_llc.hd.common.llc_type =3D SMC_LLC_ADD_LINK; smc_llc_init_msg_hdr(&add_llc.hd, link->lgr, sizeof(add_llc)); /* no dev and port needed */ - smc_llc_enqueue(link, (union smc_llc_msg *)&add_llc); + smc_llc_enqueue(link, (union smc_llc_msg *)&add_llc, + sizeof(union smc_llc_msg)); } =20 /* worker to process an add link message */ @@ -1597,7 +1612,8 @@ void smc_llc_srv_delete_link_local(struct smc_link *l= ink, u8 del_link_id) del_llc.link_num =3D del_link_id; del_llc.reason =3D htonl(SMC_LLC_DEL_LOST_PATH); del_llc.hd.flags |=3D SMC_LLC_FLAG_DEL_LINK_ORDERLY; - smc_llc_enqueue(link, (union smc_llc_msg *)&del_llc); + smc_llc_enqueue(link, (union smc_llc_msg *)&del_llc, + sizeof(union smc_llc_msg)); } =20 static void smc_llc_process_cli_delete_link(struct smc_link_group *lgr) @@ -1819,27 +1835,28 @@ static void smc_llc_rmt_delete_rkey(struct smc_link= _group *lgr) link =3D qentry->link; =20 if (lgr->smc_version =3D=3D SMC_V2) { - const u32 rkey_off =3D - offsetof(struct smc_llc_msg_delete_rkey_v2, rkey); - struct smc_llc_msg_delete_rkey_v2 *llcv2; - u32 buf_len; - - if (smc_link_shared_v2_rxbuf(link)) { - memcpy(lgr->wr_rx_buf_v2, llc, sizeof(*llc)); - llcv2 =3D (struct smc_llc_msg_delete_rkey_v2 *)lgr->wr_rx_buf_v2; - buf_len =3D SMC_WR_BUF_V2_SIZE; - } else { - llcv2 =3D (struct smc_llc_msg_delete_rkey_v2 *)llc; - buf_len =3D sizeof(qentry->msg); - } + struct smc_llc_msg_delete_rkey_v2_inline *llcv2; + + /* The leading SMC_LLC_DEL_RKEY_V2_INLINE rkeys are declared in + * the message itself, any further ones were received into + * qentry->body. + */ + llcv2 =3D &qentry->msg.delete_rkey_v2; llcv2->num_inval_rkeys =3D 0; =20 max =3D min_t(u8, llcv2->num_rkeys, SMC_LLC_RKEYS_PER_MSG_V2); - /* bound by the buffer llcv2 points at */ - max =3D min_t(u32, max, (buf_len - rkey_off) / - sizeof(llcv2->rkey[0])); + max =3D min_t(u32, max, SMC_LLC_DEL_RKEY_V2_INLINE + + qentry->body_len / sizeof(__be32)); for (i =3D 0; i < max; i++) { - if (smc_rtoken_delete(link, llcv2->rkey[i])) + __be32 rkey; + + if (i < SMC_LLC_DEL_RKEY_V2_INLINE) + rkey =3D llcv2->rkey[i]; + else + memcpy(&rkey, qentry->body + + (i - SMC_LLC_DEL_RKEY_V2_INLINE) * + sizeof(rkey), sizeof(rkey)); + if (smc_rtoken_delete(link, rkey)) llcv2->num_inval_rkeys++; } memset(&llc->rkey[0], 0, sizeof(llc->rkey)); @@ -2080,18 +2097,52 @@ static void smc_llc_rx_response(struct smc_link *li= nk, wake_up(&link->lgr->llc_msg_waiter); } =20 -static void smc_llc_enqueue(struct smc_link *link, union smc_llc_msg *llc) +/* the longest tail either reader of qentry->body can use */ +static u32 smc_llc_max_body_len(union smc_llc_msg *llc) +{ + switch (llc->raw.hdr.common.llc_type) { + case SMC_LLC_ADD_LINK: + return offsetof(struct smc_llc_msg_add_link_v2_ext, rt) + + SMC_LLC_RKEYS_PER_MSG_V2 * + sizeof(struct smc_llc_msg_add_link_cont_rt); + case SMC_LLC_DELETE_RKEY: + return (SMC_LLC_RKEYS_PER_MSG_V2 - + SMC_LLC_DEL_RKEY_V2_INLINE) * sizeof(__be32); + default: + return 0; + } +} + +static void smc_llc_enqueue(struct smc_link *link, union smc_llc_msg *llc, + u32 byte_len) { struct smc_link_group *lgr =3D link->lgr; struct smc_llc_qentry *qentry; unsigned long flags; + u16 body_len =3D 0; + + /* V2 messages can be longer than the inline union smc_llc_msg. Carry + * the remainder in the qentry itself, so that its lifetime and its + * length match the message the peer actually sent. + */ + if (lgr->smc_version =3D=3D SMC_V2 && byte_len > SMC_WR_TX_SIZE) + body_len =3D min_t(u32, byte_len, SMC_WR_BUF_V2_SIZE) - + SMC_WR_TX_SIZE; + body_len =3D min_t(u32, body_len, smc_llc_max_body_len(llc)); =20 - qentry =3D kmalloc_obj(*qentry, GFP_ATOMIC); + qentry =3D kmalloc_flex(*qentry, body, body_len, GFP_ATOMIC); if (!qentry) return; + qentry->body_len =3D body_len; qentry->link =3D link; INIT_LIST_HEAD(&qentry->list); memcpy(&qentry->msg, llc, sizeof(union smc_llc_msg)); + if (body_len) { + u8 *src =3D smc_link_shared_v2_rxbuf(link) ? + (u8 *)lgr->wr_rx_buf_v2 : (u8 *)llc; + + memcpy(qentry->body, src + SMC_WR_TX_SIZE, body_len); + } =20 /* process responses immediately */ if ((llc->raw.hdr.flags & SMC_LLC_FLAG_RESP) && @@ -2123,7 +2174,7 @@ static void smc_llc_rx_handler(struct ib_wc *wc, void= *buf) return; /* invalid message */ } =20 - smc_llc_enqueue(link, llc); + smc_llc_enqueue(link, llc, wc->byte_len); } =20 /***************************** worker, utils *****************************= ****/ diff --git a/net/smc/smc_wr.c b/net/smc/smc_wr.c index 59c92b46945c..97ba46893b17 100644 --- a/net/smc/smc_wr.c +++ b/net/smc/smc_wr.c @@ -602,9 +602,9 @@ static void smc_wr_init_sge(struct smc_link *lnk) =20 /* With SMC-Rv2 there can be messages larger than SMC_WR_TX_SIZE. * Each ib_recv_wr gets 2 sges, the second one is a spillover buffer - * and the same buffer for all sges. When a larger message arrived then - * the content of the first small sge is copied to the beginning of - * the larger spillover buffer, allowing easy data mapping. + * and the same buffer for all sges. The spillover sge starts at + * SMC_WR_TX_SIZE, so the leading bytes of that buffer are never + * written. */ for (i =3D 0; i < lnk->wr_rx_cnt; i++) { int x =3D i * lnk->wr_rx_sge_cnt; --=20 2.43.0