SELinux blocks podman container from talking to libvirt

I received this bug report this week.

"I see this when I try to use vagrant from a container using podman on Fedora 29 Beta.

Podman version: 0.8.4

Command to run container:

sudo podman run -it --rm -v /run/libvirt:/run/libvirt:Z -v $(pwd):/root:Z localhost/vagrant vagrant up

Logs:

...

Sep 30 21:17:25 Home audit[22760]: AVC avc:  denied  { connectto } for  pid=22760 comm="batch_action.r*" path="/run/libvirt/libvirt-sock" scontext=system_u:system_r:container_t:s0:c57,c527 tcontext=system_u:system_r:virtd_t:s0-s0:c0.c1023 tclass=unix_stream_socket permissive=0

"

This is an interesting use case of using SELinux and containers.  SELinux is protecting the file system, and the host from attack from inside of the container.  People who have listened to me over the years understand that SELinux is protecting the label of files, in the case of containers, it only allows a container_t to read/write/execute files labeled container_file_t.

But the reporter of the bug, thinks he did the right thing, he told podman to relabel the volumes he was mounting into the container.

Lets look at his command to launch the container.

sudo podman run -it --rm -v /run/libvirt:/run/libvirt:Z -v $(pwd):/root:Z localhost/vagrant vagrant up

He told podman to go out and relabel /run/libvirt and $(pwd)/root with a private label generated for the container, that is what the ":Z" means, system_u:object_r:container_file_t:MCS.  Well sadly this is not the right thing to do and will probably cause him issues going forward.  Since /run/libvirt is probably used by other processes outside of the container, he might have broken them.  libvirt running as virtd_t is not probably not allowed to write to container_file_t.  The $(pwd)/root directory is probably fine, since this is not likely to be shared with other confined daemons.

Ignoring that this was the wrong thing to do, 

SELinux still blocked the container, Why?

SELinux does not only block access to files on disk.  While SElinux would allow container_t to write to a unix domain socket, "/run/libvirt/libvirt-sock", labeled container_file_t, a second SELinux check happens between the processes. SELinux also checks whether the container can talk to the daemon, libvirt,  running as virtd_t.

Since there is no allow rule for container_t to connectto virtd_t, the connection fails.

Currently in situations like this I tell people to just disable SELinux separation inside this container, rather then fooling around with the labels.

sudo podman run -it --security-opt label=disable  --rm -v /run/libvirt:/run/libvirt -v $(pwd):/root localhost/vagrant vagrant up

Notice I removed the :Z. This will cause podman to run the container as spc_t, which is an unconfined domain, and all confined domains are allowed to communicate with it.

Since this is not a full disablement of SELinux, it does not make me cry.  :^)

In the future Lukas Vrabek is working on a better solution, udica, where you could simple create a new type based on container_t, and then run your container with it.

udica should allow you to generate container_vagrant_t which would be allowed to write to /run/libvirts labels and communicate with virtd_t, and still have all other SELinux confinement. Then you could execute something like this:

sudo podman run -it --security-opt label=type:container_vagrant_t --rm -v /run/libvirt:/run/libvirt -v $(pwd):/root localhost/vagrant vagrant up


Error

Anonymous comments are disabled in this journal

default userpic

Your reply will be screened