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 :-)

Reply via email to