[CRIU] [PATCH v4 30/31] ns: Convert task cred's xids to target user ns
Kirill Tkhai
ktkhai at virtuozzo.com
Wed Feb 22 03:34:58 PST 2017
xids are saved according to NS_ROOT, while in pie
we may set them in their target user_ns. So, let's
convert them. Look at the commentary in the code,
while we save them in NS_ROOT.
Also, small cleanup: use creds instead of args->creds
for caps.
v4: Use target_userns_gid() to convert gids.
Signed-off-by: Kirill Tkhai <ktkhai at virtuozzo.com>
---
criu/cr-restore.c | 48 +++++++++++++++++++++++++++++++++++++++++-------
criu/pie/restorer.c | 41 +++++++++++++++++++++++++----------------
2 files changed, 66 insertions(+), 23 deletions(-)
diff --git a/criu/cr-restore.c b/criu/cr-restore.c
index 8665c8c37..586a8770b 100644
--- a/criu/cr-restore.c
+++ b/criu/cr-restore.c
@@ -2765,6 +2765,9 @@ rst_prep_creds_args(CredsEntry *ce, unsigned long *prev_pos)
{
unsigned long this_pos;
struct thread_creds_args *args;
+ struct ns_id *ns = NULL;
+ CredsEntry *creds;
+ int i;
if (!verify_cap_size(ce)) {
pr_err("Caps size mismatch %d %d %d %d\n",
@@ -2773,6 +2776,16 @@ rst_prep_creds_args(CredsEntry *ce, unsigned long *prev_pos)
return ERR_PTR(-EINVAL);
}
+ if (current->ids->has_user_ns_id) {
+ ns = lookup_ns_by_id(current->ids->user_ns_id, &user_ns_desc);
+ if (!ns) {
+ pr_err("Can't find user_ns\n");
+ return ERR_PTR(-ENOENT);
+ }
+ if (ns->type == NS_ROOT)
+ ns = NULL;
+ }
+
this_pos = rst_mem_align_cpos(RM_PRIVATE);
args = rst_mem_alloc(sizeof(*args), RM_PRIVATE);
@@ -2780,7 +2793,8 @@ rst_prep_creds_args(CredsEntry *ce, unsigned long *prev_pos)
return ERR_PTR(-ENOMEM);
args->cap_last_cap = kdat.last_cap;
- memcpy(&args->creds, ce, sizeof(args->creds));
+ creds = &args->creds;
+ memcpy(creds, ce, sizeof(*creds));
if (ce->lsm_profile || opts.lsm_supplied) {
char *rendered = NULL, *profile;
@@ -2821,12 +2835,12 @@ rst_prep_creds_args(CredsEntry *ce, unsigned long *prev_pos)
/*
* Zap fields which we can't use.
*/
- args->creds.cap_inh = NULL;
- args->creds.cap_eff = NULL;
- args->creds.cap_prm = NULL;
- args->creds.cap_bnd = NULL;
- args->creds.groups = NULL;
- args->creds.lsm_profile = NULL;
+ creds->cap_inh = NULL;
+ creds->cap_eff = NULL;
+ creds->cap_prm = NULL;
+ creds->cap_bnd = NULL;
+ creds->groups = NULL;
+ creds->lsm_profile = NULL;
memcpy(args->cap_inh, ce->cap_inh, sizeof(args->cap_inh));
memcpy(args->cap_eff, ce->cap_eff, sizeof(args->cap_eff));
@@ -2847,6 +2861,26 @@ rst_prep_creds_args(CredsEntry *ce, unsigned long *prev_pos)
args->groups = NULL;
args->mem_groups_pos = 0;
}
+ if (ns) {
+ /*
+ * Note, that some of xids may not have mapping
+ * in target user namespace. This is the reason
+ * why we dump xids from NS_ROOT. Ideally, it's
+ * need to restore a xid in the lowest user_ns,
+ * where it's mapped, but it's not implemented
+ * for now.
+ */
+ creds->uid = target_userns_uid(ns, creds->uid);
+ creds->gid = target_userns_gid(ns, creds->gid);
+ creds->euid = target_userns_uid(ns, creds->euid);
+ creds->egid = target_userns_gid(ns, creds->egid);
+ creds->suid = target_userns_uid(ns, creds->suid);
+ creds->sgid = target_userns_gid(ns, creds->sgid);
+ creds->fsuid = target_userns_uid(ns, creds->fsuid);
+ creds->fsgid = target_userns_gid(ns, creds->fsgid);
+ for (i = 0; i < ce->n_groups; i++)
+ args->groups[i] = target_userns_gid(ns, args->groups[i]);
+ }
args->mem_pos_next = 0;
diff --git a/criu/pie/restorer.c b/criu/pie/restorer.c
index 2da95cf28..1df5e2000 100644
--- a/criu/pie/restorer.c
+++ b/criu/pie/restorer.c
@@ -45,6 +45,7 @@
#include "shmem.h"
#include "restorer.h"
+#include "namespaces.h"
#ifndef PR_SET_PDEATHSIG
#define PR_SET_PDEATHSIG 1
@@ -195,28 +196,36 @@ static int restore_creds(struct thread_creds_args *args, int procfd)
* to override the setresXid settings.
*/
- ret = sys_setresuid(ce->uid, ce->euid, ce->suid);
- if (ret) {
- pr_err("Unable to set real, effective and saved user ID: %d\n", ret);
- return -1;
+ if (ce->uid != NS_INVALID_XID || ce->euid != NS_INVALID_XID || ce->suid != NS_INVALID_XID) {
+ ret = sys_setresuid(ce->uid, ce->euid, ce->suid);
+ if (ret) {
+ pr_err("Unable to set real, effective and saved user ID: %d\n", ret);
+ return -1;
+ }
}
- sys_setfsuid(ce->fsuid);
- if (sys_setfsuid(-1) != ce->fsuid) {
- pr_err("Unable to set fsuid\n");
- return -1;
+ if (ce->fsuid != NS_INVALID_XID) {
+ sys_setfsuid(ce->fsuid);
+ if (sys_setfsuid(-1) != ce->fsuid) {
+ pr_err("Unable to set fsuid\n");
+ return -1;
+ }
}
- ret = sys_setresgid(ce->gid, ce->egid, ce->sgid);
- if (ret) {
- pr_err("Unable to set real, effective and saved group ID: %d\n", ret);
- return -1;
+ if (ce->gid != NS_INVALID_XID || ce->egid != NS_INVALID_XID || ce->sgid != NS_INVALID_XID) {
+ ret = sys_setresgid(ce->gid, ce->egid, ce->sgid);
+ if (ret) {
+ pr_err("Unable to set real, effective and saved group ID: %d\n", ret);
+ return -1;
+ }
}
- sys_setfsgid(ce->fsgid);
- if (sys_setfsgid(-1) != ce->fsgid) {
- pr_err("Unable to set fsgid\n");
- return -1;
+ if (ce->fsgid != NS_INVALID_XID) {
+ sys_setfsgid(ce->fsgid);
+ if (sys_setfsgid(-1) != ce->fsgid) {
+ pr_err("Unable to set fsgid\n");
+ return -1;
+ }
}
/*
More information about the CRIU
mailing list