From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pj1-f49.google.com (mail-pj1-f49.google.com [209.85.216.49]) (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 A288833ADAF for ; Wed, 6 May 2026 09:24:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.49 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778059496; cv=none; b=XUsmkRuY7vR718blKobCvOW5ZMZkKJaNzKczMpM3G8BMpy6Z9WpvjSRxgo3dyLZXoS+JXlC/8KvogNY2Anuh2zF3Ye1/1WyXAprBmY+tblmbA+PIOcnb//JfmlkPsPbUHtzjkF9I3oqSe+IWVWClDzy+ShD4a6cV8Uz9Wv0Vikc= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778059496; c=relaxed/simple; bh=OV7kw/pGisRe9JOuNhKKAFp1urzMk+K+3mO5rR+o9CM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ipaXp+5L828t7xRenenwvNeAsWAJOI24PWCS9rfDX1rCUJxiBTFq98QYc4rotgjc2SCZ8AIKU7n9auZHqexbSLot7mFAD8xVXouImgGWUpx32Fhn3+NAdgL2nT4Jzdk+CHAWw0KAfIcgLRCY0+Ecm+Xst1Vii2IpvnxSbNpSFVI= 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=DFfCSmAT; arc=none smtp.client-ip=209.85.216.49 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="DFfCSmAT" Received: by mail-pj1-f49.google.com with SMTP id 98e67ed59e1d1-364d13df3ccso897136a91.3 for ; Wed, 06 May 2026 02:24:53 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1778059493; x=1778664293; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=IVw4UQ1Otw6PPSYzAZJJw/x+RLkMIP+IcH6IHhLdhuQ=; b=DFfCSmAT2g1FMDV/A69vtN7FzMYztdQVCTbrkR3fU+/s1pn8pe7LYeMbhFW0hR7Zz7 kfi0YcVDY3VhqUBwj8FhYGdkvKbRnHhI/1da2OapfCwzAimdz5mHp0NKcosjQMXFhOpW 4eeOxT7EN9j354U4cJu4nXh37zUgalxLOUAQAl7S9w1hkMhO3KLzu56/uNmjQ1c/zGxV 9QKp8zSjZZcChprz4HvPhUkFc+l2/d7agY1V4zVkDVlkWYOQQLKKjITzbyQYG2m1Wfzg cewCruCaCDLJpx7HmmQEL8l6M9MFZfZ8i++rQqYc5X1eZZMav0q4L1nv/DevadiG2VES T2dg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1778059493; x=1778664293; h=content-transfer-encoding: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; bh=IVw4UQ1Otw6PPSYzAZJJw/x+RLkMIP+IcH6IHhLdhuQ=; b=f4N5hsJMeErqxCpXbpb4iz0tqnT/jIi7tlqYOGkCqz86LR4qd4wQ/GXc//Al+Uf4Rv opNnnq8wSLUH6oyc1MHOecSb+NFVSLICgZJTzQPZo/LxgH1nmi38zOCaDYPR0Ewb+iwS 5yyEIDepASoa3bAOj5ibPXYEwqYvO9pLqb+E3Xox4H34MHaBty0hy9q6Vdjz6E0E+txk KILdVUjGBsIV/dgIm5DYlnW7l5PdKU1tdWZLgkKXT/twPle8o/aRg9Htz7pYS5PlJHTt VgUOwSl6t4eMgVYks+IhOaZlVSFQfSc4BfjH0HQuOiRfLyzoJ1ijj2kz/uR1SvMq1NIx YdVA== X-Forwarded-Encrypted: i=1; AFNElJ9uVy+57dwBqIBjIYihg+JVnVxURS6vAega94PypLYZ1ANjDazsjaNeznh+MmhwMG2ifzSZMI9nKKTyPFg=@vger.kernel.org X-Gm-Message-State: AOJu0YwaZY1HqVq9NtZ0SgVvtCPFpm5jHanDMRWvZRIL2LJ4iiMiZhaX iyZ+vt8qZ0JMQoy6sI8p3OKbv3h3QMcdueA6SPemFggsvG9l8QG/VPva X-Gm-Gg: AeBDietOGcY+KSYfo9PGXlzNmu1EAhIWe/eUnmb4+/6dQfku1ZfLKFeqj9XJFgOR4XG x6cMxRw7mOEeC7D2MUcQurp0VJCqy04q4ysMNpJEMiMp1ov/i2aWT2v0rmYie7f3REQT2EnUuMl T2GBQrSQMdErqAUHEsVkj0+SXLRjzMwPgor1O2fDt3THtq7uhdiTnc98XzHG63HggaVdLWLAMj4 OKrPokgDb/obXZfH4Zs14HLgF5C3HHIy/u6KWEtDUPNPy4LFm2rFR5koU9RarvzAKAZCqVG7xSS gxLsF+T81VwLpMBPapmXCQkTwyHbp4/IPBmYO3iB9uUk6VHJopTA+98QZB9TIOzCRzYjL5AJWe/ xduufBfnEG1nzKNLT7okCBwdekwq9fHbDEp4p+VeSB6ULkfmFd+icjMvw7JXPO7o7GdNq9atKbd 0b2zE+5JTel+QJrGxqHVr5qPDFqpk= X-Received: by 2002:a17:90a:c886:b0:35d:ab8b:abe6 with SMTP id 98e67ed59e1d1-365ad70d711mr1408222a91.4.1778059492859; Wed, 06 May 2026 02:24:52 -0700 (PDT) Received: from ser8.. ([221.156.231.192]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-365b4bc8fb9sm2101888a91.4.2026.05.06.02.24.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 06 May 2026 02:24:52 -0700 (PDT) From: DaeMyung Kang To: Namjae Jeon , Hyunchul Lee Cc: linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, DaeMyung Kang Subject: [PATCH v2] ntfs: fix out-of-bounds write in ntfs_rl_collapse_range() merge path Date: Wed, 6 May 2026 18:24:48 +0900 Message-ID: <20260506092448.521995-1-charsyam@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260504154851.3034915-1-charsyam@gmail.com> References: <20260504154851.3034915-1-charsyam@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit ntfs_rl_collapse_range() merges the run on the left of the collapsed region with the run on its right when they are contiguous. The contiguous check chooses a clamped index when @new_1st_cnt is 0: i = new_1st_cnt == 0 ? 1 : new_1st_cnt; if (ntfs_rle_lcn_contiguous(&new_rl[i - 1], &new_rl[i])) { but the merge itself uses the unclamped value: s_rl = &new_rl[new_1st_cnt - 1]; s_rl->length += s_rl[1].length; When @new_1st_cnt is 0 this computes &new_rl[-1] and writes 8 bytes before the kvcalloc() runlist buffer. The path is reachable through fallocate(FALLOC_FL_COLLAPSE_RANGE) starting at vcn 0 against an attribute whose first run after the collapsed region and the following run are holes. In that case ntfs_rle_lcn_contiguous() returns true because both checked entries are LCN_HOLE, so the merge path is entered with @new_1st_cnt still 0. Such consecutive holes do not occur on a well-formed runlist (NTFS keeps runlists coalesced in memory), so this OOB path is only reachable from a crafted volume. A normal runlist has no element to the left of vcn 0, so the left/right merge is not valid when @new_1st_cnt is 0. Require @new_1st_cnt to be positive before checking or performing the merge. This skips the merge entirely in that case instead of clamping the merge target. The out-of-bounds write can corrupt an adjacent slab object. On a non-KASAN kernel, it is reachable after a crafted NTFS volume has been mounted read-write with the legacy fs/ntfs driver, by a local user that has write access to the crafted file. Fixes: 11ccc9107dc4 ("ntfs: update runlist handling and cluster allocator") Suggested-by: Hyunchul Lee Signed-off-by: DaeMyung Kang --- Changes since v1: - Skip the merge entirely when @new_1st_cnt == 0 instead of using a clamped index, per review feedback. The clamped form silently changed the operation's semantics from "merge the run left of the collapsed region with the run right of it" to "coalesce two right-side runs"; the new form closes a path that is only reachable on malformed runlists. Behaviour on well-formed runlists is unchanged. fs/ntfs/runlist.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/fs/ntfs/runlist.c b/fs/ntfs/runlist.c index da21dbeaaf66..e7de3d01257e 100644 --- a/fs/ntfs/runlist.c +++ b/fs/ntfs/runlist.c @@ -2056,10 +2056,11 @@ struct runlist_element *ntfs_rl_collapse_range(struct runlist_element *dst_rl, i * consists of holes. */ merge_cnt = 0; - i = new_1st_cnt == 0 ? 1 : new_1st_cnt; - if (ntfs_rle_lcn_contiguous(&new_rl[i - 1], &new_rl[i])) { - /* Merge right and left */ - s_rl = &new_rl[new_1st_cnt - 1]; + if (new_1st_cnt > 0 && + ntfs_rle_lcn_contiguous(&new_rl[new_1st_cnt - 1], + &new_rl[new_1st_cnt])) { + /* Merge right and left. */ + s_rl = &new_rl[new_1st_cnt - 1]; s_rl->length += s_rl[1].length; merge_cnt = 1; } -- 2.43.0