diff -Nru zfs-linux-2.2.0/debian/changelog zfs-linux-2.2.0/debian/changelog --- zfs-linux-2.2.0/debian/changelog 2024-01-31 13:12:31.000000000 +0000 +++ zfs-linux-2.2.0/debian/changelog 2024-03-21 11:10:14.000000000 +0000 @@ -1,11 +1,16 @@ -zfs-linux (2.2.0-0ubuntu1~23.10.2) mantic-security; urgency=medium +zfs-linux (2.2.0-0ubuntu1~23.10.3) mantic-security; urgency=medium - * SECURITY UPDATE: data corruption due to an incorrect dirty dnode check - - debian/patches/CVE-2023-49298.patch: dnode_is_dirty: check dnode - and its data for dirtiness - - CVE-2023-49298 + * No change rebuild to fix CVE-2023-49298 in the -security pocket. - -- Nick Galanis Wed, 31 Jan 2024 13:12:31 +0000 + -- Nick Galanis Thu, 21 Mar 2024 11:10:14 +0000 + +zfs-linux (2.2.0-0ubuntu1~23.10.2) mantic; urgency=medium + + * d/p/9b9b09f452a469458451c221debfbab944e7f081.patch Cherry-pick + "dnode_is_dirty: check dnode and its data for dirtiness" fix from + zfs-2.2.2. LP: #2044657 + + -- Dimitri John Ledkov Tue, 30 Jan 2024 15:54:02 +0000 zfs-linux (2.2.0-0ubuntu1~23.10.1) mantic; urgency=medium diff -Nru zfs-linux-2.2.0/debian/patches/9b9b09f452a469458451c221debfbab944e7f081.patch zfs-linux-2.2.0/debian/patches/9b9b09f452a469458451c221debfbab944e7f081.patch --- zfs-linux-2.2.0/debian/patches/9b9b09f452a469458451c221debfbab944e7f081.patch 1970-01-01 00:00:00.000000000 +0000 +++ zfs-linux-2.2.0/debian/patches/9b9b09f452a469458451c221debfbab944e7f081.patch 2024-01-30 15:54:02.000000000 +0000 @@ -0,0 +1,93 @@ +From 9b9b09f452a469458451c221debfbab944e7f081 Mon Sep 17 00:00:00 2001 +From: Rob N +Date: Wed, 29 Nov 2023 04:15:48 +1100 +Subject: [PATCH] dnode_is_dirty: check dnode and its data for dirtiness + +Over its history this the dirty dnode test has been changed between +checking for a dnodes being on `os_dirty_dnodes` (`dn_dirty_link`) and +`dn_dirty_record`. + + de198f2d9 Fix lseek(SEEK_DATA/SEEK_HOLE) mmap consistency + 2531ce372 Revert "Report holes when there are only metadata changes" + ec4f9b8f3 Report holes when there are only metadata changes + 454365bba Fix dirty check in dmu_offset_next() + 66aca2473 SEEK_HOLE should not block on txg_wait_synced() + +Also illumos/illumos-gate@c543ec060d illumos/illumos-gate@2bcf0248e9 + +It turns out both are actually required. + +In the case of appending data to a newly created file, the dnode proper +is dirtied (at least to change the blocksize) and dirty records are +added. Thus, a single logical operation is represented by separate +dirty indicators, and must not be separated. + +The incorrect dirty check becomes a problem when the first block of a +file is being appended to while another process is calling lseek to skip +holes. There is a small window where the dnode part is undirtied while +there are still dirty records. In this case, `lseek(fd, 0, SEEK_DATA)` +would not know that the file is dirty, and would go to +`dnode_next_offset()`. Since the object has no data blocks yet, it +returns `ESRCH`, indicating no data found, which results in `ENXIO` +being returned to `lseek()`'s caller. + +Since coreutils 9.2, `cp` performs sparse copies by default, that is, it +uses `SEEK_DATA` and `SEEK_HOLE` against the source file and attempts to +replicate the holes in the target. When it hits the bug, its initial +search for data fails, and it goes on to call `fallocate()` to create a +hole over the entire destination file. + +This has come up more recently as users upgrade their systems, getting +OpenZFS 2.2 as well as a newer coreutils. However, this problem has been +reproduced against 2.1, as well as on FreeBSD 13 and 14. + +This change simply updates the dirty check to check both types of dirty. +If there's anything dirty at all, we immediately go to the "wait for +sync" stage, It doesn't really matter after that; both changes are on +disk, so the dirty fields should be correct. + +Sponsored-by: Klara, Inc. +Sponsored-by: Wasabi Technology, Inc. +Reviewed-by: Brian Behlendorf +Reviewed-by: Alexander Motin +Reviewed-by: Rich Ercolani +Signed-off-by: Rob Norris +Closes #15571 +Closes #15526 +--- + module/zfs/dnode.c | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +diff --git a/module/zfs/dnode.c b/module/zfs/dnode.c +index 7cf03264dc..ad9988366a 100644 +--- a/module/zfs/dnode.c ++++ b/module/zfs/dnode.c +@@ -1764,7 +1764,14 @@ dnode_try_claim(objset_t *os, uint64_t object, int slots) + } + + /* +- * Checks if the dnode contains any uncommitted dirty records. ++ * Checks if the dnode itself is dirty, or is carrying any uncommitted records. ++ * It is important to check both conditions, as some operations (eg appending ++ * to a file) can dirty both as a single logical unit, but they are not synced ++ * out atomically, so checking one and not the other can result in an object ++ * appearing to be clean mid-way through a commit. ++ * ++ * Do not change this lightly! If you get it wrong, dmu_offset_next() can ++ * detect a hole where there is really data, leading to silent corruption. + */ + boolean_t + dnode_is_dirty(dnode_t *dn) +@@ -1772,7 +1779,8 @@ dnode_is_dirty(dnode_t *dn) + mutex_enter(&dn->dn_mtx); + + for (int i = 0; i < TXG_SIZE; i++) { +- if (multilist_link_active(&dn->dn_dirty_link[i])) { ++ if (multilist_link_active(&dn->dn_dirty_link[i]) || ++ !list_is_empty(&dn->dn_dirty_records[i])) { + mutex_exit(&dn->dn_mtx); + return (B_TRUE); + } +-- +2.34.1 + diff -Nru zfs-linux-2.2.0/debian/patches/CVE-2023-49298.patch zfs-linux-2.2.0/debian/patches/CVE-2023-49298.patch --- zfs-linux-2.2.0/debian/patches/CVE-2023-49298.patch 2024-01-31 13:12:15.000000000 +0000 +++ zfs-linux-2.2.0/debian/patches/CVE-2023-49298.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,90 +0,0 @@ -From 9b9b09f452a469458451c221debfbab944e7f081 Mon Sep 17 00:00:00 2001 -From: Rob N -Date: Wed, 29 Nov 2023 04:15:48 +1100 -Subject: [PATCH] dnode_is_dirty: check dnode and its data for dirtiness - -Over its history this the dirty dnode test has been changed between -checking for a dnodes being on `os_dirty_dnodes` (`dn_dirty_link`) and -`dn_dirty_record`. - - de198f2d9 Fix lseek(SEEK_DATA/SEEK_HOLE) mmap consistency - 2531ce372 Revert "Report holes when there are only metadata changes" - ec4f9b8f3 Report holes when there are only metadata changes - 454365bba Fix dirty check in dmu_offset_next() - 66aca2473 SEEK_HOLE should not block on txg_wait_synced() - -Also illumos/illumos-gate@c543ec060d illumos/illumos-gate@2bcf0248e9 - -It turns out both are actually required. - -In the case of appending data to a newly created file, the dnode proper -is dirtied (at least to change the blocksize) and dirty records are -added. Thus, a single logical operation is represented by separate -dirty indicators, and must not be separated. - -The incorrect dirty check becomes a problem when the first block of a -file is being appended to while another process is calling lseek to skip -holes. There is a small window where the dnode part is undirtied while -there are still dirty records. In this case, `lseek(fd, 0, SEEK_DATA)` -would not know that the file is dirty, and would go to -`dnode_next_offset()`. Since the object has no data blocks yet, it -returns `ESRCH`, indicating no data found, which results in `ENXIO` -being returned to `lseek()`'s caller. - -Since coreutils 9.2, `cp` performs sparse copies by default, that is, it -uses `SEEK_DATA` and `SEEK_HOLE` against the source file and attempts to -replicate the holes in the target. When it hits the bug, its initial -search for data fails, and it goes on to call `fallocate()` to create a -hole over the entire destination file. - -This has come up more recently as users upgrade their systems, getting -OpenZFS 2.2 as well as a newer coreutils. However, this problem has been -reproduced against 2.1, as well as on FreeBSD 13 and 14. - -This change simply updates the dirty check to check both types of dirty. -If there's anything dirty at all, we immediately go to the "wait for -sync" stage, It doesn't really matter after that; both changes are on -disk, so the dirty fields should be correct. - -Sponsored-by: Klara, Inc. -Sponsored-by: Wasabi Technology, Inc. -Reviewed-by: Brian Behlendorf -Reviewed-by: Alexander Motin -Reviewed-by: Rich Ercolani -Signed-off-by: Rob Norris -Closes #15571 -Closes #15526 ---- - module/zfs/dnode.c | 12 ++++++++++-- - 1 file changed, 10 insertions(+), 2 deletions(-) - -Index: zfs-linux-2.2.0/module/zfs/dnode.c -=================================================================== ---- zfs-linux-2.2.0.orig/module/zfs/dnode.c -+++ zfs-linux-2.2.0/module/zfs/dnode.c -@@ -1764,7 +1764,14 @@ dnode_try_claim(objset_t *os, uint64_t o - } - - /* -- * Checks if the dnode contains any uncommitted dirty records. -+ * Checks if the dnode itself is dirty, or is carrying any uncommitted records. -+ * It is important to check both conditions, as some operations (eg appending -+ * to a file) can dirty both as a single logical unit, but they are not synced -+ * out atomically, so checking one and not the other can result in an object -+ * appearing to be clean mid-way through a commit. -+ * -+ * Do not change this lightly! If you get it wrong, dmu_offset_next() can -+ * detect a hole where there is really data, leading to silent corruption. - */ - boolean_t - dnode_is_dirty(dnode_t *dn) -@@ -1772,7 +1779,8 @@ dnode_is_dirty(dnode_t *dn) - mutex_enter(&dn->dn_mtx); - - for (int i = 0; i < TXG_SIZE; i++) { -- if (multilist_link_active(&dn->dn_dirty_link[i])) { -+ if (multilist_link_active(&dn->dn_dirty_link[i]) || -+ !list_is_empty(&dn->dn_dirty_records[i])) { - mutex_exit(&dn->dn_mtx); - return (B_TRUE); - } diff -Nru zfs-linux-2.2.0/debian/patches/series zfs-linux-2.2.0/debian/patches/series --- zfs-linux-2.2.0/debian/patches/series 2024-01-31 13:12:09.000000000 +0000 +++ zfs-linux-2.2.0/debian/patches/series 2024-01-30 15:54:02.000000000 +0000 @@ -28,4 +28,4 @@ fixup-abi.patch 4630-ubsan-Support-varlen-arrays-at-end-of-struct-as-1-or.patch ubuntu/zed-fix-typo-ZED_POWER_OFF_ENCLOUSRE_SLOT_ON_FAULT.patch -CVE-2023-49298.patch +9b9b09f452a469458451c221debfbab944e7f081.patch