From nobody Fri Dec 19 16:26:29 2025 Received: from mail-pf1-f173.google.com (mail-pf1-f173.google.com [209.85.210.173]) (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 9ED8827D77D for ; Fri, 5 Dec 2025 05:59:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.173 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764914365; cv=none; b=BjajoTmC8Z1NRZnv38IVjcrVizfMhvGg1RK0EbSOUtztCXr/BzWuk9S2KQ4ThV4fpBDrQEL7LyEd59Ppvte66gY7b3c/3CzsQzHh015HHSKud9MEXA8VNLn6nxJ+SEoxqQYiZymr3D0z8Wx2bW8PFi63i6bPW7eDN9jm+b9pCgM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764914365; c=relaxed/simple; bh=v3qKnkp64bhmNVNTkIDedzgiGCfEjfMUA4wc3TYHZAY=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=eSBpCTQjbisD/V+reXiB9DquPFAJ7zbYYx4K5or03aZ94kSfdjz3O2K9S/qT9Cu6g1sVUB4JM12p3VatcpxbKdaFpWAxt0kLxmnh5nN0P8VnQ09Ly8wzq/00WzIHVEy0+OIbTx6jqy6A4qqzG1J40ZDSfFFDof/F3hFertfJtPg= 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=VGGdRQpf; arc=none smtp.client-ip=209.85.210.173 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="VGGdRQpf" Received: by mail-pf1-f173.google.com with SMTP id d2e1a72fcca58-7b8bbf16b71so1992898b3a.2 for ; Thu, 04 Dec 2025 21:59:23 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1764914363; x=1765519163; 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=VFAk5wktF2UPyOn0DQ7lF1B8QLbujwtGCDKJwa1qmTI=; b=VGGdRQpfoWMtELD8rWabJmyrua0ogyJYd/NiHnZLxC9d53SGtOrpiS8NrN8uhno0JZ 3VMR4Dj/2VI8tgREBXcfN4rkfXH1bx4sMDqB6DzLBw7BG+WamM6PsljMawWw3xyxgGCG AFfqNNKr56+tSAxB5Dy15wZqjCvmTgOzGzhcGx2bSuYKg79NB/B5A2Eh/iRa2iRuFATW Z0igJCYRjFcK0L2LuN2a7mGCopC/uTVjG9UP8tKeTW+zJ1x18UF5EHI95dGHyznzZwMw faZ/6rhgIfpa5Gc0HHpm1oyrtm73rqgzsip2n8VfYTm3eekgIEZpXD/4lYug4xAZPHIB EaMg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764914363; x=1765519163; 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=VFAk5wktF2UPyOn0DQ7lF1B8QLbujwtGCDKJwa1qmTI=; b=SzBdmmi0V6eEb+bawMtLgw0mBffQTTaucGNqvzWwvctJdpOr6q1BJ5miKUIv+ho6gw bH9hlFuG1f8ZmaynPDdDhiVWAAFjy3d4SolL7aG+ZOuxQS7z+JBEvwQSfYrxxgS98L6h oSTDeyFpkjohABex3XXKPm429ClWMphZf2Xmb+DmiPSOQMU5LhH6w+2KLJ/9bCuIjSou o+7OvR/hg1O8Uj5ysFe+3n/IxfVaJFeyfBmrv4pNTq4/aYXEOfSjH5Tvm+hP5bgtdSPt i+eyaOjHA5PeBJh5ZvVi5stQKv/lq6MLqiB5pbUJ1xnuNA1VZnW53y3JVhRFHKldeZRQ uh3g== X-Forwarded-Encrypted: i=1; AJvYcCXFmDPVzs/OE/AXfR0sRTp5ar9J2IeDiX4DRAsls6RDydP26Ci1BLAeHpoR1lkBgr1oXjEl4OizckxPloE=@vger.kernel.org X-Gm-Message-State: AOJu0Yy5r35QCbKlVBrqmRcVafF1OUUQG6bWWlhBBtUr+r5wOLQowQ8N m/KEePlg35dR4CkztCQmylwYE56WjONKXt8D7lta+jE1U4gTw50/jzNRuItRlJYQ X-Gm-Gg: ASbGncuHcqIHzqYp9FE6/oB/hBGZ3nsZiQBU/+AkfD/liwQOwbqH30TFUc/8zQG+E1P FYb9NAYmrp1Y5zS10NNixLk6JAgVXdJtwj3Ute3Ffd1UMJkc+23Dj0aWQMz/VoBW4a4BL2xfnGy 4L9s41I5OAXlM6VQjc+FH1icK1vViHFoEYKXDv1jDcIcjNoIPgvOaT28M797/NY2m1rDB07Z7tm vsR1gOLwTqAESCcHhQB3XEb8uG/+pm1yRnT12dTiOd8t4tezohkpmzaT2Rr+SN9R+N0e4fGht+l aDI1ei3akfxZovN9VAad8aPmmb1YVoaUVZG40YJBCStLfyT7FPpQbw6E4uH4bi1VHcop6XEjKqw MLi+ui4s8BXegEfHPgopBhnv2b5g5cl8ooUNs2lmE/ADloWlIQ5CccaYScBMJRPMQVYtSlrgR+X B9sVzs/NZHdUip+yDEX+BTMxajJdM9/DOHb5yYZzlfcK3vuA1a4rKqGrkGGnZzyjj0/kCBSZW6U D6H X-Google-Smtp-Source: AGHT+IErHmTOgxQdfHXp41sLKOKxSJ4zHAhFZyhwuy4ysXGwWzRghuqw0arHP6wu7kMlAl94HE0eaA== X-Received: by 2002:a05:6a20:6a1a:b0:35d:d477:a7ff with SMTP id adf61e73a8af0-363f5d3eacemr10179646637.21.1764914362786; Thu, 04 Dec 2025 21:59:22 -0800 (PST) Received: from deepanshu-kernel-hacker.. ([2405:201:682f:389d:7d03:7bff:42c:9a84]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-bf6a2364693sm3469759a12.26.2025.12.04.21.59.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 04 Dec 2025 21:59:22 -0800 (PST) From: Deepanshu Kartikey To: tytso@mit.edu, adilger.kernel@dilger.ca, willy@infradead.org Cc: linux-ext4@vger.kernel.org, linux-kernel@vger.kernel.org, yi.zhang@huaweicloud.com, djwong@kernel.org, Deepanshu Kartikey , syzbot+b0a0670332b6b3230a0a@syzkaller.appspotmail.com Subject: [PATCH v3] ext4: unmap invalidated folios from page tables in mpage_release_unused_pages() Date: Fri, 5 Dec 2025 11:29:14 +0530 Message-ID: <20251205055914.1393799-1-kartikey406@gmail.com> 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: quoted-printable Content-Type: text/plain; charset="utf-8" When delayed block allocation fails (e.g., due to filesystem corruption detected in ext4_map_blocks()), the writeback error handler calls mpage_release_unused_pages(invalidate=3Dtrue) which invalidates affected folios by clearing their uptodate flag via folio_clear_uptodate(). However, these folios may still be mapped in process page tables. If a subsequent operation (such as ftruncate calling ext4_block_truncate_page) triggers a write fault, the existing page table entry allows access to the now-invalidated folio. This leads to ext4_page_mkwrite() being called with a non-uptodate folio, which then gets marked dirty, triggering: WARNING: CPU: 0 PID: 5 at mm/page-writeback.c:2960 __folio_mark_dirty+0x578/0x880 Call Trace: fault_dirty_shared_page+0x16e/0x2d0 do_wp_page+0x38b/0xd20 handle_pte_fault+0x1da/0x450 The sequence leading to this warning is: 1. Process writes to mmap'd file, folio becomes uptodate and dirty 2. Writeback begins, but delayed allocation fails due to corruption 3. mpage_release_unused_pages(invalidate=3Dtrue) is called: - block_invalidate_folio() clears dirty flag - folio_clear_uptodate() clears uptodate flag - But folio remains mapped in page tables 4. Later, ftruncate triggers ext4_block_truncate_page() 5. This causes a write fault on the still-mapped folio 6. ext4_page_mkwrite() is called with folio that is !uptodate 7. block_page_mkwrite() marks buffers dirty 8. fault_dirty_shared_page() tries to mark folio dirty 9. block_dirty_folio() calls __folio_mark_dirty(warn=3D1) 10. WARNING triggers: WARN_ON_ONCE(warn && !uptodate && !dirty) Fix this by unmapping folios from page tables before invalidating them using unmap_mapping_pages(). This ensures that subsequent accesses trigger new page faults rather than reusing invalidated folios through stale page table entries. Note that this results in data loss for any writes to the mmap'd region that couldn't be written back, but this is expected behavior when writeback fails due to filesystem corruption. The existing error message already states "This should not happen!! Data will be lost". Changes in v3: - Complete redesign based on feedback from Matthew Wilcox and Ted Ts'o - Moved fix from ext4_page_mkwrite() to mpage_release_unused_pages() - Now unmaps folios from page tables before invalidation using unmap_mapping_pages() - Prevents non-uptodate folios from being accessible via stale PTEs - No performance impact (only affects error path with invalidate=3Dtrue) - Removed folio_lock() overhead from page fault path Changes in v2: - Corrected explanation of when folios become non-uptodate - Added detailed description of mpage_release_unused_pages() invocation - Clarified that folio_clear_uptodate() is explicitly called during error handling, not a side effect Reported-by: syzbot+b0a0670332b6b3230a0a@syzkaller.appspotmail.com Tested-by: syzbot+b0a0670332b6b3230a0a@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=3Db0a0670332b6b3230a0a Suggested-by: Matthew Wilcox Signed-off-by: Deepanshu Kartikey --- fs/ext4/inode.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index e99306a8f47c..16f73c0c33c4 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -1749,8 +1749,17 @@ static void mpage_release_unused_pages(struct mpage_= da_data *mpd, BUG_ON(!folio_test_locked(folio)); BUG_ON(folio_test_writeback(folio)); if (invalidate) { - if (folio_mapped(folio)) + if (folio_mapped(folio)) { folio_clear_dirty_for_io(folio); + /* + * Unmap folio from page tables to prevent subsequent + * accesses through stale PTEs. This ensures future + * accesses trigger new page faults rather than reusing + * the invalidated folio. + */ + unmap_mapping_pages(folio->mapping, folio->index, + folio_nr_pages(folio), false); + } block_invalidate_folio(folio, 0, folio_size(folio)); folio_clear_uptodate(folio); --=20 2.43.0