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