From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pl1-f171.google.com (mail-pl1-f171.google.com [209.85.214.171]) (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 A43588287E for ; Mon, 27 Apr 2026 04:52:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.171 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777265559; cv=none; b=MsLLmKbtnrduDMAyAcBbC0oisjyZ1g4d0UYccAyhS/LrdvpcLkAzEzGLWwD6QGj47lQ5iLas9sm72qRbDsLwwVZhlnbwlxc4PtTPtqcTpwMbhCtzeCfkbC3iqqCfiUAVBqq0NaYfTpNJ5ySixEimu0DmGnPxnBb4FUTldyLsGrw= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777265559; c=relaxed/simple; bh=bM0Xwd5dls9Z5gOFS6K7bvtolAkJX85lZOyxdWBaEDE=; h=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=OPydTlnKMvjdC2qiji+gZ3q/srM0EBN9iuYMUpbsIuwG7jd+sQy6oAxUU74+Z1FqhI9mPvvkBbllYToLRD9iEFYQQb8vAaUuKwJAdGqXOOQ3I/gfmImmzndSnqvI92byGL45avJhOpFHXydeKYL7zliN1z2mOWU+n1zA/f0QLdA= 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=Ta2uUsxX; arc=none smtp.client-ip=209.85.214.171 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="Ta2uUsxX" Received: by mail-pl1-f171.google.com with SMTP id d9443c01a7336-2b788a98557so45285595ad.2 for ; Sun, 26 Apr 2026 21:52:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1777265558; x=1777870358; darn=vger.kernel.org; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:from:to:cc:subject:date:message-id:reply-to; bh=MYGjbgqA8sfSy7ijwz+W7o0Ei+QecHCwo356psEF9nw=; b=Ta2uUsxXjON2YEVN2aqwnSFaxg1ejWds3UpACM6y3Xo/HP0PDNDhvNkzCVdtZeSdR8 PCCX9gsKcvlUitsBY2lxE6jpGyMz96+v7DK3+NZsCpVULriTUn6G7fU5cmYAZ3BIck34 CZ43ovBXKDDEbhFYn/x5w6loRaFEoq48BIFeaU2GEyByqY2KBjXonkDaXaRY/1abM8u3 kCV1G+bxzCNKKVfPcMQ7QSjiaKUIP9b4mv2PXi8wL0UrNUn0N1UQbrQC/GgYv+xHaCDk 32pJiS9nMyk77FPdW+kUne4Mn385ud03ekzM9yp3OmJ9HPrH/cU84WdwT/CZkC2kf7CJ RnnQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1777265558; x=1777870358; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:x-gm-gg:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=MYGjbgqA8sfSy7ijwz+W7o0Ei+QecHCwo356psEF9nw=; b=T2vrTjc3LvhZZIzGR9ITkAdudcwz1fUUZ9olS1fLOntH0uEXvtk7fuqJPo8KATS7gb bmEtMz9rcJ028lk49ZOlzNvWfS0QN8be54yiszKihiab+1aKaqQfds6vMNRz6Eyi6BT3 2bQ+IehHHlgYKXYh3Yetr4n7YLZNoapaT5y20tExOMtpyqEe9qzRHPL4BQtd7bTWkZjC 4Yfo6KhZIpDxumj+BDUx616vDTRN1xTe9gQeTHxpAUpbbJ+3UYtZgRDGZkiVqNwLsTzM JJu6k3oGiXeaRIDnd1xTmtwgdmJtnkiVhPpvzvAV8PKUl20TQZGzYTCIeGcQcQ1s8de6 5KcQ== X-Gm-Message-State: AOJu0YziYmWfEJvJI2P/+jFvDcOgI+UzZFSCljY6mkIURs4qXtb1/XHT 2tzmMIpSC4lEaQdU6/DP08gmRW/FQkKbEyi6kTWSWNRCfHogEo8surDng3dyVsJ9Uig= X-Gm-Gg: AeBDieuIHxfM4en0eI/3atvJqKTYawhUlmzD594CPQeHhQpMtj8JCr4vf1SqB3I6b4d DVhem8Ov9myxwGc5qeM6tk2Zf+UfsvFO8JQt65gAVeV+xP4xPNPpCifVVaACKRgqE2IQTdsui1y UNA5djh65HJoF79uPnYwBXR0aOhrfi36xbbayffeSIpu5B+KTyUcmvIULvMyUAWysE6h53U8Bxe PkIqA3ZEAwcWP0tURQMEyxLZsdx9+RYVHDA1uwDePdXaHtuqPjMndaa+vzsJZ6jHBCf3cea2sFh T6MLRICGOB8xY1Tyyb5Tntn5YxAxQdL7CdBt0jlOFYWqZgJuhV0bL6QJX6thYYo5JVXU7Wexbr8 YoVxlVCOukw5q13MU+4lBwov4Adl/M0o62UcoF1WFB8XouxA88ApqsHgqHf5CeIjbafEGQeANaA KdISqctnrdntDci1usuBnNvsUC X-Received: by 2002:a17:903:1212:b0:2b4:6608:41dd with SMTP id d9443c01a7336-2b5f9edec67mr416025325ad.17.1777265557945; Sun, 26 Apr 2026 21:52:37 -0700 (PDT) Received: from localhost ([27.122.242.71]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2b5faa1763dsm271801815ad.23.2026.04.26.21.52.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 26 Apr 2026 21:52:37 -0700 (PDT) Date: Mon, 27 Apr 2026 13:52:34 +0900 From: Hyunchul Lee To: Zhan Xusheng Cc: linux-kernel@vger.kernel.org, Zhan Xusheng , linkinjeon@kernel.org Subject: Re: [PATCH v3] ntfs: fix VCN overflow in ntfs_mapping_pairs_decompress() Message-ID: References: <20260423045227.249857-1-zhanxusheng@xiaomi.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-Disposition: inline In-Reply-To: <20260423045227.249857-1-zhanxusheng@xiaomi.com> Hello Zhan, On Thu, Apr 23, 2026 at 12:52:26PM +0800, Zhan Xusheng wrote: > In ntfs_mapping_pairs_decompress(), lowest_vcn is read from > on-disk metadata and used as the initial vcn without validation. > A malformed value can introduce an invalid (e.g. negative) vcn, > corrupting the runlist from the start. > > Additionally, the accumulation > vcn += deltaxcn > > does not check for s64 overflow. A crafted mapping pairs array > can wrap vcn to a negative value, breaking the monotonically- > increasing invariant relied upon by ntfs_rl_vcn_to_lcn() and > related helpers. > > Fix this by validating lowest_vcn and using check_add_overflow() > for vcn accumulation. > > Signed-off-by: Zhan Xusheng The recipient is wrong. Anyway looks good to me. Reviewed-by: Hyunchul Lee > --- > v3: > - Use overflows_type() for lowest_vcn validation (Hyunchul) > v2: > - Validate lowest_vcn from on-disk metadata > - Use check_add_overflow() for vcn accumulation > --- > fs/ntfs/runlist.c | 24 +++++++++++++++++++++--- > 1 file changed, 21 insertions(+), 3 deletions(-) > > diff --git a/fs/ntfs/runlist.c b/fs/ntfs/runlist.c > index b213b4976d2b..be6ca3d374bb 100644 > --- a/fs/ntfs/runlist.c > +++ b/fs/ntfs/runlist.c > @@ -15,6 +15,8 @@ > * Copyright (c) 2007-2022 Jean-Pierre Andre > */ > > +#include > + > #include "ntfs.h" > #include "attrib.h" > > @@ -739,6 +741,7 @@ struct runlist_element *ntfs_mapping_pairs_decompress(const struct ntfs_volume * > int rlsize; /* Size of runlist buffer. */ > u16 rlpos; /* Current runlist position in units of struct runlist_elements. */ > u8 b; /* Current byte offset in buf. */ > + u64 lowest_vcn; /* Raw on-disk lowest_vcn. */ > > #ifdef DEBUG > /* Make sure attr exists and is non-resident. */ > @@ -747,8 +750,14 @@ struct runlist_element *ntfs_mapping_pairs_decompress(const struct ntfs_volume * > return ERR_PTR(-EINVAL); > } > #endif > + lowest_vcn = le64_to_cpu(attr->data.non_resident.lowest_vcn); > + /* Validate lowest_vcn from on-disk metadata to ensure it is sane. */ > + if (overflows_type(lowest_vcn, vcn)) { > + ntfs_error(vol->sb, "Invalid lowest_vcn in mapping pairs."); > + goto err_out; > + } > /* Start at vcn = lowest_vcn and lcn 0. */ > - vcn = le64_to_cpu(attr->data.non_resident.lowest_vcn); > + vcn = lowest_vcn; > lcn = 0; > /* Get start of the mapping pairs array. */ > buf = (u8 *)attr + > @@ -823,8 +832,17 @@ struct runlist_element *ntfs_mapping_pairs_decompress(const struct ntfs_volume * > * element. > */ > rl[rlpos].length = deltaxcn; > - /* Increment the current vcn by the current run length. */ > - vcn += deltaxcn; > + /* > + * Increment the current vcn by the current run length. > + * Guard against s64 overflow from a crafted mapping > + * pairs array to preserve the monotonically-increasing > + * vcn invariant. > + */ > + if (unlikely(check_add_overflow(vcn, deltaxcn, &vcn))) { > + ntfs_error(vol->sb, "VCN overflow in mapping pairs array."); > + goto err_out; > + } > + > /* > * There might be no lcn change at all, as is the case for > * sparse clusters on NTFS 3.0+, in which case we set the lcn > -- > 2.43.0 > > -- Thanks, Hyunchul