From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pj1-f45.google.com (mail-pj1-f45.google.com [209.85.216.45]) (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 8CD9A3806D7 for ; Sat, 2 May 2026 15:43:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.45 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777736608; cv=none; b=H5MU16OHMryDWJWHnZbysR5xMNBDBIzK3Ktqhla2gZX6R/pyl0/vVLk2ixidKrylWB83X0rBqM5c+iy9Xmvyt+G/wHKCLDX8ddFxhxJJJ3KsZ1viYrDTkXusNHAYeH38TkNAFeE97t5k8vM7vO2yXH+up+9ruxq+R8y2dK/A2j4= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777736608; c=relaxed/simple; bh=Qcqo8Bkv1OmcFLp2M409Xk+TJ506bXJtcrDPRa0OEk0=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=O6Qzyov9oE8NwRhVDhK0Fj1o35pr9o6qY71yB7moxzyTGkruf4wc6A7QLXCJMoz8eSQ6ooTAA+61Mwmi4YCcX+AC9fU88Vp6UZm7UpU6AjozE9eQajoDvM4Bj1QagGaWejknAX54jQKg/IC4RlK4nJlKRRtqyS1IlcI+CRb2yM0= 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=Y/pOUegs; arc=none smtp.client-ip=209.85.216.45 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="Y/pOUegs" Received: by mail-pj1-f45.google.com with SMTP id 98e67ed59e1d1-36526b81c21so14313a91.0 for ; Sat, 02 May 2026 08:43:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1777736606; x=1778341406; 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=dPLhh/sYehPY6xGFGWFMg/n/yf/ziOgLoWmXDVIRRZ4=; b=Y/pOUegsqE3BfsxqGiYVDMQl/OkgrXGS7GwbdOvefwrVA9LlPUs+SDxcl1S992Lwo/ yjGwIII2G1JCRzaXCpENO1YgAd+agBRgoko+NjtrBlWdtfMuFXa5e7pB+y/z+dlEhhYx wauy8uxzRyoI2pFSnW21PUc3cDiSl3ZCwmzLkXjF9/Ys96V5uXHOkxjaYaJDhkVWf6w/ YtlW9SBiottGcA1mnXGYs0go8GHBb/dMu+EQp0E+mQW5EUqxgJqYB13nDlt/ewHHQJYA 2hCvBDekCs8NN8MZrYOzY5ZiJIJWFamDI9+kgLhEoVfrzPYgR+wj+jETYBcmM6Me8BlX 4cUw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1777736606; x=1778341406; 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=dPLhh/sYehPY6xGFGWFMg/n/yf/ziOgLoWmXDVIRRZ4=; b=brrGmT2KrPLuBeVLQF37NIE+CvcBraZoINS4YsoKnfKlxvs3PTheZpQeR9A3GCxmQl 7MZew2HH/m8Qi2VfnammgHUJFl2R8frtfV8u0VMw/3nXCd4ObFlqqucadsA2xChSZqch XgAogtOAd8rJwYM+//w0Gzn74aN4EkYhztywMQJZZdXnxQzyAw3wX6Zqnht10fkdBsFk 8FCc6YSWuiUKrItwpH0+5Q5mplgKOihqQKxbZ/fy2+HQz7HWlf1PCWXMvGmQdWr8l1HD tvREgdAnIMrvfwmxGuRa4DEnRXr6Ak5vveaacusDkQdU35ERLQ2wHVArGI5Cjpm4RSs1 g+8w== X-Gm-Message-State: AOJu0YwBSaX/0xBZD3Md1K7RLK0+OsmkWoV5JeiYShPCbXqWPUYin9tC drRidkkmT9p+3mhsrYCD1QyOTF/Y0KLaqFT7qkJozxQno1vt/EFJVzLE X-Gm-Gg: AeBDievzCsaWIDI9Ru1M+EvJbEa7xjIeJ0JlwmL/IeMY+J8RC+qQJxt2ZiN6nbQ/Ha+ 81nHp+VT/F+QaoGkNebHxqVaOChQRmhSDKOTiXXuSIZu06ThwoBVTUdcLlYZrasU24VpUY9ax2k Zlurgn+WzcP30L9Ew29mrfwQqQxAagP4Te3wLPVZ0/nZLgHu0Hqh9imD2vPHsABpLXiTslGdZGA /e0OURox5WUadzzmfyQ0rgxXEIhEEbE7szmVQ7YaijH43SzSqK/JS/vKwAKha81Bj/aL732HJj9 MGnwdrCTmys9NqWBhh83+RH/1HS65o6M1832504EqXPE+q6nFdCUGpOkBowm89AVsCmFN9v3bMr KIuMmTjzOjJ74MjhwmoyoM/x1wpE07ZoO5VgQlHOhf+gIWHRL5NgPT4SGBQO4k5UjuKqercYmJd FOzgNkcJ2wKL9fXnNjh4KH06pV/6l8 X-Received: by 2002:a17:90a:d407:b0:362:be3b:c8d4 with SMTP id 98e67ed59e1d1-3650ce10197mr1847644a91.3.1777736605937; Sat, 02 May 2026 08:43:25 -0700 (PDT) Received: from kali ([103.195.202.195]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2b9caaae29dsm52915385ad.19.2026.05.02.08.43.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 02 May 2026 08:43:25 -0700 (PDT) From: Pavitra Jha To: almaz.alexandrovich@paragon-software.com Cc: linux-kernel@vger.kernel.org, ntfs3@lists.linux.dev, stable@vger.kernel.org, Pavitra Jha Subject: [PATCH] fs/ntfs3: validate lcns_follow in log_replay conversion Date: Sat, 2 May 2026 11:42:51 -0400 Message-ID: <20260502154252.164586-1-jhapavitra98@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: 8bit log_replay() converts DIR_PAGE_ENTRY_32 records into DIR_PAGE_ENTRY records when replaying version 0 restart tables. During this conversion, the memmove() length is derived directly from the on-disk lcns_follow field: memmove(&dp->vcn, &dp0->vcn_low, 2 * sizeof(u64) + le32_to_cpu(dp->lcns_follow) * sizeof(u64)); check_rstbl() validates restart table structure, but does not constrain per-entry lcns_follow values relative to the entry size. A malformed filesystem image can provide an oversized lcns_follow value, causing the conversion memmove() to access memory beyond the bounds of the allocated restart table buffer. The same field is later used to bound iteration over page_lcns[], so validating lcns_follow during conversion also prevents downstream out-of-bounds access from the same malformed metadata. Compute the maximum valid lcns_follow from the already-validated restart table entry size and reject entries that exceed this bound. Reuse the existing t16/t32 scratch variables already declared in log_replay() to avoid introducing new declarations. Fixes: b46acd6a6a62 ("fs/ntfs3: Add NTFS journal") Cc: stable@vger.kernel.org Signed-off-by: Pavitra Jha --- fs/ntfs3/fslog.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/fs/ntfs3/fslog.c b/fs/ntfs3/fslog.c index c0237f7d0..91dc2d503 100644 --- a/fs/ntfs3/fslog.c +++ b/fs/ntfs3/fslog.c @@ -4215,13 +4215,22 @@ int log_replay(struct ntfs_inode *ni, bool *initialized) if (rst->major_ver) goto end_conv_1; /* reduce tab pressure. */ + t16 = le16_to_cpu(dptbl->size); + if (t16 < sizeof(struct DIR_PAGE_ENTRY)) + goto dirty_vol; + + t32 = (t16 - sizeof(struct DIR_PAGE_ENTRY)) / sizeof(u64); + dp = NULL; while ((dp = enum_rstbl(dptbl, dp))) { struct DIR_PAGE_ENTRY_32 *dp0 = (struct DIR_PAGE_ENTRY_32 *)dp; - // NOTE: Danger. Check for of boundary. + u32 lcns = le32_to_cpu(dp->lcns_follow); + + if (lcns > t32) + goto dirty_vol; + memmove(&dp->vcn, &dp0->vcn_low, - 2 * sizeof(u64) + - le32_to_cpu(dp->lcns_follow) * sizeof(u64)); + 2 * sizeof(u64) + lcns * sizeof(u64)); } end_conv_1: -- 2.53.0