Applied, thanks!
Milos Nikic, le lun. 05 oct. 2026 15:34:26 -0700, a ecrit:
> Before a truncate, force_delayed_copies maps the file and writes every
> page past the new size, so that delayed copies of the data are made
> before it is discarded. When the write fault on such a page fails, for
> instance because an earlier pager_unlock_page for it found no free
> block, libpager answers the fault with memory_object_data_error and the
> kernel raises a memory exception in ext2fs itself. diskfs_catch_exception
> only covers faults on the disk image, so the exception kills the
> translator. Filling the filesystem and truncating a file whose writes
> failed is enough to crash it, with or without a journal.
>
> Poke each page with hurd_safe_copyin and hurd_safe_copyout, which catch
> the fault, and skip a page that faults. The page lies past the new size
> and is discarded anyway. A delayed copy of such a page is then not
> forced, so a holder of that copy can see it as zeros; the page could not
> be written in the first place.
>
> To reproduce:
> - fill an ext2 filesystem until writes fail with ENOSPC,
> then truncate one of the files whose writes failed;
> the ext2fs translator dies with SIGBUS in poke_pages,
> with or without a journal.
>
> With this fix fsck remains clean in such a case with or
> without a journal.
> ---
> ext2fs/truncate.c | 13 ++++++++++++-
> 1 file changed, 12 insertions(+), 1 deletion(-)
>
> diff --git a/ext2fs/truncate.c b/ext2fs/truncate.c
> index 16f852fdb..837fd02c3 100644
> --- a/ext2fs/truncate.c
> +++ b/ext2fs/truncate.c
> @@ -18,6 +18,7 @@
> along with this program; if not, write to the Free Software
> Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
>
> +#include <hurd/sigpreempt.h>
> #include "ext2fs.h"
>
> #ifdef DONT_CACHE_MEMORY_OBJECTS
> @@ -227,7 +228,17 @@ poke_pages (memory_object_t obj, vm_offset_t start,
> vm_offset_t end)
> {
> vm_address_t poke;
> for (poke = addr; poke < addr + len; poke += vm_page_size)
> - *(volatile int *)poke = *(volatile int *)poke;
> + {
> + int word;
> +
> + /* A page whose write fault fails, for instance because
> + pager_unlock_page found no free block, raises a memory
> + exception here, and diskfs_catch_exception only covers the
> + disk image. Every poked page lies past the new size and is
> + discarded, so skip it rather than crash. */
> + if (hurd_safe_copyin (&word, (void *) poke, sizeof word) == 0)
> + hurd_safe_copyout ((void *) poke, &word, sizeof word);
> + }
> munmap ((caddr_t) addr, len);
> }
>
> --
> 2.56.0
>
--
Samuel
<L> pour moi le seul qui est autorisé à fasciser, c moi :-)