From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-wm1-f54.google.com (mail-wm1-f54.google.com [209.85.128.54]) (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 9F63841C2FD for ; Mon, 11 May 2026 18:16:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.54 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778523383; cv=none; b=mOKwIs0hiockHtlwo5UDcPR84IkU0L+drUiXWmhbM8tJAzyQmYHRDPSRruUvg7QNiijcfMbKAr4gpQc8mIfSh8iQQAUbvL2DlAygoXdFA9XyqvO5QtZf2wgRcJa1iBNq+Vnx5WJAbvi8/nSElpYmlzFQ3DivaVbJtdMtWUbzn/o= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778523383; c=relaxed/simple; bh=/ePDKYvRy9DMjD6SCrcU3Xu8vaRvl6YIH1WPK0CW07U=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=fTUl6i8I2Vhuy6Xr4ujbi72kj3QOjxZ7wr26h/OYY4TOwqUEzLKqt/wZpVDOLoM9Q8p/rMJsUEcw9eiRl0kA8JXMrNvKWhj+GDrSeVYzl8hOb8ywFDb7whrUshV9KAZCnIpkD3vvjnr2bf9AurR2ecOU+KX57UkAhw5IDu0MHO8= 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=BPmE1apM; arc=none smtp.client-ip=209.85.128.54 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="BPmE1apM" Received: by mail-wm1-f54.google.com with SMTP id 5b1f17b1804b1-488b8bc6bc9so28854195e9.3 for ; Mon, 11 May 2026 11:16:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1778523380; x=1779128180; 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; bh=mbzWIIoT+Bw+pAGkNBdxls5iXss5yHMpdPL7pkQ74Ps=; b=BPmE1apMbp0xi5Wq87OO4wRZS1lxo1R39LOUPlwcfOpTjBYtZCBCrs8Iq1A8SAW4bl I3tYaeYsyTRYs4iWochCNLLQEZVl6sDCu+8/lvJA2fHOfTmRB1CFxL9rvmGinV9lZ5qF bTHFOZyWhV+AmQy/QPzjoyuKwTnBl7EobVGvVozctfJDT7MkfMW+9vB9fDxLmGmyAuoZ EQjTWkk0o3stlB5Isr/ifVqToh14kfNoW/HNQuEkDCLDVImgGwE7UaZd4rrx0zTxvQ5z xPxZ/StIyjQLJLh4MNua+R5ao3cGI+6lJaJlPM8m7OWa4Hq9oW0BeIFgYuxfwIrRGAND A2Bw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1778523380; x=1779128180; 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; bh=mbzWIIoT+Bw+pAGkNBdxls5iXss5yHMpdPL7pkQ74Ps=; b=SomL+THBoxztFzZKno6IxFVrRNdPxS0l9mpY6o/y2SjbdpiLPq0tU82qWkFtnMlp+f mxg3Vqd/axH4Hv3A4y4rMMKrAMh9mS3HKLNBe7rnl5PGKNpytIJi9BqwGoxy3AldXpZQ 01nzQHS62I+2C08amzGKHKpE2uQ49GIs8mH/Hwd/IQTMwrltjF3zcVHnTw+sGUY3HZWk DIKCeCQcJt9nvesdGVuczl8VphQ1wpUR83jjjswNSbiYKJ7wojVW4o/4ZCNYpfvzo8/e uWY98ecEXmqvFWKmeRr0EvNCGXusFOZ4uLMl3+JDpdQkcw3syrXIMahB7Svg6mmylqC/ kGUg== X-Forwarded-Encrypted: i=1; AFNElJ8MmrnsetXP06xSsGRtrLbikhdYrOeof01CWfTdPOJ2/5+o+DpdugYjkg8OWZyArugEp5XIQPtD4c7kPeg=@vger.kernel.org X-Gm-Message-State: AOJu0Yx3L5SRjiVFMGhU0ViIGzOhzUEa3EQpyDfShpZMYxkV4Q4w76yI 0HDiDPtaZggTzWbbGW+u+X4p0xgXCeW86imW7PWyPtZox98s4bqD91i9 X-Gm-Gg: Acq92OFIMRyN07h5URiTcpVjWuSQSQe3XAu1YEKr57SeDf5xFau0MMcfyAVeUUiZ2vG BKuMunfmPivxp22P+O9mKLB9kNTBCdpETnQBY5QRRGhvaZ3u3rom68Zio5Kkb8WJyVek/PiRIwn /2ULiGGQgaBd74czD7FPXbkGBGI8pVjnF1jeaxUuO8GQdpDO27obBakurYXlwDO7hvy5tkr91Wo +gMN1Y9JnOMJdb3GYLIX8M1ciYS8QLTm5k+ac9VFTy+vqLpDSb9MyolR9BpWSloC/+t+/nsBRFX tTXW8nyEJh2peF2C83s0E2kVECnqOOKCf6a2MVF4kDeRqeEKBD8tbuZSwdPIf5m+kzN8TnjZOxb ctrFKQDXcEf8NOdOFcn3UbCpw8UkccEsUK97mg8OlEkP1UNvQHPbXOZjd5jxX8GpK340jL2a+gu C784AqnkuicAcZMQ2icPdEkelc1S9fwotS1H+rteSDcbRcPG80v1wZbU4FdC9v6eAB8O79Gw352 fUhT+UDEr0YBXl+6Q== X-Received: by 2002:a05:600c:3f18:b0:48e:5990:9698 with SMTP id 5b1f17b1804b1-48e5990978bmr354079365e9.24.1778523379855; Mon, 11 May 2026 11:16:19 -0700 (PDT) Received: from localhost.localdomain ([2a01:827:3b28:500:4954:471e:9dc7:7f18]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-48e6db1742asm68957235e9.31.2026.05.11.11.16.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 11 May 2026 11:16:19 -0700 (PDT) From: Alessandro Schino <7991aleschino@gmail.com> To: ntfs3@lists.linux.dev Cc: almaz.alexandrovich@paragon-software.com, linux-kernel@vger.kernel.org, Alessandro Schino <7991aleschino@gmail.com> Subject: [PATCH] ntfs3: fix out-of-bounds read in ntfs_dir_emit() and hdr_find_e() Date: Mon, 11 May 2026 20:15:15 +0200 Message-ID: <20260511181516.220-1-7991aleschino@gmail.com> X-Mailer: git-send-email 2.41.0.windows.3 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit The bounds check in ntfs_dir_emit() compares fname->name_len (a character count) against e->size (a byte count) without accounting for the 2-byte-per-character UTF-16LE encoding or the ATTR_FILE_NAME header size: if (fname->name_len + sizeof(struct NTFS_DE) > le16_to_cpu(e->size)) This computes: name_len + 16 > e_size The correct check must account for the ATTR_FILE_NAME header (66 bytes before the name) and the UTF-16LE character size (2 bytes each): sizeof(NTFS_DE) + offsetof(ATTR_FILE_NAME, name) + name_len * sizeof(short) > e_size Which computes: 16 + 66 + name_len * 2 > e_size The correct calculation already exists as fname_full_size() in ntfs.h and is used in cmp_fnames(), namei.c, and fslog.c, but was not used in the readdir path. A crafted NTFS image with an index entry containing a small e->size but large fname->name_len bypasses the current check, causing ntfs_utf16_to_nls() to read past the entry boundary. Additionally, add a key_size validation in hdr_find_e() to ensure the declared key_size does not exceed the available entry data, preventing comparison functions from reading past entry boundaries on the lookup path. Signed-off-by: Alessandro Schino <7991aleschino@gmail.com> --- fs/ntfs3/dir.c | 4 +++- fs/ntfs3/index.c | 4 ++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/fs/ntfs3/dir.c b/fs/ntfs3/dir.c index d99ab086..6cd66ce0 100644 --- a/fs/ntfs3/dir.c +++ b/fs/ntfs3/dir.c @@ -305,7 +305,9 @@ static inline bool ntfs_dir_emit(struct ntfs_sb_info *sbi, if (sbi->options->nohidden && (fname->dup.fa & FILE_ATTRIBUTE_HIDDEN)) return true; - if (fname->name_len + sizeof(struct NTFS_DE) > le16_to_cpu(e->size)) + if (sizeof(struct NTFS_DE) + + offsetof(struct ATTR_FILE_NAME, name) + + fname->name_len * sizeof(short) > le16_to_cpu(e->size)) return true; name_len = ntfs_utf16_to_nls(sbi, fname->name, fname->name_len, name, diff --git a/fs/ntfs3/index.c b/fs/ntfs3/index.c index 5344b29b..46dc7642 100644 --- a/fs/ntfs3/index.c +++ b/fs/ntfs3/index.c @@ -754,6 +754,10 @@ static struct NTFS_DE *hdr_find_e(const struct ntfs_index *indx, binary_search: e_key_len = le16_to_cpu(e->key_size); + /* Validate key_size fits within the entry data area. */ + if (e_key_len > le16_to_cpu(e->size) - sizeof(struct NTFS_DE)) + return NULL; + diff2 = (*cmp)(key, key_len, e + 1, e_key_len, ctx); if (diff2 > 0) { if (found) { -- 2.43.0