Subject: Re: bug#47106: Bubblewrap hates Guix containers😞

From: Ludovic Courtès <[email-masked]>
Date: Mon, 15 Mar 2021 14:29:17 +0100

Hi,

Leo Prikler <[email-masked]> skribis:

> Okay, so here's my basic workflow: Starting with an empty set of --
> expose:
> bwrap: Can't find source path /sys/block: No such file or directory
> repeated a few times along with warnings, that the web process crashed
> until finally Epiphany itself crashes. 
> I add /sys/block, and Epiphany miraculously doesn't crash, but bwrap
> still complains and the web processes still crash, so we march on. 
> I'll abbreviate it a little and only show the error messages.
> bwrap: Can't find source path /sys/bus: No such file or directory
> bwrap: Can't find source path /sys/class: No such file or directory 
> bwrap: Can't find source path /sys/dev: No such file or directory 
> bwrap: Can't find source path /sys/devices: No such file or directory

OK.  Additional data points from my Guix System laptop:

--8<---------------cut here---------------start------------->8---
$ guix environment -C --ad-hoc findutils -- find /sys |wc -l
37575
$ find /sys | wc -l
find: ‘/sys/kernel/debug’: Mankas permeso
38026
$ guix environment -C --ad-hoc findutils -- find /sys/block |wc -l
27
$ find /sys/block | wc -l
27
--8<---------------cut here---------------end--------------->8---

The offending Bubblewrap code is:

--8<---------------cut here---------------start------------->8---
static void
resolve_symlinks_in_ops (void)
{
  SetupOp *op;

  for (op = ops; op != NULL; op = op->next)
    {
      const char *old_source;

      switch (op->type)
        {
        case SETUP_RO_BIND_MOUNT:
        case SETUP_DEV_BIND_MOUNT:
        case SETUP_BIND_MOUNT:
          old_source = op->source;
          op->source = realpath (old_source, NULL);
          if (op->source == NULL)
            {
              if (op->flags & ALLOW_NOTEXIST && errno == ENOENT)
                op->source = old_source;
              else
                die_with_error("Can't find source path %s", old_source);
            }
          break;
        default:
          break;
        }
    }
}
--8<---------------cut here---------------end--------------->8---

I wonder how ‘realpath’ can fail here.  In fact, it Works For Me:

--8<---------------cut here---------------start------------->8---
$ cat realpath.scm
(use-modules (system foreign))

(define realpath
  (let ((proc (pointer->procedure '* (dynamic-func "realpath" (dynamic-link))
                                  '(* *))))
    (lambda (path)
      (let ((result (proc (string->pointer path) %null-pointer)))
        (and (not (null-pointer? result))
             (pointer->string result))))))

(pk 'realpath-> (realpath "/sys/block"))
$ guix environment -C --ad-hoc guile -- guile -s realpath.scm
;;; note: auto-compilation is enabled, set GUILE_AUTO_COMPILE=0
;;;       or pass the --no-auto-compile argument to disable.
;;; compiling /home/ludo/src/guix-debugging/realpath.scm
;;; compiled /home/ludo/.cache/guile/ccache/3.0-LE-8-4.4/home/ludo/src/guix-debugging/realpath.scm.go

;;; (realpath-> "/sys/block")
--8<---------------cut here---------------end--------------->8---

So I presume bwrap does something else before it reaches that warning.
We should really strace it.

Thanks,
Ludo’.