ABRT docker image experiments - abrt/abrt GitHub Wiki

Would it be possible to create a docker image shipping ABRT tools?

The answer is yes, with privileged containers you can do almost anything but privileged containers are evil (from Jakub Filak's point of view). Why? Because there is no standard around them and it breaks security. Such an image can install anything on the host and if its container disappears the stuff will remain on the host.

Is it possible to create a not privileged container with ABRT tools?

I believe that with some code changes it is. The only problem is that we need to be able to run processes as root, be able to read host's /proc directory and modify SELinux. And we also need a tiny script on the host which will forward core dump files from Kernel to the ABRT container. Core files are created by Kernel which utilizes /proc/sys/kernel/core_pattern to figure out where to lay the core file (or 'sysctl kernel.core_pattern'). Kernel can send the core file through pipe to a process which is started by Kernel itself. The problem is that Kernel starts the process in its namespace. Hence we need to find a way how to tell Kernel to start the process in the correct namespace. One might suggest using a wrapper script with docker but we can use nsenter to accomplish that job instead. The last thing we need to know is the namespace we want to enter. Fortunately we can tell nsenter to join namespaces of any process, so we can ask nsenter to join namespaces of abrtd which must be running in the ABRT container. And here is the final script which I placed to the /usr/local/libexec/abrt-container-coredump file:

#!/bin/sh                                                                        
                                                                                 
ABRT_SAVED_CORE_PATTERN=/usr/local/var/run/abrt/saved_core_pattern               
                                                                                 
function dump                                                                    
{                                                                                
    ABRTD_PID=$(pidof abrtd) || return 1                                         
    ABRTD_EXE=$(readlink /proc/$ABRTD_PID/exe) || return 2                       
    test "/usr/sbin/abrtd" == "$ABRTD_EXE" || return 3                           
                                                                                 
    nsenter -t ${ABRTD_PID} -m -u -i -n -p -C -r -w \                         
        /usr/libexec/abrt-hook-ccpp $1 $2 $3 $4 $5 $6 $7 $8 $9 || return 4       
}                                                                                
                                                                                 
function install                                                                 
{                                                                                
    sysctl kernel.core_pattern > $ABRT_SAVED_CORE_PATTERN || return 1            
    sysctl kernel.core_pattern="|/usr/local/libexec/abrt-container-coredump -dump %s %c %p %u %g %t %P %I" || return 2
    return 0                                                                     
}                                                                                
                                                                                 
function uninstall                                                               
{                                                                                
    if [ -f $ABRT_SAVED_CORE_PATTERN ]; then                                     
        sysctl kernel.core_pattern=$(cat $ABRT_SAVED_CORE_PATTERN)               
        rm $ABRT_SAVED_CORE_PATTERN                                              
    fi                                                                           
}                                                                                
                                                                                 
case $1 in                                                                       
    "-install")                                                                  
        install                                                                  
        ;;                                                                       
    "-uninstall")                                                                
        uninstall                                                                
        ;;                                                                       
    "-dump")                                                                     
        shift                                                                    
        dump $@                                                                  
        ;;                                                                       
        *)                                                                       
        echo "$0: unrecognized argument: $1"                                     
        ;;                                                                       
esac

Update the core_pattern with:

# /usr/local/libexec/abrt-container-coredump -install

The core_pattern is ready to forward core files to the ABRT container, so let's create the container. We can start from the base fedora docker image.

# setenforce 0

Please, bear with us and temporarily turn SELinux into Permissive mode.

# docker pull fedora
# docker run -it -v /dev/log:/dev/log --pid=host fedora /usr/bin/bash

We need to start a privileged container because we need to be able to read data of all processes. ABRT expects those data in the /proc directory, but we can teach ABRT to look into a different directory (e.g. /host/proc), which would allow us to run a non-privileged container as:

# docker run -it -v /:/host -v /run:/run -v /dev/log:/dev/log fedora /usr/bin/bash

This is a proof of concept and things do not need to be perfect. Once we know there is a demand for ABRT in container and people will use it, we can invest a lot more time to make the container secure.

Let's continue with installation of ABRT packages and tweaking the configuration:

# dnf install abrt-cli abrt-cli-ng augeas
# augtool set /files/etc/abrt/plugins/CCpp.conf/CreateCoreBacktrace no

The CreateCoreBacktrace option is used to enable dump-time-bactrace-generation - in other words, ABRT is capable of generating basic backtrace without the need to save core file on disk. This feature requires the ability to close STDIN, which is currently impossible when using nsenter.

Finally, we need to start dbus-daemon and abrtd. We either need to run own dbus-daemon in the container or we can bind mount the run directory from the host to the container. But using the host's dbus deamon requires placing ABRT's dbus configuration to host and we want to avoid this for now.

# mkdir -p /var/run/dbus
# dbus-daemon --system
# abrtd

We are done. The container is ready to collect core files from the host and other containers. You can test it by killing a sleep command in another terminal.

$ sleep 1000 &
$ kill -SEGV %%
$ fg
# docker run -it fedora /usr/bin/bash
# sleep 1000 &
# kills -SEGV %%
# fg

Check the result in the ABRT container:

# abrt list
⚠️ **GitHub.com Fallback** ⚠️