From nobody Sat Feb 7 22:55:04 2026 Received: from mail-dy1-f177.google.com (mail-dy1-f177.google.com [74.125.82.177]) (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 2035D36657F for ; Sat, 31 Jan 2026 18:53:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.177 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769885633; cv=none; b=uRHQWkKC9/kY/oJ8hml8iPRBYTQTbszdACRWMwQ0bzvSZA+t6GAH/5fkgN+3U8A/UZs+2IxfRIfV82gQz1/GaJIGJ9rEN7QF+Cr3TtUJo70k3t8ZWv0dmQoZI7BEwqxQczPyw55UY6UVFs9AWGzzfyO8p7ROFFbUIhcfDsRPB0g= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769885633; c=relaxed/simple; bh=PBKpupetibXO3Ennx631NgSMEZvGpbZUn+SaHduTJlA=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=V+UhVIbMwSq15QFH8iCiGlrXVUY5T5pt+g/J8pzFM9EXGspMcjQJz6g8pAh268Y+7l/AKM/x6q2dodX8z7AEyaI7IlpSV3GF2FeHXBPwcZx2fH5FC4KiFgGEyZfZQs49gpF8PHxyomP92gcJXBoF8iGyB00NHkZ8Nhk2hABeD6c= 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=FiPWWTNc; arc=none smtp.client-ip=74.125.82.177 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="FiPWWTNc" Received: by mail-dy1-f177.google.com with SMTP id 5a478bee46e88-2b7c5db431cso2996299eec.1 for ; Sat, 31 Jan 2026 10:53:50 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1769885630; x=1770490430; 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=TTZPBapmJrq4oJtHIScdpAnX9Q/PsyNXOSyLOul7qcI=; b=FiPWWTNcntw0/K4ICPesB9SPTPZA6Ygrgp09jAiqy8pGDa7R9H50wHL5xUK8w/pkvX MY2KpB/Of7rSnqL8dJXkiSynK6FBt0sodfdgbzTR0n5MVmkPnfwtSbOfmX/xIlANof9Z hklR/M/2Pe0pJXB6w6NMOiUOZflyMW5JQM1KCqaCMGOOywBOxFbkqbMu2DjWTPMmlE3k 9ZtuPx+vzbFdzxVmRQ+oF48yxjv5iy4Z+PBaXSEwAi97eHdeJxVQ2EfSB6eFsvt+VygE oblUr6fGBigdSFltY0A/IjY5WfLZWsL5xzNCDHZDQoQO33K51T/ZKoamBqopxMFCkGwC JQuA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1769885630; x=1770490430; 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=TTZPBapmJrq4oJtHIScdpAnX9Q/PsyNXOSyLOul7qcI=; b=ZIP1X8VcUv9YkyB6Oz874vpZk+0CBrdaBNaTYE/o+ZCNpTDqfGlkhrhnuueewB168Y DD8P5h+jUkIuJ1If5Y4MMHnabO7DFbz0hyC6M3Zxx55I3EY0MvXp7QDrBu7KOsP9ljKK wHu7Mt6GJd9UrIAzGkLwJygsHnxzn6wW9US/c8UdhXN8X0jKw8jwAM7G+4X+HEvU9fB4 Ma8nreQLbDeWIBzN6XMwrYG+9ABYa35p6tuoatWE5HMZX6tcwIi7232qDBW2MeeExYxC RgI2wR6JayMYnO8j066I3xBgXWuz6Aln5VfGM2Q189Z/SoWM8lKX3GQEJ5hgOD6sqGsV ZAhw== X-Forwarded-Encrypted: i=1; AJvYcCVvjp57SZS+Y0E0JXpGTrCjTFi3FXPqmJSTs3fNiUvg4xqFRms0VjUm39dfbpKwpFDYHeoX4bxcrThevUI=@vger.kernel.org X-Gm-Message-State: AOJu0YzFRL3/cbRWdC5UZUAbjQ9ksDEGjJKiu+3du/I238L7ujh6COIt STNWZbZNA/rZOxhNaPCMvpF0VzXu7K3BPa2Uq6Eo0M5dOiVQdZ4msz9S X-Gm-Gg: AZuq6aLDWWAxUhKOssGoHnTtRUuouNZFhN4DIIxPfz0KWvEMqt610Fknsu3yYHMIWxy yBnq1LtvOppWsEwVTCk+mNbtTVpQ4KM9dh+TRB83Pjk4ebaLfwqMLjUiIm6sHbhLxaQzJC0eaV3 jwl8tr04cCQg10jrPeo0HtR+TfwKarVlwibdFBWPq8qcCvK2KzXBoaixubP9z81EDd2xN8ZDWqo u4v053E6yM2D9A0EEQLn/fU7Dny3J5l2NQL3qfK64iLvTuNMR1u4x0MTXuX+i43B4m3hm4qiMiL NelNCqxBHyAFnQYaosKH7v+JAFAuN9iQdy2368gHsG+DM17GSfIJHRlCT9VQEMkKdkUVgDb+Pg5 z/x/J7SoWn2fgmAvXYAYnFLDITkoCEEAyv1srGQM/VZU7S4YkNZjfeSTs+RZ8Mg1WxqBAqrNHil /7ZAnGZdSemKK0yhxkLx67i2FVl7cOzLgQRFNZEw== X-Received: by 2002:a05:7301:3e18:b0:2b7:4118:88aa with SMTP id 5a478bee46e88-2b7c890c90emr2980431eec.35.1769885630233; Sat, 31 Jan 2026 10:53:50 -0800 (PST) Received: from jpkobryn-fedora-PF5CFKNC.lan ([73.222.117.172]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-2b7a170ca0esm16355941eec.15.2026.01.31.10.53.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 31 Jan 2026 10:53:49 -0800 (PST) From: JP Kobryn To: wqu@suse.com, boris@bur.io, clm@fb.com, dsterba@suse.com Cc: linux-btrfs@vger.kernel.org, stable@vger.kernel.org, linux-kernel@vger.kernel.org, kernel-team@meta.com Subject: [PATCH 6.12] btrfs: prevent use-after-free prealloc_file_extent_cluster() Date: Sat, 31 Jan 2026 10:53:35 -0800 Message-ID: <20260131185335.72204-1-inwardvessel@gmail.com> X-Mailer: git-send-email 2.52.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" Users of filemap_lock_folio() need to guard against the situation where release_folio() has been invoked during reclaim but the folio was ultimately not removed from the page cache. This patch covers one location that was overlooked. Affected code has changed as of 6.17, so this patch is only targeting stable trees prior. After acquiring the folio, use set_folio_extent_mapped() to ensure the folio private state is valid. This is especially important in the subpage case, where the private field is an allocated struct containing bitmap and lock data. Without this protection, the race below is possible: [mm] page cache reclaim path [fs] relocation in subpage mode shrink_folio_list() folio_trylock() /* lock acquired */ filemap_release_folio() mapping->a_ops->release_folio() btrfs_release_folio() __btrfs_release_folio() clear_folio_extent_mapped() btrfs_detach_folio_state() bfs =3D folio_detach_private(folio) btrfs_free_folio_state(folio) kfree(bfs) /* point A */ prealloc_file_extent_cluster() filemap_lock_folio() folio_try_get() /* inc refcount */ folio_lock() /* wait for lock */ if (...) ... else if (!mapping || !__remove_mapping(..)) /* * __remove_mapping() returns zero when * folio_ref_freeze(folio, refcount) fails /* point B */ */ goto keep_locked /* folio remains in cache */ keep_locked: folio_unlock(folio) /* lock released */ /* lock acquired */ btrfs_subpage_clear_updodate() bfs =3D folio->priv /* use-after-free = */ This patch is intended as a minimal fix for backporting to affected kernels. As of 6.17, a commit [0] replaced the vulnerable filemap_lock_folio() + btrfs_subpage_clear_uptodate() sequence with filemap_invalidate_inode() avoiding the race entirely. That commit was part of a series with a different goal of preparing for large folio support so backporting may not be straight forward. Signed-off-by: JP Kobryn Fixes: 9d9ea1e68a05 ("btrfs: subpage: fix relocation potentially overwritin= g last page data") [0] 4e346baee95f ("btrfs: reloc: unconditionally invalidate the page cache = for each cluster") Reviewed-by: Qu Wenruo --- fs/btrfs/relocation.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index 0d5a3846811a..040e8f28b200 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c @@ -2811,6 +2811,20 @@ static noinline_for_stack int prealloc_file_extent_c= luster(struct reloc_control * will re-read the whole page anyway. */ if (!IS_ERR(folio)) { + /* + * release_folio() could have cleared the folio private data + * while we were not holding the lock. + * Reset the mapping if needed so subpage operations can access + * a valid private folio state. + */ + ret =3D set_folio_extent_mapped(folio); + if (ret) { + folio_unlock(folio); + folio_put(folio); + + return ret; + } + btrfs_subpage_clear_uptodate(fs_info, folio, i_size, round_up(i_size, PAGE_SIZE) - i_size); folio_unlock(folio); --=20 2.52.0