From nobody Sun Feb 8 15:25:12 2026 Received: from mail-ej1-f48.google.com (mail-ej1-f48.google.com [209.85.218.48]) (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 B348A2874FF for ; Tue, 23 Dec 2025 16:28:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.48 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766507315; cv=none; b=XZDIW6zFbU9+ssoAuh3IlSZXEAo+FMMlFc7cIDtAx+K01oZgnhNWX+M8vE1jl1qWAprN05nXBfzuVdWYgVW/EQzVHo6MmIdx5LEB3w03x6rvRBHzzFUzLMarURlhB7GuUI9x73qBmApBB3NcWewyVEkhozbKi5YhbMjHwcefkMM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766507315; c=relaxed/simple; bh=XjuuqyYryF1zpq80ZhZ1GTFAhaklCy7h5FsWj1gDWsQ=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=OrKRjmoRwraVHhMESTA13G7D6wNubbtt1JP+1DGqRDG0aDAO2BkNN8pc4DPO3RXJ4EBdSQeMGybO6y33m5YzvyGC0p5U+pkOOqH71q27lOIPl3e7tR7ZTvzw06GtsPeAqWTZaS2o3raEjSruSrNVcszzH3ISKicfOa3lwWZn3ys= 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=PGqrcz5p; arc=none smtp.client-ip=209.85.218.48 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="PGqrcz5p" Received: by mail-ej1-f48.google.com with SMTP id a640c23a62f3a-b727f452fffso996227766b.1 for ; Tue, 23 Dec 2025 08:28:33 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1766507312; x=1767112112; 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=R6N7SmWdG7wGTQNVA34AngnepibAQGWrihX4rBYMWoA=; b=PGqrcz5pQuCle6eNWOjKrEUl4B/ByOk12wUzOUeQ6Zj53vaJy33sDh8fuDaotkS+09 JJxO9KhkH/qYNkqyH84BASiPYT+BBBswlMwAHfCbokfXH2ZdtrwXCf6fSne+lY/1+ghr Z3AjC6hFMNFtoYN1HLlmNN77kqyxmQj3lwmZnCRNRvuOCKz2GbtOXE10vhN1J8TChmzJ 8KVM0TY4JrJlmkfz/auC5B/ejNHoYz+VZvUV5hdmyYfyduvbtu7BkaN/UMOHYoSjdz7n sVVQc9A3hvvs72wrftbVtCUG49eaC1zoLhSCTJWVm23JPD4qPuQLT+FaRYZyKwJchR1B 1h7Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1766507312; x=1767112112; 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=R6N7SmWdG7wGTQNVA34AngnepibAQGWrihX4rBYMWoA=; b=MFqqKMtJRYnJASxmkigsfAPiCv8vI9UuRqj2Zgui9kGnpd2aZOexHxp8sV+pNF6Y1f eINniveYpq0QTinv5bqUM3hTvdPsKbwJIHlvNXgetvS87RU+qlrSx/rAOQ3ICfXPF5TM CazkRqUbr+Ck7kPe1L1jW/KJgNsZtulm4T27MRBt7WG+33Sg2Wg5PkRIDk5JPre6z7nL A2PcktW0R0Y4ChddpyDSu8ZkXoyv1BQcbBx8BYe5LiUZRx8/ELcwkvLhkhWaBWWOShgD rd0gyYM2IKRwSa1vsGaTn9B1R/PWaTWeBDquInhW+ddMpjQzeZAR4DxuddQkZgC53Pk+ eLQg== X-Forwarded-Encrypted: i=1; AJvYcCXAYfXRtvgLbdq97c49hB5VPaTsUG81cGh0AiSRkw4LaKbHmaq5Woed5RXif25Fk4USouCPOcRMTYglkxM=@vger.kernel.org X-Gm-Message-State: AOJu0Yyi2Zij8658nCrLJifuVu4jAo2FywL8BLzIIKeOrvdKmhDk+emb ughKfYeb3FwPNOLpewnzzwXIegIctsk1lhvw72upuyz9FJniszZY0BIP X-Gm-Gg: AY/fxX5Z9spAFquXRumM//dS0KziVp+GMJSe94ia2omB+cyXMTPwyDIoVzWnm02dGL5 GiYEnnmIDuoclyfiQR+JwIx/wwhezWh1A+T2LLBrB1+bTW4JStJl4ARuiuyjjc7d7LnpEx9oxPR BNqTqjNurwLMYnJ7286XcmgzZBT+rihiYAZL3YStNoypdcXAsg0AzbiM+nLAg+whSechUcrkLjM Xrr0VJZ1Vzxq+t49NmmOnjJNGEKTvS9bTmlQvAFFMP5ZTYZSDaSqX3EjuKMvguioKfuKYYccLAI kihwZ3BglalixcCt27zPDfLtYXD2S8nZTdbD3va/ccKMWTtW7X2zGGyt65WoIqgKbs3Qf9uavs4 A6u5yR5MQqDrfbdG5rJ+3DIS2H7AThh8D3dlSUVv/nszUABNyys5ybjTOo5n/sYrnkmG0ez8Ji7 Q+cd/bp1TovYVOAQ== X-Google-Smtp-Source: AGHT+IGXEWJV6JYzuU1+X/Q+U2xEJJKDgTfcJHzJ4CQpfIzaEW7hSw06XH8iLmHXg+fDADhKWgoVSg== X-Received: by 2002:a17:906:ef09:b0:b6d:5dbb:a1e1 with SMTP id a640c23a62f3a-b80355b2500mr1847721166b.5.1766507311730; Tue, 23 Dec 2025 08:28:31 -0800 (PST) Received: from prometheus ([85.11.110.37]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-b8037f0cea9sm1417276066b.50.2025.12.23.08.28.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 23 Dec 2025 08:28:31 -0800 (PST) From: Szymon Wilczek To: jaegeuk@kernel.org Cc: chao@kernel.org, linux-f2fs-devel@lists.sourceforge.net, linux-kernel@vger.kernel.org, Szymon Wilczek , syzbot+b4444e3c972a7a124187@syzkaller.appspotmail.com Subject: [PATCH] f2fs: fix use-after-free in f2fs_write_end_io Date: Tue, 23 Dec 2025 17:28:23 +0100 Message-ID: <20251223162823.23606-1-swilczek.lx@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" Syzbot reported a slab-use-after-free issue in f2fs_write_end_io(): [ 86.643336] BUG: KASAN: slab-use-after-free in f2fs_write_end_io+0x9b9/0= xb60 [ 86.644120] Read of size 4 at addr ffff88804357d170 by task kworker/u4:4= /45 ... [ 86.656543] Call Trace: ... [ 86.660351] f2fs_write_end_io+0x9b9/0xb60 ... [ 86.685123] Allocated by task 5484: ... [ 86.688325] f2fs_fill_super+0x8c/0x6ec0 ... [ 86.697685] Freed by task 5484: ... [ 86.702700] kfree+0x1c0/0x660 [ 86.703273] kill_f2fs_super+0x5b6/0x6c0 The problem is a race condition between the shutdown of the filesystem (kill_f2fs_super) and the asynchronous I/O completion handler (f2fs_write_end_io). When unmounting, kill_f2fs_super() frees the sbi structure. However, if there are pending checkpoint data (CP_DATA) writes, the f2fs_write_end_io() callback might still be running. In the original code, f2fs_write_end_io() accesses sbi->cp_wait after decrementing the page count. If the page count drops to zero, f2fs_wait_on_all_pages() in the unmount path returns, allowing kill_f2fs_super() to free sbi. If the callback then tries to wake up waiters on sbi->cp_wait, a UAF occurs. To fix this, I applied a two-step solution: 1. In kill_f2fs_super(), explicitly wait for all CP_DATA pages to obtain a count of zero using f2fs_wait_on_all_pages(). This ensures specific synchronization for these metadata writes. 2. In f2fs_write_end_io(), move the wake_up() call INSIDE the bio_for_each_folio_all() loop. This ensures that the wakeup (which signals completion to the waiter) happens before processing of the bio is effectively 'done' from the perspective of the waiter. More importantly, it removes any access to 'sbi' after the loop, eliminating the UAF window. Reported-by: syzbot+b4444e3c972a7a124187@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=3Db4444e3c972a7a124187 Signed-off-by: Szymon Wilczek --- fs/f2fs/data.c | 11 ++++++++--- fs/f2fs/super.c | 1 + 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index c30e69392a62..5808d73c2598 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -318,10 +318,13 @@ static void f2fs_write_end_io(struct bio *bio) { struct f2fs_sb_info *sbi; struct folio_iter fi; + bool is_close; =20 iostat_update_and_unbind_ctx(bio); sbi =3D bio->bi_private; =20 + is_close =3D is_sbi_flag_set(sbi, SBI_IS_CLOSE); + if (time_to_inject(sbi, FAULT_WRITE_IO)) bio->bi_status =3D BLK_STS_IOERR; =20 @@ -360,10 +363,12 @@ static void f2fs_write_end_io(struct bio *bio) f2fs_del_fsync_node_entry(sbi, folio); folio_clear_f2fs_gcing(folio); folio_end_writeback(folio); - } - if (!get_pages(sbi, F2FS_WB_CP_DATA) && + + if (!is_close && type =3D=3D F2FS_WB_CP_DATA && + !get_pages(sbi, F2FS_WB_CP_DATA) && wq_has_sleeper(&sbi->cp_wait)) - wake_up(&sbi->cp_wait); + wake_up(&sbi->cp_wait); + } =20 bio_put(bio); } diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index c4c225e09dc4..c9ee3fae1958 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -5454,6 +5454,7 @@ static void kill_f2fs_super(struct super_block *sb) kill_block_super(sb); /* Release block devices last, after fscrypt_destroy_keyring(). */ if (sbi) { + f2fs_wait_on_all_pages(sbi, F2FS_WB_CP_DATA); destroy_device_list(sbi); kfree(sbi); sb->s_fs_info =3D NULL; --=20 2.52.0