From nobody Sat Jul 25 04:29:55 2026 Received: from mail-pj1-f46.google.com (mail-pj1-f46.google.com [209.85.216.46]) (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 F3D5016CD33 for ; Sat, 18 Jul 2026 08:29:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.46 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784363364; cv=none; b=iRhNPumL1FGO7wYRDK4pjooa9A7FTT5rlMv2IQOUMqkKKsz1YkPM1IbyCTzhRb6iUozQB9BVLYPla8TBmeDxnWlIMQFBQwz0813qpOvt7N6Om0dfaA9XUNOH3ODbcSyuiHW6afDiNbdARN8Q1zAPRyFbcvDTqbwEthXVgQGJ2xE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784363364; c=relaxed/simple; bh=cFRdYJQ9DUesk8N2/b/6uB5QoE/r+87nPyzHhbww9sA=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=YfohZ/0RcG1xvC++eJmrbN8pg2S94m4pcnEUfYWHcQOur8nL+BWMX7iwTt6Y0nXlCIbj1E9gobnrDsk0SRTteJyAW4UKp9GjTupT+dr4CKyqzwg8TNxGY3c7T0Os0QGAPLuBDn7Y+Dga+hjDf2hUfHztJmHNcyQFfuGT5NuF0y0= 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=mnz7TtNg; arc=none smtp.client-ip=209.85.216.46 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="mnz7TtNg" Received: by mail-pj1-f46.google.com with SMTP id 98e67ed59e1d1-38e58034d05so794572a91.2 for ; Sat, 18 Jul 2026 01:29:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1784363362; x=1784968162; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to:content-type; bh=4BDHRtDWbYPF+cmLCV698xypLp+xxdwFOzev9CgqvlM=; b=mnz7TtNgUQduymo1Oe/0fx5lcZ+bEAxAHn+6mRJiBggv7Wnd4UhThVcUvJu2e9Kwz+ 9DAZec1zZddA7pF7dDGrC5kB1B1yOoqrmeidR/VIDT7ee/aLhCy7tAiLMLjbKICWiQYh X5vmOKBD3aulOatEdwDNvVrM5SYurPbO3dVTimrlodmUnCvWBDnAlwvcqcgdePP8mggq 9Cym4KYR6Y4j0aBLWLDnnXm8U4wPfsbIgEh9kI0Iat6eAqOkoa05RwAKXFBFXSmLCMD/ nwH8RPOkLLXHaj8bMshaeynstBCp26DueoXZrN3RZumYwy7Skza7C0Q+ZlSsZK/XkLIM quFg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1784363362; x=1784968162; h=content-transfer-encoding:mime-version: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=4BDHRtDWbYPF+cmLCV698xypLp+xxdwFOzev9CgqvlM=; b=ZNmyJnj9YLAARDXMi7rIeVz3gRnUA0mxQKmaa8OrshpYLCdsGHiXI9oE+MmrcgJStK Z50VC0eTDQjOHAcdilolCvolBtEEH6msEq16HDflo2LSMmkKmLQ37kle5XLW2ZAaL2Gt snA1JVlg9V9GP2VG+YJ0O5rDGMTJsk9DPaTi/4km6b9brbMcoRWgKdT31MGjAjfl0Ey8 dosefE26X2pbEiO2j1xTmSQq+MIWYS23nFSExShevS5ZS/AOjFZp2Z0lEXleyZflwC8C ov8ucVVXExOC7mEaYIYY8+2465h0WFfNAx/RZL+VTVFI1il6x7BbOF9K1u2bXqRILf5F eT5g== X-Forwarded-Encrypted: i=1; AHgh+RrpGVJflEZuYYK2hqa/cR//l/YzObiJWJLgbHmvPeur5w3cBBwhBdI9TNG+KSLd1nHKV/F1/SB3kntaJfk=@vger.kernel.org X-Gm-Message-State: AOJu0YzmM6kAJV0oT6pmy3i3pmw3sr2mevTCZjrBz8RjzpY8IsOo5gz2 /PxtBLvr1qqzNS6Jyr79tJUbmIHr/53Q/yJKtRIaycXo3AMPdwa0rGgB X-Gm-Gg: AfdE7cmaP1trVkgeeBHbM27VMXg9ufpA8g73TnwxNVTeM8ybPClxVn+uTL7/xY47RIl hzu76j9a4pmPVk+3Rjz6wMQMKQNcwIsBhB2xdtxnVF036FtCd+meu4wnwAniLmEBEBlFrU+CuEh EPZecm5gUw/6pgFqGAsns0TTH0MV8dtKsfMzE3VC+K6bb7sn4ce1i2jSBmygrpypS+rSc3Z9CiE ROsKrP5n80gy7sf725iSVE4+iQFy/vCuMoGLJgFticdFhDH5RFfHG5Z9Z0KhqnR//fnY7MME0gh X7CP0cKUQEMkZvXpzx5PXgkf9IVjhKkvGszccDxI5PUjQNXYp0zb2Y2X7cyAxf1+cxD50Ih1qKy f/I9dceAcDrHt0H57XQt1k5wEURJIxQoVU+dUFcaXOP8L7IN/ADlHRvQH7odAM9akOh5o0WJWto f4skCqQm00tsQqwn3MqCe3cuqoX3fJy5OpHmAmLCCECYziRfQ= X-Received: by 2002:a17:90b:2684:b0:38d:f5bb:e0f4 with SMTP id 98e67ed59e1d1-38e4b3e1473mr6213134a91.1.1784363362183; Sat, 18 Jul 2026 01:29:22 -0700 (PDT) Received: from fx.tailc0aff1.ts.net ([206.206.192.132]) by smtp.gmail.com with ESMTPSA id a92af1059eb24-13ce2ddfb35sm12522523c88.14.2026.07.18.01.29.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 18 Jul 2026 01:29:21 -0700 (PDT) From: Weiming Shi To: Jean Delvare Cc: linux-i2c@vger.kernel.org, linux-kernel@vger.kernel.org, Xiang Mei , Weiming Shi Subject: [PATCH] i2c: i801: keep the byte-by-byte ISR buffer private to the driver Date: Sat, 18 Jul 2026 01:29:05 -0700 Message-ID: <20260718082904.1561226-2-bestswngs@gmail.com> X-Mailer: git-send-email 2.43.0 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" From: Xiang Mei For interrupt-driven byte-by-byte block transfers, i801_block_transaction_byte_by_byte() points priv->data at the caller's union i2c_smbus_data and lets the BYTE_DONE interrupt handler i801_isr_byte_done() fill or drain it one byte at a time. In the i2c-dev ioctl path that buffer lives on the caller's kernel (vmap) stack. On a wait_for_completion_timeout() the transfer thread returns -ETIMEDOUT without fencing the interrupt, and a BYTE_DONE that is still in flight or fires later then writes a byte through priv->data (priv->data[priv->count++] =3D inb(...)) after the caller has returned and its vmap stack has been freed: BUG: KASAN: stack-out-of-bounds in i801_isr Write of size 1 at addr ffffc90002a2fda9 by task exploit/5144 i801_isr_byte_done drivers/i2c/busses/i2c-i801.c:546 [inlined] i801_isr drivers/i2c/busses/i2c-i801.c:613 __handle_irq_event_percpu kernel/irq/handle.c:158 handle_irq_event kernel/irq/handle.c:195 handle_fasteoi_irq kernel/irq/chip.c:661 __common_interrupt arch/x86/kernel/irq.c:263 common_interrupt arch/x86/kernel/irq.c:240 The buggy address belongs to a freed vmap kernel stack (task exploit), created by kernel_clone -> copy_process. The completion-based paths (i801_transaction(), i801_block_transaction_by_block()) never expose the caller's buffer to the handler: they copy to/from the hardware block buffer in process context and use the interrupt only to signal completion. Give the byte-by-byte path the same property. The handler now fills a driver-private buffer (priv->data_buf); the transfer copies the caller's data in before starting and copies the result back out on success, so a late or spurious BYTE_DONE can only ever touch driver-owned memory. i801_block_transaction() already bounds data->block[0] to I2C_SMBUS_BLOCK_MAX, so the buffer cannot overflow. Fixes: d3ff6ce40031 ("i2c-i801: Enable IRQ for byte_by_byte transactions") Reported-by: Weiming Shi Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Xiang Mei --- drivers/i2c/busses/i2c-i801.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index c8cb5ed55..37741fdca 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -279,6 +279,9 @@ struct i801_priv { int count; int len; u8 *data; + /* Driver-private buffer the isr fills/drains, so a late interrupt + * never dereferences a pointer into the caller's block buffer. */ + u8 data_buf[I2C_SMBUS_BLOCK_MAX + 2]; =20 #if IS_ENABLED(CONFIG_I2C_MUX_GPIO) && defined CONFIG_DMI const struct i801_mux_config *mux_drvdata; @@ -671,12 +674,23 @@ static int i801_block_transaction_byte_by_byte(struct= i801_priv *priv, priv->cmd =3D smbcmd | SMBHSTCNT_INTREN; priv->len =3D len; priv->count =3D 0; - priv->data =3D &data->block[1]; + /* + * The interrupt handler fills or drains this buffer + * asynchronously and may still run after a timeout, so keep it + * in driver-private storage instead of pointing into the + * caller's block buffer, which is freed once we return. + */ + memcpy(priv->data_buf, data->block, len + 1); + priv->data =3D &priv->data_buf[1]; =20 reinit_completion(&priv->done); outb_p(priv->cmd | SMBHSTCNT_START, SMBHSTCNT(priv)); result =3D wait_for_completion_timeout(&priv->done, adap->timeout); - return result ? priv->status : -ETIMEDOUT; + if (!result) + return -ETIMEDOUT; + if (priv->is_read) + memcpy(data->block, priv->data_buf, priv->len + 1); + return priv->status; } =20 for (i =3D 1; i <=3D len; i++) { --=20 2.43.0