From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pj1-f53.google.com (mail-pj1-f53.google.com [209.85.216.53]) (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 3F209369D4E for ; Sat, 18 Jul 2026 09:03:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.53 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784365420; cv=none; b=OBCEhxUxB/KxekYvT3FGQdwvv0T2thRQoF/LKzD8IP5Q9xShGz0Z6aPCRSFHuZ61+D1Sf/d3TnMbsKatAEwmvmglIoBf+iPePdHEIeyOymb+Xkyx29vFc04BQ6g4I6rS7BRydSxnBnSlmMss0M9F3qkcq8kZ/vJW31DkSd1fGJ4= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784365420; c=relaxed/simple; bh=wxLNkNVEM+EW0Q1B7ghLRQXzeadsZ5crecqVlqI6M34=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=MSn25ildwwyRlz8C2FkUd6TDofJPw3n7SvtREyYMazw1VRP/G49MvAXI4aIWvq7LfVB95LGJ/BDRU5QgDRwKsaS64MJrVfFivhQH8Ob7Mj1GMmqE7n/PIpE3yWKHFk7M0+OKHudR0DQAKDj7rWOghc06zadUk6tLh3FdFJy79oE= 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=cdFhlmlh; arc=none smtp.client-ip=209.85.216.53 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="cdFhlmlh" Received: by mail-pj1-f53.google.com with SMTP id 98e67ed59e1d1-383cb94f742so8005275a91.3 for ; Sat, 18 Jul 2026 02:03:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1784365419; x=1784970219; 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=DcZ1SQGu/N0fFPEiHGk0VNuvuqYiBFKMIZfbviUQEsU=; b=cdFhlmlh5CUGrLn//aYiR5bNGADDUce8ZSBBMiwgSxYT4FGfzTd3N0zR72JPf8yI9F /5QOkVlqRtnzHPVnag/+JMrWecLP52ixZ8K7y4DJgLWmNxHmQ0EIVAPf3gwB+AqV/+fb nLoWU2sqOfZnXhTfM0pkcH1kfrbM2OJOc6JacVaKDfg5i9y12YiZ/uTWKEZgisnIOgCb /UFafo/sqjF31x+/YhIKFiqCeS2q+kXSkxfHU9k1XSJ02iyfSTUPupTvKIyozWHyZdxM hiXZdkfQqUup/mnWp8SNf4eE29bk60rKU+g+Ip7Paz5+JrBrzQXgvP/ZBriRz+v8+OLT EWiQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1784365419; x=1784970219; 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=DcZ1SQGu/N0fFPEiHGk0VNuvuqYiBFKMIZfbviUQEsU=; b=Zvzpj+UjDQq9Yqv5SVpLYfmmIFMGdWmPW58ycY8q+Dx8KoVCO7uISeIwJPK47vmIkg YqwGwlQBxmqOXj2gZUUd2mCjw3CwWUceUe8HZODgZib5GJjBNK+LzQqaf7KgwrWQCFR8 7g3vD2JdpRQwScjoA8RkYQ0wjqnpKUSY+g10KyFUn9fzA/E3M13jFj43cCyM/C4lQM/C WB3pAw2244WTrPoexhIH9v0OQfBYf5YA/Npen4yrlVkiGR/5JUGuyRGEaPc17wMjmW/R VX/FxLYjCabuqi3EJrHdOiSJ0qhBb3+JtezfA3E/5gf2uKj2oxqGfWyFx8AUp/B5POnt B4Cg== X-Forwarded-Encrypted: i=1; AHgh+RrS3+Nuq/cp9N6MgJiq+L8qZqyOkJtH75mvQ7uY/ikGuLcPbFWYOow5kSgchdYkd0sQnMfeKBYkxCFN4+w=@vger.kernel.org X-Gm-Message-State: AOJu0YwuO5yFTIJxYc069VDXPTWApD1OyTUr68z6YTYPew7ovvVbDtMe YrS+vqzUTzk28eLaWb0WqGEPsBsZAHUl18oC5dDdopJeQxTh5Ks6+ySSrHk5VaOKbgc= X-Gm-Gg: AfdE7clfFU7WYRSFywmVCnKgER3Y3K/0u5FHcRjeMb/HThhQXYLcKcgj2KdJIQ+BXBh uhwOTB6t8f2HqZfsAQgHX0Q/JKmqdHmWQO0AI3M430+h3X+PDQ5q+ZYxzaG6tu+1+lrMGIdIqkR XGp5NEljBUacDpmDHUpswjkSiYpjsaDQ7eMka3hXxXhreE1E9M0ijfSg1vg90Lin75qcBbdtby4 BRa+mYnDjsjUS0JXHUCQi4cVaw8q/eq5SMVdf4F5Qcu8LUXCLL7H22gA+CJ0uEVf64pm3qz7IXS y5Ma/KGOtzIKtzsMxqTV+MpkW3+PurEO2ozDeghmBsAXAKktpx47Is3s2kz9D+uCQH6mWgzchpV NpeuXF/QuL/eBzCoAyLB6k1SDt1Sf6I6s0fbegonRIwBvLqbpd7Xiahtq5nuktsUcF07UkwpVND iHn6NoIlKlbOJl8iBOZZzy+jNgVh7xe/+tLpbniaM9NxCvB14= X-Received: by 2002:a17:90b:388e:b0:38e:475f:810c with SMTP id 98e67ed59e1d1-38e4b5e8a53mr6610509a91.41.1784365418538; Sat, 18 Jul 2026 02:03:38 -0700 (PDT) Received: from fx.tailc0aff1.ts.net ([206.206.192.132]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-3142a20b037sm16580102eec.27.2026.07.18.02.03.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 18 Jul 2026 02:03:37 -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 v2] i2c: i801: keep the byte-by-byte ISR buffer private to the driver Date: Sat, 18 Jul 2026 02:03:30 -0700 Message-ID: <20260718090329.1622366-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: 8bit 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++] = 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: Xiang Mei Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Weiming Shi --- Changes in v2: - Fix the author: From/Signed-off-by. No code change. 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]; #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 = smbcmd | SMBHSTCNT_INTREN; priv->len = len; priv->count = 0; - priv->data = &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 = &priv->data_buf[1]; reinit_completion(&priv->done); outb_p(priv->cmd | SMBHSTCNT_START, SMBHSTCNT(priv)); result = 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; } for (i = 1; i <= len; i++) { -- 2.43.0