[CRIU] [PATCH 2/6] criu: Use shared libraries for optional functionality
Dmitry Safonov
dima at arista.com
Sun Nov 24 02:46:23 MSK 2019
Introduce cr-libs for using .so libraries those not critical for CRIU
functioning, but provide extended functionality.
Signed-off-by: Dmitry Safonov <dima at arista.com>
---
criu/Makefile.crtools | 1 +
criu/cr-libs.c | 132 +++++++++++++++++++++++++++++++++++++++++
criu/crtools.c | 18 +++++-
criu/include/cr-libs.h | 38 ++++++++++++
4 files changed, 186 insertions(+), 3 deletions(-)
create mode 100644 criu/cr-libs.c
create mode 100644 criu/include/cr-libs.h
diff --git a/criu/Makefile.crtools b/criu/Makefile.crtools
index d19ff8123b95..1833ba77526d 100644
--- a/criu/Makefile.crtools
+++ b/criu/Makefile.crtools
@@ -14,6 +14,7 @@ obj-y += cr-check.o
obj-y += cr-dedup.o
obj-y += cr-dump.o
obj-y += cr-errno.o
+obj-y += cr-libs.o
obj-y += cr-restore.o
obj-y += cr-service.o
obj-y += crtools.o
diff --git a/criu/cr-libs.c b/criu/cr-libs.c
new file mode 100644
index 000000000000..b7da1f847afa
--- /dev/null
+++ b/criu/cr-libs.c
@@ -0,0 +1,132 @@
+#include <dlfcn.h>
+#include <link.h>
+#include <linux/limits.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include "common/compiler.h"
+#include "cr-libs.h"
+#include "log.h"
+
+struct so_desc {
+ const char *so_name;
+ const char *warning;
+
+ /*
+ * You have to specify major version to make sure that ABI
+ * version of library is the required.
+ */
+ const unsigned major;
+ /* other major versions supported */
+ const unsigned *also_supported;
+ const size_t also_supported_sz;
+
+ /* Set up on load */
+ void *so_handle;
+ unsigned loaded_major;
+};
+static struct so_desc crlibs[SHARED_LIB_LAST] = {
+};
+
+static void *try_load_name_version(const char *so_name, const unsigned major)
+{
+ char buf[PATH_MAX];
+ void *ret;
+
+ snprintf(buf, ARRAY_SIZE(buf), "%s.%u", so_name, major);
+
+ ret = dlopen(buf, RTLD_LAZY);
+ if (ret)
+ pr_debug("Loaded `%s' succesfully\n", buf);
+
+ return ret;
+}
+
+static void try_load_lib(struct so_desc *lib)
+{
+ size_t i;
+
+ lib->so_handle = try_load_name_version(lib->so_name, lib->major);
+ if (lib->so_handle) {
+ lib->loaded_major = lib->major;
+ return;
+ }
+
+ for (i = 0; i < lib->also_supported_sz; i++) {
+ unsigned ver = lib->also_supported[i];
+
+ lib->so_handle = try_load_name_version(lib->so_name, ver);
+ if (lib->so_handle) {
+ lib->loaded_major = ver;
+ return;
+ }
+ }
+
+ print_once(LOG_INFO, "CRIU functionality may be limited\n");
+ pr_info("Can't load a shared library %s: %s\n", lib->so_name, dlerror());
+ if (lib->warning)
+ pr_info("%s: %s\n", lib->so_name, lib->warning);
+}
+
+void shared_libs_load(void)
+{
+ size_t i;
+
+ for (i = 0; i < ARRAY_SIZE(crlibs); i++)
+ try_load_lib(&crlibs[i]);
+}
+
+void shared_libs_unload(void)
+{
+ size_t i;
+
+ for (i = 0; i < ARRAY_SIZE(crlibs); i++) {
+ struct so_desc *lib = &crlibs[i];
+
+ if (lib->so_handle == NULL)
+ continue;
+
+ if (dlclose(lib->so_handle))
+ pr_warn("Failed to unload `%s': %s\n",
+ lib->so_name, dlerror());
+ lib->so_handle = NULL;
+ }
+}
+
+void *shared_libs_lookup(enum shared_libs id, const char *func)
+{
+ struct so_desc *lib;
+ void *ret;
+
+ if (id > SHARED_LIB_LAST) {
+ pr_err("BUG: shared library id is too big: %u\n", id);
+ return NULL;
+ }
+
+ lib = &crlibs[id];
+ if (lib->so_handle == NULL)
+ return NULL;
+
+ ret = dlsym(lib->so_handle, func);
+ if (ret == NULL)
+ pr_debug("Can't find `%s' function in %s\n", func, lib->so_name);
+
+ return ret;
+}
+
+int shared_libs_major(enum shared_libs id, unsigned *major)
+{
+ struct so_desc *lib;
+
+ if (id > SHARED_LIB_LAST) {
+ pr_err("BUG: shared library id is too big: %u\n", id);
+ return -1;
+ }
+
+ lib = &crlibs[id];
+ if (lib->so_handle == NULL)
+ return -1;
+
+ *major = lib->loaded_major;
+ return 0;
+}
diff --git a/criu/crtools.c b/criu/crtools.c
index 1bf2d98c35b0..25cce4265cce 100644
--- a/criu/crtools.c
+++ b/criu/crtools.c
@@ -25,6 +25,7 @@
#include "common/compiler.h"
#include "crtools.h"
#include "cr_options.h"
+#include "cr-libs.h"
#include "external.h"
#include "files.h"
#include "sk-inet.h"
@@ -48,13 +49,24 @@
#include "sysctl.h"
#include "img-remote.h"
-void flush_early_log_to_stderr() __attribute__((destructor));
-
-void flush_early_log_to_stderr(void)
+__attribute__((destructor))
+static void flush_early_log_to_stderr()
{
flush_early_log_buffer(STDERR_FILENO);
}
+__attribute__((destructor))
+static void exit_shared_libs(void)
+{
+ shared_libs_unload();
+}
+
+__attribute__((constructor))
+static void init_shared_libs(void)
+{
+ shared_libs_load();
+}
+
int main(int argc, char *argv[], char *envp[])
{
int ret = -1;
diff --git a/criu/include/cr-libs.h b/criu/include/cr-libs.h
new file mode 100644
index 000000000000..ef6ceca1f64d
--- /dev/null
+++ b/criu/include/cr-libs.h
@@ -0,0 +1,38 @@
+#ifndef __CR_LIBS_H__
+#define __CR_LIBS_H__
+
+#ifdef CR_NOGLIBC
+#error Shared libraries are not supported for PIEs
+#endif
+
+enum shared_libs {
+ SHARED_LIB_LAST = 0,
+};
+
+/* Called on init to dlopen() all .so libraries */
+extern void shared_libs_load(void);
+
+/* Called on exit to call all libraries destructors */
+extern void shared_libs_unload(void);
+
+/* Loaded library's major version number */
+extern int shared_libs_major(enum shared_libs id, unsigned *major);
+
+/*
+ * Lookup a function in a shared library.
+ * Returns NULL on failure.
+ */
+extern void *shared_libs_lookup(enum shared_libs id, const char *func);
+
+#define shared_libs_lookup_once(id, func) \
+({ \
+ static int searched; \
+ static void *ret; \
+ if (!searched) { \
+ ret = shared_libs_lookup(id, func); \
+ searched = 1; \
+ } \
+ ret; \
+})
+
+#endif /* __CR_LIBS_H__ */
--
2.24.0
More information about the CRIU
mailing list