From nobody Sat Jul 25 23:03:58 2026 Received: from mail-qk1-f173.google.com (mail-qk1-f173.google.com [209.85.222.173]) (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 3F5812D73B6 for ; Sat, 11 Jul 2026 15:26:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.222.173 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783783609; cv=none; b=mKQVBTjC1pOQGZ/kApMtcWQfAaANT+2mxMRbhGZlKAYeOQw1qf2jVhohFTvDzreVZ6krHHtc5YbGROnhR6wc8Eh3r2zb0fb3o6ye7pxwRQxDIuBDR1z0a3GsrVC3pVcx0ugijXnabeQyN5CG8uUgZyjtcXjXA3w08IpT83fPeU4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783783609; c=relaxed/simple; bh=qu2LqjVG3gwCwIWPHQe2SrI7PA5vY7y+JJc4s9CiPJ0=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=dWLR651xfJQIWiivVu+HAwFCV6axcxFRQPI6QCfMrFy4WU1yivLPGkg2YJlWeA3HYCsRpT0ykPXNQ8E47xU/e8sc9MwnRW3L3alY5KzvnjmpNSv9I1K/1V96X2BysNoIGVwtIB8lSjW5O9ExS5r/xiQZhbn+IPikRu6ZG0Ab6cc= 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=Lgc5ovR3; arc=none smtp.client-ip=209.85.222.173 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="Lgc5ovR3" Received: by mail-qk1-f173.google.com with SMTP id af79cd13be357-92efc443c61so21857685a.2 for ; Sat, 11 Jul 2026 08:26:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1783783607; x=1784388407; 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=OGvjcggjuRHrVJRozwL5aIcsoUIst8NdaqhwI9EK350=; b=Lgc5ovR37HI4QAbBbdYChotZWcBl99mvDQVgjxQw8+KssIf/9bUBBj4hdjh6E61nfr yD4AXD4/lZvzFpdFTcSnGxHucPyQ0zct251JRNOyl/dsefg6rIXPcP62mvjlOwbF+4QS 2IO6KtPto/gqzp5cP26o+EKYfWlBITqVuXsJ+TX5NBAENRLfouZ2cfYIdV2PKsh9bzE6 eBuMKJrijSa+a5uzjxH+ww/U+FNYCEJ3nc+frVpvCwCzHi1tVhktV4FEQY/wljAOn3rR QD66FhcXx8jmbKf8X/OTIPkW5CGWHp6Ob2Q4uYCubkepDcOJ8dAtVlq4aFFNXdzei2W3 GYbQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1783783607; x=1784388407; 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=OGvjcggjuRHrVJRozwL5aIcsoUIst8NdaqhwI9EK350=; b=TtLrKJ5OZnj+jt5MhkVgqy42jf6IbV0I9XuszKABFCNP6N6U+frBkjDgCWch3A/qXG VGNwMs2J/KKYNjuHreqf6MczCclgYsW/td632IbjK3KBsn2DslrMIoCDX1DSWwgB/6Xe mzTPtF9ybKRxIycy+0oPKxR4hAsg0AMMBi2O80Rbm9Hy1nu/j/IicNcNJ3FyhcMbmccG AWtESzacux9bkaVF683G2RYlncpFLYH1L6cUAzQ0P1nGKv9s54SS2XOXwZFLd8KFgNtH oDmSQxSV42ZCvBUmNjOVcGhBtCVGqwtjTBbGJ3QJhx5uCUEcIOUYB6vP7jdSMDVnCt1Z 2Yuw== X-Forwarded-Encrypted: i=1; AHgh+RrEeXdh9b2ORp1miMpsn7xtU7371pPNt/P4eyL1JHqmY6uDZxPgMtC1pWg8GhDW/NRJm1nWJYAq/ksiZ94=@vger.kernel.org X-Gm-Message-State: AOJu0YwyjLBOYnT/U3YMDkQfaNK7Tttuj8lAXR/yJ2f0wwggvvzl6Qyh XRCxepJP99oQ6Vxgw4jtv+nu9Nymiyanh6NukKTmaLkz8nRLLBbQtL5f X-Gm-Gg: AfdE7cmkhAXseHySRj7A/7fMvX2jK4P3FMVjmbnVvWJHMTGbRENqSGhX90mck372uPm GoUoAAO7FlvGbEVW2ubg4NSnDZ4kjksFYALdvxi7Sd3rKDT/YeBq23rI003rJUX9zNhJjEPzH9x bYX2NItjPnHlJEJD3EsQGefb7IcSqhZGrodmgKn0B7z9wvp5i6nbhrhsMa4VP2MOYuzDLiwhyNO vFttg1JM6ZW5KR4snng5vAX4fsvXyYN5Y1unH/fNhmEgm6Mab5FHkOzev0rVIK3jB9YahMF5+Re wlFpNy9KFpYUR+nuKWTFXlJ7BBsA7vkUV2UjW8aHmS9TOcehLOYMiMudGPFGWuLoOvpCPLO2Ys1 2n6Dm0kzjp8bJ0/mKZnMR8rFWv2G2QpzNb2dJVLYQR/JlZSNw49N2rbjxtvEdicqBo8xlawXM/1 qh2+hPlS+k22ZIGkvJewG/UaxyS9Myin9ERSrglvxR1AY3xl1EedSPAKfjZn1y5QLqTUnrkYn0O tRpzol4EQ== X-Received: by 2002:a05:620a:2245:10b0:92e:51fc:3f1a with SMTP id af79cd13be357-92ef2c844demr268665485a.67.1783783606862; Sat, 11 Jul 2026 08:26:46 -0700 (PDT) Received: from server0 (c-68-48-65-54.hsd1.mi.comcast.net. [68.48.65.54]) by smtp.gmail.com with ESMTPSA id af79cd13be357-92ee5b492ebsm468641285a.9.2026.07.11.08.26.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 11 Jul 2026 08:26:46 -0700 (PDT) From: Michael Bommarito To: Konstantin Komarov , ntfs3@lists.linux.dev Cc: Mihai Brodschi , linux-fsdevel@vger.kernel.org, stable@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v2] fs/ntfs3: reject an oversized resident attribute on the inline iomap path Date: Sat, 11 Jul 2026 11:26:30 -0400 Message-ID: <20260711152630.2975127-1-michael.bommarito@gmail.com> X-Mailer: git-send-email 2.53.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" attr_data_get_block_locked() maps a resident attribute as a one-page IOMAP_INLINE extent: it allocates a single page, copies the resident value into it with memcpy(), and hands that page to ntfs_iomap_begin() as the inline data. The copy length is the on-disk resident value length (res.data_size), and mi_enum_attr() only bounds that length against the MFT record size. A corrupted volume with MFT records larger than a page can therefore present a resident $DATA whose length exceeds PAGE_SIZE, and the memcpy() then writes past the single destination page. Impact: reading or writing a resident file on a mounted crafted NTFS volume whose MFT records are larger than a page overflows the one-page inline buffer in attr_data_get_block_locked() with attacker-controlled bytes. Reject such an attribute in attr_data_get_block_locked(), before the page is allocated and the copy is made. Fixes: 099ef9ab9203 ("fs/ntfs3: implement iomap-based file operations") Cc: stable@vger.kernel.org Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Michael Bommarito --- Changes since v1: - Reworded the code comment and changelog. The oversized resident length overflows the single alloc_page() page that attr_data_get_block_locked() copies the resident value into; v1 described the older iomap_write_end_inline() BUG_ON(!iomap_inline_data_valid()), which was removed in 7.2-rc1. Thanks to Mihai Brodschi for catching the stale reference. The fix itself is unchanged. The unbounded resident length dates to the iomap conversion; only the manifestation changed when the inline buffer became a single alloc_page(): - 7.2-rc: the memcpy() into the one-page buffer overflows the page (out-of-bounds write, below). - 7.0..7.1: the buffer was kmemdup()ed at the real size and the oversized length instead tripped BUG_ON(!iomap_inline_data_valid()) in iomap_write_end_inline() (a denial of service). The same data_size > PAGE_SIZE check prevents both, so it is the correct fix across the stable range. Reproduced under QEMU + KASAN on 7.2-rc2. A resident $DATA value length above PAGE_SIZE, as a volume with MFT records larger than a page presents, was supplied while the alloc_page() + memcpy() path ran unchanged; the stock kernel faults with a KASAN out-of-bounds write in attr_data_get_block_locked(): BUG: KASAN: out-of-bounds in attr_data_get_block_locked Write of size by task ... __asan_memcpy attr_data_get_block_locked attr_data_get_block ntfs_iomap_begin iomap_iter iomap_file_buffered_write With the patch the same access returns -EINVAL and does not fault. An in-bounds resident file (control) and a non-resident file are unaffected on both the stock and patched kernels. fs/ntfs3/attrib.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/fs/ntfs3/attrib.c b/fs/ntfs3/attrib.c index c621a4c582f9e..2f73714a2db97 100644 --- a/fs/ntfs3/attrib.c +++ b/fs/ntfs3/attrib.c @@ -1034,6 +1034,21 @@ int attr_data_get_block_locked(struct ntfs_inode *ni= , CLST vcn, CLST clen, =20 if (!attr_b->non_res) { u32 data_size =3D le32_to_cpu(attr_b->res.data_size); + + /* + * A resident attribute is copied into a single page below + * (alloc_page() + memcpy()) and mapped as a one-page + * IOMAP_INLINE extent by ntfs_iomap_begin(). mi_enum_attr() + * only bounds the resident value length against the MFT record + * size, so a corrupted volume whose records are larger than a + * page can report data_size > PAGE_SIZE; copying that many bytes + * would overflow the single destination page. Reject it. + */ + if (data_size > PAGE_SIZE) { + err =3D -EINVAL; + goto out; + } + *lcn =3D RESIDENT_LCN; *len =3D data_size; if (res && data_size) { --=20 2.53.0