[CRIU] [PATCH v5 09/31] ns: Implement target_userns_{u, g}id() and root_userns_{u, g}id()
Kirill Tkhai
ktkhai at virtuozzo.com
Thu Feb 23 07:13:50 PST 2017
Add primitives for converting xids from NS_ROOT to custom
NS_OTHER, and vice versa.
v4: Fixed erratum in root_userns_gid()
Signed-off-by: Kirill Tkhai <ktkhai at virtuozzo.com>
---
criu/include/namespaces.h | 7 ++++++
criu/namespaces.c | 53 ++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 59 insertions(+), 1 deletion(-)
diff --git a/criu/include/namespaces.h b/criu/include/namespaces.h
index 86a7a15b8..0a8002ea6 100644
--- a/criu/include/namespaces.h
+++ b/criu/include/namespaces.h
@@ -121,6 +121,7 @@ struct ns_id {
};
};
extern struct ns_id *ns_ids;
+extern struct ns_id *root_user_ns;
#define NS_DESC_ENTRY(_cflag, _str) \
{ \
@@ -164,6 +165,12 @@ extern int stop_usernsd(void);
extern uid_t userns_uid(uid_t uid);
extern gid_t userns_gid(gid_t gid);
+extern unsigned int target_userns_uid(struct ns_id *ns, unsigned int uid);
+extern unsigned int target_userns_gid(struct ns_id *ns, unsigned int gid);
+
+extern unsigned int root_userns_uid(struct ns_id *ns, unsigned int uid);
+extern unsigned int root_userns_gid(struct ns_id *ns, unsigned int gid);
+
extern void free_userns_maps(void);
extern int join_ns_add(const char *type, char *ns_file, char *extra_opts);
extern int check_namespace_opts(void);
diff --git a/criu/namespaces.c b/criu/namespaces.c
index 06d132ae4..c136ae49f 100644
--- a/criu/namespaces.c
+++ b/criu/namespaces.c
@@ -753,6 +753,7 @@ static int set_ns_hookups(struct ns_id *ns)
return ret;
}
+struct ns_id *root_user_ns = NULL;
/* Mapping NS_ROOT to NS_CRIU */
static UsernsEntry *userns_entry;
@@ -815,6 +816,54 @@ gid_t userns_gid(gid_t gid)
return child_userns_xid(gid, e->gid_map, e->n_gid_map);
}
+/* Convert uid from NS_ROOT down to its representation in NS_OTHER */
+unsigned int target_userns_uid(struct ns_id *ns, unsigned int uid)
+{
+ if (!(root_ns_mask & CLONE_NEWUSER))
+ return uid;
+ if (ns == root_user_ns)
+ return uid;
+ /* User ns max nesting level is only 32 */
+ uid = target_userns_uid(ns->parent, uid);
+ return child_userns_xid(uid, ns->user.e->uid_map, ns->user.e->n_uid_map);
+}
+
+/* Convert gid from NS_ROOT down to its representation in NS_OTHER */
+unsigned int target_userns_gid(struct ns_id *ns, unsigned int gid)
+{
+ if (!(root_ns_mask & CLONE_NEWUSER))
+ return gid;
+ if (ns == root_user_ns)
+ return gid;
+ /* User ns max nesting level is only 32 */
+ gid = target_userns_gid(ns->parent, gid);
+ return child_userns_xid(gid, ns->user.e->gid_map, ns->user.e->n_gid_map);
+}
+
+/* Convert uid from NS_OTHER ns up to its representation in NS_ROOT */
+unsigned int root_userns_uid(struct ns_id *ns, unsigned int uid)
+{
+ if (!(root_ns_mask & CLONE_NEWUSER))
+ return uid;
+ while (ns != root_user_ns) {
+ uid = parent_userns_uid(ns->user.e, uid);
+ ns = ns->parent;
+ }
+ return uid;
+}
+
+/* Convert gid from NS_OTHER ns up to its representation in NS_ROOT */
+unsigned int root_userns_gid(struct ns_id *ns, unsigned int gid)
+{
+ if (!(root_ns_mask & CLONE_NEWUSER))
+ return gid;
+ while (ns != root_user_ns) {
+ gid = parent_userns_gid(ns->user.e, gid);
+ ns = ns->parent;
+ }
+ return gid;
+}
+
static int parse_id_map(pid_t pid, char *name, UidGidExtent ***pb_exts)
{
UidGidExtent *extents = NULL;
@@ -890,8 +939,10 @@ int collect_user_ns(struct ns_id *ns, void *oarg)
return -1;
userns_entry__init(e);
ns->user.e = e;
- if (ns->type == NS_ROOT)
+ if (ns->type == NS_ROOT) {
userns_entry = e;
+ root_user_ns = ns;
+ }
/*
* User namespace is dumped before files to get uid and gid
* mappings, which are used for convirting local id-s to
More information about the CRIU
mailing list