GNU bug report logs - #77900
Unprivileged guix-daemon fails to build in Docker/relocatable pack

Previous Next

Package: guix;

Reported by: Ludovic Courtès <ludovic.courtes <at> inria.fr>

Date: Fri, 18 Apr 2025 14:25:11 UTC

Severity: normal

To reply to this bug, email your comments to 77900 AT debbugs.gnu.org.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to bug-guix <at> gnu.org:
bug#77900; Package guix. (Fri, 18 Apr 2025 14:25:15 GMT) Full text and rfc822 format available.

Acknowledgement sent to Ludovic Courtès <ludovic.courtes <at> inria.fr>:
New bug report received and forwarded. Copy sent to bug-guix <at> gnu.org. (Fri, 18 Apr 2025 14:25:15 GMT) Full text and rfc822 format available.

Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Ludovic Courtès <ludovic.courtes <at> inria.fr>
To: bug-guix <at> gnu.org
Subject: Unprivileged guix-daemon fails to build in Docker/relocatable pack
Date: Fri, 18 Apr 2025 16:23:42 +0200
When running guix-daemon unprivileged in Docker (or, similarly, in a
‘guix pack -R’ relocatable pack), it fails to spawn the build process:

--8<---------------cut here---------------start------------->8---
ludo <at> fencepost:~/packs/guix$ GUIX_STATE_DIRECTORY=$HOME/var GUIX_LOG_DIRECTORY=$HOME/var/log ./bin/guix-daemon 
^Z
[1]+  Stopped                 GUIX_STATE_DIRECTORY=$HOME/var GUIX_LOG_DIRECTORY=$HOME/var/log ./bin/guix-daemon
ludo <at> fencepost:~/packs/guix$ bg
[1]+ GUIX_STATE_DIRECTORY=$HOME/var GUIX_LOG_DIRECTORY=$HOME/var/log ./bin/guix-daemon &
ludo <at> fencepost:~/packs/guix$ GUIX_DAEMON_SOCKET=$HOME/var/daemon-socket/socket ./bin/guix build guile-bootstrap  --no-substitutes
accepted connection from pid 19182, user ludo
The following derivation will be built:
  /gnu/store/d9gcqaq0mag354svxsdpkvr8swdqsny8-guile-bootstrap-2.0.drv
guix build: error: cannot create process in unprivileged user namespace: Operation not permitted
--8<---------------cut here---------------end--------------->8---

The clone(2) man page lists two reasons for getting EPERM with
CLONE_NEWUSER:

   EPERM  CLONE_NEWUSER was specified in the flags mask,  but  either  the
          effective  user  ID or the effective group ID of the caller does
          not have a mapping  in  the  parent  namespace  (see  user_name‐
          spaces(7)).

   EPERM (since Linux 3.9)
          CLONE_NEWUSER  was specified in the flags mask and the caller is
          in a chroot environment (i.e., the caller's root directory  does
          not  match the root directory of the mount namespace in which it
          resides).

Ludo’.




Information forwarded to bug-guix <at> gnu.org:
bug#77900; Package guix. (Mon, 07 Jul 2025 19:12:02 GMT) Full text and rfc822 format available.

Message #8 received at 77900 <at> debbugs.gnu.org (full text, mbox):

From: David Elsing <david.elsing <at> posteo.net>
To: Ludovic Courtès <ludovic.courtes <at> inria.fr>
Cc: 77900 <at> debbugs.gnu.org
Subject: Re: Unprivileged guix-daemon fails to build in Docker/relocatable pack
Date: Mon, 07 Jul 2025 19:10:54 +0000
Hello,

Ludovic Courtès <ludovic.courtes <at> inria.fr> writes:

> When running guix-daemon unprivileged in Docker (or, similarly, in a
> ‘guix pack -R’ relocatable pack), it fails to spawn the build process:
> [...]
> The clone(2) man page lists two reasons for getting EPERM with
> CLONE_NEWUSER:

I'm not sure about `guix pack -R', but I think in the default Docker
seccomp profile, the unshare system call [1] requires CAP_SYS_ADMIN,
otherwise EPERM is also return. I just tested the Docker seccomp profile
with podman, and indeed the unshare command fails because the unshare
system call returns EPERM. Maybe you can try with
"--security-opt=seccomp=unconfined"?

Best,
David

[1] https://github.com/moby/moby/blob/master/profiles/seccomp/default.json




Information forwarded to bug-guix <at> gnu.org:
bug#77900; Package guix. (Tue, 08 Jul 2025 16:37:02 GMT) Full text and rfc822 format available.

Message #11 received at 77900 <at> debbugs.gnu.org (full text, mbox):

From: Ludovic Courtès <ludovic.courtes <at> inria.fr>
To: David Elsing <david.elsing <at> posteo.net>
Cc: 77900 <at> debbugs.gnu.org, Reepca Russelstein <reepca <at> russelstein.xyz>
Subject: Re: Unprivileged guix-daemon fails to build in Docker/relocatable pack
Date: Tue, 08 Jul 2025 10:08:50 +0200
Hi David,

