From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pl1-f179.google.com (mail-pl1-f179.google.com [209.85.214.179]) (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 B8B7B372EF5 for ; Sun, 26 Jul 2026 08:04:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.179 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785053065; cv=none; b=N3vDL84+ad65oaGfh9g20obljPfM/gqoWko0qGlONTzPoXP2DzTZxpwjmzex1UhmrUVg1srmP/iUQZTv9LC8OY1/6IK0gc030p0m2Vb+tIg0/5eHF1Mc1wHYmVd4nE3WxajhcLS8CGHI02eFhYOYzk2faADQIwE87nhCMbSmeIM= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785053065; c=relaxed/simple; bh=Y7HcoRerzsbgTMKBHjGeBjlXnASBY1wVnyZiToHg+S0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=UY63bTrqtnq1GrW54mlsEdtAsGD5MiMb9+5lDYzDy2N2JMrmSI/kQvjitOBV2lr/59nLWycZl1mHBcaP9l27oSa9XkrgPvQM0GhATcO7ZS529zJvQAK6KRaxUZabsiinld1swwdOF26arkfGHLEgjzb1kaURbUgr/OfqLHOAFQo= 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=XMS4EqwQ; arc=none smtp.client-ip=209.85.214.179 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="XMS4EqwQ" Received: by mail-pl1-f179.google.com with SMTP id d9443c01a7336-2cc7ef7ec27so22002135ad.1 for ; Sun, 26 Jul 2026 01:04:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1785053063; x=1785657863; darn=vger.kernel.org; h=content-transfer-encoding:content-type: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=Pc+LLUxUsAlG4VNPUy+0mBD+EfmSxjlMd8BD9q3fDIk=; b=XMS4EqwQRmWWEEy+kDeohTo3n9a4hZth8paKV+SoVvM6v5nXx8lI+3CvLpyh5aYmKq sQy7YOTXODIOp7zPLxoJyhS1rx0hjM9HbPtKIGtEefU0BSfcrTI5MIeT7fwxaYrLdInX HbrxEnRDrcDDuLZTnE3PMifKdX6VYys+gVJgm4qq2ZBZXc88Lo4rT6uxRohsoKu3S5+w YqTKgsBXY1uEnHdf/t75nI+WPsj39r+2fAR4jF8NaKsZs5Ba2GApq1IacpKdwDYzpnNo 46H/iw/afEE47cy7Hh3ktmjHnJzDKyYFCj+VAxlgxGLzfEZq2JwvzqPZtJ0ciUkeNfUH hphg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785053063; x=1785657863; h=content-transfer-encoding:content-type: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=Pc+LLUxUsAlG4VNPUy+0mBD+EfmSxjlMd8BD9q3fDIk=; b=l1rWzj1LKT2g26M0wdTgGroGoJBzyfyhYotQCcd2ZBHbK/Dr8JZcFkWUEW6rsvbl/o 8qZLLSK2ZjM5b5SzsZFbGmT9h8eO/zMsci+gFcbiLkPneGX0WahqsEXaSYLuoe2GNpA5 YmA8uZt+5+kOcXwBzT5g8q3KEYnfpXyCXVvZRmk1rMD60vSpGqCAdh7u+4t6fZBORZK1 kWNpA/rmMTC40rZceRfj0CLcOt06MTrEm5ZRTInyrRA0q5wvQrK1eA6elGHFboXFmlgH pH9jHxWjcHklS8z9e+v86fgYBogcWa3sgMbN31kC9Ib+XHPkVAThogcyWk6DECX4at9a +01A== X-Forwarded-Encrypted: i=1; AHgh+RoYFKnYDVgrk3JjrWgOJq2Q78hUFQ9SPP0dZPvAlKH3gAZskDuXkMVRox8XcaiguTYcwiWCa5vC2B/PSbk=@vger.kernel.org X-Gm-Message-State: AOJu0YxFWis9IwI1qVJmsQadc4RL4NqEpLIgHNb7ttIsS0c4OaIv7kGl 3lJkmxmFWpaYQedOHcoIo18gTehiXq63qe4bA7HtAT+7NfiuJDAu0FaY X-Gm-Gg: AR+sD10d2I2ORPhn+PwNCxGtV/ajpa4VDWScy8N288l0woYFfKAQyBrds+kDMe+zWH9 5oYBkg80iBEEe6sb3kPdbjwLKjwx4d5FlZn5xQkR2P9GIvEpHiaRknGIcheLIW/5ffXiYZpS9v9 /qe0huhkgCvD3dpsHP4EBqjfWPjGEGMEB+DsxDjIyFoK7CigvjCQy43ZWAyGp7/7eVOFlpBVpcH J0kIf6Fn4wvjJJ5+shc8504d2zSYFERO5OAh7QYRaGS0n4RvUCkHHznPqecYeonh5PGSeyhGqnb DlaiG43bHHPEb+ctc4IBoP8Hu3JM9qZVWc5EV0+kG5sXE+URps8dZW6dYE9Qy706NRH68qDbtbT uMaafYst5P2SUWFdqlGFJ3r4mZ0q6HQXxPvRifC0JkdUISSGlkm3hnckqOvOqEkm7JH5gUHE8ef oRHFJZbOxf5tcnCgikmqV7hIGVPiRt6quSXeRBcTL3fSvIDlBjVqnzsSl3oXBv4Ic= X-Received: by 2002:a17:902:c402:b0:2cf:a2d2:84c0 with SMTP id d9443c01a7336-2cfde55bb4amr44610785ad.0.1785053062892; Sun, 26 Jul 2026 01:04:22 -0700 (PDT) Received: from localhost.localdomain (211-20-143-81.hinet-ip.hinet.net. [211.20.143.81]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2cfde5e2b8esm17503365ad.31.2026.07.26.01.04.19 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Sun, 26 Jul 2026 01:04:22 -0700 (PDT) From: =?UTF-8?q?HE=20WEI=20=28=E3=82=AE=E3=82=AB=E3=82=AF=29?= To: Israel Cepeda , Hans de Goede , Greg Kroah-Hartman , Andi Shyti Cc: Sakari Ailus , linux-usb@vger.kernel.org, linux-i2c@vger.kernel.org, linux-kernel@vger.kernel.org, HE WEI , stable@vger.kernel.org Subject: [PATCH 3/3] usb: misc: usbio: bound the debug hex dumps by the received length Date: Sun, 26 Jul 2026 16:59:13 +0900 Message-ID: <20260726080129.44969-4-skyexpoc@gmail.com> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260726080129.44969-1-skyexpoc@gmail.com> References: <20260726080129.44969-1-skyexpoc@gmail.com> 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: 8bit usbio_ctrl_msg() and usbio_bulk_msg() hex dump the reply with "%*phN", using a length the device supplied and that has not been validated yet: ret = usb_control_msg(usbio->udev, pipe, 0, request | USB_DIR_IN, 0, 0, cpkt, cpkt_len, USBIO_CTRLXFER_TIMEOUT); dev_dbg(usbio->dev, "control in %d hdr %*phN data %*phN\n", ret, (int)sizeof(*cpkt), cpkt, (int)cpkt->len, cpkt->data); cpkt->len is a u8 read back out of usbio->ctrlbuf after the IN transfer, and bpkt_len in usbio_bulk_msg() is le16_to_cpu(bpkt->len) read out of usbio->rxbuf. Both are handed to "%*phN" as the field width. hex_string() in lib/vsprintf.c caps that at 64, and dereferences every byte up to that cap regardless of how much room the output buffer has: if (spec.field_width > 0) len = min(spec.field_width, 64); for (i = 0; i < len; ++i) { if (buf < end) *buf = hex_asc_hi(addr[i]); So the dump reads up to byte 67 of ctrlbuf and byte 68 of rxbuf. Both buffers are sized from the endpoint packet sizes, so this is out of bounds whenever ep0 wMaxPacketSize is below 68 and whenever the bulk in endpoint is below 69. That covers every low, full and high speed ep0 (8, 16, 32 or 64) and the bulk sizes the supported bridges actually use (64, or 63 for the Synaptics Sabre via USBIO_QUIRK_BULK_MAXP_63). A device answering one of the five usbio_ctrl_msg() calls in usbio_probe() with cpkt->len = 255 therefore leaks up to 60 bytes of adjacent slab memory into the kernel log during enumeration, before any user space is involved. On the bulk path a reply claiming bpkt->len = 0xffff reads 5 bytes past a 64 byte rxbuf. Unlike the endpoint size issues this needs no malformed descriptor at all; it only needs the dev_dbg() calls to be enabled. When they are, it is a slab-out-of-bounds read under KASAN and the bytes reach dmesg. Bound both dumps by the number of bytes actually received. That is in bounds by construction and also stops the dump printing stale bytes left over from an earlier transfer. The matching dumps on the two OUT paths are left alone: they use lengths the driver itself just wrote, which the size checks above them already bound. Found by code review. The out-of-bounds read was reproduced under AddressSanitizer with a userspace model of the two dev_dbg() call sites and of hex_string()'s field-width handling; it has not been exercised on hardware or on dummy_hcd. Fixes: 121a0f839dbb ("usb: misc: Add Intel USBIO bridge driver") Cc: stable@vger.kernel.org Signed-off-by: HE WEI (ギカク) --- --- a/drivers/usb/misc/usbio.c +++ b/drivers/usb/misc/usbio.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -141,7 +142,7 @@ struct usbio_ctrl_packet *cpkt; unsigned int pipe; u16 cpkt_len; - int ret; + int dbg_len, ret; lockdep_assert_held(&usbio->ctrl_mutex); @@ -181,8 +182,15 @@ cpkt_len = sizeof(*cpkt) + ibuf_len; ret = usb_control_msg(usbio->udev, pipe, 0, request | USB_DIR_IN, 0, 0, cpkt, cpkt_len, USBIO_CTRLXFER_TIMEOUT); + /* + * cpkt->len has just been written by the device and is not validated + * until below, while %*phN dereferences up to 64 bytes of whatever + * field width it is handed. Bound the dump by what was received. + */ + dbg_len = (ret > (int)sizeof(*cpkt)) ? + min_t(int, cpkt->len, ret - (int)sizeof(*cpkt)) : 0; dev_dbg(usbio->dev, "control in %d hdr %*phN data %*phN\n", ret, - (int)sizeof(*cpkt), cpkt, (int)cpkt->len, cpkt->data); + (int)sizeof(*cpkt), cpkt, dbg_len, cpkt->data); if (ret < sizeof(*cpkt)) { dev_err(usbio->dev, "USB control in failed: %d\n", ret); @@ -258,7 +266,7 @@ struct usbio_client *client = adev_to_client(adev); struct usbio_device *usbio = client->bridge; struct usbio_bulk_packet *bpkt; - int ret, act = 0; + int ret, act = 0, dbg_len; u16 bpkt_len; lockdep_assert_held(&client->mutex); @@ -314,8 +322,14 @@ act = usbio->rxdat_len; bpkt = usbio->rxbuf; bpkt_len = le16_to_cpu(bpkt->len); + /* + * Same as in usbio_ctrl_msg(): bpkt_len is device supplied and is only + * validated below, so bound the dump by what was received. + */ + dbg_len = (act > (int)sizeof(*bpkt)) ? + min_t(int, bpkt_len, act - (int)sizeof(*bpkt)) : 0; dev_dbg(usbio->dev, "bulk in %d hdr %*phN data %*phN\n", act, - (int)sizeof(*bpkt), bpkt, bpkt_len, bpkt->data); + (int)sizeof(*bpkt), bpkt, dbg_len, bpkt->data); /* * Unsupported bulk commands get only an usbio_packet_header with -- 2.51.0