archlinuxhardened / selinux

PKGBUILDs to build SELinux enabled packages for Arch Linux
146 stars 25 forks source link

GitHub Actions job fails to build packages because of Docker seccomp filter #82

Closed fishilico closed 3 years ago

fishilico commented 3 years ago

When trying to reproduce an issue (https://github.com/archlinuxhardened/selinux/issues/81) on my fork, I encountered an issue with Docker in https://github.com/fishilico/arch-selinux/actions/runs/545045259 :

Run docker build -t arch-selinux-build .
Sending build context to Docker daemon  1.843MB

Step 1/6 : FROM docker.io/archlinux/archlinux:latest
latest: Pulling from archlinux/archlinux
cc8a014baa70: Pulling fs layer
c32d6397cb52: Pulling fs layer
c32d6397cb52: Verifying Checksum
c32d6397cb52: Download complete
cc8a014baa70: Verifying Checksum
cc8a014baa70: Download complete
cc8a014baa70: Pull complete
c32d6397cb52: Pull complete
Digest: sha256:5effbeff2e75c62639b9420be526fe8d5469412c669048b3a86c37ed0ff21c74
Status: Downloaded newer image for archlinux/archlinux:latest
 ---> 07a1e0448ec2
Step 2/6 : LABEL Description="Build SELinux packages for Arch Linux"
 ---> Running in b0cf9033cd0b
Removing intermediate container b0cf9033cd0b
 ---> afed295a7c20
Step 3/6 : COPY . /startdir
 ---> 09d35795b967
Step 4/6 : RUN     pacman -q --noconfirm -Syu base base-devel expect git &&     pacman --noconfirm -Sc &&     rm -rf /var/cache/pacman/pkg/* &&     ln -sf /usr/share/zoneinfo/UTC /etc/localtime &&     useradd -g users -m builduser &&     echo 'builduser ALL=(ALL) NOPASSWD: /usr/bin/pacman' >> /etc/sudoers &&     echo 'builduser ALL=(ALL) NOPASSWD: /usr/bin/sh -c { pacman --noconfirm --ask=4 -U sudo-selinux/sudo-selinux-*.pkg.tar.zst && if test -e /etc/sudoers.pacsave ; then mv /etc/sudoers.pacsave /etc/sudoers ; fi }' >> /etc/sudoers &&     echo 'MAKEFLAGS="-j$(nproc)"' >> /etc/makepkg.conf &&     echo 'BUILDDIR=/build' >> /etc/makepkg.conf &&     echo 'LOGDEST=/logdest' >> /etc/makepkg.conf &&     mkdir /packages /build /logdest &&     chown -R builduser /startdir /packages /build /logdest &&     sudo -u builduser /startdir/clean.sh &&     sudo -u builduser /startdir/recv_gpg_keys.sh &&     sudo -u builduser /startdir/build_and_install_all.sh &&     rm -rf /startdir/*/src/ /startdir/*/pkg/ &&     pacman --noconfirm -Sc && rm -rf /var/cache/pacman/pkg/*
 ---> Running in 4ad6c76ef5ff
error: failed to initialize alpm library
(could not find or read directory: /var/lib/pacman/)

I reproduced locally this issue, and an strace shows (among other things):

165820 execve("/usr/sbin/pacman", ["pacman", "-Syu"], 0x55b8e4d37470 /* 9 vars */ <unfinished ...>
165820 <... execve resumed>)            = 0
165820 stat("/var/lib/pacman/",  <unfinished ...>
165820 <... stat resumed>{st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
165820 readlink("/var",  <unfinished ...>
165820 <... readlink resumed>0x7ffffcf8e6d0, 1023) = -1 EINVAL (Invalid argument)
165820 readlink("/var/lib", 0x7ffffcf8e6d0, 1023) = -1 EINVAL (Invalid argument)
165820 readlink("/var/lib/pacman", 0x7ffffcf8e6d0, 1023) = -1 EINVAL (Invalid argument)
165820 faccessat2(AT_FDCWD, "/var/lib/pacman/", F_OK, AT_EACCESS) = -1 EPERM (Operation not permitted)
165820 write(2, "failed to initialize alpm library\n(could not find or read directory: /var/lib/pacman/)\n", 87) = 87

These syscalls come from https://git.archlinux.org/pacman.git/tree/lib/libalpm/handle.c?h=v5.2.2#n391 :

        if(stat(path, &st) == -1 || !S_ISDIR(st.st_mode)) {
            return ALPM_ERR_NOT_A_DIR;
        }
        if(!realpath(path, real)) {
            return ALPM_ERR_NOT_A_DIR;
        }
        path = real;

The fact that faccessat2 returns EPERM (in the call to realpath) even though the directory /var/lib/pacman exists, is due to the default SECCOMP filter: adding faccessat2 to the whitelist of system calls is quite "recent" (https://github.com/moby/moby/commit/a18139111d8a203bd211b0861c281ebe77daccd9 in August 2020 for Docker, https://github.com/containers/common/commit/313a3251c223e223944ff73e706339574c99e0d7 in September 2020 for podman & cie.)

Locally, I managed to reproduce the issue with podman 2.2.1-1 (on Arch Linux):

TL;DR: the default SECCOMP filter used by docker build prevents pacman from running because it calls faccessat2 (probably in glibc's implementation of realpath) and this syscall is not (yet) allowed in the default Docker profile used by GitHub Action runners (on Ubuntu 18.04 and Ubuntu 20.04).

How should this issue be fixed? I am open to suggestions :)

tqre commented 3 years ago

Well, we can't set seccomp filters from the command line on the main.yml. One way to go around this is to separate the container from the Dockerfile we have, and use GH Actions container commands as this thread suggests: https://bugzilla.redhat.com/show_bug.cgi?id=1900021

I'll see if I can make this work, but I really wouldn't want to touch the Dockerfile we have...

fishilico commented 3 years ago

Fixed by https://github.com/archlinuxhardened/selinux/pull/84