Cc: Reepca.

David Elsing <david.elsing <at> posteo.net> writes:

> Ludovic Courtès <ludovic.courtes <at> inria.fr> writes:
>
>> When running guix-daemon unprivileged in Docker (or, similarly, in a
>> ‘guix pack -R’ relocatable pack), it fails to spawn the build process:
>> [...]
>> The clone(2) man page lists two reasons for getting EPERM with
>> CLONE_NEWUSER:
>
> I'm not sure about `guix pack -R', but I think in the default Docker
> seccomp profile, the unshare system call [1] requires CAP_SYS_ADMIN,
> otherwise EPERM is also return. I just tested the Docker seccomp profile
> with podman, and indeed the unshare command fails because the unshare
> system call returns EPERM. Maybe you can try with
> "--security-opt=seccomp=unconfined"?

Oh I see, thanks for chiming in.

I don’t actually use podman and Docker but I think it would be nice if
the unprivileged guix-daemon would work out of the box in these
environments, particularly in CI environments like GitLab-CI where
passing ‘--security-opt=seccomp=unconfined’ is not an option.

We can ‘unshare’ only once, to lock the mounts inside the build
environment.  If that’s the only issue, we could add a command-line
option to disable that or perhaps even detect that we’re in such an
environment and disable it automatically.

WDYT?

Ludo’.




Information forwarded to bug-guix <at> gnu.org:
bug#77900; Package guix. (Tue, 08 Jul 2025 20:16:02 GMT) Full text and rfc822 format available.

Message #14 received at 77900 <at> debbugs.gnu.org (full text, mbox):

From: David Elsing <david.elsing <at> posteo.net>
To: Ludovic Courtès <ludovic.courtes <at> inria.fr>
Cc: 77900 <at> debbugs.gnu.org, Reepca Russelstein <reepca <at> russelstein.xyz>
Subject: Re: Unprivileged guix-daemon fails to build in Docker/relocatable pack
Date: Tue, 08 Jul 2025 20:15:20 +0000
Hello,

Ludovic Courtès <ludovic.courtes <at> inria.fr> writes:

> I don’t actually use podman and Docker but I think it would be nice if
> the unprivileged guix-daemon would work out of the box in these
> environments, particularly in CI environments like GitLab-CI where
> passing ‘--security-opt=seccomp=unconfined’ is not an option.

Is it not working using `--disable-chroot'? I don't think the isolated
build environment is possible when `unshare' is not allowed and the UID
is not 0 (except by using something like PRoot), right?

> We can ‘unshare’ only once, to lock the mounts inside the build
> environment.  If that’s the only issue, we could add a command-line
> option to disable that or perhaps even detect that we’re in such an
> environment and disable it automatically.

Ah no, user namespaces can be nested (with a maximum depth of 32), or
maybe I'm misunderstanding what you mean? It is just a bit slow to bind
mount all directories (and files) in "/" in order to add (or replace)
the store, so I added an environment variable inside the chroot in [1].

Cheers,
David

[1] https://codeberg.org/guix/guix/issues/1054




Information forwarded to bug-guix <at> gnu.org:
bug#77900; Package guix. (Fri, 11 Jul 2025 07:36:01 GMT) Full text and rfc822 format available.

Message #17 received at 77900 <at> debbugs.gnu.org (full text, mbox):

From: Ludovic Courtès <ludovic.courtes <at> inria.fr>
To: David Elsing <david.elsing <at> posteo.net>
Cc: 77900 <at> debbugs.gnu.org, Reepca Russelstein <reepca <at> russelstein.xyz>
Subject: Re: Unprivileged guix-daemon fails to build in Docker/relocatable pack
Date: Fri, 11 Jul 2025 09:34:47 +0200
Hi,

David Elsing <david.elsing <at> posteo.net> writes:

> Ludovic Courtès <ludovic.courtes <at> inria.fr> writes:
>
>> I don’t actually use podman and Docker but I think it would be nice if
>> the unprivileged guix-daemon would work out of the box in these
>> environments, particularly in CI environments like GitLab-CI where
>> passing ‘--security-opt=seccomp=unconfined’ is not an option.
>
> Is it not working using `--disable-chroot'?

It is:

  https://blog.josefsson.org/2024/12/18/guix-container-images-for-gitlab-ci-cd/

But it’s unsatisfactory: I would hope the unprivileged daemon would
allow us to address that shortcoming.

> I don't think the isolated build environment is possible when
> `unshare' is not allowed and the UID is not 0 (except by using
> something like PRoot), right?

What I meant is that there’s only one ‘unshare’ call, which is necessary
from a security viewpoint but not from a functional viewpoint.  Offering
an option to skip it in contexts where the tradeoff is acceptable could
help maybe?

Thanks,
Ludo’.




Information forwarded to bug-guix <at> gnu.org:
bug#77900; Package guix. (Fri, 11 Jul 2025 14:13:01 GMT) Full text and rfc822 format available.

Message #20 received at 77900 <at> debbugs.gnu.org (full text, mbox):

