From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pl1-f179.google.com (mail-pl1-f179.google.com [209.85.214.179]) (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 410953446C7 for ; Wed, 10 Jun 2026 17:29:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.179 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1781112595; cv=none; b=dyvTe8m1XlyFWm2AybhgFQ2MXl6LPNPKPmOUZd+bzMJzrD7XE4mQWJ+ZjcCSkwphQp5bRXT18KqSbSLuJHhgZxgdIyyCIt0TAE3ujjRlJS5k0Ac05r17vy8n3QG+Abw62kPhufbCi9WLPPlLSTpOj6or3rXcagej7lSVZ6OySug= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1781112595; c=relaxed/simple; bh=XZfnN6ZNxwHS7fU7g8TzTldYmgQ7NvyTpBuR7s+jRiY=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=m6JRW+WkTprR9ngOlIbPvwzcoCNT8hHY1RXgWghrCsZD/THuGVr+guCOdn5JlyJSBxNoLyJUMbQMZagRCWFrPRQS6GFL0tT81BJlP9UR405OEMykO5RG2WgnSx68z1IX5wSnRvgsx2h1U9OZkTr327YZiiw7DGGUl5JNnkZIArc= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=asu.edu; spf=pass smtp.mailfrom=asu.edu; dkim=pass (2048-bit key) header.d=asu.edu header.i=@asu.edu header.b=iIPkiBf8; arc=none smtp.client-ip=209.85.214.179 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=asu.edu Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=asu.edu Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=asu.edu header.i=@asu.edu header.b="iIPkiBf8" Received: by mail-pl1-f179.google.com with SMTP id d9443c01a7336-2bf20f6be6bso56120115ad.3 for ; Wed, 10 Jun 2026 10:29:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=asu.edu; s=google; t=1781112594; x=1781717394; 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=3wRjusoj4yCY+EA/COKpBZREn13VScyeq7V5TJXl1HQ=; b=iIPkiBf8wOUpUGeI/cO5DAFscFSswVIaBog7Lqete9fNfmopPLHUuHAlR2BdrxAtFs TO/Sw5DZoMfi5msVA+5072uOc1HNeaDrmugg9PEDgIEm3wrGENRBTT+o3PuBadoldHYl Q/UcEXCYNJgkdankAyv1KoBWFY8VrIWI53nj0TKKIGiBsOi3+aiylk2uwLol9i5dWV5F cL9Ldmw0177CmxEo+vvlmdDC2YsOTqO1OaMCHaEoXrh8LmVaBk9chIxdNYLBad1AzPtJ oNh9q8b8OfYCbCgqyMF6E8GEv69ZTJ3zdzs99IfQVW14FvpIW8sDPxNSeOjkasz8k73M kzIA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1781112594; x=1781717394; 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=3wRjusoj4yCY+EA/COKpBZREn13VScyeq7V5TJXl1HQ=; b=jSI4gJIt2Gm3perrZF4U88U93Ao/rnJd/axD3MLZlhotjL8NJNgoheEMQ4cx4mL6WL 0ErOfAKEzUYsKi5Ijvx5PCdvZlO2K+s2MtgCktjYzMAHlnfenXH6/rKoo2XYHj761YhY Vfyq0YlHrsnIf9Ktlhx1NFdM5XrkiWSlAeJJd/LBbt+rc9mMC/PqajN606/lLrr4muxx S6M45hKl2Vw16HYNkmIi21E6h9X7/BeQNqZk6UxXjLbgdHkxM/B4h49HLPFXqmKugYuD jEOVgqJx9GBkg0w2CfP067QyY8qQ5EWMyU71o1I5ppalwndX3Ba9ykYXyulz25lOK3zH GUfQ== X-Forwarded-Encrypted: i=1; AFNElJ/gp5G7KPrmsnGsbM3G+hozcE1fD2I3WtZMj+ypalvmzQwUIcm7v2DPqpSSkQ8wYnr3T2K69LED3Fti8/k=@vger.kernel.org X-Gm-Message-State: AOJu0Yw98EL88E73wRABrBp4dQzYYFtjkKQYX/Ad5LhyoxgqE10uxA+W j8nGNGmKJdfYpLv1QLU0J8zJA6t6Xt8F596kudxGYWT6j4mN/CHAEOoIucfaksOKSQ== X-Gm-Gg: Acq92OFKNSCp/4/6L8jPw/1USbBsGy0FnTUpbr3Tv1X1BIdzVDupjJKWXC/dhWRqYLT hfbWStCTCOKBQP3d0M8JqYjG78tGwXt45EdRTNWdVe5boa1kjkYy3IltQjFWcEgvCu0XneBBhMl Vl2Wp6/lN8Kmv3VpMBHTnk7MwmpFMxyIyBJlySrMTxl6essVkNKfTO34pwtMRsM2b55gUar0Ew+ MxnuVZurYam5ZmtL/egCg8xN6m2XbS0e3SSwCMpCuIY4Y7/vxcucDK5u/EfSzH3p3/weCi3kQXA Cm+R6Xo1Q0AOB1F275Vuvq98y7LcPwWDBWv8bIXpGeFH7gKkXcuLXwvGrQm/XHufbV2wY6yhfxh rVs1EXC4unnTAUphAJoL+Cu8nTip6n/hz/u/jukAVIf7uoRh26RhlBzcVL/63VMEGNKWTXWM5cP pYOF2Q9gSwJgmRGcVFvzA= X-Received: by 2002:a17:903:19e6:b0:2c0:b6c7:227e with SMTP id d9443c01a7336-2c1e79e1fd3mr271789045ad.5.1781112593535; Wed, 10 Jun 2026 10:29:53 -0700 (PDT) Received: from p1.. ([2607:fb90:ec2a:d56a:f3c0:4361:94a8:6696]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2c16609df6esm275109775ad.48.2026.06.10.10.29.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 10 Jun 2026 10:29:53 -0700 (PDT) From: Xiang Mei To: David Sterba , Chris Mason , linux-btrfs@vger.kernel.org Cc: Josef Bacik , Weiming Shi , linux-kernel@vger.kernel.org, Xiang Mei Subject: [PATCH btrfs v2] btrfs: reject free space cache with more entries than pages Date: Wed, 10 Jun 2026 10:29:26 -0700 Message-ID: <20260610172926.844265-1-xmei5@asu.edu> X-Mailer: git-send-email 2.43.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 When loading a v1 free space cache, __load_free_space_cache() takes num_entries and num_bitmaps straight from the on-disk btrfs_free_space_header. That header is stored in the tree_root under a key with type 0, which the tree-checker has no case for, so neither count is validated before the load trusts it. The load loops num_entries times and maps the next page whenever the current one runs out, going through io_ctl_check_crc() -> io_ctl_map_page(), which does io_ctl->pages[io_ctl->index++]. But pages[] is allocated in io_ctl_init() from the cache inode's i_size, not from num_entries: num_pages = DIV_ROUND_UP(i_size_read(inode), PAGE_SIZE); io_ctl->pages = kcalloc(num_pages, sizeof(struct page *), GFP_NOFS); So if num_entries claims more records than the pages can hold, io_ctl->index runs off the end of pages[]. The write side never hits this because io_ctl_add_entry() and io_ctl_add_bitmap() both stop once io_ctl->index >= io_ctl->num_pages; the read side just never had the same check. To trigger it, take a clean cache (num_entries = here), set num_entries in the header to 0x10000, and fix up the leaf checksum so it still passes the tree-checker. The cache inode has i_size = 65536, so num_pages is 16 and pages[] is a 16-pointer (kmalloc-128) array. The load now tries to read 65536 entries, io_ctl->index walks up to 16, and pages[16] is read past the array: BUG: KASAN: slab-out-of-bounds in io_ctl_check_crc (fs/btrfs/free-space-cache.c:420 fs/btrfs/free-space-cache.c:565) Read of size 8 at addr ffff88800c833a80 by task kworker/u8:3/58 io_ctl_check_crc (fs/btrfs/free-space-cache.c:420 fs/btrfs/free-space-cache.c:565) __load_free_space_cache (fs/btrfs/free-space-cache.c:655 fs/btrfs/free-space-cache.c:820) load_free_space_cache (fs/btrfs/free-space-cache.c:1017) caching_thread (fs/btrfs/block-group.c:880) btrfs_work_helper (fs/btrfs/async-thread.c:312) process_one_work worker_thread kthread ret_from_fork free-space-cache.c:420 is io_ctl_map_page(), inlined into io_ctl_check_crc() at line 565, which is why that is the frame KASAN names. The out-of-bounds slot is then treated as a struct page and handed to crc32c(), so the bad read turns into a GP fault. Add the missing check to io_ctl_check_crc(), which is where both the entry loop and the bitmap loop end up. When num_entries is too large the load now fails like any corrupt cache: __load_free_space_cache() drops it and rebuilds the free space from the extent tree, so a valid cache is never rejected. Fixes: 5b0e95bf607d ("Btrfs: inline checksums into the disk free space cache") Reported-by: Weiming Shi Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Xiang Mei --- v2: add more details in the commit message fs/btrfs/free-space-cache.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index ab22e4f9ffdd..bbc4db7fe74b 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c @@ -555,6 +555,9 @@ static int io_ctl_check_crc(struct btrfs_io_ctl *io_ctl, int index) u32 crc = ~(u32)0; unsigned offset = 0; + if (index >= io_ctl->num_pages) + return -EIO; + if (index == 0) offset = sizeof(u32) * io_ctl->num_pages; -- 2.43.0