Skip to content
Permalink
Browse files

net: add correct SELinux label to parasite socket

If running on a system with SELinux enabled the socket for the
communication between parasite daemon and the main CRIU process needs to
be correctly labeled.

Initially this was motivated by Podman's use case: The container is
usually running as something like '...:...:container_t:...:....' and
CRIU started from runc and Podman will run as
'...:...:container_runtime_t:...:...'. As the parasite will be running
with the same context as the container process: 'container_t'.

Allowing a container process to connect via socket to the outside
of the container ('container_runtime_t') is not desired and therefore
CRIU needs to label the socket with the context of the
container: 'container_t'.

So this first gets the context of the root container process and tells
SELinux to label the next created socket with the same label as the root
container process. For this to work it is necessary to have the correct
SELinux policies installed. For Fedora based systems this is part of the
container-selinux package.

This assumes that all processes CRIU wants to dump are labeled with the
same SELinux context. If some of the child processes have different
labels this will not work and needs additional SELinux policies. But the
whole SELinux socket labeling relies on the correct SELinux being
available.

Signed-off-by: Adrian Reber <areber@redhat.com>
  • Loading branch information...
adrianreber authored and avagin committed Mar 12, 2019
1 parent 796da06 commit 8eb430904b717454da34aaa63970da55b9e8c6b0
Showing with 70 additions and 0 deletions.
  1. +70 −0 criu/net.c
@@ -17,6 +17,10 @@
#include <libnl3/netlink/msg.h>
#include <libnl3/netlink/netlink.h>

#ifdef CONFIG_HAS_SELINUX
#include <selinux/selinux.h>
#endif

#include "../soccr/soccr.h"

#include "imgset.h"
@@ -40,6 +44,7 @@

#include "protobuf.h"
#include "images/netdev.pb-c.h"
#include "images/inventory.pb-c.h"

#ifndef IFLA_LINK_NETNSID
#define IFLA_LINK_NETNSID 37
@@ -2745,13 +2750,78 @@ static int prep_ns_sockets(struct ns_id *ns, bool for_dump)
} else
ns->net.nlsk = -1;

#ifdef CONFIG_HAS_SELINUX
/*
* If running on a system with SELinux enabled the socket for the
* communication between parasite daemon and the main
* CRIU process needs to be correctly labeled.
* Initially this was motivated by Podman's use case: The container
* is usually running as something like '...:...:container_t:...:....'
* and CRIU started from runc and Podman will run as
* '...:...:container_runtime_t:...:...'. As the parasite will be
* running with the same context as the container process: 'container_t'.
* Allowing a container process to connect via socket to the outside
* of the container ('container_runtime_t') is not desired and
* therefore CRIU needs to label the socket with the context of
* the container: 'container_t'.
* So this first gets the context of the root container process
* and tells SELinux to label the next created socket with
* the same label as the root container process.
* For this to work it is necessary to have the correct SELinux
* policies installed. For Fedora based systems this is part
* of the container-selinux package.
*/
security_context_t ctx;

/*
* This assumes that all processes CRIU wants to dump are labeled
* with the same SELinux context. If some of the child processes
* have different labels this will not work and needs additional
* SELinux policies. But the whole SELinux socket labeling relies
* on the correct SELinux being available.
*/
if (kdat.lsm == LSMTYPE__SELINUX) {
ret = getpidcon_raw(root_item->pid->real, &ctx);
if (ret < 0) {
pr_perror("Getting SELinux context for PID %d failed",
root_item->pid->real);
goto err_sq;
}

ret = setsockcreatecon(ctx);
freecon(ctx);
if (ret < 0) {
pr_perror("Setting SELinux socket context for PID %d failed",
root_item->pid->real);
goto err_sq;
}
}
#endif

ret = ns->net.seqsk = socket(PF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK, 0);
if (ret < 0) {
pr_perror("Can't create seqsk for parasite");
goto err_sq;
}

ret = 0;

#ifdef CONFIG_HAS_SELINUX
/*
* Once the socket has been created, reset the SELinux socket labelling
* back to the default value of this process.
*/
if (kdat.lsm == LSMTYPE__SELINUX) {
ret = setsockcreatecon_raw(NULL);
if (ret < 0) {
pr_perror("Resetting SELinux socket context to "
"default for PID %d failed",
root_item->pid->real);
goto err_ret;
}
}
#endif

out:
if (nsret >= 0 && restore_ns(nsret, &net_ns_desc) < 0) {
nsret = -1;

0 comments on commit 8eb4309

Please sign in to comment.
You can’t perform that action at this time.