From: David Elsing <david.elsing <at> posteo.net>
To: Ludovic Courtès <ludovic.courtes <at> inria.fr>
Cc: 77900 <at> debbugs.gnu.org, Reepca Russelstein <reepca <at> russelstein.xyz>
Subject: Re: Unprivileged guix-daemon fails to build in Docker/relocatable pack
Date: Fri, 11 Jul 2025 14:12:39 +0000
Hi,

Ludovic Courtès <ludovic.courtes <at> inria.fr> writes:

> But it’s unsatisfactory: I would hope the unprivileged daemon would
> allow us to address that shortcoming.

Yes it does, as long as the needed syscalls are not restricted. I'm not
sure when this will change with Docker [1].

>> I don't think the isolated build environment is possible when
>> `unshare' is not allowed and the UID is not 0 (except by using
>> something like PRoot), right?
>
> What I meant is that there’s only one ‘unshare’ call, which is necessary
> from a security viewpoint but not from a functional viewpoint.  Offering
> an option to skip it in contexts where the tradeoff is acceptable could
> help maybe?

Ah sorry, I was conflating `unshare` and `clone`. The default Docker
seccomp profile [2] of course also blocks (among other flags)
CLONE_NEWUSER (0x10000000) for the `clone` syscall without
CAP_SYS_ADMIN, using SCMP_CMP_MASKED_EQ. This also leads to EPERM being
returned.

Best,
David

[1] https://github.com/moby/moby/issues/42441
[2] https://github.com/moby/moby/blob/master/profiles/seccomp/default.json




Information forwarded to bug-guix <at> gnu.org:
bug#77900; Package guix. (Tue, 15 Jul 2025 09:46:01 GMT) Full text and rfc822 format available.

Message #23 received at 77900 <at> debbugs.gnu.org (full text, mbox):

From: Ludovic Courtès <ludovic.courtes <at> inria.fr>
To: David Elsing <david.elsing <at> posteo.net>
Cc: 77900 <at> debbugs.gnu.org, Reepca Russelstein <reepca <at> russelstein.xyz>
Subject: Re: Unprivileged guix-daemon fails to build in Docker/relocatable pack
Date: Tue, 15 Jul 2025 11:36:42 +0200
Hi,

David Elsing <david.elsing <at> posteo.net> writes:

> Ludovic Courtès <ludovic.courtes <at> inria.fr> writes:
>
>> But it’s unsatisfactory: I would hope the unprivileged daemon would
>> allow us to address that shortcoming.
>
> Yes it does, as long as the needed syscalls are not restricted. I'm not
> sure when this will change with Docker [1].
>
>>> I don't think the isolated build environment is possible when
>>> `unshare' is not allowed and the UID is not 0 (except by using
>>> something like PRoot), right?
>>
>> What I meant is that there’s only one ‘unshare’ call, which is necessary
>> from a security viewpoint but not from a functional viewpoint.  Offering
>> an option to skip it in contexts where the tradeoff is acceptable could
>> help maybe?
>
> Ah sorry, I was conflating `unshare` and `clone`. The default Docker
> seccomp profile [2] of course also blocks (among other flags)
> CLONE_NEWUSER (0x10000000) for the `clone` syscall without
> CAP_SYS_ADMIN, using SCMP_CMP_MASKED_EQ. This also leads to EPERM being
> returned.

Oh OK.

> [1] https://github.com/moby/moby/issues/42441
> [2] https://github.com/moby/moby/blob/master/profiles/seccomp/default.json

So hmm, it looks like in practice we’re left with no choice but to keep
using ‘--disable-chroot’ in Docker?

Do you happen to know what people running Docker-in-Docker (or similar)
do?

Thanks,
Ludo’.




Information forwarded to bug-guix <at> gnu.org:
bug#77900; Package guix. (Thu, 17 Jul 2025 17:10:02 GMT) Full text and rfc822 format available.

Message #26 received at 77900 <at> debbugs.gnu.org (full text, mbox):

From: David Elsing <david.elsing <at> posteo.net>
To: Ludovic Courtès <ludovic.courtes <at> inria.fr>
Cc: 77900 <at> debbugs.gnu.org, Reepca Russelstein <reepca <at> russelstein.xyz>
Subject: Re: Unprivileged guix-daemon fails to build in Docker/relocatable pack
Date: Thu, 17 Jul 2025 17:09:02 +0000
Hi,

Ludovic Courtès <ludovic.courtes <at> inria.fr> writes:

> So hmm, it looks like in practice we’re left with no choice but to keep
> using ‘--disable-chroot’ in Docker?

Without unprivileged user namespaces being allowed, the situation hasn't
changed I think.

> Do you happen to know what people running Docker-in-Docker (or similar)
> do?

No, but I found this [1] and this [2], so using `--privileged` (or at
least allowing unprivileged user namespaces) seems to be necessary.

Cheers,
David

[1] https://docs.docker.com/engine/security/rootless/#rootless-docker-in-docker
[2] https://github.com/moby/moby/issues/22139




This bug report was last modified today.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.