[CRIU] [PATCH 1/4] join-ns: add join-ns option to criu CLI and RPC

Pavel Emelyanov xemul at virtuozzo.com
Mon Apr 4 04:19:41 PDT 2016


> @@ -473,6 +479,10 @@ static int setup_opts_from_req(int sk, CriuOpts *req)
>  		}
>  	}
> 
> +	/* check namespace flags here */

This comment is useless.

> +	if (check_namespace_opts())
> +		goto err;
> +
>  	return 0;
> 
>  err:
> diff --git a/criu/crtools.c b/criu/crtools.c
> index 537bcc9..5e9085a 100644
> --- a/criu/crtools.c
> +++ b/criu/crtools.c

> @@ -19,6 +21,24 @@ struct ns_desc {
>  	size_t		len;
>  };
> 
> +struct user_ns_extra {
> +	char	*uid;
> +	char	*gid;
> +};
> +
> +/* struct join_ns is used for storing parameters specified by --join-ns */
> +struct join_ns {
> +	struct list_head 	list;
> +	char			*ns_file;
> +	struct ns_desc		*nd; 	/* namespace descriptor */
> +	int			ns_fd;
> +	/* extra options of --join-ns, like uid&gid in user namespace */
> +	union {
> +		struct user_ns_extra	user_extra;
> +		char			*common_extra;
> +	}extra_opts;

Space is needed after }.

