Skip to content

Commit

Permalink
restore: support restoring threads with SELinux
Browse files Browse the repository at this point in the history
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 29, 2019
1 parent 1cb8f71 commit e86c2e9
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 5 deletions.
7 changes: 7 additions & 0 deletions criu/cr-restore.c
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Expand Down
1 change: 1 addition & 0 deletions criu/include/restorer.h
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ struct task_restore_args {
#ifdef ARCH_HAS_LONG_PAGES
unsigned page_size;
#endif
int lsm_type;
} __aligned(64);

/*
Expand Down
30 changes: 25 additions & 5 deletions criu/pie/restorer.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);

Expand Down

0 comments on commit e86c2e9

Please sign in to comment.