Skip to content
Permalink
Browse files

restore: support restoring threads with SELinux

Restoring a multi-threaded process with CRIU's SELinux support fails
because SELinux does not always support changing the process context of
a multi-threaded process.

Reading the man-page for setcon(), to change the context of a running
process, it states that changing the SELinux context of a multi-threaded
process can only work 'if the new security context is bounded by the old
security context'.

To be able to restore a process without the need to have 'the new
security context [] bounded by the old security context', this sets the
SELinux process context before creating the threads. Thus all threads
are created with the process context of the main process.

Signed-off-by: Adrian Reber <areber@redhat.com>
  • Loading branch information...
adrianreber authored and avagin committed Mar 26, 2019
1 parent 1cb8f71 commit e86c2e93e9b6a464af89edbd83c86e79348bd56e
Showing with 33 additions and 5 deletions.
  1. +7 −0 criu/cr-restore.c
  2. +1 −0 criu/include/restorer.h
  3. +25 −5 criu/pie/restorer.c
@@ -3533,6 +3533,13 @@ static int sigreturn_restore(pid_t pid, struct task_restore_args *task_args, uns

task_args->auto_dedup = opts.auto_dedup;

/*
* In the restorer we need to know if it is SELinux or not. For SELinux
* we must change the process context before creating threads. For
* Apparmor we can change each thread after they have been created.
*/
task_args->lsm_type = kdat.lsm;

/*
* Make root and cwd restore _that_ late not to break any
* attempts to open files by paths above (e.g. /proc).
@@ -216,6 +216,7 @@ struct task_restore_args {
#ifdef ARCH_HAS_LONG_PAGES
unsigned page_size;
#endif
int lsm_type;
} __aligned(64);

/*
@@ -43,6 +43,7 @@

#include "images/creds.pb-c.h"
#include "images/mm.pb-c.h"
#include "images/inventory.pb-c.h"

#include "shmem.h"
#include "restorer.h"
@@ -179,7 +180,8 @@ static int lsm_set_label(char *label, int procfd)
return 0;
}

static int restore_creds(struct thread_creds_args *args, int procfd)
static int restore_creds(struct thread_creds_args *args, int procfd,
int lsm_type)
{
CredsEntry *ce = &args->creds;
int b, i, ret;
@@ -296,8 +298,16 @@ static int restore_creds(struct thread_creds_args *args, int procfd)
return -1;
}

if (lsm_set_label(args->lsm_profile, procfd) < 0)
return -1;
if (lsm_type != LSMTYPE__SELINUX) {
/*
* SELinux does not support setting the process context for
* threaded processes. So this is skipped if running with
* SELinux and instead the process context is set before the
* threads are created.
*/
if (lsm_set_label(args->lsm_profile, procfd) < 0)
return -1;
}
return 0;
}

@@ -576,7 +586,8 @@ long __export_restore_thread(struct thread_restore_args *args)
if (restore_seccomp(args))
BUG();

ret = restore_creds(args->creds_args, args->ta->proc_fd);
ret = restore_creds(args->creds_args, args->ta->proc_fd,
args->ta->lsm_type);
ret = ret || restore_dumpable_flag(&args->ta->mm);
ret = ret || restore_pdeath_sig(args);
if (ret)
@@ -1556,6 +1567,14 @@ long __export_restore_task(struct task_restore_args *args)
if (ret)
goto core_restore_end;

/* SELinux (1) process context needs to be set before creating threads. */
if (args->lsm_type == LSMTYPE__SELINUX) {
/* Only for SELinux */
if (lsm_set_label(args->t->creds_args->lsm_profile,
args->proc_fd) < 0)
goto core_restore_end;
}

/*
* We need to prepare a valid sigframe here, so
* after sigreturn the kernel will pick up the
@@ -1713,7 +1732,8 @@ long __export_restore_task(struct task_restore_args *args)
* turning off TCP repair is CAP_SYS_NED_ADMIN protected,
* thus restore* creds _after_ all of the above.
*/
ret = restore_creds(args->t->creds_args, args->proc_fd);
ret = restore_creds(args->t->creds_args, args->proc_fd,
args->lsm_type);
ret = ret || restore_dumpable_flag(&args->mm);
ret = ret || restore_pdeath_sig(args->t);

0 comments on commit e86c2e9

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