> +};
> +
>  enum ns_type {
>  	NS_UNKNOWN = 0,
>  	NS_CRIU,
> @@ -70,6 +90,7 @@ extern bool check_ns_proc(struct fd_link *link);
>  extern struct ns_desc pid_ns_desc;
>  extern struct ns_desc user_ns_desc;
>  extern unsigned long root_ns_mask;
> +extern unsigned int join_ns_flags;
> 
>  extern const struct fdtype_ops nsfile_dump_ops;
>  extern struct collect_image_info nsfile_cinfo;
> @@ -100,6 +121,8 @@ extern gid_t userns_gid(gid_t gid);
> 
>  extern int dump_user_ns(pid_t pid, int ns_id);
>  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();
> 
>  typedef int (*uns_call_t)(void *arg, int fd, pid_t pid);
>  /*
> diff --git a/criu/namespaces.c b/criu/namespaces.c
> index 724203e..6994cf0 100644
> --- a/criu/namespaces.c
> +++ b/criu/namespaces.c
> @@ -10,7 +10,11 @@
>  #include <signal.h>
>  #include <sched.h>
>  #include <sys/capability.h>
> +#include <sys/stat.h>
> +#include <limits.h>
> +#include <errno.h>
> 
> +#include "cr_options.h"
>  #include "util.h"
>  #include "imgset.h"
>  #include "uts_ns.h"
> @@ -35,6 +39,146 @@ static struct ns_desc *ns_desc_array[] = {
>  	&cgroup_ns_desc,
>  };
> 
> +unsigned int join_ns_flags = 0;

This variable is only read in patch #3, but the patch itself looks
unneeded (see comment to it), so the whole join_ns_flags becomes
unneeded too.

> +
> +int check_namespace_opts() {

{ should go on separate line. We used Linux kernel coding style, you can
check your patches to fit one with linux/scripts/checkpatch.pl

> +	errno = 22;
> +	if (join_ns_flags & opts.rst_namespaces_flags) {
> +		pr_perror("Conflict flags: -join-ns and -namespace");
> +		return -1;
> +	}
> +	if (join_ns_flags & opts.empty_ns) {
> +		pr_perror("Conflict flags: -join-ns and -empty-ns");
> +		return -1;
> +	}
> +	if (opts.empty_ns & opts.rst_namespaces_flags) {
> +		pr_perror("Conflict flags: -empty-ns and -namespace");
> +		return -1;
> +	}
> +	errno = 0;
> +	return 0;
> +}
> +
> +static int check_int_str(char *str) {

Same here -- { on separate line.

> +	if (str == NULL)
> +		return 0;
> +
> +	if (*str == '\0') {
> +		str = NULL;
> +		return 0;
> +	}
> +
> +	char *endptr;
> +	long val;

Variable declaration should be done before any code.

> +	errno = 22;
> +	val = strtol(str, &endptr, 10);
> +	if ((errno == ERANGE) || (endptr == str)
> +			|| (*endptr != '\0')
> +			|| (val < 0) || (val > 65535)) {
> +		str = NULL;
> +		return -1;
> +	}
> +
> +	errno = 0;
> +	return 0;
> +}
> +
> +static int check_ns_file(char *ns_file) {

{ on separate line

> +	int pid, ret, proc_dir;
> +
> +	if (!check_int_str(ns_file)) {
> +		pid = atoi(ns_file);
> +		if (pid <= 0) {
> +			pr_perror("Invalid join_ns pid %s", ns_file);
> +			return -1;
> +		}
> +		proc_dir = open_pid_proc(pid);
> +		if (proc_dir < 0) {
> +			pr_perror("Invalid join_ns pid: /proc/%s not found", ns_file);
> +			return -1;
> +		}
> +		return 0;
> +	}
> +
> +	ret = access(ns_file, 0);
> +	if (ret < 0) {
> +		pr_perror("Can't access join-ns file: %s", ns_file);
> +		return -1;
> +	}
> +	return 0;
> +}
> +
> +static int set_user_extra_opts(struct join_ns *jn, char *extra_opts) {

{ on separate line

> +	char *uid, *gid, *aux;
> +	if (extra_opts == NULL) {
> +		jn->extra_opts.user_extra.uid = NULL;
> +		jn->extra_opts.user_extra.gid = NULL;
> +		return 0;
> +	}
> +
> +	uid = extra_opts;
> +	aux = strchr(extra_opts, ',');
> +	if (aux == NULL) {
> +		gid = NULL;
> +	} else {
> +		*aux = '\0';
> +		gid = aux + 1;
> +	}
> +
> +	if (check_int_str(uid) || check_int_str(gid)) {
> +		return -1;
> +	}
> +	jn->extra_opts.user_extra.uid = uid;
> +	jn->extra_opts.user_extra.gid = gid;
> +
> +	return 0;
> +}
> +
> +int join_ns_add(const char *type, char *ns_file, char *extra_opts) {

{ on separate line

> +	struct join_ns *jn;
> +
> +	jn = xmalloc(sizeof(*jn));
> +	if (!jn) {
> +		return -1;
> +	}
> +
> +	if (check_ns_file(ns_file)) {
> +		return -1;
> +	}
> +
> +	jn->ns_file = ns_file;
> +	if (!strncmp(type, "net", 4)) {
> +		jn->nd = &net_ns_desc;
> +		join_ns_flags |= CLONE_NEWNET;
> +	} else if (!strncmp(type, "uts", 4)) {
> +		jn->nd = &uts_ns_desc;
> +		join_ns_flags |= CLONE_NEWUTS;
> +	} else if (!strncmp(type, "ipc", 4)) {
> +		jn->nd = &ipc_ns_desc;
> +		join_ns_flags |= CLONE_NEWIPC;
> +	} else if (!strncmp(type, "pid", 4)) {
> +		jn->nd = &pid_ns_desc;
> +		join_ns_flags |= CLONE_NEWPID;

Here we should abort with error, you wrote that joining pidns doesn't work.

> +	} else if (!strncmp(type, "user", 5)) {
> +		jn->nd = &user_ns_desc;
> +		if (set_user_extra_opts(jn, extra_opts)) {
> +			pr_perror("invalid user namespace extra_opts %s\n", extra_opts);
> +			return -1;
> +		}
> +		join_ns_flags |= CLONE_NEWUSER;
> +	} else if (!strncmp(type, "mnt", 4)) {
> +		jn->nd = &mnt_ns_desc;
> +		join_ns_flags |= CLONE_NEWNS;
> +	} else {
> +		pr_perror("invalid namespace type %s\n", type);
> +		return -1;
> +	}
> +
> +	list_add_tail(&jn->list, &opts.join_ns);
> +	pr_info("Added %s:%s join namespace\n", type, ns_file);
> +	return 0;
> +}
> +
>  static unsigned int parse_ns_link(char *link, size_t len, struct ns_desc *d)
>  {
>  	unsigned long kid = 0;
> diff --git a/images/rpc.proto b/images/rpc.proto
> index fac4b9f..9ece4da 100644
> --- a/images/rpc.proto
> +++ b/images/rpc.proto
> @@ -15,6 +15,12 @@ message ext_mount_map {
>  	required string		val	= 2;
>  };
> 
> +message join_namespace {
> +	required string		ns		= 1;
> +	required string		ns_file		= 2;
> +	optional string		extra_opt	= 3;
> +}
> +
>  message inherit_fd {
>  	required string		key	= 1;
>  	required int32		fd	= 2;
> @@ -90,6 +96,7 @@ message criu_opts {
>  	repeated string			irmap_scan_paths = 36;
>  	repeated string			external	= 37;
>  	optional uint32			empty_ns	= 38;
> +	repeated join_namespace		join_ns		= 39;
>  }
> 
>  message criu_dump_resp {
> 



More information about the CRIU mailing list