From nobody Tue Dec 2 01:51:41 2025 Received: from mail-il1-f199.google.com (mail-il1-f199.google.com [209.85.166.199]) (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 11F0984A35 for ; Fri, 21 Nov 2025 01:34:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.166.199 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763688894; cv=none; b=NlqtivlJCegYmq6NqFCzi63arqJyJw+Ta/8yuqntHUEXSAIHGQrWNKw/eE/Rn37fSwJMAlbDx5VwYzW2iaEl5auZiMio4tQeROctc26FPJWwe+5XBta8a+AWyhf8W5kIPf+5e3QIG/O/fYttb+i1EgvpUlyjy/QHqUAx0733y+g= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763688894; c=relaxed/simple; bh=FURU9hYQnzxUENj+OvhgutaOtIK/yeSfER2yF8gDyi0=; h=MIME-Version:Date:In-Reply-To:Message-ID:Subject:From:To: Content-Type; b=Lqqu8aKMI3IZWW1ms4xLOgiwCruq1SWh1lYlky219NFKGirHOh3i0iClTiYhLIHANF8mj/QkRwsdG45XexICQHb3OVWqo5XV2QLLWG6OCQrfjs74PTOCSUj6k8DAqxg/JMhAzXHvd3o4BZypzo6m/g7ErcpEcMrVCGisAecJw6E= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=syzkaller.appspotmail.com; spf=pass smtp.mailfrom=M3KW2WVRGUFZ5GODRSRYTGD7.apphosting.bounces.google.com; arc=none smtp.client-ip=209.85.166.199 Authentication-Results: smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=syzkaller.appspotmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=M3KW2WVRGUFZ5GODRSRYTGD7.apphosting.bounces.google.com Received: by mail-il1-f199.google.com with SMTP id e9e14a558f8ab-4337e3aca0cso17643095ab.1 for ; Thu, 20 Nov 2025 17:34:52 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1763688892; x=1764293692; h=to:from:subject:message-id:in-reply-to:date:mime-version :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=iQQOoliVjwhZehq1XTEc1n2tQFZOLAWNqG/dSMlX/Uk=; b=kkJ6TTzz/RXf9Oi1DWiJGITRXZF4LqDQEz7dE0drlK6DhRVkXmJV2SXUe2Li0BAeQB Tzay0JkyQ3yR6IMWC47kkzhJHTl2zMWqujlUB1kyHCyhiYLjzgTzKKXGA9dGkbrxhe12 b0qiwkuU7wJT5JD94tnYjYszzab5qxtlnyxfkhTyefZCNmierrmbWRhNvQjJPmoD+BnW 6RQsPxhngQx5oVjmiaACl2zoqgUue7dMgQ8PI5juTc5KBMxynGfMfNBLMN3Dfs0qTMsW x5NE1JlIRV+leYD15fk9dhbK5MUfOt+23My71WqRiy72NiDCmsu35fp4Rq4g0uqTvvu8 dUKw== X-Gm-Message-State: AOJu0YwJqNDJjR4Ha0O1RtVaJE2q3FdAL3sbpihwWTeP5UXieKcz5Jrq 9A9WMysG+Rf/K+UnGZm/DPFyOq3rJr0lf9N3JGb/nXKqbazfLkplVVnYG2jwIVsKMqyG19n5Tkx S79xQ9n86fu4LonPKkOOa7v+awQrQETmxpD4ygcrMwWNxRexHAsDuDOVMjvU= X-Google-Smtp-Source: AGHT+IErfRjs0KnryNyUcroHru1NsTUxhZj2bTNiH+P/eD10Q8H4J4NnmUeIRDymYQgMzdPGpmlZUyO4qJ7x+KDUUVHE2PuCV1TJ Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Received: by 2002:a05:6e02:1805:b0:433:29c3:c512 with SMTP id e9e14a558f8ab-435b8e68ed2mr6387015ab.21.1763688892200; Thu, 20 Nov 2025 17:34:52 -0800 (PST) Date: Thu, 20 Nov 2025 17:34:52 -0800 In-Reply-To: <691f44bb.a70a0220.2ea503.0032.GAE@google.com> X-Google-Appengine-App-Id: s~syzkaller X-Google-Appengine-App-Id-Alias: syzkaller Message-ID: <691fc1bc.a70a0220.2ea503.003f.GAE@google.com> Subject: Forwarded: [PATCH] ext4: check folio uptodate state in ext4_page_mkwrite() From: syzbot To: linux-kernel@vger.kernel.org, syzkaller-bugs@googlegroups.com Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" For archival purposes, forwarding an incoming command email to linux-kernel@vger.kernel.org, syzkaller-bugs@googlegroups.com. *** Subject: [PATCH] ext4: check folio uptodate state in ext4_page_mkwrite() Author: kartikey406@gmail.com #syz test: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git= master When a write fault occurs on a memory-mapped ext4 file, ext4_page_mkwrite() is called to prepare the folio for writing. However, if the folio could not be read successfully due to filesystem corruption or I/O errors, it will not be marked uptodate. Attempting to write to a non-uptodate folio is problematic because: 1. We don't have valid data from the backing store to preserve 2. A subsequent writeback could write uninitialized data to disk 3. It triggers a warning in __folio_mark_dirty(): WARN_ON_ONCE(warn && !folio_test_uptodate(folio)) This issue can be reproduced by: 1. Creating a corrupted ext4 filesystem with invalid extent entries 2. Memory-mapping a file on that filesystem 3. Attempting to write to the mapped region The sequence of events is: - User reads/writes to mmap region -> page fault - ext4_filemap_fault() -> ext4_map_blocks() detects corruption - Returns error, folio allocated but NOT marked uptodate - User writes to same region -> ext4_page_mkwrite() called - No uptodate check -> folio marked dirty -> WARNING Fix this by checking folio_test_uptodate() after locking the folio in ext4_page_mkwrite(). If the folio is not uptodate, unlock it and return VM_FAULT_SIGBUS to signal the error to userspace. This is consistent with how we handle other error conditions like truncated folios. Reported-by: syzbot+b0a0670332b6b3230a0a@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=3Db0a0670332b6b3230a0a Signed-off-by: Deepanshu Kartikey --- fs/buffer.c | 5 +++-- fs/ext4/inode.c | 11 ++++++++++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/fs/buffer.c b/fs/buffer.c index 6a8752f7bbed..805cc0a2ecab 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -2621,7 +2621,8 @@ int block_page_mkwrite(struct vm_area_struct *vma, st= ruct vm_fault *vmf, unsigned long end; loff_t size; int ret; - + pr_info("BUFFER_DEBUG: block_page_mkwrite called for inode %lu, folio ind= ex %lu, uptodate=3D%d\n", + inode->i_ino, folio->index, folio_test_uptodate(folio)); folio_lock(folio); size =3D i_size_read(inode); if ((folio->mapping !=3D inode->i_mapping) || @@ -2630,7 +2631,7 @@ int block_page_mkwrite(struct vm_area_struct *vma, st= ruct vm_fault *vmf, ret =3D -EFAULT; goto out_unlock; } - + pr_info("BUFFER_DEBUG: Folio checks passed, calling __block_write_begin\n= "); end =3D folio_size(folio); /* folio is wholly or partially inside EOF */ if (folio_pos(folio) + end > size) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index e99306a8f47c..535da8fa9233 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -6675,7 +6675,8 @@ vm_fault_t ext4_page_mkwrite(struct vm_fault *vmf) struct address_space *mapping =3D inode->i_mapping; get_block_t *get_block =3D ext4_get_block; int retries =3D 0; - + pr_info("EXT4_DEBUG: ext4_page_mkwrite called for inode %lu, folio index = %lu, uptodate=3D%d\n", + inode->i_ino, folio->index, folio_test_uptodate(folio)); if (unlikely(IS_IMMUTABLE(inode))) return VM_FAULT_SIGBUS; =20 @@ -6700,19 +6701,27 @@ vm_fault_t ext4_page_mkwrite(struct vm_fault *vmf) /* Delalloc case is easy... */ if (test_opt(inode->i_sb, DELALLOC) && !ext4_nonda_switch(inode->i_sb)) { + pr_info("EXT4_DEBUG: Taking delalloc path, calling block_page_mkwrite\n"= ); do { err =3D block_page_mkwrite(vma, vmf, ext4_da_get_block_prep); + pr_info("EXT4_DEBUG: block_page_mkwrite returned err=3D%d\n", err); } while (err =3D=3D -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries)); goto out_ret; } =20 folio_lock(folio); + if (!folio_test_uptodate(folio)) { + folio_unlock(folio); + ret =3D VM_FAULT_SIGBUS; + goto out; + } size =3D i_size_read(inode); /* Page got truncated from under us? */ if (folio->mapping !=3D mapping || folio_pos(folio) > size) { folio_unlock(folio); + pr_info("EXT4_DEBUG: Folio truncated, returning VM_FAULT_NOPAGE\n"); ret =3D VM_FAULT_NOPAGE; goto out; } --=20 2.43.0