[CRIU] [PATCH v2] criu: Add --keep-on-exec option
Cyrill Gorcunov
gorcunov at gmail.com
Tue Jun 4 10:41:21 MSK 2019
When we run action scripts we communicate with third-party
tools via file descriptors inherited from a criu execution
caller.
Since commit 6c8ea60491305482eb60d9b17a8635ab9248a5ab this
no longer possible, moreover it breaks API.
Thus lets provide --keep-on-exec option where we could
tell explicitly which exactly fds should be kept opened.
v2:
- provide qsort_cmp_int_array to avoid code duplication
Signed-off-by: Cyrill Gorcunov <gorcunov at gmail.com>
---
Documentation/criu.txt | 7 +++++++
criu/config.c | 23 +++++++++++++++++++++++
criu/include/cr_options.h | 2 ++
criu/include/util.h | 2 ++
criu/util.c | 23 +++++++++++++++++++++++
5 files changed, 57 insertions(+)
diff --git a/Documentation/criu.txt b/Documentation/criu.txt
index 6111c3baf0e1..5ffdd7cb1b28 100644
--- a/Documentation/criu.txt
+++ b/Documentation/criu.txt
@@ -138,6 +138,13 @@ Common options are applicable to any 'command'.
notification message contains a file descriptor for
the master pty
+*--keep-on-exec* 'fd'::
+ Keep 'fd' file descriptor when executing service programs and scripts
+ during certain stages. When *criu* is executed it inherits opened file
+ descriptors or a caller (if they are present). Sometimes it is needed
+ to pass such descriptors to the *--action-script* scripts, otherwise
+ they get closed for security reason.
+
*-V*, *--version*::
Print program version and exit.
diff --git a/criu/config.c b/criu/config.c
index 24f0b33858ad..a53f0c0ab6ce 100644
--- a/criu/config.c
+++ b/criu/config.c
@@ -416,6 +416,22 @@ static int parse_join_ns(const char *ptr)
return 0;
}
+static int parse_keep_on_exec(char *optarg)
+{
+ size_t size = sizeof(opts.keep_on_exec[0]) * (opts.nr_keep_on_exec + 1);
+ int fd = atoi(optarg);
+
+ if (xrealloc_safe(&opts.keep_on_exec, size))
+ return -ENOMEM;
+
+ opts.keep_on_exec[opts.nr_keep_on_exec++] = fd;
+ qsort(opts.keep_on_exec, opts.nr_keep_on_exec,
+ sizeof(opts.keep_on_exec[0]),
+ qsort_cmp_int_array);
+
+ return 0;
+}
+
/*
* parse_options() is the point where the getopt parsing happens. The CLI
* parsing as well as the configuration file parsing happens here.
@@ -511,6 +527,7 @@ int parse_options(int argc, char **argv, bool *usage_error,
BOOL_OPT("remote", &opts.remote),
{ "config", required_argument, 0, 1089},
{ "no-default-config", no_argument, 0, 1090},
+ { "keep-on-exec", required_argument, 0, 1092},
{ },
};
@@ -797,6 +814,12 @@ int parse_options(int argc, char **argv, bool *usage_error,
case 1091:
opts.ps_socket = atoi(optarg);
break;
+ case 1092:
+ if (parse_keep_on_exec(optarg)) {
+ pr_err("Unable to parse value for --keep-on-exec\n");
+ return 1;
+ }
+ break;
case 'V':
pr_msg("Version: %s\n", CRIU_VERSION);
if (strcmp(CRIU_GITID, "0"))
diff --git a/criu/include/cr_options.h b/criu/include/cr_options.h
index 8ddbf2341a48..2022ba12f8ec 100644
--- a/criu/include/cr_options.h
+++ b/criu/include/cr_options.h
@@ -90,6 +90,8 @@ struct cr_options {
struct list_head inherit_fds;
struct list_head external;
struct list_head join_ns;
+ int *keep_on_exec;
+ size_t nr_keep_on_exec;
char *libdir;
int use_page_server;
unsigned short port;
diff --git a/criu/include/util.h b/criu/include/util.h
index a14be72293be..f4d2171bca35 100644
--- a/criu/include/util.h
+++ b/criu/include/util.h
@@ -378,4 +378,6 @@ static inline void print_stack_trace(pid_t pid) {}
___ret; \
})
+extern int qsort_cmp_int_array(const void *__a, const void *__b);
+
#endif /* __CR_UTIL_H__ */
diff --git a/criu/util.c b/criu/util.c
index 31cdee1ff60f..3cfe7e02cce2 100644
--- a/criu/util.c
+++ b/criu/util.c
@@ -515,6 +515,20 @@ int cr_system(int in, int out, int err, char *cmd, char *const argv[], unsigned
return cr_system_userns(in, out, err, cmd, argv, flags, -1);
}
+static bool should_keep_on_exec(int fd)
+{
+ if (!opts.nr_keep_on_exec)
+ return false;
+
+ if (bsearch(&fd, opts.keep_on_exec,
+ opts.nr_keep_on_exec,
+ sizeof(opts.keep_on_exec[0]),
+ qsort_cmp_int_array))
+ return true;
+
+ return false;
+}
+
static int close_fds(int minfd)
{
DIR *dir;
@@ -541,6 +555,8 @@ static int close_fds(int minfd)
continue;
if (fd < minfd)
continue;
+ if (should_keep_on_exec(fd))
+ continue;
close(fd);
}
closedir(dir);
@@ -1341,6 +1357,13 @@ void rlimit_unlimit_nofile(void)
service_fd_rlim_cur = kdat.sysctl_nr_open;
}
+int qsort_cmp_int_array(const void *__a, const void *__b)
+{
+ int a = ((int *)__a)[0];
+ int b = ((int *)__b)[0];
+ return a == b ? 0 : (a < b ? -1 : 1);
+}
+
#ifdef __GLIBC__
#include <execinfo.h>
--
2.20.1
More information about the CRIU
mailing list