#1104405 mmdebstrap: readdir() attempted on invalid dirhandle

Package:
mmdebstrap
Source:
mmdebstrap
Submitter:
J.P.Malhado
Date:
2025-09-06 16:23:01 UTC
Severity:
normal
Tags:
#1104405#5
Date:
2025-04-29 15:26:34 UTC
From:
To:
Dear Maintainer,

When running with the following command prompt

mmdebstrap --mode=chrootless --format=directory --arch=hurd-i386 \
  --include=sysvinit-core,sysv-rc,debian-ports-archive-keyring,gnumach-image-1-486
  --customize-hook="passwd --root=\"\$1\" --delete root" \
  --variant=apt unstable /hurd \
  "deb http://deb.debian.org/debian-ports/ unstale main" \
  "deb http://deb.debian.org/debian-ports/ unreleased main"

where /hurd is the mountpoint for a partition with a filesystem
generated with "mk2efs -o hurd" with write permissions to non-root
users, and the command is being run by a normal user account,
I'm getting the following output:

I: skipping emulation check in chrootless mode
I: finding correct signed-by value...
done
readdir() attempted on invalid dirhandle $dh2 at /usr/bin/mmdebstrap line 6889.
readdir() attempted on invalid dirhandle $dh2 at /usr/bin/mmdebstrap line 6890.
readdir() attempted on invalid dirhandle $dh2 at /usr/bin/mmdebstrap line 6893.
closedir() attempted on invalid dirhandle $dh2 at /usr/bin/mmdebstrap line 6897.
I: running apt-get update...
downloading:   0.00 [>

And seems to get stuck.

Thank you for considering this issue,
Joao

#1104405#8
Date:
2025-04-29 21:09:21 UTC
From:
To:
Hi,

I'm putting Debian Hurd maintainers in CC.

Quoting J.P.Malhado (2025-04-29 17:26:34)

you title your bug "readdir() attempted on invalid dirhandle". That problem is
easily "fixed" with the following patch:
--- a/mmdebstrap +++ b/mmdebstrap @@ -6914,7 +6914,9 @@ sub main() { # it, if it's empty if ($entry eq "lost+found" and -d "$options->{root}/$entry") { - opendir(my $dh2, "$options->{root}/$entry"); + opendir(my $dh2, "$options->{root}/$entry") + or error + "Can't opendir($options->{root}/$entry): $!"; # Attempt reading the directory thrice. If the third # time succeeds, then it has more entries than just "." # and ".." and must thus not be empty. The problem is, that you are running mmdebstrap as the normal user and that user does not have the required privileges to look into the lost+found directory to check whether it's really empty. With above patch, mmdebstrap will just fail with an appropriate error message. This will avoid the "readdir() attempted on invalid dirhandle" errors from the subject of this bug. But I guess this is not quite why you opened this bug and your actual problem is that mmdebstrap gets stuck? If yes, please read on. Otherwise, consider the bug as fixed with the next upload of mmdebstrap via above patch. Firstly, please be *very* careful with chrootless mode. You are running maintainer scripts outside the chroot and this mode is barely tested and many packages are not made to work with it at all. So anything can happen including a complete wipe of your $HOME. For that reason and because nothing is checking whether the versions of programs run by maintainer scripts are of the version that your packages inside the chroot expect, it is always a good idea to wrap a chrootless mmdebstrap call in some sort of containerization. This includes running mmdebstrap in chrootless mode as a customize hooks inside mmdebstrap in unshare mode, for example. Secondly, have you tried creating a hurd chroot on linux the "normal" way? That is by creating a filesystem from a tarball? Here is my latest set of runes on the topic: https://salsa.debian.org/helmutg/dpkg-root-demo/-/merge_requests/3/diffs#57c00b22e45b81dde62199ab610d05ce70f829bf_0_17 What do you ultimately want to do? I fear that it takes somebody who understands Hurd to track down your "stalling" problem with apt. Did you try running strace or something to figure out where it stalls? Thanks! cheers, josch
#1104405#13
Date:
2025-04-30 17:13:57 UTC
From:
To:
Hello josch,

Thank you for looking into this.

mmdebstrap might not have been stuck at the download phase, my network was just
irresponsive and I was killing the process as I saw the errors showing up.
However, I am seeing errors further down. With the same prompt, I'm now seeing

I: skipping emulation check in chrootless mode
I: finding correct signed-by values...
done
I: running apt-get update...
done
I: downloading packages with apt...
done
I: extracting archives...
tar: .: Cannot utime: Operation not permitted
tar: .: Cannot change mode to rwxr-xr-x: Operation not permitted
tar: Exiting with failure status due to previous errors
E: tar --extract failed: 512
W: hooklistener errored out: E: received eof on socket

I: main() received signal PIPE: waiting for setup...
E: mmdebstrap failed to run

What I am trying to do is to use mmdebstrap to setup a hurd + linux dual boot
setup, in a similar way to what is achieved with crosshurd
(https://packages.debian.org/sid/crosshurd).

I see what you mean about creating a tarball and copying this over to a new
partition, but since mmdebstrap can use a directory as a target, I thought it
would be possible to shortcut that step.

I hear all the warnings you make about chrootless mode, and that is why I was
running as a normal user instead of root, but you seem to advise even against
that. The problem in running mmdebstrap --mode=chrootless --arch=hurd-i396
inside another mmdebstrap chroot is that the target mountpoint for the hurd
partition would not be accessible.

Do you see a way to install a hurd image to a partition without creating and
copying a tarball explicitly?

Many thanks,
João

#1104405#18
Date:
2025-09-06 16:21:47 UTC
From:
To:
Hi João,

sorry for taking so long to come back to you on this. Life (exam season) got in
the way of things.

Quoting João Pedro Malhado (2025-04-30 19:13:57)

Further down you write that you are running mmdebstrap as the normal user. What
the above error message is telling you is, that your user does not have the
required permissions to change the utime and mode of your /hurd directory which
tar sees as ".".
create files owned by root you need to have the required privileges which your
normal user does not. Going via a tarball "cheats" because of course anybody
can create a tarball containing files owned by 0:0.

It could work if you run it as the superuser but doing so is very dangerous
thanks to how chrootless mode works. This is why I'd recommend splitting your
installation into two steps, each of which has different risks:

First step: create the rootfs. Since this involves running arbitrary maintainer
scripts, this should be contained in a way that avoids messing with the rest of
your system. This requirement directly conflicts with your requirement of "I
want it to perform changes in /hurd" which is why there is:

Second step: now that you have the tarball created, extract it somewhere.
Extracting a tarball is not running arbitrary shell scripts and is thus much
safer to do as the superuser.

Yes. Your normal user still has the required privileges to wipe your $HOME.

You can cheat though because mmdebstrap allows execution of arbitrary code as
part of hooks. You thus could use a hook to mount things in a way which allow
the inner mmdebstrap to perform the changes you need but I have not done that.
If you want to go that route, you are exploring new territory.

If you hate creating temporary files that much there is also the option of
piping the tarball which mmdebstrap can write to stdout into mke2fs:

mmdebstrap [options and hooks] "-" | sudo mke2fs -d - /dev/sdX

Again, unexplored territory. If you have more questions please don't hesitate
to ask.

Thanks!

cheers, josch